J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright 2004-2005 Sun Microsystems, Inc. All Rights Reserved. |
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| 4 | * |
| 5 | * This code is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of the GNU General Public License version 2 only, as |
| 7 | * published by the Free Software Foundation. |
| 8 | * |
| 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
| 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| 12 | * version 2 for more details (a copy is included in the LICENSE file that |
| 13 | * accompanied this code). |
| 14 | * |
| 15 | * You should have received a copy of the GNU General Public License version |
| 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
| 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| 18 | * |
| 19 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| 20 | * CA 95054 USA or visit www.sun.com if you need additional information or |
| 21 | * have any questions. |
| 22 | */ |
| 23 | |
| 24 | /* |
| 25 | * @test |
| 26 | * @bug 4982289 |
| 27 | * @summary Test ThreadInfo.from to return a valid |
| 28 | * ThreadInfo object. Or throw exception if |
| 29 | * the input CompositeData is invalid. |
| 30 | * @author Mandy Chung |
| 31 | * |
| 32 | * @compile -source 1.5 OpenTypeConverter.java |
| 33 | * @build ThreadInfoCompositeData |
| 34 | * @run main ThreadInfoCompositeData |
| 35 | */ |
| 36 | |
| 37 | import javax.management.openmbean.*; |
| 38 | import java.lang.management.LockInfo; |
| 39 | import java.lang.management.MonitorInfo; |
| 40 | import java.lang.management.ThreadInfo; |
| 41 | |
| 42 | public class ThreadInfoCompositeData { |
| 43 | private static StackTraceElement[] ste = new StackTraceElement[1]; |
| 44 | private static CompositeData[] steCD = new CompositeData[1]; |
| 45 | private static String lockClassName = "myClass"; |
| 46 | private static int lockIdentityHashCode = 123456; |
| 47 | private static String lockName = lockClassName + '@' + |
| 48 | Integer.toHexString(lockIdentityHashCode); |
| 49 | private static LockInfo lockInfo = |
| 50 | new LockInfo(lockClassName, lockIdentityHashCode); |
| 51 | |
| 52 | public static void main(String[] argv) throws Exception { |
| 53 | // A valid CompositeData is passed to ThreadInfo |
| 54 | createGoodCompositeData(); |
| 55 | // A valid CompositeData for JDK 5.0 ThreadInfo |
| 56 | // is passed to ThreadInfo |
| 57 | createV5ThreadInfo(); |
| 58 | // An invalid CompositeData is passed to ThreadInfo.from() |
| 59 | badNameCompositeData(); |
| 60 | badTypeCompositeData(); |
| 61 | System.out.println("Test passed"); |
| 62 | } |
| 63 | |
| 64 | public static void createGoodCompositeData() throws Exception { |
| 65 | CompositeType ct = |
| 66 | new CompositeType("MyCompositeType", |
| 67 | "CompositeType for ThreadInfo", |
| 68 | validItemNames, |
| 69 | validItemNames, |
| 70 | validItemTypes); |
| 71 | CompositeData cd = |
| 72 | new CompositeDataSupport(ct, |
| 73 | validItemNames, |
| 74 | values); |
| 75 | ThreadInfo info = ThreadInfo.from(cd); |
| 76 | checkThreadInfo(info); |
| 77 | } |
| 78 | |
| 79 | public static void createV5ThreadInfo() throws Exception { |
| 80 | String[] v5ItemNames = new String[NUM_V5_ATTS]; |
| 81 | OpenType[] v5ItemTypes = new OpenType[NUM_V5_ATTS]; |
| 82 | Object[] v5ItemValues = new Object[NUM_V5_ATTS]; |
| 83 | for (int i = 0; i < NUM_V5_ATTS; i++) { |
| 84 | v5ItemNames[i] = validItemNames[i]; |
| 85 | v5ItemTypes[i] = validItemTypes[i]; |
| 86 | v5ItemValues[i] = values[i]; |
| 87 | } |
| 88 | CompositeType ct = |
| 89 | new CompositeType("MyCompositeType", |
| 90 | "CompositeType for JDK 5.0 ThreadInfo", |
| 91 | v5ItemNames, |
| 92 | v5ItemNames, |
| 93 | v5ItemTypes); |
| 94 | CompositeData cd = |
| 95 | new CompositeDataSupport(ct, |
| 96 | v5ItemNames, |
| 97 | v5ItemValues); |
| 98 | ThreadInfo info = ThreadInfo.from(cd); |
| 99 | checkThreadInfo(info); |
| 100 | } |
| 101 | |
| 102 | static void checkThreadInfo(ThreadInfo info) throws Exception { |
| 103 | if (info.getThreadId() != ((Long) values[THREAD_ID]).longValue()) { |
| 104 | throw new RuntimeException("Thread Id = " + info.getThreadId() + |
| 105 | " expected = " + values[THREAD_ID]); |
| 106 | } |
| 107 | if (!info.getThreadName().equals(values[THREAD_NAME])) { |
| 108 | throw new RuntimeException("Thread Name = " + |
| 109 | info.getThreadName() + " expected = " + values[THREAD_NAME]); |
| 110 | } |
| 111 | if (info.getThreadState() != Thread.State.RUNNABLE) { |
| 112 | throw new RuntimeException("Thread Name = " + |
| 113 | info.getThreadName() + " expected = " + Thread.State.RUNNABLE); |
| 114 | } |
| 115 | if (info.getBlockedTime() != ((Long) values[BLOCKED_TIME]).longValue()) { |
| 116 | throw new RuntimeException("blocked time = " + |
| 117 | info.getBlockedTime() + |
| 118 | " expected = " + values[BLOCKED_TIME]); |
| 119 | } |
| 120 | if (info.getBlockedCount() != ((Long) values[BLOCKED_COUNT]).longValue()) { |
| 121 | throw new RuntimeException("blocked count = " + |
| 122 | info.getBlockedCount() + |
| 123 | " expected = " + values[BLOCKED_COUNT]); |
| 124 | } |
| 125 | if (info.getWaitedTime() != ((Long) values[WAITED_TIME]).longValue()) { |
| 126 | throw new RuntimeException("waited time = " + |
| 127 | info.getWaitedTime() + |
| 128 | " expected = " + values[WAITED_TIME]); |
| 129 | } |
| 130 | if (info.getWaitedCount() != ((Long) values[WAITED_COUNT]).longValue()) { |
| 131 | throw new RuntimeException("waited count = " + |
| 132 | info.getWaitedCount() + |
| 133 | " expected = " + values[WAITED_COUNT]); |
| 134 | } |
| 135 | if (!info.getLockName().equals(values[LOCK_NAME])) { |
| 136 | throw new RuntimeException("Lock Name = " + |
| 137 | info.getLockName() + " expected = " + values[LOCK_NAME]); |
| 138 | } |
| 139 | if (info.getLockOwnerId() != |
| 140 | ((Long) values[LOCK_OWNER_ID]).longValue()) { |
| 141 | throw new RuntimeException( |
| 142 | "LockOwner Id = " + info.getLockOwnerId() + |
| 143 | " expected = " + values[LOCK_OWNER_ID]); |
| 144 | } |
| 145 | if (!info.getLockOwnerName().equals(values[LOCK_OWNER_NAME])) { |
| 146 | throw new RuntimeException("LockOwner Name = " + |
| 147 | info.getLockOwnerName() + " expected = " + |
| 148 | values[LOCK_OWNER_NAME]); |
| 149 | } |
| 150 | |
| 151 | checkStackTrace(info.getStackTrace()); |
| 152 | |
| 153 | checkLockInfo(info.getLockInfo()); |
| 154 | } |
| 155 | |
| 156 | private static void checkStackTrace(StackTraceElement[] s) |
| 157 | throws Exception { |
| 158 | if (ste.length != s.length) { |
| 159 | throw new RuntimeException("Stack Trace length = " + |
| 160 | s.length + " expected = " + ste.length); |
| 161 | } |
| 162 | |
| 163 | StackTraceElement s1 = ste[0]; |
| 164 | StackTraceElement s2 = s[0]; |
| 165 | |
| 166 | if (!s1.getClassName().equals(s2.getClassName())) { |
| 167 | throw new RuntimeException("Class name = " + |
| 168 | s2.getClassName() + " expected = " + s1.getClassName()); |
| 169 | } |
| 170 | if (!s1.getMethodName().equals(s2.getMethodName())) { |
| 171 | throw new RuntimeException("Method name = " + |
| 172 | s2.getMethodName() + " expected = " + s1.getMethodName()); |
| 173 | } |
| 174 | if (!s1.getFileName().equals(s2.getFileName())) { |
| 175 | throw new RuntimeException("File name = " + |
| 176 | s2.getFileName() + " expected = " + s1.getFileName()); |
| 177 | } |
| 178 | if (s1.getLineNumber() != s2.getLineNumber()) { |
| 179 | throw new RuntimeException("Line number = " + |
| 180 | s2.getLineNumber() + " expected = " + s1.getLineNumber()); |
| 181 | } |
| 182 | } |
| 183 | |
| 184 | private static void checkLockInfo(LockInfo li) |
| 185 | throws Exception { |
| 186 | if (!li.getClassName().equals(lockInfo.getClassName())) { |
| 187 | throw new RuntimeException("Class Name = " + |
| 188 | li.getClassName() + " expected = " + lockInfo.getClassName()); |
| 189 | } |
| 190 | if (li.getIdentityHashCode() != lockInfo.getIdentityHashCode()) { |
| 191 | throw new RuntimeException("Class Name = " + |
| 192 | li.getIdentityHashCode() + " expected = " + |
| 193 | lockInfo.getIdentityHashCode()); |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | public static void badNameCompositeData() throws Exception { |
| 198 | CompositeType ct = |
| 199 | new CompositeType("MyCompositeType", |
| 200 | "CompositeType for ThreadInfo", |
| 201 | badItemNames, |
| 202 | badItemNames, |
| 203 | validItemTypes); |
| 204 | CompositeData cd = |
| 205 | new CompositeDataSupport(ct, |
| 206 | badItemNames, |
| 207 | values); |
| 208 | |
| 209 | try { |
| 210 | ThreadInfo info = ThreadInfo.from(cd); |
| 211 | } catch (IllegalArgumentException e) { |
| 212 | System.out.println("Expected exception: " + |
| 213 | e.getMessage()); |
| 214 | return; |
| 215 | } |
| 216 | throw new RuntimeException( |
| 217 | "IllegalArgumentException not thrown"); |
| 218 | } |
| 219 | |
| 220 | public static void badTypeCompositeData() throws Exception { |
| 221 | CompositeType ct = |
| 222 | new CompositeType("MyCompositeType", |
| 223 | "CompositeType for ThreadInfo", |
| 224 | validItemNames, |
| 225 | validItemNames, |
| 226 | badItemTypes); |
| 227 | |
| 228 | // patch values[STACK_TRACE] to Long |
| 229 | values[STACK_TRACE] = new Long(1000); |
| 230 | values[LOCK_INFO] = new Long(1000); |
| 231 | CompositeData cd = |
| 232 | new CompositeDataSupport(ct, |
| 233 | validItemNames, |
| 234 | values); |
| 235 | |
| 236 | try { |
| 237 | ThreadInfo info = ThreadInfo.from(cd); |
| 238 | } catch (IllegalArgumentException e) { |
| 239 | System.out.println("Expected exception: " + |
| 240 | e.getMessage()); |
| 241 | return; |
| 242 | } |
| 243 | throw new RuntimeException( |
| 244 | "IllegalArgumentException not thrown"); |
| 245 | } |
| 246 | |
| 247 | private static final int THREAD_ID = 0; |
| 248 | private static final int THREAD_NAME = 1; |
| 249 | private static final int THREAD_STATE = 2; |
| 250 | private static final int BLOCKED_TIME = 3; |
| 251 | private static final int BLOCKED_COUNT = 4; |
| 252 | private static final int WAITED_TIME = 5; |
| 253 | private static final int WAITED_COUNT = 6; |
| 254 | private static final int LOCK_NAME = 7; |
| 255 | private static final int LOCK_OWNER_ID = 8; |
| 256 | private static final int LOCK_OWNER_NAME = 9; |
| 257 | private static final int STACK_TRACE = 10; |
| 258 | private static final int SUSPENDED = 11; |
| 259 | private static final int IN_NATIVE = 12; |
| 260 | private static final int NUM_V5_ATTS = 13; |
| 261 | // JDK 6.0 ThreadInfo attribtues |
| 262 | private static final int LOCK_INFO = 13; |
| 263 | |
| 264 | private static final String[] validItemNames = { |
| 265 | "threadId", |
| 266 | "threadName", |
| 267 | "threadState", |
| 268 | "blockedTime", |
| 269 | "blockedCount", |
| 270 | "waitedTime", |
| 271 | "waitedCount", |
| 272 | "lockName", |
| 273 | "lockOwnerId", |
| 274 | "lockOwnerName", |
| 275 | "stackTrace", |
| 276 | "suspended", |
| 277 | "inNative", |
| 278 | "lockInfo", |
| 279 | }; |
| 280 | |
| 281 | private static OpenType[] validItemTypes = { |
| 282 | SimpleType.LONG, |
| 283 | SimpleType.STRING, |
| 284 | SimpleType.STRING, |
| 285 | SimpleType.LONG, |
| 286 | SimpleType.LONG, |
| 287 | SimpleType.LONG, |
| 288 | SimpleType.LONG, |
| 289 | SimpleType.STRING, |
| 290 | SimpleType.LONG, |
| 291 | SimpleType.STRING, |
| 292 | null, // ArrayType for StackTraceElement[] |
| 293 | SimpleType.BOOLEAN, |
| 294 | SimpleType.BOOLEAN, |
| 295 | null, // CompositeType for LockInfo |
| 296 | }; |
| 297 | |
| 298 | private static Object[] values = { |
| 299 | new Long(100), |
| 300 | "FooThread", |
| 301 | "RUNNABLE", |
| 302 | new Long(200), |
| 303 | new Long(10), |
| 304 | new Long(300), |
| 305 | new Long(20), |
| 306 | lockName, |
| 307 | new Long(99), |
| 308 | "BarThread", |
| 309 | steCD, |
| 310 | new Boolean(false), |
| 311 | new Boolean(false), |
| 312 | null, // To be initialized to lockInfoCD |
| 313 | }; |
| 314 | |
| 315 | private static final String[] steItemNames = { |
| 316 | "className", |
| 317 | "methodName", |
| 318 | "fileName", |
| 319 | "lineNumber", |
| 320 | "nativeMethod", |
| 321 | }; |
| 322 | |
| 323 | private static final String[] lockInfoItemNames = { |
| 324 | "className", |
| 325 | "identityHashCode", |
| 326 | }; |
| 327 | |
| 328 | static { |
| 329 | // create stack trace element |
| 330 | ste[0] = new StackTraceElement("FooClass", "getFoo", "Foo.java", 100); |
| 331 | |
| 332 | // initialize the ste[0] and values and validItemTypes |
| 333 | try { |
| 334 | CompositeType steCType = (CompositeType) |
| 335 | OpenTypeConverter.toOpenType(StackTraceElement.class); |
| 336 | validItemTypes[STACK_TRACE] = new ArrayType(1, steCType); |
| 337 | |
| 338 | final Object[] steValue = { |
| 339 | ste[0].getClassName(), |
| 340 | ste[0].getMethodName(), |
| 341 | ste[0].getFileName(), |
| 342 | new Integer(ste[0].getLineNumber()), |
| 343 | new Boolean(ste[0].isNativeMethod()), |
| 344 | }; |
| 345 | |
| 346 | steCD[0] = |
| 347 | new CompositeDataSupport(steCType, |
| 348 | steItemNames, |
| 349 | steValue); |
| 350 | |
| 351 | CompositeType lockInfoCType = (CompositeType) |
| 352 | OpenTypeConverter.toOpenType(LockInfo.class); |
| 353 | validItemTypes[LOCK_INFO] = lockInfoCType; |
| 354 | |
| 355 | final Object[] lockInfoValue = { |
| 356 | lockInfo.getClassName(), |
| 357 | lockInfo.getIdentityHashCode(), |
| 358 | }; |
| 359 | |
| 360 | values[LOCK_INFO] = |
| 361 | new CompositeDataSupport(lockInfoCType, |
| 362 | lockInfoItemNames, |
| 363 | lockInfoValue); |
| 364 | } catch (Exception e) { |
| 365 | throw new RuntimeException(e); |
| 366 | } |
| 367 | } |
| 368 | |
| 369 | private static final String[] badItemNames = { |
| 370 | "threadId", |
| 371 | "threadName", |
| 372 | "threadState", |
| 373 | "blockedTime", |
| 374 | "blockedCount", |
| 375 | "waitedTime", |
| 376 | "waitedCount", |
| 377 | "lockName", |
| 378 | "lockOwnerId", |
| 379 | "lockOwnerName", |
| 380 | "BadStackTrace", // bad item name |
| 381 | "suspended", |
| 382 | "inNative", |
| 383 | "lockInfo", |
| 384 | }; |
| 385 | private static final OpenType[] badItemTypes = { |
| 386 | SimpleType.LONG, |
| 387 | SimpleType.STRING, |
| 388 | SimpleType.STRING, |
| 389 | SimpleType.LONG, |
| 390 | SimpleType.LONG, |
| 391 | SimpleType.LONG, |
| 392 | SimpleType.LONG, |
| 393 | SimpleType.STRING, |
| 394 | SimpleType.LONG, |
| 395 | SimpleType.STRING, |
| 396 | SimpleType.LONG, // bad type |
| 397 | SimpleType.BOOLEAN, |
| 398 | SimpleType.BOOLEAN, |
| 399 | SimpleType.LONG, // bad type |
| 400 | }; |
| 401 | |
| 402 | } |