1 /* 2 * Copyright (c) 2012, 2014, 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 finishListener 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 ListenerTestCommon { 48 49 // Short delay in milliseconds 50 private static final int DELAY = 10; 51 52 // Sleep time showing/hiding window in milliseconds 53 private static final int SLEEP_TIME = 1000; 54 55 // Used to launch the platform before running any test 56 private final CountDownLatch launchLatch = new CountDownLatch(1); 57 58 // Used to determine when the toolkit is shutdown 59 private CountDownLatch exitLatch; 60 61 // Finish listener used by the various tests 62 private PlatformImpl.FinishListener listener = null; 63 64 private final CountDownLatch idleNotification = new CountDownLatch(1); 65 private final CountDownLatch exitNotification = new CountDownLatch(1); 66 private final AtomicBoolean implicitExit = new AtomicBoolean(); 67 68 private Stage stage; 69 70 public enum ThrowableType { 71 NONE, 72 EXCEPTION, 73 ERROR 74 } 75 76 private void setup() { 77 // Start the FX Platform 78 new Thread(() -> PlatformImpl.startup(() -> { 79 assertTrue(Platform.isFxApplicationThread()); 80 launchLatch.countDown(); 81 })).start(); 82 83 try { 84 if (!launchLatch.await(TIMEOUT, TimeUnit.MILLISECONDS)) { 85 throw new AssertionFailedError("Timeout waiting for Platform to start"); 86 } 87 } catch (InterruptedException ex) { 88 AssertionFailedError err = new AssertionFailedError("Unexpected exception"); 89 err.initCause(ex); 90 throw err; 91 } 92 exitLatch = PlatformImpl.test_getPlatformExitLatch(); 93 assertEquals(1, exitLatch.getCount()); 94 assertEquals(0, launchLatch.getCount()); 95 assertEquals(1, exitLatch.getCount()); 96 assertNull(listener); 97 98 listener = new PlatformImpl.FinishListener() { 99 public void idle(boolean flag) { 100 implicitExit.set(flag); 101 idleNotification.countDown(); 102 } 103 public void exitCalled() { 104 exitNotification.countDown(); 105 } 106 }; 107 PlatformImpl.addListener(listener); 108 } 109 110 private Stage makeStage() { 111 Stage stg = new Stage(); 112 stg.setTitle("Primary stage"); 113 Group root = new Group(); 114 Scene scene = new Scene(root); 115 scene.setFill(Color.LIGHTYELLOW); 116 stg.setScene(scene); 117 stg.setX(0); 118 stg.setY(0); 119 stg.setWidth(210); 120 stg.setHeight(180); 121 return stg; 122 } 123 124 // ========================== TEST CASES ========================== 125 126 public void doTestExit() { 127 setup(); 128 assertNotNull(listener); 129 130 Util.runAndWait(() -> { 131 assertTrue(Platform.isFxApplicationThread()); 132 assertTrue(Platform.isImplicitExit()); 133 }); 134 135 Util.sleep(DELAY); 136 assertEquals(1, exitNotification.getCount()); 137 assertEquals(1, idleNotification.getCount()); 138 139 Platform.exit(); 140 try { 141 if (!exitNotification.await(TIMEOUT, TimeUnit.MILLISECONDS)) { 142 throw new AssertionFailedError("Timeout waiting for exit notification"); 143 } 144 } catch (InterruptedException ex) { 145 AssertionFailedError err = new AssertionFailedError("Unexpected exception"); 146 err.initCause(ex); 147 throw err; 148 } 149 assertEquals(0, exitNotification.getCount()); 150 151 Util.sleep(DELAY); 152 assertEquals(1, idleNotification.getCount()); 153 assertEquals(1, exitLatch.getCount()); 154 155 PlatformImpl.removeListener(listener); 156 listener = null; 157 } 158 159 public void doTestIdleImplicit(final boolean implicit, 160 final ThrowableType throwableType) { 161 162 setup(); 163 assertNotNull(listener); 164 165 Util.runAndWait(() -> { 166 assertTrue(Platform.isFxApplicationThread()); 167 assertTrue(Platform.isImplicitExit()); 168 if (!implicit) { 169 Platform.setImplicitExit(false); 170 } 171 PlatformImpl.addListener(listener); 172 }); 173 174 Util.sleep(DELAY); 175 assertEquals(1, exitNotification.getCount()); 176 assertEquals(1, idleNotification.getCount()); 177 178 Util.runAndWait(() -> { 179 stage = makeStage(); 180 stage.show(); 181 }); 182 183 Util.sleep(SLEEP_TIME); 184 assertEquals(1, exitNotification.getCount()); 185 assertEquals(1, idleNotification.getCount()); 186 187 final CountDownLatch rDone = new CountDownLatch(1); 188 Platform.runLater(() -> { 189 try { 190 if (throwableType == ThrowableType.EXCEPTION) { 191 throw new RuntimeException("this exception is expected"); 192 } else if (throwableType == ThrowableType.ERROR) { 193 throw new InternalError("this error is expected"); 194 } 195 } finally { 196 rDone.countDown(); 197 } 198 }); 199 200 try { 201 if (!rDone.await(TIMEOUT, TimeUnit.MILLISECONDS)) { 202 throw new AssertionFailedError("Timeout waiting for runLater, throwableType = " 203 + throwableType); 204 } 205 } catch (InterruptedException ex) { 206 throw new AssertionFailedError("Unexpected exception waiting for runLater, throwableType = " 207 + throwableType); 208 } 209 210 Util.runAndWait(stage::hide); 211 212 try { 213 if (!idleNotification.await(TIMEOUT, TimeUnit.MILLISECONDS)) { 214 throw new AssertionFailedError("Timeout waiting for exit notification"); 215 } 216 } catch (InterruptedException ex) { 217 AssertionFailedError err = new AssertionFailedError("Unexpected exception"); 218 err.initCause(ex); 219 throw err; 220 } 221 assertEquals(0, idleNotification.getCount()); 222 assertEquals(implicit, implicitExit.get()); 223 224 Util.sleep(DELAY); 225 assertEquals(1, exitNotification.getCount()); 226 assertEquals(1, exitLatch.getCount()); 227 228 PlatformImpl.removeListener(listener); 229 listener = null; 230 } 231 232 }