rlm@10: ;; Tests for JMX support for Clojure (see also clojure/contrib/jmx.clj) rlm@10: rlm@10: ;; by Stuart Halloway rlm@10: rlm@10: ;; Copyright (c) Stuart Halloway, 2009. All rights reserved. The use rlm@10: ;; and distribution terms for this software are covered by the Eclipse rlm@10: ;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) rlm@10: ;; which can be found in the file epl-v10.html at the root of this rlm@10: ;; distribution. By using this software in any fashion, you are rlm@10: ;; agreeing to be bound by the terms of this license. You must not rlm@10: ;; remove this notice, or any other, from this software. rlm@10: rlm@10: (ns clojure.contrib.test-jmx rlm@10: (:import javax.management.openmbean.CompositeDataSupport rlm@10: [javax.management MBeanAttributeInfo AttributeList] rlm@10: [java.util.logging LogManager Logger] rlm@10: clojure.contrib.jmx.Bean) rlm@10: (:use clojure.test) rlm@10: (:require [clojure.contrib [jmx :as jmx]])) rlm@10: rlm@10: rlm@10: (defn =set [a b] rlm@10: (= (set a) (set b))) rlm@10: rlm@10: (defn seq-contains-all? rlm@10: "Does container contain every item in containee? rlm@10: Not fast. Testing use only" rlm@10: [container containee] rlm@10: (let [container (set container)] rlm@10: (every? #(contains? container %) containee))) rlm@10: rlm@10: (deftest finding-mbeans rlm@10: (testing "as-object-name" rlm@10: (are [cname object-name] rlm@10: (= cname (.getCanonicalName object-name)) rlm@10: "java.lang:type=Memory" (jmx/as-object-name "java.lang:type=Memory"))) rlm@10: (testing "mbean-names" rlm@10: (are [cnames object-name] rlm@10: (= cnames (map #(.getCanonicalName %) object-name)) rlm@10: ["java.lang:type=Memory"] (jmx/mbean-names "java.lang:type=Memory")))) rlm@10: rlm@10: ; These actual beans may differ on different JVM platforms. rlm@10: ; Tested April 2010 to work on Sun and IBM JDKs. rlm@10: (deftest testing-actual-beans rlm@10: (testing "reflecting on capabilities" rlm@10: (are [attr-list mbean-name] rlm@10: (seq-contains-all? (jmx/attribute-names mbean-name) attr-list) rlm@10: [:Verbose :ObjectPendingFinalizationCount :HeapMemoryUsage :NonHeapMemoryUsage] "java.lang:type=Memory") rlm@10: (are [op-list mbean-name] rlm@10: (seq-contains-all? (jmx/operation-names mbean-name) op-list) rlm@10: [:gc] "java.lang:type=Memory")) rlm@10: (testing "mbean-from-oname" rlm@10: (are [key-names oname] rlm@10: (seq-contains-all? (keys (jmx/mbean oname)) key-names) rlm@10: [:Verbose :ObjectPendingFinalizationCount :HeapMemoryUsage :NonHeapMemoryUsage] "java.lang:type=Memory"))) rlm@10: rlm@10: (deftest raw-reading-attributes rlm@10: (let [mem "java.lang:type=Memory" rlm@10: log "java.util.logging:type=Logging"] rlm@10: (testing "simple scalar attributes" rlm@10: (are [a b] (= a b) rlm@10: false (jmx/raw-read mem :Verbose)) rlm@10: (are [type attr] (instance? type attr) rlm@10: Number (jmx/raw-read mem :ObjectPendingFinalizationCount))))) rlm@10: rlm@10: (deftest reading-attributes rlm@10: (testing "simple scalar attributes" rlm@10: (are [type attr] (instance? type attr) rlm@10: Number (jmx/read "java.lang:type=Memory" :ObjectPendingFinalizationCount))) rlm@10: (testing "composite attributes" rlm@10: (are [ks attr] (=set ks (keys attr)) rlm@10: [:used :max :init :committed] (jmx/read "java.lang:type=Memory" :HeapMemoryUsage))) rlm@10: (testing "tabular attributes" rlm@10: (is (map? (jmx/read "java.lang:type=Runtime" :SystemProperties))))) rlm@10: rlm@10: (deftest writing-attributes rlm@10: (let [mem "java.lang:type=Memory"] rlm@10: (jmx/write! mem :Verbose true) rlm@10: (is (true? (jmx/raw-read mem :Verbose))) rlm@10: (jmx/write! mem :Verbose false))) rlm@10: rlm@10: (deftest test-invoke-operations rlm@10: (testing "without arguments" rlm@10: (jmx/invoke "java.lang:type=Memory" :gc)) rlm@10: (testing "with arguments" rlm@10: (.addLogger (LogManager/getLogManager) (Logger/getLogger "clojure.contrib.test_contrib.test_jmx")) rlm@10: (jmx/invoke "java.util.logging:type=Logging" :setLoggerLevel "clojure.contrib.test_contrib.test_jmx" "WARNING"))) rlm@10: rlm@10: (deftest test-jmx->clj rlm@10: (testing "it works recursively on maps" rlm@10: (let [some-map {:foo (jmx/raw-read "java.lang:type=Memory" :HeapMemoryUsage)}] rlm@10: (is (map? (:foo (jmx/jmx->clj some-map)))))) rlm@10: (testing "it leaves everything else untouched" rlm@10: (is (= "foo" (jmx/jmx->clj "foo"))))) rlm@10: rlm@10: rlm@10: (deftest test-composite-data->map rlm@10: (let [data (jmx/raw-read "java.lang:type=Memory" :HeapMemoryUsage) rlm@10: prox (jmx/composite-data->map data)] rlm@10: (testing "returns a map with keyword keys" rlm@10: (is (= (set [:committed :init :max :used]) (set (keys prox))))))) rlm@10: rlm@10: (deftest test-tabular-data->map rlm@10: (let [raw-props (jmx/raw-read "java.lang:type=Runtime" :SystemProperties) rlm@10: props (jmx/tabular-data->map raw-props)] rlm@10: (are [k] (contains? props k) rlm@10: :java.class.path rlm@10: :path.separator))) rlm@10: rlm@10: (deftest test-creating-attribute-infos rlm@10: (let [infos (jmx/map->attribute-infos [[:a 1] [:b 2]]) rlm@10: info (first infos)] rlm@10: (testing "generates the right class" rlm@10: (is (= (class (into-array MBeanAttributeInfo [])) (class infos)))) rlm@10: (testing "generates the right instance data" rlm@10: (are [result expr] (= result expr) rlm@10: "a" (.getName info) rlm@10: "a" (.getDescription info))))) rlm@10: rlm@10: (deftest various-beans-are-readable rlm@10: (testing "that all java.lang beans can be read without error" rlm@10: (doseq [mb (jmx/mbean-names "*:*")] rlm@10: (is (map? (jmx/mbean mb)) mb)))) rlm@10: rlm@10: (deftest test-jmx-url rlm@10: (testing "creates default url" rlm@10: (is (= "service:jmx:rmi:///jndi/rmi://localhost:3000/jmxrmi" rlm@10: (jmx/jmx-url)))) rlm@10: (testing "creates custom url" rlm@10: (is (= "service:jmx:rmi:///jndi/rmi://example.com:4000/jmxrmi" rlm@10: (jmx/jmx-url {:host "example.com" :port 4000})))) rlm@10: (testing "creates custom jndi path" rlm@10: (is (= "service:jmx:rmi:///jndi/rmi://example.com:4000/jmxconnector" rlm@10: (jmx/jmx-url {:host "example.com" :port 4000 :jndi-path "jmxconnector"}))))) rlm@10: rlm@10: ;; ---------------------------------------------------------------------- rlm@10: ;; tests for clojure.contrib.jmx.Bean. rlm@10: rlm@10: (deftest dynamic-mbean-from-compiled-class rlm@10: (let [mbean-name "clojure.contrib.test_contrib.test_jmx:name=Foo"] rlm@10: (jmx/register-mbean rlm@10: (Bean. rlm@10: (ref {:string-attribute "a-string"})) rlm@10: mbean-name) rlm@10: (are [result expr] (= result expr) rlm@10: "a-string" (jmx/read mbean-name :string-attribute) rlm@10: {:string-attribute "a-string"} (jmx/mbean mbean-name) rlm@10: ))) rlm@10: rlm@10: (deftest test-getAttribute rlm@10: (doseq [reftype [ref atom agent]] rlm@10: (let [state (reftype {:a 1 :b 2}) rlm@10: bean (Bean. state)] rlm@10: (testing (str "accessing values from a " (class state)) rlm@10: (are [result expr] (= result expr) rlm@10: 1 (.getAttribute bean "a")))))) rlm@10: rlm@10: (deftest test-bean-info rlm@10: (let [state (ref {:a 1 :b 2}) rlm@10: bean (Bean. state) rlm@10: info (.getMBeanInfo bean)] rlm@10: (testing "accessing info" rlm@10: (are [result expr] (= result expr) rlm@10: "clojure.contrib.jmx.Bean" (.getClassName info))))) rlm@10: rlm@10: (deftest test-getAttributes rlm@10: (let [bean (Bean. (ref {:r 5 :d 4})) rlm@10: atts (.getAttributes bean (into-array ["r" "d"]))] rlm@10: (are [x y] (= x y) rlm@10: AttributeList (class atts) rlm@10: [5 4] (seq atts)))) rlm@10: rlm@10: (deftest test-guess-attribute-typename rlm@10: (are [x y] (= x (jmx/guess-attribute-typename y)) rlm@10: ; "long" 10 rlm@10: "boolean" false rlm@10: "java.lang.String" "foo" rlm@10: "long" (Long/valueOf (long 10))))