Path: blob/master/test/jdk/tools/launcher/FXLauncherTest.java
66643 views
/*1* Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @library /test/lib26* @build FXLauncherTest jdk.test.lib.compiler.CompilerUtils27* @bug 8001533 8004547 8035782 820255328* @summary Test launching FX application with java -jar29* Test uses main method and blank main method, a jfx app class and an incorrect30* jfx app class, a main-class for the manifest, a bogus one and none.31* Now that FX is no longer bundled with the JDK, this test uses a32* "mock" javafx.graphics module to test the FX launcher. It also verifies33* that FX is, in fact, not included with the JDK.34* All should execute except the incorrect fx app class entries.35* @run main/othervm FXLauncherTest36*/37import java.io.File;38import java.nio.file.Path;39import java.nio.file.Paths;40import java.io.IOException;41import java.util.ArrayList;42import java.util.Arrays;43import java.util.List;4445import jdk.test.lib.compiler.CompilerUtils;4647public class FXLauncherTest extends TestHelper {48private static final String FX_MARKER_CLASS = "javafx.application.Application";49private static void line() {50System.out.println("_____________________________________________");51}52private static File MainJavaFile = null;53private static final File FXtestJar = new File("fxtest.jar");54private static final File ManifestFile = new File("manifest.txt");55private static final File ScratchDir = new File(".");5657private static final Path SRC_DIR =58TEST_SOURCES_DIR.toPath().resolve("mockfx/src");59private static final Path MODS_DIR = Paths.get("mods");60private static final String MODULE_DIR = MODS_DIR.toString();6162/* standard main class can be used as java main for fx app class */63static final String StdMainClass = "helloworld.HelloWorld";64static final String ExtMainClass = "helloworld.ExtHello";65static final String NonFXMainClass = "helloworld.HelloJava";66static int testcount = 0;6768static final String LAUNCH_MODE_CLASS = "LM_CLASS";69static final String LAUNCH_MODE_JAR = "LM_JAR";70static final String LAUNCH_MODE_MODULE = "LM_MODULE";7172/* a main method and a blank. */73static final String[] MAIN_METHODS = {74"public static void main(String[] args) { launch(args); }",75" "76};7778// Array of parameters to pass to fx application.79static final String[] APP_PARMS = { "one", "two" };8081// Create fx java file for test application82static void createJavaFile(String mainmethod) {83try {84String mainClass = "HelloWorld";85List<String> contents = new ArrayList<>();86contents.add("package helloworld;");87contents.add("import javafx.application.Application;");88contents.add("import javafx.stage.Stage;");89contents.add("public class HelloWorld extends Application {");90contents.add(mainmethod);91contents.add("@Override");92contents.add("public void start(Stage primaryStage) {");93contents.add(" throw new InternalError(\"should never get here\");");94contents.add("}");95contents.add("}");9697// Create and compile java source.98MainJavaFile = new File(mainClass + JAVA_FILE_EXT);99createFile(MainJavaFile, contents);100doFxCompile("-d", ".", mainClass + JAVA_FILE_EXT);101} catch (java.io.IOException ioe) {102ioe.printStackTrace();103throw new RuntimeException("Failed creating HelloWorld.");104}105}106107/*108* Create class that extends HelloWorld instead of Application109*/110static void createExtJavaFile(String mainmethod) {111try {112String mainClass = "ExtHello";113List<String> contents = new ArrayList<>();114contents.add("package helloworld;");115contents.add("public class ExtHello extends HelloWorld {");116contents.add(mainmethod);117contents.add("}");118// Create and compile java source.119MainJavaFile = new File(mainClass + JAVA_FILE_EXT);120createFile(MainJavaFile, contents);121doFxCompile("-cp", ".", "-d", ".", mainClass + JAVA_FILE_EXT);122} catch (java.io.IOException ioe) {123ioe.printStackTrace();124throw new RuntimeException("Failed creating ExtHello.");125}126}127128/*129* Create non-JavaFX class for testing if jfxrt.jar is being loaded130* when it shouldn't be131*/132static void createNonFXJavaFile() {133try {134String mainClass = "HelloJava";135List<String> contents = new ArrayList<>();136contents.add("package helloworld;");137contents.add("public class HelloJava {");138contents.add(" public static void main(String[] args) {");139contents.add(" for(String aa : args)");140contents.add(" System.out.println(\"arg: \" + aa);" );141contents.add(" }");142contents.add("}");143// Create and compile java source.144MainJavaFile = new File(mainClass + JAVA_FILE_EXT);145createFile(MainJavaFile, contents);146doFxCompile("-cp", ".", "-d", ".", mainClass + JAVA_FILE_EXT);147} catch (java.io.IOException ioe) {148ioe.printStackTrace();149throw new RuntimeException("Failed creating HelloJava.");150}151}152153// Create manifest for test fx application154static List<String> createManifestContents(String mainClassEntry, String fxMainEntry) {155List<String> mcontents = new ArrayList<>();156mcontents.add("Manifest-Version: 1.0");157mcontents.add("Created-By: FXLauncherTest");158if (mainClassEntry != null) {159mcontents.add("Main-Class: " + mainClassEntry);160System.out.println("Main-Class: " + mainClassEntry);161}162if (fxMainEntry != null) {163mcontents.add("JavaFX-Application-Class: " + fxMainEntry);164System.out.println("JavaFX-Application-Class: " + fxMainEntry);165}166return mcontents;167}168169// Method to marshal createJar to TestHelper.createJar()170static void createJar(File theJar, File manifestFile) {171createJar("cvmf", manifestFile.getName(),172theJar.getAbsolutePath(), "helloworld");173}174175static void saveFile(String tname, int testcount, File srcFile) {176File newFile = new File(tname + "-" + testcount + "-" + srcFile.getName());177System.out.println("renaming " + srcFile.getName() +178" to " + newFile.getName());179srcFile.renameTo(newFile);180}181182static void cleanupFiles() throws IOException {183for(File f : ScratchDir.listFiles()) {184recursiveDelete(f);185}186}187188static void checkStatus(TestResult tr, String testName, int testCount,189String mainclass) throws Exception {190if (tr.testStatus) {191System.out.println("PASS: " + testName + ":" + testCount +192" : test with " + mainclass);193cleanupFiles();194} else {195saveFile(testName, testcount, FXtestJar);196System.out.println("FAIL: " + testName + ":" + testCount +197" : test with " + mainclass);198cleanupFiles();199System.err.println(tr);200throw new Exception("Failed: " + testName + ":" + testCount);201}202}203204public static void compileFXModule() {205final String JAVAFX_GRAPHICS_MODULE = "javafx.graphics";206207try {208// Compile mockfx/src/javafx.graphics/** into mods/javafx.graphics209boolean compiled210= CompilerUtils.compile(SRC_DIR.resolve(JAVAFX_GRAPHICS_MODULE),211MODS_DIR.resolve(JAVAFX_GRAPHICS_MODULE));212213if (!compiled) {214throw new RuntimeException("Error compiling mock javafx.graphics module");215}216} catch (IOException ioe) {217throw new RuntimeException(ioe);218}219}220221static void doFxCompile(String...compilerArgs) {222compileFXModule();223224List<String> fxCompilerArgs = new ArrayList<>();225fxCompilerArgs.add("--module-path=" + MODULE_DIR);226fxCompilerArgs.add("--add-modules=javafx.graphics");227fxCompilerArgs.addAll(Arrays.asList(compilerArgs));228compile(fxCompilerArgs.toArray(new String[fxCompilerArgs.size()]));229}230231static TestResult doFxExec(String...cmds) {232List<String> fxCmds = new ArrayList<>();233fxCmds.addAll(Arrays.asList(cmds));234fxCmds.add(1, "--module-path=" + MODULE_DIR);235fxCmds.add(2, "--add-modules=javafx.graphics");236return doExec(fxCmds.toArray(new String[fxCmds.size()]));237}238239/*240* Set Main-Class and iterate main_methods.241* Try launching with both -jar and -cp methods, with and without FX main242* class manifest entry.243* All cases should run.244*245* See sun.launcher.LauncherHelper$FXHelper for more details on how JavaFX246* applications are launched.247*/248@Test249static void testBasicFXApp() throws Exception {250testBasicFXApp(true, false); // -cp, no JAC251testBasicFXApp(false, true); // -jar, with JAC252testBasicFXApp(false, false); // -jar, no JAC253}254255static void testBasicFXApp(boolean useCP, boolean setFXMainClass) throws Exception {256String testname = "testBasicFXApp";257if (useCP) {258testname = testname.concat("_useCP");259}260String fxMC = StdMainClass;261if (!setFXMainClass) {262testname = testname.concat("_noJAC");263fxMC = null;264}265for (String mm : MAIN_METHODS) {266testcount++;267line();268System.out.println("test# " + testcount + "- Main method: " + mm);269createJavaFile(mm);270createFile(ManifestFile, createManifestContents(StdMainClass, fxMC));271createJar(FXtestJar, ManifestFile);272String sTestJar = FXtestJar.getAbsolutePath();273String launchMode;274final TestResult tr;275if (useCP) {276tr = doFxExec(javaCmd, "-cp", sTestJar, StdMainClass, APP_PARMS[0], APP_PARMS[1]);277launchMode = LAUNCH_MODE_CLASS;278} else {279tr = doFxExec(javaCmd, "-jar", sTestJar, APP_PARMS[0], APP_PARMS[1]);280launchMode = LAUNCH_MODE_JAR;281}282tr.checkPositive();283if (tr.testStatus) {284if (!tr.contains(launchMode)) {285System.err.println("ERROR: Did not find "286+ launchMode + " in output!");287}288for (String p : APP_PARMS) {289if (!tr.contains(p)) {290System.err.println("ERROR: Did not find "291+ p + " in output!");292}293}294}295checkStatus(tr, testname, testcount, StdMainClass);296}297}298299/*300* Set Main-Class and iterate main methods.301* Main class extends another class that extends Application.302* Try launching with both -jar and -cp methods.303* All cases should run.304*/305@Test306static void testExtendFXApp() throws Exception {307testExtendFXApp(true, false); // -cp, no JAC308testExtendFXApp(false, true); // -jar, with JAC309testExtendFXApp(false, false); // -jar, no JAC310}311312static void testExtendFXApp(boolean useCP, boolean setFXMainClass) throws Exception {313String testname = "testExtendFXApp";314if (useCP) {315testname = testname.concat("_useCP");316}317String fxMC = ExtMainClass;318if (!setFXMainClass) {319testname = testname.concat("_noJAC");320fxMC = null;321}322for (String mm : MAIN_METHODS) {323testcount++;324line();325System.out.println("test# " + testcount + "- Main method: " + mm);326createJavaFile(mm);327createExtJavaFile(mm);328createFile(ManifestFile, createManifestContents(ExtMainClass, fxMC));329createJar(FXtestJar, ManifestFile);330String sTestJar = FXtestJar.getAbsolutePath();331String launchMode;332final TestResult tr;333if (useCP) {334tr = doFxExec(javaCmd, "-cp", sTestJar, ExtMainClass, APP_PARMS[0], APP_PARMS[1]);335launchMode = LAUNCH_MODE_CLASS;336} else {337tr = doFxExec(javaCmd, "-jar", sTestJar, APP_PARMS[0], APP_PARMS[1]);338launchMode = LAUNCH_MODE_JAR;339}340tr.checkPositive();341if (tr.testStatus) {342if (!tr.contains(launchMode)) {343System.err.println("ERROR: Did not find "344+ launchMode + " in output!");345}346for (String p : APP_PARMS) {347if (!tr.contains(p)) {348System.err.println("ERROR: Did not find "349+ p + " in output!");350}351}352}353checkStatus(tr, testname, testcount, ExtMainClass);354}355}356357/*358* Ensure we can NOT launch a FX app jar with no Main-Class manifest entry359*/360@Test361static void testMissingMC() throws Exception {362if (!isEnglishLocale()) {363return;364}365366String testname = "testMissingMC";367testcount++;368line();369System.out.println("test# " + testcount + ": abort on missing Main-Class");370createJavaFile(" "); // no main() needed371createFile(ManifestFile, createManifestContents(null, StdMainClass)); // No MC, but supply JAC372createJar(FXtestJar, ManifestFile);373String sTestJar = FXtestJar.getAbsolutePath();374TestResult tr = doFxExec(javaCmd, "-jar", sTestJar, APP_PARMS[0], APP_PARMS[1]);375tr.checkNegative(); // should abort if no Main-Class376if (tr.testStatus) {377if (!tr.contains("no main manifest attribute")) {378System.err.println("ERROR: launcher did not abort properly");379}380} else {381System.err.println("ERROR: jar executed with no Main-Class!");382}383checkStatus(tr, testname, testcount, StdMainClass);384}385386/*387* test to ensure that we don't load any extraneous fx jars when388* launching a standard java application389* Test both -cp and -jar methods since they use different code paths.390* Neither case should cause jfxrt.jar to be loaded.391*/392@Test393static void testExtraneousJars() throws Exception {394testExtraneousJars(true);395testExtraneousJars(false);396}397398static void testExtraneousJars(boolean useCP) throws Exception {399String testname = "testExtraneousJars";400if (useCP) {401testname = testname.concat("_useCP");402}403testcount++;404line();405System.out.println("test# " + testcount406+ ": test for erroneous jfxrt.jar loading");407createNonFXJavaFile();408createFile(ManifestFile, createManifestContents(NonFXMainClass, null));409createJar(FXtestJar, ManifestFile);410String sTestJar = FXtestJar.getAbsolutePath();411final TestResult tr;412413if (useCP) {414tr = doFxExec(javaCmd, "-verbose:class", "-cp", sTestJar, NonFXMainClass, APP_PARMS[0], APP_PARMS[1]);415} else {416tr = doFxExec(javaCmd, "-verbose:class", "-jar", sTestJar, APP_PARMS[0], APP_PARMS[1]);417}418tr.checkPositive();419if (tr.testStatus) {420if (!tr.notContains("jfxrt.jar")) {421System.out.println("testing for extraneous jfxrt jar");422System.out.println(tr);423throw new Exception("jfxrt.jar is being loaded, it should not be!");424}425if (!tr.notContains("sun.launcher.LauncherHelper$FXHelper")) {426System.out.println("testing for extraneous 'sun.launcher.LauncherHelper$FXHelper'");427System.out.println(tr);428throw new Exception("FXHelper is being loaded, it should not be!");429}430for (String p : APP_PARMS) {431if (!tr.contains(p)) {432System.err.println("ERROR: Did not find "433+ p + " in output!");434}435}436}437checkStatus(tr, testname, testcount, NonFXMainClass);438}439440public static void main(String... args) throws Exception {441442// Ensure that FX is not part of jdk443Class<?> fxClass = null;444try {445fxClass = Class.forName(FX_MARKER_CLASS);446} catch (ClassNotFoundException ex) {447// do nothing448}449if (fxClass != null) {450throw new RuntimeException("JavaFX modules erroneously included in the JDK");451}452453FXLauncherTest fxt = new FXLauncherTest();454fxt.run(args);455if (testExitValue > 0) {456System.out.println("Total of " + testExitValue457+ " failed. Test cases covered: "458+ FXLauncherTest.testcount);459System.exit(1);460} else {461System.out.println("All tests pass. Test cases covered: "462+ FXLauncherTest.testcount);463}464}465466}467468469