xref: /illumos-gate/usr/src/cmd/dtrace/test/tst/common/java_api/src/TestBean.java (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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
84     exit(int status)
85     {
86 	System.out.flush();
87 	System.err.flush();
88 	System.exit(status);
89     }
90 
91     public static XMLEncoder
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
107     getXMLDecoder(File file)
108     {
109         return getXMLDecoder(file, null);
110     }
111 
112     public static XMLDecoder
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
128     getExitRecord()
129     {
130 	ExitRecord r = new ExitRecord(1);
131 	return r;
132     }
133 
134     public static AggregationRecord
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
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
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
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
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
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
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
268     getOption()
269     {
270 	Option option = new Option("aggrate", "1s");
271 	return option;
272     }
273 
274     public static ProcessState
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
284     getProbeDescription()
285     {
286 	ProbeDescription d = new ProbeDescription(256, "syscall", null,
287 	    "malloc", "entry");
288 	return d;
289     }
290 
291     public static PrintaRecord
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
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
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
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
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
381     getAvgValue()
382     {
383 	AvgValue v = new AvgValue(5, 20, 4);
384 	return v;
385     }
386 
387     public static CountValue
388     getCountValue()
389     {
390 	CountValue v = new CountValue(9);
391 	return v;
392     }
393 
394     public static MinValue
395     getMinValue()
396     {
397 	MinValue v = new MinValue(101);
398 	return v;
399     }
400 
401     public static MaxValue
402     getMaxValue()
403     {
404 	MaxValue v = new MaxValue(101);
405 	return v;
406     }
407 
408     public static SumValue
409     getSumValue()
410     {
411 	SumValue v = new SumValue(25);
412 	return v;
413     }
414 
415     public static org.opensolaris.os.dtrace.Error
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
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
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
446     getProgramInfo()
447     {
448 	ProgramInfo info = new ProgramInfo(getInterfaceAttributes(),
449 		getInterfaceAttributes(), 256);
450 	return info;
451     }
452 
453     public static ProbeInfo
454     getProbeInfo()
455     {
456 	ProbeInfo info = new ProbeInfo(getInterfaceAttributes(),
457 		getInterfaceAttributes());
458 	return info;
459     }
460 
461     public static Probe
462     getProbe()
463     {
464 	Probe p = new Probe(getProbeDescription(), getProbeInfo());
465 	return p;
466     }
467 
468     public static Flow
469     getFlow()
470     {
471 	Flow f = new Flow(Flow.Kind.RETURN.name(), 3);
472 	return f;
473     }
474 
475     public static KernelSymbolRecord
476     getKernelSymbolRecord()
477     {
478 	KernelSymbolRecord r = new KernelSymbolRecord("mod`func+0x4", -1L);
479 	return r;
480     }
481 
482     public static UserSymbolRecord
483     getUserSymbolRecord()
484     {
485 	UserSymbolRecord r = new UserSymbolRecord(7, "mod`func+0x4", -1L);
486 	return r;
487     }
488 
489     public static UserSymbolRecord.Value
490     getUserSymbolRecord$Value()
491     {
492 	UserSymbolRecord.Value v = new UserSymbolRecord.Value(7, -1L);
493 	return v;
494     }
495 
496     public static Program
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
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
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
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
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
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
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
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