1 /* 2 * Copyright (c) 2012, 2018, 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 = 10000; 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 public static boolean await(final CountDownLatch latch) { 80 try { 81 return latch.await(TIMEOUT, TimeUnit.MILLISECONDS); 82 } catch (InterruptedException ex) { 83 throw new AssertionError(ex); 84 } 85 } 86 87 private static Future submit(final Runnable r, final CountDownLatch delayLatch) { 88 final Throwable[] testError = new Throwable[1]; 89 final CountDownLatch latch = new CountDownLatch(1); 90 91 Platform.runLater(() -> { 92 try { 93 if (delayLatch != null) { 94 delayLatch.await(); 95 } 96 r.run(); 97 } catch (Throwable th) { 98 testError[0] = th; 99 } finally { 100 latch.countDown(); 101 } 102 }); 103 104 Future future = (timeout, unit) -> { 105 try { 106 if (!latch.await(timeout, unit)) { 107 return false; 108 } 109 } catch (InterruptedException ex) { 110 AssertionFailedError err = new AssertionFailedError("Unexpected exception"); 111 err.initCause(ex); 112 throw err; 113 } 114 115 if (testError[0] != null) { 116 if (testError[0] instanceof Error) { 117 throw (Error)testError[0]; 118 } else if (testError[0] instanceof RuntimeException) { 119 throw (RuntimeException)testError[0]; 120 } else { 121 AssertionFailedError err = new AssertionFailedError("Unknown execution exception"); 122 err.initCause(testError[0].getCause()); 123 throw err; 124 } 125 } 126 127 return true; 128 }; 129 130 return future; 131 } 132 133 public static void runAndWait(Runnable... runnables) { 134 runAndWait(false, runnables); 135 } 136 137 public static void runAndWait(boolean delay, Runnable... runnables) { 138 List<Future> futures = new ArrayList(runnables.length); 139 int i = 0; 140 CountDownLatch delayLatch = delay ? new CountDownLatch(1) : null; 141 for (Runnable r : runnables) { 142 futures.add(submit(r, delayLatch)); 143 } 144 if (delayLatch != null) { 145 delayLatch.countDown(); 146 } 147 148 int count = TIMEOUT / 100; 149 while (!futures.isEmpty() && count-- > 0) { 150 Iterator<Future> it = futures.iterator(); 151 while (it.hasNext()) { 152 Future future = it.next(); 153 if (future.await(0, TimeUnit.MILLISECONDS)) { 154 it.remove(); 155 } 156 } 157 if (!futures.isEmpty()) { 158 Util.sleep(100); 159 } 160 } 161 162 if (!futures.isEmpty()) { 163 throw new AssertionFailedError("Exceeded timeout limit of " + TIMEOUT + " msec"); 164 } 165 } 166 167 public static ArrayList<String> createApplicationLaunchCommand( 168 String testAppName, 169 String testPldrName, 170 String testPolicy) throws IOException { 171 172 return createApplicationLaunchCommand(testAppName, testPldrName, testPolicy, null); 173 } 174 175 public static ArrayList<String> createApplicationLaunchCommand( 176 String testAppName, 177 String testPldrName, 178 String testPolicy, 179 String[] jvmArgs) throws IOException { 180 181 final boolean isJar = testAppName.endsWith(".jar"); 182 183 /* 184 * note: the "worker" properties are tied into build.gradle 185 */ 186 final String workerJavaCmd = System.getProperty("worker.java.cmd"); 187 final String workerPatchModuleFile = System.getProperty("worker.patchmodule.file"); 188 final String workerPatchPolicy = System.getProperty("worker.patch.policy"); 189 final String workerClassPath = System.getProperty("worker.classpath.file"); 190 final Boolean workerDebug = Boolean.getBoolean("worker.debug"); 191 192 final ArrayList<String> cmd = new ArrayList<>(30); 193 194 if (workerJavaCmd != null) { 195 cmd.add(workerJavaCmd); 196 } else { 197 cmd.add("java"); 198 } 199 200 if (workerPatchModuleFile != null) { 201 cmd.add("@" + workerPatchModuleFile); 202 } else { 203 System.out.println("Warning: no worker.patchmodule passed to unit test"); 204 } 205 206 // This is a "minimum" set, rather than the full @addExports 207 cmd.add("--add-exports=javafx.graphics/com.sun.javafx.application=ALL-UNNAMED"); 208 209 if (workerClassPath != null) { 210 cmd.add("@" + workerClassPath); 211 } 212 213 if (testPldrName != null) { 214 cmd.add("-Djavafx.preloader=" + testPldrName); 215 } 216 217 if (testPolicy != null) { 218 219 cmd.add("-Djava.security.manager"); 220 221 try { 222 if (workerPatchPolicy != null) { 223 // with Jigsaw, we need to create a merged java.policy 224 // file that contains the permissions for the patchmodule classes 225 // as well as the permissions needed for this test 226 227 File wpp = new File(workerPatchPolicy); 228 if (!wpp.exists()) { 229 throw new RuntimeException("Missing workerPatchPolicy"); 230 } 231 232 File tempFile = null; 233 if (workerDebug) { 234 String baseAppName = isJar 235 ? testAppName.substring(0, testAppName.length() - 4) 236 : testAppName; 237 final int lastSlashIdx = baseAppName.lastIndexOf("/"); 238 if (lastSlashIdx >= 0) { 239 baseAppName = baseAppName.substring(lastSlashIdx + 1); 240 } 241 tempFile = new File(workerPatchPolicy + 242 "_" + baseAppName); 243 } else { 244 tempFile = File.createTempFile("java", "policy"); 245 tempFile.deleteOnExit(); 246 } 247 248 BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile)); 249 250 BufferedReader reader1 = new BufferedReader(new FileReader(wpp)); 251 URL url = new URL(testPolicy); 252 BufferedReader reader2 = new BufferedReader(new FileReader(url.getFile())); 253 254 String line = null; 255 while ((line = reader1.readLine()) != null) { 256 writer.write(line); 257 writer.newLine(); 258 } 259 while ((line = reader2.readLine()) != null) { 260 writer.write(line); 261 writer.newLine(); 262 } 263 writer.close(); 264 cmd.add("-Djava.security.policy=" + 265 tempFile.getAbsolutePath().replaceAll("\\\\","/")); 266 } else { 267 cmd.add("-Djava.security.policy=" + testPolicy); 268 } 269 } catch (IOException e) { 270 throw e; 271 } 272 273 } 274 275 if (jvmArgs != null) { 276 for (String arg : jvmArgs) { 277 cmd.add(arg); 278 } 279 } 280 281 if (isJar) { 282 cmd.add("-jar"); 283 } 284 cmd.add(testAppName); 285 286 if (workerDebug) { 287 System.err.println("Child cmd is"); 288 cmd.stream().forEach((s) -> { 289 System.err.println(" " + s); 290 }); 291 System.err.println("Child cmd: end"); 292 } 293 294 return cmd; 295 } 296 }