001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: /*
042: * MTestExecutor
043: * Class running tests by executing chosen testbags with appropriate
044: * executor (result processor).
045: *
046: * Created on March 28, 2001, 6:57 PM
047: */
048:
049: package org.netbeans.xtest.harness;
050:
051: import org.apache.tools.ant.*;
052: import org.apache.tools.ant.types.*;
053: import org.apache.tools.ant.taskdefs.*;
054:
055: import java.util.*;
056: import java.io.File;
057: import java.io.IOException;
058: import org.netbeans.junit.Filter;
059: import org.netbeans.xtest.testrunner.*;
060: import org.netbeans.xtest.plugin.PluginExecuteTask;
061:
062: /**
063: *
064: * @author mk97936
065: * @version
066: */
067: public class MTestExecutor extends Task {
068:
069: String targetName = null;
070: String targetParamClasspathProp = null;
071: String targetParamTestConfigProp = "tbag.testtype";
072: String targetParamNameProp = null;
073: String targetParamExecutorProp = "tbag.executor";
074: String targetParamTimeoutProp = "xtest.timeout";
075:
076: /*
077: protected boolean enableAssertions = true;
078: protected int debugPort = 0;
079: protected boolean debugSuspend = false;
080: */
081:
082: File resultDir;
083: File workDir;
084:
085: public void setTargetName(String name) {
086: this .targetName = name;
087: }
088:
089: public void setParamClasspathProp(String param) {
090: this .targetParamClasspathProp = param;
091: }
092:
093: public void setParamTestConfigProp(String param) {
094: this .targetParamTestConfigProp = param;
095: }
096:
097: public void setParamNameProp(String param) {
098: this .targetParamNameProp = param;
099: }
100:
101: public void setParamExecutorProp(String param) {
102: this .targetParamExecutorProp = param;
103: }
104:
105: public void setParamTimeoutProp(String param) {
106: this .targetParamTimeoutProp = param;
107: }
108:
109: public void setResultDir(File s) {
110: resultDir = s;
111: }
112:
113: public void setWorkDir(File s) {
114: workDir = s;
115: }
116:
117: /*
118: public void setDebugPort(int debugPort) {
119: this.debugPort = debugPort;
120: }
121:
122: public void setDebugSuspend(boolean suspend) {
123: this.debugSuspend = suspend;
124: }
125:
126: public void setEnableAssertions(boolean enableAssertions) {
127: this.enableAssertions = enableAssertions;
128: }
129: */
130:
131: public void execute() throws BuildException {
132:
133: if (null == targetParamClasspathProp
134: || 0 == targetParamClasspathProp.length())
135: throw new BuildException(
136: "Attribute 'targetParamClasspathProp' has to be set.");
137:
138: if (resultDir == null) {
139: throw new BuildException("ResultDir is not set");
140: }
141: if (workDir == null) {
142: throw new BuildException("WorkDir is not set");
143: }
144:
145: Testbag testbags[] = MTestConfigTask.getTestbags();
146: if (null == testbags)
147: throw new BuildException(
148: "TestBag configuration wasn't chosen.",
149: getLocation());
150:
151: for (int i = 0; i < testbags.length; i++) {
152:
153: // get TestBag
154: Testbag testbag = testbags[i];
155:
156: MTestConfig.AntExecType exec = testbag.getExecutor();
157: if (exec == null)
158: throw new BuildException("Testbag " + testbag.getName()
159: + " has not a executor.");
160:
161: Ant ant_new = (Ant) getProject().createTask("ant");
162: ant_new.setOwningTarget(getOwningTarget());
163: ant_new.setAntfile(exec.getAntFile());
164: ant_new.setTarget(exec.getTarget());
165: if (exec.getDir() != null)
166: ant_new.setDir(getProject().resolveFile(exec.getDir()));
167: ant_new.init();
168:
169: /// ??????? add xtest.userdata| prefix ?????
170:
171: // add all test properties for given testbag
172: Testbag.TestProperty properties[] = testbag
173: .getTestProperties();
174: if (properties != null)
175: for (int j = 0; j < properties.length; j++) {
176: Property ant_prop = ant_new.createProperty();
177: ant_prop.setName(properties[j].getName());
178: ant_prop.setValue(properties[j].getValue());
179: }
180:
181: // Set classpath property for given testbag
182: Property clspth_prop = ant_new.createProperty();
183: clspth_prop.setName(targetParamClasspathProp);
184:
185: StringBuffer stb = new StringBuffer();
186:
187: // if any of the testset contains setup dir, it does not
188: // have to be added to classpath
189: boolean testsetContainsSetupDir = false;
190: if (testbag.getSetupDir() == null) {
191: testsetContainsSetupDir = true;
192: }
193:
194: for (int j = 0; j < testbag.getTestsets().length; j++) {
195: // add compiled tests to classpath (work/sys/test)
196:
197: stb.append(ant_new.getProject().getProperty(
198: "xtest.tests.dir"));
199: stb.append(File.pathSeparatorChar);
200:
201: // check if this testset contains setup dir
202: if (!testsetContainsSetupDir) {
203: String testsetDir = testbag.getTestsets()[j]
204: .getDir();
205: testsetContainsSetupDir = testbag.getSetupDir()
206: .equals(testsetDir);
207: }
208: }
209: // add setup/teardown dir if available
210: if (!testsetContainsSetupDir) {
211: stb.append(testbag.getSetupDir());
212: stb.append(File.pathSeparatorChar);
213: }
214:
215: if (stb.length() > 1) {
216: stb.deleteCharAt(stb.length() - 1);
217: }
218: clspth_prop.setValue(stb.toString());
219:
220: // set name of executed test config
221: Property cttprop = ant_new.createProperty();
222: cttprop.setName(targetParamTestConfigProp);
223: cttprop.setValue(MTestConfigTask.getMTestConfig()
224: .getTesttype());
225:
226: // set name of executed testbag
227: Property nameprop = ant_new.createProperty();
228: nameprop.setName(targetParamNameProp);
229: nameprop.setValue(testbag.getName());
230:
231: // set name of executor for executed testbags
232: Property execprop = ant_new.createProperty();
233: execprop.setName(targetParamExecutorProp);
234: execprop.setValue(testbag.getExecutor().getName());
235:
236: if (testbag.getTimeout() != null) {
237: Property timeoutprop = ant_new.createProperty();
238: timeoutprop.setName(targetParamTimeoutProp);
239: timeoutprop.setValue(testbag.getTimeout().toString());
240: }
241:
242: // Need to unpack test because we want to search for tests only
243: // in compiled distribution.
244: getProject().executeTarget("prepare-tests");
245:
246: createJUnitTestRunnerPropertyFile(testbag);
247:
248: // execute tests
249: ant_new.execute();
250:
251: // run results processor
252: PluginExecuteTask.executeCorrespondingResultProcessor(this );
253: }
254:
255: }
256:
257: private JUnitTestRunnerProperties createJUnitTestRunnerPropertyFile(
258: Testbag testbag) {
259:
260: ArrayList testsWithFilters = new ArrayList();
261: try {
262:
263: for (int i = 0; i < testbag.getTestsets().length; i++) {
264: Testbag.Testset testset = testbag.getTestsets()[i];
265: TestScanner ts = new TestScanner();
266:
267: // scan for tests in ${xtest.tests.dir} (i.e. work/sys/tests)
268: String testsClassesDir = getProject().getProperty(
269: "xtest.tests.dir");
270: ts.setBasedir(testsClassesDir);
271:
272: /*
273: for (int i=0; i<additionalPatterns.size(); i++) {
274: Object o = additionalPatterns.elementAt(i);
275: defaultPatterns.append((PatternSet) o, p);
276: } */
277:
278: /*System.out.println("Testbag "+testbag.getName());
279: System.out.println("testset = "+testset);
280: System.out.println("Testset includes "+testset.getIncludes());
281: */
282: ts.setIncludes(testset.getIncludes());
283: ts.setExcludes(testset.getExcludes());
284:
285: // scan directories for test classes and associated test patterns
286: ts.scan();
287:
288: TestFilter[] filter;
289: filter = ts.getIncludedFiles();
290:
291: // go through all found test classes and prepare the JUnitTest instances
292: for (int j = 0; j < filter.length; j++) {
293: String testName = fileToClassname(filter[j]
294: .getFile());
295: log("Adding test class " + testName,
296: Project.MSG_VERBOSE);
297: TestWithFilter test = new TestWithFilter();
298: test.testName = testName;
299: test.includeFilter = filter[j].getFilter()
300: .getIncludes();
301: test.excludeFilter = filter[j].getFilter()
302: .getExcludes();
303: // add test to array
304: testsWithFilters.add(test);
305: }
306: }
307: } catch (IOException e) {
308: throw new BuildException(e.getMessage(), e);
309: }
310:
311: log("Preparing test runner property file", Project.MSG_DEBUG);
312: JUnitTestRunnerProperties props = new JUnitTestRunnerProperties();
313: // results dir
314: props.setResultsDirName(resultDir.getAbsolutePath());
315: // setup teardown
316: if ((testbag.getSetUpClassName() != null)
317: && (testbag.getSetUpMethodName() != null)) {
318: props.setTestbagSetup(testbag.getSetUpClassName(), testbag
319: .getSetUpMethodName());
320: }
321: if ((testbag.getTearDownClassName() != null)
322: && (testbag.getTearDownMethodName() != null)) {
323: props.setTestbagTeardown(testbag.getTearDownClassName(),
324: testbag.getTearDownMethodName());
325: }
326: // tests
327: for (int i = 0; i < testsWithFilters.size(); i++) {
328: TestWithFilter test = (TestWithFilter) testsWithFilters
329: .get(i);
330: props.addTestNameWithFilter(test.testName,
331: test.includeFilter, test.excludeFilter);
332: }
333: // save it to workdir
334: try {
335: File testRunnerPropertyFile = new File(workDir,
336: TestRunnerHarness.TESTLIST_FILENAME);
337: log("Saving test runner property to "
338: + testRunnerPropertyFile, Project.MSG_DEBUG);
339: props.save(testRunnerPropertyFile);
340: } catch (IOException ioe) {
341: throw new BuildException(
342: "Cannot save test runner property file", ioe);
343: }
344: return props;
345:
346: }
347:
348: // convert file to class name
349: private String fileToClassname(String file) {
350: if (file.endsWith(".java")) {
351: file = file.substring(0, file.length() - 5); // ".java".length() equals 5
352: } else if (file.endsWith(".class")) {
353: file = file.substring(0, file.length() - 6); // ".class".length() equals 6
354: }
355: return javaToClass(file);
356: }
357:
358: /**
359: * convenient method to convert a pathname without extension to a
360: * fully qualified classname. For example <tt>org/apache/Whatever</tt> will
361: * be converted to <tt>org.apache.Whatever</tt>
362: * @param filename the filename to "convert" to a classname.
363: * @return the classname matching the filename.
364: */
365: public final static String javaToClass(String filename) {
366: return filename.replace(File.separatorChar, '.');
367: }
368:
369: // this is rather struct than class :-(
370: // this represents test (testname) with include and exclude filters
371: static class TestWithFilter {
372: String testName;
373: Filter.IncludeExclude[] includeFilter;
374: Filter.IncludeExclude[] excludeFilter;
375: }
376: }
|