1 /* ForkTest.java */
2
3 package org.quilt.frontend.ant;
4
5 import org.apache.tools.ant.BuildException;
6 import org.apache.tools.ant.Project;
7 import org.apache.tools.ant.Task;
8 import org.apache.tools.ant.taskdefs.Execute;
9 import org.apache.tools.ant.taskdefs.ExecuteWatchdog; // need this
10 import org.apache.tools.ant.taskdefs.LogStreamHandler;
11 import org.apache.tools.ant.types.CommandlineJava;
12 import org.apache.tools.ant.types.EnumeratedAttribute;
13 import org.apache.tools.ant.types.Environment;
14 import org.apache.tools.ant.types.Path;
15 import org.apache.tools.ant.util.FileUtils;
16
17 import java.io.File;
18 import java.io.FileOutputStream;
19 import java.io.IOException;
20 import java.io.OutputStream;
21
22 import java.util.Enumeration;
23 import java.util.Hashtable;
24 import java.util.Properties;
25 import java.util.Vector;
26
27 import junit.framework.AssertionFailedError;
28 import junit.framework.Test;
29 import junit.framework.TestResult;
30
31 import org.quilt.framework.*;
32 import org.quilt.reports.*;
33
34 // //////////////////////////////////////////////////////////////////
35 // NEEDS LOTS OF ATTENTION //////////////////////////////////////////
36 // //////////////////////////////////////////////////////////////////
37 //
38 /***
39 * Run an individual test in a separate JVM. Search on Bug 23150;
40 * needs to return correct status code if interrupted or times out.
41 */
42 public class ForkTest {
43
44 private Project project = null;
45 private Task task = null;
46 private TaskControl tc = null;
47 private QuiltTest qt = null;
48 private boolean mockery = false;
49 private boolean checkingCoverage = false;
50
51 /*** No-arg constructor. */
52 public ForkTest() { }
53
54 /***
55 * Fork an individual test, running it in a separate Java virtual
56 * machine.
57 *
58 * @param qt Data structure holding test parameters.
59 * @param tc Structure holding parameters for the entire run.
60 * @param watchdog Sets timeout in ms for this test.
61 */
62 protected int execTest (QuiltTest qt, TaskControl tc,
63 ExecuteWatchdog watchdog) throws BuildException {
64
65 this.tc = tc;
66 task = tc.getTask();
67 project = task.getProject();
68 mockery = qt.getMockTestRun();
69 checkingCoverage = qt.getCheckCoverage();
70
71 CommandlineJava cmd = (CommandlineJava) tc.getCommandline().clone();
72
73 if (mockery) {
74 task.log("ForkTest: setting class name to MockTestRunner");
75 cmd.setClassname( "org.quilt.textui.MockTestRunner");
76 } else {
77 cmd.setClassname( "org.quilt.textui.TestRunner");
78 }
79 // //////////////////////////////////////////////////////////
80 // THIS INTERFACE MUST BE KEPT IN SYNC WITH textui.TestRunner
81 // and textui.MockTestRunner
82 // //////////////////////////////////////////////////////////
83 cmd.createArgument().setValue(qt.getName());
84 cmd.createArgument().setValue("checkCoverage=" + checkingCoverage);
85 if (checkingCoverage) {
86 String excluded = qt.getCheckExcludes();
87 String included = qt.getCheckIncludes();
88 if (excluded != null ) {
89 cmd.createArgument().setValue(
90 "checkExcludes=" + excluded);
91 }
92 if (included != null ) {
93 cmd.createArgument().setValue(
94 "checkIncludes=" + included);
95 }
96 }
97 cmd.createArgument().setValue("filtertrace="
98 + qt.getFiltertrace());
99 cmd.createArgument().setValue("haltOnError="
100 + qt.getHaltOnError());
101 cmd.createArgument().setValue("haltOnFailure="
102 + qt.getHaltOnFailure());
103
104 if (tc.getIncludeAntRuntime()) {
105 task.log("Adding " + tc.getAntRuntimeClasses()
106 + " to CLASSPATH",
107 Project.MSG_VERBOSE);
108 cmd.createClasspath(project).createPath()
109 .append(tc.getAntRuntimeClasses());
110 }
111
112 if (tc.getSummary()) {
113 task.log("Running " + qt.getName(), Project.MSG_INFO);
114 cmd.createArgument().setValue(
115 "formatter=org.quilt.reports.SummaryFormatter");
116 }
117
118 cmd.createArgument().setValue("showoutput="
119 + String.valueOf(qt.getShowOutput()));
120
121 StringBuffer formatterArg = new StringBuffer(256);
122 final FmtSelector[] selectors = tc.mergeSelectors(qt);
123 for (int i = 0; i < selectors.length; i++) {
124 FmtSelector fs = selectors[i];
125 formatterArg.append("formatter=");
126 formatterArg.append(fs.getClassname());
127 File outFile = tc.getOutput(fs, qt);
128 if (outFile != null) {
129 formatterArg.append(",");
130 formatterArg.append(outFile);
131 }
132 cmd.createArgument().setValue(formatterArg.toString());
133 formatterArg.setLength(0);
134 }
135
136 File propsFile =
137 FileUtils.newFileUtils().
138 createTempFile("quilt", ".properties",
139 project.getBaseDir());
140 cmd.createArgument().setValue("propsfile="
141 + propsFile.getAbsolutePath());
142 Hashtable p = project.getProperties();
143 Properties props = new Properties();
144 for (Enumeration e = p.keys(); e.hasMoreElements(); ) {
145 Object key = e.nextElement();
146 props.put(key, p.get(key));
147 }
148 try {
149 FileOutputStream outstream =
150 new FileOutputStream(propsFile);
151 // props.save() is deprecated
152 props.save(outstream,
153 "Ant QuiltTask generated properties file");
154 outstream.close();
155 } catch (java.io.IOException e) {
156 propsFile.delete();
157 throw new BuildException(
158 "Error creating temporary properties "
159 + "file.", e, task.getLocation());
160 }
161 // prepare to fork the test
162 Execute forker = new Execute(
163 new LogStreamHandler(task,
164 Project.MSG_INFO, Project.MSG_WARN), watchdog);
165 forker.setCommandline(cmd.getCommandline());
166 forker.setAntRun(project);
167 if (tc.getDir() != null) {
168 forker.setWorkingDirectory(tc.getDir());
169 }
170
171 String[] environment = tc.getEnv().getVariables();
172 if (environment != null) {
173 for (int i = 0; i < environment.length; i++) {
174 task.log("Setting environment variable: " + environment[i],
175 Project.MSG_VERBOSE);
176 }
177 }
178 forker.setNewenvironment(tc.getNewEnvironment());
179 forker.setEnvironment(environment);
180
181 task.log(cmd.describeCommand(), Project.MSG_VERBOSE);
182
183 int retVal;
184 try {
185 retVal = forker.execute (); // do the actual fork
186 } catch (IOException e) {
187 throw new BuildException(
188 "Error forking test", e, task.getLocation());
189 } finally {
190 if (watchdog != null && watchdog.killedProcess()) {
191 logTimeout(selectors, qt);
192 // see Bug 23150; also needs to be set to 1 if interrrupted
193 retVal = 1;
194 }
195
196 if (!propsFile.delete()) {
197 throw new BuildException(
198 "Error deleting temporary properties file.");
199 }
200 }
201 return retVal;
202 }
203
204 // DO WE REALLY WANT TO DO THIS, ONCE PER FORMATTER ?
205
206 private void logTimeout(FmtSelector[] selectors,
207 QuiltTest qt) {
208
209 for (int i = 0; i < selectors.length; i++) {
210 FmtSelector fs = selectors[i];
211 File outFile = tc.getOutput(fs, qt);
212 Formatter formatter = fs.createFormatter();
213 if (outFile != null && formatter != null) {
214 try {
215 OutputStream out = new FileOutputStream(outFile);
216 formatter.setOutput(out);
217 formatter.startTestSuite(qt);
218 qt.setCounts(0, 0, 1);
219 Test t = new Test() {
220 public int countTestCases() { return 0; }
221 public void run(TestResult r) {
222 throw new AssertionFailedError(
223 "Timeout during test run.");
224 }
225 };
226 formatter.startTest(t);
227 formatter.addError(t, new AssertionFailedError(
228 "Timeout during test run."));
229
230 formatter.endTestSuite(qt);
231 } catch (IOException e) {
232 // just ignore any more exceptions
233 }
234 }
235 }
236 }
237 }
This page was automatically generated by Maven