1 /* 2 * Copyright (c) 2015, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package test.com.sun.javafx.application; 27 28 import com.sun.javafx.application.PlatformImplShim; 29 import java.util.concurrent.CountDownLatch; 30 import java.util.concurrent.TimeUnit; 31 import java.util.concurrent.atomic.AtomicBoolean; 32 import javafx.application.Platform; 33 import javafx.scene.Group; 34 import javafx.scene.Scene; 35 import javafx.scene.paint.Color; 36 import javafx.stage.Stage; 37 import junit.framework.AssertionFailedError; 38 import test.util.Util; 39 40 import static org.junit.Assert.*; 41 import static test.util.Util.TIMEOUT; 42 43 /** 44 * Test program for Platform startup. 45 * Each of the tests must be run in a separate JVM which is why each 46 * is in its own subclass. 47 */ 48 public class PlatformStartupCommon { 49 50 // Sleep time showing/hiding window in milliseconds 51 private static final int SLEEP_TIME = 1000; 52 53 // Used to start the toolkit before running any test 54 private final CountDownLatch startupLatch = new CountDownLatch(1); 55 56 private Stage mainStage; 57 58 private void createMainStage() { 59 mainStage = new Stage(); 60 mainStage.setTitle("Primary stage"); 61 Group root = new Group(); 62 Scene scene = new Scene(root); 63 scene.setFill(Color.LIGHTYELLOW); 64 mainStage.setScene(scene); 65 mainStage.setX(0); 66 mainStage.setY(0); 67 mainStage.setWidth(210); 68 mainStage.setHeight(180); 69 } 70 71 private void doTestCommon(final boolean implicitExit) { 72 final Throwable[] testError = new Throwable[1]; 73 final Thread testThread = Thread.currentThread(); 74 75 // Start the Toolkit 76 assertFalse(Platform.isFxApplicationThread()); 77 assertEquals(1, startupLatch.getCount()); 78 Platform.setImplicitExit(implicitExit); 79 Platform.startup(() -> { 80 try { 81 assertTrue(Platform.isFxApplicationThread()); 82 startupLatch.countDown(); 83 assertEquals(0, startupLatch.getCount()); 84 } catch (Throwable th) { 85 testError[0] = th; 86 testThread.interrupt(); 87 } 88 }); 89 assertFalse(Platform.isFxApplicationThread()); 90 91 try { 92 if (!startupLatch.await(TIMEOUT, TimeUnit.MILLISECONDS)) { 93 throw new AssertionFailedError("Timeout waiting for Toolkit to start"); 94 } 95 96 final CountDownLatch rDone = new CountDownLatch(1); 97 // Test that we can do a runLater that throws exception 98 Platform.runLater(() -> { 99 try { 100 throw new RuntimeException("this exception is expected"); 101 } finally { 102 rDone.countDown(); 103 } 104 }); 105 if (!rDone.await(TIMEOUT, TimeUnit.MILLISECONDS)) { 106 throw new AssertionFailedError("Timeout waiting for runLater with Exception"); 107 } 108 109 // Create and show main stage 110 Util.runAndWait(() -> { 111 createMainStage(); 112 mainStage.show(); 113 }); 114 115 // Hide the primary stage after a short delay 116 Thread.sleep(SLEEP_TIME); 117 Util.runAndWait(mainStage::hide); 118 119 // Test exit behavior after another short delay 120 Thread.sleep(SLEEP_TIME); 121 122 final CountDownLatch exitLatch = PlatformImplShim.test_getPlatformExitLatch(); 123 124 if (implicitExit) { 125 // Verify that that the runtime has exited 126 assertEquals(0, exitLatch.getCount()); 127 128 // Verify that that a runLater is a no-op 129 final AtomicBoolean isAlive = new AtomicBoolean(false); 130 Platform.runLater(() -> isAlive.set(true)); 131 Thread.sleep(SLEEP_TIME); 132 assertFalse(isAlive.get()); 133 } else { 134 // Verify that the FX runtime has not exited 135 assertEquals(1, exitLatch.getCount()); 136 137 // Make sure Toolkit is still alive and running 138 AtomicBoolean isAlive = new AtomicBoolean(false); 139 Util.runAndWait(() -> isAlive.set(true)); 140 assertTrue(isAlive.get()); 141 142 // Shutdown the FX runtime and wait for toolkit to exit 143 Platform.exit(); 144 145 if (!exitLatch.await(TIMEOUT, TimeUnit.MILLISECONDS)) { 146 throw new AssertionFailedError("Timeout waiting for Platform to exit"); 147 } 148 } 149 } catch (InterruptedException ex) { 150 if (testError[0] != null) { 151 Util.throwError(testError[0]); 152 } else { 153 fail("Unexpected exception: " + ex); 154 } 155 } 156 } 157 158 // ========================== TEST CASES ========================== 159 160 protected void doTestStartupExplicitExit() { 161 doTestCommon(false); 162 } 163 164 protected void doTestStartupImplicitExit() { 165 doTestCommon(true); 166 } 167 168 }