diff options
author | wisberg <wisberg> | 2003-08-06 02:08:40 +0000 |
---|---|---|
committer | wisberg <wisberg> | 2003-08-06 02:08:40 +0000 |
commit | a63bc04fb1cb6e8d6d0bc2a509ab9658e3d78c43 (patch) | |
tree | cd4e827c60136df7bf9850591b0c64baff549d20 /docs/sandbox/inoculated/src | |
parent | b0d37c4b51a344bee94bb7f7cc1ecef1a233e3ab (diff) | |
download | aspectj-a63bc04fb1cb6e8d6d0bc2a509ab9658e3d78c43.tar.gz aspectj-a63bc04fb1cb6e8d6d0bc2a509ab9658e3d78c43.zip |
initial checkin of the sandbox.
The basic structure and examples of each type are there,
but I have more examples and the ones there are not
altogether validated. I'll make a few more changes
before emailing dev and users about usage, etc.
Diffstat (limited to 'docs/sandbox/inoculated/src')
-rw-r--r-- | docs/sandbox/inoculated/src/BufferTest.java | 61 | ||||
-rw-r--r-- | docs/sandbox/inoculated/src/Injection.java | 123 | ||||
-rw-r--r-- | docs/sandbox/inoculated/src/MainFailure.java | 74 | ||||
-rw-r--r-- | docs/sandbox/inoculated/src/RunTime.java | 72 | ||||
-rw-r--r-- | docs/sandbox/inoculated/src/RuntimeWrites.java | 145 | ||||
-rw-r--r-- | docs/sandbox/inoculated/src/StubReplace.java | 64 | ||||
-rw-r--r-- | docs/sandbox/inoculated/src/buildRun.sh | 20 | ||||
-rw-r--r-- | docs/sandbox/inoculated/src/com/xerox/printing/CompileTime.java | 69 | ||||
-rw-r--r-- | docs/sandbox/inoculated/src/com/xerox/printing/RecordingInput.java | 44 | ||||
-rw-r--r-- | docs/sandbox/inoculated/src/com/xerox/printing/RoundTrip.java | 77 |
10 files changed, 749 insertions, 0 deletions
diff --git a/docs/sandbox/inoculated/src/BufferTest.java b/docs/sandbox/inoculated/src/BufferTest.java new file mode 100644 index 000000000..f2cc479e8 --- /dev/null +++ b/docs/sandbox/inoculated/src/BufferTest.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1998-2002 PARC Inc. All rights reserved. + * + * Use and copying of this software and preparation of derivative works based + * upon this software are permitted. Any distribution of this software or + * derivative works must comply with all applicable United States export + * control laws. + * + * This software is made available AS IS, and PARC Inc. makes no + * warranty about the software, its performance or its conformity to any + * specification. + */ + +import java.util.*; +import java.io.*; + +import org.aspectj.lang.*; + +/** @author Wes Isberg */ +public aspect BufferTest { + + // article page 43 - input driver + // START-SAMPLE testing-inoculated-proceedVariants Using around for integration testing + /** + * When PrinterBuffer.capacity(int) is called, + * test it with repeatedly with a set of input + * (validating the result) and then continue with + * the original call. + * + * This assumes that the capacity method causes no + * relevant state changes in the buffer. + */ + int around(int original, PrinterBuffer buffer) : + call(int PrinterBuffer.capacity(int)) && args(original) && target(buffer) { + int[] input = new int[] { 0, 1, 10, 1000, -1, 4096 }; + for (int i = 0; i < input.length; i++) { + int result = proceed(input[i], buffer); // invoke test + validateResult(buffer, input[i], result); + } + return proceed(original, buffer); // continue with original processing + } + // END-SAMPLE testing-inoculated-proceedVariants + + void validateResult(PrinterBuffer buffer, int input, int result) { + System.err.println("validating input=" + input + " result=" + result + + " buffer=" + buffer); + } + + public static void main(String[] args) { + PrinterBuffer p = new PrinterBuffer(); + int i = p.capacity(0); + System.err.println("main - result " + i); + } +} + +class PrinterBuffer { + int capacity(int i) { + System.err.println("capacity " + i); + return i; + } +} diff --git a/docs/sandbox/inoculated/src/Injection.java b/docs/sandbox/inoculated/src/Injection.java new file mode 100644 index 000000000..6a857ef7a --- /dev/null +++ b/docs/sandbox/inoculated/src/Injection.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 1998-2002 PARC Inc. All rights reserved. + * + * Use and copying of this software and preparation of derivative works based + * upon this software are permitted. Any distribution of this software or + * derivative works must comply with all applicable United States export + * control laws. + * + * This software is made available AS IS, and PARC Inc. makes no + * warranty about the software, its performance or its conformity to any + * specification. + */ + +import java.io.*; + +/** + * Demonstrate technique of fault-injection + * as coordinated by test driver. + * @author Wes Isberg + */ +aspect InjectingIOException { + + // article page 43 - fault injection + // START-SAMPLE testing-inoculated-injectIOException Inject IOException on test driver command + /** the test starts when the driver starts executing */ + pointcut testEntryPoint(TestDriver driver) : + target(driver) && execution(* TestDriver.startTest()); + + /** + * The fault may be injected at the execution of any + * (non-static) PrinterStream method that throws an IOException + */ + pointcut testCheckPoint(PrinterStream stream) : target(stream) + && execution(public * PrinterStream+.*(..) throws IOException); + + /** + * After the method returns normally, query the + * test driver to see if we should instead throw + * an exception ("inject" the fault). + */ + after (TestDriver driver, PrinterStream stream) returning + throws IOException : + cflowbelow(testEntryPoint(driver)) + && testCheckPoint(stream) { + IOException e = driver.createException(stream); + if (null != e) { + System.out.println("InjectingIOException - injecting " + e); + throw e; + } + } + /* Comment on the after advice IOException declaration: + + "throws IOException" is a declaration of the advice, + not the pointcut. + + Since the advice might throw the injected fault, it + must declare that it throws IOException. When advice declares + exceptions thrown, the compiler will emit an error if any + join point is not also declared to throw an IOException. + + In this case, the testCheckPoint pointcut only picks out + methods that throw IOException, so the compile will not + signal any errors. + */ + // END-SAMPLE testing-inoculated-injectIOException +} + +/** this runs the test case */ +public class Injection { + /** Run three print jobs, two as a test and one normally */ + public static void main(String[] args) throws Exception { + Runnable r = new Runnable() { + public void run() { + try { new TestDriver().startTest(); } + catch (IOException e) { + System.err.println("got expected injected error " + e.getMessage()); + } + } + }; + + System.out.println("Injection.main() - starting separate test thread"); + Thread t = new Thread(r); + t.start(); + + System.out.println("Injection.main() - running test in this thread"); + r.run(); + t.join(); + + System.out.println("Injection.main() - running job normally, not by TestDriver"); + new PrintJob().runPrintJob(); + } +} + +/** handle starting of test and determining whether to inject failure */ +class TestDriver { + + /** start a new test */ + public void startTest() throws IOException { + new PrintJob().runPrintJob(); + } + + /** this implementation always injects a failure */ + public IOException createException(PrinterStream p) { + return new IOException(""+p); + } +} + +//--------------------------------------- target classes + +class PrintJob { + /** this job writes to the printer stream */ + void runPrintJob() throws IOException { + new PrinterStream().write(); + } +} + +class PrinterStream { + /** this printer stream writes without exception */ + public void write() throws IOException { + System.err.println("PrinterStream.write() - not throwing exception"); + } +} + diff --git a/docs/sandbox/inoculated/src/MainFailure.java b/docs/sandbox/inoculated/src/MainFailure.java new file mode 100644 index 000000000..6d5a62a35 --- /dev/null +++ b/docs/sandbox/inoculated/src/MainFailure.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 1998-2002 PARC Inc. All rights reserved. + * + * Use and copying of this software and preparation of derivative works based + * upon this software are permitted. Any distribution of this software or + * derivative works must comply with all applicable United States export + * control laws. + * + * This software is made available AS IS, and PARC Inc. makes no + * warranty about the software, its performance or its conformity to any + * specification. + */ + +import java.util.*; +import java.io.*; +import org.aspectj.lang.*; + +/** @author Wes Isberg */ + +public aspect MainFailure { + + public static void main (String[] args) { TargetClass.main(args); } + + pointcut main(String[] args) : + args(args) && execution(public static void main(String[])); + + // article page 42 - recording failures from main + // START-SAMPLE testing-inoculated-failureCapture Log failures + /** log after failure, but do not affect exception */ + after(String[] args) throwing (Throwable t) : main(args) { + logFailureCase(args, t, thisJoinPoint); + } + // END-SAMPLE testing-inoculated-failureCapture + + // alternate to swallow exception +// /** log after failure and swallow exception */ +// Object around() : main(String[]) { +// try { +// return proceed(); +// } catch (Error e) { // ignore +// logFailureCase(args, t, thisJoinPoint); +// // can log here instead +// } +// return null; +// } + + public static void logFailureCase(String[] args, Throwable t, Object jp) { + System.err.println("failure case: args " + Arrays.asList(args)); + } +} + +class TargetClass { + static Thread thread; + /** will throw error if exactly one argument */ + public static void main (String[] args) { + // make sure to do at least one failure + if (thread == null) { + Runnable r = new Runnable() { + public void run() { + main(new String[] {"throwError" }); + } + }; + thread = new Thread(r); + thread.start(); + } + if (1 == args.length) { + throw new Error("hello"); + } + try { thread.join(); } + catch (InterruptedException ie) { } + } +} + + diff --git a/docs/sandbox/inoculated/src/RunTime.java b/docs/sandbox/inoculated/src/RunTime.java new file mode 100644 index 000000000..e3e93e9d0 --- /dev/null +++ b/docs/sandbox/inoculated/src/RunTime.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1998-2002 PARC Inc. All rights reserved. + * + * Use and copying of this software and preparation of derivative works based + * upon this software are permitted. Any distribution of this software or + * derivative works must comply with all applicable United States export + * control laws. + * + * This software is made available AS IS, and PARC Inc. makes no + * warranty about the software, its performance or its conformity to any + * specification. + */ + +import java.util.*; +import java.awt.Point; + +import org.aspectj.lang.JoinPoint; + +public class RunTime { + public static void main(String[] a) { + AnotherPoint.create(); + SubPoint.create(); + } +} + +/** @author Wes Isberg */ +aspect FactoryValidation { + + // START-SAMPLE declares-inoculated-prohibitNonprivateConstructors Error to have accessible sub-Point constructors + /** We make it an error for any Point subclasses to have non-private constructors */ + declare error : execution(!private Point+.new(..)) + && !within(java*..*) : + "non-private Point subclass constructor"; + // END-SAMPLE declares-inoculated-prohibitNonprivateConstructors + + // article page 41 - runtime NPE + // START-SAMPLE testing-inoculated-runtimeErrorWhenNullReturnedFromFactory Throw Error when factory returns null + /** Throw Error if a factory method for creating a Point returns null */ + after () returning (Point p) : + call(Point+ SubPoint+.create(..)) { + if (null == p) { + String err = "Null Point constructed when this (" + + thisJoinPoint.getThis() + + ") called target (" + + thisJoinPoint.getTarget() + + ") at join point (" + + thisJoinPoint.getSignature() + + ") from source location (" + + thisJoinPoint.getSourceLocation() + + ") with args (" + + Arrays.asList(thisJoinPoint.getArgs()) + + ")"; + throw new Error(err); + } + } + // END-SAMPLE testing-inoculated-runtimeErrorWhenNullReturnedFromFactory +} + +class SubPoint extends Point { + public static SubPoint create() { return null; } // will cause Error + private SubPoint(){} +} + +class AnotherPoint extends Point { + public static Point create() { return new Point(); } + + // to see that default constructor is picked out by declare error + // comment out this constructor + private AnotherPoint(){} +} + + diff --git a/docs/sandbox/inoculated/src/RuntimeWrites.java b/docs/sandbox/inoculated/src/RuntimeWrites.java new file mode 100644 index 000000000..0f49247cb --- /dev/null +++ b/docs/sandbox/inoculated/src/RuntimeWrites.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 1998-2002 PARC Inc. All rights reserved. + * + * Use and copying of this software and preparation of derivative works based + * upon this software are permitted. Any distribution of this software or + * derivative works must comply with all applicable United States export + * control laws. + * + * This software is made available AS IS, and PARC Inc. makes no + * warranty about the software, its performance or its conformity to any + * specification. + */ + +import org.aspectj.lang.*; + +/** test cases for controlling field writes */ +public class RuntimeWrites { + + public static void main(String[] args) { + System.err.println("---- setup: valid write"); + final SubPrinterStream me = new SubPrinterStream(); + + System.err.println("---- setup: invalid write, outside initialization - nonstatic"); + me.setOne(1); + + System.err.println("---- setup: invalid write, outside initialization - static"); + me.one = 0; + + System.err.println("---- setup: invalid write, caller is not same as target"); + PrinterStream other = new PrinterStream(me); + } +} + + +/** + * Control field writes. + * This implementation restricts writes to the same object during initialization. + * This is like having field values be final, except that + * they may be set set outside the constructor. + * @author Wes Isberg + */ +aspect ControlFieldWrites { + public static boolean throwError; + + // article page 42 - field writes + + // START-SAMPLE testing-inoculated-permitWritesDuringConstruction Constructor execution + /** execution of any constructor for PrinterStream */ + pointcut init() : execution(PrinterStream+.new(..)); + // END-SAMPLE testing-inoculated-permitWritesDuringConstruction + + // START-SAMPLE testing-inoculated-prohibitWritesExceptWhenConstructing Prohibit field writes after construction + /** any write to a non-static field in PrinterStream itself */ + pointcut fieldWrites() : set(!static * PrinterStream.*); + + + /** + * Handle any situation where fields are written + * outside of the control flow of initialization + */ + before() : fieldWrites() && !cflow(init()) { + handle("field set outside of init", thisJoinPointStaticPart); + } + // END-SAMPLE testing-inoculated-prohibitWritesExceptWhenConstructing + + // START-SAMPLE testing-inoculated-prohibitWritesByOthers Prohibit field writes by other instances + /** + * Handle any situation where fields are written + * by another object. + */ + before(Object caller, PrinterStream targ) : this(caller) + && target(targ) && fieldWrites() { + if (caller != targ) { + String err = "variation 1: caller (" + caller + + ") setting fields in targ (" + targ + ")"; + handle(err, thisJoinPointStaticPart); + } + } + // END-SAMPLE testing-inoculated-prohibitWritesByOthers + + //---- variations to pick out subclasses as well + // START-SAMPLE testing-inoculated-prohibitWritesEvenBySubclasses Prohibit writes by subclasses + /** any write to a non-static field in PrinterStream or any subclasses */ + //pointcut fieldWrites() : set(!static * PrinterStream+.*); + + /** execution of any constructor for PrinterStream or any subclasses */ + //pointcut init() : execution(PrinterStream+.new(..)); + // END-SAMPLE testing-inoculated-prohibitWritesEvenBySubclasses + + //---- variation to pick out static callers as well + // START-SAMPLE testing-inoculated-prohibitWritesEvenByStaticOthers Prohibit writes by other instances and static methods + /** + * Handle any situation where fields are written + * other than by the same object. + */ + before(PrinterStream targ) : target(targ) && fieldWrites() { + Object caller = thisJoinPoint.getThis(); + if (targ != caller) { + String err = "variation 2: caller (" + caller + + ") setting fields in targ (" + targ + ")"; + handle(err, thisJoinPointStaticPart); + } + } + // END-SAMPLE testing-inoculated-prohibitWritesEvenByStaticOthers + + //-------------- utility method + void handle(String error, JoinPoint.StaticPart jpsp) { + error += " - " + jpsp; + if (throwError) { + throw new Error(error); + } else { + System.err.println(error); + } + } +} + + +class PrinterStream { + int one; + private int another; + + PrinterStream() { setOne(1); } + + PrinterStream(PrinterStream other) { + other.another = 3; + } + + public void setOne(int i) { + one = i; + } +} + +class SubPrinterStream extends PrinterStream { + private int two; + + SubPrinterStream() { + setOne(2); + setTwo(); + } + + public void setTwo() { + two = 2; + } +} + diff --git a/docs/sandbox/inoculated/src/StubReplace.java b/docs/sandbox/inoculated/src/StubReplace.java new file mode 100644 index 000000000..56bda0367 --- /dev/null +++ b/docs/sandbox/inoculated/src/StubReplace.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 1998-2002 PARC Inc. All rights reserved. + * + * Use and copying of this software and preparation of derivative works based + * upon this software are permitted. Any distribution of this software or + * derivative works must comply with all applicable United States export + * control laws. + * + * This software is made available AS IS, and PARC Inc. makes no + * warranty about the software, its performance or its conformity to any + * specification. + */ + +public class StubReplace { + public static void main(String[] args) { + new PrintJob().run(); + } +} + +/** @author Wes Isberg */ +aspect Stubs { + + // article page 76 - stubs + + // START-SAMPLE testing-inoculated-replaceWithProxy Replace object with proxy on constructiono + /** + * Replace all PrintStream with our StubStream + * by replacing the call to any constructor of + * PrinterStream or any subclasses. + */ + PrinterStream around () : within(PrintJob) + && call (PrinterStream+.new(..)) && !call (StubStream+.new(..)) { + return new StubStream(thisJoinPoint.getArgs()); + } + // END-SAMPLE testing-inoculated-replaceWithProxy + + // START-SAMPLE testing-inoculated-adviseProxyCallsOnly Advise calls to the proxy object only + pointcut stubWrite() : printerStreamTestCalls() && target(StubStream); + + pointcut printerStreamTestCalls() : call(* PrinterStream.write()); + + before() : stubWrite() { + System.err.println("picking out stubWrite" ); + } + // END-SAMPLE testing-inoculated-adviseProxyCallsOnly +} + +class PrinterStream { + public void write() {} +} + +class StubStream extends PrinterStream { + public StubStream(Object[] args) {} +} + +class PrintJob { + public void run() { + PrinterStream p = new PrinterStream(); + System.err.println("not PrinterStream: " + p); + System.err.println("now trying call..."); + p.write(); + } +} + diff --git a/docs/sandbox/inoculated/src/buildRun.sh b/docs/sandbox/inoculated/src/buildRun.sh new file mode 100644 index 000000000..8f3c283c3 --- /dev/null +++ b/docs/sandbox/inoculated/src/buildRun.sh @@ -0,0 +1,20 @@ +#!/bin/sh
+
+JDKDIR="${JDKDIR:-${JAVA_HOME:-`setjdk.sh`}}"
+AJ_HOME="${AJ_HOME:-`setajhome.sh`}"
+PS="${PS:-;}"
+ajrt=`pathtojava.sh "$AJ_HOME/lib/aspectjrt.jar"`
+mkdir -p ../classes
+
+for i in *.java; do
+ pack=`sed -n '/package/s|.*package *\([^ ][^ ]*\)[ ;].*|\1|p' "$i"`
+ [ -n "$pack" ] && pack="${pack}."
+ rm -rf classes/*
+ cname=$pack`basename $i .java`
+ echo ""
+ echo "########## $cname"
+ $AJ_HOME/bin/ajc -d ../classes -classpath "$ajrt" "$i"
+ && $JDKDIR/bin/java -classpath "../classes${PS}$ajrt" $cname
+done
+
+rm -rf ../classes
diff --git a/docs/sandbox/inoculated/src/com/xerox/printing/CompileTime.java b/docs/sandbox/inoculated/src/com/xerox/printing/CompileTime.java new file mode 100644 index 000000000..f7af344e0 --- /dev/null +++ b/docs/sandbox/inoculated/src/com/xerox/printing/CompileTime.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1998-2002 PARC Inc. All rights reserved. + * + * Use and copying of this software and preparation of derivative works based + * upon this software are permitted. Any distribution of this software or + * derivative works must comply with all applicable United States export + * control laws. + * + * This software is made available AS IS, and PARC Inc. makes no + * warranty about the software, its performance or its conformity to any + * specification. + */ + +package com.xerox.printing; + +import java.awt.Point; +import java.io.IOException; + +class ClassOne { + int i = 1 ; // 20 expect warning +} + +class ClassError { + int i = 1 ; // 24 expect warning +} + +class PrinterStream {} + +class SubPrinterStream extends PrinterStream { + public void delegate() { + try { + throw new IOException(""); + } catch (IOException e) {} // 33 expect error + } +} + +class SubPoint extends Point { + Point create() { return new Point(); } // no error + Point another() { return new Point(); } // 39 expect error +} + +/** @author Wes Isberg */ +aspect CompileTime { + + // article page 40 - warning + // START-SAMPLE declares-inoculated-nonSetterWrites Warn when setting non-public field + /** warn if setting non-public field outside a setter */ + declare warning : + within(com.xerox.printing..*) + && set(!public * *) && !withincode(* set*(..)) + : "writing field outside setter" ; + // END-SAMPLE declares-inoculated-nonSetterWrites + + // article page 41 - error + // START-SAMPLE declares-inoculated-validExceptionHandlingMethod Error when subclass method handles exception + declare error : handler(IOException+) + && withincode(* PrinterStream+.delegate(..)) + : "do not handle IOException in this method"; + // END-SAMPLE declares-inoculated-validExceptionHandlingMethod + + // START-SAMPLE declares-inoculated-validPointConstruction Error when factory not used + declare error : !withincode(Point+ SubPoint+.create(..)) + && within(com.xerox..*) + && call(Point+.new(..)) + : "use SubPoint.create() to create Point"; + // END-SAMPLE declares-inoculated-validPointConstruction +} + + diff --git a/docs/sandbox/inoculated/src/com/xerox/printing/RecordingInput.java b/docs/sandbox/inoculated/src/com/xerox/printing/RecordingInput.java new file mode 100644 index 000000000..aab1d2076 --- /dev/null +++ b/docs/sandbox/inoculated/src/com/xerox/printing/RecordingInput.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 1998-2002 PARC Inc. All rights reserved. + * + * Use and copying of this software and preparation of derivative works based + * upon this software are permitted. Any distribution of this software or + * derivative works must comply with all applicable United States export + * control laws. + * + * This software is made available AS IS, and PARC Inc. makes no + * warranty about the software, its performance or its conformity to any + * specification. + */ + +package com.xerox.printing; + +class PrinterBuffer { + public int capacity(int i) { return i; } +} + +public aspect RecordingInput { + + // @author Wes Isberg + // article page 42 - recording input + pointcut capacityCall (int i) : + within(com.xerox..*) && args(i) + && call(public * PrinterBuffer.capacity(int)) ; + // XXX style error - + not needed + // call(public * PrinterBuffer+.capacity(int)) + + before (int i) : capacityCall(i) { + log.print("<capacityCall tjp=\"" + thisJoinPoint + + "\" input=\"" + i + "\"/>"); + } + + Log log = new Log(); + class Log { + void print(String s) { System.out.println(s); } + } + public static void main(String[] args) { + PrinterBuffer p = new PrinterBuffer(); + p.capacity(1); + p.capacity(2); + } +} diff --git a/docs/sandbox/inoculated/src/com/xerox/printing/RoundTrip.java b/docs/sandbox/inoculated/src/com/xerox/printing/RoundTrip.java new file mode 100644 index 000000000..4aeb0892b --- /dev/null +++ b/docs/sandbox/inoculated/src/com/xerox/printing/RoundTrip.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1998-2002 PARC Inc. All rights reserved. + * + * Use and copying of this software and preparation of derivative works based + * upon this software are permitted. Any distribution of this software or + * derivative works must comply with all applicable United States export + * control laws. + * + * This software is made available AS IS, and PARC Inc. makes no + * warranty about the software, its performance or its conformity to any + * specification. + */ + +package com.xerox.printing; + +public class RoundTrip { + public static void main(String[] args) { + PrinterStream p = testing(); + System.err.println(" got "+ p.number); + } + static PrinterStream testing() { return new PrinterStream(1); } + +} + +/** @author Wes Isberg */ +aspect VerifyPrinterStreamIntegrity { + // article page 76 - round trip + // START-SAMPLE testing-inoculated-roundTrip Round-trip integration testing + /** + * After returning a PrinterStream from any call in our + * packages, verify it by doing a round-trip between + * PrinterStream and BufferedPrinterStream. + * This uses a round-trip as a way to verify the + * integrity of PrinterStream, but one could also use + * a self-test (built-in or otherwise) coded specifically + * for validating the object (without changing state). + */ + after () returning (PrinterStream stream) : + call (PrinterStream+ com.xerox.printing..*(..)) + && !call (PrinterStream PrinterStream.make(BufferedPrinterStream)) { + BufferedPrinterStream bufferStream = new BufferedPrinterStream(stream); + PrinterStream newStream = PrinterStream.make(bufferStream); + if (!stream.equals(newStream)) { + throw new Error("round-trip failed for " + stream); + } else { + System.err.println("round-trip passed for " + stream); + } + } + // END-SAMPLE testing-inoculated-roundTrip +} + +class BufferedPrinterStream { + int num; + BufferedPrinterStream(int i) { this.num = i; } + BufferedPrinterStream(PrinterStream p) { this(p.number); } +} + +class PrinterStream { + int number; + static PrinterStream make(BufferedPrinterStream p) { + return new PrinterStream(p.num); + } + PrinterStream(int i) { this.number = i; } + void write() {} + // XXX hashcode + public boolean equals(Object o) { + if (o == this) { + return true; + } else if (null == o) { + return false; + } else if (o instanceof PrinterStream) { + return ((PrinterStream)o).number == number; + } else { + return o.equals(this); + } + } +} |