Skip to content

Commit

Permalink
Merge pull request #7 from ojung/add-tests
Browse files Browse the repository at this point in the history
Add tests
  • Loading branch information
oskar committed Sep 30, 2015
2 parents 25e2957 + d4624b5 commit 9f134f2
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 71 deletions.
1 change: 1 addition & 0 deletions project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
[http-kit "2.1.17"]
[ring/ring-mock "0.3.0"]
[ring/ring-defaults "0.1.2"]
[ring/ring-devel "1.4.0"]
[ring/ring-json "0.4.0"]
[org.clojure/data.json "0.2.6"]
[clj-stacktrace "0.2.8"]]
Expand Down
5 changes: 0 additions & 5 deletions src/mbeanz/common.clj

This file was deleted.

4 changes: 2 additions & 2 deletions src/mbeanz/core.clj
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
(ns mbeanz.core
(:gen-class)
(:require [clojure.java.jmx :as jmx]
[clojure.core.match :refer [match]]
[mbeanz.common :refer :all])
[clojure.core.match :refer [match]])
(:import [java.lang.IllegalArgumentException]))

(defn get-identifiers [[bean-name & bean-ops]]
(->> bean-ops
(flatten)
(sort)
(map (partial hash-map :bean (str bean-name) :operation))))

(defn list-beans [object-name-pattern]
Expand Down
6 changes: 2 additions & 4 deletions src/mbeanz/handler.clj
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
(:require [compojure.route :as route]
[ring.middleware.defaults :refer [wrap-defaults api-defaults]]
[ring.middleware.json :refer [wrap-json-response]]
[ring.middleware.reload :refer [wrap-reload]]
[compojure.core :refer :all]
[mbeanz.core :refer :all]
[mbeanz.common :refer :all]
[clojure.java.jmx :as jmx]
[clojure.edn :as edn])
(:use [org.httpkit.server :only [run-server]]
Expand All @@ -21,9 +21,6 @@

(defonce jmx-remote-port (atom 1080))

(defn- identifier-string [identifiers]
(map #(str (:bean %) " " (stringify (:operation %))) identifiers))

(defn- handle-describe [operation]
(fn [request]
(jmx/with-connection {:host @jmx-remote-host :port @jmx-remote-port}
Expand Down Expand Up @@ -61,6 +58,7 @@

(def app
(-> app-routes
(wrap-reload)
(wrap-json-response)
(wrap-defaults api-defaults)))

Expand Down
69 changes: 39 additions & 30 deletions test/mbeanz/core_test.clj
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
(ns mbeanz.core-test
(:require [clojure.test :refer :all]
[mbeanz.core :refer :all]
[mbeanz.common :refer :all])
[mbeanz.core :refer :all])
(:import [java.lang.IllegalArgumentException]))

(deftest index
(deftest test-list-beans
(testing "list single mbean"
(is (= (list-beans "java.lang:type=Memory") [{:bean "java.lang:type=Memory" :operation :gc}])))
(testing "list multiple mbeans"
Expand All @@ -18,43 +17,53 @@
{:bean "java.lang:type=MemoryPool,name=PS Survivor Space"
:operation :resetPeakUsage}]))))

(deftest show
(testing "mbean description"
(is (= (describe "java.lang:type=Memory" :gc) "gc")))
(testing "mbean parameters"
(is (= (get-params "java.lang:type=Threading" :dumpAllThreads)
(list {:name "p0", :type "boolean", :description "p0"}
{:name "p1", :type "boolean", :description "p1"})))))
(deftest test-describe
(testing "mbean operation without arguments"
(is (= (describe "java.lang:type=Memory" :gc)
[{:name "gc", :description "gc", :signature []}])))
(testing "mbean operation with parameters"
(is (= (describe "java.lang:type=Threading" :dumpAllThreads)
[{:name "dumpAllThreads",
:description "dumpAllThreads",
:signature [{:description "p0", :name "p0", :type "boolean"}
{:description "p1", :name "p1", :type "boolean"}]}]))))

(deftest test-invoke
(testing "type deduction for monadic operations"
(is (= (get-typed-args "java.util.logging:type=Logging" :getLoggerLevel "asd")
[[:java.lang.String "asd"]])))
(testing "type deduction for variadic operations"
(is (= (get-typed-args "java.lang:type=Threading" :dumpAllThreads "true" "true")
[[:boolean "true"] [:boolean "true"]])))
(testing "mbean with arguments"
(is (not (invoke "java.util.logging:type=Logging" :getLoggerLevel "asdfg"))))
;TODO: handle overloaded signatures
;(testing "overloaded mbean with arguments"
;(is (invoke "java.lang:type=Threading" :getThreadUserTime "1")))
(is (not (invoke "java.util.logging:type=Logging"
:getLoggerLevel
["java.lang.String" "someInexistentLogger"]))))
(testing "overloaded mbean with arguments"
(is (invoke "java.lang:type=Threading" :getThreadUserTime ["long" "1"])))
(testing "mbean without arguments"
(is (= (invoke "java.lang:type=Memory" :gc) nil))))
(is (not (invoke "java.lang:type=Memory" :gc)))))

(deftest type-casting
(testing "stringify function"
(is (= (stringify :int) "int"))
(is (= (stringify :Boolean) "Boolean")))
(testing "int"
(is (= (cast-type [:int "1"]) (int 1))))
(is (= (cast-type ["int" "1"]) (int 1))))
(testing "Integer"
(is (= (cast-type ["java.lang.Integer" "1"]) (Integer. 1))))
(testing "long"
(is (= (cast-type [:long "1"]) (long 1))))
(is (= (cast-type ["long" "1"]) 1)))
(testing "Long"
(is (= (cast-type ["java.lang.Long" "1"]) 1)))
(testing "boolean"
(is (= (cast-type [:boolean "true"]) (boolean true))))
(is (= (cast-type ["boolean" "true"]) true)))
(testing "Boolean"
(is (= (cast-type ["java.lang.Boolean" "true"]) true)))
(testing "double"
(is (= (cast-type ["double" "1"]) (double 1))))
(testing "Double"
(is (= (cast-type ["java.lang.Double" "1"]) (double 1))))
(testing "float"
(is (= (cast-type ["float" "1"]) (float 1))))
(testing "Float"
(is (= (cast-type ["java.lang.Float" "1"]) (float 1))))
(testing "string"
(is (= (cast-type [:java.lang.String "hello world"]) "hello world")))
(is (= (cast-type ["java.lang.String" "hello world"]) "hello world")))
(testing "number format exception"
(is (thrown? NumberFormatException (cast-type ["int" "asd"]))))
(testing "unsupported type"
(is (thrown-with-msg? IllegalArgumentException
#"Unsupported argument type"
(cast-type '(:asdjl "asd"))))))

(cast-type ["short" "asd"])))))
96 changes: 66 additions & 30 deletions test/mbeanz/handler_test.clj
Original file line number Diff line number Diff line change
@@ -1,36 +1,72 @@
(ns mbeanz.handler_test
(ns mbeanz.handler-test
(:require [clojure.test :refer :all]
[mbeanz.handler :refer :all]
[ring.mock.request :as mock]
[clojure.data.json :as json]))

(deftest handler
(use-fixtures :once (fn [do-tests] (reset! object-pattern "java.lang:*") (do-tests)))

(defn- request [url params cb]
(let [mock-request (mock/query-string (mock/request :get url) params)
response (app mock-request)]
(cb response)))

(deftest list-route
(testing "list route"
(let [response (app (mock/request :get "/list"))]
(is (= (:status response) 200))
(is (= (json/read-str (:body response))
["java.lang:type=Memory gc",
"java.lang:type=MemoryPool,name=Code Cache resetPeakUsage",
"java.lang:type=MemoryPool,name=Compressed Class Space resetPeakUsage",
"java.lang:type=MemoryPool,name=Metaspace resetPeakUsage",
"java.lang:type=MemoryPool,name=PS Eden Space resetPeakUsage",
"java.lang:type=MemoryPool,name=PS Old Gen resetPeakUsage",
"java.lang:type=MemoryPool,name=PS Survivor Space resetPeakUsage",
"java.lang:type=Threading getThreadCpuTime",
"java.lang:type=Threading getThreadCpuTime",
"java.lang:type=Threading getThreadUserTime",
"java.lang:type=Threading getThreadUserTime",
"java.lang:type=Threading getThreadAllocatedBytes",
"java.lang:type=Threading getThreadAllocatedBytes",
"java.lang:type=Threading getThreadInfo",
"java.lang:type=Threading getThreadInfo",
"java.lang:type=Threading getThreadInfo",
"java.lang:type=Threading getThreadInfo",
"java.lang:type=Threading getThreadInfo",
"java.lang:type=Threading findMonitorDeadlockedThreads",
"java.lang:type=Threading resetPeakThreadCount",
"java.lang:type=Threading findDeadlockedThreads",
"java.lang:type=Threading dumpAllThreads"]))))
(testing "describe route"
(let [response (app (mock/request :get "/describe/gc?bean=java.lang:type=Memory"))]
(is (= (:status response) 200)))))
(request "/list" {}
#(is (= (json/read-str (:body %))
[{"bean" "java.lang:type=Memory", "operation" "gc"}
{"bean" "java.lang:type=MemoryPool,name=Code Cache", "operation" "resetPeakUsage"}
{"bean" "java.lang:type=MemoryPool,name=Compressed Class Space"
"operation" "resetPeakUsage"}
{"bean" "java.lang:type=MemoryPool,name=Metaspace", "operation" "resetPeakUsage"}
{"bean" "java.lang:type=MemoryPool,name=PS Eden Space", "operation" "resetPeakUsage"}
{"bean" "java.lang:type=MemoryPool,name=PS Old Gen", "operation" "resetPeakUsage"}
{"bean" "java.lang:type=MemoryPool,name=PS Survivor Space", "operation" "resetPeakUsage"}
{"bean" "java.lang:type=Threading", "operation" "dumpAllThreads"}
{"bean" "java.lang:type=Threading", "operation" "findDeadlockedThreads"}
{"bean" "java.lang:type=Threading", "operation" "findMonitorDeadlockedThreads"}
{"bean" "java.lang:type=Threading", "operation" "getThreadAllocatedBytes"}
{"bean" "java.lang:type=Threading", "operation" "getThreadCpuTime"}
{"bean" "java.lang:type=Threading", "operation" "getThreadInfo"}
{"bean" "java.lang:type=Threading", "operation" "getThreadUserTime"}
{"bean" "java.lang:type=Threading", "operation" "resetPeakThreadCount"}])))))

(deftest describe-route
(testing "operation with single signature"
(request "/describe/gc" {"bean" "java.lang:type=Memory"}
#(is (= (json/read-str (:body %))
[{"name" "gc", "description" "gc", "signature" []}]))))

(testing "operation with multiple signatures"
(request "/describe/getThreadCpuTime" {"bean" "java.lang:type=Threading"}
#(is (= (json/read-str (:body %))
[{"name" "getThreadCpuTime"
"description" "getThreadCpuTime"
"signature" [{"description" "p0", "name" "p0", "type" "[J"}]}
{"name" "getThreadCpuTime"
"description" "getThreadCpuTime"
"signature" [{"description" "p0", "name" "p0", "type" "long"}]}]))))

(testing "inexistent operation"
;TODO: Make api return error (404):
(request "/describe/inexistent" {"bean" "java.lang:type=Threading"}
#(is (= (json/read-str (:body %)) [])))))

(deftest invoke-route
(testing "operation without arguments"
(request "/invoke/gc" {"bean" "java.lang:type=Memory"}
#(is (= (json/read-str (:body %)) {"result" nil}))))

(testing "operation with arguments invoked with wrong signature"
(request "/invoke/getThreadInfo" {"bean" "java.lang:type=Threading"}
#(is (= (json/read-str (:body %))
{"error" {"class" "class javax.management.ReflectionException"
"message" "Operation getThreadInfo exists but not with this signature: ()"}}))))

(testing "operation with single argument invoked with correct signature"
;TODO: Setup mock mbeans
(request "/invoke/getThreadCpuTime"
;Hoping this thread id doesn't exist
{"bean" "java.lang:type=Threading", "args" "99999999999", "types" "long"}
#(is (= (json/read-str (:body %)) {"result" -1})))))

0 comments on commit 9f134f2

Please sign in to comment.