1 18 19 package org.apache.tools.ant.taskdefs.optional.junit; 20 21 import java.io.BufferedReader ; 22 import java.io.ByteArrayOutputStream ; 23 import java.io.File ; 24 import java.io.FileInputStream ; 25 import java.io.FileWriter ; 26 import java.io.IOException ; 27 import java.io.OutputStream ; 28 import java.io.PrintStream ; 29 import java.io.PrintWriter ; 30 import java.io.StringReader ; 31 import java.io.StringWriter ; 32 import java.lang.reflect.Method ; 33 import java.util.Enumeration ; 34 import java.util.Hashtable ; 35 import java.util.Properties ; 36 import java.util.StringTokenizer ; 37 import java.util.Vector ; 38 import junit.framework.AssertionFailedError; 39 import junit.framework.Test; 40 import junit.framework.TestFailure; 41 import junit.framework.TestListener; 42 import junit.framework.TestResult; 43 import junit.framework.TestSuite; 44 import org.apache.tools.ant.BuildException; 45 import org.apache.tools.ant.Project; 46 import org.apache.tools.ant.types.Permissions; 47 import org.apache.tools.ant.util.StringUtils; 48 import org.apache.tools.ant.util.TeeOutputStream; 49 50 67 68 public class JUnitTestRunner implements TestListener, JUnitTaskMirror.JUnitTestRunnerMirror { 69 70 73 private Vector formatters = new Vector (); 74 75 78 private TestResult res; 79 80 83 private static boolean filtertrace = true; 84 85 88 private boolean showOutput = false; 89 90 private boolean outputToFormatters = true; 91 92 95 private Permissions perm = null; 96 97 private static final String [] DEFAULT_TRACE_FILTERS = new String [] { 98 "junit.framework.TestCase", 99 "junit.framework.TestResult", 100 "junit.framework.TestSuite", 101 "junit.framework.Assert.", "junit.swingui.TestRunner", 103 "junit.awtui.TestRunner", 104 "junit.textui.TestRunner", 105 "java.lang.reflect.Method.invoke(", 106 "sun.reflect.", 107 "org.apache.tools.ant.", 108 "org.junit.", 110 "junit.framework.JUnit4TestAdapter", 111 "Caused by: java.lang.AssertionError", 113 " more", 114 }; 115 116 117 120 private boolean haltOnError = false; 121 122 125 private boolean haltOnFailure = false; 126 127 130 private int retCode = SUCCESS; 131 132 135 private JUnitTest junitTest; 136 137 138 private PrintStream systemError; 139 140 141 private PrintStream systemOut; 142 143 144 private boolean forked = false; 145 146 147 private static boolean multipleTests = false; 148 149 150 private ClassLoader loader; 151 152 153 private boolean logTestListenerEvents = false; 154 155 156 private boolean junit4; 157 158 162 private static String crashFile = null; 163 164 172 public JUnitTestRunner(JUnitTest test, boolean haltOnError, 173 boolean filtertrace, boolean haltOnFailure) { 174 this(test, haltOnError, filtertrace, haltOnFailure, false); 175 } 176 177 186 public JUnitTestRunner(JUnitTest test, boolean haltOnError, 187 boolean filtertrace, boolean haltOnFailure, 188 boolean showOutput) { 189 this(test, haltOnError, filtertrace, haltOnFailure, showOutput, false); 190 } 191 192 203 public JUnitTestRunner(JUnitTest test, boolean haltOnError, 204 boolean filtertrace, boolean haltOnFailure, 205 boolean showOutput, boolean logTestListenerEvents) { 206 this(test, haltOnError, filtertrace, haltOnFailure, showOutput, 207 logTestListenerEvents, null); 208 } 209 210 218 public JUnitTestRunner(JUnitTest test, boolean haltOnError, 219 boolean filtertrace, boolean haltOnFailure, 220 ClassLoader loader) { 221 this(test, haltOnError, filtertrace, haltOnFailure, false, loader); 222 } 223 224 233 public JUnitTestRunner(JUnitTest test, boolean haltOnError, 234 boolean filtertrace, boolean haltOnFailure, 235 boolean showOutput, ClassLoader loader) { 236 this(test, haltOnError, filtertrace, haltOnFailure, showOutput, 237 false, loader); 238 } 239 240 251 public JUnitTestRunner(JUnitTest test, boolean haltOnError, 252 boolean filtertrace, boolean haltOnFailure, 253 boolean showOutput, boolean logTestListenerEvents, 254 ClassLoader loader) { 255 JUnitTestRunner.filtertrace = filtertrace; 256 this.junitTest = test; 257 this.haltOnError = haltOnError; 258 this.haltOnFailure = haltOnFailure; 259 this.showOutput = showOutput; 260 this.logTestListenerEvents = logTestListenerEvents; 261 this.loader = loader; 262 } 263 264 private PrintStream savedOut = null; 265 266 269 public void run() { 270 res = new TestResult(); 271 res.addListener(wrapListener(this)); 272 for (int i = 0; i < formatters.size(); i++) { 273 res.addListener(wrapListener((TestListener) formatters.elementAt(i))); 274 } 275 276 ByteArrayOutputStream errStrm = new ByteArrayOutputStream (); 277 systemError = new PrintStream (errStrm); 278 279 ByteArrayOutputStream outStrm = new ByteArrayOutputStream (); 280 systemOut = new PrintStream (outStrm); 281 282 PrintStream savedErr = null; 283 284 if (forked) { 285 if (!outputToFormatters) { 286 if (!showOutput) { 287 savedOut = System.out; 288 savedErr = System.err; 289 System.setOut( 290 new PrintStream ( 291 new OutputStream () { 292 public void write(int b) { 293 } 294 })); 295 System.setErr( 296 new PrintStream ( 297 new OutputStream () { 298 public void write(int b) { 299 } 300 })); 301 } 302 } else { 303 savedOut = System.out; 304 savedErr = System.err; 305 if (!showOutput) { 306 System.setOut(systemOut); 307 System.setErr(systemError); 308 } else { 309 System.setOut(new PrintStream ( 310 new TeeOutputStream(savedOut, systemOut) 311 ) 312 ); 313 System.setErr(new PrintStream ( 314 new TeeOutputStream(savedErr, 315 systemError) 316 ) 317 ); 318 } 319 perm = null; 320 } 321 } else { 322 if (perm != null) { 323 perm.setSecurityManager(); 324 } 325 } 326 327 Test suite = null; 328 Throwable exception = null; 329 boolean startTestSuiteSuccess = false; 330 331 try { 332 333 try { 334 Class testClass = null; 335 if (loader == null) { 336 testClass = Class.forName(junitTest.getName()); 337 } else { 338 testClass = Class.forName(junitTest.getName(), true, 339 loader); 340 } 341 342 Method suiteMethod = null; 345 try { 346 suiteMethod = testClass.getMethod("suite", new Class [0]); 348 } catch (NoSuchMethodException e) { 349 } 352 353 if (suiteMethod != null) { 354 suite = (Test) suiteMethod.invoke(null, new Class [0]); 358 359 } else { 360 Class junit4TestAdapterClass = null; 361 362 367 370 try { 371 Class.forName("java.lang.annotation.Annotation"); 372 if (loader == null) { 373 junit4TestAdapterClass = 374 Class.forName("junit.framework.JUnit4TestAdapter"); 375 } else { 376 junit4TestAdapterClass = 377 Class.forName("junit.framework.JUnit4TestAdapter", 378 true, loader); 379 } 380 } catch (ClassNotFoundException e) { 381 } 383 junit4 = junit4TestAdapterClass != null; 384 385 if (junit4) { 386 suite = 388 (Test) junit4TestAdapterClass 389 .getConstructor(new Class [] {Class .class}). 390 newInstance(new Object [] {testClass}); 391 } else { 392 394 suite = new TestSuite(testClass); 398 } 399 400 } 401 402 } catch (Throwable e) { 403 retCode = ERRORS; 404 exception = e; 405 } 406 407 long start = System.currentTimeMillis(); 408 409 fireStartTestSuite(); 410 startTestSuiteSuccess = true; 411 if (exception != null) { for (int i = 0; i < formatters.size(); i++) { 413 ((TestListener) formatters.elementAt(i)) 414 .addError(null, exception); 415 } 416 junitTest.setCounts(1, 0, 1); 417 junitTest.setRunTime(0); 418 } else { 419 try { 420 logTestListenerEvent("tests to run: " + suite.countTestCases()); 421 suite.run(res); 422 } finally { 423 if (junit4) { 424 int[] cnts = findJUnit4FailureErrorCount(res); 425 junitTest.setCounts(res.runCount(), cnts[0], cnts[1]); 426 } else { 427 junitTest.setCounts(res.runCount(), res.failureCount(), 428 res.errorCount()); 429 } 430 junitTest.setRunTime(System.currentTimeMillis() - start); 431 } 432 } 433 } finally { 434 if (perm != null) { 435 perm.restoreSecurityManager(); 436 } 437 if (savedOut != null) { 438 System.setOut(savedOut); 439 } 440 if (savedErr != null) { 441 System.setErr(savedErr); 442 } 443 444 systemError.close(); 445 systemError = null; 446 systemOut.close(); 447 systemOut = null; 448 if (startTestSuiteSuccess) { 449 sendOutAndErr(new String (outStrm.toByteArray()), 450 new String (errStrm.toByteArray())); 451 } 452 } 453 fireEndTestSuite(); 454 455 if (retCode != SUCCESS || res.errorCount() != 0) { 456 retCode = ERRORS; 457 } else if (res.failureCount() != 0) { 458 retCode = FAILURES; 459 } 460 } 461 462 467 public int getRetCode() { 468 return retCode; 469 } 470 471 477 public void startTest(Test t) { 478 String testName = JUnitVersionHelper.getTestCaseName(t); 479 logTestListenerEvent("startTest(" + testName + ")"); 480 } 481 482 488 public void endTest(Test test) { 489 String testName = JUnitVersionHelper.getTestCaseName(test); 490 logTestListenerEvent("endTest(" + testName + ")"); 491 } 492 493 private void logTestListenerEvent(String msg) { 494 PrintStream out = savedOut != null ? savedOut : System.out; 495 if (logTestListenerEvents) { 496 out.flush(); 497 out.println(JUnitTask.TESTLISTENER_PREFIX + msg); 498 out.flush(); 499 } 500 } 501 502 509 public void addFailure(Test test, Throwable t) { 510 String testName = JUnitVersionHelper.getTestCaseName(test); 511 logTestListenerEvent("addFailure(" + testName + ", " + t.getMessage() + ")"); 512 if (haltOnFailure) { 513 res.stop(); 514 } 515 } 516 517 524 public void addFailure(Test test, AssertionFailedError t) { 525 addFailure(test, (Throwable ) t); 526 } 527 528 535 public void addError(Test test, Throwable t) { 536 String testName = JUnitVersionHelper.getTestCaseName(test); 537 logTestListenerEvent("addError(" + testName + ", " + t.getMessage() + ")"); 538 if (haltOnError) { 539 res.stop(); 540 } 541 } 542 543 548 public void setPermissions(Permissions permissions) { 549 perm = permissions; 550 } 551 552 556 public void handleOutput(String output) { 557 if (!logTestListenerEvents && output.startsWith(JUnitTask.TESTLISTENER_PREFIX)) { 558 } else if (systemOut != null) { 560 systemOut.print(output); 561 } 562 } 563 564 575 public int handleInput(byte[] buffer, int offset, int length) 576 throws IOException { 577 return -1; 578 } 579 580 581 public void handleErrorOutput(String output) { 582 if (systemError != null) { 583 systemError.print(output); 584 } 585 } 586 587 588 public void handleFlush(String output) { 589 if (systemOut != null) { 590 systemOut.print(output); 591 } 592 } 593 594 595 public void handleErrorFlush(String output) { 596 if (systemError != null) { 597 systemError.print(output); 598 } 599 } 600 601 private void sendOutAndErr(String out, String err) { 602 for (int i = 0; i < formatters.size(); i++) { 603 JUnitResultFormatter formatter = 604 ((JUnitResultFormatter) formatters.elementAt(i)); 605 606 formatter.setSystemOutput(out); 607 formatter.setSystemError(err); 608 } 609 } 610 611 private void fireStartTestSuite() { 612 for (int i = 0; i < formatters.size(); i++) { 613 ((JUnitResultFormatter) formatters.elementAt(i)) 614 .startTestSuite(junitTest); 615 } 616 } 617 618 private void fireEndTestSuite() { 619 for (int i = 0; i < formatters.size(); i++) { 620 ((JUnitResultFormatter) formatters.elementAt(i)) 621 .endTestSuite(junitTest); 622 } 623 } 624 625 629 public void addFormatter(JUnitResultFormatter f) { 630 formatters.addElement(f); 631 } 632 633 634 public void addFormatter(JUnitTaskMirror.JUnitResultFormatterMirror f) { 635 formatters.addElement((JUnitResultFormatter) f); 636 } 637 638 667 public static void main(String [] args) throws IOException { 668 boolean haltError = false; 669 boolean haltFail = false; 670 boolean stackfilter = true; 671 Properties props = new Properties (); 672 boolean showOut = false; 673 boolean outputToFormat = true; 674 boolean logTestListenerEvents = false; 675 676 677 if (args.length == 0) { 678 System.err.println("required argument TestClassName missing"); 679 System.exit(ERRORS); 680 } 681 682 if (args[0].startsWith(Constants.TESTSFILE)) { 683 multipleTests = true; 684 args[0] = args[0].substring(Constants.TESTSFILE.length()); 685 } 686 687 for (int i = 1; i < args.length; i++) { 688 if (args[i].startsWith(Constants.HALT_ON_ERROR)) { 689 haltError = Project.toBoolean(args[i].substring(Constants.HALT_ON_ERROR.length())); 690 } else if (args[i].startsWith(Constants.HALT_ON_FAILURE)) { 691 haltFail = Project.toBoolean(args[i].substring(Constants.HALT_ON_FAILURE.length())); 692 } else if (args[i].startsWith(Constants.FILTERTRACE)) { 693 stackfilter = Project.toBoolean(args[i].substring(Constants.FILTERTRACE.length())); 694 } else if (args[i].startsWith(Constants.CRASHFILE)) { 695 crashFile = args[i].substring(Constants.CRASHFILE.length()); 696 registerTestCase(Constants.BEFORE_FIRST_TEST); 697 } else if (args[i].startsWith(Constants.FORMATTER)) { 698 try { 699 createAndStoreFormatter(args[i].substring(Constants.FORMATTER.length())); 700 } catch (BuildException be) { 701 System.err.println(be.getMessage()); 702 System.exit(ERRORS); 703 } 704 } else if (args[i].startsWith(Constants.PROPSFILE)) { 705 FileInputStream in = new FileInputStream (args[i] 706 .substring(Constants.PROPSFILE.length())); 707 props.load(in); 708 in.close(); 709 } else if (args[i].startsWith(Constants.SHOWOUTPUT)) { 710 showOut = Project.toBoolean(args[i].substring(Constants.SHOWOUTPUT.length())); 711 } else if (args[i].startsWith(Constants.LOGTESTLISTENEREVENTS)) { 712 logTestListenerEvents = Project.toBoolean( 713 args[i].substring(Constants.LOGTESTLISTENEREVENTS.length())); 714 } else if (args[i].startsWith(Constants.OUTPUT_TO_FORMATTERS)) { 715 outputToFormat = Project.toBoolean( 716 args[i].substring(Constants.OUTPUT_TO_FORMATTERS.length())); 717 } 718 } 719 720 Hashtable p = System.getProperties(); 722 for (Enumeration e = p.keys(); e.hasMoreElements();) { 723 Object key = e.nextElement(); 724 props.put(key, p.get(key)); 725 } 726 727 int returnCode = SUCCESS; 728 if (multipleTests) { 729 try { 730 java.io.BufferedReader reader = 731 new java.io.BufferedReader (new java.io.FileReader (args[0])); 732 String testCaseName; 733 int code = 0; 734 boolean errorOccurred = false; 735 boolean failureOccurred = false; 736 String line = null; 737 while ((line = reader.readLine()) != null) { 738 StringTokenizer st = new StringTokenizer (line, ","); 739 testCaseName = st.nextToken(); 740 JUnitTest t = new JUnitTest(testCaseName); 741 t.setTodir(new File (st.nextToken())); 742 t.setOutfile(st.nextToken()); 743 code = launch(t, haltError, stackfilter, haltFail, 744 showOut, outputToFormat, 745 logTestListenerEvents, props); 746 errorOccurred = (code == ERRORS); 747 failureOccurred = (code != SUCCESS); 748 if (errorOccurred || failureOccurred) { 749 if ((errorOccurred && haltError) 750 || (failureOccurred && haltFail)) { 751 registerNonCrash(); 752 System.exit(code); 753 } else { 754 if (code > returnCode) { 755 returnCode = code; 756 } 757 System.out.println("TEST " + t.getName() 758 + " FAILED"); 759 } 760 } 761 } 762 } catch (IOException e) { 763 e.printStackTrace(); 764 } 765 } else { 766 returnCode = launch(new JUnitTest(args[0]), haltError, 767 stackfilter, haltFail, 768 showOut, outputToFormat, 769 logTestListenerEvents, props); 770 } 771 772 registerNonCrash(); 773 System.exit(returnCode); 774 } 775 776 private static Vector fromCmdLine = new Vector (); 777 778 private static void transferFormatters(JUnitTestRunner runner, 779 JUnitTest test) { 780 runner.addFormatter(new JUnitResultFormatter() { 781 782 public void startTestSuite(JUnitTest suite) throws BuildException { 783 } 784 785 public void endTestSuite(JUnitTest suite) throws BuildException { 786 } 787 788 public void setOutput(OutputStream out) { 789 } 790 791 public void setSystemOutput(String out) { 792 } 793 794 public void setSystemError(String err) { 795 } 796 797 public void addError(Test arg0, Throwable arg1) { 798 } 799 800 public void addFailure(Test arg0, AssertionFailedError arg1) { 801 } 802 803 public void endTest(Test arg0) { 804 } 805 806 public void startTest(Test arg0) { 807 registerTestCase(JUnitVersionHelper.getTestCaseName(arg0)); 808 } 809 }); 810 for (int i = 0; i < fromCmdLine.size(); i++) { 811 FormatterElement fe = (FormatterElement) fromCmdLine.elementAt(i); 812 if (multipleTests && fe.getUseFile()) { 813 File destFile = 814 new File (test.getTodir(), 815 test.getOutfile() + fe.getExtension()); 816 fe.setOutfile(destFile); 817 } 818 runner.addFormatter((JUnitResultFormatter) fe.createFormatter()); 819 } 820 } 821 822 825 private static void createAndStoreFormatter(String line) 826 throws BuildException { 827 FormatterElement fe = new FormatterElement(); 828 int pos = line.indexOf(','); 829 if (pos == -1) { 830 fe.setClassname(line); 831 fe.setUseFile(false); 832 } else { 833 fe.setClassname(line.substring(0, pos)); 834 fe.setUseFile(true); 835 if (!multipleTests) { 836 fe.setOutfile(new File (line.substring(pos + 1))); 837 } else { 838 int fName = line.indexOf(IGNORED_FILE_NAME); 839 if (fName > -1) { 840 fe.setExtension(line 841 .substring(fName 842 + IGNORED_FILE_NAME.length())); 843 } 844 } 845 } 846 fromCmdLine.addElement(fe); 847 } 848 849 855 public static String getFilteredTrace(Throwable t) { 856 String trace = StringUtils.getStackTrace(t); 857 return JUnitTestRunner.filterStack(trace); 858 } 859 860 865 public static String filterStack(String stack) { 866 if (!filtertrace) { 867 return stack; 868 } 869 StringWriter sw = new StringWriter (); 870 PrintWriter pw = new PrintWriter (sw); 871 StringReader sr = new StringReader (stack); 872 BufferedReader br = new BufferedReader (sr); 873 874 String line; 875 try { 876 while ((line = br.readLine()) != null) { 877 if (!filterLine(line)) { 878 pw.println(line); 879 } 880 } 881 } catch (Exception e) { 882 return stack; } 884 return sw.toString(); 885 } 886 887 private static boolean filterLine(String line) { 888 for (int i = 0; i < DEFAULT_TRACE_FILTERS.length; i++) { 889 if (line.indexOf(DEFAULT_TRACE_FILTERS[i]) != -1) { 890 return true; 891 } 892 } 893 return false; 894 } 895 896 899 private static int launch(JUnitTest t, boolean haltError, 900 boolean stackfilter, boolean haltFail, 901 boolean showOut, boolean outputToFormat, 902 boolean logTestListenerEvents, 903 Properties props) { 904 t.setProperties(props); 905 JUnitTestRunner runner = 906 new JUnitTestRunner(t, haltError, stackfilter, haltFail, showOut, 907 logTestListenerEvents, null); 908 runner.forked = true; 909 runner.outputToFormatters = outputToFormat; 910 transferFormatters(runner, t); 911 912 runner.run(); 913 return runner.getRetCode(); 914 } 915 916 919 private static void registerNonCrash() 920 throws IOException { 921 if (crashFile != null) { 922 FileWriter out = null; 923 try { 924 out = new FileWriter (crashFile); 925 out.write(Constants.TERMINATED_SUCCESSFULLY + "\n"); 926 out.flush(); 927 } finally { 928 if (out != null) { 929 out.close(); 930 } 931 } 932 } 933 } 934 935 private static void registerTestCase(String testCase) { 936 if (crashFile != null) { 937 try { 938 FileWriter out = null; 939 try { 940 out = new FileWriter (crashFile); 941 out.write(testCase + "\n"); 942 out.flush(); 943 } finally { 944 if (out != null) { 945 out.close(); 946 } 947 } 948 } catch (IOException e) { 949 } 951 } 952 } 953 954 960 private TestListener wrapListener(final TestListener testListener) { 961 return new TestListener() { 962 public void addError(Test test, Throwable t) { 963 if (junit4 && t instanceof AssertionFailedError) { 964 testListener.addFailure(test, (AssertionFailedError) t); 968 } else if (junit4 && t.getClass().getName().equals("java.lang.AssertionError")) { 969 try { 974 String msg = t.getMessage(); 975 AssertionFailedError failure = msg != null 976 ? new AssertionFailedError(msg) : new AssertionFailedError(); 977 Method initCause = Throwable .class.getMethod( 979 "initCause", new Class [] {Throwable .class}); 980 initCause.invoke(failure, new Object [] {t}); 981 testListener.addFailure(test, failure); 982 } catch (Exception e) { 983 e.printStackTrace(); testListener.addError(test, t); 986 } 987 } else { 988 testListener.addError(test, t); 989 } 990 } 991 public void addFailure(Test test, AssertionFailedError t) { 992 testListener.addFailure(test, t); 993 } 994 public void addFailure(Test test, Throwable t) { if (t instanceof AssertionFailedError) { 996 testListener.addFailure(test, (AssertionFailedError) t); 997 } else { 998 testListener.addError(test, t); 999 } 1000 } 1001 public void endTest(Test test) { 1002 testListener.endTest(test); 1003 } 1004 public void startTest(Test test) { 1005 testListener.startTest(test); 1006 } 1007 }; 1008 } 1009 1010 1015 private int[] findJUnit4FailureErrorCount(TestResult res) { 1016 int failures = 0; 1017 int errors = 0; 1018 Enumeration e = res.failures(); 1019 while (e.hasMoreElements()) { 1020 e.nextElement(); 1021 failures++; 1022 } 1023 e = res.errors(); 1024 while (e.hasMoreElements()) { 1025 Throwable t = ((TestFailure) e.nextElement()).thrownException(); 1026 if (t instanceof AssertionFailedError 1027 || t.getClass().getName().equals("java.lang.AssertionError")) { 1028 failures++; 1029 } else { 1030 errors++; 1031 } 1032 } 1033 return new int[] {failures, errors}; 1034 } 1035 1036} | Popular Tags |