/* * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * @test * @bug 4758537 4809833 8149599 8293877 * @summary Test that javac and java find files in similar ways * @library /tools/lib * @build toolbox.ToolBox Util MineField * @run main MineField */ /* * Converted from MineField.sh, originally written by Martin Buchholz. * * For the last version of the original, MineField.sh, see * https://git.openjdk.org/jdk/blob/jdk-19%2B36/test/langtools/tools/javac/Paths/MineField.sh * * This class primarily tests that javac and the java launcher provide * equivalent handling of all path-related options, like {@code -classpath}. */ /* #---------------------------------------------------------------- # The search order for classes used by both java and javac is: # # -Xbootclasspath/p: # -endorseddirs or -Djava.endorsed.dirs= (search for jar/zip only) # -bootclasspath or -Xbootclasspath: # -Xbootclasspath/a: # -extdirs or -Djava.ext.dirs= (search for jar/zip only) # -classpath , -cp , env CLASSPATH= # # Peculiarities of the class file search: # - Empty elements of the (user) classpath default to ".", # while empty elements of other paths are ignored. # - Only for the user classpath is an empty string value equivalent to "." # - Specifying a bootclasspath on the command line obliterates any # previous -Xbootclasspath/p: or -Xbootclasspath/a: command line flags. # # JDK 9 update: # java: The java launcher does not support any of the following: # * -Xbootclasspath/p: -Xbootclasspath: # * -endorseddirs -Djava.endorsed.dirs # * -extdirs -Djava.ext.dirs # All test cases exercising these features have been removed. # javac: The following features are only supported when compiling # for older releases: # * -Xbootclasspath/p: -Xbootclasspath: -bootclasspath -Xbootclasspath/a: # * -endorseddirs -Djava.endorsed.dirs # * -extdirs -Djava.ext.dirs # All test cases exercising these features have been modified to # use -source 8 -target 8. In addition, javac test cases involving # use of the runtime properties java.endorsed.dirs and java.extdirs # (by means of -J-Dname=value) have been removed. # Although the primary purpose of the test cases in this file is to # compare javac and java behavior, some tests remain for javac for # which there is no java equivalent. However, the cases remain as useful # test cases for javac handling of the paths involved. */ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; public class MineField extends Util { public static void main(String... args) throws Exception { new MineField().run(args); } void run(String... args) throws Exception{ setup(); tests(); cleanup(); bottomLine(); } void cleanup() throws IOException { deleteFiles("GooSrc", "GooJar", "GooZip", "GooClass"); deleteFiles("BadSrc", "BadJar", "BadZip", "BadClass"); deleteFiles("OneDir", "Main.java", "MANIFEST.MF"); deleteFiles(listFiles(Path.of("."), "*.class")); deleteFiles("java-lang.jar"); } /** * "Prepare the minefield". */ void setup() throws Exception { cleanup(); tb.createDirectories("GooSrc", "GooJar", "GooZip", "GooClass"); tb.createDirectories("BadSrc", "BadJar", "BadZip", "BadClass"); Files.writeString(Path.of("Lib.java"), "public class Lib {public static void f(){}}"); javac("Lib.java"); jar("cf", "GooJar/Lib.jar", "Lib.class"); jar("cf", "GooZip/Lib.zip", "Lib.class"); tb.moveFile("Lib.class", "GooClass/."); tb.moveFile("Lib.java", "GooSrc/."); checkFiles("GooZip/Lib.zip", "GooJar/Lib.jar", "GooSrc/Lib.java"); Files.writeString(Path.of("Lib.java"), "public class Lib {/* Bad */}"); javac("Lib.java"); jar("cf", "BadJar/Lib.jar", "Lib.class"); jar("cf", "BadZip/Lib.zip", "Lib.class"); tb.moveFile("Lib.class", "BadClass/."); tb.moveFile("Lib.java", "BadSrc/."); checkFiles("BadZip/Lib.zip", "BadJar/Lib.jar", "BadSrc/Lib.java"); Files.writeString(Path.of("Main.java"), "public class Main {public static void main(String[] a) {Lib.f();}}"); Path libModules = javaHome.resolve("lib").resolve("modules"); if (Files.isReadable(libModules)) { jimage("extract", "--dir", "modules", libModules.toString()); jar("cf", "java-lang.jar", "-C", "modules/java.base", "java/lang"); deleteFiles("modules"); } else { Path modules = javaHome.resolve("modules"); if (Files.isDirectory(modules)) { jar("cf", "java-lang.jar", "-C", modules.resolve("java.base").toString(), "java/lang"); } else { throw new Exception("Cannot create java-lang.jar"); } } } void tests() throws Exception { //---------------------------------------------------------------- // Verify that javac class search order is the same as java's //---------------------------------------------------------------- expectFail(JAVAC, """ -source 8 -target 8 -Xbootclasspath/p:GooClass -bootclasspath java-lang.jar${PS}BadZip/Lib.zip Main.java"""); expectPass(JAVAC, """ -source 8 -target 8 -Xbootclasspath/p:BadClass${PS}GooClass -bootclasspath java-lang.jar${PS}GooZip/Lib.zip${PS}BadClass Main.java"""); expectPass(JAVAC, """ -source 8 -target 8 -Xbootclasspath/p:BadJar/Lib.jar -Xbootclasspath:java-lang.jar${PS}GooClass Main.java"""); //---------------------------------------------------------------- expectFail(JAVAC, """ -source 8 -target 8 -bootclasspath java-lang.jar${PS}GooZip/Lib.zip -Xbootclasspath/p:BadClass Main.java"""); expectPass(JAVAC, """ -source 8 -target 8 -bootclasspath java-lang.jar${PS}BadZip/Lib.zip -Xbootclasspath/p:GooClass${PS}BadJar/Lib.jar Main.java"""); //---------------------------------------------------------------- expectFail(JAVAC, """ -source 8 -target 8 -Xbootclasspath/p:BadClass -Xbootclasspath/a:GooClass Main.java"""); expectPass(JAVAC, """ -source 8 -target 8 -Xbootclasspath/p:GooClass${PS}BadClass -Xbootclasspath/a:BadClass Main.java"""); expectPass(JAVA, """ -Xbootclasspath/a:GooClass Main"""); //---------------------------------------------------------------- expectFail(JAVAC, """ -source 8 -target 8 -Xbootclasspath/p:GooClass -Xbootclasspath:BadClass${PS}java-lang.jar -Xbootclasspath/a:GooClass Main.java"""); expectPass(JAVAC, """ -source 8 -target 8 -Xbootclasspath/p:BadClass -Xbootclasspath:GooClass${PS}BadClass${PS}java-lang.jar -Xbootclasspath/a:BadClass Main.java"""); //---------------------------------------------------------------- expectPass(JAVAC, """ -source 8 -target 8 -endorseddirs BadClass${PS}GooZip${PS}BadJar -Xbootclasspath:"BadClass${PS}java-lang.jar Main.java"""); expectPass(JAVAC, """ -source 8 -target 8 -Djava.endorsed.dirs=BadClass${PS}GooZip${PS}BadJar -Xbootclasspath:BadClass${PS}java-lang.jar Main.java"""); //---------------------------------------------------------------- expectFail(JAVAC, """ -source 8 -target 8 -Xbootclasspath/a:BadClass -extdirs GooZip Main.java"""); expectPass(JAVAC, """ -source 8 -target 8 -Xbootclasspath/a:GooClass${PS}BadClass -extdirs BadZip Main.java"""); //---------------------------------------------------------------- expectFail(JAVAC, """ -source 8 -target 8 -extdirs GooClass${PS}BadZip -cp GooZip/Lib.zip Main.java"""); expectPass(JAVAC, """ -source 8 -target 8 -extdirs BadClass${PS}GooZip${PS}BadJar -cp BadZip/Lib.zip Main.java"""); expectPass(JAVAC, """ -source 8 -target 8 -Djava.ext.dirs=GooZip${PS}BadJar -classpath BadZip/Lib.zip Main.java"""); //---------------------------------------------------------------- expectFail(JAVAC, "-classpath BadClass${PS}GooClass Main.java"); expectPass(JAVAC, "-classpath GooClass${PS}BadClass Main.java"); expectFail(JAVA, "-classpath BadClass${PS}GooClass${PS}. Main"); expectPass(JAVA, "-classpath GooClass${PS}BadClass${PS}. Main"); expectFail(JAVAC, "-cp BadJar/Lib.jar${PS}GooZip/Lib.zip Main.java"); expectPass(JAVAC, "-cp GooJar/Lib.jar${PS}BadZip/Lib.zip Main.java"); expectFail(JAVA, "-cp BadJar/Lib.jar${PS}${PS}GooZip/Lib.zip Main"); expectPass(JAVA, "-cp GooJar/Lib.jar${PS}${PS}BadZip/Lib.zip Main"); //---------------------------------------------------------------- expectFail(classpath("BadZip/Lib.zip${PS}GooJar/Lib.jar"), JAVAC,"Main.java"); expectPass(classpath("GooZip/Lib.zip${PS}BadJar/Lib.jar"), JAVAC, "Main.java"); expectFail(classpath("${PS}BadZip/Lib.zip${PS}GooJar/Lib.jar"), JAVA, "Main"); expectPass(classpath("${PS}GooZip/Lib.zip${PS}BadJar/Lib.jar"), JAVA, "Main"); //---------------------------------------------------------------- // Check behavior of empty paths and empty path elements //---------------------------------------------------------------- Path GooClass = Path.of("GooClass"); Path GooJar = Path.of("GooJar"); expectFail(GooClass, JAVAC, "-cp .. ../Main.java"); expectFail(GooClass, JAVA, "-cp .. Main"); // Unspecified classpath defaults to "." Path OneDir = Path.of("OneDir"); tb.createDirectories(OneDir); tb.copyFile(Path.of("Main.java"), OneDir); tb.copyFile(GooClass.resolve("Lib.class"), OneDir); expectPass(OneDir, JAVAC, "Main.java"); expectPass(OneDir, JAVA, "Main"); // Empty classpath elements mean "." expectPass(GooClass, JAVAC, "-cp ${PS}.. ../Main.java"); expectPass(GooClass, JAVA, "-cp ${PS}.. Main"); expectPass(GooClass, JAVAC, "-cp ..${PS} ../Main.java"); expectPass(GooClass, JAVA, "-cp ..${PS} Main"); expectPass(GooClass, JAVAC, "-cp ..${PS}${PS}/xyzzy ../Main.java"); expectPass(GooClass, JAVA, "-cp ..${PS}${PS}/xyzzy Main"); // All other empty path elements are ignored. // note presence of empty arg in this invocation expectFail(GooJar, null, JAVAC, "-source", "8", "-target", "8", "-extdirs", "", "-cp", "..", "../Main.java"); expectFail(GooJar, JAVAC, "-source 8 -target 8 -extdirs ${PS} -cp .. ../Main.java"); expectFail(GooJar, JAVAC, "-source 8 -target 8 -Djava.ext.dirs=${PS} -cp .. ../Main.java"); expectPass(GooJar, JAVAC, "-source 8 -target 8 -extdirs . -cp .. ../Main.java"); expectPass(GooJar, JAVAC, "-source 8 -target 8 -Djava.ext.dirs=. -cp .. ../Main.java"); expectFail(GooJar, JAVAC, "-source 8 -target 8 -Djava.endorsed.dirs= -cp .. ../Main.java"); expectFail(GooJar, JAVAC, "-source 8 -target 8 -endorseddirs ${PS} -cp .. ../Main.java"); expectPass(GooJar, JAVAC, "-source 8 -target 8 -Djava.endorsed.dirs=. -cp .. ../Main.java"); expectFail(GooClass, JAVAC, "-source 8 -target 8 -Xbootclasspath/p: -cp .. ../Main.java"); expectPass(GooClass, JAVAC, "-source 8 -target 8 -Xbootclasspath/p:. -cp .. ../Main.java"); expectFail(GooClass, JAVAC, "-source 8 -target 8 -Xbootclasspath:../java-lang.jar -cp .. ../Main.java"); expectPass(GooClass, JAVAC, "-source 8 -target 8 -Xbootclasspath:../java-lang.jar${PS}. -cp .. ../Main.java"); expectFail(GooClass, JAVAC, "-source 8 -target 8 -Xbootclasspath/a: -cp .. ../Main.java"); expectFail(GooClass, JAVA, "-Xbootclasspath/a: -cp .. Main"); expectPass(GooClass, JAVAC, "-source 8 -target 8 -Xbootclasspath/a:. -cp .. ../Main.java"); expectPass(GooClass, JAVA, "-Xbootclasspath/a:. -cp .. Main"); } }