1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 * ident "%Z%%M% %I% %E% SMI" 27 */ 28 29 import org.opensolaris.os.dtrace.*; 30 import java.util.*; 31 import java.io.*; 32 import java.beans.*; 33 import java.lang.reflect.*; 34 35 /** 36 * Regression test for serialization and XML encoding/decoding. Tests 37 * every Serializable class in the Java DTrace API by creating a dummy 38 * instance, writing it to a file, then reading it back in and comparing 39 * the string values of the object before and after, as well as 40 * verifying object equality before and after if the class overrides the 41 * equals() method. 42 */ 43 public class TestBean { 44 public static final String[] TESTS = new String[] { 45 "ExitRecord", 46 "AggregationRecord", 47 "Aggregation", 48 "Tuple", 49 "ScalarRecord", 50 "KernelStackRecord", 51 "LogDistribution", 52 "LinearDistribution", 53 "Option", 54 "ProcessState", 55 "ProbeDescription", 56 "PrintaRecord", 57 "PrintfRecord", 58 "ProbeData", 59 "Aggregate", 60 "UserStackRecord", 61 "AvgValue", 62 "CountValue", 63 "SumValue", 64 "MinValue", 65 "MaxValue", 66 "Error", 67 "Drop", 68 "InterfaceAttributes", 69 "ProgramInfo", 70 "ProbeInfo", 71 "Probe", 72 "Flow", 73 "KernelSymbolRecord", 74 "UserSymbolRecord", 75 "UserSymbolRecord$Value" 76 }; 77 78 static void 79 exit(int status) 80 { 81 System.out.flush(); 82 System.err.flush(); 83 System.exit(status); 84 } 85 86 public static XMLEncoder 87 getXMLEncoder(File file) 88 { 89 XMLEncoder encoder = null; 90 try { 91 OutputStream out = new BufferedOutputStream 92 (new FileOutputStream(file)); 93 encoder = new XMLEncoder(out); 94 } catch (Exception e) { 95 e.printStackTrace(); 96 exit(1); 97 } 98 return encoder; 99 } 100 101 public static XMLDecoder 102 getXMLDecoder(File file) 103 { 104 return getXMLDecoder(file, null); 105 } 106 107 public static XMLDecoder 108 getXMLDecoder(File file, ExceptionListener exceptionListener) 109 { 110 XMLDecoder decoder = null; 111 try { 112 InputStream in = new BufferedInputStream 113 (new FileInputStream(file)); 114 decoder = new XMLDecoder(in, null, exceptionListener); 115 } catch (Exception e) { 116 e.printStackTrace(); 117 exit(1); 118 } 119 return decoder; 120 } 121 122 public static ExitRecord 123 getExitRecord() 124 { 125 ExitRecord r = new ExitRecord(1); 126 return r; 127 } 128 129 public static AggregationRecord 130 getAggregationRecord() 131 { 132 Tuple tuple = getTuple(); 133 AggregationValue value = new CountValue(7); 134 AggregationRecord r = new AggregationRecord(tuple, value); 135 return r; 136 } 137 138 public static Aggregation 139 getAggregation() 140 { 141 List < AggregationRecord > list = 142 new ArrayList < AggregationRecord > (); 143 AggregationRecord r; 144 r = getAggregationRecord(); 145 list.add(r); 146 147 ValueRecord v1 = new ScalarRecord(new byte[] {(byte)1, (byte)2, 148 (byte)3}, 3); 149 ValueRecord v2 = new ScalarRecord("shebang!", 256); 150 Tuple tuple = new Tuple(v1, v2); 151 AggregationValue value = getLinearDistribution(); 152 r = new AggregationRecord(tuple, value); 153 list.add(r); 154 155 Aggregation a = new Aggregation("counts", 2, list); 156 return a; 157 } 158 159 public static Tuple 160 getTuple() 161 { 162 ValueRecord r1 = new ScalarRecord("cat", 256); 163 ValueRecord r2 = new ScalarRecord(new Integer(9), 2); 164 ValueRecord r3 = new KernelStackRecord( 165 new StackFrame[] { 166 new StackFrame("has"), 167 new StackFrame("nine"), 168 new StackFrame("lives")}, 169 new byte[] { (byte)0, (byte)1, (byte)2 }); 170 ValueRecord r4 = new ScalarRecord(new byte[] {(byte)1, (byte)2, 171 (byte)3}, 3); 172 173 Tuple tuple = new Tuple(r1, r2, r3, r4); 174 return tuple; 175 } 176 177 public static ScalarRecord 178 getScalarRecord() 179 { 180 Object v = new byte[] {(byte)1, (byte)2, (byte)3}; 181 ScalarRecord r = new ScalarRecord(v, 3); 182 return r; 183 } 184 185 public static KernelStackRecord 186 getKernelStackRecord() 187 { 188 StackFrame[] stackFrames = new StackFrame[] { 189 new StackFrame("Frame 1"), 190 new StackFrame("Frame 2"), 191 new StackFrame("Frame 3") 192 }; 193 KernelStackRecord r = new KernelStackRecord(stackFrames, 194 new byte[] { (byte)0, (byte)1, (byte)2 }); 195 return r; 196 } 197 198 public static LogDistribution 199 getLogDistribution() 200 { 201 List < Distribution.Bucket > buckets = 202 new ArrayList < Distribution.Bucket > (); 203 Distribution.Bucket bucket; 204 int n = 0; 205 long base = 0; 206 long i; 207 long sign; 208 long nextSign; 209 long power; 210 long nextPower; 211 long lowerBound; 212 long upperBound; 213 for (i = -62; i <= 62; ++i) { 214 if (i == 0) { 215 bucket = new Distribution.Bucket(-1, -1, n++); 216 buckets.add(bucket); 217 bucket = new Distribution.Bucket(0, 0, n++); 218 buckets.add(bucket); 219 bucket = new Distribution.Bucket(1, 1, n++); 220 buckets.add(bucket); 221 continue; 222 } 223 sign = ((i < 0) ? -1L : 1L); 224 power = (sign * i); 225 nextSign = (((i + 1) < 0) ? -1L : 1L); 226 nextPower = (nextSign * (i + 1)); 227 lowerBound = sign * ((long) Math.pow(2L, power)); 228 upperBound = (nextPower == 0 ? -2L : 229 (nextSign * ((long) Math.pow(2L, nextPower))) - 1); 230 if ((upperBound > 0) && ((upperBound * 2L) < 0)) { 231 upperBound = Long.MAX_VALUE; 232 } 233 bucket = new Distribution.Bucket(lowerBound, upperBound, n++); 234 buckets.add(bucket); 235 } 236 LogDistribution d = new LogDistribution(buckets); 237 return d; 238 } 239 240 public static LinearDistribution 241 getLinearDistribution() 242 { 243 List < Distribution.Bucket > buckets = 244 new ArrayList < Distribution.Bucket > (); 245 Distribution.Bucket bucket; 246 int n = 10; // number of buckets 247 int base = 1; 248 int step = 10; 249 bucket = new Distribution.Bucket(Long.MIN_VALUE, (base - 1), 0); 250 buckets.add(bucket); 251 for (int i = base; i < (n * step); i += step) { 252 bucket = new Distribution.Bucket(i, (i + (step - 1)), 253 ((i - 1) / step)); 254 buckets.add(bucket); 255 } 256 bucket = new Distribution.Bucket((n * step) + 1, Long.MAX_VALUE, 0); 257 buckets.add(bucket); 258 LinearDistribution d = new LinearDistribution(base, step, buckets); 259 return d; 260 } 261 262 public static Option 263 getOption() 264 { 265 Option option = new Option("aggrate", "1s"); 266 return option; 267 } 268 269 public static ProcessState 270 getProcessState() 271 { 272 ProcessState p = new ProcessState(123456, "UNDEAD", 273 3, "SIGSTOP", 274 -2, "Process stopped on dime"); 275 return p; 276 } 277 278 public static ProbeDescription 279 getProbeDescription() 280 { 281 ProbeDescription d = new ProbeDescription(256, "syscall", null, 282 "malloc", "entry"); 283 return d; 284 } 285 286 public static PrintaRecord 287 getPrintaRecord() 288 { 289 List < Aggregation > aggregations = new ArrayList < Aggregation > (); 290 Aggregation a = getAggregation(); 291 aggregations.add(a); 292 aggregations.add(a); 293 Map < Tuple, String > formattedOutput = 294 new HashMap < Tuple, String > (); 295 for (Tuple t : a.asMap().keySet()) { 296 formattedOutput.put(t, "cat"); 297 } 298 List < Tuple > tuples = new ArrayList < Tuple > (); 299 for (Tuple t : a.asMap().keySet()) { 300 tuples.add(t); 301 } 302 Collections.sort(tuples); 303 PrintaRecord r = new PrintaRecord(1234567890L, 304 aggregations, formattedOutput, tuples, 305 "Yes, this is the formatted printa() output"); 306 return r; 307 } 308 309 public static PrintfRecord 310 getPrintfRecord() 311 { 312 List < ValueRecord > list = new ArrayList < ValueRecord > (); 313 ValueRecord v1 = getScalarRecord(); 314 ValueRecord v2 = new ScalarRecord(new Integer(7), 4); 315 list.add(v1); 316 list.add(v2); 317 PrintfRecord r = new PrintfRecord(list, 318 "long formatted string"); 319 return r; 320 } 321 322 public static ProbeData 323 getProbeData() 324 { 325 List < Record > list = new ArrayList < Record > (); 326 list.add(getPrintaRecord()); 327 list.add(getPrintfRecord()); 328 list.add(getScalarRecord()); 329 ProbeData d = new ProbeData(7, 1, getProbeDescription(), 330 getFlow(), list); 331 return d; 332 } 333 334 public static Aggregate 335 getAggregate() 336 { 337 List < Aggregation > list = new ArrayList < Aggregation > (); 338 list.add(getAggregation()); 339 340 List < AggregationRecord > reclist = 341 new ArrayList < AggregationRecord > (); 342 AggregationRecord r; 343 ValueRecord v1 = new ScalarRecord("cat", 256); 344 ValueRecord v2 = new ScalarRecord("dog", 256); 345 ValueRecord v3 = new ScalarRecord("mouse", 256); 346 ValueRecord v4 = new ScalarRecord("mouse", 256); 347 ValueRecord v5 = new ScalarRecord(new Byte((byte) 'C'), 1); 348 ValueRecord v6 = new ScalarRecord(new Short((short) 7), 2); 349 Tuple tuple = new Tuple(v1, v2, v3, v4, v5, v6); 350 AggregationValue value = getCountValue(); 351 r = new AggregationRecord(tuple, value); 352 reclist.add(r); 353 list.add(new Aggregation("times", 1, reclist)); 354 355 Aggregate a = new Aggregate(1234567890L, list); 356 return a; 357 } 358 359 public static UserStackRecord 360 getUserStackRecord() 361 { 362 StackFrame[] frames = new StackFrame[] { 363 new StackFrame("User Stack Frame 1"), 364 new StackFrame("User Stack Frame 2"), 365 new StackFrame("User Stack Frame 3") 366 }; 367 UserStackRecord r = new UserStackRecord(123456, frames, 368 new byte[] { (byte)0, (byte)1, (byte)2 }); 369 return r; 370 } 371 372 public static AvgValue 373 getAvgValue() 374 { 375 AvgValue v = new AvgValue(5, 20, 4); 376 return v; 377 } 378 379 public static CountValue 380 getCountValue() 381 { 382 CountValue v = new CountValue(9); 383 return v; 384 } 385 386 public static MinValue 387 getMinValue() 388 { 389 MinValue v = new MinValue(101); 390 return v; 391 } 392 393 public static MaxValue 394 getMaxValue() 395 { 396 MaxValue v = new MaxValue(101); 397 return v; 398 } 399 400 public static SumValue 401 getSumValue() 402 { 403 SumValue v = new SumValue(25); 404 return v; 405 } 406 407 public static org.opensolaris.os.dtrace.Error 408 getError() 409 { 410 ProbeDescription probe = getProbeDescription(); 411 org.opensolaris.os.dtrace.Error e = 412 new org.opensolaris.os.dtrace.Error(probe, 8, 3, 413 1, 20, "DTRACEFLT_BADALIGN", -1, "error on enabled probe ID 8 " + 414 "(ID " + probe.getID() + ": " + probe + "): Bad alignment " + 415 "(0x33ef) in action #1 at DIF offset 20"); 416 return e; 417 } 418 419 public static Drop 420 getDrop() 421 { 422 Drop drop = new Drop(2, "SPECBUSY", 72, 1041, 423 "Guess we dropped stuff all over the place."); 424 return drop; 425 } 426 427 public static InterfaceAttributes 428 getInterfaceAttributes() 429 { 430 InterfaceAttributes a = new InterfaceAttributes( 431 InterfaceAttributes.Stability.UNSTABLE, 432 InterfaceAttributes.Stability.EVOLVING, 433 InterfaceAttributes.DependencyClass.ISA); 434 return a; 435 } 436 437 public static ProgramInfo 438 getProgramInfo() 439 { 440 ProgramInfo info = new ProgramInfo(getInterfaceAttributes(), 441 getInterfaceAttributes(), 256); 442 return info; 443 } 444 445 public static ProbeInfo 446 getProbeInfo() 447 { 448 ProbeInfo info = new ProbeInfo(getInterfaceAttributes(), 449 getInterfaceAttributes()); 450 return info; 451 } 452 453 public static Probe 454 getProbe() 455 { 456 Probe p = new Probe(getProbeDescription(), getProbeInfo()); 457 return p; 458 } 459 460 public static Flow 461 getFlow() 462 { 463 Flow f = new Flow(Flow.Kind.RETURN.name(), 3); 464 return f; 465 } 466 467 public static KernelSymbolRecord 468 getKernelSymbolRecord() 469 { 470 KernelSymbolRecord r = new KernelSymbolRecord("mod`func+0x4", -1L); 471 return r; 472 } 473 474 public static UserSymbolRecord 475 getUserSymbolRecord() 476 { 477 UserSymbolRecord r = new UserSymbolRecord(7, "mod`func+0x4", -1L); 478 return r; 479 } 480 481 public static UserSymbolRecord.Value 482 getUserSymbolRecord$Value() 483 { 484 UserSymbolRecord.Value v = new UserSymbolRecord.Value(7, -1L); 485 return v; 486 } 487 488 static String 489 getString(Object o) 490 { 491 String s; 492 if (o instanceof ScalarRecord) { 493 o = ((ScalarRecord)o).getValue(); 494 } 495 496 if (o instanceof byte[]) { 497 s = Arrays.toString((byte[])o); 498 } else if (o instanceof Object[]) { 499 s = Arrays.toString((Object[])o); 500 } else { 501 Class c = o.getClass(); 502 try { 503 Method m = c.getDeclaredMethod("toLogString"); 504 s = (String)m.invoke(o); 505 } catch (Exception e) { 506 s = o.toString(); 507 } 508 } 509 return s; 510 } 511 512 static void 513 checkEquality(Object obj, Object newobj) 514 { 515 // If the class overrides equals(), make sure the re-created 516 // object still equals the original object 517 try { 518 Method eq = obj.getClass().getDeclaredMethod("equals", 519 Object.class); 520 Boolean ret = (Boolean) eq.invoke(obj, newobj); 521 if (ret != true) { 522 System.err.println("serialization failed: " + 523 obj.getClass().getName()); 524 exit(1); 525 } 526 } catch (Exception e) { 527 // Does not override equals(), although a super-class might. 528 // A better test would check for any superclass other than 529 // Object.class. 530 } 531 } 532 533 static void 534 performSerializationTest(File file, String classname) 535 throws IOException, ClassNotFoundException 536 { 537 String methodName = "get" + classname; 538 Object obj = null; 539 Object newobj = null; 540 try { 541 Method method = TestBean.class.getDeclaredMethod(methodName); 542 obj = method.invoke(null); 543 } catch (Exception e) { 544 e.printStackTrace(); 545 exit(1); 546 } 547 548 System.out.println(classname + ":"); 549 String serialized = getString(obj); 550 System.out.println(" serialized: " + serialized); 551 FileOutputStream fos = new FileOutputStream(file); 552 ObjectOutputStream out = new ObjectOutputStream(fos); 553 out.writeObject(obj); 554 FileInputStream fis = new FileInputStream(file); 555 ObjectInputStream in = new ObjectInputStream(fis); 556 newobj = in.readObject(); 557 String deserialized = getString(newobj); 558 System.out.println(" deserialized: " + deserialized); 559 560 if (!serialized.equals(deserialized)) { 561 System.err.println("serialization failed: " + classname); 562 exit(1); 563 } 564 checkEquality(obj, newobj); 565 } 566 567 static void 568 performBeanTest(File file, String classname) 569 { 570 String methodName = "get" + classname; 571 Object obj = null; 572 Object newobj = null; 573 try { 574 Method method = TestBean.class.getDeclaredMethod(methodName); 575 obj = method.invoke(null); 576 } catch (Exception e) { 577 e.printStackTrace(); 578 exit(1); 579 } 580 581 System.out.println(classname + ":"); 582 XMLEncoder encoder = getXMLEncoder(file); 583 String encoded = getString(obj); 584 System.out.println(" encoded: " + encoded); 585 encoder.writeObject(obj); 586 encoder.close(); 587 XMLDecoder decoder = getXMLDecoder(file); 588 newobj = decoder.readObject(); 589 String decoded = getString(newobj); 590 System.out.println(" decoded: " + decoded); 591 decoder.close(); 592 593 if (!encoded.equals(decoded)) { 594 System.err.println("bean persistence failed: " + classname); 595 exit(1); 596 } 597 checkEquality(obj, newobj); 598 } 599 600 public static void 601 main(String[] args) 602 { 603 if ((args.length != 1) && (args.length != 2)) { 604 System.err.println("usage: java TestBean < filename > " + 605 "[ < classname > ]"); 606 exit(1); 607 } 608 609 String filename = args[0]; 610 String classname = null; 611 if (args.length >= 2) { 612 classname = args[1]; 613 } 614 615 File file = new File(filename); 616 try { 617 if (!file.canRead()) { 618 try { 619 file.createNewFile(); 620 } catch (Exception e) { 621 System.err.println("failed to create " + filename); 622 exit(1); 623 } 624 } 625 } catch (SecurityException e) { 626 System.err.println("failed to open " + filename); 627 exit(1); 628 } 629 630 String[] tests = (classname == null ? TESTS: 631 new String[] { classname }); 632 try { 633 for (int i = 0; i < tests.length; ++i) { 634 performSerializationTest(file, tests[i]); 635 performBeanTest(file, tests[i]); 636 } 637 } catch (IOException e) { 638 e.printStackTrace(); 639 exit(1); 640 } catch (ClassNotFoundException e) { 641 e.printStackTrace(); 642 exit(1); 643 } 644 } 645 } 646