1 11 12 package org.eclipse.jdt.internal.junit.model; 13 14 import java.io.File ; 15 import java.text.SimpleDateFormat ; 16 import java.util.ArrayList ; 17 import java.util.Arrays ; 18 import java.util.Date ; 19 import java.util.HashMap ; 20 import java.util.List ; 21 22 import org.eclipse.core.runtime.Assert; 23 import org.eclipse.core.runtime.CoreException; 24 import org.eclipse.core.runtime.ListenerList; 25 26 import org.eclipse.debug.core.DebugPlugin; 27 import org.eclipse.debug.core.ILaunch; 28 import org.eclipse.debug.core.ILaunchConfiguration; 29 import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; 30 import org.eclipse.debug.core.ILaunchManager; 31 import org.eclipse.debug.core.ILaunchesListener2; 32 33 import org.eclipse.jdt.core.IJavaProject; 34 35 import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; 36 37 import org.eclipse.jdt.junit.model.ITestElement; 38 import org.eclipse.jdt.junit.model.ITestElementContainer; 39 import org.eclipse.jdt.junit.model.ITestRunSession; 40 41 import org.eclipse.jdt.internal.junit.Messages; 42 import org.eclipse.jdt.internal.junit.launcher.ITestKind; 43 import org.eclipse.jdt.internal.junit.launcher.JUnitLaunchConfigurationConstants; 44 import org.eclipse.jdt.internal.junit.model.TestElement.Status; 45 import org.eclipse.jdt.internal.junit.runner.MessageIds; 46 import org.eclipse.jdt.internal.junit.ui.JUnitMessages; 47 import org.eclipse.jdt.internal.junit.ui.JUnitPlugin; 48 49 53 public class TestRunSession implements ITestRunSession { 54 55 58 private final ILaunch fLaunch; 59 private final String fTestRunName; 60 63 private final IJavaProject fProject; 64 65 private final ITestKind fTestRunnerKind; 66 67 70 private RemoteTestRunnerClient fTestRunnerClient; 71 72 private final ListenerList fSessionListeners; 73 74 77 private TestRoot fTestRoot; 78 79 82 private Result fTestResult; 83 84 87 private HashMap fIdToTest; 88 89 92 private List fIncompleteTestSuites; 93 94 97 private TestSuiteElement fUnrootedSuite; 98 99 102 volatile int fStartedCount; 103 106 volatile int fIgnoredCount; 107 110 volatile int fErrorCount; 111 114 volatile int fFailureCount; 115 118 volatile int fTotalCount; 119 122 volatile long fStartTime; 123 volatile boolean fIsRunning; 124 125 volatile boolean fIsStopped; 126 127 128 132 public TestRunSession(String testRunName, IJavaProject project) { 133 135 fLaunch= null; 136 fProject= null; 138 Assert.isNotNull(testRunName); 139 fTestRunName= testRunName; 140 fTestRunnerKind= ITestKind.NULL; 142 fTestRoot= new TestRoot(this); 143 fIdToTest= new HashMap (); 144 145 fTestRunnerClient= null; 146 147 fSessionListeners= new ListenerList(); 148 } 149 150 151 public TestRunSession(ILaunch launch, IJavaProject project, int port) { 152 Assert.isNotNull(launch); 153 154 fLaunch= launch; 155 fProject= project; 156 157 ILaunchConfiguration launchConfiguration= launch.getLaunchConfiguration(); 158 if (launchConfiguration != null) { 159 fTestRunName= launchConfiguration.getName(); 160 fTestRunnerKind= JUnitLaunchConfigurationConstants.getTestRunnerKind(launchConfiguration); 161 } else { 162 fTestRunName= project.getElementName(); 163 fTestRunnerKind= ITestKind.NULL; 164 } 165 166 fTestRoot= new TestRoot(this); 167 fIdToTest= new HashMap (); 168 169 fTestRunnerClient= new RemoteTestRunnerClient(); 170 fTestRunnerClient.startListening(new ITestRunListener2[] { new TestSessionNotifier() }, port); 171 172 final ILaunchManager launchManager= DebugPlugin.getDefault().getLaunchManager(); 173 launchManager.addLaunchListener(new ILaunchesListener2() { 174 public void launchesTerminated(ILaunch[] launches) { 175 if (Arrays.asList(launches).contains(fLaunch)) { 176 if (fTestRunnerClient != null) { 177 fTestRunnerClient.stopWaiting(); 178 } 179 launchManager.removeLaunchListener(this); 180 } 181 } 182 public void launchesRemoved(ILaunch[] launches) { 183 if (Arrays.asList(launches).contains(fLaunch)) { 184 if (fTestRunnerClient != null) { 185 fTestRunnerClient.stopWaiting(); 186 } 187 launchManager.removeLaunchListener(this); 188 } 189 } 190 public void launchesChanged(ILaunch[] launches) { 191 } 192 public void launchesAdded(ILaunch[] launches) { 193 } 194 }); 195 196 fSessionListeners= new ListenerList(); 197 addTestSessionListener(new TestRunListenerAdapter(this)); 198 } 199 200 void reset() { 201 fStartedCount= 0; 202 fFailureCount= 0; 203 fErrorCount= 0; 204 fIgnoredCount= 0; 205 fTotalCount= 0; 206 207 fTestRoot= new TestRoot(this); 208 fTestResult= null; 209 fIdToTest= new HashMap (); 210 } 211 212 215 public ProgressState getProgressState() { 216 if (isRunning()) { 217 return ProgressState.RUNNING; 218 } 219 if (isStopped()) { 220 return ProgressState.STOPPED; 221 } 222 return ProgressState.COMPLETED; 223 } 224 225 228 public Result getTestResult(boolean includeChildren) { 229 if (fTestRoot != null) { 230 return fTestRoot.getTestResult(true); 231 } else { 232 return fTestResult; 233 } 234 } 235 236 239 public ITestElement[] getChildren() { 240 return getTestRoot().getChildren(); 241 } 242 243 246 public FailureTrace getFailureTrace() { 247 return null; 248 } 249 250 253 public ITestElementContainer getParentContainer() { 254 return null; 255 } 256 257 260 public ITestRunSession getTestRunSession() { 261 return this; 262 } 263 264 265 public TestRoot getTestRoot() { 266 swapIn(); return fTestRoot; 268 } 269 270 273 public IJavaProject getLaunchedProject() { 274 return fProject; 275 } 276 277 public ITestKind getTestRunnerKind() { 278 return fTestRunnerKind; 279 } 280 281 282 285 public ILaunch getLaunch() { 286 return fLaunch; 287 } 288 289 public String getTestRunName() { 290 return fTestRunName; 291 } 292 293 public int getErrorCount() { 294 return fErrorCount; 295 } 296 297 public int getFailureCount() { 298 return fFailureCount; 299 } 300 301 public int getStartedCount() { 302 return fStartedCount; 303 } 304 305 public int getIgnoredCount() { 306 return fIgnoredCount; 307 } 308 309 public int getTotalCount() { 310 return fTotalCount; 311 } 312 313 public long getStartTime() { 314 return fStartTime; 315 } 316 317 320 public boolean isStopped() { 321 return fIsStopped; 322 } 323 324 public void addTestSessionListener(ITestSessionListener listener) { 325 swapIn(); 326 fSessionListeners.add(listener); 327 } 328 329 public void removeTestSessionListener(ITestSessionListener listener) { 330 fSessionListeners.remove(listener); 331 } 332 333 public void swapOut() { 334 if (fTestRoot == null) 335 return; 336 if (isRunning() || isStarting() || isKeptAlive()) 337 return; 338 339 Object [] listeners= fSessionListeners.getListeners(); 340 for (int i= 0; i < listeners.length; ++i) { 341 ITestSessionListener registered= (ITestSessionListener) listeners[i]; 342 if (! registered.acceptsSwapToDisk()) 343 return; 344 } 345 346 try { 347 File swapFile= getSwapFile(); 348 349 JUnitModel.exportTestRunSession(this, swapFile); 350 fTestResult= fTestRoot.getTestResult(true); 351 fTestRoot= null; 352 fTestRunnerClient= null; 353 fIdToTest= new HashMap (); 354 fIncompleteTestSuites= null; 355 fUnrootedSuite= null; 356 357 } catch (IllegalStateException e) { 358 JUnitPlugin.log(e); 359 } catch (CoreException e) { 360 JUnitPlugin.log(e); 361 } 362 } 363 364 private boolean isStarting() { 365 return getStartTime() == 0 && fLaunch != null && ! fLaunch.isTerminated(); 366 } 367 368 369 public void removeSwapFile() { 370 File swapFile= getSwapFile(); 371 if (swapFile.exists()) 372 swapFile.delete(); 373 } 374 375 private File getSwapFile() throws IllegalStateException { 376 File historyDir= JUnitPlugin.getHistoryDirectory(); 377 String isoTime= new SimpleDateFormat ("yyyyMMdd-HHmmss.SSS").format(new Date (getStartTime())); String swapFileName= isoTime + ".xml"; return new File (historyDir, swapFileName); 380 } 381 382 383 public void swapIn() { 384 if (fTestRoot != null) 385 return; 386 387 try { 388 JUnitModel.importIntoTestRunSession(getSwapFile(), this); 389 } catch (IllegalStateException e) { 390 JUnitPlugin.log(e); 391 fTestRoot= new TestRoot(this); 392 fTestResult= null; 393 } catch (CoreException e) { 394 JUnitPlugin.log(e); 395 fTestRoot= new TestRoot(this); 396 fTestResult= null; 397 } 398 } 399 400 public void stopTestRun() { 401 if (isRunning() || ! isKeptAlive()) 402 fIsStopped= true; 403 if (fTestRunnerClient != null) 404 fTestRunnerClient.stopTest(); 405 } 406 407 410 public boolean isKeptAlive() { 411 if (fTestRunnerClient != null 412 && fLaunch != null 413 && fTestRunnerClient.isRunning() 414 && ILaunchManager.DEBUG_MODE.equals(fLaunch.getLaunchMode())) { 415 ILaunchConfiguration config= fLaunch.getLaunchConfiguration(); 416 try { 417 return config != null 418 && config.getAttribute(JUnitLaunchConfigurationConstants.ATTR_KEEPRUNNING, false); 419 } catch (CoreException e) { 420 return false; 421 } 422 423 } else { 424 return false; 425 } 426 } 427 428 431 public boolean isRunning() { 432 return fIsRunning; 433 } 434 435 443 public boolean rerunTest(String testId, String className, String testName, String launchMode) throws CoreException { 444 if (isKeptAlive()) { 445 Status status= ((TestCaseElement) getTestElement(testId)).getStatus(); 446 if (status == Status.ERROR) { 447 fErrorCount--; 448 } else if (status == Status.FAILURE) { 449 fFailureCount--; 450 } 451 fTestRunnerClient.rerunTest(testId, className, testName); 452 return true; 453 454 } else if (fLaunch != null) { 455 ILaunchConfiguration launchConfiguration= fLaunch.getLaunchConfiguration(); 457 if (launchConfiguration != null) { 458 459 String name= className; 460 if (testName != null) 461 name+= "."+testName; String configName= Messages.format(JUnitMessages.TestRunnerViewPart_configName, name); 463 ILaunchConfigurationWorkingCopy tmp= launchConfiguration.copy(configName); 464 tmp.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, className); 466 tmp.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_CONTAINER, ""); if (testName != null) { 469 tmp.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_METHOD_NAME, testName); 470 } 473 tmp.launch(launchMode, null); 474 return true; 475 } 476 } 477 478 return false; 479 } 480 481 public TestElement getTestElement(String id) { 482 return (TestElement) fIdToTest.get(id); 483 } 484 485 private TestElement addTreeEntry(String treeEntry) { 486 int index0= treeEntry.indexOf(','); 488 String id= treeEntry.substring(0, index0); 489 490 StringBuffer testNameBuffer= new StringBuffer (100); 491 int index1= scanTestName(treeEntry, index0 + 1, testNameBuffer); 492 String testName= testNameBuffer.toString().trim(); 493 494 int index2= treeEntry.indexOf(',', index1 + 1); 495 boolean isSuite= treeEntry.substring(index1 + 1, index2).equals("true"); 497 int testCount= Integer.parseInt(treeEntry.substring(index2 + 1)); 498 499 if (fIncompleteTestSuites.isEmpty()) { 500 return createTestElement(fTestRoot, id, testName, isSuite, testCount); 501 } else { 502 int suiteIndex= fIncompleteTestSuites.size() - 1; 503 IncompleteTestSuite openSuite= (IncompleteTestSuite) fIncompleteTestSuites.get(suiteIndex); 504 openSuite.fOutstandingChildren--; 505 if (openSuite.fOutstandingChildren <= 0) 506 fIncompleteTestSuites.remove(suiteIndex); 507 return createTestElement(openSuite.fTestSuiteElement, id, testName, isSuite, testCount); 508 } 509 } 510 511 public TestElement createTestElement(TestSuiteElement parent, String id, String testName, boolean isSuite, int testCount) { 512 TestElement testElement; 513 if (isSuite) { 514 TestSuiteElement testSuiteElement= new TestSuiteElement(parent, id, testName, testCount); 515 testElement= testSuiteElement; 516 if (testCount > 0) 517 fIncompleteTestSuites.add(new IncompleteTestSuite(testSuiteElement, testCount)); 518 } else { 519 testElement= new TestCaseElement(parent, id, testName); 520 } 521 fIdToTest.put(id, testElement); 522 return testElement; 523 } 524 525 534 private int scanTestName(String s, int start, StringBuffer testName) { 535 boolean inQuote= false; 536 int i= start; 537 for (; i < s.length(); i++) { 538 char c= s.charAt(i); 539 if (c == '\\' && !inQuote) { 540 inQuote= true; 541 continue; 542 } else if (inQuote) { 543 inQuote= false; 544 testName.append(c); 545 } else if (c == ',') 546 break; 547 else 548 testName.append(c); 549 } 550 return i; 551 } 552 553 558 private class TestSessionNotifier implements ITestRunListener2 { 559 560 public void testRunStarted(int testCount) { 561 fIncompleteTestSuites= new ArrayList (); 562 563 fStartedCount= 0; 564 fIgnoredCount= 0; 565 fFailureCount= 0; 566 fErrorCount= 0; 567 fTotalCount= testCount; 568 569 fStartTime= System.currentTimeMillis(); 570 fIsRunning= true; 571 572 Object [] listeners= fSessionListeners.getListeners(); 573 for (int i= 0; i < listeners.length; ++i) { 574 ((ITestSessionListener) listeners[i]).sessionStarted(); 575 } 576 } 577 578 public void testRunEnded(long elapsedTime) { 579 fIsRunning= false; 580 581 Object [] listeners= fSessionListeners.getListeners(); 582 for (int i= 0; i < listeners.length; ++i) { 583 ((ITestSessionListener) listeners[i]).sessionEnded(elapsedTime); 584 } 585 } 586 587 public void testRunStopped(long elapsedTime) { 588 fIsRunning= false; 589 fIsStopped= true; 590 591 Object [] listeners= fSessionListeners.getListeners(); 592 for (int i= 0; i < listeners.length; ++i) { 593 ((ITestSessionListener) listeners[i]).sessionStopped(elapsedTime); 594 } 595 } 596 597 public void testRunTerminated() { 598 fIsRunning= false; 599 fIsStopped= true; 600 601 Object [] listeners= fSessionListeners.getListeners(); 602 for (int i= 0; i < listeners.length; ++i) { 603 ((ITestSessionListener) listeners[i]).sessionTerminated(); 604 } 605 } 606 607 610 public void testTreeEntry(String description) { 611 TestElement testElement= addTreeEntry(description); 612 613 Object [] listeners= fSessionListeners.getListeners(); 614 for (int i= 0; i < listeners.length; ++i) { 615 ((ITestSessionListener) listeners[i]).testAdded(testElement); 616 } 617 } 618 619 private TestElement createUnrootedTestElement(String testId, String testName) { 620 TestSuiteElement unrootedSuite= getUnrootedSuite(); 621 TestElement testElement= createTestElement(unrootedSuite, testId, testName, false, 1); 622 623 Object [] listeners= fSessionListeners.getListeners(); 624 for (int i= 0; i < listeners.length; ++i) { 625 ((ITestSessionListener) listeners[i]).testAdded(testElement); 626 } 627 628 return testElement; 629 } 630 631 private TestSuiteElement getUnrootedSuite() { 632 if (fUnrootedSuite == null) { 633 fUnrootedSuite= (TestSuiteElement) createTestElement(fTestRoot, "-2", JUnitMessages.TestRunSession_unrootedTests, true, 0); } 635 return fUnrootedSuite; 636 } 637 638 public void testStarted(String testId, String testName) { 639 if (fStartedCount == 0) { 640 Object [] listeners= fSessionListeners.getListeners(); 641 for (int i= 0; i < listeners.length; ++i) { 642 ((ITestSessionListener) listeners[i]).runningBegins(); 643 } 644 } 645 TestElement testElement= getTestElement(testId); 646 if (testElement == null) { 647 testElement= createUnrootedTestElement(testId, testName); 648 } else if (! (testElement instanceof TestCaseElement)) { 649 logUnexpectedTest(testId, testElement); 650 return; 651 } 652 TestCaseElement testCaseElement= (TestCaseElement) testElement; 653 setStatus(testCaseElement, Status.RUNNING); 654 655 fStartedCount++; 656 657 Object [] listeners= fSessionListeners.getListeners(); 658 for (int i= 0; i < listeners.length; ++i) { 659 ((ITestSessionListener) listeners[i]).testStarted(testCaseElement); 660 } 661 } 662 663 public void testEnded(String testId, String testName) { 664 TestElement testElement= getTestElement(testId); 665 if (testElement == null) { 666 testElement= createUnrootedTestElement(testId, testName); 667 } else if (! (testElement instanceof TestCaseElement)) { 668 logUnexpectedTest(testId, testElement); 669 return; 670 } 671 TestCaseElement testCaseElement= (TestCaseElement) testElement; 672 if (testName.startsWith(MessageIds.IGNORED_TEST_PREFIX)) { 673 testCaseElement.setIgnored(true); 674 fIgnoredCount++; 675 } 676 677 if (testCaseElement.getStatus() == Status.RUNNING) 678 setStatus(testCaseElement, Status.OK); 679 680 Object [] listeners= fSessionListeners.getListeners(); 681 for (int i= 0; i < listeners.length; ++i) { 682 ((ITestSessionListener) listeners[i]).testEnded(testCaseElement); 683 } 684 } 685 686 687 public void testFailed(int status, String testId, String testName, String trace) { 688 testFailed(status, testId, testName, trace, null, null); 689 } 690 691 694 public void testFailed(int statusCode, String testId, String testName, String trace, String expected, String actual) { 695 TestElement testElement= getTestElement(testId); 696 if (testElement == null) { 697 testElement= createUnrootedTestElement(testId, testName); 698 return; 699 } 700 701 Status status= Status.convert(statusCode); 702 registerTestFailed(testElement, status, trace, nullifyEmpty(expected), nullifyEmpty(actual)); 703 704 Object [] listeners= fSessionListeners.getListeners(); 705 for (int i= 0; i < listeners.length; ++i) { 706 ((ITestSessionListener) listeners[i]).testFailed(testElement, status, trace, expected, actual); 707 } 708 } 709 710 private String nullifyEmpty(String string) { 711 int length= string.length(); 712 if (length == 0) 713 return null; 714 else if (string.charAt(length - 1) == '\n') 715 return string.substring(0, length - 1); 716 else 717 return string; 718 } 719 720 public void testReran(String testId, String testClass, String testName, int status, String trace) { 721 testReran(testId, testClass, testName, status, trace, "", ""); } 723 724 727 public void testReran(String testId, String className, String testName, int statusCode, String trace, String expectedResult, String actualResult) { 728 TestElement testElement= getTestElement(testId); 729 if (testElement == null) { 730 testElement= createUnrootedTestElement(testId, testName); 731 } else if (! (testElement instanceof TestCaseElement)) { 732 logUnexpectedTest(testId, testElement); 733 return; 734 } 735 TestCaseElement testCaseElement= (TestCaseElement) testElement; 736 737 Status status= Status.convert(statusCode); 738 registerTestFailed(testElement, status, trace, nullifyEmpty(expectedResult), nullifyEmpty(actualResult)); 739 740 Object [] listeners= fSessionListeners.getListeners(); 741 for (int i= 0; i < listeners.length; ++i) { 742 ((ITestSessionListener) listeners[i]).testReran(testCaseElement, status, trace, expectedResult, actualResult); 744 } 745 } 746 747 private void logUnexpectedTest(String testId, TestElement testElement) { 748 JUnitPlugin.log(new Exception ("Unexpected TestElement type for testId '" + testId + "': " + testElement)); } 750 } 751 752 private static class IncompleteTestSuite { 753 public TestSuiteElement fTestSuiteElement; 754 public int fOutstandingChildren; 755 756 public IncompleteTestSuite(TestSuiteElement testSuiteElement, int outstandingChildren) { 757 fTestSuiteElement= testSuiteElement; 758 fOutstandingChildren= outstandingChildren; 759 } 760 } 761 762 public void registerTestFailed(TestElement testElement, Status status, String trace, String expected, String actual) { 763 testElement.setStatus(status, trace, expected, actual); 764 if (status.isError()) { 765 fErrorCount++; 766 } else { 767 fFailureCount++; 768 } 769 } 770 771 public void registerTestEnded(TestElement testElement, boolean completed) { 772 if (testElement instanceof TestCaseElement) { 773 fTotalCount++; 774 if (! completed) { 775 return; 776 } 777 fStartedCount++; 778 if (((TestCaseElement) testElement).isIgnored()) { 779 fIgnoredCount++; 780 } 781 if (! testElement.getStatus().isErrorOrFailure()) 782 setStatus(testElement, Status.OK); 783 } 784 } 785 786 private void setStatus(TestElement testElement, Status status) { 787 testElement.setStatus(status); 788 } 789 790 public TestElement[] getAllFailedTestElements() { 791 ArrayList failures= new ArrayList (); 792 addFailures(failures, getTestRoot()); 793 return (TestElement[]) failures.toArray(new TestElement[failures.size()]); 794 } 795 796 private void addFailures(ArrayList failures, ITestElement testElement) { 797 Result testResult= testElement.getTestResult(true); 798 if (testResult == Result.ERROR || testResult == Result.FAILURE) { 799 failures.add(testElement); 800 } 801 if (testElement instanceof TestSuiteElement) { 802 TestSuiteElement testSuiteElement= (TestSuiteElement) testElement; 803 ITestElement[] children= testSuiteElement.getChildren(); 804 for (int i= 0; i < children.length; i++) { 805 addFailures(failures, children[i]); 806 } 807 } 808 } 809 810 811 } 812 | Popular Tags |