Index: src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
===================================================================
RCS file: /home/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java,v
retrieving revision 1.8
diff -u -r1.8 BatchCompilerTest.java
--- src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java 23 Feb 2005 02:52:37 -0000 1.8
+++ src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java 18 May 2005 13:19:46 -0000
@@ -10,17 +10,321 @@
*******************************************************************************/
package org.eclipse.jdt.core.tests.compiler.regression;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.eclipse.jdt.core.tests.util.Util;
import org.eclipse.jdt.internal.compiler.batch.Main;
public class BatchCompilerTest extends AbstractRegressionTest {
+ public static final String OUTPUT_DIR_PLACEHOLDER = "---OUTPUT_DIR_PLACEHOLDER---";
+ static final String JRE_HOME_DIR = Util.getJREDirectory();
+
public BatchCompilerTest(String name) {
super(name);
}
public static Test suite() {
+ if (false) {
+ TestSuite suite = new TestSuite();
+ suite.addTest(new BatchCompilerTest("test013"));
+ suite.addTest(new BatchCompilerTest("test014"));
+ suite.addTest(new BatchCompilerTest("test015"));
+ return suite;
+ }
return setupSuite(testClass());
+ // TODO find a way to reduce the number of command line tests to one per
+ // test run (aka do not add 1.3, 1.4, 1.5 supplementary level)
}
+
+ /**
+ * Run a compilation test that is expected to complete successfully and
+ * compare the outputs to expected ones.
+ *
+ * @param testFiles
+ * the source files, given as a suite of file name, file content;
+ * file names are relative to the output directory
+ * @param commandLine
+ * the command line to pass to
+ * {@link Main#compile(String) Main#compile}
+ * @param expectedSuccessOutOutputString
+ * the expected contents of the standard output stream; pass null
+ * to bypass the comparison
+ * @param expectedSuccessErrOutputString
+ * the expected contents of the standard error output stream;
+ * pass null to bypass the comparison
+ * @param shouldFlushOutputDirectory
+ * pass true to get the output directory flushed before the test
+ * runs
+ */
+ protected void runConformTest(String[] testFiles, String commandLine,
+ String expectedSuccessOutOutputString,
+ String expectedSuccessErrOutputString,
+ boolean shouldFlushOutputDirectory) {
+ runTest(true, testFiles, commandLine, expectedSuccessOutOutputString,
+ expectedSuccessErrOutputString, shouldFlushOutputDirectory);
+ }
+
+ /**
+ * Run a compilation test that is expected to fail and compare the outputs
+ * to expected ones.
+ *
+ * @param testFiles
+ * the source files, given as a suite of file name, file content;
+ * file names are relative to the output directory
+ * @param commandLine
+ * the command line to pass to
+ * {@link Main#compile(String) Main#compile}
+ * @param expectedFailureOutOutputString
+ * the expected contents of the standard output stream; pass null
+ * to bypass the comparison
+ * @param expectedFailureErrOutputString
+ * the expected contents of the standard error output stream;
+ * pass null to bypass the comparison
+ * @param shouldFlushOutputDirectory
+ * pass true to get the output directory flushed before the test
+ * runs
+ */
+ protected void runNegativeTest(String[] testFiles, String commandLine,
+ String expectedFailureOutOutputString,
+ String expectedFailureErrOutputString,
+ boolean shouldFlushOutputDirectory) {
+ runTest(false, testFiles, commandLine, expectedFailureOutOutputString,
+ expectedFailureErrOutputString, shouldFlushOutputDirectory);
+ }
+
+ /**
+ * Worker method for runConformTest and runNegativeTest.
+ *
+ * @param shouldCompileOK
+ * set to true if the compiler should compile the given sources
+ * without errors
+ * @param testFiles
+ * the source files, given as a suite of file name, file content;
+ * file names are relative to the output directory
+ * @param commandLine
+ * the command line to pass to
+ * {@link Main#compile(String) Main#compile}
+ * @param expectedOutOutputString
+ * the expected contents of the standard output stream; pass null
+ * to bypass the comparison
+ * @param expectedErrOutputString
+ * the expected contents of the standard error output stream;
+ * pass null to bypass the comparison
+ * @param shouldFlushOutputDirectory
+ * pass true to get the output directory flushed before the test
+ * runs
+ */
+ private void runTest(boolean shouldCompileOK, String[] testFiles, String commandLine,
+ String expectedOutOutputString,
+ String expectedErrOutputString,
+ boolean shouldFlushOutputDirectory) {
+ File outputDirectory = new File(OUTPUT_DIR);
+ if (shouldFlushOutputDirectory)
+ Util.flushDirectoryContent(outputDirectory);
+ try {
+ if (!outputDirectory.isDirectory()) {
+ outputDirectory.mkdirs();
+ }
+ PrintWriter sourceFileWriter;
+ for (int i = 0; i < testFiles.length; i += 2) {
+ String fileName = OUTPUT_DIR + File.separator + testFiles[i];
+ File file = new File(fileName), innerOutputDirectory = file
+ .getParentFile();
+ if (!innerOutputDirectory.isDirectory()) {
+ innerOutputDirectory.mkdirs();
+ }
+ sourceFileWriter = new PrintWriter(new FileOutputStream(file));
+ sourceFileWriter.write(testFiles[i + 1]);
+ sourceFileWriter.close();
+ }
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ String printerWritersNameRoot = OUTPUT_DIR + File.separator + testName();
+ String outFileName = printerWritersNameRoot + "out.txt",
+ errFileName = printerWritersNameRoot + "err.txt";
+ Main batchCompiler;
+ try {
+ batchCompiler = new Main(new PrintWriter(new FileOutputStream(
+ outFileName)), new PrintWriter(new FileOutputStream(
+ errFileName)), false);
+ } catch (FileNotFoundException e) {
+ System.out.println(getClass().getName() + '#' + getName());
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ boolean compileOK;
+ try {
+ compileOK = batchCompiler.compile(Main.tokenize(commandLine));
+ } catch (RuntimeException e) {
+ compileOK = false;
+ System.out.println(getClass().getName() + '#' + getName());
+ e.printStackTrace();
+ throw e;
+ }
+ String outOutputString = Util.fileContent(outFileName),
+ errOutputString = Util.fileContent(errFileName);
+ boolean compareOK = false;
+ if (compileOK == shouldCompileOK) {
+ compareOK = semiNormalizedComparison(expectedOutOutputString,
+ outOutputString, outputDirNormalizer)
+ && semiNormalizedComparison(expectedErrOutputString,
+ errOutputString, outputDirNormalizer);
+ }
+ if (compileOK != shouldCompileOK || !compareOK) {
+ System.out.println(getClass().getName() + '#' + getName());
+ for (int i = 0; i < testFiles.length; i += 2) {
+ System.out.print(testFiles[i]);
+ System.out.println(" [");
+ System.out.println(testFiles[i + 1]);
+ System.out.println("]");
+ }
+ }
+ if (compileOK != shouldCompileOK)
+ System.out.println(errOutputString);
+ if (compileOK == shouldCompileOK && !compareOK) {
+ System.out.println(
+ "------------ [START OUT] ------------\n"
+ + "------------- Expected: -------------\n"
+ + expectedOutOutputString
+ + "\n------------- but was: -------------\n"
+ + outOutputString
+ + "\n--------- (cut and paste:) ----------\n"
+ + Util.displayString(outputDirNormalizer
+ .normalized(outOutputString))
+ + "\n------------- [END OUT] -------------\n"
+ + "------------ [START ERR] ------------\n"
+ + "------------- Expected: -------------\n"
+ + expectedErrOutputString
+ + "\n------------- but was: -------------\n"
+ + errOutputString
+ + "\n--------- (cut and paste:) ----------\n"
+ + Util.displayString(outputDirNormalizer
+ .normalized(errOutputString))
+ + "\n------------- [END ERR] -------------\n");
+ }
+ if (shouldCompileOK)
+ assertTrue("Unexpected problems: " + errOutputString, compileOK);
+ else
+ assertTrue("Unexpected success: " + errOutputString, !compileOK);
+ assertTrue("Unexpected output for invocation with arguments ["
+ + commandLine + "]:\n--[START]--\n" + outOutputString + "\n"
+ + errOutputString + "\n---[END]---\n", compareOK);
+ }
+
+ /**
+ * Abstract normalizer for output comparison. This class merely embodies a
+ * chain of responsibility, plus the signature of the method of interest
+ * here, that is {@link #normalized(String) normalized}.
+ */
+ private static abstract class Normalizer {
+ private Normalizer nextInChain;
+ Normalizer(Normalizer nextInChain) {
+ this.nextInChain = nextInChain;
+ }
+ String normalized(String originalValue) {
+ if (nextInChain == null)
+ return originalValue;
+ else
+ return nextInChain.normalized(originalValue);
+ }
+ }
+
+ /**
+ * This normalizer replaces occurrences of a given string with a given
+ * placeholder.
+ */
+ private static class StringNormalizer extends Normalizer {
+ private String match;
+ private int matchLength;
+ private String placeholder;
+ StringNormalizer(Normalizer nextInChain, String match, String placeholder) {
+ super(nextInChain);
+ this.match = match;
+ this.matchLength = match.length();
+ this.placeholder = placeholder;
+ }
+ String normalized(String originalValue) {
+ StringBuffer normalizedValueBuffer = new StringBuffer(originalValue);
+ int nextOccurrenceIndex;
+ while ((nextOccurrenceIndex = normalizedValueBuffer.indexOf(match)) != -1)
+ normalizedValueBuffer.replace(nextOccurrenceIndex,
+ nextOccurrenceIndex + matchLength, placeholder);
+ return super.normalized(normalizedValueBuffer.toString());
+ }
+ }
+
+ /**
+ * This normalizer replaces the whole classpaths section of a log file with
+ * a normalized placeholder.
+ */
+ private static class XMLClasspathsSectionNormalizer extends Normalizer {
+ XMLClasspathsSectionNormalizer() {
+ super(null);
+ }
+ XMLClasspathsSectionNormalizer(Normalizer nextInChain) {
+ super(nextInChain);
+ }
+ String normalized(String originalValue) {
+ StringBuffer normalizedValueBuffer = new StringBuffer(originalValue);
+ int classpathsStartTagStart = normalizedValueBuffer
+ .indexOf(""), classpathsEndTagStart = normalizedValueBuffer
+ .indexOf("");
+ if (classpathsStartTagStart != -1 && classpathsEndTagStart != -1
+ && classpathsStartTagStart < classpathsEndTagStart)
+ normalizedValueBuffer.replace(classpathsStartTagStart + 12,
+ classpathsEndTagStart, "NORMALIZED SECTION");
+ return super.normalized(normalizedValueBuffer.toString());
+ }
+ }
+
+ /**
+ * Normalizer instance that replaces occurrences of OUTPUT_DIR with
+ * OUTPUT_DIR_PLACEHOLDER.
+ */
+ private static Normalizer outputDirNormalizer = new StringNormalizer(null,
+ OUTPUT_DIR, OUTPUT_DIR_PLACEHOLDER);
+ /**
+ * Normalizer instance that replaces the list of concrete classpaths XML
+ * elements of an XML log file with a placeholder, and occurrences of
+ * OUTPUT_DIR with OUTPUT_DIR_PLACEHOLDER.
+ */
+ private static Normalizer xmlClasspathsNormalizer = new StringNormalizer(
+ new XMLClasspathsSectionNormalizer(), OUTPUT_DIR,
+ OUTPUT_DIR_PLACEHOLDER);
+
+
+ /**
+ * Return true if and only if the two strings passed as parameters compare
+ * equal, modulo the transformation of the second string by a normalizer
+ * passed in parameter. This is meant to erase the variations of subparts of
+ * the compared strings in function of the test machine, the user account,
+ * etc.
+ *
+ * @param keep
+ * the first string to compare, gets compared as it is
+ * @param normalize
+ * the second string to compare, passed through the normalizer
+ * before comparison
+ * @param normalizer
+ * the transformation applied to normalize
+ * @return true if keep and normalize compare equal after normalize has been
+ * normalized
+ */
+ private boolean semiNormalizedComparison(String keep, String normalize,
+ Normalizer normalizer) {
+ if (keep == null)
+ return normalize == null;
+ if (normalize == null)
+ return false;
+ return keep.equals(normalizer.normalized(normalize));
+ }
+
public void test01() {
String commandLine = "-classpath \"D:/a folder\";d:/jdk1.4/jre/lib/rt.jar -1.4 -preserveAllLocals -g -verbose d:/eclipse/workspaces/development2.0/plugins/Bar/src2/ -d d:/test";
@@ -117,6 +421,693 @@
expected,
result);
}
+// test the tester - runConformTest
+public void test007(){
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.util.List;\n" +
+ "\n" +
+ "@SuppressWarnings(\"all\"//$NON-NLS-1$\n" +
+ ")\n" +
+ "public class X {\n" +
+ " public static void main(String[] args) {\n" +
+ " if (false) {\n" +
+ " ;\n" +
+ " } else {\n" +
+ " }\n" +
+ " // Zork z;\n" +
+ " }\n" +
+ "}"
+ },
+ "\"" + OUTPUT_DIR + File.separator + "X.java\""
+ + " -1.5 -g -preserveAllLocals"
+ + " -bootclasspath " + JRE_HOME_DIR + "/lib/rt.jar"
+ + " -cp " + JRE_HOME_DIR + "/lib/jce.jar"
+ + " -verbose -warn:+deprecation,syntheticAccess,uselessTypeCheck,unsafe,finalBound,unusedLocal"
+ + " -proceedOnError -referenceInfo -d \"" + OUTPUT_DIR + "\"",
+ "[1 .class file generated]\r\n",
+ "----------\r\n" +
+ "1. WARNING in ---OUTPUT_DIR_PLACEHOLDER---\\X.java\r\n" +
+ " (at line 1)\r\n" +
+ " import java.util.List;\r\n" +
+ " ^^^^^^^^^^^^^^\r\n" +
+ "The import java.util.List is never used\r\n" +
+ "----------\r\n" +
+ "1 problem (1 warning)", true);
+}
+// test the tester - runNegativeTest
+public void test008(){
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.util.List;\n" +
+ "\n" +
+ "@SuppressWarnings(\"all\"//$NON-NLS-1$\n" +
+ ")\n" +
+ "public class X {\n" +
+ " public static void main(String[] args) {\n" +
+ " if (false) {\n" +
+ " ;\n" +
+ " } else {\n" +
+ " }\n" +
+ " Zork z;\n" +
+ " }\n" +
+ "}"
+ },
+ "\"" + OUTPUT_DIR + File.separator + "X.java\""
+ + " -1.5 -g -preserveAllLocals"
+ + " -bootclasspath " + JRE_HOME_DIR + "/lib/rt.jar"
+ + " -cp " + JRE_HOME_DIR + "/lib/jce.jar"
+ + " -verbose -warn:+deprecation,syntheticAccess,uselessTypeCheck,unsafe,finalBound,unusedLocal"
+ + " -proceedOnError -referenceInfo -d \"" + OUTPUT_DIR + "\"",
+ "[1 .class file generated]\r\n",
+ "----------\r\n" +
+ "1. WARNING in ---OUTPUT_DIR_PLACEHOLDER---\\X.java\r\n" +
+ " (at line 1)\r\n" +
+ " import java.util.List;\r\n" +
+ " ^^^^^^^^^^^^^^\r\n" +
+ "The import java.util.List is never used\r\n" +
+ "----------\r\n" +
+ "----------\r\n" +
+ "2. ERROR in ---OUTPUT_DIR_PLACEHOLDER---\\X.java\r\n" +
+ " (at line 11)\r\n" +
+ " Zork z;\r\n" +
+ " ^^^^\r\n" +
+ "Zork cannot be resolved to a type\r\n" +
+ "----------\r\n" +
+ "2 problems (1 error, 1 warning)", true);
+}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=92398 -- a case that works, another that does not
+// revisit this test case depending on https://bugs.eclipse.org/bugs/show_bug.cgi?id=95349
+public void test009(){
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "/** */\n" +
+ "public class X {\n" +
+ " OK1 ok1;\n" +
+ " OK2 ok2;\n" +
+ " Warn warn;\n" +
+ " KO ko;\n" +
+ " Zork z;\r\n" +
+ "}",
+ "OK1.java",
+ "/** */\n" +
+ "public class OK1 {\n" +
+ " // empty\n" +
+ "}",
+ "OK2.java",
+ "/** */\n" +
+ "public class OK2 {\n" +
+ " // empty\n" +
+ "}",
+ "Warn.java",
+ "/** */\n" +
+ "public class Warn {\n" +
+ " // empty\n" +
+ "}",
+ "KO.java",
+ "/** */\n" +
+ "public class KO {\n" +
+ " // empty\n" +
+ "}",
+ },
+ "\"" + OUTPUT_DIR + File.separator + "X.java\""
+ + " -1.5 -g -preserveAllLocals"
+ + " -cp \"" + OUTPUT_DIR + "[+OK2.java;~Warn.java;-KO.java]\""
+ + " -verbose -warn:+deprecation,syntheticAccess,uselessTypeCheck,unsafe,finalBound,unusedLocal"
+ + " -proceedOnError -referenceInfo -d \"" + OUTPUT_DIR + "\"",
+ "[5 .class files generated]\r\n",
+ "----------\r\n" +
+ "1. WARNING in ---OUTPUT_DIR_PLACEHOLDER---\\X.java\r\n" +
+ " (at line 5)\r\n" +
+ " Warn warn;\r\n" +
+ " ^^^^\r\n" +
+ "Discouraged access: Warn\r\n" +
+ "----------\r\n" +
+ "----------\r\n" +
+ "2. WARNING in ---OUTPUT_DIR_PLACEHOLDER---\\X.java\r\n" +
+ " (at line 6)\r\n" +
+ " KO ko;\r\n" +
+ " ^^\r\n" +
+ "Access restriction: KO\r\n" +
+ "----------\r\n" +
+ "----------\r\n" +
+ "3. ERROR in ---OUTPUT_DIR_PLACEHOLDER---\\X.java\r\n" +
+ " (at line 7)\r\n" +
+ " Zork z;\r\n" +
+ " ^^^^\r\n" +
+ "Zork cannot be resolved to a type\r\n" +
+ "----------\r\n" +
+ "3 problems (1 error, 2 warnings)",
+ true);
+}
+// command line - no user classpath nor bootclasspath
+public void test010(){
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.util.List;\n" +
+ "\n" +
+ "@SuppressWarnings(\"all\"//$NON-NLS-1$\n" +
+ ")\n" +
+ "public class X {\n" +
+ " public static void main(String[] args) {\n" +
+ " if (false) {\n" +
+ " ;\n" +
+ " } else {\n" +
+ " }\n" +
+ " // Zork z;\n" +
+ " }\n" +
+ "}"
+ },
+ "\"" + OUTPUT_DIR + File.separator + "X.java\""
+ + " -1.5 -g -preserveAllLocals"
+ + " -verbose -warn:+deprecation,syntheticAccess,uselessTypeCheck,unsafe,finalBound,unusedLocal"
+ + " -proceedOnError -referenceInfo -d \"" + OUTPUT_DIR + "\"",
+ "[1 .class file generated]\r\n",
+ "----------\r\n" +
+ "1. WARNING in ---OUTPUT_DIR_PLACEHOLDER---\\X.java\r\n" +
+ " (at line 1)\r\n" +
+ " import java.util.List;\r\n" +
+ " ^^^^^^^^^^^^^^\r\n" +
+ "The import java.util.List is never used\r\n" +
+ "----------\r\n" +
+ "1 problem (1 warning)", true);
+}
+// command line - unusual classpath (ends with ';', still OK)
+public void test011(){
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "/** */\n" +
+ "public class X {\n" +
+ "}",
+ },
+ "\"" + OUTPUT_DIR + File.separator + "X.java\""
+ + " -1.5 -g -preserveAllLocals"
+ + " -cp \"" + OUTPUT_DIR + "[+**/OK2.java;~**/Warn.java;-KO.java]"
+ + "\";"
+ + " -proceedOnError -referenceInfo -d \"" + OUTPUT_DIR + "\"",
+ "",
+ "",
+ true);
+}
+// command line - help
+public void test012(){
+ this.runConformTest(
+ new String[0],
+ " -help -showversion -referenceInfo",
+ "Eclipse Java Compiler 0.558, pre-3.1.0 release candidate-1, Copyright IBM Corp 2000, 2005. All rights reserved.\n" +
+ " \n" +
+ " Usage: