Path: blob/master/test/jdk/tools/launcher/FXLauncherTest.java
41144 views
/*1* Copyright (c) 2012, 2018, 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 {362String testname = "testMissingMC";363testcount++;364line();365System.out.println("test# " + testcount + ": abort on missing Main-Class");366createJavaFile(" "); // no main() needed367createFile(ManifestFile, createManifestContents(null, StdMainClass)); // No MC, but supply JAC368createJar(FXtestJar, ManifestFile);369String sTestJar = FXtestJar.getAbsolutePath();370TestResult tr = doFxExec(javaCmd, "-jar", sTestJar, APP_PARMS[0], APP_PARMS[1]);371tr.checkNegative(); // should abort if no Main-Class372if (tr.testStatus) {373if (!tr.contains("no main manifest attribute")) {374System.err.println("ERROR: launcher did not abort properly");375}376} else {377System.err.println("ERROR: jar executed with no Main-Class!");378}379checkStatus(tr, testname, testcount, StdMainClass);380}381382/*383* test to ensure that we don't load any extraneous fx jars when384* launching a standard java application385* Test both -cp and -jar methods since they use different code paths.386* Neither case should cause jfxrt.jar to be loaded.387*/388@Test389static void testExtraneousJars() throws Exception {390testExtraneousJars(true);391testExtraneousJars(false);392}393394static void testExtraneousJars(boolean useCP) throws Exception {395String testname = "testExtraneousJars";396if (useCP) {397testname = testname.concat("_useCP");398}399testcount++;400line();401System.out.println("test# " + testcount402+ ": test for erroneous jfxrt.jar loading");403createNonFXJavaFile();404createFile(ManifestFile, createManifestContents(NonFXMainClass, null));405createJar(FXtestJar, ManifestFile);406String sTestJar = FXtestJar.getAbsolutePath();407final TestResult tr;408409if (useCP) {410tr = doFxExec(javaCmd, "-verbose:class", "-cp", sTestJar, NonFXMainClass, APP_PARMS[0], APP_PARMS[1]);411} else {412tr = doFxExec(javaCmd, "-verbose:class", "-jar", sTestJar, APP_PARMS[0], APP_PARMS[1]);413}414tr.checkPositive();415if (tr.testStatus) {416if (!tr.notContains("jfxrt.jar")) {417System.out.println("testing for extraneous jfxrt jar");418System.out.println(tr);419throw new Exception("jfxrt.jar is being loaded, it should not be!");420}421if (!tr.notContains("sun.launcher.LauncherHelper$FXHelper")) {422System.out.println("testing for extraneous 'sun.launcher.LauncherHelper$FXHelper'");423System.out.println(tr);424throw new Exception("FXHelper is being loaded, it should not be!");425}426for (String p : APP_PARMS) {427if (!tr.contains(p)) {428System.err.println("ERROR: Did not find "429+ p + " in output!");430}431}432}433checkStatus(tr, testname, testcount, NonFXMainClass);434}435436public static void main(String... args) throws Exception {437438// Ensure that FX is not part of jdk439Class<?> fxClass = null;440try {441fxClass = Class.forName(FX_MARKER_CLASS);442} catch (ClassNotFoundException ex) {443// do nothing444}445if (fxClass != null) {446throw new RuntimeException("JavaFX modules erroneously included in the JDK");447}448449FXLauncherTest fxt = new FXLauncherTest();450fxt.run(args);451if (testExitValue > 0) {452System.out.println("Total of " + testExitValue453+ " failed. Test cases covered: "454+ FXLauncherTest.testcount);455System.exit(1);456} else {457System.out.println("All tests pass. Test cases covered: "458+ FXLauncherTest.testcount);459}460}461462}463464465