1 /* QuiltTask.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.optional.junit.Enumerations;
9 import org.apache.tools.ant.types.Commandline;
10 import org.apache.tools.ant.types.CommandlineJava;
11 import org.apache.tools.ant.types.Environment;
12 import org.apache.tools.ant.types.Path;
13
14 import java.io.File;
15 import java.net.URL;
16 import java.util.Enumeration;
17 import java.util.Vector;
18
19 import org.quilt.cl.QuiltClassLoader;
20 import org.quilt.framework.QuiltTest;
21 import org.quilt.reports.FmtSelector;
22 import org.quilt.cover.stmt.StmtRegistry;
23 //import org.quilt.runner.*;
24
25 /***
26 * Ant task for running Quilt and JUnit.
27 *
28 * <p>The Quilt Ant task is meant to be a plug-in replacement for
29 * the Ant JUnitTask. Whatever build.xml works with JUnitTask
30 * should behave identically with QuiltTask. The opposite is not
31 * true: using QuiltTask allows you to run coverage tests in
32 * addition to JUnit unit tests</p>
33 *
34 * <p>Parameter names / build file options are compatible with
35 * the build.xml options for JUnitTask as of Ant 1.5.3-1, so that
36 * if <junit> and </junit> are replaced with <quilt> and </quilt>
37 * respectively in the build.xml file, test behavior should be the same.</p>
38 *
39 * <p>Build file options either control the individual test and so
40 * are passed to Quilt and JUnit, or manage QuiltTask and the test
41 * process.</p>
42 *
43 * <p>Most test options will go through Quilt to JUnit.
44 * All are set by Ant set* methods, where the name for the method
45 * setting the variable 'var' is 'setVar'. That is, the first
46 * letter of the variable name is capitalized, then the modified
47 * name is appended to 'set'.</p>
48 *
49 * <p>Task control parameters are NOT passed through to Quilt or JUnit.
50 * These variables are modified by Ant add*, set*, and create* routines, where
51 * the names are determined as described above.</p>
52 *
53 * <p>QuiltTest options can be set at three levels. First, then can
54 * be set as attributes to the <quilt&gr; element. In this case,
55 * they are the defaults for all tests.</p>
56 *
57 * <p>Next, they can be set at the <batchtest> leve.. In this case,
58 * these attributes will be used for all files in the batch test.</p>
59 *
60 * <p>Finally, they can be set at the <test> level, in which case
61 * they will override the defaults set higher up.</p>
62 *
63 * <p>QuiltTask collects filesets from batch test elements and the
64 * names of individual tests. These are then passed to a Scheduler
65 * which unpacks the batch tests and schedules all tests for running.</p>
66 *
67 * <p>It may be important to understand that under certain circumstances
68 * batches of tests will be run more than once result. This will normally
69 * be the result of an error in the way that dependencies are structured
70 * in build.xml. </p>
71 *
72 * @see QuiltTest
73 * @see Scheduler
74 * @see TaskControl
75 */
76 public class QuiltTask extends Task {
77 private Scheduler sch = null;
78 private TaskControl tc = null;
79
80 // // THESE DUPLICATE ELEMENTS OF TaskControl //////////////////
81 // // XXX and this apparently isn't set -- leading to bugs
82 // private CommandlineJava commandline = new CommandlineJava();
83
84 // DO THESE BELONG IN TaskControl ?
85 private boolean includeAntRuntime = true;
86 private Path antRuntimeClasses = null;
87
88 // COLLECT ANT PARAMETERS USING ADD/CREATE/SET //////////////////
89 // Please keep in order by variable name ////////////////////////
90
91 // TEST PARAMETERS //////////////////////////////////////////////
92 // Ant creates child elements (individual tests and BatchTests),
93 // then assigns values to task attributes, and THEN assigns
94 // values to child element attributes. This means that the
95 // default values assigned at the task level can be overridden
96 // by test and batch level assignments, IF the task-level values
97 // are applied immediately to all tests and batch tests.
98 //
99 // The methods that follow assign such task-level defaults. It
100 // is important to bear in mind that Ant uses methods of the same
101 // name and call QuiltTask to assign defaults and to call
102 // QuiltTest and BatchTest to override these defaults.
103 // //////////////////////////////////////////////////////////////
104 private QuiltTest qt // scratch variable
105 = new QuiltTest(); // to keep the compiler quiet
106 public void setCheckCoverage (boolean b) {
107 sch.schedule();
108 while ( (qt = sch.nextTest()) != null) {
109 qt.setCheckCoverage(b);
110 }
111 }
112 public void setCheckExcludes (String s) {
113 sch.schedule();
114 while ( (qt = sch.nextTest()) != null) {
115 qt.setCheckExcludes(s);
116 }
117 }
118 public void setCheckIncludes (String s) {
119 sch.schedule();
120 while ( (qt = sch.nextTest()) != null) {
121 qt.setCheckIncludes(s);
122 }
123 }
124 public void setErrorProperty(String propertyName) {
125 sch.schedule();
126 while ( (qt = sch.nextTest()) != null) {
127 qt.setErrorProperty(propertyName);
128 }
129 }
130 public void setFailureProperty(String propertyName) {
131 sch.schedule();
132 while ( (qt = sch.nextTest()) != null) {
133 qt.setFailureProperty(propertyName);
134 }
135 }
136 public void setFiltertrace(boolean b) {
137 sch.schedule();
138 while ( (qt = sch.nextTest()) != null) {
139 qt.setFiltertrace(b);
140 }
141 }
142 public void setFork(boolean b) {
143 sch.schedule();
144 while ( (qt = sch.nextTest()) != null) {
145 qt.setFork(b);
146 }
147 }
148 public void setHaltOnError(boolean b) {
149 sch.schedule();
150 while ( (qt = sch.nextTest()) != null) {
151 qt.setHaltOnError(b);
152 }
153 }
154 public void setHaltOnFailure(boolean b) {
155 sch.schedule();
156 while ( (qt = sch.nextTest()) != null) {
157 qt.setHaltOnFailure(b);
158 }
159 }
160 public void setMockTestRun(boolean b) {
161 sch.schedule();
162 while ( (qt = sch.nextTest()) != null) {
163 qt.setMockTestRun (b);
164 }
165 }
166 public void setShowOutput(boolean b) {
167 tc.setShowOutput(b); // NEEDS FIXING
168 sch.schedule();
169 while ( (qt = sch.nextTest()) != null) {
170 qt.setShowOutput(b);
171 }
172 }
173
174 // TASK PARAMETERS //////////////////////////////////////////////
175 // //////////////////////////////////////////////////////////////
176
177 public BatchTest createBatchTest () {
178 BatchTest bt = new BatchTest (getProject());
179 sch.addBatchTest(bt);
180 return bt; // returns to Ant a reference to the object created
181 }
182
183 public Path createClasspath() {
184 // commandline.createClasspath(getProject()).createPath(); // XXX
185 return tc.createClasspath();
186 }
187 public void setDir(File dir) {
188 tc.setDir(dir);
189 }
190 public void addEnv(Environment.Variable var) {
191 tc.addEnv(var);
192 }
193 public void addFormatter(FmtSelector fe) {
194 tc.addFormatter(fe);
195 }
196 public void setIncludeAntRuntime(boolean b) {
197 tc.setIncludeAntRuntime(b);
198 }
199 public void setJvm(String value) {
200 tc.setJvm(value);
201 }
202 public Commandline.Argument createJvmarg() {
203 return tc.createJvmarg();
204 }
205 public void setMaxmemory(String max) {
206 tc.setMaxmemory (max);
207 }
208 public void setMockExec(boolean b) {
209 tc.setMockExec(b);
210 }
211 public void setNewenvironment(boolean b) {
212 tc.setNewEnvironment(b);
213 }
214 // compatible with JUnitTask but kludgey
215 public void setPrintsummary(String sValue) {
216 SummaryAttribute sa = new SummaryAttribute(sValue);
217 tc.setSummary (sa.asBoolean());
218 tc.setSummaryValue (sa.getValue());
219 }
220 public void addSysproperty(Environment.Variable sysp) {
221 tc.addSysproperty(sysp);
222 }
223 public void addTest(QuiltTest qt) {
224 sch.addTest (qt);
225 }
226 public void setTimeout(Long t) {
227 tc.setTimeout (t);
228 }
229
230 // CONSTRUCTOR //////////////////////////////////////////////////
231 public QuiltTask() throws Exception {
232 sch = new Scheduler (this);
233 tc = sch.getTaskControl();
234 }
235
236 private MockExec mockE = null;
237 private TestExec testE = null;
238 private boolean mockery = false;
239
240 private boolean firstTimeThrough = true;
241 private void addCPEs () {
242 mockery = tc.getMockExec();
243 if (mockery) {
244 mockE = new MockExec();
245 } else {
246 testE = new TestExec();
247 }
248 addClasspathEntry("/junit/framework/TestCase.class");
249 addClasspathEntry("/org/apache/tools/ant/Task.class");
250 addClasspathEntry("/org/quilt/runner/BaseTestRunner.class");
251 }
252 // FIRST ANT ENTRY POINT: init() ////////////////////////////////
253 // only called once /////////////////////////////////////////////
254 public void init() {
255 antRuntimeClasses = new Path(getProject());
256 }
257
258 // SECOND ANT ENTRY POINT: execute () ///////////////////////////
259 // May be called many times /////////////////////////////////////
260 public void execute() throws BuildException {
261 if (firstTimeThrough) {
262 firstTimeThrough = false;
263 addCPEs();
264 sch.unbatch(); // merge batch tests with other tests
265 }
266 sch.schedule();
267
268 Path quiltClassPath = tc.getCommandline().getClasspath();
269 if (tc.getIncludeAntRuntime()) {
270 quiltClassPath.append ( tc.getAntRuntimeClasses() );
271 }
272 QuiltClassLoader qcl = new QuiltClassLoader (
273 QuiltClassLoader.cpToURLs(
274 tc.getCommandline().getClasspath().toString()),
275 this.getClass().getClassLoader(), // we delegate to ..
276 // delegated included excluded
277 (String[])null, (String[])null, (String[])null);
278 StmtRegistry stmtReg = (StmtRegistry)qcl.addQuiltRegistry(
279 "org.quilt.cover.stmt.StmtRegistry" );
280 if (stmtReg == null) {
281 System.out.println(
282 "QuiltTask.execute: org.quilt.cover.stmt.StmtRegistry not found\n"
283 + " classpath error?");
284 }
285 tc.setLoader(qcl);
286 while ( (qt = sch.nextTest()) != null) {
287 if (tc.getMockExec()) {
288 mockE.run(qt, tc);
289 } else if (qt.runMe (getProject())) {
290 testE.execute(qt, tc);
291 }
292 }
293 if (stmtReg != null) {
294 System.out.println (
295 stmtReg.getReport()
296 );
297 }
298 // DEBUG
299 else System.out.println(
300 "QuiltTask.execute: after running tests, stmtReg is null");
301 // END
302 }
303
304 // //////////////////////////////////////////////////////////////
305 // CLEAN ME UP. This code is per JUnit task, needs work.
306 // //////////////////////////////////////////////////////////////
307
308 protected void addClasspathEntry(String resource) {
309 URL url = getClass().getResource(resource);
310 if (url != null) {
311 String u = url.toString();
312 if (u.startsWith("jar:file:")) {
313 int pling = u.indexOf("!"); // Ant standard term
314 String jarName = u.substring(9, pling);
315 log("Found " + jarName, Project.MSG_DEBUG);
316 antRuntimeClasses.createPath()
317 .setLocation(new File((new File(jarName))
318 .getAbsolutePath()));
319 } else if (u.startsWith("file:")) {
320 int tail = u.indexOf(resource);
321 String dirName = u.substring(5, tail);
322 log("Found " + dirName, Project.MSG_DEBUG);
323 antRuntimeClasses.createPath()
324 .setLocation(new File((new File(dirName))
325 .getAbsolutePath()));
326 } else {
327 log("Don\'t know how to handle resource URL " + u,
328 Project.MSG_DEBUG);
329 }
330 } else {
331 log("Couldn\'t find " + resource, Project.MSG_DEBUG);
332 }
333 }
334 // TASK CONTROL SUPPORT //////////////////////////////////////////
335 public void handleTheOutput(String line) {
336 super.handleOutput(line);
337 }
338 public void handleTheFlush(String line) {
339 super.handleFlush(line);
340 }
341 public void handleTheErrorOutput(String line) {
342 super.handleErrorOutput(line);
343 }
344 public void handleTheErrorFlush(String line) {
345 super.handleErrorFlush(line);
346 }
347 }
This page was automatically generated by Maven