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 private static String getJfxrtDir(final String classpath) { 160 final String jfxrt = "jfxrt.jar"; 161 String cp = classpath; 162 int idx = cp.replace('\\', '/').indexOf("/" + jfxrt); 163 if (idx >= 0) { 164 cp = cp.substring(0, idx); 165 idx = cp.lastIndexOf(File.pathSeparator); 166 if (idx >= 0) { 167 cp = cp.substring(idx, cp.length()); 168 } 169 return cp; 170 } 171 return null; 172 } 173 174 public static ArrayList<String> createApplicationLaunchCommand( 175 String testAppName, 176 String testPldrName, 177 String testPolicy) throws IOException { 178 179 final String classpath = System.getProperty("java.class.path"); 180 final String libraryPath = System.getProperty("java.library.path"); 181 182 /* 183 * note: the "worker" properties are tied into build.gradle and a 184 * the related GradleJUnitWorker as a workaround until the build 185 * is fully converted to a modular build 186 */ 187 final Boolean isJDK9 = Boolean.getBoolean("worker.isJDK9"); 188 final String workerJavaCmd = System.getProperty("worker.java.cmd"); 189 final String workerPatch = System.getProperty("worker.xpatch.dir"); 190 final String workerPatchPolicy = System.getProperty("worker.patch.policy"); 191 final String workerClassPath = System.getProperty("worker.classpath.file"); 192 final Boolean workerDebug = Boolean.getBoolean("worker.debug"); 193 194 final ArrayList<String> cmd = new ArrayList<>(30); 195 196 if (workerJavaCmd != null) { 197 cmd.add(workerJavaCmd); 198 } else { 199 cmd.add("java"); 200 } 201 202 if (isJDK9 && workerPatch != null) { 203 cmd.add("-Xpatch:" + workerPatch); 204 } else { 205 String jfxdir = getJfxrtDir(classpath); 206 Assert.assertNotNull("failed to find jfxdir",jfxdir); 207 cmd.add("-Djava.ext.dirs=" + jfxdir); 208 } 209 210 // This is a "minimum" set, rather than the full @addExports 211 if (isJDK9) { 212 cmd.add("-XaddExports:javafx.graphics/com.sun.javafx.application=ALL-UNNAMED"); 213 } 214 215 if (isJDK9 && libraryPath != null) { 216 // needed for use with Xpatch but not otherwise 217 cmd.add("-Djava.library.path=" + libraryPath); 218 } 219 220 if (isJDK9 && workerClassPath != null) { 221 cmd.add("@" + workerClassPath); 222 } else { 223 cmd.add("-cp"); 224 cmd.add(classpath); 225 } 226 227 if (testPldrName != null) { 228 cmd.add("-Djavafx.preloader=" + testPldrName); 229 } 230 231 if (testPolicy != null) { 232 233 cmd.add("-Djava.security.manager"); 234 235 try { 236 if (workerPatchPolicy != null) { 237 // with Jake, we need to create a merged java.policy 238 // file that contains the permissions for the Xpatch classes 239 // as well as the permissions needed for this test 240 241 File tempFile = File.createTempFile("java", "policy"); 242 tempFile.deleteOnExit(); 243 244 File wpp = new File(workerPatchPolicy); 245 if (!wpp.exists()) { 246 throw new RuntimeException("Missing workerPatchPolicy"); 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 cmd.add(testAppName); 276 277 if (workerDebug) { 278 System.err.println("Child cmd is"); 279 cmd.stream().forEach((s) -> { 280 System.err.println(" " + s); 281 }); 282 System.err.println("Child cmd: end"); 283 } 284 285 return cmd; 286 } 287 }