1/* 2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24/** 25 * @test 26 * @bug 8132562 27 * @summary javac fails with CLASSPATH with double-quotes as an environment variable 28 * @library /tools/lib 29 * @modules jdk.compiler/com.sun.tools.javac.api 30 * jdk.compiler/com.sun.tools.javac.main 31 * jdk.compiler/com.sun.tools.javac.util 32 * @build toolbox.ToolBox toolbox.JavacTask 33 * @run main ClassPathWithDoubleQuotesTest 34*/ 35 36import java.io.File; 37import java.nio.file.Path; 38import java.nio.file.Paths; 39 40import com.sun.tools.javac.util.Assert; 41import toolbox.TestRunner; 42import toolbox.JarTask; 43import toolbox.JavacTask; 44import toolbox.Task; 45import toolbox.ToolBox; 46 47public class ClassPathWithDoubleQuotesTest extends TestRunner { 48 49 ToolBox tb; 50 51 private static final String ASrc = "public class A { J j; B b;}"; 52 private static final String BSrc = "public class B {}"; 53 private static final String JarSrc = "public class J {}"; 54 private static final String[] jarArgs = {"cf", "test/jarOut/J.jar", "-C", "test/jarSrc", "J.java"}; 55 public static final String NEW_LINE = System.getProperty("line.separator"); 56 private static final String expectedFailureOutput1 = 57 "A.java:1:18: compiler.err.cant.resolve.location: kindname.class, J, , , (compiler.misc.location: kindname.class, A, null)" + NEW_LINE + 58 "A.java:1:23: compiler.err.cant.resolve.location: kindname.class, B, , , (compiler.misc.location: kindname.class, A, null)" + NEW_LINE + 59 "2 errors" + NEW_LINE; 60 private static final String expectedFailureOutput2A = 61 "- compiler.warn.invalid.path: \"test/jarOut/J.jar" + NEW_LINE + 62 "- compiler.warn.invalid.path: test/src\"" + NEW_LINE + 63 "A.java:1:18: compiler.err.cant.resolve.location: kindname.class, J, , , (compiler.misc.location: kindname.class, A, null)" + NEW_LINE + 64 "A.java:1:23: compiler.err.cant.resolve.location: kindname.class, B, , , (compiler.misc.location: kindname.class, A, null)" + NEW_LINE + 65 "2 errors" + NEW_LINE + 66 "2 warnings" + NEW_LINE; 67 private static final String expectedFailureOutput2B = 68 "- compiler.warn.path.element.not.found: \"test/jarOut/J.jar" + NEW_LINE + 69 "- compiler.warn.path.element.not.found: test/src\"" + NEW_LINE + 70 "A.java:1:18: compiler.err.cant.resolve.location: kindname.class, J, , , (compiler.misc.location: kindname.class, A, null)" + NEW_LINE + 71 "A.java:1:23: compiler.err.cant.resolve.location: kindname.class, B, , , (compiler.misc.location: kindname.class, A, null)" + NEW_LINE + 72 "2 errors" + NEW_LINE + 73 "2 warnings" + NEW_LINE; 74 75 public static void main(String... args) throws Exception { 76 new ClassPathWithDoubleQuotesTest().runTests(); 77 } 78 79 ClassPathWithDoubleQuotesTest() { 80 super(System.err); 81 tb = new ToolBox(); 82 } 83 84 public void runTests() throws Exception { 85 runTests(m -> new Object[] { Paths.get(m.getName()) }); 86 } 87 88 @Test 89 public void test(Path base) throws Exception { 90 Path current = base.resolve("."); 91 Path jarSrc = current.resolve("jarSrc"); 92 tb.writeJavaFiles(jarSrc, JarSrc); 93 Path jarOut = current.resolve("jarOut"); 94 tb.createDirectories(jarOut); 95 new JarTask(tb).run(jarArgs).writeAll(); 96 97 Path src = current.resolve("src"); 98 tb.writeJavaFiles(src, ASrc, BSrc); 99 100 /** In any system there can be three possible scenarios: 101 * 1 - The system swallows the problem character (the quote in this case) 102 * and the test case compiles 103 * 2 - The problem character gets into javac, but it's not bad enough to trigger 104 * InvalidPathException, but it does mean you can't find the file you're looking for 105 * 3 - The problem character gets into javac and is bad enough to trigger 106 * InvalidPathException, in which case javac needs to handle the exception in a reasonable way. 107 */ 108 109 // testing scenario 1 110 System.err.println("invoking javac EXEC mode without double quotes in the CLASSPATH env variable"); 111 new JavacTask(tb, Task.Mode.EXEC) 112 .envVar("CLASSPATH", "test/jarOut/J.jar" + File.pathSeparator + "test/src") 113 .files("test/src/A.java").run(Task.Expect.SUCCESS); 114 System.err.println("successful compilation"); 115 System.err.println(); 116 117 // testing scenario 2 118 System.err.println("Simulate a system in which double quotes are preserved in the environment variable," + 119 "and for which they are a legal filename character"); 120 String log = new JavacTask(tb, Task.Mode.EXEC) 121 .envVar("CLASSPATH", "Ztest/jarOut/J.jar" + File.pathSeparator + "test/srcZ") 122 .options("-XDrawDiagnostics") 123 .files("test/src/A.java").run(Task.Expect.FAIL) 124 .writeAll() 125 .getOutput(Task.OutputKind.STDERR); 126 Assert.check(log.equals(expectedFailureOutput1), "unexpected output"); 127 System.err.println("compilation is expected to fail"); 128 System.err.println(); 129 130 // testing scenario 3 131 System.err.println("invoking javac EXEC mode with double quotes in the CLASSPATH env variable"); 132 String log2 = new JavacTask(tb, Task.Mode.EXEC) 133 .envVar("CLASSPATH", "\"test/jarOut/J.jar" + File.pathSeparator + "test/src\"") 134 .options("-Xlint:path", "-XDrawDiagnostics") 135 .files("test/src/A.java").run(Task.Expect.FAIL) 136 .writeAll() 137 .getOutput(Task.OutputKind.STDERR); 138 System.err.println(); 139 System.err.println("the log:" + log2); 140 Assert.check(log2.equals(expectedFailureOutput2A) || log2.equals(expectedFailureOutput2B), 141 "unexpected output"); 142 } 143} 144