/******************************************************************************* * Copyright (c) 2000, 2007 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.core.tests.compiler.regression; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.io.StringReader; import java.text.MessageFormat; import java.util.ArrayList; import junit.framework.Test; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.compiler.InvalidInputException; import org.eclipse.jdt.core.tests.util.Util; import org.eclipse.jdt.internal.compiler.batch.ClasspathLocation; 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(); private static final Main MAIN = new Main(null, null, false); static { // TESTS_NAMES = new String[] { "test000" }; // TESTS_NUMBERS = new int[] { 24 }; // TESTS_RANGE = new int[] { 107, -1 }; } public BatchCompilerTest(String name) { super(name); } /** * This test suite only needs to be run on one compliance. * As it includes some specific 1.5 tests, it must be used with a least a 1.5 VM * and not be duplicated in general test suite. * @see TestAll */ public static Test suite() { return buildUniqueComplianceTestSuite(testClass(), COMPLIANCE_1_5); } private String getLibraryClasses() { String[] paths = Util.getJavaClassLibs(); StringBuffer buffer = new StringBuffer(); for (int i = 0, max = paths.length; i < max; i++) { if (i != 0) { buffer.append(File.pathSeparatorChar); } buffer.append(paths[i]); } return String.valueOf(buffer); } private String getJCEJar() { if (Util.isMacOS()) { return JRE_HOME_DIR + "/../Classes/jce.jar"; } return JRE_HOME_DIR + "/lib/jce.jar"; } private String getExtDirectory() { return JRE_HOME_DIR + "/lib/ext"; } /** * 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; PrintWriter out = null; PrintWriter err = null; boolean compileOK; try { try { out = new PrintWriter(new FileOutputStream(outFileName)); err = new PrintWriter(new FileOutputStream(errFileName)); batchCompiler = new Main(out, err, false); } catch (FileNotFoundException e) { System.out.println(getClass().getName() + '#' + getName()); e.printStackTrace(); throw new RuntimeException(e); } try { final String[] tokenizeCommandLine = Main.tokenize(commandLine); compileOK = batchCompiler.compile(tokenizeCommandLine); } catch (RuntimeException e) { compileOK = false; System.out.println(getClass().getName() + '#' + getName()); e.printStackTrace(); throw e; } } finally { if (out != null) out.close(); if (err != null) err.close(); } String outOutputString = Util.fileContent(outFileName), errOutputString = Util.fileContent(errFileName); boolean compareOK = false, outCompareOK = false, errCompareOK = false; if (compileOK == shouldCompileOK) { compareOK = (outCompareOK = semiNormalizedComparison(expectedOutOutputString, outOutputString, outputDirNormalizer)) && (errCompareOK = 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); if (!outCompareOK) { // calling assertEquals to benefit from the comparison UI // (need appropriate exception) assertEquals( "Unexpected standard output for invocation with arguments [" + commandLine + "]", expectedOutOutputString, outOutputString); } if (!errCompareOK) { assertEquals( "Unexpected error output for invocation with arguments [" + commandLine + "]", expectedErrOutputString, errOutputString); } } private void runClasspathTest(String classpathInput, String[] expectedClasspathEntries, String expectedError) { File outputDirectory = new File(OUTPUT_DIR); if (!outputDirectory.isDirectory()) { outputDirectory.mkdirs(); } ArrayList paths = new ArrayList(Main.DEFAULT_SIZE_CLASSPATH); try { (new Main(new PrintWriter(System.out), new PrintWriter(System.err), true)). processPathEntries(Main.DEFAULT_SIZE_CLASSPATH, paths, classpathInput, null /* customEncoding */, true /* isSourceOnly */, false /* rejectDestinationPathOnJars*/); } catch (InvalidInputException e) { // e.printStackTrace(); if (expectedError == null) { fail("unexpected invalid input exception: " + e.getMessage()); } else if (! expectedError.equals(e.getMessage())) { System.out.println("\"" + e.getMessage() + "\""); assertEquals(expectedError, e.getMessage()); } return; } if (expectedError == null) { int l = paths.size(); assertEquals("unexpected classpaths entries number: ", expectedClasspathEntries == null ? 0 : expectedClasspathEntries.length / 3, l); for (int i = 0, j = 0; i < l ; i++) { ClasspathLocation result = (ClasspathLocation) paths.get(i); String expected = expectedClasspathEntries[j++]; String actual = result.toString(); if (! actual.equals("ClasspathDirectory " + expected + File.separator) && ! actual.equals("Classpath for jar file " + expected)) { assertEquals("dir/jar " + expected, actual); } expected = expectedClasspathEntries[j++]; if (result.accessRuleSet == null) { assertNull("actual access rule is null instead of <" + expected +">", expected); } else if (! result.accessRuleSet.toString(false). startsWith("AccessRuleSet " + expected)) { System.out.println("\"" + result.accessRuleSet.toString(false) + "\""); fail("inappropriate rules (expected " + expected + ", got " + result.accessRuleSet.toString(false)); } expected = expectedClasspathEntries[j++]; if (expected == null) { assertNull(result.destinationPath); } else if (expected == Main.NONE && result.destinationPath != Main.NONE) { fail("expected 'none' output directory"); } else if (! expected.equals(result.destinationPath)) { System.out.println("\"" + result.destinationPath + "\""); assertEquals(expected, result.destinationPath); } } } else { fail("missing error: " + expectedError); } } /** * Check that no line of message extends beyond width columns. Tabs count for * 4 characters. * @param message the message to check * @param width the maximum number of columns for the message */ private void checkWidth(String message, int width) { BufferedReader reader = new BufferedReader( new StringReader(message.replaceAll("\t", " "))); String line; try { while ((line = reader.readLine()) != null) { assertTrue("line exceeds " + width + "characters: " + line, line.length() <= width); } } catch (IOException e) { // should never happen on a StringReader } } /** * 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) { String result; if (nextInChain == null) result = Util.convertToIndependantLineDelimiter(originalValue); else result = nextInChain.normalized(originalValue); return result; } } /** * 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) { String result; StringBuffer normalizedValueBuffer = new StringBuffer(originalValue); int nextOccurrenceIndex; while ((nextOccurrenceIndex = normalizedValueBuffer.indexOf(match)) != -1) normalizedValueBuffer.replace(nextOccurrenceIndex, nextOccurrenceIndex + matchLength, placeholder); result = super.normalized(normalizedValueBuffer.toString()); return result; } } /** * 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) { String result; 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"); result = super.normalized(normalizedValueBuffer.toString()); return result; } } /** * This normalizer removes a selected range of lines from a log file. */ private static class LinesRangeNormalizer extends Normalizer { private int first, number; LinesRangeNormalizer() { super(null); first = number = 0; } LinesRangeNormalizer(Normalizer nextInChain) { super(nextInChain); first = number = 0; } /** * Make a new normalizer able to suppress a range of lines delimited by * "\n" sequences from a log file (or another string). * * @param nextInChain * the next normalizer in the chain of responsibility; pass * null if none is needed * @param firstLineToRemove * the index of the first line to remove, starting at 0 * @param linesNumber * the number or lines to remove; if 0, no other * transformation occurs than those operated by nextInChain * (if any) */ LinesRangeNormalizer(Normalizer nextInChain, int firstLineToRemove, int linesNumber) { super(nextInChain); first = firstLineToRemove; number = linesNumber >= 0 ? linesNumber : 0; } String normalized(String originalValue) { String result; if (number == 0 || originalValue.length() == 0) result = super.normalized(originalValue); else { final int START = 0, KEEPING = 1, KEEPING_R = 2, SKIPING = 3, SKIPING_R = 4, END = 5, ERROR = 6; int state = START, currentLineIndex = 0, currentCharIndex = 0, sourceLength; char currentChar = '\0'; if (first <= 0) state = SKIPING; else state = KEEPING; StringBuffer normalizedValueBuffer = new StringBuffer(), source = new StringBuffer( originalValue); sourceLength = source.length(); while (state != END && state != ERROR) { if (currentCharIndex < sourceLength) { currentChar = source.charAt(currentCharIndex++); switch (currentChar) { case '\r': switch (state) { case KEEPING: normalizedValueBuffer.append(currentChar); state = KEEPING_R; break; case SKIPING: state = SKIPING_R; break; default: state = ERROR; } break; case '\n': currentLineIndex++; switch (state) { case KEEPING: // tolerate Linux line delimiters case KEEPING_R: normalizedValueBuffer.append(currentChar); if (currentLineIndex == first) { state = SKIPING; } break; case SKIPING: // tolerate Linux line delimiters case SKIPING_R: // in effect, we tolerate too big first and number // values if (currentLineIndex >= first + number) { if (currentCharIndex < sourceLength) normalizedValueBuffer.append(source .substring(currentCharIndex)); state = END; } else { state = SKIPING; } break; default: state = ERROR; } break; default: switch (state) { case KEEPING: normalizedValueBuffer.append(currentChar); break; case SKIPING: break; default: state = ERROR; } } } else if (currentChar == '\n') state = END; else state = ERROR; } if (state == ERROR) normalizedValueBuffer .append("UNEXPECTED ERROR in LinesRangeNormalizer"); result = super.normalized(normalizedValueBuffer.toString()); } return result; } } /** * Normalizer instance that replaces occurrences of OUTPUT_DIR with * OUTPUT_DIR_PLACEHOLDER and changes file separator to / if the * platform file separator is different from /. */ private static Normalizer outputDirNormalizer; static { if (File.separatorChar == '/') { outputDirNormalizer = new StringNormalizer( null, OUTPUT_DIR, OUTPUT_DIR_PLACEHOLDER); } else { outputDirNormalizer = new StringNormalizer( new StringNormalizer( null, File.separator, "/"), OUTPUT_DIR, OUTPUT_DIR_PLACEHOLDER); } } /** * Normalizer instance for non XML log files. */ private static Normalizer textLogsNormalizer = new StringNormalizer( new XMLClasspathsSectionNormalizer(new LinesRangeNormalizer(null, 0, 2)), OUTPUT_DIR, OUTPUT_DIR_PLACEHOLDER); /** * Normalizer instance for XML log files. */ private static Normalizer xmlLogsNormalizer = new StringNormalizer( new XMLClasspathsSectionNormalizer(new LinesRangeNormalizer(null, 1, 1)), 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)); return equals(keep, normalizer.normalized(normalize)); } private static boolean equals(String a, String b) { StringBuffer aBuffer = new StringBuffer(a), bBuffer = new StringBuffer(b); int length = aBuffer.length(), bLength; boolean result = true; if (length != (bLength = bBuffer.length())) { System.err.println("a and b lengths differ"); if (length > bLength) { length = bLength; } result = false; } for (int i = 0; i < length; i++) if (aBuffer.charAt(i) != bBuffer.charAt(i)) { int beforeStart = i - 5, beforeEnd = i - 1, afterStart = i + 1, afterEnd = i + 5; if (beforeStart < 0) { beforeStart = 0; if (beforeEnd < 0) beforeEnd = 0; } if (afterEnd >= length) { afterEnd = length - 1; if (afterStart >= length) afterStart = length - 1; } System.err.println("a and b differ at rank: " + i + "\na: ..." + aBuffer.substring(beforeStart, beforeEnd) + "<" + aBuffer.charAt(i) + ">" + aBuffer.substring(afterStart, afterEnd) + "..." + "\nb: ..." + bBuffer.substring(beforeStart, beforeEnd) + "<" + bBuffer.charAt(i) + ">" + bBuffer.substring(afterStart, afterEnd) + "..."); return false; } return result; // may be false if one of the strings equals the beginning // of the other one, which is longer anyway } public void test001() { 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"; String expected = " <-classpath> <-1.4> <-preserveAllLocals> <-g> <-verbose> <-d> "; String[] args = Main.tokenize(commandLine); StringBuffer buffer = new StringBuffer(30); for (int i = 0; i < args.length; i++){ buffer.append(" <"+args[i]+">"); } String result = buffer.toString(); //System.out.println(Util.displayString(result, 2)); assertEquals("incorrect tokenized command line", expected, result); } public void test002() { String commandLine = "-classpath \"a folder\";\"b folder\""; String expected = " <-classpath> "; String[] args = Main.tokenize(commandLine); StringBuffer buffer = new StringBuffer(30); for (int i = 0; i < args.length; i++){ buffer.append(" <"+args[i]+">"); } String result = buffer.toString(); //System.out.println(Util.displayString(result, 2)); assertEquals("incorrect tokenized command line", expected, result); } public void test003() { String commandLine = "-classpath \"a folder;b folder\""; String expected = " <-classpath> "; String[] args = Main.tokenize(commandLine); StringBuffer buffer = new StringBuffer(30); for (int i = 0; i < args.length; i++){ buffer.append(" <"+args[i]+">"); } String result = buffer.toString(); //System.out.println(Util.displayString(result, 2)); assertEquals("incorrect tokenized command line", expected, result); } public void test004() { String commandLine = "\"d:/tmp A/\"A.java -classpath \"d:/tmp A\";d:/jars/rt.jar -nowarn -time -g -d d:/tmp"; String expected = " <-classpath> <-nowarn> <-time> <-g> <-d> "; String[] args = Main.tokenize(commandLine); StringBuffer buffer = new StringBuffer(30); for (int i = 0; i < args.length; i++){ buffer.append(" <"+args[i]+">"); } String result = buffer.toString(); //System.out.println(Util.displayString(result, 2)); assertEquals("incorrect tokenized command line", expected, result); } public void test005() { String commandLine = "\"d:/tmp A/\"A.java -classpath d:/jars/rt.jar;\"d:/tmp A\";\"toto\" -nowarn -time -g -d d:/tmp"; String expected = " <-classpath> <-nowarn> <-time> <-g> <-d> "; String[] args = Main.tokenize(commandLine); StringBuffer buffer = new StringBuffer(30); for (int i = 0; i < args.length; i++){ buffer.append(" <"+args[i]+">"); } String result = buffer.toString(); //System.out.println(Util.displayString(result, 2)); assertEquals("incorrect tokenized command line", expected, result); } public void test006() { String commandLine = "\"d:/tmp A/A.java\" -classpath d:/jars/rt.jar;\"d:/tmp A\";d:/tmpB/ -nowarn -time -g -d d:/tmp"; String expected = " <-classpath> <-nowarn> <-time> <-g> <-d> "; String[] args = Main.tokenize(commandLine); StringBuffer buffer = new StringBuffer(30); for (int i = 0; i < args.length; i++){ buffer.append(" <"+args[i]+">"); } String result = buffer.toString(); //System.out.println(Util.displayString(result, 2)); assertEquals("incorrect tokenized command line", 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 " + "\"" + getLibraryClasses() + "\"" + " -cp " + "\"" + getJCEJar() + "\"" + " -warn:+deprecation,syntheticAccess,uselessTypeCheck,unsafe,finalBound,unusedLocal" + " -verbose -proceedOnError -referenceInfo -d \"" + OUTPUT_DIR + "\"", "[parsing ---OUTPUT_DIR_PLACEHOLDER---/X.java - #1/1]\n" + "[reading java/lang/Object.class]\n" + "[analyzing ---OUTPUT_DIR_PLACEHOLDER---/X.java - #1/1]\n" + "[reading java/util/List.class]\n" + "[reading java/lang/SuppressWarnings.class]\n" + "[reading java/lang/String.class]\n" + "[writing X.class - #1]\n" + "[completed ---OUTPUT_DIR_PLACEHOLDER---/X.java - #1/1]\n" + "[1 unit compiled]\n" + "[1 .class file generated]\n", "", // changed with bug 123522: now the SuppressWarning upon the first type // influences warnings on unused imports 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 " + "\"" + getLibraryClasses() + "\"" + " -cp " + "\"" + getJCEJar() + "\"" + " -warn:+deprecation,syntheticAccess,uselessTypeCheck,unsafe,finalBound,unusedLocal" + " -proceedOnError -referenceInfo -d \"" + OUTPUT_DIR + "\"", "", "----------\n" + "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/X.java (at line 11)\n" + " Zork z;\n" + " ^^^^\n" + "Zork cannot be resolved to a type\n" + "----------\n" + "1 problem (1 error)", 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;\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" + File.pathSeparator + "~Warn" + File.pathSeparator + "-KO]\"" + " -warn:+deprecation,syntheticAccess,uselessTypeCheck,unsafe,finalBound,unusedLocal" + " -proceedOnError -referenceInfo -d \"" + OUTPUT_DIR + "\"", "", "----------\n" + "1. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/X.java (at line 5)\n" + " Warn warn;\n" + " ^^^^\n" + "Discouraged access: The type Warn is not accessible due to restriction on classpath entry ---OUTPUT_DIR_PLACEHOLDER---\n" + "----------\n" + "2. WARNING in ---OUTPUT_DIR_PLACEHOLDER---/X.java (at line 6)\n" + " KO ko;\n" + " ^^\n" + "Access restriction: The type KO is not accessible due to restriction on classpath entry ---OUTPUT_DIR_PLACEHOLDER---\n" + "----------\n" + "3. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/X.java (at line 7)\n" + " Zork z;\n" + " ^^^^\n" + "Zork cannot be resolved to a type\n" + "----------\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 + "\"", "[parsing ---OUTPUT_DIR_PLACEHOLDER---/X.java - #1/1]\n" + "[reading java/lang/Object.class]\n" + "[analyzing ---OUTPUT_DIR_PLACEHOLDER---/X.java - #1/1]\n" + "[reading java/util/List.class]\n" + "[reading java/lang/SuppressWarnings.class]\n" + "[reading java/lang/String.class]\n" + "[writing X.class - #1]\n" + "[completed ---OUTPUT_DIR_PLACEHOLDER---/X.java - #1/1]\n" + "[1 unit compiled]\n" + "[1 .class file generated]\n", "", true); } // command line - unusual classpath (ends with ';', still OK) public void test011_classpath(){ 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;~**/Warn;-KO]" + "\"" + File.pathSeparator + " -proceedOnError -referenceInfo -d \"" + OUTPUT_DIR + "\"", "", "", true); } // command line - help // amended for https://bugs.eclipse.org/bugs/show_bug.cgi?id=141512 (checking // width) public void test012(){ final String expectedOutput = "{0} {1}\n" + "{2}\n" + " \n" + " Usage: \n" + " If directories are specified, then their source contents are compiled.\n" + " Possible options are listed below. Options enabled by default are prefixed\n" + " with ''+''.\n" + " \n" + " Classpath options:\n" + " -cp -classpath \n" + " specify location for application classes and sources.\n" + " Each directory or file can specify access rules for\n" + " types between ''['' and '']'' (e.g. [-X] to forbid\n" + " access to type X, [~X] to discourage access to type X,\n" + " [+p/X" + File.pathSeparator + "-p/*] to forbid access to all types in package p\n" + " but allow access to p/X)\n" + " -bootclasspath \n" + " specify location for system classes. Each directory or\n" + " file can specify access rules for types between ''[''\n" + " and '']''\n" + " -sourcepath \n" + " specify location for application sources. Each directory\n" + " or file can specify access rules for types between ''[''\n" + " and '']''. Each directory can further specify a specific\n" + " destination directory using a ''-d'' option between ''[''\n" + " and '']''; this overrides the general ''-d'' option.\n" + " .class files created from source files contained in a\n" + " jar file are put in the user.dir folder in case no\n" + " general ''-d'' option is specified. zip/jar files cannot\n" + " override the general ''-d'' option\n" + " -extdirs \n" + " specify location for extension zip/jar files\n" + " -endorseddirs \n" + " specify location for endorsed zip/jar files\n" + " -d destination directory (if omitted, no directory is\n" + " created); this option can be overridden per source\n" + " directory\n" + " -d none generate no .class files\n" + " -encoding specify custom encoding for all sources. Each\n" + " file/directory can override it when suffixed with\n" + " ''['''']'' (e.g. X.java[utf8])\n" + " \n" + " Compliance options:\n" + " -1.3 use 1.3 compliance (-source 1.3 -target 1.1)\n" + " -1.4 + use 1.4 compliance (-source 1.3 -target 1.2)\n" + " -1.5 -5 -5.0 use 1.5 compliance (-source 1.5 -target 1.5)\n" + " -1.6 -6 -6.0 use 1.6 compliance (-source 1.6 -target 1.6)\n" + " -1.7 -7 -7.0 use 1.7 compliance (-source 1.7 -target 1.7)\n" + " -source set source level: 1.3 to 1.7 (or 5, 5.0, etc)\n" + " -target set classfile target: 1.1 to 1.7 (or 5, 5.0, etc)\n" + " \n" + " Warning options:\n" + " -deprecation + deprecation outside deprecated code (equivalent to\n" + " -warn:+deprecation)\n" + " -nowarn -warn:none disable all warnings\n" + " -?:warn -help:warn display advanced warning options\n" + " \n" + " Debug options:\n" + " -g[:lines,vars,source] custom debug info\n" + " -g:lines,source + both lines table and source debug info\n" + " -g all debug info\n" + " -g:none no debug info\n" + " -preserveAllLocals preserve unused local vars for debug purpose\n" + " \n" + " Annotation processing options:\n" + " These options are meaningful only in a 1.6 environment.\n" + " -Akey[=value] annotation processors options that are made to\n" + " annotation processors. key are identifiers separated\n" + " by ''.''.\n" + " -processorpath \n" + " specify locations where to find annotation processors\n" + " If this option is not used, the classpath will be\n" + " searched for processors.\n" + " -processor \n" + " Qualified names of the annotation processors to run.\n" + " This bypasses the default annotation discovery process\n" + " -proc:only run annotation processors, but do not compile\n" + " -proc:none perform compilation but do not run annotation\n" + " processors\n" + " -s specify a directory where to put the generated source\n" + " files\n" + " -XprintProcessorInfo print information about which annotations and which\n" + " elements a processor is asked to process\n" + " -XprintRounds print information about annotation processing rounds.\n" + " -classNames \n" + " Qualified names of the classes that need\n" + " to be processed\n" + " \n" + " Advanced options:\n" + " @ read command line arguments from file\n" + " -maxProblems max number of problems per compilation unit (100 by\n" + " default)\n" + " -log log to a file. If the file extension is ''.xml'', then\n" + " the log will be a xml file.\n" + " -proceedOnError do not stop at first error, dumping class files with\n" + " problem methods\n" + " -verbose enable verbose output\n" + " -referenceInfo compute reference info\n" + " -progress show progress (only in -log mode)\n" + " -time display speed information \n" + " -noExit do not call System.exit(n) at end of compilation (n==0\n" + " if no error)\n" + " -repeat repeat compilation process times for perf analysis\n" + " -inlineJSR inline JSR bytecode (implicit if target >= 1.5)\n" + " -enableJavadoc consider references in javadoc\n" + " -Xemacs used to enable emacs-style output in the console.\n" + " It does not affect the xml log output\n" + " \n" + " -? -help print this help message\n" + " -v -version print compiler version\n" + " -showversion print compiler version and continue\n" + " \n" + " Ignored options:\n" + " -J