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 com.sun.javafx.application; 27 28 import java.util.concurrent.CountDownLatch; 29 import java.util.concurrent.TimeUnit; 30 import java.util.concurrent.atomic.AtomicBoolean; 31 import javafx.application.Platform; 32 import javafx.scene.Group; 33 import javafx.scene.Scene; 34 import javafx.scene.paint.Color; 35 import javafx.stage.Stage; 36 import junit.framework.AssertionFailedError; 37 import util.Util; 38 39 import static org.junit.Assert.*; 40 import static util.Util.TIMEOUT; 41 42 /** 43 * Test program for Platform startup. 44 * Each of the tests must be run in a separate JVM which is why each 45 * is in its own subclass. 46 */ 47 public class PlatformStartupCommon { 48 49 // Sleep time showing/hiding window in milliseconds 50 private static final int SLEEP_TIME = 1000; 51 52 // Used to start the toolkit before running any test 53 private final CountDownLatch startupLatch = new CountDownLatch(1); 54 55 private Stage mainStage; 56 57 private void createMainStage() { 58 mainStage = new Stage(); 59 mainStage.setTitle("Primary stage"); 60 Group root = new Group(); 61 Scene scene = new Scene(root); 62 scene.setFill(Color.LIGHTYELLOW); 63 mainStage.setScene(scene); 64 mainStage.setX(0); 65 mainStage.setY(0); 66 mainStage.setWidth(210); 67 mainStage.setHeight(180); 68 } 69 70 private void doTestCommon(final boolean implicitExit) { 71 final Throwable[] testError = new Throwable[1]; 72 final Thread testThread = Thread.currentThread(); 73 74 // Start the Toolkit 75 assertFalse(Platform.isFxApplicationThread()); 76 assertEquals(1, startupLatch.getCount()); 77 Platform.setImplicitExit(implicitExit); 78 Platform.startup(() -> { 79 try { 80 assertTrue(Platform.isFxApplicationThread()); 81 startupLatch.countDown(); 82 assertEquals(0, startupLatch.getCount()); 83 } catch (Throwable th) { 84 testError[0] = th; 85 testThread.interrupt(); 86 } 87 }); 88 assertFalse(Platform.isFxApplicationThread()); 89 90 try { 91 if (!startupLatch.await(TIMEOUT, TimeUnit.MILLISECONDS)) { 92 throw new AssertionFailedError("Timeout waiting for Toolkit to start"); 93 } 94 95 final CountDownLatch rDone = new CountDownLatch(1); 96 // Test that we can do a runLater that throws exception 97 Platform.runLater(() -> { 98 try { 99 throw new RuntimeException("this exception is expected"); 100 } finally { 101 rDone.countDown(); 102 } 103 }); 104 if (!rDone.await(TIMEOUT, TimeUnit.MILLISECONDS)) { 105 throw new AssertionFailedError("Timeout waiting for runLater with Exception"); 106 } 107 108 // Create and show main stage 109 Util.runAndWait(() -> { 110 createMainStage(); 111 mainStage.show(); 112 }); 113 114 // Hide the primary stage after a short delay 115 Thread.sleep(SLEEP_TIME); 116 Util.runAndWait(mainStage::hide); 117 118 // Test exit behavior after another short delay 119 Thread.sleep(SLEEP_TIME); 120 121 final CountDownLatch exitLatch = PlatformImpl.test_getPlatformExitLatch(); 122 123 if (implicitExit) { 124 // Verify that that the runtime has exited 125 assertEquals(0, exitLatch.getCount()); 126 127 // Verify that that a runLater is a no-op 128 final AtomicBoolean isAlive = new AtomicBoolean(false); 129 Platform.runLater(() -> isAlive.set(true)); 130 Thread.sleep(SLEEP_TIME); 131 assertFalse(isAlive.get()); 132 } else { 133 // Verify that the FX runtime has not exited 134 assertEquals(1, exitLatch.getCount()); 135 136 // Make sure Toolkit is still alive and running 137 AtomicBoolean isAlive = new AtomicBoolean(false); 138 Util.runAndWait(() -> isAlive.set(true)); 139 assertTrue(isAlive.get()); 140 141 // Shutdown the FX runtime and wait for toolkit to exit 142 Platform.exit(); 143 144 if (!exitLatch.await(TIMEOUT, TimeUnit.MILLISECONDS)) { 145 throw new AssertionFailedError("Timeout waiting for Platform to exit"); 146 } 147 } 148 } catch (InterruptedException ex) { 149 if (testError[0] != null) { 150 Util.throwError(testError[0]); 151 } else { 152 fail("Unexpected exception: " + ex); 153 } 154 } 155 } 156 157 // ========================== TEST CASES ========================== 158 159 protected void doTestStartupExplicitExit() { 160 doTestCommon(false); 161 } 162 163 protected void doTestStartupImplicitExit() { 164 doTestCommon(true); 165 } 166 167 }