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.ThreadInfo;
024:
025: import javax.management.openmbean.ArrayType;
026: import javax.management.openmbean.CompositeData;
027: import javax.management.openmbean.CompositeDataSupport;
028: import javax.management.openmbean.CompositeType;
029: import javax.management.openmbean.OpenDataException;
030: import javax.management.openmbean.OpenType;
031: import javax.management.openmbean.SimpleType;
032:
033: import junit.framework.TestCase;
034:
035: /**
036: * ThreadInfo objects can only be obtained from the ThreadMXBean or else by
037: * calling the static from() method with an existing CompositeData object that
038: * maps to a ThreadInfo. Trying to unit test using the former approach only gets
039: * us so far as we have no idea what the expected values should be. We only know
040: * their types, ranges etc etc. This testcase goes the long way round by
041: * creating a CompositeData representing a ThreadInfo with well understood
042: * values that we can test for once we have passed the CompositeData into the
043: * from() method to get a ThreadInfo.
044: * <p>
045: * The "problem" with this approach is that the hand-rolled CompositeData
046: * created in this testcase is not liked by the RI which has its own internal
047: * way of validating CompositeData and CompositeType instances. So, while this
048: * test case is creating CompositeData and CompositeType objects which adhere to
049: * the spec, the below tests will all fail when run against the RI. For that
050: * reason, this testcase cannot be considered as implementation independent.
051: *
052: */
053: public class ThreadInfoTest extends TestCase {
054:
055: private static final boolean GOOD_SUSPENDED = false;
056:
057: private static final boolean GOOD_IN_NATIVE = false;
058:
059: private static final int GOOD_STACK_SIZE = 3;
060:
061: private static final boolean GOOD_STACK_NATIVEMETHOD = false;
062:
063: private static final int GOOD_STACK_LINENUMBER = 2100;
064:
065: private static final String GOOD_STACK_FILENAME = "Blobby.java";
066:
067: private static final String GOOD_STACK_METHODNAME = "takeOverWorld";
068:
069: private static final String GOOD_STACK_CLASSNAME = "foo.bar.Blobby";
070:
071: private static final Thread.State GOOD_THREAD_STATE = Thread.State.RUNNABLE;
072:
073: private static final String GOOD_THREAD_NAME = "Marty";
074:
075: private static final int GOOD_THREAD_ID = 46664;
076:
077: private static final String GOOD_LOCK_OWNER_NAME = "Noam Chomsky";
078:
079: private static final int GOOD_LOCK_OWNER_ID = 24141;
080:
081: private static final int GOOD_WAITED_TIME = 3779;
082:
083: private static final int GOOD_WAITED_COUNT = 21;
084:
085: private static final int GOOD_BLOCKED_TIME = 3309;
086:
087: private static final int GOOD_BLOCKED_COUNT = 250;
088:
089: private static final String GOOD_LOCK_NAME = "foo.Bar@1234567";
090:
091: private CompositeData tiCD;
092:
093: private ThreadInfo ti;
094:
095: protected void setUp() throws Exception {
096: super .setUp();
097: tiCD = createGoodCompositeData();
098: ti = ThreadInfo.from(tiCD);
099: assertNotNull(ti);
100: }
101:
102: public CompositeData createGoodCompositeData() {
103: CompositeData result = null;
104: String[] names = { "threadId", "threadName", "threadState",
105: "suspended", "inNative", "blockedCount", "blockedTime",
106: "waitedCount", "waitedTime", "lockName", "lockOwnerId",
107: "lockOwnerName", "stackTrace" };
108: Object[] values = {
109: /* threadId */new Long(GOOD_THREAD_ID),
110: /* threadName */new String(GOOD_THREAD_NAME),
111: /* threadState */new String(GOOD_THREAD_STATE.toString()),
112: /* suspended */new Boolean(GOOD_SUSPENDED),
113: /* inNative */new Boolean(GOOD_IN_NATIVE),
114: /* blockedCount */new Long(GOOD_BLOCKED_COUNT),
115: /* blockedTime */new Long(GOOD_BLOCKED_TIME),
116: /* waitedCount */new Long(GOOD_WAITED_COUNT),
117: /* waitedTime */new Long(GOOD_WAITED_TIME),
118: /* lockName */new String(GOOD_LOCK_NAME),
119: /* lockOwnerId */new Long(GOOD_LOCK_OWNER_ID),
120: /* lockOwnerName */new String(GOOD_LOCK_OWNER_NAME),
121: /* stackTrace */createGoodStackTraceCompositeData() };
122: CompositeType cType = createGoodThreadInfoCompositeType();
123: try {
124: result = new CompositeDataSupport(cType, names, values);
125: } catch (OpenDataException e) {
126: // TODO Auto-generated catch block
127: e.printStackTrace();
128: }
129: return result;
130: }
131:
132: /**
133: * @return new array of <code>CompositeData</code> representing an array
134: * of <code>StackTraceElement</code>.
135: */
136: public static CompositeData[] createGoodStackTraceCompositeData() {
137: // Let's make the array have three elements. Doesn't matter that
138: // they are all identical.
139: CompositeData[] result = new CompositeData[GOOD_STACK_SIZE];
140: CompositeType cType = createGoodStackTraceElementCompositeType();
141: String[] names = { "className", "methodName", "fileName",
142: "lineNumber", "nativeMethod" };
143: Object[] values = { GOOD_STACK_CLASSNAME,
144: GOOD_STACK_METHODNAME, GOOD_STACK_FILENAME,
145: new Integer(GOOD_STACK_LINENUMBER),
146: new Boolean(GOOD_STACK_NATIVEMETHOD) };
147:
148: for (int i = 0; i < result.length; i++) {
149: try {
150: result[i] = new CompositeDataSupport(cType, names,
151: values);
152: } catch (OpenDataException e) {
153: // TODO Auto-generated catch block
154: e.printStackTrace();
155: }
156: }// end for
157: return result;
158: }
159:
160: /**
161: * @return <code>CompositeType</code> for use when wrapping up
162: * <code>ThreadInfo</code> objects in <code>CompositeData</code>
163: * s.
164: */
165: private static CompositeType createGoodThreadInfoCompositeType() {
166: CompositeType result = null;
167: try {
168: String[] typeNames = { "threadId", "threadName",
169: "threadState", "suspended", "inNative",
170: "blockedCount", "blockedTime", "waitedCount",
171: "waitedTime", "lockName", "lockOwnerId",
172: "lockOwnerName", "stackTrace" };
173: String[] typeDescs = { "threadId", "threadName",
174: "threadState", "suspended", "inNative",
175: "blockedCount", "blockedTime", "waitedCount",
176: "waitedTime", "lockName", "lockOwnerId",
177: "lockOwnerName", "stackTrace", };
178: OpenType[] typeTypes = {
179: SimpleType.LONG,
180: SimpleType.STRING,
181: SimpleType.STRING,
182: SimpleType.BOOLEAN,
183: SimpleType.BOOLEAN,
184: SimpleType.LONG,
185: SimpleType.LONG,
186: SimpleType.LONG,
187: SimpleType.LONG,
188: SimpleType.STRING,
189: SimpleType.LONG,
190: SimpleType.STRING,
191: new ArrayType(1,
192: createGoodStackTraceElementCompositeType()) };
193: result = new CompositeType(ThreadInfo.class.getName(),
194: ThreadInfo.class.getName(), typeNames, typeDescs,
195: typeTypes);
196: } catch (OpenDataException e) {
197: // TODO Auto-generated catch block
198: e.printStackTrace();
199: }
200: return result;
201: }
202:
203: private static CompositeType createGoodStackTraceElementCompositeType() {
204: CompositeType result = null;
205: String[] typeNames = { "className", "methodName", "fileName",
206: "lineNumber", "nativeMethod" };
207: String[] typeDescs = { "className", "methodName", "fileName",
208: "lineNumber", "nativeMethod" };
209: OpenType[] typeTypes = { SimpleType.STRING, SimpleType.STRING,
210: SimpleType.STRING, SimpleType.INTEGER,
211: SimpleType.BOOLEAN };
212: try {
213: result = new CompositeType(StackTraceElement.class
214: .getName(), StackTraceElement.class.getName(),
215: typeNames, typeDescs, typeTypes);
216: } catch (OpenDataException e) {
217: // TODO Auto-generated catch block
218: e.printStackTrace();
219: }
220: return result;
221: }
222:
223: protected void tearDown() throws Exception {
224: super .tearDown();
225: }
226:
227: /*
228: * Test method for 'java.lang.management.ThreadInfo.getBlockedCount()'
229: */
230: public void testGetBlockedCount() {
231: assertEquals(GOOD_BLOCKED_COUNT, ti.getBlockedCount());
232: }
233:
234: /*
235: * Test method for 'java.lang.management.ThreadInfo.getBlockedTime()'
236: */
237: public void testGetBlockedTime() {
238: assertEquals(GOOD_BLOCKED_TIME, ti.getBlockedTime());
239: }
240:
241: /*
242: * Test method for 'java.lang.management.ThreadInfo.getLockOwnerId()'
243: */
244: public void testGetLockOwnerId() {
245: assertEquals(GOOD_LOCK_OWNER_ID, ti.getLockOwnerId());
246: }
247:
248: /*
249: * Test method for 'java.lang.management.ThreadInfo.getLockOwnerName()'
250: */
251: public void testGetLockOwnerName() {
252: assertEquals(GOOD_LOCK_OWNER_NAME, ti.getLockOwnerName());
253: }
254:
255: /*
256: * Test method for 'java.lang.management.ThreadInfo.getStackTrace()'
257: */
258: public void testGetStackTrace() {
259: StackTraceElement[] stack = ti.getStackTrace();
260: assertEquals(GOOD_STACK_SIZE, stack.length);
261: for (StackTraceElement element : stack) {
262: assertEquals(GOOD_STACK_CLASSNAME, element.getClassName());
263: assertEquals(GOOD_STACK_NATIVEMETHOD, element
264: .isNativeMethod());
265: assertEquals(GOOD_STACK_FILENAME, element.getFileName());
266: assertEquals(GOOD_STACK_LINENUMBER, element.getLineNumber());
267: assertEquals(GOOD_STACK_METHODNAME, element.getMethodName());
268: }
269: }
270:
271: /*
272: * Test method for 'java.lang.management.ThreadInfo.getThreadId()'
273: */
274: public void testGetThreadId() {
275: assertEquals(GOOD_THREAD_ID, ti.getThreadId());
276: }
277:
278: /*
279: * Test method for 'java.lang.management.ThreadInfo.getThreadName()'
280: */
281: public void testGetThreadName() {
282: assertEquals(GOOD_THREAD_NAME, ti.getThreadName());
283: }
284:
285: /*
286: * Test method for 'java.lang.management.ThreadInfo.getThreadState()'
287: */
288: public void testGetThreadState() {
289: assertEquals(GOOD_THREAD_STATE, (ti.getThreadState()));
290: }
291:
292: /*
293: * Test method for 'java.lang.management.ThreadInfo.getWaitedCount()'
294: */
295: public void testGetWaitedCount() {
296: assertEquals(GOOD_WAITED_COUNT, ti.getWaitedCount());
297: }
298:
299: /*
300: * Test method for 'java.lang.management.ThreadInfo.getWaitedTime()'
301: */
302: public void testGetWaitedTime() {
303: assertEquals(GOOD_WAITED_TIME, ti.getWaitedTime());
304: }
305:
306: /*
307: * Test method for 'java.lang.management.ThreadInfo.isInNative()'
308: */
309: public void testIsInNative() {
310: assertEquals(GOOD_IN_NATIVE, ti.isInNative());
311: }
312:
313: /*
314: * Test method for 'java.lang.management.ThreadInfo.isSuspended()'
315: */
316: public void testIsSuspended() {
317: assertEquals(GOOD_SUSPENDED, ti.isSuspended());
318: }
319:
320: /*
321: * Test method for 'java.lang.management.ThreadInfo.toString()'
322: */
323: public void testToString() {
324: assertEquals(getGoodToStringVal(), ti.toString());
325: }
326:
327: String getGoodToStringVal() {
328: StringBuilder result = new StringBuilder();
329: result.append("Thread " + GOOD_THREAD_NAME + " (Id = "
330: + GOOD_THREAD_ID + ") " + GOOD_THREAD_STATE + " "
331: + GOOD_LOCK_NAME);
332: return result.toString();
333: }
334: }
|