1 /******************************************************************************* 2 * Copyright (c) 2000, 2019 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 * Sebastian Davids: sdavids@gmx.de bug 26754 14 *******************************************************************************/ 15 package org.eclipse.jdt.internal.junit.runner; 16 17 import java.io.BufferedReader; 18 import java.io.BufferedWriter; 19 import java.io.File; 20 import java.io.FileInputStream; 21 import java.io.IOException; 22 import java.io.InputStreamReader; 23 import java.io.OutputStreamWriter; 24 import java.io.PrintWriter; 25 import java.io.StringWriter; 26 import java.io.UnsupportedEncodingException; 27 import java.net.Socket; 28 import java.util.Vector; 29 30 import org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestLoader; 31 32 /** 33 * A TestRunner that reports results via a socket connection. 34 * See MessageIds for more information about the protocol. 35 */ 36 public class RemoteTestRunner implements MessageSender, IVisitsTestTrees { 37 /** 38 * Holder for information for a rerun request 39 */ 40 private static class RerunRequest { 41 String fRerunClassName; 42 String fRerunTestName; 43 int fRerunTestId; 44 RerunRequest(int testId, String className, String testName)45 public RerunRequest(int testId, String className, String testName) { 46 fRerunTestId= testId; 47 fRerunClassName= className; 48 fRerunTestName= testName; 49 } 50 51 } 52 53 public static final String RERAN_FAILURE = "FAILURE"; //$NON-NLS-1$ 54 55 public static final String RERAN_ERROR = "ERROR"; //$NON-NLS-1$ 56 57 public static final String RERAN_OK = "OK"; //$NON-NLS-1$ 58 59 /** 60 * The name of the test classes to be executed 61 */ 62 private String[] fTestClassNames; 63 /** 64 * The name of the test (argument -test) 65 */ 66 private String fTestName; 67 /** 68 * The names of the packages containing tests to run 69 */ 70 private String[] fPackageNames; 71 /** 72 * The unique ID of test to run or "" if not available 73 */ 74 private String fUniqueId; 75 /** 76 * Tags to be included and excluded in the test run 77 */ 78 private String[][] fIncludeExcludeTags= new String[2][]; 79 80 /** 81 * The current test result 82 */ 83 private TestExecution fExecution; 84 85 /** 86 * The client socket. 87 */ 88 private Socket fClientSocket; 89 /** 90 * Print writer for sending messages 91 */ 92 private PrintWriter fWriter; 93 /** 94 * Reader for incoming messages 95 */ 96 private BufferedReader fReader; 97 /** 98 * Host to connect to, default is the localhost 99 */ 100 private String fHost= ""; //$NON-NLS-1$ 101 /** 102 * Port to connect to. 103 */ 104 private int fPort= -1; 105 /** 106 * Is the debug mode enabled? 107 */ 108 private boolean fDebugMode= false; 109 /** 110 * Keep the test run server alive after a test run has finished. 111 * This allows to rerun tests. 112 */ 113 private boolean fKeepAlive= false; 114 /** 115 * Has the server been stopped 116 */ 117 private boolean fStopped= false; 118 /** 119 * Queue of rerun requests. 120 */ 121 private Vector<RerunRequest> fRerunRequests= new Vector<RerunRequest>(10); 122 /** 123 * Thread reading from the socket 124 */ 125 private ReaderThread fReaderThread; 126 127 private String fRerunTest; 128 129 private final TestIdMap fIds = new TestIdMap(); 130 131 private String[] fFailureNames; 132 133 private ITestLoader fLoader; 134 135 private MessageSender fSender; 136 137 private boolean fConsoleMode = false; 138 139 /** 140 * Reader thread that processes messages from the client. 141 */ 142 private class ReaderThread extends Thread { ReaderThread()143 public ReaderThread() { 144 super("ReaderThread"); //$NON-NLS-1$ 145 } 146 147 @Override run()148 public void run(){ 149 try { 150 String message= null; 151 while (true) { 152 if ((message= fReader.readLine()) != null) { 153 154 if (message.startsWith(MessageIds.TEST_STOP)){ 155 fStopped= true; 156 RemoteTestRunner.this.stop(); 157 synchronized(RemoteTestRunner.this) { 158 RemoteTestRunner.this.notifyAll(); 159 } 160 break; 161 } 162 163 else if (message.startsWith(MessageIds.TEST_RERUN)) { 164 String arg= message.substring(MessageIds.MSG_HEADER_LENGTH); 165 //format: testId className testName 166 int c0= arg.indexOf(' '); 167 int c1= arg.indexOf(' ', c0+1); 168 String s= arg.substring(0, c0); 169 int testId= Integer.parseInt(s); 170 String className= arg.substring(c0+1, c1); 171 String testName= arg.substring(c1+1, arg.length()); 172 synchronized(RemoteTestRunner.this) { 173 fRerunRequests.add(new RerunRequest(testId, className, testName)); 174 RemoteTestRunner.this.notifyAll(); 175 } 176 } 177 } 178 } 179 } catch (Exception e) { 180 RemoteTestRunner.this.stop(); 181 } 182 } 183 } 184 RemoteTestRunner()185 public RemoteTestRunner() { 186 setMessageSender(this); 187 } 188 setMessageSender(MessageSender sender)189 public void setMessageSender(MessageSender sender) { 190 fSender = sender; 191 } 192 193 /** 194 * The main entry point. 195 * 196 * @param args Parameters: 197 * <pre>-classnames: the name of the test suite class 198 * -testfilename: the name of a file containing classnames of test suites 199 * -test: the test method name (format classname testname) 200 * -packagenamefile: the name of a file containing package names of tests 201 * -host: the host to connect to default local host 202 * -port: the port to connect to, mandatory argument 203 * -keepalive: keep the process alive after a test run 204 * </pre> 205 */ main(String[] args)206 public static void main(String[] args) { 207 try { 208 RemoteTestRunner testRunServer= new RemoteTestRunner(); 209 testRunServer.init(args); 210 testRunServer.run(); 211 } catch (Throwable e) { 212 e.printStackTrace(); // don't allow System.exit(0) to swallow exceptions 213 } finally { 214 // fix for 14434 215 System.exit(0); 216 } 217 } 218 219 /** 220 * Parse command line arguments. Hook for subclasses to process 221 * additional arguments. 222 * @param args the arguments 223 */ init(String[] args)224 protected void init(String[] args) { 225 defaultInit(args); 226 } 227 228 /** 229 * The class loader to be used for loading tests. 230 * Subclasses may override to use another class loader. 231 * @return the class loader to lead test classes 232 */ getTestClassLoader()233 protected ClassLoader getTestClassLoader() { 234 return getClass().getClassLoader(); 235 } 236 237 /** 238 * Process the default arguments. 239 * @param args arguments 240 */ defaultInit(String[] args)241 protected final void defaultInit(String[] args) { 242 for(int i= 0; i < args.length; i++) { 243 if(args[i].toLowerCase().equals("-classnames") || args[i].toLowerCase().equals("-classname")){ //$NON-NLS-1$ //$NON-NLS-2$ 244 Vector<String> list= new Vector<String>(); 245 for (int j= i+1; j < args.length; j++) { 246 if (args[j].startsWith("-")) //$NON-NLS-1$ 247 break; 248 list.add(args[j]); 249 } 250 fTestClassNames= list.toArray(new String[list.size()]); 251 } 252 else if(args[i].toLowerCase().equals("-test")) { //$NON-NLS-1$ 253 String testName= args[i+1]; 254 int p= testName.indexOf(':'); 255 if (p == -1) 256 throw new IllegalArgumentException("Testname not separated by \'%\'"); //$NON-NLS-1$ 257 fTestName= testName.substring(p+1); 258 fTestClassNames= new String[]{ testName.substring(0, p) }; 259 i++; 260 } 261 else if(args[i].toLowerCase().equals("-testnamefile")) { //$NON-NLS-1$ 262 String testNameFile= args[i+1]; 263 try { 264 readTestNames(testNameFile); 265 } catch (IOException e) { 266 throw new IllegalArgumentException("Cannot read testname file."); //$NON-NLS-1$ 267 } 268 i++; 269 270 } else if (args[i].toLowerCase().equals("-packagenamefile")) { //$NON-NLS-1$ 271 String pkgNameFile= args[i+1]; 272 try { 273 readPackageNames(pkgNameFile); 274 } catch (IOException e) { 275 throw new IllegalArgumentException("Cannot read packagename file."); //$NON-NLS-1$ 276 } 277 i++; 278 279 } else if (args[i].toLowerCase().equals("-testfailures")) { //$NON-NLS-1$ 280 String testFailuresFile= args[i+1]; 281 try { 282 readFailureNames(testFailuresFile); 283 } catch (IOException e) { 284 throw new IllegalArgumentException("Cannot read testfailures file."); //$NON-NLS-1$ 285 } 286 i++; 287 288 } else if(args[i].toLowerCase().equals("-port")) { //$NON-NLS-1$ 289 fPort= Integer.parseInt(args[i+1]); 290 i++; 291 } 292 else if(args[i].toLowerCase().equals("-host")) { //$NON-NLS-1$ 293 fHost= args[i+1]; 294 i++; 295 } 296 else if(args[i].toLowerCase().equals("-rerun")) { //$NON-NLS-1$ 297 fRerunTest= args[i+1]; 298 i++; 299 } 300 else if(args[i].toLowerCase().equals("-keepalive")) { //$NON-NLS-1$ 301 fKeepAlive= true; 302 } 303 else if(args[i].toLowerCase().equals("-debugging") || args[i].toLowerCase().equals("-debug")){ //$NON-NLS-1$ //$NON-NLS-2$ 304 fDebugMode= true; 305 306 } else if (args[i].toLowerCase().equals("-junitconsole")) { //$NON-NLS-1$ 307 fConsoleMode = true; 308 } else if (args[i].toLowerCase().equals("-testloaderclass")) { //$NON-NLS-1$ 309 String className = args[i + 1]; 310 createLoader(className); 311 i++; 312 } else if(args[i].toLowerCase().equals("-uniqueid")) { //$NON-NLS-1$ 313 fUniqueId= args[i+1]; 314 i++; 315 } else if (args[i].toLowerCase().equals("--include-tag")) { //$NON-NLS-1$ 316 String[] includeTags= fIncludeExcludeTags[0]; 317 if (includeTags == null) { 318 includeTags= new String[1]; 319 includeTags[0]= args[i + 1]; 320 } else { 321 String[] tags= new String[includeTags.length + 1]; 322 System.arraycopy(includeTags, 0, tags, 0, includeTags.length); 323 tags[includeTags.length]= args[i + 1]; 324 includeTags= tags; 325 } 326 fIncludeExcludeTags[0]= includeTags; 327 i++; 328 } else if (args[i].toLowerCase().equals("--exclude-tag")) { //$NON-NLS-1$ 329 String[] excludeTags= fIncludeExcludeTags[1]; 330 if (excludeTags == null) { 331 excludeTags= new String[1]; 332 excludeTags[0]= args[i + 1]; 333 } else { 334 String[] tags= new String[excludeTags.length + 1]; 335 System.arraycopy(excludeTags, 0, tags, 0, excludeTags.length); 336 tags[excludeTags.length]= args[i + 1]; 337 excludeTags= tags; 338 } 339 fIncludeExcludeTags[1]= excludeTags; 340 i++; 341 } 342 } 343 344 if (getTestLoader() == null) 345 initDefaultLoader(); 346 347 if(fTestClassNames == null || fTestClassNames.length == 0) { 348 if (fPackageNames == null || fPackageNames.length == 0) { 349 throw new IllegalArgumentException(JUnitMessages.getString("RemoteTestRunner.error.classnamemissing")); //$NON-NLS-1$ 350 } else { 351 fTestClassNames= new String[0]; 352 } 353 } 354 355 if (fPort == -1) 356 throw new IllegalArgumentException(JUnitMessages.getString("RemoteTestRunner.error.portmissing")); //$NON-NLS-1$ 357 if (fDebugMode) 358 System.out.println("keepalive "+fKeepAlive); //$NON-NLS-1$ 359 } 360 initDefaultLoader()361 public void initDefaultLoader() { 362 createLoader(JUnit3TestLoader.class.getName()); 363 } 364 createLoader(String className)365 public void createLoader(String className) { 366 setLoader(createRawTestLoader(className)); 367 } 368 createRawTestLoader(String className)369 protected ITestLoader createRawTestLoader(String className) { 370 try { 371 return (ITestLoader) loadTestLoaderClass(className).newInstance(); 372 } catch (Exception e) { 373 StringWriter trace= new StringWriter(); 374 e.printStackTrace(new PrintWriter(trace)); 375 String message= JUnitMessages.getFormattedString("RemoteTestRunner.error.invalidloader", new Object[] {className, trace.toString()}); //$NON-NLS-1$ 376 throw new IllegalArgumentException(message); 377 } 378 } 379 loadTestLoaderClass(String className)380 protected Class<?> loadTestLoaderClass(String className) throws ClassNotFoundException { 381 return Class.forName(className); 382 } 383 setLoader(ITestLoader newInstance)384 public void setLoader(ITestLoader newInstance) { 385 fLoader = newInstance; 386 } 387 readPackageNames(String pkgNameFile)388 private void readPackageNames(String pkgNameFile) throws IOException { 389 BufferedReader br= new BufferedReader(new InputStreamReader(new FileInputStream(new File(pkgNameFile)), "UTF-8")); //$NON-NLS-1$ 390 try { 391 String line; 392 Vector<String> list= new Vector<String>(); 393 while ((line= br.readLine()) != null) { 394 list.add(line); 395 } 396 fPackageNames= list.toArray(new String[list.size()]); 397 } 398 finally { 399 br.close(); 400 } 401 if (fDebugMode) { 402 System.out.println("Packages:"); //$NON-NLS-1$ 403 for (int i= 0; i < fPackageNames.length; i++) { 404 System.out.println(" "+fPackageNames[i]); //$NON-NLS-1$ 405 } 406 } 407 } 408 readTestNames(String testNameFile)409 private void readTestNames(String testNameFile) throws IOException { 410 BufferedReader br= new BufferedReader(new InputStreamReader(new FileInputStream(new File(testNameFile)), "UTF-8")); //$NON-NLS-1$ 411 try { 412 String line; 413 Vector<String> list= new Vector<String>(); 414 while ((line= br.readLine()) != null) { 415 list.add(line); 416 } 417 fTestClassNames= list.toArray(new String[list.size()]); 418 } 419 finally { 420 br.close(); 421 } 422 if (fDebugMode) { 423 System.out.println("Tests:"); //$NON-NLS-1$ 424 for (int i= 0; i < fTestClassNames.length; i++) { 425 System.out.println(" "+fTestClassNames[i]); //$NON-NLS-1$ 426 } 427 } 428 } 429 readFailureNames(String testFailureFile)430 private void readFailureNames(String testFailureFile) throws IOException { 431 BufferedReader br= new BufferedReader(new InputStreamReader(new FileInputStream(new File(testFailureFile)), "UTF-8")); //$NON-NLS-1$ 432 try { 433 String line; 434 Vector<String> list= new Vector<String>(); 435 while ((line= br.readLine()) != null) { 436 list.add(line); 437 } 438 fFailureNames= list.toArray(new String[list.size()]); 439 } 440 finally { 441 br.close(); 442 } 443 if (fDebugMode) { 444 System.out.println("Failures:"); //$NON-NLS-1$ 445 for (int i= 0; i < fFailureNames.length; i++) { 446 System.out.println(" "+fFailureNames[i]); //$NON-NLS-1$ 447 } 448 } 449 } 450 451 /** 452 * Connects to the remote ports and runs the tests. 453 */ run()454 protected void run() { 455 if (!connect()) 456 return; 457 if (fRerunTest != null) { 458 rerunTest(new RerunRequest(Integer.parseInt(fRerunTest), fTestClassNames[0], fTestName)); 459 return; 460 } 461 462 FirstRunExecutionListener listener= firstRunExecutionListener(); 463 fExecution= new TestExecution(listener, getClassifier()); 464 runTests(fExecution); 465 if (fKeepAlive) 466 waitForReruns(); 467 468 shutDown(); 469 470 } 471 firstRunExecutionListener()472 public FirstRunExecutionListener firstRunExecutionListener() { 473 return new FirstRunExecutionListener(fSender, fIds); 474 } 475 476 /** 477 * Waits for rerun requests until an explicit stop request 478 */ waitForReruns()479 private synchronized void waitForReruns() { 480 while (!fStopped) { 481 try { 482 wait(); 483 if (!fStopped && fRerunRequests.size() > 0) { 484 RerunRequest r= fRerunRequests.remove(0); 485 rerunTest(r); 486 } 487 } catch (InterruptedException e) { 488 } 489 } 490 } 491 runFailed(String message, Exception exception)492 public void runFailed(String message, Exception exception) { 493 //TODO: remove System.err.println? 494 System.err.println(message); 495 if (exception != null) 496 exception.printStackTrace(System.err); 497 } 498 loadClasses(String[] testClassNames)499 protected Class<?>[] loadClasses(String[] testClassNames) { 500 Vector<Class<?>> classes= new Vector<Class<?>>(); 501 for (int i = 0; i < testClassNames.length; i++) { 502 String name = testClassNames[i]; 503 Class<?> clazz = loadClass(name, this); 504 if (clazz != null) { 505 classes.add(clazz); 506 } 507 } 508 return classes.toArray(new Class[classes.size()]); 509 } 510 notifyListenersOfTestEnd(TestExecution execution, long testStartTime)511 protected void notifyListenersOfTestEnd(TestExecution execution, 512 long testStartTime) { 513 if (execution == null || execution.shouldStop()) 514 notifyTestRunStopped(System.currentTimeMillis() - testStartTime); 515 else 516 notifyTestRunEnded(System.currentTimeMillis() - testStartTime); 517 } 518 519 /** 520 * Runs a set of tests. 521 * @param testClassNames classes to be run 522 * @param testName individual method to be run 523 * @param execution executor 524 */ runTests(String[] testClassNames, String testName, TestExecution execution)525 public void runTests(String[] testClassNames, String testName, TestExecution execution) { 526 ITestReference[] suites= fLoader.loadTests(loadClasses(testClassNames), testName, fFailureNames, fPackageNames, fIncludeExcludeTags, fUniqueId, this); 527 528 // count all testMethods and inform ITestRunListeners 529 int count= countTests(suites); 530 531 notifyTestRunStarted(count); 532 533 // test count is 0 if only dynamic tests will be run (i.e. only @TestFactory methods are present), hence test run should continue. 534 /*if (count == 0) { 535 notifyTestRunEnded(0); 536 return; 537 }*/ 538 539 sendTrees(suites); 540 541 long testStartTime= System.currentTimeMillis(); 542 execution.run(suites); 543 notifyListenersOfTestEnd(execution, testStartTime); 544 } 545 sendTrees(ITestReference[] suites)546 private void sendTrees(ITestReference[] suites) { 547 long startTime = System.currentTimeMillis(); 548 if (fDebugMode) 549 System.out.print("start send tree..."); //$NON-NLS-1$ 550 for (int i = 0; i < suites.length; i++) { 551 suites[i].sendTree(this); 552 } 553 if (fDebugMode) 554 System.out.println("done send tree - time(ms): " + (System.currentTimeMillis() - startTime)); //$NON-NLS-1$ 555 } 556 countTests(ITestReference[] tests)557 private int countTests(ITestReference[] tests) { 558 int count= 0; 559 for (int i= 0; i < tests.length; i++) { 560 ITestReference test= tests[i]; 561 if (test != null) 562 count= count + test.countTestCases(); 563 } 564 return count; 565 } 566 567 /** 568 * Reruns a test as defined by the fully qualified class name and 569 * the name of the test. 570 * @param r rerun request 571 */ rerunTest(RerunRequest r)572 public void rerunTest(RerunRequest r) { 573 final Class<?>[] classes= loadClasses(new String[] { r.fRerunClassName }); 574 ITestReference rerunTest1= fLoader.loadTests(classes, r.fRerunTestName, null, null, fIncludeExcludeTags, fUniqueId, this)[0]; 575 RerunExecutionListener service= rerunExecutionListener(); 576 577 TestExecution execution= new TestExecution(service, getClassifier()); 578 ITestReference[] suites= new ITestReference[] { rerunTest1 }; 579 execution.run(suites); 580 581 notifyRerunComplete(r, service.getStatus()); 582 } 583 rerunExecutionListener()584 public RerunExecutionListener rerunExecutionListener() { 585 return new RerunExecutionListener(fSender, fIds); 586 } 587 getClassifier()588 protected IClassifiesThrowables getClassifier() { 589 return new DefaultClassifier(); 590 } 591 visitTreeEntry(ITestIdentifier identifier, boolean hasChildren, int testCount, boolean isDynamicTest, String parentId)592 public void visitTreeEntry(ITestIdentifier identifier, boolean hasChildren, int testCount, boolean isDynamicTest, String parentId) { 593 String treeEntry= getTestId(identifier) + ',' + escapeText(identifier.getName()) + ',' + hasChildren + ',' + testCount 594 + ',' + isDynamicTest + ',' + parentId + ',' + escapeText(identifier.getDisplayName()) + ',' + escapeText(identifier.getParameterTypes()) 595 + ',' + escapeText(identifier.getUniqueId()); 596 notifyTestTreeEntry(treeEntry); 597 } 598 escapeText(String s)599 public static String escapeText(String s) { 600 if ((s.indexOf(',') < 0) && (s.indexOf('\\') < 0) && (s.indexOf('\r') < 0) && (s.indexOf('\n') < 0)) 601 return s; 602 StringBuffer sb= new StringBuffer(s.length()+10); 603 for (int i= 0; i < s.length(); i++) { 604 char c= s.charAt(i); 605 switch (c) { 606 case ',': 607 sb.append("\\,"); //$NON-NLS-1$ 608 break; 609 case '\\': 610 sb.append("\\\\"); //$NON-NLS-1$ 611 break; 612 case '\r': 613 if (i + 1 < s.length() && s.charAt(i + 1) == '\n') { 614 i++; 615 } 616 sb.append(' '); 617 break; 618 case '\n': 619 sb.append(' '); 620 break; 621 default: 622 sb.append(c); 623 break; 624 } 625 } 626 return sb.toString(); 627 } 628 629 // WANT: work in bug fixes since RC2? getTestId(ITestIdentifier id)630 public String getTestId(ITestIdentifier id) { 631 return fIds.getTestId(id); 632 } 633 634 /** 635 * Stop the current test run. 636 */ stop()637 protected void stop() { 638 if (fExecution != null) { 639 fExecution.stop(); 640 } 641 } 642 643 /** 644 * Connect to the remote test listener. 645 * 646 * @return <code>true</code> if connection successful, <code>false</code> if failed 647 */ connect()648 protected boolean connect() { 649 if (fConsoleMode) { 650 fClientSocket = null; 651 fWriter = new PrintWriter(System.out); 652 fReader = new BufferedReader(new InputStreamReader(System.in)); 653 fReaderThread= new ReaderThread(); 654 fReaderThread.start(); 655 return true; 656 } 657 if (fDebugMode) 658 System.out.println("RemoteTestRunner: trying to connect" + fHost + ":" + fPort); //$NON-NLS-1$ //$NON-NLS-2$ 659 Exception exception= null; 660 for (int i= 1; i < 20; i++) { 661 try{ 662 fClientSocket= new Socket(fHost, fPort); 663 try { 664 fWriter= new PrintWriter(new BufferedWriter(new OutputStreamWriter(fClientSocket.getOutputStream(), "UTF-8")), false/*true*/); //$NON-NLS-1$ 665 } catch (UnsupportedEncodingException e1) { 666 fWriter= new PrintWriter(new BufferedWriter(new OutputStreamWriter(fClientSocket.getOutputStream())), false/*true*/); 667 } 668 try { 669 fReader= new BufferedReader(new InputStreamReader(fClientSocket.getInputStream(), "UTF-8")); //$NON-NLS-1$ 670 } catch (UnsupportedEncodingException e1) { 671 fReader= new BufferedReader(new InputStreamReader(fClientSocket.getInputStream())); 672 } 673 fReaderThread= new ReaderThread(); 674 fReaderThread.start(); 675 return true; 676 } catch(IOException e){ 677 exception= e; 678 } 679 try { 680 Thread.sleep(2000); 681 } catch(InterruptedException e) { 682 } 683 } 684 runFailed(JUnitMessages.getFormattedString("RemoteTestRunner.error.connect", new String[]{fHost, Integer.toString(fPort)} ), exception); //$NON-NLS-1$ 685 return false; 686 } 687 688 /** 689 * Shutsdown the connection to the remote test listener. 690 */ shutDown()691 private void shutDown() { 692 if (fWriter != null) { 693 fWriter.close(); 694 fWriter= null; 695 } 696 try { 697 if (fReaderThread != null) { 698 // interrupt reader thread so that we don't block on close 699 // on a lock held by the BufferedReader 700 // fix for bug: 38955 701 fReaderThread.interrupt(); 702 } 703 if (fReader != null) { 704 fReader.close(); 705 fReader= null; 706 } 707 } catch(IOException e) { 708 if (fDebugMode) 709 e.printStackTrace(); 710 } 711 712 try { 713 if (fClientSocket != null) { 714 fClientSocket.close(); 715 fClientSocket= null; 716 } 717 } catch(IOException e) { 718 if (fDebugMode) 719 e.printStackTrace(); 720 } 721 } 722 723 /* 724 * @see org.eclipse.jdt.internal.junit.runner.MessageSender#sendMessage(java.lang.String) 725 */ sendMessage(String msg)726 public void sendMessage(String msg) { 727 if(fWriter == null) 728 return; 729 fWriter.println(msg); 730 // if (!fConsoleMode) 731 // System.out.println(msg); 732 } 733 notifyTestRunStarted(int testCount)734 protected void notifyTestRunStarted(int testCount) { 735 fSender.sendMessage(MessageIds.TEST_RUN_START + testCount + " " + "v2"); //$NON-NLS-1$ //$NON-NLS-2$ 736 } 737 notifyTestRunEnded(long elapsedTime)738 private void notifyTestRunEnded(long elapsedTime) { 739 fSender.sendMessage(MessageIds.TEST_RUN_END + elapsedTime); 740 fSender.flush(); 741 //shutDown(); 742 } 743 notifyTestRunStopped(long elapsedTime)744 protected void notifyTestRunStopped(long elapsedTime) { 745 fSender.sendMessage(MessageIds.TEST_STOPPED + elapsedTime); 746 fSender.flush(); 747 //shutDown(); 748 } 749 notifyTestTreeEntry(String treeEntry)750 protected void notifyTestTreeEntry(String treeEntry) { 751 fSender.sendMessage(MessageIds.TEST_TREE + treeEntry); 752 } 753 754 /* 755 * @see org.eclipse.jdt.internal.junit.runner.RerunCompletionListener#notifyRerunComplete(org.eclipse.jdt.internal.junit.runner.RerunRequest, 756 * java.lang.String) 757 */ notifyRerunComplete(RerunRequest r, String status)758 public void notifyRerunComplete(RerunRequest r, String status) { 759 if (fPort != -1) { 760 fSender.sendMessage(MessageIds.TEST_RERAN + r.fRerunTestId + " " + r.fRerunClassName + " " + r.fRerunTestName + " " + status); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 761 fSender.flush(); 762 } 763 } 764 flush()765 public void flush() { 766 fWriter.flush(); 767 } 768 runTests(TestExecution execution)769 public void runTests(TestExecution execution) { 770 runTests(fTestClassNames, fTestName, execution); 771 } 772 getTestLoader()773 public ITestLoader getTestLoader() { 774 return fLoader; 775 } 776 loadClass(String className, RemoteTestRunner listener)777 public Class<?> loadClass(String className, RemoteTestRunner listener) { 778 Class<?> clazz= null; 779 try { 780 clazz= getTestClassLoader().loadClass(className); 781 } catch (ClassNotFoundException e) { 782 listener.runFailed(JUnitMessages.getFormattedString("RemoteTestRunner.error.classnotfound", className), e); //$NON-NLS-1$ 783 } 784 return clazz; 785 } 786 } 787