001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: *
019: */
020:
021: package org.apache.harmony.lang.management;
022:
023: import java.lang.management.ManagementFactory;
024: import java.lang.management.MemoryNotificationInfo;
025: import java.lang.management.MemoryUsage;
026: import java.util.ArrayList;
027: import java.util.Hashtable;
028: import java.util.Iterator;
029:
030: import javax.management.Attribute;
031: import javax.management.AttributeList;
032: import javax.management.AttributeNotFoundException;
033: import javax.management.InvalidAttributeValueException;
034: import javax.management.ListenerNotFoundException;
035: import javax.management.MBeanAttributeInfo;
036: import javax.management.MBeanConstructorInfo;
037: import javax.management.MBeanInfo;
038: import javax.management.MBeanNotificationInfo;
039: import javax.management.MBeanOperationInfo;
040: import javax.management.Notification;
041: import javax.management.NotificationFilterSupport;
042: import javax.management.ObjectName;
043: import javax.management.openmbean.CompositeData;
044:
045: import org.apache.harmony.lang.management.ManagementUtils;
046: import org.apache.harmony.lang.management.MemoryMXBeanImpl;
047:
048: public class MemoryMXBeanImplTest extends
049: SingleInstanceDynamicMXBeanImplTestBase {
050:
051: private MemoryMXBeanImpl notifierBean;
052:
053: protected void setUp() throws Exception {
054: super .setUp();
055: mb = (MemoryMXBeanImpl) ManagementFactory.getMemoryMXBean();
056: notifierBean = (MemoryMXBeanImpl) mb;
057: }
058:
059: protected void tearDown() throws Exception {
060: super .tearDown();
061: }
062:
063: // -----------------------------------------------------------------
064: // DynamicMBean behaviour tests follow ....
065: // -----------------------------------------------------------------
066:
067: public final void testGetAttribute() throws Exception {
068: // The good attributes...
069: assertNotNull(mb.getAttribute("HeapMemoryUsage"));
070: assertTrue(mb.getAttribute("HeapMemoryUsage") instanceof CompositeData);
071: assertTrue(((CompositeData) (mb.getAttribute("HeapMemoryUsage")))
072: .containsKey("committed"));
073:
074: assertNotNull(mb.getAttribute("NonHeapMemoryUsage"));
075: assertTrue(mb.getAttribute("NonHeapMemoryUsage") instanceof CompositeData);
076: assertTrue(((CompositeData) (mb
077: .getAttribute("NonHeapMemoryUsage")))
078: .containsKey("max"));
079:
080: assertNotNull(mb.getAttribute("ObjectPendingFinalizationCount"));
081: assertTrue(mb.getAttribute("ObjectPendingFinalizationCount") instanceof Integer);
082:
083: assertNotNull(mb.getAttribute("Verbose"));
084: assertTrue(mb.getAttribute("Verbose") instanceof Boolean);
085:
086: // A nonexistent attribute should throw an AttributeNotFoundException
087: try {
088: long rpm = ((Long) (mb.getAttribute("RPM")));
089: fail("Should have thrown an AttributeNotFoundException.");
090: } catch (AttributeNotFoundException ignore) {
091: }
092:
093: // Type mismatch should result in a casting exception
094: try {
095: String bad = (String) (mb.getAttribute("HeapMemoryUsage"));
096: fail("Should have thrown a ClassCastException");
097: } catch (ClassCastException ignore) {
098: }
099: }
100:
101: public final void testSetAttribute() throws Exception {
102: // The one writable attribute of this type of bean
103: Attribute attr = new Attribute("Verbose", new Boolean(true));
104: mb.setAttribute(attr);
105:
106: // Now check the other attributes can't be set...
107: MemoryUsage mu = new MemoryUsage(1, 2, 3, 4);
108: CompositeData cd = ManagementUtils
109: .toMemoryUsageCompositeData(mu);
110: attr = new Attribute("HeapMemoryUsage", cd);
111: try {
112: mb.setAttribute(attr);
113: fail("Should have thrown an AttributeNotFoundException.");
114: } catch (AttributeNotFoundException ignore) {
115: }
116:
117: attr = new Attribute("NonHeapMemoryUsage", cd);
118: try {
119: mb.setAttribute(attr);
120: fail("Should have thrown an AttributeNotFoundException.");
121: } catch (AttributeNotFoundException ignore) {
122: }
123:
124: attr = new Attribute("ObjectPendingFinalizationCount",
125: new Long(38));
126: try {
127: mb.setAttribute(attr);
128: fail("Should have thrown an AttributeNotFoundException.");
129: } catch (AttributeNotFoundException ignore) {
130: }
131:
132: // Try and set the Verbose attribute with an incorrect type.
133: attr = new Attribute("Verbose", new Long(42));
134: try {
135: mb.setAttribute(attr);
136: fail("Should have thrown an InvalidAttributeValueException.");
137: } catch (InvalidAttributeValueException ignore) {
138: }
139: }
140:
141: public final void testInvoke() throws Exception {
142: // Only one operation for this bean...
143: Object retVal;
144: retVal = mb.invoke("gc", new Object[] {}, null);
145: assertNull(retVal);
146: }
147:
148: public final void testGetAttributes() {
149: AttributeList attributes = mb.getAttributes(attribs.keySet()
150: .toArray(new String[] {}));
151: assertNotNull(attributes);
152: assertTrue(attributes.size() == attribs.size());
153:
154: // Check through the returned values
155: Iterator<?> it = attributes.iterator();
156: while (it.hasNext()) {
157: Attribute element = (Attribute) it.next();
158: assertNotNull(element);
159: String name = element.getName();
160: Object value = element.getValue();
161: if (attribs.containsKey(name)) {
162: if (attribs.get(name).type.equals(Integer.TYPE
163: .getName())) {
164: assertNotNull(value);
165: assertTrue(value instanceof Integer);
166: assertTrue((Integer) value > -1);
167: }// end if a String value expected
168: else if (attribs.get(name).type.equals(Boolean.TYPE
169: .getName())) {
170: boolean tmp = ((Boolean) value).booleanValue();
171: }// end else a long expected
172: else if (attribs.get(name).type
173: .equals(CompositeData.class.getName())) {
174: assertNotNull(value);
175: assertTrue(value instanceof CompositeData);
176: // Sanity check on the contents of the returned
177: // CompositeData instance. For this kind of bean
178: // the "wrapped" type must be a MemoryUsage.
179: CompositeData cd = (CompositeData) value;
180: assertTrue(cd.containsKey("committed"));
181: assertTrue(cd.containsKey("init"));
182: assertTrue(cd.containsKey("max"));
183: assertTrue(cd.containsKey("used"));
184: assertFalse(cd.containsKey("trash"));
185: }// end else a String array expected
186: }// end if a known attribute
187: else {
188: fail("Unexpected attribute name returned!");
189: }// end else an unknown attribute
190: }// end while
191: }
192:
193: public final void testSetAttributes() {
194: // Ideal scenario...
195: AttributeList attList = new AttributeList();
196: Attribute verbose = new Attribute("Verbose", new Boolean(false));
197: attList.add(verbose);
198: AttributeList setAttrs = mb.setAttributes(attList);
199: assertNotNull(setAttrs);
200: assertTrue(setAttrs.size() == 1);
201: assertTrue(((Attribute) (setAttrs.get(0))).getName().equals(
202: "Verbose"));
203:
204: // A failure scenario - a non-existent attribute...
205: AttributeList badList = new AttributeList();
206: Attribute garbage = new Attribute("H.R. Puffenstuff", new Long(
207: 2888));
208: badList.add(garbage);
209: setAttrs = mb.setAttributes(badList);
210: assertNotNull(setAttrs);
211: assertTrue(setAttrs.size() == 0);
212:
213: // Another failure scenario - a non-writable attribute...
214: badList = new AttributeList();
215: garbage = new Attribute("ObjectPendingFinalizationCount",
216: new Integer(2888));
217: badList.add(garbage);
218: setAttrs = mb.setAttributes(badList);
219: assertNotNull(setAttrs);
220: assertTrue(setAttrs.size() == 0);
221:
222: // Yet another failure scenario - a wrongly-typed attribute...
223: badList = new AttributeList();
224: garbage = new Attribute("Verbose", new Long(2888));
225: badList.add(garbage);
226: setAttrs = mb.setAttributes(badList);
227: assertNotNull(setAttrs);
228: assertTrue(setAttrs.size() == 0);
229: }
230:
231: public final void testGetMBeanInfo() {
232: MBeanInfo mbi = mb.getMBeanInfo();
233: assertNotNull(mbi);
234:
235: // Now make sure that what we got back is what we expected.
236:
237: // Class name
238: assertTrue(mbi.getClassName().equals(mb.getClass().getName()));
239:
240: // No public constructors
241: MBeanConstructorInfo[] constructors = mbi.getConstructors();
242: assertNotNull(constructors);
243: assertTrue(constructors.length == 0);
244:
245: // One public operation
246: MBeanOperationInfo[] operations = mbi.getOperations();
247: assertNotNull(operations);
248: assertTrue(operations.length == 1);
249:
250: // One notification
251: MBeanNotificationInfo[] notifications = mbi.getNotifications();
252: assertNotNull(notifications);
253: assertTrue(notifications.length == 1);
254:
255: // Description is just the class name (until I hear it should be
256: // different)
257: assertTrue(mbi.getDescription().equals(mb.getClass().getName()));
258:
259: // Four attributes - some writable.
260: MBeanAttributeInfo[] attributes = mbi.getAttributes();
261: assertNotNull(attributes);
262: assertEquals(4, attributes.length);
263: for (int i = 0; i < attributes.length; i++) {
264: MBeanAttributeInfo info = attributes[i];
265: assertNotNull(info);
266: validateAttributeInfo(info);
267: }// end for
268: }
269:
270: // -----------------------------------------------------------------
271: // Notification implementation tests follow ....
272: // -----------------------------------------------------------------
273:
274: /*
275: * Class under test for void
276: * removeNotificationListener(NotificationListener, NotificationFilter,
277: * Object)
278: */
279: public final void testRemoveNotificationListenerNotificationListenerNotificationFilterObject()
280: throws Exception {
281: // Register a listener
282: NotificationFilterSupport filter = new NotificationFilterSupport();
283: filter
284: .enableType(MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED);
285: SimpleTestListener listener = new SimpleTestListener();
286: notifierBean.addNotificationListener(listener, filter, null);
287:
288: // Fire off a notification and ensure that the listener receives it.
289: MemoryUsage mu = new MemoryUsage(1, 2, 3, 4);
290: MemoryNotificationInfo info = new MemoryNotificationInfo("Tim",
291: mu, 42);
292: CompositeData cd = ManagementUtils
293: .toMemoryNotificationInfoCompositeData(info);
294: Notification notification = new Notification(
295: MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED,
296: new ObjectName(ManagementFactory.MEMORY_MXBEAN_NAME),
297: 42);
298: notification.setUserData(cd);
299: notifierBean.sendNotification(notification);
300: assertEquals(1, listener.getNotificationsReceivedCount());
301:
302: // Remove the listener
303: notifierBean.removeNotificationListener(listener, filter, null);
304:
305: // Fire off a notification and ensure that the listener does
306: // *not* receive it.
307: listener.resetNotificationsReceivedCount();
308: notification = new Notification(
309: MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED,
310: new ObjectName(ManagementFactory.MEMORY_MXBEAN_NAME),
311: 43);
312: notification.setUserData(cd);
313: notifierBean.sendNotification(notification);
314: assertEquals(0, listener.getNotificationsReceivedCount());
315:
316: // Try and remove the listener one more time. Should result in a
317: // ListenerNotFoundException being thrown.
318: try {
319: notifierBean.removeNotificationListener(listener, filter,
320: null);
321: fail("Should have thrown a ListenerNotFoundException!");
322: } catch (ListenerNotFoundException e) {
323: }
324: }
325:
326: public final void testAddNotificationListener() throws Exception {
327: // Add a listener with a handback object.
328: SimpleTestListener listener = new SimpleTestListener();
329: ArrayList<String> arr = new ArrayList<String>();
330: arr.add("Hegemony or survival ?");
331: notifierBean.addNotificationListener(listener, null, arr);
332:
333: // Fire off a notification and ensure that the listener receives it.
334: MemoryUsage mu = new MemoryUsage(1, 2, 3, 4);
335: MemoryNotificationInfo info = new MemoryNotificationInfo(
336: "Lloyd", mu, 42);
337: CompositeData cd = ManagementUtils
338: .toMemoryNotificationInfoCompositeData(info);
339: Notification notification = new Notification(
340: MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED,
341: new ObjectName(ManagementFactory.MEMORY_MXBEAN_NAME),
342: 42);
343: notification.setUserData(cd);
344: notifierBean.sendNotification(notification);
345: assertEquals(1, listener.getNotificationsReceivedCount());
346:
347: // Verify that the handback is as expected.
348: assertNotNull(listener.getHandback());
349: assertSame(arr, listener.getHandback());
350: ArrayList arr2 = (ArrayList) listener.getHandback();
351: assertTrue(arr2.size() == 1);
352: assertEquals("Hegemony or survival ?", arr2.get(0));
353: }
354:
355: /*
356: * Class under test for void
357: * removeNotificationListener(NotificationListener)
358: */
359: public final void testRemoveNotificationListenerNotificationListener()
360: throws Exception {
361: // Add a listener without a filter object.
362: SimpleTestListener listener = new SimpleTestListener();
363: notifierBean.addNotificationListener(listener, null, null);
364: // Fire off a notification and ensure that the listener receives it.
365: MemoryUsage mu = new MemoryUsage(1, 2, 3, 4);
366: MemoryNotificationInfo info = new MemoryNotificationInfo(
367: "Sinclair", mu, 42);
368: CompositeData cd = ManagementUtils
369: .toMemoryNotificationInfoCompositeData(info);
370: Notification notification = new Notification(
371: MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED,
372: new ObjectName(ManagementFactory.MEMORY_MXBEAN_NAME),
373: 42);
374: notification.setUserData(cd);
375: notifierBean.sendNotification(notification);
376: assertEquals(1, listener.getNotificationsReceivedCount());
377:
378: // Verify that the handback is as expected.
379: assertNull(listener.getHandback());
380:
381: // Verify the user data of the notification.
382: Notification n = listener.getNotification();
383: assertNotNull(n);
384: verifyNotificationUserData(n.getUserData());
385:
386: // Remove the listener
387: notifierBean.removeNotificationListener(listener);
388:
389: // Fire off a notification and ensure that the listener does
390: // *not* receive it.
391: listener.resetNotificationsReceivedCount();
392: notification = new Notification(
393: MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED,
394: new ObjectName(ManagementFactory.MEMORY_MXBEAN_NAME),
395: 43);
396: notification.setUserData(cd);
397: notifierBean.sendNotification(notification);
398: assertEquals(0, listener.getNotificationsReceivedCount());
399:
400: // Try and remove the listener one more time. Should result in a
401: // ListenerNotFoundException being thrown.
402: try {
403: notifierBean.removeNotificationListener(listener);
404: fail("Should have thrown a ListenerNotFoundException!");
405: } catch (ListenerNotFoundException ignore) {
406: }
407: }
408:
409: /**
410: * @param userData
411: */
412: private void verifyNotificationUserData(Object userData) {
413: // Should be a CompositeData instance
414: assertTrue(userData instanceof CompositeData);
415: CompositeData cd = (CompositeData) userData;
416: assertTrue(cd.containsKey("poolName"));
417: assertTrue(cd.containsKey("usage"));
418: assertTrue(cd.containsKey("count"));
419: assertTrue(cd.get("poolName") instanceof String);
420: assertTrue(((String) cd.get("poolName")).length() > 0);
421: assertTrue(cd.get("count") instanceof Long);
422: assertTrue(((Long) cd.get("count")) > 0);
423: }
424:
425: public final void testGetNotificationInfo() {
426: MBeanNotificationInfo[] notifications = notifierBean
427: .getNotificationInfo();
428: assertNotNull(notifications);
429: assertTrue(notifications.length > 0);
430: for (int i = 0; i < notifications.length; i++) {
431: MBeanNotificationInfo info = notifications[i];
432: assertEquals(Notification.class.getName(), info.getName());
433: assertEquals("Memory Notification", info.getDescription());
434: String[] types = info.getNotifTypes();
435: for (int j = 0; j < types.length; j++) {
436: String type = types[j];
437: assertTrue(type
438: .equals(MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED)
439: || type
440: .equals(MemoryNotificationInfo.MEMORY_COLLECTION_THRESHOLD_EXCEEDED));
441:
442: }// end for
443: }// end for
444: }
445:
446: @Override
447: protected void populateTestAttributes() {
448: attribs = new Hashtable<String, AttributeData>();
449: attribs.put("HeapMemoryUsage", new AttributeData(
450: CompositeData.class.getName(), true, false, false));
451: attribs.put("NonHeapMemoryUsage", new AttributeData(
452: CompositeData.class.getName(), true, false, false));
453: attribs.put("ObjectPendingFinalizationCount",
454: new AttributeData(Integer.TYPE.getName(), true, false,
455: false));
456: attribs.put("Verbose", new AttributeData(
457: Boolean.TYPE.getName(), true, true, true));
458: }
459: }
|