1 12 package org.eclipse.jdt.internal.junit.runner; 13 14 import java.io.BufferedReader ; 15 import java.io.BufferedWriter ; 16 import java.io.File ; 17 import java.io.FileReader ; 18 import java.io.IOException ; 19 import java.io.InputStreamReader ; 20 import java.io.OutputStreamWriter ; 21 import java.io.PrintWriter ; 22 import java.io.StringWriter ; 23 import java.io.UnsupportedEncodingException ; 24 import java.net.Socket ; 25 import java.util.Vector ; 26 27 import org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestLoader; 28 29 33 public class RemoteTestRunner implements MessageSender, IVisitsTestTrees { 34 37 private static class RerunRequest { 38 String fRerunClassName; 39 String fRerunTestName; 40 int fRerunTestId; 41 42 public RerunRequest(int testId, String className, String testName) { 43 fRerunTestId= testId; 44 fRerunClassName= className; 45 fRerunTestName= testName; 46 } 47 48 } 49 50 public static final String RERAN_FAILURE = "FAILURE"; 52 public static final String RERAN_ERROR = "ERROR"; 54 public static final String RERAN_OK = "OK"; 56 59 private String [] fTestClassNames; 60 63 private String fTestName; 64 67 private TestExecution fExecution; 68 69 72 private String fVersion= ""; 74 77 private Socket fClientSocket; 78 81 private PrintWriter fWriter; 82 85 private BufferedReader fReader; 86 89 private String fHost= ""; 93 private int fPort= -1; 94 97 private boolean fDebugMode= false; 98 102 private boolean fKeepAlive= false; 103 106 private boolean fStopped= false; 107 110 private Vector fRerunRequests= new Vector (10); 111 114 private ReaderThread fReaderThread; 115 116 private String fRerunTest; 117 118 private final TestIdMap fIds = new TestIdMap(); 119 120 private String [] fFailureNames; 121 122 private ITestLoader fLoader; 123 124 private MessageSender fSender; 125 126 private boolean fConsoleMode = false; 127 128 131 private class ReaderThread extends Thread { 132 public ReaderThread() { 133 super("ReaderThread"); } 135 136 public void run(){ 137 try { 138 String message= null; 139 while (true) { 140 if ((message= fReader.readLine()) != null) { 141 142 if (message.startsWith(MessageIds.TEST_STOP)){ 143 fStopped= true; 144 RemoteTestRunner.this.stop(); 145 synchronized(RemoteTestRunner.this) { 146 RemoteTestRunner.this.notifyAll(); 147 } 148 break; 149 } 150 151 else if (message.startsWith(MessageIds.TEST_RERUN)) { 152 String arg= message.substring(MessageIds.MSG_HEADER_LENGTH); 153 int c0= arg.indexOf(' '); 155 int c1= arg.indexOf(' ', c0+1); 156 String s= arg.substring(0, c0); 157 int testId= Integer.parseInt(s); 158 String className= arg.substring(c0+1, c1); 159 String testName= arg.substring(c1+1, arg.length()); 160 synchronized(RemoteTestRunner.this) { 161 fRerunRequests.add(new RerunRequest(testId, className, testName)); 162 RemoteTestRunner.this.notifyAll(); 163 } 164 } 165 } 166 } 167 } catch (Exception e) { 168 RemoteTestRunner.this.stop(); 169 } 170 } 171 } 172 173 public RemoteTestRunner() { 174 setMessageSender(this); 175 } 176 177 public void setMessageSender(MessageSender sender) { 178 fSender = sender; 179 } 180 181 192 public static void main(String [] args) { 193 try { 194 RemoteTestRunner testRunServer= new RemoteTestRunner(); 195 testRunServer.init(args); 196 testRunServer.run(); 197 } catch (Throwable e) { 198 e.printStackTrace(); } finally { 200 System.exit(0); 202 } 203 } 204 205 209 protected void init(String [] args) { 210 defaultInit(args); 211 } 212 213 217 protected ClassLoader getTestClassLoader() { 218 return getClass().getClassLoader(); 219 } 220 221 224 protected final void defaultInit(String [] args) { 225 for(int i= 0; i < args.length; i++) { 226 if(args[i].toLowerCase().equals("-classnames") || args[i].toLowerCase().equals("-classname")){ Vector list= new Vector (); 228 for (int j= i+1; j < args.length; j++) { 229 if (args[j].startsWith("-")) break; 231 list.add(args[j]); 232 } 233 fTestClassNames= (String []) list.toArray(new String [list.size()]); 234 } 235 else if(args[i].toLowerCase().equals("-test")) { String testName= args[i+1]; 237 int p= testName.indexOf(':'); 238 if (p == -1) 239 throw new IllegalArgumentException ("Testname not separated by \'%\'"); fTestName= testName.substring(p+1); 241 fTestClassNames= new String []{ testName.substring(0, p) }; 242 i++; 243 } 244 else if(args[i].toLowerCase().equals("-testnamefile")) { String testNameFile= args[i+1]; 246 try { 247 readTestNames(testNameFile); 248 } catch (IOException e) { 249 throw new IllegalArgumentException ("Cannot read testname file."); } 251 i++; 252 253 } else if(args[i].toLowerCase().equals("-testfailures")) { String testFailuresFile= args[i+1]; 255 try { 256 readFailureNames(testFailuresFile); 257 } catch (IOException e) { 258 throw new IllegalArgumentException ("Cannot read testfailures file."); } 260 i++; 261 262 } else if(args[i].toLowerCase().equals("-port")) { fPort= Integer.parseInt(args[i+1]); 264 i++; 265 } 266 else if(args[i].toLowerCase().equals("-host")) { fHost= args[i+1]; 268 i++; 269 } 270 else if(args[i].toLowerCase().equals("-rerun")) { fRerunTest= args[i+1]; 272 i++; 273 } 274 else if(args[i].toLowerCase().equals("-keepalive")) { fKeepAlive= true; 276 } 277 else if(args[i].toLowerCase().equals("-debugging") || args[i].toLowerCase().equals("-debug")){ fDebugMode= true; 279 } 280 else if(args[i].toLowerCase().equals("-version")){ fVersion= args[i+1]; 282 i++; 283 } else if (args[i].toLowerCase().equals("-junitconsole")) { fConsoleMode = true; 285 } else if (args[i].toLowerCase().equals("-testloaderclass")) { String className = args[i + 1]; 287 createLoader(className); 288 i++; 289 } 290 } 291 292 if (getTestLoader() == null) 293 initDefaultLoader(); 294 295 if(fTestClassNames == null || fTestClassNames.length == 0) 296 throw new IllegalArgumentException (JUnitMessages.getString("RemoteTestRunner.error.classnamemissing")); 298 if (fPort == -1) 299 throw new IllegalArgumentException (JUnitMessages.getString("RemoteTestRunner.error.portmissing")); if (fDebugMode) 301 System.out.println("keepalive "+fKeepAlive); } 303 304 public void initDefaultLoader() { 305 createLoader(JUnit3TestLoader.class.getName()); 306 } 307 308 public void createLoader(String className) { 309 setLoader(createRawTestLoader(className)); 310 } 311 312 protected ITestLoader createRawTestLoader(String className) { 313 try { 314 return (ITestLoader) loadTestLoaderClass(className).newInstance(); 315 } catch (Exception e) { 316 StringWriter trace= new StringWriter (); 317 e.printStackTrace(new PrintWriter (trace)); 318 String message= JUnitMessages.getFormattedString("RemoteTestRunner.error.invalidloader", new Object [] {className, trace.toString()}); throw new IllegalArgumentException (message); 320 } 321 } 322 323 protected Class loadTestLoaderClass(String className) throws ClassNotFoundException { 324 return Class.forName(className); 325 } 326 327 public void setLoader(ITestLoader newInstance) { 328 fLoader = newInstance; 329 } 330 331 private void readTestNames(String testNameFile) throws IOException { 332 BufferedReader br= new BufferedReader (new FileReader (new File (testNameFile))); 333 try { 334 String line; 335 Vector list= new Vector (); 336 while ((line= br.readLine()) != null) { 337 list.add(line); 338 } 339 fTestClassNames= (String []) list.toArray(new String [list.size()]); 340 } 341 finally { 342 br.close(); 343 } 344 if (fDebugMode) { 345 System.out.println("Tests:"); for (int i= 0; i < fTestClassNames.length; i++) { 347 System.out.println(" "+fTestClassNames[i]); } 349 } 350 } 351 352 private void readFailureNames(String testFailureFile) throws IOException { 353 BufferedReader br= new BufferedReader (new FileReader (new File (testFailureFile))); 354 try { 355 String line; 356 Vector list= new Vector (); 357 while ((line= br.readLine()) != null) { 358 list.add(line); 359 } 360 fFailureNames= (String []) list.toArray(new String [list.size()]); 361 } 362 finally { 363 br.close(); 364 } 365 if (fDebugMode) { 366 System.out.println("Failures:"); for (int i= 0; i < fFailureNames.length; i++) { 368 System.out.println(" "+fFailureNames[i]); } 370 } 371 } 372 373 376 protected void run() { 377 if (!connect()) 378 return; 379 if (fRerunTest != null) { 380 rerunTest(new RerunRequest(Integer.parseInt(fRerunTest), fTestClassNames[0], fTestName)); 381 return; 382 } 383 384 FirstRunExecutionListener listener= firstRunExecutionListener(); 385 fExecution= new TestExecution(listener, getClassifier()); 386 runTests(fExecution); 387 if (fKeepAlive) 388 waitForReruns(); 389 390 shutDown(); 391 392 } 393 394 public FirstRunExecutionListener firstRunExecutionListener() { 395 return new FirstRunExecutionListener(fSender, fIds); 396 } 397 398 401 private synchronized void waitForReruns() { 402 while (!fStopped) { 403 try { 404 wait(); 405 if (!fStopped && fRerunRequests.size() > 0) { 406 RerunRequest r= (RerunRequest)fRerunRequests.remove(0); 407 rerunTest(r); 408 } 409 } catch (InterruptedException e) { 410 } 411 } 412 } 413 414 public void runFailed(String message, Exception exception) { 415 System.err.println(message); 417 if (exception != null) 418 exception.printStackTrace(System.err); 419 } 420 421 protected Class [] loadClasses(String [] testClassNames) { 422 Vector classes= new Vector (); 423 for (int i = 0; i < testClassNames.length; i++) { 424 String name = testClassNames[i]; 425 Class clazz = loadClass(name, this); 426 if (clazz != null) { 427 classes.add(clazz); 428 } 429 } 430 return (Class []) classes.toArray(new Class [classes.size()]); 431 } 432 433 protected void notifyListenersOfTestEnd(TestExecution execution, 434 long testStartTime) { 435 if (execution == null || execution.shouldStop()) 436 notifyTestRunStopped(System.currentTimeMillis() - testStartTime); 437 else 438 notifyTestRunEnded(System.currentTimeMillis() - testStartTime); 439 } 440 441 444 public void runTests(String [] testClassNames, String testName, TestExecution execution) { 445 ITestReference[] suites= fLoader.loadTests(loadClasses(testClassNames), testName, fFailureNames, this); 446 447 int count= countTests(suites); 449 450 notifyTestRunStarted(count); 451 452 if (count == 0) { 453 notifyTestRunEnded(0); 454 return; 455 } 456 457 sendTrees(suites); 458 459 long testStartTime= System.currentTimeMillis(); 460 execution.run(suites); 461 notifyListenersOfTestEnd(execution, testStartTime); 462 } 463 464 private void sendTrees(ITestReference[] suites) { 465 long startTime = System.currentTimeMillis(); 466 if (fDebugMode) 467 System.out.print("start send tree..."); for (int i = 0; i < suites.length; i++) { 469 suites[i].sendTree(this); 470 } 471 if (fDebugMode) 472 System.out.println("done send tree - time(ms): " + (System.currentTimeMillis() - startTime)); } 474 475 private int countTests(ITestReference[] tests) { 476 int count= 0; 477 for (int i= 0; i < tests.length; i++) { 478 ITestReference test= tests[i]; 479 if (test != null) 480 count= count + test.countTestCases(); 481 } 482 return count; 483 } 484 485 489 public void rerunTest(RerunRequest r) { 490 final Class [] classes= loadClasses(new String [] { r.fRerunClassName }); 491 ITestReference rerunTest1= fLoader.loadTests(classes, r.fRerunTestName, null, this)[0]; 492 RerunExecutionListener service= rerunExecutionListener(); 493 494 TestExecution execution= new TestExecution(service, getClassifier()); 495 ITestReference[] suites= new ITestReference[] { rerunTest1 }; 496 execution.run(suites); 497 498 notifyRerunComplete(r, service.getStatus()); 499 } 500 501 public RerunExecutionListener rerunExecutionListener() { 502 return new RerunExecutionListener(fSender, fIds); 503 } 504 505 protected IClassifiesThrowables getClassifier() { 506 return new DefaultClassifier(fVersion); 507 } 508 509 public void visitTreeEntry(ITestIdentifier id, boolean b, int i) { 510 notifyTestTreeEntry(getTestId(id) + ',' + escapeComma(id.getName()) + ',' + b + ',' + i); 511 } 512 513 private String escapeComma(String s) { 514 if ((s.indexOf(',') < 0) && (s.indexOf('\\') < 0)) 515 return s; 516 StringBuffer sb= new StringBuffer (s.length()+10); 517 for (int i= 0; i < s.length(); i++) { 518 char c= s.charAt(i); 519 if (c == ',') 520 sb.append("\\,"); else if (c == '\\') 522 sb.append("\\\\"); else 524 sb.append(c); 525 } 526 return sb.toString(); 527 } 528 529 private String getTestId(ITestIdentifier id) { 531 return fIds.getTestId(id); 532 } 533 534 537 protected void stop() { 538 if (fExecution != null) { 539 fExecution.stop(); 540 } 541 } 542 543 546 protected boolean connect() { 547 if (fConsoleMode) { 548 fClientSocket = null; 549 fWriter = new PrintWriter (System.out); 550 fReader = new BufferedReader (new InputStreamReader (System.in)); 551 fReaderThread= new ReaderThread(); 552 fReaderThread.start(); 553 return true; 554 } 555 if (fDebugMode) 556 System.out.println("RemoteTestRunner: trying to connect" + fHost + ":" + fPort); Exception exception= null; 558 for (int i= 1; i < 20; i++) { 559 try{ 560 fClientSocket= new Socket (fHost, fPort); 561 try { 562 fWriter= new PrintWriter (new BufferedWriter (new OutputStreamWriter (fClientSocket.getOutputStream(), "UTF-8")), false); } catch (UnsupportedEncodingException e1) { 564 fWriter= new PrintWriter (new BufferedWriter (new OutputStreamWriter (fClientSocket.getOutputStream())), false); 565 } 566 try { 567 fReader= new BufferedReader (new InputStreamReader (fClientSocket.getInputStream(), "UTF-8")); } catch (UnsupportedEncodingException e1) { 569 fReader= new BufferedReader (new InputStreamReader (fClientSocket.getInputStream())); 570 } 571 fReaderThread= new ReaderThread(); 572 fReaderThread.start(); 573 return true; 574 } catch(IOException e){ 575 exception= e; 576 } 577 try { 578 Thread.sleep(2000); 579 } catch(InterruptedException e) { 580 } 581 } 582 runFailed(JUnitMessages.getFormattedString("RemoteTestRunner.error.connect", new String []{fHost, Integer.toString(fPort)} ), exception); return false; 584 } 585 586 589 private void shutDown() { 590 if (fWriter != null) { 591 fWriter.close(); 592 fWriter= null; 593 } 594 try { 595 if (fReaderThread != null) { 596 fReaderThread.interrupt(); 600 } 601 if (fReader != null) { 602 fReader.close(); 603 fReader= null; 604 } 605 } catch(IOException e) { 606 if (fDebugMode) 607 e.printStackTrace(); 608 } 609 610 try { 611 if (fClientSocket != null) { 612 fClientSocket.close(); 613 fClientSocket= null; 614 } 615 } catch(IOException e) { 616 if (fDebugMode) 617 e.printStackTrace(); 618 } 619 } 620 621 624 public void sendMessage(String msg) { 625 if(fWriter == null) 626 return; 627 fWriter.println(msg); 628 } 631 632 protected void notifyTestRunStarted(int testCount) { 633 fSender.sendMessage(MessageIds.TEST_RUN_START + testCount + " " + "v2"); } 635 636 private void notifyTestRunEnded(long elapsedTime) { 637 fSender.sendMessage(MessageIds.TEST_RUN_END + elapsedTime); 638 fSender.flush(); 639 } 641 642 protected void notifyTestRunStopped(long elapsedTime) { 643 fSender.sendMessage(MessageIds.TEST_STOPPED + elapsedTime); 644 fSender.flush(); 645 } 647 648 protected void notifyTestTreeEntry(String treeEntry) { 649 fSender.sendMessage(MessageIds.TEST_TREE + treeEntry); 650 } 651 652 656 public void notifyRerunComplete(RerunRequest r, String status) { 657 if (fPort != -1) { 658 fSender.sendMessage(MessageIds.TEST_RERAN + r.fRerunTestId + " " + r.fRerunClassName + " " + r.fRerunTestName + " " + status); fSender.flush(); 660 } 661 } 662 663 public void flush() { 664 fWriter.flush(); 665 } 666 667 672 public void runTests(TestExecution execution) { 673 runTests(fTestClassNames, fTestName, execution); 674 } 675 676 public ITestLoader getTestLoader() { 677 return fLoader; 678 } 679 680 public Class loadClass(String className, RemoteTestRunner listener) { 681 Class clazz= null; 682 try { 683 clazz= getTestClassLoader().loadClass(className); 684 } catch (ClassNotFoundException e) { 685 listener.runFailed(JUnitMessages.getFormattedString("RemoteTestRunner.error.classnotfound", className), e); } 687 return clazz; 688 } 689 } 690 | Popular Tags |