# HG changeset patch # User kcr # Date 1448062917 28800 # Node ID 0c051b5cfd8c0b845ced568f30016983983aaf47 # Parent 4c14b9f7e3509a2438a5c21cae6a3c3b79ecf02f imported patch 8090585-platform-startup diff --git a/modules/graphics/src/main/java/com/sun/javafx/application/PlatformImpl.java b/modules/graphics/src/main/java/com/sun/javafx/application/PlatformImpl.java --- a/modules/graphics/src/main/java/com/sun/javafx/application/PlatformImpl.java +++ b/modules/graphics/src/main/java/com/sun/javafx/application/PlatformImpl.java @@ -133,10 +133,25 @@ /** * This method is invoked typically on the main thread. At this point, * the JavaFX Application Thread has not been started. Any attempt - * to call startup twice results in an exception. + * to call startup more than once results in all subsequent calls turning into + * nothing more than a runLater call with the provided Runnable being called. * @param r */ public static void startup(final Runnable r) { + startup(r, false); + } + + /** + * This method is invoked typically on the main thread. At this point, + * the JavaFX Application Thread has not been started. If preventDuplicateCalls + * is true, calling this method multiple times will result in an + * IllegalStateException. If it is false, calling this method multiple times + * will result in all subsequent calls turning into + * nothing more than a runLater call with the provided Runnable being called. + * @param r + * @param preventDuplicateCalls + */ + public static void startup(final Runnable r, boolean preventDuplicateCalls) { // NOTE: if we ever support re-launching an application and/or // launching a second application in the same VM/classloader @@ -146,10 +161,15 @@ } if (initialized.getAndSet(true)) { + if (preventDuplicateCalls) { + throw new IllegalStateException("Toolkit already initialized"); + } + // If we've already initialized, just put the runnable on the queue. runLater(r); return; } + AccessController.doPrivileged((PrivilegedAction) () -> { contextual2DNavigation = Boolean.getBoolean( "com.sun.javafx.isContextual2DNavigation"); diff --git a/modules/graphics/src/main/java/javafx/application/Platform.java b/modules/graphics/src/main/java/javafx/application/Platform.java --- a/modules/graphics/src/main/java/javafx/application/Platform.java +++ b/modules/graphics/src/main/java/javafx/application/Platform.java @@ -41,6 +41,64 @@ } /** + * This method starts the JavaFX runtime. The specified Runnable will then be + * called on the JavaFX Application Thread. In general it is not necessary to + * explicitly call this method, since it is invoked as a consequence of + * how most JavaFX applications are built. However there are valid use cases + * for calling this method directly. Because this method starts the JavaFX + * runtime, there is not yet any JavaFX Application Thread, so it is normal + * that this method is called directly on the main thread of the application. + * + *

+ * This method may or may not return to the caller before the run method + * of the specified Runnable has been called. In any case, once this method + * returns, you may call {@link #runLater} with additional Runnables. + * Those Runnables will be called, also on the JavaFX Application Thread, + * after the Runnable passed into this method has been called. + *

+ * + *

As noted, it is normally the case that the JavaFX Application Thread + * is started automatically. It is important that this method only be called + * when the JavaFX runtime has not yet been initialized. Situations where + * the JavaFX runtime is started automatically include: + *

+ * + * + * + *

When an application does not follow any of these common approaches, + * then it becomes the responsibility of the developer to manually start the + * JavaFX runtime by calling this startup method. + *

+ * + *

Calling this method when the JavaFX runtime is already running will result in an + * {@link IllegalStateException} being thrown - it is only valid to request + * that the JavaFX runtime be started once. + *

+ * + * @throws IllegalStateException if the JavaFX runtime is already running + * + * @param runnable the Runnable whose run method will be executed on the + * JavaFX Application Thread once it has been started. + * + * @since 9 + */ + public static void startup(Runnable runnable) { + PlatformImpl.startup(runnable, true); + } + + /** * Run the specified Runnable on the JavaFX Application Thread at some * unspecified * time in the future. This method, which may be called from any thread, @@ -73,6 +131,9 @@ * runtime is initialized when the first JFXPanel instance is constructed. * For SWT application that use FXCanvas to display FX content, the FX * runtime is initialized when the first FXCanvas instance is constructed. + * For applications that do not follow any of these approaches, then it is + * necessary to manually start the JavaFX runtime by calling + * {@link #startup(Runnable)} once. *

* * @param runnable the Runnable whose run method will be executed on the diff --git a/tests/system/src/test/java/com/sun/javafx/application/PlatformStartupCommon.java b/tests/system/src/test/java/com/sun/javafx/application/PlatformStartupCommon.java new file mode 100644 --- /dev/null +++ b/tests/system/src/test/java/com/sun/javafx/application/PlatformStartupCommon.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2015, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package com.sun.javafx.application; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import javafx.application.Platform; +import javafx.scene.Group; +import javafx.scene.Scene; +import javafx.scene.paint.Color; +import javafx.stage.Stage; +import junit.framework.AssertionFailedError; +import util.Util; + +import static org.junit.Assert.*; +import static util.Util.TIMEOUT; + +/** + * Test program for Platform startup. + * Each of the tests must be run in a separate JVM which is why each + * is in its own subclass. + */ +public class PlatformStartupCommon { + + // Sleep time showing/hiding window in milliseconds + private static final int SLEEP_TIME = 1000; + + // Used to start the toolkit before running any test + private final CountDownLatch startupLatch = new CountDownLatch(1); + + private Stage mainStage; + + private void createMainStage() { + mainStage = new Stage(); + mainStage.setTitle("Primary stage"); + Group root = new Group(); + Scene scene = new Scene(root); + scene.setFill(Color.LIGHTYELLOW); + mainStage.setScene(scene); + mainStage.setX(0); + mainStage.setY(0); + mainStage.setWidth(210); + mainStage.setHeight(180); + } + + private void doTestCommon(final boolean implicitExit) { + final Throwable[] testError = new Throwable[1]; + final Thread testThread = Thread.currentThread(); + + // Start the Toolkit + assertFalse(Platform.isFxApplicationThread()); + assertEquals(1, startupLatch.getCount()); + Platform.setImplicitExit(implicitExit); + Platform.startup(() -> { + try { + assertTrue(Platform.isFxApplicationThread()); + startupLatch.countDown(); + assertEquals(0, startupLatch.getCount()); + } catch (Throwable th) { + testError[0] = th; + testThread.interrupt(); + } + }); + assertFalse(Platform.isFxApplicationThread()); + + try { + if (!startupLatch.await(TIMEOUT, TimeUnit.MILLISECONDS)) { + throw new AssertionFailedError("Timeout waiting for Toolkit to start"); + } + + final CountDownLatch rDone = new CountDownLatch(1); + // Test that we can do a runLater that throws exception + Platform.runLater(() -> { + try { + throw new RuntimeException("this exception is expected"); + } finally { + rDone.countDown(); + } + }); + if (!rDone.await(TIMEOUT, TimeUnit.MILLISECONDS)) { + throw new AssertionFailedError("Timeout waiting for runLater with Exception"); + } + + // Create and show main stage + Util.runAndWait(() -> { + createMainStage(); + mainStage.show(); + }); + + // Hide the primary stage after a short delay + Thread.sleep(SLEEP_TIME); + Util.runAndWait(mainStage::hide); + + // Test exit behavior after another short delay + Thread.sleep(SLEEP_TIME); + + final CountDownLatch exitLatch = PlatformImpl.test_getPlatformExitLatch(); + + if (implicitExit) { + // Verify that that the runtime has exited + assertEquals(0, exitLatch.getCount()); + + // Verify that that a runLater is a no-op + final AtomicBoolean isAlive = new AtomicBoolean(false); + Platform.runLater(() -> isAlive.set(true)); + Thread.sleep(SLEEP_TIME); + assertFalse(isAlive.get()); + } else { + // Verify that the FX runtime has not exited + assertEquals(1, exitLatch.getCount()); + + // Make sure Toolkit is still alive and running + AtomicBoolean isAlive = new AtomicBoolean(false); + Util.runAndWait(() -> isAlive.set(true)); + assertTrue(isAlive.get()); + + // Shutdown the FX runtime and wait for toolkit to exit + Platform.exit(); + + if (!exitLatch.await(TIMEOUT, TimeUnit.MILLISECONDS)) { + throw new AssertionFailedError("Timeout waiting for Platform to exit"); + } + } + } catch (InterruptedException ex) { + if (testError[0] != null) { + Util.throwError(testError[0]); + } else { + fail("Unexpected exception: " + ex); + } + } + } + + // ========================== TEST CASES ========================== + + protected void doTestStartupExplicitExit() { + doTestCommon(false); + } + + protected void doTestStartupImplicitExit() { + doTestCommon(true); + } + +} diff --git a/tests/system/src/test/java/com/sun/javafx/application/PlatformStartupExplicitTest.java b/tests/system/src/test/java/com/sun/javafx/application/PlatformStartupExplicitTest.java new file mode 100644 --- /dev/null +++ b/tests/system/src/test/java/com/sun/javafx/application/PlatformStartupExplicitTest.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package com.sun.javafx.application; + +import org.junit.Test; + +/** + * Test for Platform exit behavior when implicitExit is set to false + */ +public class PlatformStartupExplicitTest extends PlatformStartupCommon { + + @Test + public void testPlatformStartupExplicitExit() { + doTestStartupExplicitExit(); + } +} diff --git a/tests/system/src/test/java/com/sun/javafx/application/PlatformStartupImplicitTest.java b/tests/system/src/test/java/com/sun/javafx/application/PlatformStartupImplicitTest.java new file mode 100644 --- /dev/null +++ b/tests/system/src/test/java/com/sun/javafx/application/PlatformStartupImplicitTest.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package com.sun.javafx.application; + +import org.junit.Test; + +/** + * Test for Platform exit behavior when implicitExit is set to true + */ +public class PlatformStartupImplicitTest extends PlatformStartupCommon { + + @Test + public void testPlatformStartupImplicitExit() { + doTestStartupImplicitExit(); + } +} diff --git a/tests/system/src/test/java/launchertest/Constants.java b/tests/system/src/test/java/launchertest/Constants.java --- a/tests/system/src/test/java/launchertest/Constants.java +++ b/tests/system/src/test/java/launchertest/Constants.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, 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 @@ -61,4 +61,9 @@ static final int ERROR_CONSTRUCTOR_WRONG_CCL = 24; static final int ERROR_START_WRONG_CCL = 25; + + static final int ERROR_STARTUP_SUCCEEDED = 26; + static final int ERROR_STARTUP_FAILED = 27; + + static final int ERROR_ASSERTION_FAILURE = 28; } diff --git a/tests/system/src/test/java/launchertest/MainLauncherTest.java b/tests/system/src/test/java/launchertest/MainLauncherTest.java --- a/tests/system/src/test/java/launchertest/MainLauncherTest.java +++ b/tests/system/src/test/java/launchertest/MainLauncherTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, 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 @@ -82,6 +82,11 @@ new TestData("TestApp"), new TestData("TestAppNoMain"), new TestData("TestNotApplication"), + new TestData("TestStartupApp1", ERROR_NONE), + new TestData("TestStartupApp2", ERROR_NONE), + new TestData("TestStartupAppNoMain", ERROR_NONE), + new TestData("TestStartupJFXPanel", ERROR_NONE), + new TestData("TestStartupNotApplication", ERROR_NONE), new TestData("TestAppThreadCheck", ERROR_NONE), new TestData("TestAppNoMainThreadCheck", ERROR_NONE), new TestData("TestNotApplicationThreadCheck", ERROR_NONE), @@ -224,13 +229,23 @@ case ERROR_START_WRONG_CCL: throw new AssertionFailedError(testAppName + ": start has wrong CCL"); + case ERROR_LAUNCH_SUCCEEDED: + throw new AssertionFailedError(testAppName + + ": Application.launch unexpectedly succeeded"); + case ERROR_STARTUP_SUCCEEDED: + throw new AssertionFailedError(testAppName + + ": Plataform.startup unexpectedly succeeded"); + case ERROR_STARTUP_FAILED: + throw new AssertionFailedError(testAppName + + ": Plataform.startup failed"); + + case ERROR_ASSERTION_FAILURE: + throw new AssertionFailedError(testAppName + + ": Assertion failure in test application"); case ERROR_UNEXPECTED_EXCEPTION: throw new AssertionFailedError(testAppName + ": unexpected exception"); - case ERROR_LAUNCH_SUCCEEDED: - throw new AssertionFailedError(testAppName - + ": Application.launch unexpectedly succeeded"); default: throw new AssertionFailedError(testAppName diff --git a/tests/system/src/test/java/launchertest/TestStartupApp1.java b/tests/system/src/test/java/launchertest/TestStartupApp1.java new file mode 100644 --- /dev/null +++ b/tests/system/src/test/java/launchertest/TestStartupApp1.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2015, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package launchertest; + +import javafx.application.Application; +import javafx.application.Platform; +import javafx.stage.Stage; + +import static launchertest.Constants.*; + +/** + * Test Platform.startup from FX application. + * This is launched by MainLauncherTest. + */ +public class TestStartupApp1 extends Application { + + @Override public void start(Stage stage) throws Exception { + System.err.println("Should never get here"); + System.exit(ERROR_START_BEFORE_MAIN); + } + + public static void main(String[] args) { + try { + Platform.startup(() -> { + // do nothing + }); + System.err.println("ERROR: platform startup unexpectedly succeeded"); + System.exit(ERROR_STARTUP_SUCCEEDED); + } catch (IllegalStateException ex) { + System.exit(ERROR_NONE); + } + /*NOTREACHED*/ +// Application.launch(args); + } + + static { + try { + Platform.runLater(() -> { + // do nothing + }); + } catch (IllegalStateException ex) { + ex.printStackTrace(); + System.exit(ERROR_TOOLKIT_NOT_RUNNING); + } catch (RuntimeException ex) { + ex.printStackTrace(); + System.exit(ERROR_UNEXPECTED_EXCEPTION); + } + } + +} diff --git a/tests/system/src/test/java/launchertest/TestStartupApp2.java b/tests/system/src/test/java/launchertest/TestStartupApp2.java new file mode 100644 --- /dev/null +++ b/tests/system/src/test/java/launchertest/TestStartupApp2.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2015, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package launchertest; + +import javafx.application.Application; +import javafx.application.Platform; +import javafx.stage.Stage; + +import static launchertest.Constants.*; + +/** + * Test Platform.startup from FX application. + * This is launched by MainLauncherTest. + */ +public class TestStartupApp2 extends Application { + + @Override public void start(Stage stage) throws Exception { + try { + Platform.startup(() -> { + // do nothing + }); + System.err.println("ERROR: platform startup unexpectedly succeeded"); + System.exit(ERROR_STARTUP_SUCCEEDED); + } catch (IllegalStateException ex) { + System.exit(ERROR_NONE); + } + } + + public static void main(String[] args) { + Application.launch(args); + } + + static { + try { + Platform.runLater(() -> { + // do nothing + }); + } catch (IllegalStateException ex) { + ex.printStackTrace(); + System.exit(ERROR_TOOLKIT_NOT_RUNNING); + } catch (RuntimeException ex) { + ex.printStackTrace(); + System.exit(ERROR_UNEXPECTED_EXCEPTION); + } + } + +} diff --git a/tests/system/src/test/java/launchertest/TestStartupAppNoMain.java b/tests/system/src/test/java/launchertest/TestStartupAppNoMain.java new file mode 100644 --- /dev/null +++ b/tests/system/src/test/java/launchertest/TestStartupAppNoMain.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package launchertest; + +import javafx.application.Application; +import javafx.application.Platform; +import javafx.stage.Stage; + +import static launchertest.Constants.*; + +/** + * Test Platform.startup from application with no main method. + * This is launched by MainLauncherTest. + */ +public class TestStartupAppNoMain extends Application { + + @Override public void start(Stage stage) throws Exception { + try { + Platform.startup(() -> { + // do nothing + }); + System.err.println("ERROR: platform startup unexpectedly succeeded"); + System.exit(ERROR_STARTUP_SUCCEEDED); + } catch (IllegalStateException ex) { + System.exit(ERROR_NONE); + } + } + + static { + try { + Platform.runLater(() -> { + // do nothing + }); + } catch (IllegalStateException ex) { + ex.printStackTrace(); + System.exit(ERROR_TOOLKIT_NOT_RUNNING); + } catch (RuntimeException ex) { + ex.printStackTrace(); + System.exit(ERROR_UNEXPECTED_EXCEPTION); + } + } + +} diff --git a/tests/system/src/test/java/launchertest/TestStartupJFXPanel.java b/tests/system/src/test/java/launchertest/TestStartupJFXPanel.java new file mode 100644 --- /dev/null +++ b/tests/system/src/test/java/launchertest/TestStartupJFXPanel.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package launchertest; + +import javafx.application.Platform; +import javafx.embed.swing.JFXPanel; + +import static launchertest.Constants.*; + +/** + * Test Platform.startup from class that is not an Application. + * This is launched by MainLauncherTest. + */ +public class TestStartupJFXPanel { + + public static void main(String[] args) { + try { + Platform.runLater(() -> { + // do nothing + }); + System.exit(ERROR_TOOLKIT_IS_RUNNING); + } catch (IllegalStateException ex) { + // OK + } catch (RuntimeException ex) { + ex.printStackTrace(); + System.exit(ERROR_UNEXPECTED_EXCEPTION); + } + + // This will start the platform + new JFXPanel(); + + // Verify that Platform.startup throws expected exception + try { + Platform.startup(() -> { + // do nothing + }); + System.err.println("ERROR: platform startup unexpectedly succeeded"); + System.exit(ERROR_STARTUP_SUCCEEDED); + } catch (IllegalStateException ex) { + System.exit(ERROR_NONE); + } + } + +} diff --git a/tests/system/src/test/java/launchertest/TestStartupNotApplication.java b/tests/system/src/test/java/launchertest/TestStartupNotApplication.java new file mode 100644 --- /dev/null +++ b/tests/system/src/test/java/launchertest/TestStartupNotApplication.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2015, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package launchertest; + +import java.util.ArrayList; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Semaphore; +import javafx.application.Platform; + +import static launchertest.Constants.*; + +/** + * Test Platform.startup from class that is not an Application. + * This is launched by MainLauncherTest. + */ +public class TestStartupNotApplication { + + private static void assertEquals(String expected, String actual) { + if (expected == null && actual == null) return; + if (expected != null && expected.equals(actual)) return; + System.err.println("Assertion failed: expected (" + expected + ") != actual (" + actual + ")"); + System.exit(ERROR_ASSERTION_FAILURE); + } + + public static void main(String[] args) { + try { + Platform.runLater(() -> { + // do nothing + }); + System.exit(ERROR_TOOLKIT_IS_RUNNING); + } catch (IllegalStateException ex) { + // OK + } catch (RuntimeException ex) { + ex.printStackTrace(); + System.exit(ERROR_UNEXPECTED_EXCEPTION); + } + + final Semaphore sem = new Semaphore(0); + final ArrayList list = new ArrayList<>(); + final String keyStartup = "Startup runnable"; + final String keyRunLater0 = "runLater #0"; + final String keyRunLater1 = "runLater #1"; + try { + Platform.startup(() -> { + list.add(keyStartup); + sem.release(); + }); + Platform.runLater(() -> { + list.add(keyRunLater0); + sem.release(); + }); + sem.acquire(2); + } catch (IllegalStateException ex) { + ex.printStackTrace(); + System.exit(ERROR_STARTUP_FAILED); + } catch (InterruptedException ex) { + ex.printStackTrace(); + System.exit(ERROR_UNEXPECTED_EXCEPTION); + } + + Platform.runLater(() -> { + list.add(keyRunLater1); + sem.release(); + }); + try { + sem.acquire(); + } catch (InterruptedException ex) { + ex.printStackTrace(); + System.exit(ERROR_UNEXPECTED_EXCEPTION); + } + assertEquals(keyStartup, list.get(0)); + assertEquals(keyRunLater0, list.get(1)); + assertEquals(keyRunLater1, list.get(2)); + + System.exit(ERROR_NONE); + } + +}