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