xref: /illumos-gate/usr/src/cmd/dtrace/test/tst/common/java_api/src/TestBean.java (revision 60a3f738d56f92ae8b80e4b62a2331c6e1f2311f)
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