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