]> source.dussan.org Git - aspectj.git/commitdiff
mainly reflective loading - unfortunately also reformatted
authorwisberg <wisberg>
Wed, 11 May 2005 09:46:48 +0000 (09:46 +0000)
committerwisberg <wisberg>
Wed, 11 May 2005 09:46:48 +0000 (09:46 +0000)
testing-util/src/org/aspectj/testing/util/TestUtil.java

index c6b4aa33bf86f0ec1cf030134c86e79c0e9f5ad8..56af178376a1946acb3f394dd1afe7a7ae6d2ef8 100644 (file)
 
 package org.aspectj.testing.util;
 
-import org.aspectj.bridge.IMessageHandler;
-import org.aspectj.bridge.MessageUtil;
-import org.aspectj.util.FileUtil;
-import org.aspectj.util.LangUtil;
-import org.aspectj.util.Reflection;
-
 import java.io.BufferedReader;
 import java.io.ByteArrayOutputStream;
 import java.io.DataInputStream;
@@ -26,13 +20,16 @@ import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintStream;
+import java.io.PrintWriter;
 import java.io.StringReader;
 import java.io.StringWriter;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -41,15 +38,23 @@ import jdiff.text.FileLine;
 import jdiff.util.Diff;
 import jdiff.util.DiffNormalOutput;
 import junit.framework.Assert;
+import junit.framework.Test;
 import junit.framework.TestCase;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
 import junit.runner.TestCaseClassLoader;
 
-/** 
- * Things that junit should perhaps have, but doesn't.
- * Note the file-comparison methods require JDiff to run,
- * but JDiff types are not required to resolve this class.
- * Also, the bytecode weaver is required to compare class
- * files, but not to compare other files.
+import org.aspectj.bridge.IMessageHandler;
+import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.FileUtil;
+import org.aspectj.util.LangUtil;
+import org.aspectj.util.Reflection;
+
+/**
+ * Things that junit should perhaps have, but doesn't. Note the file-comparison
+ * methods require JDiff to run, but JDiff types are not required to resolve
+ * this class. Also, the bytecode weaver is required to compare class files, but
+ * not to compare other files.
  */
 
 public final class TestUtil {
@@ -58,10 +63,13 @@ public final class TestUtil {
         super();
     }
 
+
     // ---- arrays
 
-    public static void assertArrayEquals(String msg, Object[] expected, Object[] found) {
-        TestCase.assertEquals(msg, Arrays.asList(expected), Arrays.asList(found));
+    public static void assertArrayEquals(String msg, Object[] expected,
+            Object[] found) {
+        TestCase.assertEquals(msg, Arrays.asList(expected), Arrays
+                .asList(found));
     }
 
     // ---- unordered
@@ -70,14 +78,13 @@ public final class TestUtil {
         assertSetEquals(null, expected, found);
     }
 
-    public static void assertSetEquals(String msg, Object[] expected, Object[] found) {
+    public static void assertSetEquals(String msg, Object[] expected,
+            Object[] found) {
         assertSetEquals(msg, Arrays.asList(expected), Arrays.asList(found));
     }
 
-    public static void assertSetEquals(
-        String msg,
-        Collection expected,
-        Collection found) {
+    public static void assertSetEquals(String msg, Collection expected,
+            Collection found) {
         msg = (msg == null) ? "" : msg + ": ";
 
         Set results1 = new HashSet(found);
@@ -87,27 +94,22 @@ public final class TestUtil {
         results2.removeAll(found);
 
         if (results1.isEmpty()) {
-            TestCase.assertTrue(
-                msg + "Expected but didn't find: " + results2.toString(),
-                results2.isEmpty());
+            TestCase.assertTrue(msg + "Expected but didn't find: "
+                    + results2.toString(), results2.isEmpty());
         } else if (results2.isEmpty()) {
-            TestCase.assertTrue(
-                msg + "Didn't expect: " + results1.toString(),
-                results1.isEmpty());
+            TestCase.assertTrue(msg + "Didn't expect: " + results1.toString(),
+                    results1.isEmpty());
         } else {
-            TestCase.assertTrue(
-                msg
-                    + "Expected but didn't find: "
-                    + results2.toString()
-                    + "\nDidn't expect: "
-                    + results1.toString(),
-                false);
+            TestCase.assertTrue(msg + "Expected but didn't find: "
+                    + results2.toString() + "\nDidn't expect: "
+                    + results1.toString(), false);
         }
     }
 
     // ---- objects
 
-    public static void assertCommutativeEquals(Object a, Object b, boolean should) {
+    public static void assertCommutativeEquals(Object a, Object b,
+            boolean should) {
         TestCase.assertEquals(a + " equals " + b, should, a.equals(b));
         TestCase.assertEquals(b + " equals " + a, should, b.equals(a));
         assertHashEquals(a, b, should);
@@ -115,124 +117,130 @@ public final class TestUtil {
 
     private static void assertHashEquals(Object s, Object t, boolean should) {
         if (should) {
-            TestCase.assertTrue(
-                s + " does not hash to same as " + t,
-                s.hashCode() == t.hashCode());
+            TestCase.assertTrue(s + " does not hash to same as " + t, s
+                    .hashCode() == t.hashCode());
         } else {
             if (s.hashCode() == t.hashCode()) {
-                System.err.println("warning: hash collision with hash = " + t.hashCode());
+                System.err.println("warning: hash collision with hash = "
+                        + t.hashCode());
                 System.err.println("  for " + s);
                 System.err.println("  and " + t);
             }
         }
     }
-    
+
     // -- reflective stuff
 
-       public static void runMain(String classPath, String className) {
-               runMethod(classPath, className, "main", new Object[] { new String[0] });
-       }
-
-
-       public static Object runMethod(String classPath, String className, String methodName, Object[] args) {
-               classPath += File.pathSeparator + System.getProperty("java.class.path");
-               
-               ClassLoader loader = new TestCaseClassLoader(classPath);
-               
-               Class c=null;
-               try {
-                       c = loader.loadClass(className);
-               } catch (ClassNotFoundException e) {
-                       Assert.assertTrue("unexpected exception: " + e, false);
-               }
-               return Reflection.invokestaticN(c, methodName, args);
-       }
-
-               
-       /**
-        * Checks that two multi-line strings have the same value.
-        * Each line is trimmed before comparision
-        * Produces an error on the particular line of conflict
-        */    
-    public static void assertMultiLineStringEquals(String message, String s1, String s2) {
-       try {
-               BufferedReader r1 = new BufferedReader(new StringReader(s1));
-               BufferedReader r2 = new BufferedReader(new StringReader(s2));
-               
-               
-               List lines = new ArrayList();
-               String l1, l2;
-               
-               int index = 1;
-               while(true) {
-                   l1 = readNonBlankLine(r1);
-                   l2 = readNonBlankLine(r2);
-                   if (l1 == null || l2 == null) break;
-                   if (l1.equals(l2)) {
-                       lines.add(l1);
-                   } else {
-                       showContext(lines);
-                       Assert.assertEquals(message +"(line " + index +")", l1, l2);
-                   }
-                   index++;
-               }
-               if (l1 != null) showContext(lines);
-               Assert.assertTrue(message + ": unexpected " + l1, l1 == null);
-               if (l2 != null) showContext(lines);
-               Assert.assertTrue(message + ": unexpected " + l2, l2 == null);
-       } catch (IOException ioe) {
-               Assert.assertTrue(message + ": caught " + ioe.getMessage(), false);
-       }
+    public static void runMain(String classPath, String className) {
+        runMethod(classPath, className, "main", new Object[] { new String[0] });
     }
-    
-       private static void showContext(List lines) {
-               int n = lines.size();
-               for (int i = Math.max(0, n - 8); i < n; i++) {
-                       System.err.println(lines.get(i));
-               }
-       }       
-       
-       private static String readNonBlankLine(BufferedReader r) throws IOException {
-               String l = r.readLine();
-               if (l == null) return null;
+
+    public static Object runMethod(String classPath, String className,
+            String methodName, Object[] args) {
+        classPath += File.pathSeparator + System.getProperty("java.class.path");
+
+        ClassLoader loader = new TestCaseClassLoader(classPath);
+
+        Class c = null;
+        try {
+            c = loader.loadClass(className);
+        } catch (ClassNotFoundException e) {
+            Assert.assertTrue("unexpected exception: " + e, false);
+        }
+        return Reflection.invokestaticN(c, methodName, args);
+    }
+
+    /**
+     * Checks that two multi-line strings have the same value. Each line is
+     * trimmed before comparision Produces an error on the particular line of
+     * conflict
+     */
+    public static void assertMultiLineStringEquals(String message, String s1,
+            String s2) {
+        try {
+            BufferedReader r1 = new BufferedReader(new StringReader(s1));
+            BufferedReader r2 = new BufferedReader(new StringReader(s2));
+
+            List lines = new ArrayList();
+            String l1, l2;
+
+            int index = 1;
+            while (true) {
+                l1 = readNonBlankLine(r1);
+                l2 = readNonBlankLine(r2);
+                if (l1 == null || l2 == null)
+                    break;
+                if (l1.equals(l2)) {
+                    lines.add(l1);
+                } else {
+                    showContext(lines);
+                    Assert.assertEquals(message + "(line " + index + ")", l1,
+                            l2);
+                }
+                index++;
+            }
+            if (l1 != null)
+                showContext(lines);
+            Assert.assertTrue(message + ": unexpected " + l1, l1 == null);
+            if (l2 != null)
+                showContext(lines);
+            Assert.assertTrue(message + ": unexpected " + l2, l2 == null);
+        } catch (IOException ioe) {
+            Assert.assertTrue(message + ": caught " + ioe.getMessage(), false);
+        }
+    }
+
+    private static void showContext(List lines) {
+        int n = lines.size();
+        for (int i = Math.max(0, n - 8); i < n; i++) {
+            System.err.println(lines.get(i));
+        }
+    }
+
+    private static String readNonBlankLine(BufferedReader r) throws IOException {
+        String l = r.readLine();
+        if (l == null)
+            return null;
         l = l.trim();
         // comment to include comments when reading
         int commentLoc = l.indexOf("//");
         if (-1 != commentLoc) {
             l = l.substring(0, commentLoc).trim();
         }
-               if ("".equals(l)) return readNonBlankLine(r);
+        if ("".equals(l))
+            return readNonBlankLine(r);
         return l;
-       }
-    
+    }
+
     /**
-     * If there is an expected dir, expect each file in its subtree
-     * to match a corresponding actual file in the base directory.
-     * This does NOT check that all actual files have corresponding
-     * expected files.
-     * This ignores directory paths containing "CVS".
-     * @param handler the IMessageHandler sink for error messages
-     * @param expectedBaseDir the File path to the directory
-     *         containing expected files, all of which are compared
-     *         with any corresponding actual files
-     * @param actualBaseDir the File path to the base directory
-     *         from which to find any actual files corresponding
-     *         to expected files.
-     * @return true if all files in the expectedBaseDir directory tree
-     *          have matching files in the actualBaseDir directory tree.
+     * If there is an expected dir, expect each file in its subtree to match a
+     * corresponding actual file in the base directory. This does NOT check that
+     * all actual files have corresponding expected files. This ignores
+     * directory paths containing "CVS".
+     * 
+     * @param handler
+     *            the IMessageHandler sink for error messages
+     * @param expectedBaseDir
+     *            the File path to the directory containing expected files, all
+     *            of which are compared with any corresponding actual files
+     * @param actualBaseDir
+     *            the File path to the base directory from which to find any
+     *            actual files corresponding to expected files.
+     * @return true if all files in the expectedBaseDir directory tree have
+     *         matching files in the actualBaseDir directory tree.
      */
-    public static boolean sameDirectoryContents(
-        final IMessageHandler handler, 
-        final File expectedBaseDir,
-        final File actualBaseDir,
-        final boolean fastFail) {
+    public static boolean sameDirectoryContents(final IMessageHandler handler,
+            final File expectedBaseDir, final File actualBaseDir,
+            final boolean fastFail) {
         LangUtil.throwIaxIfNull(handler, "handler");
         if (!FileUtil.canReadDir(expectedBaseDir)) {
-            MessageUtil.fail(handler, " expected dir not found: " + expectedBaseDir);
+            MessageUtil.fail(handler, " expected dir not found: "
+                    + expectedBaseDir);
             return false;
         }
         if (!FileUtil.canReadDir(actualBaseDir)) {
-            MessageUtil.fail(handler, " actual dir not found: " + actualBaseDir);
+            MessageUtil
+                    .fail(handler, " actual dir not found: " + actualBaseDir);
             return false;
         }
         String[] paths = FileUtil.listFiles(expectedBaseDir);
@@ -241,7 +249,8 @@ public final class TestUtil {
             if (-1 != paths[i].indexOf("CVS")) {
                 continue;
             }
-            if (!sameFiles(handler, expectedBaseDir, actualBaseDir, paths[i]) && result) {
+            if (!sameFiles(handler, expectedBaseDir, actualBaseDir, paths[i])
+                    && result) {
                 result = false;
                 if (fastFail) {
                     break;
@@ -250,88 +259,95 @@ public final class TestUtil {
         }
         return result;
     }
-    
-    //------------ File-comparison utilities (XXX need their own class...)
+
+    // ------------ File-comparison utilities (XXX need their own class...)
     /**
-     * Test interface to
-     * compare two files, line by line, and report differences as one FAIL message
-     * if a handler is supplied.  This preprocesses .class files by disassembling.
-     * @param handler the IMessageHandler for any FAIL messages (null to ignore)
-     * @param expectedFile the File path to the canonical file
-     * @param actualFile the File path to the actual file, if any
-     * @return true if the input files are the same, based on per-line comparisons
+     * Test interface to compare two files, line by line, and report differences
+     * as one FAIL message if a handler is supplied. This preprocesses .class
+     * files by disassembling.
+     * 
+     * @param handler
+     *            the IMessageHandler for any FAIL messages (null to ignore)
+     * @param expectedFile
+     *            the File path to the canonical file
+     * @param actualFile
+     *            the File path to the actual file, if any
+     * @return true if the input files are the same, based on per-line
+     *         comparisons
      */
-    public static boolean sameFiles (
-        IMessageHandler handler,
-        File expectedFile, 
-        File actualFile) {
+    public static boolean sameFiles(IMessageHandler handler, File expectedFile,
+            File actualFile) {
         return doSameFile(handler, null, null, expectedFile, actualFile);
     }
 
     /**
-     * Test interface to
-     * compare two files, line by line, and report differences as one FAIL message
-     * if a handler is supplied.  This preprocesses .class files by disassembling.
-     * This method assumes that the files are at the same offset from two
-     * respective base directories.
-     * @param handler the IMessageHandler for any FAIL messages (null to ignore)
-     * @param expectedBaseDir the File path to the canonical file base directory
-     * @param actualBaseDir the File path to the actual file base directory
-     * @param path the String path offset from the base directories
-     * @return true if the input files are the same, based on per-line comparisons
+     * Test interface to compare two files, line by line, and report differences
+     * as one FAIL message if a handler is supplied. This preprocesses .class
+     * files by disassembling. This method assumes that the files are at the
+     * same offset from two respective base directories.
+     * 
+     * @param handler
+     *            the IMessageHandler for any FAIL messages (null to ignore)
+     * @param expectedBaseDir
+     *            the File path to the canonical file base directory
+     * @param actualBaseDir
+     *            the File path to the actual file base directory
+     * @param path
+     *            the String path offset from the base directories
+     * @return true if the input files are the same, based on per-line
+     *         comparisons
      */
-    public static boolean sameFiles (
-        IMessageHandler handler,
-        File expectedBaseDir, 
-        File actualBaseDir, 
-        String path) {
+    public static boolean sameFiles(IMessageHandler handler,
+            File expectedBaseDir, File actualBaseDir, String path) {
         File actualFile = new File(actualBaseDir, path);
         File expectedFile = new File(expectedBaseDir, path);
-        return doSameFile(handler, expectedBaseDir, actualBaseDir, expectedFile, actualFile);
+        return doSameFile(handler, expectedBaseDir, actualBaseDir,
+                expectedFile, actualFile);
     }
 
     /**
      * This does the work, selecting a lineator subclass and converting public
-     * API's to JDiff APIs for comparison.
-     * Currently, all jdiff interfaces are method-local, so this class will load 
-     * without it; if we do use it, we can avoid the duplication.
+     * API's to JDiff APIs for comparison. Currently, all jdiff interfaces are
+     * method-local, so this class will load without it; if we do use it, we can
+     * avoid the duplication.
      */
-    private static boolean doSameFile(
-        IMessageHandler handler,
-        File expectedBaseDir, 
-        File actualBaseDir,
-        File expectedFile,
-        File actualFile) {
+    private static boolean doSameFile(IMessageHandler handler,
+            File expectedBaseDir, File actualBaseDir, File expectedFile,
+            File actualFile) {
         String path = expectedFile.getPath();
         // XXX permit user to specify lineator
         ILineator lineator = Lineator.TEXT;
         if (path.endsWith(".class")) {
-            if (ClassLineator.haveDisassembler() ) {
+            if (ClassLineator.haveDisassembler()) {
                 lineator = Lineator.CLASS;
             } else {
-                MessageUtil.abort(handler, "skipping - dissassembler not available");
+                MessageUtil.abort(handler,
+                        "skipping - dissassembler not available");
                 return false;
             }
         }
         CanonicalLine[] actualLines = null;
         CanonicalLine[] expectedLines = null;
         try {
-            actualLines = lineator.getLines(handler, actualFile, actualBaseDir); 
-            expectedLines = lineator.getLines(handler, expectedFile, expectedBaseDir);
+            actualLines = lineator.getLines(handler, actualFile, actualBaseDir);
+            expectedLines = lineator.getLines(handler, expectedFile,
+                    expectedBaseDir);
         } catch (IOException e) {
             MessageUtil.fail(handler, "rendering lines ", e);
             return false;
         }
         if (!LangUtil.isEmpty(actualLines) && !LangUtil.isEmpty(expectedLines)) {
-            // here's the transmutation back to jdiff - extract if publishing JDiff
-            CanonicalLine[][] clines = new CanonicalLine[][] { expectedLines, actualLines };
+            // here's the transmutation back to jdiff - extract if publishing
+            // JDiff
+            CanonicalLine[][] clines = new CanonicalLine[][] { expectedLines,
+                    actualLines };
             FileLine[][] flines = new FileLine[2][];
             for (int i = 0; i < clines.length; i++) {
                 CanonicalLine[] cline = clines[i];
                 FileLine[] fline = new FileLine[cline.length];
                 for (int j = 0; j < fline.length; j++) {
-                                       fline[j] = new FileLine(cline[j].canonical, cline[j].line);
-                               }
+                    fline[j] = new FileLine(cline[j].canonical, cline[j].line);
+                }
                 flines[i] = fline;
             }
 
@@ -340,9 +356,10 @@ public final class TestUtil {
                 // XXX confirm with jdiff that null means no edits
                 return true;
             } else {
-                //String m = render(handler, edits, flines[0], flines[1]);
+                // String m = render(handler, edits, flines[0], flines[1]);
                 StringWriter writer = new StringWriter();
-                DiffNormalOutput out = new DiffNormalOutput(flines[0], flines[1]);
+                DiffNormalOutput out = new DiffNormalOutput(flines[0],
+                        flines[1]);
                 out.setOut(writer);
                 out.setLineSeparator(LangUtil.EOL);
                 try {
@@ -351,26 +368,161 @@ public final class TestUtil {
                     MessageUtil.fail(handler, "rendering edits", e);
                 } finally {
                     if (null != writer) {
-                        try { writer.close(); } 
-                        catch (IOException e) {
-                            MessageUtil.fail(handler, "closing after rendering edits", e);
+                        try {
+                            writer.close();
+                        } catch (IOException e) {
+                            MessageUtil.fail(handler,
+                                    "closing after rendering edits", e);
                         }
                     }
                 }
-                String message = "diff between " 
-                    + path 
-                    + " in expected dir " 
-                    + expectedBaseDir
-                    + " and actual dir " 
-                    + actualBaseDir 
-                    + LangUtil.EOL
-                    + writer.toString(); 
+                String message = "diff between " + path + " in expected dir "
+                        + expectedBaseDir + " and actual dir " + actualBaseDir
+                        + LangUtil.EOL + writer.toString();
                 MessageUtil.fail(handler, message);
             }
         }
         return false;
     }
+
+
+    /**
+     * TODO move to testing-utils for use by loadtime5, others.
+     * 
+     * @param sink
+     * @param sourceName
+     */
+    public static void loadTestsReflectively(TestSuite sink, String sourceName, boolean ignoreError) {
+        Throwable thrown = null;
+        try {
+            ClassLoader loader = sink.getClass().getClassLoader();
+            Class sourceClass = loader.loadClass(sourceName);
+            if (!Modifier.isPublic(sourceClass.getModifiers())) {
+                errorSuite(sink, sourceName, "not public class");
+                return;
+            }
+            Method suiteMethod = sourceClass.getMethod("suite", new Class[0]);
+            int mods = suiteMethod.getModifiers();
+            if (!Modifier.isStatic(mods) || !Modifier.isPublic(mods)) {
+                errorSuite(sink, sourceName, "not static method");
+                return;
+            }
+            if (!Modifier.isPublic(mods)) {
+                errorSuite(sink, sourceName, "not public method");
+                return;
+            }
+            if (!Test.class.isAssignableFrom(suiteMethod.getReturnType())) {
+                errorSuite(sink, sourceName, "suite() does not return Test");
+                return;
+            }
+            Object result = suiteMethod.invoke(null, new Object[0]);
+            Test test = (Test) result;
+            if (!(test instanceof TestSuite)) {
+                sink.addTest(test);
+            } else {
+                TestSuite source = (TestSuite) test;
+                Enumeration tests = source.tests();
+                while (tests.hasMoreElements()) {
+                    sink.addTest((Test) tests.nextElement());
+                }
+            }
+
+        } catch (ClassNotFoundException e) {
+            thrown = e;
+        } catch (SecurityException e) {
+            thrown = e;
+        } catch (NoSuchMethodException e) {
+            thrown = e;
+        } catch (IllegalArgumentException e) {
+            thrown = e;
+        } catch (IllegalAccessException e) {
+            thrown = e;
+        } catch (InvocationTargetException e) {
+            thrown = e;
+        }
+        if (null != thrown) {
+            if (ignoreError) {
+                System.err.println("Error loading " + sourceName);
+                thrown.printStackTrace(System.err);
+            } else {
+                errorSuite(sink, sourceName, thrown);
+            }
+        }
+    }
+
+    private static void errorSuite(TestSuite sink, String sourceName,
+            Throwable thrown) {
+        sink.addTest(new ErrorTest(sourceName, thrown));
+    }
+
+    private static void errorSuite(TestSuite sink, String sourceName, String err) {
+        String message = "bad " + sourceName + ": " + err;
+        sink.addTest(new ErrorTest(message));
+    }
     
+    /** 
+     * Junit test failure, e.g., to report suite initialization errors at test time.
+     */
+    public static class ErrorTest implements Test {
+        private final Throwable thrown;
+
+        public ErrorTest(Throwable thrown) {
+            this.thrown = thrown;
+        }
+
+        public ErrorTest(String message) {
+            this.thrown = new Error(message);
+        }
+
+        public ErrorTest(String message, Throwable thrown) {
+            this(new TestError(message, thrown));
+        }
+
+        public int countTestCases() {
+            return 1;
+        }
+
+        public void run(TestResult result) {
+            result.startTest(this);
+            result.addError(this, thrown);
+        }
+    }
+
+    /**
+     * Nested exception - remove when using 1.4 or later.
+     */
+    public static class TestError extends Error {
+        private Throwable thrown;
+
+        public TestError(String message) {
+            super(message);
+        }
+
+        public TestError(String message, Throwable thrown) {
+            super(message);
+            this.thrown = thrown;
+        }
+
+        public Throwable getCause() {
+            return thrown;
+        }
+
+        public void printStackTrace() {
+            printStackTrace(System.err);
+        }
+
+        public void printStackTrace(PrintStream ps) {
+            printStackTrace(new PrintWriter(ps));
+        }
+
+        public void printStackTrace(PrintWriter pw) {
+            super.printStackTrace(pw);
+            if (null != thrown) {
+                pw.print("Caused by: ");
+                thrown.printStackTrace(pw);
+            }
+        }
+    }
 
     /** component that reduces file to CanonicalLine[] */
     public static interface ILineator {
@@ -382,75 +534,84 @@ public final class TestUtil {
 
         /**
          * Reduce file to CanonicalLine[].
-         * @param handler the IMessageHandler for errors (may be null) 
-         * @param file the File to render
-         * @param basedir the File for the base directory (may be null) 
+         * 
+         * @param handler
+         *            the IMessageHandler for errors (may be null)
+         * @param file
+         *            the File to render
+         * @param basedir
+         *            the File for the base directory (may be null)
          * @return CanonicalLine[] of lines - not null, but perhaps empty
          */
-        CanonicalLine[] getLines(
-            IMessageHandler handler, 
-            File file, 
-            File basedir) throws IOException;
+        CanonicalLine[] getLines(IMessageHandler handler, File file,
+                File basedir) throws IOException;
     }
-    
+
     /** alias for jdiff FileLine to avoid client binding */
     public static class CanonicalLine {
         public static final CanonicalLine[] NO_LINES = new CanonicalLine[0];
-        
+
         /** canonical variant of line for comparison */
         public final String canonical;
-        
+
         /** actual line, for logging */
         public final String line;
+
         public CanonicalLine(String canonical, String line) {
             this.canonical = canonical;
             this.line = line;
         }
+
         public String toString() {
             return line;
         }
     }
-    
+
     private abstract static class Lineator implements ILineator {
         /**
          * Reduce file to CanonicalLine[].
-         * @param handler the IMessageHandler for errors (may be null) 
-         * @param file the File to render
-         * @param basedir the File for the base directory (may be null) 
+         * 
+         * @param handler
+         *            the IMessageHandler for errors (may be null)
+         * @param file
+         *            the File to render
+         * @param basedir
+         *            the File for the base directory (may be null)
          */
-        public CanonicalLine[] getLines(
-            IMessageHandler handler, 
-            File file, 
-            File basedir) 
-            throws IOException {
-        
+        public CanonicalLine[] getLines(IMessageHandler handler, File file,
+                File basedir) throws IOException {
+
             if (!file.canRead() || !file.isFile()) {
-                MessageUtil.error(handler, "not readable file: " + basedir + " - " + file);
+                MessageUtil.error(handler, "not readable file: " + basedir
+                        + " - " + file);
                 return null;
             }
             // capture file as FileLine[]
             InputStream in = null;
-            /*String path = */FileUtil.normalizedPath(file, basedir);
+            /* String path = */FileUtil.normalizedPath(file, basedir);
             LineStream capture = new LineStream();
-            try { 
+            try {
                 lineate(capture, handler, basedir, file);
             } catch (IOException e) {
-                MessageUtil.fail(handler, 
-                    "NormalizedCompareFiles IOException reading " + file, e);
+                MessageUtil
+                        .fail(handler,
+                                "NormalizedCompareFiles IOException reading "
+                                        + file, e);
                 return null;
             } finally {
                 if (null != in) {
-                    try { in.close(); }
-                    catch (IOException e) {} // ignore
+                    try {
+                        in.close();
+                    } catch (IOException e) {
+                    } // ignore
                 }
                 capture.flush();
                 capture.close();
             }
             String missed = capture.getMissed();
             if (!LangUtil.isEmpty(missed)) {
-                MessageUtil.warn(handler, 
-                    "NormalizedCompareFiles missed input: " 
-                    + missed);
+                MessageUtil.warn(handler,
+                        "NormalizedCompareFiles missed input: " + missed);
                 return null;
             } else {
                 String[] lines = capture.getLines();
@@ -459,79 +620,72 @@ public final class TestUtil {
                     result[i] = new CanonicalLine(lines[i], lines[i]);
                 }
                 return result;
-            }                    
-        } 
-        
-        protected abstract void lineate(
-            PrintStream sink,
-            IMessageHandler handler, 
-            File basedir, 
-            File file) throws IOException;
+            }
+        }
+
+        protected abstract void lineate(PrintStream sink,
+                IMessageHandler handler, File basedir, File file)
+                throws IOException;
     }
-    
+
     private static class TextLineator extends Lineator {
-        
-        protected void lineate(
-            PrintStream sink,
-            IMessageHandler handler, 
-            File basedir, 
-            File file) throws IOException {
+
+        protected void lineate(PrintStream sink, IMessageHandler handler,
+                File basedir, File file) throws IOException {
             InputStream in = null;
             try {
                 in = new FileInputStream(file);
                 FileUtil.copyStream(new DataInputStream(in), sink);
             } finally {
-                try { in.close(); }
-                catch (IOException e) {} // ignore
+                try {
+                    in.close();
+                } catch (IOException e) {
+                } // ignore
             }
         }
     }
 
     public static class ClassLineator extends Lineator {
-        
-        protected void lineate(
-            PrintStream sink,
-            IMessageHandler handler, 
-            File basedir, 
-            File file) throws IOException {
+
+        protected void lineate(PrintStream sink, IMessageHandler handler,
+                File basedir, File file) throws IOException {
             String name = FileUtil.fileToClassName(basedir, file);
             // XXX re-enable preflight?
-//            if ((null != basedir) && (path.length()-6 != name.length())) {
-//                MessageUtil.error(handler, "unexpected class name \""
-//                        + name + "\" for path " + path);
-//                return null;
-//            }
+            // if ((null != basedir) && (path.length()-6 != name.length())) {
+            // MessageUtil.error(handler, "unexpected class name \""
+            // + name + "\" for path " + path);
+            // return null;
+            // }
             disassemble(handler, basedir, name, sink);
         }
-        
+
         public static boolean haveDisassembler() {
             try {
-                return (null != Class.forName("org.aspectj.weaver.bcel.LazyClassGen"));
+                return (null != Class
+                        .forName("org.aspectj.weaver.bcel.LazyClassGen"));
             } catch (ClassNotFoundException e) {
                 // XXX fix
-                //System.err.println(e.getMessage());
-                //e.printStackTrace(System.err);
+                // System.err.println(e.getMessage());
+                // e.printStackTrace(System.err);
                 return false;
             }
         }
-        
-        /** XXX  dependency on bcweaver/bcel */
-        private static void disassemble(
-            IMessageHandler handler, 
-            File basedir, 
-            String name, 
-            PrintStream out) throws IOException {
-            // LazyClassGen.disassemble(FileUtil.normalizedPath(basedir), name, capture);
-            
+
+        /** XXX dependency on bcweaver/bcel */
+        private static void disassemble(IMessageHandler handler, File basedir,
+                String name, PrintStream out) throws IOException {
+            // LazyClassGen.disassemble(FileUtil.normalizedPath(basedir), name,
+            // capture);
+
             Throwable thrown = null;
             String basedirPath = FileUtil.normalizedPath(basedir);
             // XXX use reflection utilities to invoke dissassembler?
             try {
                 // XXX need test to detect when this is refactored
                 Class c = Class.forName("org.aspectj.weaver.bcel.LazyClassGen");
-                Method m = c.getMethod("disassemble", 
-                    new Class[] {String.class, String.class, PrintStream.class});
-                m.invoke(null, new Object[] { basedirPath, name, out});
+                Method m = c.getMethod("disassemble", new Class[] {
+                        String.class, String.class, PrintStream.class });
+                m.invoke(null, new Object[] { basedirPath, name, out });
             } catch (ClassNotFoundException e) {
                 thrown = e;
             } catch (NoSuchMethodException e) {
@@ -546,85 +700,89 @@ public final class TestUtil {
                 thrown = t;
             }
             if (null != thrown) {
-                MessageUtil.fail(handler, "disassembling " + name  + " path: " + basedirPath,
-                    thrown);
+                MessageUtil.fail(handler, "disassembling " + name + " path: "
+                        + basedirPath, thrown);
             }
         }
     }
 
-
     /**
-     * Capture PrintStream output to String[]
-     * (delimiting component String on println()),
-     * also showing any missed text.
+     * Capture PrintStream output to String[] (delimiting component String on
+     * println()), also showing any missed text.
      */
     public static class LineStream extends PrintStream {
         StringBuffer sb = new StringBuffer();
+
         ByteArrayOutputStream missed;
+
         ArrayList sink;
+
         public LineStream() {
             super(new ByteArrayOutputStream());
             this.sink = new ArrayList();
             missed = (ByteArrayOutputStream) out;
         }
-        
+
         /** @return any text not captured by our overrides */
         public String getMissed() {
             return missed.toString();
         }
-        
+
         /** clear captured lines (but not missed text) */
         public void clear() {
             sink.clear();
         }
-        
-        /** 
-         * Get String[] of lines printed,
-         * delimited by println(..) calls.
-         * @return lines printed, exclusive of any not yet terminated by newline 
+
+        /**
+         * Get String[] of lines printed, delimited by println(..) calls.
+         * 
+         * @return lines printed, exclusive of any not yet terminated by newline
          */
         public String[] getLines() {
             return (String[]) sink.toArray(new String[0]);
         }
-        
+
         // ---------- PrintStream overrides
-               public void println(Object x) {
-                       println(x.toString());
-               }
+        public void println(Object x) {
+            println(x.toString());
+        }
 
-               public void print(Object obj) {
-                       print(obj.toString());
-               }
+        public void print(Object obj) {
+            print(obj.toString());
+        }
 
         public void println(char c) {
             sb.append(c);
             println();
         }
+
         public void println(char[] c) {
             sb.append(c);
             println();
         }
-               public void print(char c) {
+
+        public void print(char c) {
             sb.append(c);
-               }
+        }
 
         public void print(char[] c) {
             sb.append(c);
         }
-        
+
         public void println(String s) {
             print(s);
             println();
         }
+
         public void print(String s) {
             sb.append(s);
         }
+
         public void println() {
             String line = sb.toString();
             sink.add(line);
             sb.setLength(0);
         }
     }
-    
+
 }