1 18 19 package org.apache.tools.ant.taskdefs.optional.junit; 20 21 import java.io.BufferedReader ; 22 import java.io.BufferedWriter ; 23 import java.io.File ; 24 import java.io.FileOutputStream ; 25 import java.io.FileReader ; 26 import java.io.FileWriter ; 27 import java.io.IOException ; 28 import java.io.OutputStream ; 29 import java.io.PrintWriter ; 30 import java.lang.reflect.Constructor ; 31 import java.util.ArrayList ; 32 import java.util.Collection ; 33 import java.util.Enumeration ; 34 import java.util.HashMap ; 35 import java.util.Hashtable ; 36 import java.util.Iterator ; 37 import java.util.List ; 38 import java.util.Map ; 39 import java.util.Properties ; 40 import java.util.Vector ; 41 42 import org.apache.tools.ant.AntClassLoader; 43 import org.apache.tools.ant.BuildException; 44 import org.apache.tools.ant.Project; 45 import org.apache.tools.ant.Task; 46 import org.apache.tools.ant.taskdefs.Execute; 47 import org.apache.tools.ant.taskdefs.ExecuteWatchdog; 48 import org.apache.tools.ant.taskdefs.LogOutputStream; 49 import org.apache.tools.ant.taskdefs.PumpStreamHandler; 50 import org.apache.tools.ant.types.Assertions; 51 import org.apache.tools.ant.types.Commandline; 52 import org.apache.tools.ant.types.CommandlineJava; 53 import org.apache.tools.ant.types.EnumeratedAttribute; 54 import org.apache.tools.ant.types.Environment; 55 import org.apache.tools.ant.types.Path; 56 import org.apache.tools.ant.types.Permissions; 57 import org.apache.tools.ant.types.PropertySet; 58 import org.apache.tools.ant.util.FileUtils; 59 import org.apache.tools.ant.util.LoaderUtils; 60 61 127 public class JUnitTask extends Task { 128 129 private static final String CLASSPATH = "CLASSPATH="; 130 private CommandlineJava commandline; 131 private Vector tests = new Vector (); 132 private Vector batchTests = new Vector (); 133 private Vector formatters = new Vector (); 134 private File dir = null; 135 136 private Integer timeout = null; 137 private boolean summary = false; 138 private boolean reloading = true; 139 private String summaryValue = ""; 140 private JUnitTaskMirror.JUnitTestRunnerMirror runner = null; 141 142 private boolean newEnvironment = false; 143 private Environment env = new Environment(); 144 145 private boolean includeAntRuntime = true; 146 private Path antRuntimeClasses = null; 147 148 private boolean showOutput = false; 150 151 private boolean outputToFormatters = true; 153 154 private File tmpDir; 155 private AntClassLoader classLoader = null; 156 private Permissions perm = null; 157 private ForkMode forkMode = new ForkMode("perTest"); 158 159 private boolean splitJunit = false; 160 private JUnitTaskMirror delegate; 161 162 private boolean haltOnError = false; 164 private boolean haltOnFail = false; 165 private boolean filterTrace = true; 166 private boolean fork = false; 167 private String failureProperty; 168 private String errorProperty; 169 170 private static final int STRING_BUFFER_SIZE = 128; 171 174 public static final String TESTLISTENER_PREFIX = 175 "junit.framework.TestListener: "; 176 177 private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); 178 179 184 public void setReloading(boolean value) { 185 reloading = value; 186 } 187 188 200 public void setFiltertrace(boolean value) { 201 this.filterTrace = value; 202 } 203 204 214 public void setHaltonerror(boolean value) { 215 this.haltOnError = value; 216 } 217 218 229 public void setErrorProperty(String propertyName) { 230 this.errorProperty = propertyName; 231 } 232 233 244 public void setHaltonfailure(boolean value) { 245 this.haltOnFail = value; 246 } 247 248 259 public void setFailureProperty(String propertyName) { 260 this.failureProperty = propertyName; 261 } 262 263 276 public void setFork(boolean value) { 277 this.fork = value; 278 } 279 280 299 public void setForkMode(ForkMode mode) { 300 this.forkMode = mode; 301 } 302 303 315 public void setPrintsummary(SummaryAttribute value) { 316 summaryValue = value.getValue(); 317 summary = value.asBoolean(); 318 } 319 320 323 public static class SummaryAttribute extends EnumeratedAttribute { 324 328 public String [] getValues() { 329 return new String [] {"true", "yes", "false", "no", 330 "on", "off", "withOutAndErr"}; 331 } 332 333 337 public boolean asBoolean() { 338 String v = getValue(); 339 return "true".equals(v) 340 || "on".equals(v) 341 || "yes".equals(v) 342 || "withOutAndErr".equals(v); 343 } 344 } 345 346 357 public void setTimeout(Integer value) { 358 timeout = value; 359 } 360 361 368 public void setMaxmemory(String max) { 369 getCommandline().setMaxmemory(max); 370 } 371 372 382 public void setJvm(String value) { 383 getCommandline().setVm(value); 384 } 385 386 395 public Commandline.Argument createJvmarg() { 396 return getCommandline().createVmArgument(); 397 } 398 399 406 public void setDir(File dir) { 407 this.dir = dir; 408 } 409 410 419 public void addSysproperty(Environment.Variable sysp) { 420 421 getCommandline().addSysproperty(sysp); 422 } 423 424 431 public void addConfiguredSysproperty(Environment.Variable sysp) { 432 String testString = sysp.getContent(); 435 getProject().log("sysproperty added : " + testString, Project.MSG_DEBUG); 436 getCommandline().addSysproperty(sysp); 437 } 438 439 449 public void addSyspropertyset(PropertySet sysp) { 450 getCommandline().addSyspropertyset(sysp); 451 } 452 453 459 public Path createClasspath() { 460 return getCommandline().createClasspath(getProject()).createPath(); 461 } 462 463 468 public Path createBootclasspath() { 469 return getCommandline().createBootclasspath(getProject()).createPath(); 470 } 471 472 479 public void addEnv(Environment.Variable var) { 480 env.addVariable(var); 481 } 482 483 491 public void setNewenvironment(boolean newenv) { 492 newEnvironment = newenv; 493 } 494 495 503 private void preConfigure(BaseTest test) { 504 test.setFiltertrace(filterTrace); 505 test.setHaltonerror(haltOnError); 506 if (errorProperty != null) { 507 test.setErrorProperty(errorProperty); 508 } 509 test.setHaltonfailure(haltOnFail); 510 if (failureProperty != null) { 511 test.setFailureProperty(failureProperty); 512 } 513 test.setFork(fork); 514 } 515 516 523 public void addTest(JUnitTest test) { 524 tests.addElement(test); 525 preConfigure(test); 526 } 527 528 536 public BatchTest createBatchTest() { 537 BatchTest test = new BatchTest(getProject()); 538 batchTests.addElement(test); 539 preConfigure(test); 540 return test; 541 } 542 543 549 public void addFormatter(FormatterElement fe) { 550 formatters.addElement(fe); 551 } 552 553 559 public void setIncludeantruntime(boolean b) { 560 includeAntRuntime = b; 561 } 562 563 576 public void setShowOutput(boolean showOutput) { 577 this.showOutput = showOutput; 578 } 579 580 587 public void setOutputToFormatters(boolean outputToFormatters) { 588 this.outputToFormatters = outputToFormatters; 589 } 590 591 596 public void addAssertions(Assertions asserts) { 597 if (getCommandline().getAssertions() != null) { 598 throw new BuildException("Only one assertion declaration is allowed"); 599 } 600 getCommandline().setAssertions(asserts); 601 } 602 603 608 public Permissions createPermissions() { 609 if (perm == null) { 610 perm = new Permissions(); 611 } 612 return perm; 613 } 614 615 624 public void setCloneVm(boolean cloneVm) { 625 getCommandline().setCloneVm(cloneVm); 626 } 627 628 634 public JUnitTask() throws Exception { 635 getCommandline() 636 .setClassname("org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner"); 637 } 638 639 645 public void setTempdir(File tmpDir) { 646 if (tmpDir != null) { 647 if (!tmpDir.exists() || !tmpDir.isDirectory()) { 648 throw new BuildException(tmpDir.toString() 649 + " is not a valid temp directory"); 650 } 651 } 652 this.tmpDir = tmpDir; 653 } 654 655 662 public void init() { 663 antRuntimeClasses = new Path(getProject()); 664 splitJunit = !addClasspathEntry("/junit/framework/TestCase.class"); 665 addClasspathEntry("/org/apache/tools/ant/launch/AntMain.class"); 666 addClasspathEntry("/org/apache/tools/ant/Task.class"); 667 addClasspathEntry("/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.class"); 668 } 669 670 private static JUnitTaskMirror createMirror(JUnitTask task, ClassLoader loader) { 671 try { 672 loader.loadClass("junit.framework.Test"); } catch (ClassNotFoundException e) { 674 throw new BuildException( 675 "The <classpath> for <junit> must include junit.jar " 676 + "if not in Ant's own classpath", 677 e, task.getLocation()); 678 } 679 try { 680 Class c = loader.loadClass(JUnitTaskMirror.class.getName() + "Impl"); 681 if (c.getClassLoader() != loader) { 682 throw new BuildException("Overdelegating loader", task.getLocation()); 683 } 684 Constructor cons = c.getConstructor(new Class [] {JUnitTask.class}); 685 return (JUnitTaskMirror) cons.newInstance(new Object [] {task}); 686 } catch (Exception e) { 687 throw new BuildException(e, task.getLocation()); 688 } 689 } 690 691 private final class SplitLoader extends AntClassLoader { 692 693 public SplitLoader(ClassLoader parent, Path path) { 694 super(parent, getProject(), path, true); 695 } 696 697 protected synchronized Class loadClass(String classname, boolean resolve) 700 throws ClassNotFoundException { 701 Class theClass = findLoadedClass(classname); 702 if (theClass != null) { 703 return theClass; 704 } 705 if (isSplit(classname)) { 706 theClass = findClass(classname); 707 if (resolve) { 708 resolveClass(theClass); 709 } 710 return theClass; 711 } else { 712 return super.loadClass(classname, resolve); 713 } 714 } 715 716 private final String [] splitClasses = { 717 "BriefJUnitResultFormatter", 718 "JUnitResultFormatter", 719 "JUnitTaskMirrorImpl", 720 "JUnitTestRunner", 721 "JUnitVersionHelper", 722 "OutErrSummaryJUnitResultFormatter", 723 "PlainJUnitResultFormatter", 724 "SummaryJUnitResultFormatter", 725 "XMLJUnitResultFormatter", 726 }; 727 728 private boolean isSplit(String classname) { 729 String simplename = classname.substring(classname.lastIndexOf('.') + 1); 730 for (int i = 0; i < splitClasses.length; i++) { 731 if (simplename.equals(splitClasses[i]) 732 || simplename.startsWith(splitClasses[i] + '$')) { 733 return true; 734 } 735 } 736 return false; 737 } 738 739 } 740 741 747 public void execute() throws BuildException { 748 ClassLoader myLoader = JUnitTask.class.getClassLoader(); 749 ClassLoader mirrorLoader; 750 if (splitJunit) { 751 Path path = new Path(getProject()); 752 path.add(antRuntimeClasses); 753 path.add(getCommandline().getClasspath()); 754 mirrorLoader = new SplitLoader(myLoader, path); 755 } else { 756 mirrorLoader = myLoader; 757 } 758 delegate = createMirror(this, mirrorLoader); 759 760 List testLists = new ArrayList (); 761 762 boolean forkPerTest = forkMode.getValue().equals(ForkMode.PER_TEST); 763 if (forkPerTest || forkMode.getValue().equals(ForkMode.ONCE)) { 764 testLists.addAll(executeOrQueue(getIndividualTests(), 765 forkPerTest)); 766 } else { 767 final int count = batchTests.size(); 768 for (int i = 0; i < count; i++) { 769 BatchTest batchtest = (BatchTest) batchTests.elementAt(i); 770 testLists.addAll(executeOrQueue(batchtest.elements(), false)); 771 } 772 testLists.addAll(executeOrQueue(tests.elements(), forkPerTest)); 773 } 774 775 try { 776 Iterator iter = testLists.iterator(); 777 while (iter.hasNext()) { 778 List l = (List ) iter.next(); 779 if (l.size() == 1) { 780 execute((JUnitTest) l.get(0)); 781 } else { 782 execute(l); 783 } 784 } 785 } finally { 786 deleteClassLoader(); 787 if (mirrorLoader instanceof SplitLoader) { 788 ((SplitLoader) mirrorLoader).cleanup(); 789 } 790 delegate = null; 791 } 792 } 793 794 799 protected void execute(JUnitTest arg) throws BuildException { 800 JUnitTest test = (JUnitTest) arg.clone(); 801 if (test.getTodir() == null) { 804 test.setTodir(getProject().resolveFile(".")); 805 } 806 807 if (test.getOutfile() == null) { 808 test.setOutfile("TEST-" + test.getName()); 809 } 810 811 TestResultHolder result = null; 813 if (!test.getFork()) { 814 result = executeInVM(test); 815 } else { 816 ExecuteWatchdog watchdog = createWatchdog(); 817 result = executeAsForked(test, watchdog, null); 818 } 820 actOnTestResult(result, test, "Test " + test.getName()); 821 } 822 823 828 protected void execute(List tests) throws BuildException { 829 JUnitTest test = null; 830 File casesFile = createTempPropertiesFile("junittestcases"); 833 PrintWriter writer = null; 834 try { 835 writer = 836 new PrintWriter (new BufferedWriter (new FileWriter (casesFile))); 837 Iterator iter = tests.iterator(); 838 while (iter.hasNext()) { 839 test = (JUnitTest) iter.next(); 840 writer.print(test.getName()); 841 if (test.getTodir() == null) { 842 writer.print("," + getProject().resolveFile(".")); 843 } else { 844 writer.print("," + test.getTodir()); 845 } 846 847 if (test.getOutfile() == null) { 848 writer.println("," + "TEST-" + test.getName()); 849 } else { 850 writer.println("," + test.getOutfile()); 851 } 852 } 853 writer.flush(); 854 writer.close(); 855 writer = null; 856 857 ExecuteWatchdog watchdog = createWatchdog(); 859 TestResultHolder result = 860 executeAsForked(test, watchdog, casesFile); 861 actOnTestResult(result, test, "Tests"); 862 } catch (IOException e) { 863 log(e.toString(), Project.MSG_ERR); 864 throw new BuildException(e); 865 } finally { 866 if (writer != null) { 867 writer.close(); 868 } 869 870 try { 871 casesFile.delete(); 872 } catch (Exception e) { 873 log(e.toString(), Project.MSG_ERR); 874 } 875 } 876 } 877 878 892 private TestResultHolder executeAsForked(JUnitTest test, 893 ExecuteWatchdog watchdog, 894 File casesFile) 895 throws BuildException { 896 897 if (perm != null) { 898 log("Permissions ignored when running in forked mode!", 899 Project.MSG_WARN); 900 } 901 902 CommandlineJava cmd = null; 903 try { 904 cmd = (CommandlineJava) (getCommandline().clone()); 905 } catch (CloneNotSupportedException e) { 906 throw new BuildException("This shouldn't happen", e, getLocation()); 907 } 908 cmd.setClassname("org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner"); 909 if (casesFile == null) { 910 cmd.createArgument().setValue(test.getName()); 911 } else { 912 log("Running multiple tests in the same VM", Project.MSG_VERBOSE); 913 cmd.createArgument().setValue(Constants.TESTSFILE + casesFile); 914 } 915 916 cmd.createArgument().setValue(Constants.FILTERTRACE + test.getFiltertrace()); 917 cmd.createArgument().setValue(Constants.HALT_ON_ERROR + test.getHaltonerror()); 918 cmd.createArgument().setValue(Constants.HALT_ON_FAILURE 919 + test.getHaltonfailure()); 920 if (includeAntRuntime) { 921 Vector v = Execute.getProcEnvironment(); 922 Enumeration e = v.elements(); 923 while (e.hasMoreElements()) { 924 String s = (String ) e.nextElement(); 925 if (s.startsWith(CLASSPATH)) { 926 cmd.createClasspath(getProject()).createPath() 927 .append(new Path(getProject(), 928 s.substring(CLASSPATH.length() 929 ))); 930 } 931 } 932 log("Implicitly adding " + antRuntimeClasses + " to CLASSPATH", 933 Project.MSG_VERBOSE); 934 cmd.createClasspath(getProject()).createPath() 935 .append(antRuntimeClasses); 936 } 937 938 if (summary) { 939 String prefix = ""; 940 if ("withoutanderr".equalsIgnoreCase(summaryValue)) { 941 prefix = "OutErr"; 942 } 943 cmd.createArgument() 944 .setValue(Constants.FORMATTER 945 + "org.apache.tools.ant.taskdefs.optional.junit." 946 + prefix + "SummaryJUnitResultFormatter"); 947 } 948 949 cmd.createArgument().setValue(Constants.SHOWOUTPUT 950 + String.valueOf(showOutput)); 951 cmd.createArgument().setValue(Constants.OUTPUT_TO_FORMATTERS 952 + String.valueOf(outputToFormatters)); 953 954 cmd.createArgument().setValue( 955 Constants.LOGTESTLISTENEREVENTS + "true"); 957 StringBuffer formatterArg = new StringBuffer (STRING_BUFFER_SIZE); 958 final FormatterElement[] feArray = mergeFormatters(test); 959 for (int i = 0; i < feArray.length; i++) { 960 FormatterElement fe = feArray[i]; 961 if (fe.shouldUse(this)) { 962 formatterArg.append(Constants.FORMATTER); 963 formatterArg.append(fe.getClassname()); 964 File outFile = getOutput(fe, test); 965 if (outFile != null) { 966 formatterArg.append(","); 967 formatterArg.append(outFile); 968 } 969 cmd.createArgument().setValue(formatterArg.toString()); 970 formatterArg = new StringBuffer (); 971 } 972 } 973 974 File vmWatcher = createTempPropertiesFile("junitvmwatcher"); 975 cmd.createArgument().setValue(Constants.CRASHFILE 976 + vmWatcher.getAbsolutePath()); 977 File propsFile = createTempPropertiesFile("junit"); 978 cmd.createArgument().setValue(Constants.PROPSFILE 979 + propsFile.getAbsolutePath()); 980 Hashtable p = getProject().getProperties(); 981 Properties props = new Properties (); 982 for (Enumeration e = p.keys(); e.hasMoreElements();) { 983 Object key = e.nextElement(); 984 props.put(key, p.get(key)); 985 } 986 try { 987 FileOutputStream outstream = new FileOutputStream (propsFile); 988 props.store(outstream, "Ant JUnitTask generated properties file"); 989 outstream.close(); 990 } catch (java.io.IOException e) { 991 propsFile.delete(); 992 throw new BuildException("Error creating temporary properties " 993 + "file.", e, getLocation()); 994 } 995 996 Execute execute = new Execute( 997 new JUnitLogStreamHandler( 998 this, 999 Project.MSG_INFO, 1000 Project.MSG_WARN), 1001 watchdog); 1002 execute.setCommandline(cmd.getCommandline()); 1003 execute.setAntRun(getProject()); 1004 if (dir != null) { 1005 execute.setWorkingDirectory(dir); 1006 } 1007 1008 String [] environment = env.getVariables(); 1009 if (environment != null) { 1010 for (int i = 0; i < environment.length; i++) { 1011 log("Setting environment variable: " + environment[i], 1012 Project.MSG_VERBOSE); 1013 } 1014 } 1015 execute.setNewenvironment(newEnvironment); 1016 execute.setEnvironment(environment); 1017 1018 log(cmd.describeCommand(), Project.MSG_VERBOSE); 1019 TestResultHolder result = new TestResultHolder(); 1020 try { 1021 result.exitCode = execute.execute(); 1022 } catch (IOException e) { 1023 throw new BuildException("Process fork failed.", e, getLocation()); 1024 } finally { 1025 String vmCrashString = "unknown"; 1026 BufferedReader br = null; 1027 try { 1028 br = new BufferedReader (new FileReader (vmWatcher)); 1029 vmCrashString = br.readLine(); 1030 } catch (Exception e) { 1031 e.printStackTrace(); 1032 } finally { 1034 FileUtils.close(br); 1035 } 1036 if (watchdog != null && watchdog.killedProcess()) { 1037 result.timedOut = true; 1038 logTimeout(feArray, test, vmCrashString); 1039 } else if (!Constants.TERMINATED_SUCCESSFULLY.equals(vmCrashString)) { 1040 result.crashed = true; 1041 logVmCrash(feArray, test, vmCrashString); 1042 } 1043 vmWatcher.delete(); 1044 1045 if (!propsFile.delete()) { 1046 throw new BuildException("Could not delete temporary " 1047 + "properties file."); 1048 } 1049 } 1050 1051 return result; 1052 } 1053 1054 1062 private File createTempPropertiesFile(String prefix) { 1063 File propsFile = 1064 FILE_UTILS.createTempFile(prefix, ".properties", 1065 tmpDir != null ? tmpDir : getProject().getBaseDir(), true); 1066 return propsFile; 1067 } 1068 1069 1070 1077 protected void handleOutput(String output) { 1078 if (output.startsWith(TESTLISTENER_PREFIX)) { 1079 log(output, Project.MSG_VERBOSE); 1080 } else if (runner != null) { 1081 if (outputToFormatters) { 1082 runner.handleOutput(output); 1083 } 1084 if (showOutput) { 1085 super.handleOutput(output); 1086 } 1087 } else { 1088 super.handleOutput(output); 1089 } 1090 } 1091 1092 1106 protected int handleInput(byte[] buffer, int offset, int length) 1107 throws IOException { 1108 if (runner != null) { 1109 return runner.handleInput(buffer, offset, length); 1110 } else { 1111 return super.handleInput(buffer, offset, length); 1112 } 1113 } 1114 1115 1116 1123 protected void handleFlush(String output) { 1124 if (runner != null) { 1125 runner.handleFlush(output); 1126 if (showOutput) { 1127 super.handleFlush(output); 1128 } 1129 } else { 1130 super.handleFlush(output); 1131 } 1132 } 1133 1134 1141 public void handleErrorOutput(String output) { 1142 if (runner != null) { 1143 runner.handleErrorOutput(output); 1144 if (showOutput) { 1145 super.handleErrorOutput(output); 1146 } 1147 } else { 1148 super.handleErrorOutput(output); 1149 } 1150 } 1151 1152 1153 1160 public void handleErrorFlush(String output) { 1161 if (runner != null) { 1162 runner.handleErrorFlush(output); 1163 if (showOutput) { 1164 super.handleErrorFlush(output); 1165 } 1166 } else { 1167 super.handleErrorFlush(output); 1168 } 1169 } 1170 1171 1175 1180 private TestResultHolder executeInVM(JUnitTest arg) throws BuildException { 1181 JUnitTest test = (JUnitTest) arg.clone(); 1182 test.setProperties(getProject().getProperties()); 1183 if (dir != null) { 1184 log("dir attribute ignored if running in the same VM", 1185 Project.MSG_WARN); 1186 } 1187 1188 if (newEnvironment || null != env.getVariables()) { 1189 log("Changes to environment variables are ignored if running in " 1190 + "the same VM.", Project.MSG_WARN); 1191 } 1192 1193 if (getCommandline().getBootclasspath() != null) { 1194 log("bootclasspath is ignored if running in the same VM.", 1195 Project.MSG_WARN); 1196 } 1197 1198 CommandlineJava.SysProperties sysProperties = 1199 getCommandline().getSystemProperties(); 1200 if (sysProperties != null) { 1201 sysProperties.setSystem(); 1202 } 1203 1204 try { 1205 log("Using System properties " + System.getProperties(), 1206 Project.MSG_VERBOSE); 1207 if (splitJunit) { 1208 classLoader = (AntClassLoader) delegate.getClass().getClassLoader(); 1209 } else { 1210 createClassLoader(); 1211 } 1212 if (classLoader != null) { 1213 classLoader.setThreadContextLoader(); 1214 } 1215 runner = delegate.newJUnitTestRunner(test, test.getHaltonerror(), 1216 test.getFiltertrace(), 1217 test.getHaltonfailure(), false, 1218 true, classLoader); 1219 if (summary) { 1220 1221 JUnitTaskMirror.SummaryJUnitResultFormatterMirror f = 1222 delegate.newSummaryJUnitResultFormatter(); 1223 f.setWithOutAndErr("withoutanderr" 1224 .equalsIgnoreCase(summaryValue)); 1225 f.setOutput(getDefaultOutput()); 1226 runner.addFormatter(f); 1227 } 1228 1229 runner.setPermissions(perm); 1230 1231 final FormatterElement[] feArray = mergeFormatters(test); 1232 for (int i = 0; i < feArray.length; i++) { 1233 FormatterElement fe = feArray[i]; 1234 if (fe.shouldUse(this)) { 1235 File outFile = getOutput(fe, test); 1236 if (outFile != null) { 1237 fe.setOutfile(outFile); 1238 } else { 1239 fe.setOutput(getDefaultOutput()); 1240 } 1241 runner.addFormatter(fe.createFormatter(classLoader)); 1242 } 1243 } 1244 1245 runner.run(); 1246 TestResultHolder result = new TestResultHolder(); 1247 result.exitCode = runner.getRetCode(); 1248 return result; 1249 } finally { 1250 if (sysProperties != null) { 1251 sysProperties.restoreSystem(); 1252 } 1253 if (classLoader != null) { 1254 classLoader.resetThreadContextLoader(); 1255 } 1256 } 1257 } 1258 1259 1266 protected ExecuteWatchdog createWatchdog() throws BuildException { 1267 if (timeout == null) { 1268 return null; 1269 } 1270 return new ExecuteWatchdog((long) timeout.intValue()); 1271 } 1272 1273 1279 protected OutputStream getDefaultOutput() { 1280 return new LogOutputStream(this, Project.MSG_INFO); 1281 } 1282 1283 1290 protected Enumeration getIndividualTests() { 1291 final int count = batchTests.size(); 1292 final Enumeration [] enums = new Enumeration [ count + 1]; 1293 for (int i = 0; i < count; i++) { 1294 BatchTest batchtest = (BatchTest) batchTests.elementAt(i); 1295 enums[i] = batchtest.elements(); 1296 } 1297 enums[enums.length - 1] = tests.elements(); 1298 return Enumerations.fromCompound(enums); 1299 } 1300 1301 1306 protected Enumeration allTests() { 1307 Enumeration [] enums = {tests.elements(), batchTests.elements()}; 1308 return Enumerations.fromCompound(enums); 1309 } 1310 1311 1316 private FormatterElement[] mergeFormatters(JUnitTest test) { 1317 Vector feVector = (Vector ) formatters.clone(); 1318 test.addFormattersTo(feVector); 1319 FormatterElement[] feArray = new FormatterElement[feVector.size()]; 1320 feVector.copyInto(feArray); 1321 return feArray; 1322 } 1323 1324 1332 protected File getOutput(FormatterElement fe, JUnitTest test) { 1333 if (fe.getUseFile()) { 1334 String base = test.getOutfile(); 1335 if (base == null) { 1336 base = JUnitTaskMirror.JUnitTestRunnerMirror.IGNORED_FILE_NAME; 1337 } 1338 String filename = base + fe.getExtension(); 1339 File destFile = new File (test.getTodir(), filename); 1340 String absFilename = destFile.getAbsolutePath(); 1341 return getProject().resolveFile(absFilename); 1342 } 1343 return null; 1344 } 1345 1346 1357 protected boolean addClasspathEntry(String resource) { 1358 1367 if (resource.startsWith("/")) { 1368 resource = resource.substring(1); 1369 } else { 1370 resource = "org/apache/tools/ant/taskdefs/optional/junit/" 1371 + resource; 1372 } 1373 1374 File f = LoaderUtils.getResourceSource(getClass().getClassLoader(), 1375 resource); 1376 if (f != null) { 1377 log("Found " + f.getAbsolutePath(), Project.MSG_DEBUG); 1378 antRuntimeClasses.createPath().setLocation(f); 1379 return true; 1380 } else { 1381 log("Couldn\'t find " + resource, Project.MSG_DEBUG); 1382 return false; 1383 } 1384 } 1385 1386 1392 1393 private void logTimeout(FormatterElement[] feArray, JUnitTest test, String testCase) { 1394 logVmExit( 1395 feArray, test, 1396 "Timeout occurred. Please note the time in the report does" 1397 + " not reflect the time until the timeout.", 1398 testCase); 1399 } 1400 1401 1408 private void logVmCrash(FormatterElement[] feArray, JUnitTest test, String testCase) { 1409 logVmExit( 1410 feArray, test, 1411 "Forked Java VM exited abnormally. Please note the time in the report" 1412 + " does not reflect the time until the VM exit.", 1413 testCase); 1414 } 1415 1416 1422 private void logVmExit(FormatterElement[] feArray, JUnitTest test, 1423 String message, String testCase) { 1424 try { 1425 log("Using System properties " + System.getProperties(), 1426 Project.MSG_VERBOSE); 1427 if (splitJunit) { 1428 classLoader = (AntClassLoader) delegate.getClass().getClassLoader(); 1429 } else { 1430 createClassLoader(); 1431 } 1432 if (classLoader != null) { 1433 classLoader.setThreadContextLoader(); 1434 } 1435 1436 test.setCounts(1, 0, 1); 1437 test.setProperties(getProject().getProperties()); 1438 for (int i = 0; i < feArray.length; i++) { 1439 FormatterElement fe = feArray[i]; 1440 File outFile = getOutput(fe, test); 1441 JUnitTaskMirror.JUnitResultFormatterMirror formatter = 1442 fe.createFormatter(classLoader); 1443 if (outFile != null && formatter != null) { 1444 try { 1445 OutputStream out = new FileOutputStream (outFile); 1446 delegate.addVmExit(test, formatter, out, message, testCase); 1447 } catch (IOException e) { 1448 } 1450 } 1451 } 1452 if (summary) { 1453 JUnitTaskMirror.SummaryJUnitResultFormatterMirror f = 1454 delegate.newSummaryJUnitResultFormatter(); 1455 f.setWithOutAndErr("withoutanderr".equalsIgnoreCase(summaryValue)); 1456 delegate.addVmExit(test, f, getDefaultOutput(), message, testCase); 1457 } 1458 } finally { 1459 if (classLoader != null) { 1460 classLoader.resetThreadContextLoader(); 1461 } 1462 } 1463 } 1464 1465 1471 private void createClassLoader() { 1472 Path userClasspath = getCommandline().getClasspath(); 1473 if (userClasspath != null) { 1474 if (reloading || classLoader == null) { 1475 deleteClassLoader(); 1476 Path classpath = (Path) userClasspath.clone(); 1477 if (includeAntRuntime) { 1478 log("Implicitly adding " + antRuntimeClasses 1479 + " to CLASSPATH", Project.MSG_VERBOSE); 1480 classpath.append(antRuntimeClasses); 1481 } 1482 classLoader = getProject().createClassLoader(classpath); 1483 if (getClass().getClassLoader() != null 1484 && getClass().getClassLoader() != Project.class.getClassLoader()) { 1485 classLoader.setParent(getClass().getClassLoader()); 1486 } 1487 classLoader.setParentFirst(false); 1488 classLoader.addJavaLibraries(); 1489 log("Using CLASSPATH " + classLoader.getClasspath(), 1490 Project.MSG_VERBOSE); 1491 classLoader.addSystemPackageRoot("junit"); 1493 classLoader.addSystemPackageRoot("org.junit"); 1495 classLoader.addSystemPackageRoot("org.apache.tools.ant"); 1497 } 1498 } 1499 } 1500 1501 1505 private void deleteClassLoader() { 1506 if (classLoader != null) { 1507 classLoader.cleanup(); 1508 classLoader = null; 1509 } 1510 } 1511 1512 1517 protected CommandlineJava getCommandline() { 1518 if (commandline == null) { 1519 commandline = new CommandlineJava(); 1520 } 1521 return commandline; 1522 } 1523 1524 1528 private static final class ForkedTestConfiguration { 1529 private boolean filterTrace; 1530 private boolean haltOnError; 1531 private boolean haltOnFailure; 1532 private String errorProperty; 1533 private String failureProperty; 1534 1535 1543 ForkedTestConfiguration(boolean filterTrace, boolean haltOnError, 1544 boolean haltOnFailure, String errorProperty, 1545 String failureProperty) { 1546 this.filterTrace = filterTrace; 1547 this.haltOnError = haltOnError; 1548 this.haltOnFailure = haltOnFailure; 1549 this.errorProperty = errorProperty; 1550 this.failureProperty = failureProperty; 1551 } 1552 1553 1557 ForkedTestConfiguration(JUnitTest test) { 1558 this(test.getFiltertrace(), 1559 test.getHaltonerror(), 1560 test.getHaltonfailure(), 1561 test.getErrorProperty(), 1562 test.getFailureProperty()); 1563 } 1564 1565 1570 public boolean equals(Object other) { 1571 if (other == null 1572 || other.getClass() != ForkedTestConfiguration.class) { 1573 return false; 1574 } 1575 ForkedTestConfiguration o = (ForkedTestConfiguration) other; 1576 return filterTrace == o.filterTrace 1577 && haltOnError == o.haltOnError 1578 && haltOnFailure == o.haltOnFailure 1579 && ((errorProperty == null && o.errorProperty == null) 1580 || 1581 (errorProperty != null 1582 && errorProperty.equals(o.errorProperty))) 1583 && ((failureProperty == null && o.failureProperty == null) 1584 || 1585 (failureProperty != null 1586 && failureProperty.equals(o.failureProperty))); 1587 } 1588 1589 1594 public int hashCode() { 1595 return (filterTrace ? 1 : 0) 1596 + (haltOnError ? 2 : 0) 1597 + (haltOnFailure ? 4 : 0); 1598 } 1599 } 1600 1601 1605 public static final class ForkMode extends EnumeratedAttribute { 1606 1607 1610 public static final String ONCE = "once"; 1611 1614 public static final String PER_TEST = "perTest"; 1615 1618 public static final String PER_BATCH = "perBatch"; 1619 1620 1621 public ForkMode() { 1622 super(); 1623 } 1624 1625 1629 public ForkMode(String value) { 1630 super(); 1631 setValue(value); 1632 } 1633 1634 1635 public String [] getValues() { 1636 return new String [] {ONCE, PER_TEST, PER_BATCH}; 1637 } 1638 } 1639 1640 1650 protected Collection executeOrQueue(Enumeration testList, 1651 boolean runIndividual) { 1652 Map testConfigurations = new HashMap (); 1653 while (testList.hasMoreElements()) { 1654 JUnitTest test = (JUnitTest) testList.nextElement(); 1655 if (test.shouldRun(getProject())) { 1656 if (runIndividual || !test.getFork()) { 1657 execute(test); 1658 } else { 1659 ForkedTestConfiguration c = 1660 new ForkedTestConfiguration(test); 1661 List l = (List ) testConfigurations.get(c); 1662 if (l == null) { 1663 l = new ArrayList (); 1664 testConfigurations.put(c, l); 1665 } 1666 l.add(test); 1667 } 1668 } 1669 } 1670 return testConfigurations.values(); 1671 } 1672 1673 1683 protected void actOnTestResult(int exitValue, boolean wasKilled, 1684 JUnitTest test, String name) { 1685 TestResultHolder t = new TestResultHolder(); 1686 t.exitCode = exitValue; 1687 t.timedOut = wasKilled; 1688 actOnTestResult(t, test, name); 1689 } 1690 1691 1700 protected void actOnTestResult(TestResultHolder result, JUnitTest test, 1701 String name) { 1702 boolean fatal = result.timedOut || result.crashed; 1705 boolean errorOccurredHere = 1706 result.exitCode == JUnitTaskMirror.JUnitTestRunnerMirror.ERRORS || fatal; 1707 boolean failureOccurredHere = 1708 result.exitCode != JUnitTaskMirror.JUnitTestRunnerMirror.SUCCESS || fatal; 1709 if (errorOccurredHere || failureOccurredHere) { 1710 if ((errorOccurredHere && test.getHaltonerror()) 1711 || (failureOccurredHere && test.getHaltonfailure())) { 1712 throw new BuildException(name + " failed" 1713 + (result.timedOut ? " (timeout)" : "") 1714 + (result.crashed ? " (crashed)" : ""), getLocation()); 1715 } else { 1716 log(name + " FAILED" 1717 + (result.timedOut ? " (timeout)" : "") 1718 + (result.crashed ? " (crashed)" : ""), Project.MSG_ERR); 1719 if (errorOccurredHere && test.getErrorProperty() != null) { 1720 getProject().setNewProperty(test.getErrorProperty(), "true"); 1721 } 1722 if (failureOccurredHere && test.getFailureProperty() != null) { 1723 getProject().setNewProperty(test.getFailureProperty(), "true"); 1724 } 1725 } 1726 } 1727 } 1728 1729 1732 protected class TestResultHolder { 1733 1735 public int exitCode = JUnitTaskMirror.JUnitTestRunnerMirror.ERRORS; 1736 1737 public boolean timedOut = false; 1738 1739 public boolean crashed = false; 1740 } 1742 1743 1747 protected static class JUnitLogOutputStream extends LogOutputStream { 1748 private Task task; 1750 1755 public JUnitLogOutputStream(Task task, int level) { 1756 super(task, level); 1757 this.task = task; 1758 } 1759 1760 1767 protected void processLine(String line, int level) { 1768 if (line.startsWith(TESTLISTENER_PREFIX)) { 1769 task.log(line, Project.MSG_VERBOSE); 1770 } else { 1771 super.processLine(line, level); 1772 } 1773 } 1774 } 1775 1776 1780 protected static class JUnitLogStreamHandler extends PumpStreamHandler { 1781 1787 public JUnitLogStreamHandler(Task task, int outlevel, int errlevel) { 1788 super(new JUnitLogOutputStream(task, outlevel), 1789 new LogOutputStream(task, errlevel)); 1790 } 1791 } 1792} 1793 | Popular Tags |