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 2008 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 "Program", 77 "Program$File", 78 "StddevValue" 79 }; 80 81 static File file; 82 83 static void exit(int status)84 exit(int status) 85 { 86 System.out.flush(); 87 System.err.flush(); 88 System.exit(status); 89 } 90 91 public static XMLEncoder getXMLEncoder(File file)92 getXMLEncoder(File file) 93 { 94 XMLEncoder encoder = null; 95 try { 96 OutputStream out = new BufferedOutputStream 97 (new FileOutputStream(file)); 98 encoder = new XMLEncoder(out); 99 } catch (Exception e) { 100 e.printStackTrace(); 101 exit(1); 102 } 103 return encoder; 104 } 105 106 public static XMLDecoder getXMLDecoder(File file)107 getXMLDecoder(File file) 108 { 109 return getXMLDecoder(file, null); 110 } 111 112 public static XMLDecoder getXMLDecoder(File file, ExceptionListener exceptionListener)113 getXMLDecoder(File file, ExceptionListener exceptionListener) 114 { 115 XMLDecoder decoder = null; 116 try { 117 InputStream in = new BufferedInputStream 118 (new FileInputStream(file)); 119 decoder = new XMLDecoder(in, null, exceptionListener); 120 } catch (Exception e) { 121 e.printStackTrace(); 122 exit(1); 123 } 124 return decoder; 125 } 126 127 public static ExitRecord getExitRecord()128 getExitRecord() 129 { 130 ExitRecord r = new ExitRecord(1); 131 return r; 132 } 133 134 public static AggregationRecord getAggregationRecord()135 getAggregationRecord() 136 { 137 Tuple tuple = getTuple(); 138 AggregationValue value = new CountValue(7); 139 AggregationRecord r = new AggregationRecord(tuple, value); 140 return r; 141 } 142 143 public static Aggregation getAggregation()144 getAggregation() 145 { 146 List < AggregationRecord > list = 147 new ArrayList < AggregationRecord > (); 148 AggregationRecord r; 149 r = getAggregationRecord(); 150 list.add(r); 151 152 ValueRecord v1 = new ScalarRecord(new byte[] {(byte)1, (byte)2, 153 (byte)3}, 3); 154 ValueRecord v2 = new ScalarRecord("shebang!", 256); 155 Tuple tuple = new Tuple(v1, v2); 156 AggregationValue value = getLinearDistribution(); 157 r = new AggregationRecord(tuple, value); 158 list.add(r); 159 160 Aggregation a = new Aggregation("counts", 2, list); 161 return a; 162 } 163 164 public static Tuple getTuple()165 getTuple() 166 { 167 ValueRecord r1 = new ScalarRecord("cat", 256); 168 ValueRecord r2 = new ScalarRecord(new Integer(9), 2); 169 ValueRecord r3 = new KernelStackRecord( 170 new StackFrame[] { 171 new StackFrame("has"), 172 new StackFrame("nine"), 173 new StackFrame("lives")}, 174 new byte[] { (byte)0, (byte)1, (byte)2 }); 175 ValueRecord r4 = new ScalarRecord(new byte[] {(byte)1, (byte)2, 176 (byte)3}, 3); 177 178 Tuple tuple = new Tuple(r1, r2, r3, r4); 179 return tuple; 180 } 181 182 public static ScalarRecord getScalarRecord()183 getScalarRecord() 184 { 185 Object v = new byte[] {(byte)1, (byte)2, (byte)3}; 186 ScalarRecord r = new ScalarRecord(v, 3); 187 return r; 188 } 189 190 public static KernelStackRecord getKernelStackRecord()191 getKernelStackRecord() 192 { 193 StackFrame[] stackFrames = new StackFrame[] { 194 new StackFrame("Frame 1"), 195 new StackFrame("Frame 2"), 196 new StackFrame("Frame 3") 197 }; 198 KernelStackRecord r = new KernelStackRecord(stackFrames, 199 new byte[] { (byte)0, (byte)1, (byte)2 }); 200 return r; 201 } 202 203 public static LogDistribution getLogDistribution()204 getLogDistribution() 205 { 206 List < Distribution.Bucket > buckets = 207 new ArrayList < Distribution.Bucket > (); 208 Distribution.Bucket bucket; 209 int n = 0; 210 long base = 0; 211 long i; 212 long sign; 213 long nextSign; 214 long power; 215 long nextPower; 216 long lowerBound; 217 long upperBound; 218 for (i = -62; i <= 62; ++i) { 219 if (i == 0) { 220 bucket = new Distribution.Bucket(-1, -1, n++); 221 buckets.add(bucket); 222 bucket = new Distribution.Bucket(0, 0, n++); 223 buckets.add(bucket); 224 bucket = new Distribution.Bucket(1, 1, n++); 225 buckets.add(bucket); 226 continue; 227 } 228 sign = ((i < 0) ? -1L : 1L); 229 power = (sign * i); 230 nextSign = (((i + 1) < 0) ? -1L : 1L); 231 nextPower = (nextSign * (i + 1)); 232 lowerBound = sign * ((long) Math.pow(2L, power)); 233 upperBound = (nextPower == 0 ? -2L : 234 (nextSign * ((long) Math.pow(2L, nextPower))) - 1); 235 if ((upperBound > 0) && ((upperBound * 2L) < 0)) { 236 upperBound = Long.MAX_VALUE; 237 } 238 bucket = new Distribution.Bucket(lowerBound, upperBound, n++); 239 buckets.add(bucket); 240 } 241 LogDistribution d = new LogDistribution(buckets); 242 return d; 243 } 244 245 public static LinearDistribution getLinearDistribution()246 getLinearDistribution() 247 { 248 List < Distribution.Bucket > buckets = 249 new ArrayList < Distribution.Bucket > (); 250 Distribution.Bucket bucket; 251 int n = 10; // number of buckets 252 int base = 1; 253 int step = 10; 254 bucket = new Distribution.Bucket(Long.MIN_VALUE, (base - 1), 0); 255 buckets.add(bucket); 256 for (int i = base; i < (n * step); i += step) { 257 bucket = new Distribution.Bucket(i, (i + (step - 1)), 258 ((i - 1) / step)); 259 buckets.add(bucket); 260 } 261 bucket = new Distribution.Bucket((n * step) + 1, Long.MAX_VALUE, 0); 262 buckets.add(bucket); 263 LinearDistribution d = new LinearDistribution(base, step, buckets); 264 return d; 265 } 266 267 public static Option getOption()268 getOption() 269 { 270 Option option = new Option("aggrate", "1s"); 271 return option; 272 } 273 274 public static ProcessState getProcessState()275 getProcessState() 276 { 277 ProcessState p = new ProcessState(123456, "UNDEAD", 278 3, "SIGSTOP", 279 -2, "Process stopped on dime"); 280 return p; 281 } 282 283 public static ProbeDescription getProbeDescription()284 getProbeDescription() 285 { 286 ProbeDescription d = new ProbeDescription(256, "syscall", null, 287 "malloc", "entry"); 288 return d; 289 } 290 291 public static PrintaRecord getPrintaRecord()292 getPrintaRecord() 293 { 294 List < Aggregation > aggregations = new ArrayList < Aggregation > (); 295 Aggregation a = getAggregation(); 296 aggregations.add(a); 297 aggregations.add(a); 298 Map < Tuple, String > formattedOutput = 299 new HashMap < Tuple, String > (); 300 for (Tuple t : a.asMap().keySet()) { 301 formattedOutput.put(t, "cat"); 302 } 303 List < Tuple > tuples = new ArrayList < Tuple > (); 304 for (Tuple t : a.asMap().keySet()) { 305 tuples.add(t); 306 } 307 Collections.sort(tuples); 308 PrintaRecord r = new PrintaRecord(1234567890L, 309 aggregations, formattedOutput, tuples, 310 "Yes, this is the formatted printa() output"); 311 return r; 312 } 313 314 public static PrintfRecord getPrintfRecord()315 getPrintfRecord() 316 { 317 List < ValueRecord > list = new ArrayList < ValueRecord > (); 318 ValueRecord v1 = getScalarRecord(); 319 ValueRecord v2 = new ScalarRecord(new Integer(7), 4); 320 list.add(v1); 321 list.add(v2); 322 PrintfRecord r = new PrintfRecord(list, 323 "long formatted string"); 324 return r; 325 } 326 327 public static ProbeData getProbeData()328 getProbeData() 329 { 330 List < Record > list = new ArrayList < Record > (); 331 list.add(getPrintaRecord()); 332 list.add(getPrintfRecord()); 333 list.add(getScalarRecord()); 334 list.add(getUserSymbolRecord()); 335 list.add(getUserStackRecord()); 336 list.add(getExitRecord()); 337 ProbeData d = new ProbeData(7, 1, getProbeDescription(), 338 getFlow(), list); 339 return d; 340 } 341 342 public static Aggregate getAggregate()343 getAggregate() 344 { 345 List < Aggregation > list = new ArrayList < Aggregation > (); 346 list.add(getAggregation()); 347 348 List < AggregationRecord > reclist = 349 new ArrayList < AggregationRecord > (); 350 AggregationRecord r; 351 ValueRecord v1 = new ScalarRecord("cat", 256); 352 ValueRecord v2 = new ScalarRecord("dog", 256); 353 ValueRecord v3 = new ScalarRecord("mouse", 256); 354 ValueRecord v4 = new ScalarRecord("mouse", 256); 355 ValueRecord v5 = new ScalarRecord(new Byte((byte) 'C'), 1); 356 ValueRecord v6 = new ScalarRecord(new Short((short) 7), 2); 357 Tuple tuple = new Tuple(v1, v2, v3, v4, v5, v6); 358 AggregationValue value = getCountValue(); 359 r = new AggregationRecord(tuple, value); 360 reclist.add(r); 361 list.add(new Aggregation("times", 1, reclist)); 362 363 Aggregate a = new Aggregate(1234567890L, list); 364 return a; 365 } 366 367 public static UserStackRecord getUserStackRecord()368 getUserStackRecord() 369 { 370 StackFrame[] frames = new StackFrame[] { 371 new StackFrame("User Stack Frame 1"), 372 new StackFrame("User Stack Frame 2"), 373 new StackFrame("User Stack Frame 3") 374 }; 375 UserStackRecord r = new UserStackRecord(123456, frames, 376 new byte[] { (byte)0, (byte)1, (byte)2 }); 377 return r; 378 } 379 380 public static AvgValue getAvgValue()381 getAvgValue() 382 { 383 AvgValue v = new AvgValue(5, 20, 4); 384 return v; 385 } 386 387 public static CountValue getCountValue()388 getCountValue() 389 { 390 CountValue v = new CountValue(9); 391 return v; 392 } 393 394 public static MinValue getMinValue()395 getMinValue() 396 { 397 MinValue v = new MinValue(101); 398 return v; 399 } 400 401 public static MaxValue getMaxValue()402 getMaxValue() 403 { 404 MaxValue v = new MaxValue(101); 405 return v; 406 } 407 408 public static SumValue getSumValue()409 getSumValue() 410 { 411 SumValue v = new SumValue(25); 412 return v; 413 } 414 415 public static org.opensolaris.os.dtrace.Error getError()416 getError() 417 { 418 ProbeDescription probe = getProbeDescription(); 419 org.opensolaris.os.dtrace.Error e = 420 new org.opensolaris.os.dtrace.Error(probe, 8, 3, 421 1, 20, "DTRACEFLT_BADALIGN", -1, "error on enabled probe ID 8 " + 422 "(ID " + probe.getID() + ": " + probe + "): Bad alignment " + 423 "(0x33ef) in action #1 at DIF offset 20"); 424 return e; 425 } 426 427 public static Drop getDrop()428 getDrop() 429 { 430 Drop drop = new Drop(2, "SPECBUSY", 72, 1041, 431 "Guess we dropped stuff all over the place."); 432 return drop; 433 } 434 435 public static InterfaceAttributes getInterfaceAttributes()436 getInterfaceAttributes() 437 { 438 InterfaceAttributes a = new InterfaceAttributes( 439 InterfaceAttributes.Stability.UNSTABLE, 440 InterfaceAttributes.Stability.EVOLVING, 441 InterfaceAttributes.DependencyClass.ISA); 442 return a; 443 } 444 445 public static ProgramInfo getProgramInfo()446 getProgramInfo() 447 { 448 ProgramInfo info = new ProgramInfo(getInterfaceAttributes(), 449 getInterfaceAttributes(), 256); 450 return info; 451 } 452 453 public static ProbeInfo getProbeInfo()454 getProbeInfo() 455 { 456 ProbeInfo info = new ProbeInfo(getInterfaceAttributes(), 457 getInterfaceAttributes()); 458 return info; 459 } 460 461 public static Probe getProbe()462 getProbe() 463 { 464 Probe p = new Probe(getProbeDescription(), getProbeInfo()); 465 return p; 466 } 467 468 public static Flow getFlow()469 getFlow() 470 { 471 Flow f = new Flow(Flow.Kind.RETURN.name(), 3); 472 return f; 473 } 474 475 public static KernelSymbolRecord getKernelSymbolRecord()476 getKernelSymbolRecord() 477 { 478 KernelSymbolRecord r = new KernelSymbolRecord("mod`func+0x4", -1L); 479 return r; 480 } 481 482 public static UserSymbolRecord getUserSymbolRecord()483 getUserSymbolRecord() 484 { 485 UserSymbolRecord r = new UserSymbolRecord(7, "mod`func+0x4", -1L); 486 return r; 487 } 488 489 public static UserSymbolRecord.Value getUserSymbolRecord$Value()490 getUserSymbolRecord$Value() 491 { 492 UserSymbolRecord.Value v = new UserSymbolRecord.Value(7, -1L); 493 return v; 494 } 495 496 public static Program getProgram()497 getProgram() 498 { 499 final String PROGRAM = "syscall:::entry { @[execname] = count(); }"; 500 Consumer consumer = new LocalConsumer(); 501 Program p; 502 try { 503 consumer.open(); 504 p = consumer.compile(PROGRAM); 505 consumer.close(); 506 } catch (DTraceException e) { 507 e.printStackTrace(); 508 p = null; 509 } 510 return p; 511 } 512 513 public static Program.File getProgram$File()514 getProgram$File() 515 { 516 final String PROGRAM = "syscall:::entry { @[execname] = count(); }"; 517 Consumer consumer = new LocalConsumer(); 518 Program p; 519 try { 520 OutputStream out = new FileOutputStream(file); 521 out.write(PROGRAM.getBytes(), 0, PROGRAM.length()); 522 out.flush(); 523 out.close(); 524 consumer.open(); 525 p = consumer.compile(file); 526 consumer.close(); 527 } catch (Exception e) { 528 e.printStackTrace(); 529 p = null; 530 } 531 return Program.File.class.cast(p); 532 } 533 534 public static StddevValue getStddevValue()535 getStddevValue() 536 { 537 StddevValue v = new StddevValue(37, 114, 5, Integer.toString(9544)); 538 return v; 539 } 540 541 @SuppressWarnings("unchecked") 542 static String getString(Object o)543 getString(Object o) 544 { 545 String s; 546 if (o instanceof ScalarRecord) { 547 o = ((ScalarRecord)o).getValue(); 548 } 549 550 if (o instanceof byte[]) { 551 s = Arrays.toString((byte[])o); 552 } else if (o instanceof Object[]) { 553 s = Arrays.toString((Object[])o); 554 } else { 555 Class c = o.getClass(); 556 try { 557 Method m = c.getDeclaredMethod("toLogString"); 558 s = (String)m.invoke(o); 559 } catch (Exception e) { 560 s = o.toString(); 561 } 562 } 563 return s; 564 } 565 566 static void checkEquality(Object obj, Object newobj)567 checkEquality(Object obj, Object newobj) 568 { 569 // If the class overrides equals(), make sure the re-created 570 // object still equals the original object 571 try { 572 Method eq = obj.getClass().getDeclaredMethod("equals", 573 Object.class); 574 Boolean ret = (Boolean) eq.invoke(obj, newobj); 575 if (ret != true) { 576 System.err.println("serialization failed: " + 577 obj.getClass().getName()); 578 exit(1); 579 } 580 } catch (Exception e) { 581 // Does not override equals(), although a super-class might. 582 // A better test would check for any superclass other than 583 // Object.class. 584 } 585 } 586 587 static void performSerializationTest(File file, String classname)588 performSerializationTest(File file, String classname) 589 throws IOException, ClassNotFoundException 590 { 591 String methodName = "get" + classname; 592 Object obj = null; 593 Object newobj = null; 594 try { 595 Method method = TestBean.class.getDeclaredMethod(methodName); 596 obj = method.invoke(null); 597 } catch (Exception e) { 598 e.printStackTrace(); 599 exit(1); 600 } 601 602 System.out.println(classname + ":"); 603 String serialized = getString(obj); 604 System.out.println(" serialized: " + serialized); 605 FileOutputStream fos = new FileOutputStream(file); 606 ObjectOutputStream out = new ObjectOutputStream(fos); 607 out.writeObject(obj); 608 out.close(); 609 FileInputStream fis = new FileInputStream(file); 610 ObjectInputStream in = new ObjectInputStream(fis); 611 newobj = in.readObject(); 612 in.close(); 613 String deserialized = getString(newobj); 614 System.out.println(" deserialized: " + deserialized); 615 616 if (!serialized.equals(deserialized)) { 617 System.err.println("serialization failed: " + classname); 618 exit(1); 619 } 620 checkEquality(obj, newobj); 621 } 622 623 static void performBeanTest(File file, String classname)624 performBeanTest(File file, String classname) 625 { 626 String methodName = "get" + classname; 627 Object obj = null; 628 Object newobj = null; 629 try { 630 Method method = TestBean.class.getDeclaredMethod(methodName); 631 obj = method.invoke(null); 632 } catch (Exception e) { 633 e.printStackTrace(); 634 exit(1); 635 } 636 637 Class c = obj.getClass(); 638 if (c.getConstructors().length == 0) { 639 return; 640 } 641 642 System.out.println(classname + ":"); 643 XMLEncoder encoder = getXMLEncoder(file); 644 String encoded = getString(obj); 645 System.out.println(" encoded: " + encoded); 646 encoder.writeObject(obj); 647 encoder.close(); 648 XMLDecoder decoder = getXMLDecoder(file); 649 newobj = decoder.readObject(); 650 String decoded = getString(newobj); 651 System.out.println(" decoded: " + decoded); 652 decoder.close(); 653 654 if (!encoded.equals(decoded)) { 655 System.err.println("bean persistence failed: " + classname); 656 exit(1); 657 } 658 checkEquality(obj, newobj); 659 } 660 661 public static void main(String[] args)662 main(String[] args) 663 { 664 if ((args.length != 1) && (args.length != 2)) { 665 System.err.println("usage: java TestBean < filename > " + 666 "[ < classname > ]"); 667 exit(1); 668 } 669 670 String filename = args[0]; 671 String classname = null; 672 if (args.length >= 2) { 673 classname = args[1]; 674 } 675 676 file = new File(filename); 677 try { 678 if (!file.canRead()) { 679 try { 680 file.createNewFile(); 681 } catch (Exception e) { 682 System.err.println("failed to create " + filename); 683 exit(1); 684 } 685 } 686 } catch (SecurityException e) { 687 System.err.println("failed to open " + filename); 688 exit(1); 689 } 690 691 String[] tests = (classname == null ? TESTS: 692 new String[] { classname }); 693 try { 694 for (int i = 0; i < tests.length; ++i) { 695 performSerializationTest(file, tests[i]); 696 performBeanTest(file, tests[i]); 697 } 698 } catch (IOException e) { 699 e.printStackTrace(); 700 exit(1); 701 } catch (ClassNotFoundException e) { 702 e.printStackTrace(); 703 exit(1); 704 } 705 } 706 } 707