1 /* 2 * Copyright (c) 2009, 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 */ 24 25 package client.test.runner; 26 27 import client.test.ExcludeRunModeMethod; 28 import client.test.ExcludeRunModeType; 29 import client.test.OnlyRunModeMethod; 30 import client.test.OnlyRunModeType; 31 import client.test.RunModes; 32 import client.test.RunModes.RunModeException; 33 import client.test.runner.CommonTestRunnerWorker.Command; 34 import client.test.runner.CommonTestRunnerWorker.Command.CommandType; 35 import client.test.runner.interview.LookAndFeelQuestion; 36 import client.test.runner.interview.PipelineQuestion; 37 import client.util.CtrUtils; 38 import static client.util.CtrUtils.*; 39 import client.util.CtrUtils.OutputReader; 40 import client.util.JettyServer; 41 import com.sun.interview.YesNoQuestion; 42 import com.sun.javatest.Status; 43 import com.sun.javatest.TestDescription; 44 import com.sun.javatest.TestEnvironment; 45 import com.sun.javatest.TestEnvironment.Fault; 46 import java.io.*; 47 import java.lang.reflect.Method; 48 import java.net.ServerSocket; 49 import java.net.Socket; 50 import java.net.URL; 51 import java.net.UnknownHostException; 52 import java.util.concurrent.Semaphore; 53 import java.util.concurrent.TimeUnit; 54 import java.util.logging.Level; 55 import java.util.logging.Logger; 56 import org.junit.runner.RunWith; 57 import test.javaclient.shared.CanvasRunner; 58 import test.javaclient.shared.Utils; 59 60 /** 61 * 62 * @author shura, mrkam, Sergey Grinev, Victor Shubov 63 */ 64 public class TestScript extends htmltestrunner.TestScript { 65 66 private static final int FORCED_TERMINATION_TIMEOUT = 5000; 67 private static final boolean verbose = true; //TODO: use real logger 68 private volatile Process process = null; 69 private volatile ServerSocket cmdServer = null; 70 private volatile Socket cmdSocket; 71 private volatile ObjectOutputStream commandStream; 72 private volatile TestRunner.Status status = null; 73 private volatile TestEnvironment savedEnv; 74 private Thread resultThread; 75 76 @Override 77 protected synchronized void interrupt(Status status) { 78 System.out.println("interrupting with status " + status); 79 try { 80 if (process.isAlive()) { 81 process.destroyForcibly().waitFor(FORCED_TERMINATION_TIMEOUT, TimeUnit.MILLISECONDS); 82 } 83 } catch (InterruptedException ex) { 84 System.err.println("Exception while interrupting test process: " + ex.getMessage()); 85 } 86 if (resultThread.isAlive()) { 87 resultThread.interrupt(); 88 } 89 super.interrupt(status); 90 } 91 92 @Override 93 protected synchronized Status getStatus() { 94 return super.getStatus(); 95 } 96 97 @Override 98 protected void before(TestDescription description, String resultDir) throws Throwable { 99 String testClassName = td.getParameter(RunUITestFinder.UNIT_TEST_CLASS_NAME); 100 String testName = td.getParameter(RunUITestFinder.TEST_NAME); 101 final String runMode = savedEnv.lookup(BasicFXInterview.RUN_MODE_PARAM)[0]; 102 103 System.out.println("\nTEST: " + testClassName + "/" + testName); 104 System.out.println("Mode:" + runMode); 105 System.out.println("Result Dir:" + resultDir); 106 if (needToRun(testClassName, testName, runMode)) { 107 108 try { 109 int masterPort = startServer(); 110 111 if (runMode.equals(BasicFXInterview.RUN_MODE_DESKTOP) 112 || runMode.equals(BasicFXInterview.RUN_MODE_DESKTOP_SWING_INTEROPERABILITY) 113 || runMode.equals(BasicFXInterview.RUN_MODE_DESKTOP_SWT_INTEROPERABILITY)) { 114 runTd(description, resultDir, masterPort); 115 } else { 116 runPlugin(td, resultDir, BasicFXInterview.RUN_MODE_JNLP.equals(runMode)); 117 } 118 } catch (Throwable e) { 119 e.printStackTrace(System.err); 120 if (cmdServer != null) { 121 try { 122 cmdServer.close(); 123 } catch (IOException ex) { 124 ex.printStackTrace(System.err); 125 } 126 } 127 if (cmdSocket != null) { 128 try { 129 cmdSocket.close(); 130 } catch (IOException ex) { 131 ex.printStackTrace(System.err); 132 } 133 } 134 if (commandStream != null) { 135 try { 136 commandStream.close(); 137 } catch (IOException ex) { 138 ex.printStackTrace(System.err); 139 } 140 } 141 if (process != null) { 142 process.destroy(); 143 } 144 commandStream.close(); 145 interrupt(Status.error(e.toString())); 146 } 147 148 resultThread = new Thread(new Runnable() { 149 @Override 150 public void run() { 151 try { 152 System.err.println("Waiting for exit"); 153 ObjectInputStream ois = new ObjectInputStream(cmdSocket.getInputStream()); 154 status = (TestRunner.Status) ois.readObject(); 155 156 Status jtStatus; 157 System.err.println("Process returned status " + status); 158 if (status == null) { 159 jtStatus = Status.error("Unexpected status: " + status); 160 } else if (status.isPassed()) { 161 jtStatus = Status.passed(status.getText()); 162 } else if (status.isFailed()) { 163 jtStatus = Status.failed(status.getText()); 164 } else { 165 jtStatus = Status.error(status.getText()); 166 } 167 interrupt(jtStatus); 168 169 } catch (Throwable ex) { 170 ex.printStackTrace(System.err); 171 interrupt(Status.error(CtrUtils.stackTraceToString(ex))); 172 } finally { 173 174 //finalize 175 try { 176 commandStream.close(); 177 cmdSocket.close(); 178 cmdServer.close(); 179 } catch (IOException ex) { 180 ex.printStackTrace(); 181 } 182 183 if (runMode.equals(BasicFXInterview.RUN_MODE_PLUGIN)) { 184 System.err.println("closing browser"); 185 if (process != null) { 186 process.destroy(); 187 } 188 } 189 try { 190 if (process != null) { 191 process.waitFor(); 192 } 193 } catch (InterruptedException ex) { 194 ex.printStackTrace(System.err); 195 } 196 // if (jemmyProcess != null) { 197 // System.out.println("killed jemmy process"); 198 // try { 199 // jemmyProcess.getInputStream().close(); 200 // } catch (IOException ex) { 201 // ex.printStackTrace(); 202 // } 203 // 204 // jemmyProcess.destroy(); 205 // } 206 System.out.println("DONE"); 207 } 208 } 209 }, "I'm waiting for test's result"); 210 resultThread.start(); 211 } 212 } 213 214 @Override 215 protected void showTestDialog(TestDescription td, TestEnvironment env) { 216 String nodescription = td.getParameter(RunUITestFinder.NO_DESCRIPTION); 217 boolean dryRun = YesNoQuestion.YES.equals(lookup(BasicFXInterview.DRY_RUN_TAG, YesNoQuestion.NO)); 218 if (!Boolean.parseBoolean(nodescription)) { 219 if (dryRun) { 220 System.err.println("DRY RUN MODE"); 221 int delay = Integer.parseInt(lookup(BasicFXInterview.DRY_RUN_DURATION_TAG, BasicFXInterview.DRY_RUN_DURATION_TAG.toString())); 222 try { 223 Thread.sleep(delay * 1000); 224 } catch (InterruptedException ex) { 225 } 226 setStatus(Status.error("Dry Run")); 227 } else { 228 super.showTestDialog(td, env); 229 } 230 } 231 } 232 233 /** 234 * Never put any cleanup here as this method would be called only in case of 235 * success 236 * @throws java.lang.Throwable 237 */ 238 @Override 239 protected void after(TestDescription description, String resultDir) throws Throwable { 240 } 241 242 @Override 243 public Status run(String[] args, TestDescription td, TestEnvironment env) { 244 savedEnv = env; 245 try { 246 String testClassName = td.getParameter(RunUITestFinder.UNIT_TEST_CLASS_NAME); 247 String testName = td.getParameter(RunUITestFinder.TEST_NAME); 248 final String runMode = savedEnv.lookup(BasicFXInterview.RUN_MODE_PARAM)[0]; 249 if (!needToRun(testClassName, testName, runMode)) { 250 return Status.passed("Not run in " + runMode + " mode"); 251 } 252 } catch (RunModes.RunModeException ex) { 253 return Status.error(ex.toString()); 254 } catch (NoSuchMethodException ex) { 255 return Status.error(ex.toString()); 256 } catch (ClassNotFoundException ex) { 257 return Status.error(ex.toString()); 258 } catch (Fault ex) { 259 return Status.error(ex.toString()); 260 } 261 super.run(args, td, env); 262 String hasCheckUI = td.getParameter(RunUITestFinder.HAS_CHECK_UI); 263 try { 264 if (Boolean.parseBoolean(hasCheckUI)) { 265 sendCommand(CommandType.CHECK_UI_AND_EXIT); 266 } else { 267 try { 268 sendCommand(CommandType.EXIT); 269 } catch (IOException ex) { 270 //this is valid for UI to exit before we asked for 271 } 272 } 273 resultThread.join(600000); 274 if (status == null) { 275 sendCommand(CommandType.ABORT); 276 setStatus(Status.error("process didn't return valid status")); 277 } 278 } catch (Throwable ex) { 279 return Status.error(ex.toString()); 280 } 281 282 System.out.println("We are done with " + td.getName() + ". Status: " + getStatus()); 283 return getStatus(); 284 } 285 286 private String getJvmArgPrismOrder() { 287 final String pipelineOptions = lookup(PipelineQuestion.PIPELINE_PARAM_NAME, ""); 288 String jvmArgPrismOrder = ""; 289 if (!pipelineOptions.trim().equals("")) { 290 jvmArgPrismOrder = "-Dprism.order=" + pipelineOptions; 291 } 292 return jvmArgPrismOrder; 293 } 294 295 /** 296 * 297 * @param td 298 * @param resultDir 299 * @return 300 * @throws IOException 301 * @throws Fault 302 */ 303 protected String[] tdCmdArgs(TestDescription td, String resultDir, int port) throws IOException, Fault { 304 String testClassName = td.getParameter(RunUITestFinder.UNIT_TEST_CLASS_NAME); 305 306 boolean isJunit = Boolean.parseBoolean(td.getParameter(RunUITestFinder.TYPE_JUNIT)); 307 308 //String fxSdkHome = td.getParameter(BasicFXInterview.FX_SDK_HOME_PARAM_NAME); 309 String fxSdkHome = savedEnv.lookup(BasicFXInterview.FX_SDK_HOME_PARAM_NAME)[0]; 310 311 String[] pathArr = savedEnv.lookup(BasicFXInterview.JAVA_PARAM_NAME); 312 StringBuilder pathStr = new StringBuilder(); 313 for (String p : pathArr) { 314 if (pathStr.length() > 0) { 315 pathStr.append(" "); 316 } 317 pathStr.append(p); 318 } 319 String javaExec = pathStr.toString(); 320 321 322 String proxy = lookup(BasicFXInterview.PROXY_PARAM_NAME, ""); 323 String jvmProxyHost = ""; 324 String jvmProxyPort = ""; 325 if (proxy != null && proxy.trim().length() > 0) { 326 URL proxyUrl = getProxyUrl(proxy); 327 if (proxyUrl != null) { 328 jvmProxyHost = "-DproxyHost=" + proxyUrl.getHost(); 329 jvmProxyPort = "-DproxyPort=" + proxyUrl.getPort(); 330 } 331 } 332 333 String additionalOptions = getAdditionalOptions(); 334 335 String[] jvmVmOptions = savedEnv.lookup(BasicFXInterview.VM_OPTIONS_PARAM_NAME); 336 337 String jvmArgPrismOrder = getJvmArgPrismOrder(); 338 339 //TODO (SG): is this still required? 340 String jvmArgLibraryPath = ""; 341 if (fxSdkHome != null) { 342 jvmArgLibraryPath = "-Djava.library.path=" + fxSdkHome + File.separator + "rt"; 343 } 344 345 // String externaloutput = lookup(BasicFXInterview.EXTERNALOUTPUT, ""); 346 // if (externaloutput != null) { 347 // jvmArgImageUtils = "-Dimageutils.outputpath=" + externaloutput + File.separator; 348 // } 349 String jvmArgImageUtils = "-Dimageutils.outputpath=" + resultDir + File.separator; 350 351 String jvmArgNoDesc = ""; 352 if (Boolean.parseBoolean(td.getParameter(RunUITestFinder.NO_DESCRIPTION))) { 353 jvmArgNoDesc = "-Djavatest.mode.nodesc=true"; 354 } 355 356 String runMode = lookup(BasicFXInterview.RUN_MODE_PARAM, BasicFXInterview.RUN_MODE_DESKTOP); 357 358 String jvmInterop = ""; 359 if (runMode.equals(BasicFXInterview.RUN_MODE_DESKTOP_SWING_INTEROPERABILITY)) { 360 jvmInterop = "-Djavafx.swinginteroperability=true"; 361 } else if (runMode.equals(BasicFXInterview.RUN_MODE_DESKTOP_SWT_INTEROPERABILITY)) { 362 jvmInterop = "-Djavafx.swtinteroperability=true"; 363 } 364 365 String lookAndFeelOptions = ""; 366 String lfOptions = lookup(LookAndFeelQuestion.LOOKANDFEEL_PARAM_NAME, ""); 367 if (!lfOptions.trim().equals("")) { 368 lookAndFeelOptions = "-Djavafx.userAgentStylesheetUrl=" + lfOptions; 369 } 370 371 //Needed to get images via proxy in Evergreen via VPN see RT-21325 || RT-19661 372 final boolean isFXCompatibility = System.getProperty("java.class.path").contains("JavaFXCompatibility"); 373 String ipV4 = isFXCompatibility ? "-Djava.net.preferIPv4Stack=true" : ""; 374 375 String swtTestOpt = ""; 376 try { 377 if (System.getProperty("os.name").toLowerCase().indexOf("mac") >= 0) { 378 RunWith wunWithAnnotation = Class.forName(testClassName).getAnnotation(RunWith.class); 379 if ((wunWithAnnotation != null) && (wunWithAnnotation.value().equals(CanvasRunner.class))) { 380 swtTestOpt = "-XstartOnFirstThread"; 381 System.out.println("Use -XstartOnFirstThread option, as we on MacOS, and SWT test is run."); 382 } 383 } 384 } catch (ClassNotFoundException ex) { 385 System.err.println("Error : " + ex); 386 } 387 388 String jvmArgClientTestRoot = "-DtestRoot=" + RunUITestFinder.testRoot; 389 390 String[] command = new String[]{}; 391 command = addToArray(command, javaExec.trim()); 392 command = addToArray(command, jvmVmOptions); 393 command = addToArray(command, lookAndFeelOptions); 394 command = addToArray(command, ipV4); 395 command = addToArray(command, jvmArgPrismOrder, jvmArgLibraryPath, jvmArgImageUtils); 396 command = addToArray(command, additionalOptions); 397 command = addToArray(command, jvmArgNoDesc, jvmProxyHost, jvmProxyPort, jvmInterop, swtTestOpt); 398 command = addToArray(command, jvmArgClientTestRoot); 399 command = addToArray(command, "-DmasterPort=" + port); 400 command = addToArray(command, "-classpath", System.getProperty("java.class.path")); 401 // command = addToArray(command, "-Xdebug", "-Xnoagent", "-Djava.compiler=NONE", "-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5858"); 402 command = addToArray(command, isJunit ? JUnit2TestRunner.class.getName() : TestRunner.class.getName(), testClassName); 403 return command; 404 } 405 406 /** 407 * 408 * @param td 409 * @param resultDir 410 * @return 411 */ 412 protected String[] pluginCmdArgs(TestDescription td, String resultDir) { 413 return null; 414 } 415 416 /** 417 * 418 * @param command 419 * @throws IOException 420 */ 421 protected void doRunTd(String[] command) throws IOException { 422 process = Runtime.getRuntime().exec(deleteEmptyElements(command)); 423 } 424 425 private int startServer() throws IOException { 426 System.out.println("Starting server." ); 427 int iRetryCount = 3; 428 boolean bindDone = false; 429 while ( (iRetryCount > 0) && (false==bindDone) ) { 430 iRetryCount = iRetryCount - 1; 431 432 try { 433 cmdServer = new ServerSocket(0); 434 System.out.println("Started server at port " + cmdServer.getLocalPort()); 435 bindDone = true; 436 } catch (java.net.BindException be) { 437 bindDone = false; 438 System.out.println(" === bind exception ==="); 439 Socket socket = new Socket("127.0.0.1", cmdServer.getLocalPort()); 440 commandStream = new ObjectOutputStream(socket.getOutputStream()); 441 sendCommand(CommandType.ABORT); 442 try {Thread.sleep(100);} catch(Exception e){} 443 } 444 445 }// retry loop end 446 cmdServer.setSoTimeout(60000); // we need to be generous for plugin mode, it gets to "download" runnable 447 return cmdServer.getLocalPort(); 448 } 449 450 private void waitForConnection() throws IOException { 451 System.out.println("Waiting for connection..."); 452 cmdSocket = cmdServer.accept(); 453 commandStream = new ObjectOutputStream(cmdSocket.getOutputStream()); 454 System.out.println("Connected"); 455 } 456 457 private void sendCommand(CommandType command) throws UnknownHostException, IOException { 458 sendCommand(command, "-"); 459 } 460 461 private synchronized void sendCommand(CommandType command, String param) throws IOException { 462 Command trc = new Command(command, param); 463 if (verbose) { 464 System.out.println("command " + trc); 465 } 466 commandStream.writeObject(trc); 467 } 468 469 /** 470 * 471 * @param id 472 * @param def 473 * @return 474 */ 475 protected String lookup(String id, String def) { 476 String[] result = null; 477 try { 478 result = savedEnv.lookup(id); 479 } catch (Fault ex) { 480 ex.printStackTrace(System.err); 481 } 482 return result == null || result.length == 0 ? def : result[0]; 483 } 484 485 /** 486 * 487 * @param id 488 * @return 489 */ 490 protected String[] lookup(String id) { 491 String[] result = null; 492 try { 493 result = savedEnv.lookup(id); 494 } catch (Fault ex) { 495 ex.printStackTrace(System.err); 496 } 497 return result; 498 } 499 500 private void runTd(TestDescription td, String resultDir, int port) throws IOException, InterruptedException, Fault { 501 String[] command = tdCmdArgs(td, resultDir, port); 502 dumpProcessExecution(resultDir, command, null); 503 doRunTd(command); 504 System.out.println("Logs: " + resultDir + File.separator); 505 506 if (process != null) { 507 //TODO: who close that streams? 508 new Thread(new OutputReader(new FileOutputStream(resultDir + File.separator + "process.out"), process.getInputStream())).start(); 509 new Thread(new OutputReader(new FileOutputStream(resultDir + File.separator + "process.err"), process.getErrorStream())).start(); 510 } else { 511 System.out.println("ERROR: Failed to create process"); // TODO: fail test? 512 } 513 waitForConnection(); 514 String testName = td.getParameter(RunUITestFinder.TEST_NAME); 515 String testClassName = td.getParameter(RunUITestFinder.UNIT_TEST_CLASS_NAME); 516 sendCommand(CommandType.SET_TEST_CLASS, testClassName); 517 if (testName != null) { 518 sendCommand(CommandType.SET_TEST_NAME, testName); 519 } 520 sendCommand(CommandType.RUN_TEST); 521 } 522 523 private static void dumpProcessExecution(String resultDir, String[] cmd, String workdir) throws IOException { 524 final PrintWriter writer = new PrintWriter( 525 new FileWriter(resultDir + File.separator + "process_execution.log")); 526 writer.println("starting process..."); 527 writer.println("Command: "); 528 for (String s : cmd) { 529 writer.print(s); 530 writer.print("\n"); 531 } 532 writer.println(""); 533 if (workdir != null) { 534 writer.println("Workdir: " + workdir); 535 } 536 writer.flush(); 537 } 538 private static final String pluginPath = "./dist-plugin/"; 539 private static final String pluginFile = "JavaClientPluginTest"; 540 541 private void runPlugin(TestDescription td, String resultDir, boolean isJnlp) 542 throws IOException, Fault { 543 String testClassName = td.getParameter(RunUITestFinder.UNIT_TEST_CLASS_NAME); 544 String testName = td.getParameter(RunUITestFinder.TEST_NAME); 545 546 //TODO: add non-junit tests support 547 boolean isJunit = Boolean.parseBoolean(td.getParameter(RunUITestFinder.TYPE_JUNIT)); 548 if (!isJunit) { 549 throw new UnsupportedOperationException("runui is not supported yet"); 550 } 551 String[] command; 552 String param; 553 File workdir = new File(System.getProperty("user.dir")); 554 final int port = 8485; 555 if (isJnlp) { 556 String[] pathArr = savedEnv.lookup(BasicFXInterview.JAVAWS_PARAM_NAME); 557 StringBuilder pathStr = new StringBuilder(); 558 for (String p : pathArr) { 559 if (pathStr.length() > 0) { 560 pathStr.append(" "); 561 } 562 pathStr.append(p); 563 } 564 File path = new File(pathStr.toString()); 565 param = new File(pluginPath + pluginFile + ".jnlp").getAbsolutePath(); 566 if (!path.exists()) { 567 throw new IllegalArgumentException("javaws path is invalid: " + pathStr); 568 } 569 workdir = path.getParentFile(); 570 571 String jvmArgPrismOrder = getJvmArgPrismOrder(); 572 if (jvmArgPrismOrder.length() > 0) { 573 command = new String[]{pathStr.toString(), "-J" + jvmArgPrismOrder}; // "-Dprism.order=sw" 574 } else { 575 command = new String[]{pathStr.toString()}; 576 } 577 578 } else { // plugin 579 command = addBrowserTricks(savedEnv.lookup(BasicFXInterview.BROWSER_PARAM_NAME)); 580 JettyServer.getInstance(port).setBaseDir(new File(pluginPath).getAbsolutePath()); 581 param = "http://localhost:" + port + "/" + pluginFile + ".html"; 582 } 583 if (verbose) { 584 for (String string : command) { 585 System.err.println("cmd: " + string); 586 } 587 } 588 String[] merge = addToArray(command, param); 589 dumpProcessExecution(resultDir, merge, workdir.getAbsolutePath()); 590 if (Utils.isMacOS()) { 591 ensureJemmyServerRun(workdir.getAbsolutePath()); 592 } 593 process = new ProcessBuilder(merge).directory(workdir).start(); 594 if (process == null) { 595 throw new RuntimeException("Failed to create process for test "); 596 } 597 waitForConnection(); 598 sendCommand(CommandType.SET_OUT, resultDir + File.separator + "process.out"); 599 sendCommand(CommandType.SET_ERR, resultDir + File.separator + "process.err"); 600 sendCommand(CommandType.SET_TEST_CLASS, testClassName); 601 sendCommand(CommandType.SET_BASEDIR, System.getProperty("user.dir")); 602 sendCommand(CommandType.SET_ABSOLUTE_DIR, resultDir + File.separator); 603 if (testName != null) { 604 sendCommand(CommandType.SET_TEST_NAME, testName); 605 } 606 sendCommand(CommandType.RUN_TEST); 607 } 608 609 /** 610 * 611 * @param arr 612 * @param st 613 * @return 614 */ 615 public static String[] addToArray(String[] arr, String... st) { 616 String[] newArr = new String[arr.length + st.length]; 617 System.arraycopy(arr, 0, newArr, 0, arr.length); 618 System.arraycopy(st, 0, newArr, arr.length, st.length); 619 return newArr; 620 } 621 622 private static enum BROWSER { 623 624 FIREFOX("firefox"), CHROME("chrome"), IE("iexplore"), SAFARI("safari"), UNKNOWN("\n"); 625 private final String key; 626 627 private BROWSER(String key) { 628 this.key = key; 629 } 630 631 public static BROWSER detect(String[] command) { 632 for (int i = command.length - 1; i >= 0; i--) { 633 for (BROWSER browser : values()) { 634 if (command[i] != null && command[i].toLowerCase().contains(browser.key)) { 635 System.out.println("Detected Browser: " + browser.name()); 636 return browser; 637 } 638 } 639 } 640 return UNKNOWN; 641 } 642 }; 643 644 private static String[] addBrowserTricks(String[] command) { 645 switch (BROWSER.detect(command)) { 646 case CHROME: 647 return addToArray(command, "--kiosk", "--incognito", "--disable-hang-monitor", "--always-authorize-plugins", "--allow-outdated-plugins"); 648 case FIREFOX: 649 return addToArray(command, "-new-window"); 650 case IE: 651 return addToArray(command, "-k"); 652 case SAFARI: 653 return new String[]{"/usr/bin/open", "-a", "Safari"}; 654 } 655 return command; 656 } 657 658 private boolean needToRun(String testClassName, String testName, String runMode) throws NoSuchMethodException, ClassNotFoundException, RunModeException { 659 Class testClass = Class.forName(testClassName); 660 RunModes mode = RunModes.parseString(runMode); 661 if (mode == null) { 662 throw new RunModes.RunModeException(runMode); 663 } 664 ExcludeRunModeType ermt = (ExcludeRunModeType) testClass.getAnnotation(ExcludeRunModeType.class); 665 if (ermt != null) { 666 if (ermt.value() == mode) { 667 return false; 668 } 669 } 670 OnlyRunModeType ormt = (OnlyRunModeType) testClass.getAnnotation(OnlyRunModeType.class); 671 if (ormt != null) { 672 if (ormt.value() != mode) { 673 return false; 674 } 675 } 676 if (testName == null) { 677 // fox JavaFXCompatibility suite weird run mode 678 return true; 679 } 680 //not testClass.getMethod(testName) because we can't get static method. 681 Method[] methods = testClass.getMethods(); 682 for (Method testMethod : methods) { 683 if (testName.equals(testMethod.getName())) { 684 ExcludeRunModeMethod ermm = (ExcludeRunModeMethod) testMethod.getAnnotation(ExcludeRunModeMethod.class); 685 if (ermm != null) { 686 if (ermm.value() == mode) { 687 return false; 688 } 689 } 690 OnlyRunModeMethod ormm = (OnlyRunModeMethod) testMethod.getAnnotation(OnlyRunModeMethod.class); 691 if (ormm != null) { 692 if (ormm.value() != mode) { 693 return false; 694 } 695 } 696 } 697 } 698 return true; 699 } 700 701 /** 702 * 703 * @return 704 */ 705 public Thread getProcessKiller() { 706 return new ProcessKiller(5000L, process, cmdServer, cmdSocket); 707 } 708 709 private class ProcessKiller extends Thread { 710 711 long sleepTime; 712 Process targetProc; 713 ServerSocket targetSerSocket; 714 Socket targetSocket; 715 716 public ProcessKiller(long time, Process process, ServerSocket targetSerSock, Socket targetSock) { 717 this.sleepTime = time; 718 this.targetProc = process; 719 this.targetSerSocket = targetSerSock; 720 this.targetSocket = targetSock; 721 } 722 723 @Override 724 public void run() { 725 try { 726 sleep(sleepTime); 727 } catch (InterruptedException ex) { 728 Logger.getLogger(TestScript.class.getName()).log(Level.SEVERE, null, ex); 729 } 730 if (targetProc.isAlive()) { 731 System.out.println("Process has been interrupted forcibly!"); 732 targetProc.destroyForcibly(); 733 if (targetSerSocket != null) { 734 if (!targetSerSocket.isClosed()) { 735 try { 736 targetSerSocket.close(); 737 } catch (IOException ex) { 738 System.out.println("CMDSERVER: exception while cloing"); 739 ex.printStackTrace(); 740 } 741 } 742 } else { 743 System.out.println("CMDSERVER: NULL"); 744 } 745 if (targetSocket != null) { 746 if (!targetSocket.isClosed()) { 747 try { 748 targetSocket.close(); 749 } catch (IOException ex) { 750 System.out.println("CMDSOCKET: exception while cloing"); 751 ex.printStackTrace(); 752 } 753 } 754 } else { 755 System.out.println("CMDSOCKET: NULL"); 756 } 757 } 758 } 759 } 760 761 /** 762 * 763 * @return 764 */ 765 protected TestEnvironment getSavedEnv() { 766 return savedEnv; 767 } 768 769 /** 770 * 771 * @return 772 */ 773 protected String getAdditionalOptions(){ 774 return ""; 775 } 776 777 }