1 /* 2 * Copyright (c) 2012, 2016, 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.util; 27 28 import java.io.BufferedReader; 29 import java.io.BufferedWriter; 30 import java.io.File; 31 import java.io.FileReader; 32 import java.io.FileWriter; 33 import java.io.IOException; 34 import java.net.URL; 35 import java.util.ArrayList; 36 import java.util.Iterator; 37 import java.util.List; 38 import java.util.concurrent.CountDownLatch; 39 import java.util.concurrent.TimeUnit; 40 import javafx.application.Platform; 41 import junit.framework.AssertionFailedError; 42 import org.junit.Assert; 43 44 /** 45 * Utility methods for life-cycle testing 46 */ 47 public class Util { 48 49 // Test timeout value in milliseconds 50 public static final int TIMEOUT = 5000; 51 52 private static interface Future { 53 public abstract boolean await(long timeout, TimeUnit unit); 54 } 55 56 public static void throwError(Throwable testError) { 57 if (testError != null) { 58 if (testError instanceof Error) { 59 throw (Error)testError; 60 } else if (testError instanceof RuntimeException) { 61 throw (RuntimeException)testError; 62 } else { 63 AssertionFailedError err = new AssertionFailedError("Unknown exception"); 64 err.initCause(testError.getCause()); 65 throw err; 66 } 67 } else { 68 AssertionFailedError err = new AssertionFailedError("Unexpected exception"); 69 throw err; 70 } 71 } 72 73 public static void sleep(long msec) { 74 try { 75 Thread.sleep(msec); 76 } catch (InterruptedException ex) {} 77 } 78 79 private static Future submit(final Runnable r, final CountDownLatch delayLatch) { 80 final Throwable[] testError = new Throwable[1]; 81 final CountDownLatch latch = new CountDownLatch(1); 82 83 Platform.runLater(() -> { 84 try { 85 if (delayLatch != null) { 86 delayLatch.await(); 87 } 88 r.run(); 89 } catch (Throwable th) { 90 testError[0] = th; 91 } finally { 92 latch.countDown(); 93 } 94 }); 95 96 Future future = (timeout, unit) -> { 97 try { 98 if (!latch.await(timeout, unit)) { 99 return false; 100 } 101 } catch (InterruptedException ex) { 102 AssertionFailedError err = new AssertionFailedError("Unexpected exception"); 103 err.initCause(ex); 104 throw err; 105 } 106 107 if (testError[0] != null) { 108 if (testError[0] instanceof Error) { 109 throw (Error)testError[0]; 110 } else if (testError[0] instanceof RuntimeException) { 111 throw (RuntimeException)testError[0]; 112 } else { 113 AssertionFailedError err = new AssertionFailedError("Unknown execution exception"); 114 err.initCause(testError[0].getCause()); 115 throw err; 116 } 117 } 118 119 return true; 120 }; 121 122 return future; 123 } 124 125 public static void runAndWait(Runnable... runnables) { 126 runAndWait(false, runnables); 127 } 128 129 public static void runAndWait(boolean delay, Runnable... runnables) { 130 List<Future> futures = new ArrayList(runnables.length); 131 int i = 0; 132 CountDownLatch delayLatch = delay ? new CountDownLatch(1) : null; 133 for (Runnable r : runnables) { 134 futures.add(submit(r, delayLatch)); 135 } 136 if (delayLatch != null) { 137 delayLatch.countDown(); 138 } 139 140 int count = TIMEOUT / 100; 141 while (!futures.isEmpty() && count-- > 0) { 142 Iterator<Future> it = futures.iterator(); 143 while (it.hasNext()) { 144 Future future = it.next(); 145 if (future.await(0, TimeUnit.MILLISECONDS)) { 146 it.remove(); 147 } 148 } 149 if (!futures.isEmpty()) { 150 Util.sleep(100); 151 } 152 } 153 154 if (!futures.isEmpty()) { 155 throw new AssertionFailedError("Exceeded timeout limit of " + TIMEOUT + " msec"); 156 } 157 } 158 159 public static ArrayList<String> createApplicationLaunchCommand( 160 String testAppName, 161 String testPldrName, 162 String testPolicy) throws IOException { 163 164 final String classpath = System.getProperty("java.class.path"); 165 166 /* 167 * note: the "worker" properties are tied into build.gradle 168 */ 169 final String workerJavaCmd = System.getProperty("worker.java.cmd"); 170 final String workerPatchModuleFile = System.getProperty("worker.patchmodule.file"); 171 final String workerPatchPolicy = System.getProperty("worker.patch.policy"); 172 final String workerClassPath = System.getProperty("worker.classpath.file"); 173 final Boolean workerDebug = Boolean.getBoolean("worker.debug"); 174 175 final ArrayList<String> cmd = new ArrayList<>(30); 176 177 if (workerJavaCmd != null) { 178 cmd.add(workerJavaCmd); 179 } else { 180 cmd.add("java"); 181 } 182 183 if (workerPatchModuleFile != null) { 184 cmd.add("@" + workerPatchModuleFile); 185 } else { 186 System.out.println("Warning: no worker.patchmodule passed to unit test"); 187 } 188 189 // This is a "minimum" set, rather than the full @addExports 190 cmd.add("--add-exports=javafx.graphics/com.sun.javafx.application=ALL-UNNAMED"); 191 192 if (workerClassPath != null) { 193 cmd.add("@" + workerClassPath); 194 } 195 196 if (testPldrName != null) { 197 cmd.add("-Djavafx.preloader=" + testPldrName); 198 } 199 200 if (testPolicy != null) { 201 202 cmd.add("-Djava.security.manager"); 203 204 try { 205 if (workerPatchPolicy != null) { 206 // with Jigsaw, we need to create a merged java.policy 207 // file that contains the permissions for the patchmodule classes 208 // as well as the permissions needed for this test 209 210 File wpp = new File(workerPatchPolicy); 211 if (!wpp.exists()) { 212 throw new RuntimeException("Missing workerPatchPolicy"); 213 } 214 215 File tempFile = null; 216 if (workerDebug) { 217 tempFile = new File(workerPatchPolicy + 218 "_" + testAppName); 219 } else { 220 tempFile = File.createTempFile("java", "policy"); 221 tempFile.deleteOnExit(); 222 } 223 224 BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile)); 225 226 BufferedReader reader1 = new BufferedReader(new FileReader(wpp)); 227 URL url = new URL(testPolicy); 228 BufferedReader reader2 = new BufferedReader(new FileReader(url.getFile())); 229 230 String line = null; 231 while ((line = reader1.readLine()) != null) { 232 writer.write(line); 233 writer.newLine(); 234 } 235 while ((line = reader2.readLine()) != null) { 236 writer.write(line); 237 writer.newLine(); 238 } 239 writer.close(); 240 cmd.add("-Djava.security.policy=" + 241 tempFile.getAbsolutePath().replaceAll("\\\\","/")); 242 } else { 243 cmd.add("-Djava.security.policy=" + testPolicy); 244 } 245 } catch (IOException e) { 246 throw e; 247 } 248 249 } 250 251 cmd.add(testAppName); 252 253 if (workerDebug) { 254 System.err.println("Child cmd is"); 255 cmd.stream().forEach((s) -> { 256 System.err.println(" " + s); 257 }); 258 System.err.println("Child cmd: end"); 259 } 260 261 return cmd; 262 } 263 }