|  // : com:bruceeckel:simpletest:Test.java
 //Simple utility for testing program output. Intercepts
 //System.out to print both to the console and a buffer.
 //From 'Thinking in Java, 3rd ed.' (c) Bruce Eckel 2002
 //www.BruceEckel.com. See copyright notice in CopyRight.txt.
 
 import java.io.BufferedInputStream;
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintStream;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.regex.Pattern;
 
 public class Alias2 {
 private static Test monitor = new Test();
 private int i;
 public Alias2(int ii) { i = ii; }
 public static void f(Alias2 reference) { reference.i++; }
 public static void main(String[] args) {
 Alias2 x = new Alias2(7);
 System.out.println("x: " + x.i);
 System.out.println("Calling f(x)");
 f(x);
 System.out.println("x: " + x.i);
 monitor.expect(new String[] {
 "x: 7",
 "Calling f(x)",
 "x: 8"
 });
 }
 } ///:~
 
 class Test {
 // Bit-shifted so they can be added together:
 public static final int EXACT = 1 << 0, // Lines must match exactly
 AT_LEAST = 1 << 1, // Must be at least these lines
 IGNORE_ORDER = 1 << 2, // Ignore line order
 WAIT = 1 << 3; // Delay until all lines are output
 
 private String className;
 
 private TestStream testStream;
 
 public Test() {
 // Discover the name of the class this
 // object was created within:
 className = new Throwable().getStackTrace()[1].getClassName();
 testStream = new TestStream(className);
 }
 
 public static List fileToList(String fname) {
 ArrayList list = new ArrayList();
 try {
 BufferedReader in = new BufferedReader(new FileReader(fname));
 try {
 String line;
 while ((line = in.readLine()) != null) {
 if (fname.endsWith(".txt"))
 list.add(line);
 else
 list.add(new TestExpression(line));
 }
 } finally {
 in.close();
 }
 } catch (IOException e) {
 throw new RuntimeException(e);
 }
 return list;
 }
 
 public static List arrayToList(Object[] array) {
 List l = new ArrayList();
 for (int i = 0; i < array.length; i++) {
 if (array[i] instanceof TestExpression) {
 TestExpression re = (TestExpression) array[i];
 for (int j = 0; j < re.getNumber(); j++)
 l.add(re);
 } else {
 l.add(new TestExpression(array[i].toString()));
 }
 }
 return l;
 }
 
 public void expect(Object[] exp, int flags) {
 if ((flags & WAIT) != 0)
 while (testStream.numOfLines < exp.length) {
 try {
 Thread.sleep(1000);
 } catch (InterruptedException e) {
 throw new RuntimeException(e);
 }
 }
 List output = fileToList(className + "Output.txt");
 if ((flags & IGNORE_ORDER) == IGNORE_ORDER)
 OutputVerifier.verifyIgnoreOrder(output, exp);
 else if ((flags & AT_LEAST) == AT_LEAST)
 OutputVerifier.verifyAtLeast(output, arrayToList(exp));
 else
 OutputVerifier.verify(output, arrayToList(exp));
 // Clean up the output file - see c06:Detergent.java
 testStream.openOutputFile();
 }
 
 public void expect(Object[] expected) {
 expect(expected, EXACT);
 }
 
 public void expect(Object[] expectFirst, String fname, int flags) {
 List expected = fileToList(fname);
 for (int i = 0; i < expectFirst.length; i++)
 expected.add(i, expectFirst[i]);
 expect(expected.toArray(), flags);
 }
 
 public void expect(Object[] expectFirst, String fname) {
 expect(expectFirst, fname, EXACT);
 }
 
 public void expect(String fname) {
 expect(new Object[] {}, fname, EXACT);
 }
 } ///:~
 
 class TestExpression implements Comparable {
 private Pattern p;
 
 private String expression;
 
 private boolean isRegEx;
 
 // Default to only one instance of this expression:
 private int duplicates = 1;
 
 public TestExpression(String s) {
 this.expression = s;
 if (expression.startsWith("%% ")) {
 this.isRegEx = true;
 expression = expression.substring(3);
 this.p = Pattern.compile(expression);
 }
 }
 
 // For duplicate instances:
 public TestExpression(String s, int duplicates) {
 this(s);
 this.duplicates = duplicates;
 }
 
 public String toString() {
 if (isRegEx)
 return p.pattern();
 return expression;
 }
 
 public boolean equals(Object obj) {
 if (this == obj)
 return true;
 if (isRegEx)
 return (compareTo(obj) == 0);
 return expression.equals(obj.toString());
 }
 
 public int compareTo(Object obj) {
 if ((isRegEx) && (p.matcher(obj.toString()).matches()))
 return 0;
 return expression.compareTo(obj.toString());
 }
 
 public int getNumber() {
 return duplicates;
 }
 
 public String getExpression() {
 return expression;
 }
 
 public boolean isRegEx() {
 return isRegEx;
 }
 } ///:~
 
 class TestStream extends PrintStream {
 protected int numOfLines;
 
 private PrintStream console = System.out, err = System.err, fout;
 
 // To store lines sent to System.out or err
 private InputStream stdin;
 
 private String className;
 
 public TestStream(String className) {
 super(System.out, true); // Autoflush
 System.setOut(this);
 System.setErr(this);
 stdin = System.in; // Save to restore in dispose()
 // Replace the default version with one that
 // automatically produces input on demand:
 System.setIn(new BufferedInputStream(new InputStream() {
 char[] input = ("test\n").toCharArray();
 
 int index = 0;
 
 public int read() {
 return (int) input[index = (index + 1) % input.length];
 }
 }));
 this.className = className;
 openOutputFile();
 }
 
 // public PrintStream getConsole() { return console; }
 public void dispose() {
 System.setOut(console);
 System.setErr(err);
 System.setIn(stdin);
 }
 
 // This will write over an old Output.txt file:
 public void openOutputFile() {
 try {
 fout = new PrintStream(new FileOutputStream(new File(className
 + "Output.txt")));
 } catch (FileNotFoundException e) {
 throw new RuntimeException(e);
 }
 }
 
 // Override all possible print/println methods to send
 // intercepted console output to both the console and
 // the Output.txt file:
 public void print(boolean x) {
 console.print(x);
 fout.print(x);
 }
 
 public void println(boolean x) {
 numOfLines++;
 console.println(x);
 fout.println(x);
 }
 
 public void print(char x) {
 console.print(x);
 fout.print(x);
 }
 
 public void println(char x) {
 numOfLines++;
 console.println(x);
 fout.println(x);
 }
 
 public void print(int x) {
 console.print(x);
 fout.print(x);
 }
 
 public void println(int x) {
 numOfLines++;
 console.println(x);
 fout.println(x);
 }
 
 public void print(long x) {
 console.print(x);
 fout.print(x);
 }
 
 public void println(long x) {
 numOfLines++;
 console.println(x);
 fout.println(x);
 }
 
 public void print(float x) {
 console.print(x);
 fout.print(x);
 }
 
 public void println(float x) {
 numOfLines++;
 console.println(x);
 fout.println(x);
 }
 
 public void print(double x) {
 console.print(x);
 fout.print(x);
 }
 
 public void println(double x) {
 numOfLines++;
 console.println(x);
 fout.println(x);
 }
 
 public void print(char[] x) {
 console.print(x);
 fout.print(x);
 }
 
 public void println(char[] x) {
 numOfLines++;
 console.println(x);
 fout.println(x);
 }
 
 public void print(String x) {
 console.print(x);
 fout.print(x);
 }
 
 public void println(String x) {
 numOfLines++;
 console.println(x);
 fout.println(x);
 }
 
 public void print(Object x) {
 console.print(x);
 fout.print(x);
 }
 
 public void println(Object x) {
 numOfLines++;
 console.println(x);
 fout.println(x);
 }
 
 public void println() {
 if (false)
 console.print("println");
 numOfLines++;
 console.println();
 fout.println();
 }
 
 public void write(byte[] buffer, int offset, int length) {
 console.write(buffer, offset, length);
 fout.write(buffer, offset, length);
 }
 
 public void write(int b) {
 console.write(b);
 fout.write(b);
 }
 } ///:~
 
 class OutputVerifier {
 private static void verifyLength(int output, int expected, int compare) {
 if ((compare == Test.EXACT && expected != output)
 || (compare == Test.AT_LEAST && output < expected))
 throw new NumOfLinesException(expected, output);
 }
 
 public static void verify(List output, List expected) {
 verifyLength(output.size(), expected.size(), Test.EXACT);
 if (!expected.equals(output)) {
 //find the line of mismatch
 ListIterator it1 = expected.listIterator();
 ListIterator it2 = output.listIterator();
 while (it1.hasNext() && it2.hasNext()
 && it1.next().equals(it2.next()))
 ;
 throw new LineMismatchException(it1.nextIndex(), it1.previous()
 .toString(), it2.previous().toString());
 }
 }
 
 public static void verifyIgnoreOrder(List output, Object[] expected) {
 verifyLength(expected.length, output.size(), Test.EXACT);
 if (!(expected instanceof String[]))
 throw new RuntimeException(
 "IGNORE_ORDER only works with String objects");
 String[] out = new String[output.size()];
 Iterator it = output.iterator();
 for (int i = 0; i < out.length; i++)
 out[i] = it.next().toString();
 Arrays.sort(out);
 Arrays.sort(expected);
 int i = 0;
 if (!Arrays.equals(expected, out)) {
 while (expected[i].equals(out[i])) {
 i++;
 }
 
 
 throw new SimpleTestException(((String) out[i]).compareTo(expected[i]) < 0 ? "output: <" + out[i] + ">"
 : "expected: <" + expected[i] + ">");
 }
 }
 
 public static void verifyAtLeast(List output, List expected) {
 verifyLength(output.size(), expected.size(), Test.AT_LEAST);
 if (!output.containsAll(expected)) {
 ListIterator it = expected.listIterator();
 while (output.contains(it.next())) {
 }
 throw new SimpleTestException("expected: <"
 + it.previous().toString() + ">");
 }
 }
 } ///:~
 
 class SimpleTestException extends RuntimeException {
 public SimpleTestException(String msg) {
 super(msg);
 }
 } ///:~
 
 class NumOfLinesException extends SimpleTestException {
 public NumOfLinesException(int exp, int out) {
 super("Number of lines of output and "
 + "expected output did not match.\n" + "expected: <" + exp
 + ">\n" + "output:   <" + out + "> lines)");
 }
 } ///:~
 
 class LineMismatchException extends SimpleTestException {
 public LineMismatchException(int lineNum, String expected, String output) {
 super("line " + lineNum + " of output did not match expected output\n"
 + "expected: <" + expected + ">\n" + "output:   <" + output
 + ">");
 }
 } ///:~
 
 
 
 
 
 
 |