1 /*
  2  * Copyright (c) 2010, 2026, 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 import java.nio.file.Files;
 25 import java.nio.file.Path;
 26 import java.util.List;
 27 import java.util.jar.JarEntry;
 28 import java.util.jar.JarOutputStream;
 29 import java.util.spi.ToolProvider;
 30 
 31 import jdk.test.lib.JDKToolFinder;
 32 import jdk.test.lib.process.OutputAnalyzer;
 33 import jdk.test.lib.process.ProcessTools;
 34 import org.junit.jupiter.api.Test;
 35 import static java.nio.charset.StandardCharsets.US_ASCII;
 36 import static org.junit.jupiter.api.Assertions.assertEquals;
 37 import static org.junit.jupiter.api.Assertions.assertTrue;
 38 
 39 /*
 40  * @test
 41  * @bug 8154212 8154470 8392966
 42  * @summary Miscellaneous tests for java launcher
 43  * @library /test/lib
 44  * @build jdk.test.lib.process.ProcessTools jdk.test.lib.JDKToolFinder
 45  *        jdk.test.lib.process.OutputAnalyzer
 46  * @run junit ${test.main.class}
 47  */
 48 public class MiscTests {
 49 
 50     private static final ToolProvider JAVAC = ToolProvider.findFirst("javac")
 51             .orElseThrow(() -> new RuntimeException("javac not found"));
 52 
 53     /**
 54      * Launch "java" with class path set on the command line via -Djava.class.path
 55      * and verify that the launcher correctly launches the main application
 56      */
 57     @Test
 58     void testWithClassPathSetViaProperty() throws Exception {
 59         final String mainClass = "Foo";
 60         // create the .java file
 61         final Path sourceFile = Path.of(mainClass + ".java");
 62         final String content = """
 63                 public class Foo {
 64                     public static void main(String... args) {}
 65                 }
 66                 """;
 67         Files.writeString(sourceFile, content);
 68         // compile it
 69         final int compilationExitVal = JAVAC.run(System.out, System.err, sourceFile.toString());
 70         assertEquals(0, compilationExitVal, "compilation of " + sourceFile + " failed");
 71         final Path compiledFile = sourceFile.toAbsolutePath().getParent()
 72                 .resolve(mainClass + ".class");
 73         assertTrue(Files.isRegularFile(compiledFile), "missing or not a regular" +
 74                 " file " + compiledFile);
 75         // directory into which the .class was compiled to
 76         final Path classPathDir = compiledFile.getParent();
 77         // launch "java" with the classpath system property
 78         final List<String> javaCmdArgs = List.of(
 79                 "-Djava.class.path=" + classPathDir,
 80                 mainClass
 81         );
 82         final OutputAnalyzer oa = ProcessTools.executeTestJava(javaCmdArgs);
 83         oa.reportDiagnosticSummary();
 84         oa.shouldHaveExitValue(0);
 85     }
 86 
 87     /**
 88      * Verify that the "_JAVA_LAUNCHER_DEBUG" can be configured to enable
 89      * debug logging for the "java" and "javac" launchers
 90      */
 91     @Test
 92     void testJavaLauncherDebugEnvVar() throws Exception {
 93         for (String cmd : new String[]{"java", "javac"}) {
 94             final String toolLocation = JDKToolFinder.getJDKTool(cmd);
 95             System.err.println("running test against " + toolLocation);
 96             final ProcessBuilder pb = new ProcessBuilder(List.of(toolLocation, "-version"));
 97             pb.environment().put("_JAVA_LAUNCHER_DEBUG", "true");
 98             final OutputAnalyzer oa = ProcessTools.executeCommand(pb);
 99             oa.reportDiagnosticSummary();
100             oa.shouldHaveExitValue(0);
101             final String javargs = cmd.equals("javac") ? "on" : "off";
102             final String progname = cmd.equals("javac") ? "javac" : "java";
103             assertTrue(oa.matches("\\s*debug:on$"), "missing debug:on in output");
104             assertTrue(oa.matches("\\s*javargs:" + javargs + "$"), "missing javargs in output");
105             assertTrue(oa.matches("\\s*program name:" + progname + "$"),
106                     "missing program name in output");
107         }
108     }
109 
110     /**
111      * Verify that when a JAR file with no META-INF/MANIFEST.MF file is launched
112      * using "java -jar" then the launch fails
113      */
114     @Test
115     void testExecutableJARNoManifest() throws Exception {
116         final Path jarFile = Files.createTempFile(Path.of("."), "8392966-", ".jar");
117         // create a JAR file without any manifest
118         try (JarOutputStream noManifest = new JarOutputStream(Files.newOutputStream(jarFile))) {
119             final JarEntry entry = new JarEntry("foo.txt");
120             noManifest.putNextEntry(entry);
121             noManifest.write("bar".getBytes(US_ASCII));
122             noManifest.closeEntry();
123         }
124         // run "java -jar" against that JAR file and expect the launch to fail.
125         // once in headless mode and once headful
126         for (boolean headless : new boolean[]{true, false}) {
127             System.err.println("running with -Djava.awt.headless=" + headless);
128             final OutputAnalyzer oa = ProcessTools.executeTestJava(
129                     "-Djava.awt.headless=" + headless,
130                     // force the error message from the launcher to be in English
131                     "-Duser.language=en", "-Duser.country=US",
132                     "-jar", jarFile.toString());
133             oa.shouldNotHaveExitValue(0); // expected to fail with non-zero exit code
134             // verify it failed for the right reason
135             oa.shouldContain("Error: No manifest in JAR file");
136         }
137     }
138 }