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-2007 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: package org.netbeans.xtest;
043:
044: import java.io.BufferedReader;
045: import java.io.File;
046: import java.io.FileReader;
047: import java.io.IOException;
048: import java.util.Date;
049: import java.util.Enumeration;
050: import java.util.Hashtable;
051: import java.util.Iterator;
052: import java.util.Map;
053: import java.util.Set;
054: import org.apache.tools.ant.BuildException;
055: import org.apache.tools.ant.Project;
056: import org.apache.tools.ant.Task;
057: import org.apache.tools.ant.taskdefs.Ant;
058: import org.apache.tools.ant.taskdefs.Java;
059: import org.netbeans.xtest.pe.GetResultsDirsTask;
060: import org.netbeans.xtest.pe.PEConstants;
061: import org.netbeans.xtest.pe.TestRunInfoTask;
062: import org.netbeans.xtest.pe.TransformXMLTask;
063: import org.netbeans.xtest.pe.xmlbeans.ModuleError;
064: import org.netbeans.xtest.pe.xmlbeans.TestBag;
065: import org.netbeans.xtest.pe.xmlbeans.UnitTestCase;
066: import org.netbeans.xtest.pe.xmlbeans.UnitTestSuite;
067:
068: /**
069: * NbExecutor is a task which reads config from master-config and executes
070: * all tests in a loop.
071: *
072: * @author lm97939
073: */
074: public class NbExecutor extends Task {
075:
076: String targetName = null;
077: String targetParamModule = null;
078: String targetParamTestType = null;
079: String targetParamTestAttributes = null;
080: String mode = null;
081: File testrun;
082:
083: private static final String[] propertiesToPass = {
084: "netbeans.dest.dir", "netbeans.home", "build.sysclasspath",
085: "ant.home", "running.mode", "basedir", "user.dir",
086: "jdkhome", "jemmy.home", "jellytools.home", "harness.dir" };
087:
088: public void setTargetName(String name) {
089: this .targetName = name;
090: }
091:
092: public void setTargetParamModule(String param) {
093: this .targetParamModule = param;
094: }
095:
096: public void setTargetParamTesttype(String param) {
097: this .targetParamTestType = param;
098: }
099:
100: public void setTargetParamTestAttributes(String param) {
101: this .targetParamTestAttributes = param;
102: }
103:
104: public void setRunningMode(String mode) {
105: this .mode = mode;
106: }
107:
108: public void setTestRun(File testrun) {
109: if (testrun.getName().startsWith("${"))
110: return;
111: this .testrun = testrun;
112: }
113:
114: public void execute() throws BuildException {
115: if (null == targetName || 0 == targetName.length())
116: throw new BuildException(
117: "Attribute 'targetname' has to be set.");
118: if (null == targetParamModule
119: || 0 == targetParamModule.length())
120: throw new BuildException(
121: "Attribute 'targetParamModule' has to be set.");
122: if (null == targetParamTestType
123: || 0 == targetParamTestType.length())
124: throw new BuildException(
125: "Attribute 'targetParamTestType' has to be set.");
126:
127: MConfig cfg = NbTestConfig.getMConfig();
128:
129: if (null == cfg)
130: throw new BuildException(
131: "XTest configuration wasn't chosen, use call xtestconfig task first.",
132: getLocation());
133:
134: MConfig.Setup setup = cfg.getConfigSetup();
135: if (mode.equalsIgnoreCase("run") && setup != null)
136: executeStart(setup);
137:
138: Enumeration all_tests = cfg.getAllTests();
139: while (all_tests.hasMoreElements()) {
140: try {
141: MConfig.TestGroup test_group = (MConfig.TestGroup) all_tests
142: .nextElement();
143:
144: MConfig.Setup msetup = test_group.getSetup();
145: if (mode.equalsIgnoreCase("run") && msetup != null)
146: executeStart(msetup);
147:
148: Hashtable props = test_group.getProperties();
149:
150: Enumeration tests = test_group.getTests();
151:
152: while (tests.hasMoreElements()) {
153: MConfig.Test test = (MConfig.Test) tests
154: .nextElement();
155: File outputfile = null;
156: String debug_level = "";
157: try {
158: Java callee = new Java(); // do not use Project.createTask: CCE with presetdefs
159: callee.setProject(getProject());
160:
161: callee.setOwningTarget(getOwningTarget());
162: callee.setTaskName(getTaskName());
163: callee.setLocation(getLocation());
164: callee.init();
165:
166: callee
167: .setClassname("org.apache.tools.ant.Main");
168: callee.createClasspath().setPath(
169: getProject().getProperty(
170: "java.class.path"));
171: callee.setFork(true);
172: callee.setFailonerror(true);
173: callee.setInput(new File("dummy")); // #90576,103874 - otherwise it freezes when calling InetAddress.getLocalHost.
174:
175: callee.setDir(getProject().getBaseDir());
176: callee.createArg().setLine(
177: "-buildfile "
178: + "\""
179: + getProject().getProperty(
180: "ant.file") + "\"");
181:
182: outputfile = getLogFile(test.getModule() + "_"
183: + test.getType());
184: if (outputfile != null) {
185: //callee.setOutput(outputfile);
186: callee.createArg().setLine(
187: "-logfile " + "\"" + outputfile
188: + "\"");
189: }
190:
191: debug_level = getProject().getProperty(
192: "xtest.debug.level");
193: if (debug_level != null) {
194: if (debug_level.equals("debug")
195: || debug_level.equals("verbose")) {
196: callee.createArg().setValue(
197: "-" + debug_level);
198: }
199: }
200:
201: callee.createArg().setValue(targetName);
202:
203: callee.createArg().setValue(
204: "-D" + targetParamModule + "="
205: + test.getModule());
206: callee.createArg().setValue(
207: "-D" + targetParamTestType + "="
208: + test.getType());
209: callee.createArg().setValue(
210: "-D" + targetParamTestAttributes + "="
211: + test.getAttributesAsString());
212:
213: Set set = props.entrySet();
214: Iterator it = set.iterator();
215: while (it.hasNext()) {
216: Map.Entry map = (Map.Entry) it.next();
217: callee.createArg().setValue(
218: "-D" + (String) map.getKey() + "="
219: + (String) map.getValue());
220: }
221:
222: Hashtable ps = getProject().getProperties();
223: Enumeration en = ps.keys();
224: while (en.hasMoreElements()) {
225: String name = (String) en.nextElement();
226: String value = (String) ps.get(name);
227: if (name.startsWith("xtest")
228: || name.startsWith("_xtest")) {
229: callee.createArg().setValue(
230: "-D" + name + "=" + value);
231: }
232: }
233: for (int i = 0; i < propertiesToPass.length; i++) {
234: String p = getProject().getProperty(
235: propertiesToPass[i]);
236: if (p != null) {
237: callee.createArg().setValue(
238: "-D" + propertiesToPass[i]
239: + "=" + p);
240: }
241: }
242:
243: log("Executing module " + test.getModule()
244: + ", testtype " + test.getType()
245: + " at " + new Date().toString());
246: if (outputfile != null)
247: log("Output is redirected to "
248: + outputfile.getAbsolutePath());
249: callee.execute();
250: log("Executed successfully.");
251: } catch (BuildException e) {
252: String er = findErrorMessage(outputfile);
253: if (er == null) {
254: er = e.toString();
255: }
256: logError(test.getModule(), test.getType(),
257: outputfile, er);
258: }
259: }
260: if (mode.equalsIgnoreCase("run") && msetup != null)
261: executeStop(msetup);
262: } catch (BuildException e) {
263: log("Exception during executiong test:\n"
264: + e.toString(), Project.MSG_ERR);
265: logError("unknown", null, null, e.toString());
266: }
267: }
268: if (mode.equalsIgnoreCase("run") && setup != null)
269: executeStop(setup);
270: }
271:
272: private String findErrorMessage(File f) {
273: if (f == null)
274: return null;
275: StringBuffer buff = new StringBuffer();
276: try {
277: BufferedReader r = new BufferedReader(new FileReader(f));
278: String line = r.readLine();
279: while (line != null && !line.trim().equals("BUILD FAILED"))
280: line = r.readLine();
281: if (line == null || !line.trim().equals("BUILD FAILED"))
282: return "";
283: while ((line = r.readLine()) != null
284: && !line.startsWith("Total time")) {
285: if (!line.trim().equals(""))
286: buff.append(line + "\n");
287: }
288: r.close();
289: } catch (IOException e) {
290: return null;
291: }
292: return buff.toString();
293: }
294:
295: private File getLogFile(String prefix) {
296: String testrundir = getProject().getProperty(
297: "xtest.results.testrun.dir");
298: if (testrundir == null)
299: return null;
300: String dir = testrundir + File.separator + "logs";
301: File dirfile = getProject().resolveFile(dir);
302: if (!dirfile.exists())
303: dirfile.mkdirs();
304: String new_prefix = prefix.replace('/', '_');
305: File file = new File(dirfile, new_prefix + ".log");
306: int c = 1;
307: while (file.exists()) {
308: file = new File(dirfile, new_prefix + "_" + c + ".log");
309: c++;
310: }
311: return file;
312: }
313:
314: private void logError(String module, String testtype, File logfile,
315: String mess) {
316: log("ERROR when executing module "
317: + module
318: + ", testtype "
319: + testtype
320: + ". "
321: + (logfile == null ? "" : "Details in "
322: + logfile.getAbsolutePath() + ".")
323: + "\nError message: " + mess, Project.MSG_ERR);
324:
325: if (testrun == null)
326: return;
327: TestRunInfoTask task = (TestRunInfoTask) getProject()
328: .createTask("testruninfo");
329: task.setOwningTarget(getOwningTarget());
330: task.setTaskName(getTaskName());
331: task.setLocation(getLocation());
332: task.init();
333:
334: //TestRunInfoTask task = new TestRunInfoTask();
335: ModuleError moduleError = new ModuleError(module, testtype,
336: logfile == null ? null : logfile.getName(), mess);
337: task.setOutFile(testrun);
338: task.setModuleError(moduleError);
339: task.execute();
340:
341: try {
342: addErrorTestBag(module, testtype, logfile, mess);
343: } catch (Exception e) {
344: log("NbExecutor#addErrorTestBag: " + e.getMessage());
345: e.printStackTrace();
346: }
347: }
348:
349: /** Create a new test bag results to report unexpected critical error.
350: * In most case it is a compilation error but it can be something different.
351: * This test bag contains one suite with one test case. It satisfies that
352: * critical error appears in summary results.
353: */
354: private void addErrorTestBag(String module, String testtype,
355: File logfile, String message) throws Exception {
356: log(
357: "\n\n================== addErrorTestBag ========================",
358: Project.MSG_VERBOSE);
359: File resultsDir = new File(getProject().getProperty(
360: "xtest.results.testrun.dir"));
361: log("xtest.results.testrun.dir=" + resultsDir,
362: Project.MSG_VERBOSE);
363: // create new testbag dir in results (e.g. testbagDir=results\testrun_060331-120201\testbag_2)
364: GetResultsDirsTask grdt = new GetResultsDirsTask();
365: grdt.setProject(getProject());
366: // property need to be unique. It is used just only inside GetResultsDirsTask.
367: grdt.setTestBagDirProperty("dummy.xtest.results.testbag.dir"
368: + System.currentTimeMillis());
369: grdt.setTestRunDirProperty("xtest.results.testrun.dir");
370: File testbagDir = grdt.createAndSetTestBag();
371: log("testbagDir=" + testbagDir, Project.MSG_VERBOSE);
372:
373: String label = "Critical Error";
374:
375: // create test case bean
376: UnitTestCase testCaseBean = new UnitTestCase();
377: testCaseBean.xmlat_name = label;
378: testCaseBean.xmlat_class = label;
379: testCaseBean.xmlat_result = UnitTestCase.TEST_ERROR;
380: testCaseBean.xmlat_message = "Compilation failed or other critical error appeared. Look at build script log for details.";
381: testCaseBean.xml_cdata = message;
382:
383: // create test suite bean
384: String suiteName = label;
385: UnitTestSuite testSuiteBean = new UnitTestSuite();
386: testSuiteBean.xmlat_name = suiteName;
387: testSuiteBean.xmlat_time = 0;
388: testSuiteBean.xmlat_testsTotal = 1;
389: testSuiteBean.xmlat_testsPass = 0;
390: testSuiteBean.xmlat_testsFail = 0;
391: testSuiteBean.xmlat_testsError = 1;
392: testSuiteBean.xmlat_testsUnexpectedPass = 0;
393: testSuiteBean.xmlat_testsExpectedFail = 0;
394: testSuiteBean.xmlat_timeStamp = new java.sql.Timestamp(System
395: .currentTimeMillis());
396: testSuiteBean.xmlel_UnitTestCase = new UnitTestCase[] { testCaseBean };
397:
398: // create test bag bean
399: TestBag testBagBean = new TestBag();
400: testBagBean.setModule(module);
401: testBagBean.setName(label);
402: testBagBean.setTestType(testtype);
403: testBagBean.xmlel_UnitTestSuite = new UnitTestSuite[] { testSuiteBean };
404:
405: // create results dir for suite
406: File suiteResultsDir = new File(testbagDir,
407: PEConstants.XMLRESULTS_DIR + File.separator + "suites");
408: if (!suiteResultsDir.mkdir()) {
409: log("NbExecutor#addErrorTestBag: Cannot create directory "
410: + suiteResultsDir);
411: return;
412: }
413: File suiteFile = new File(suiteResultsDir, "TEST-" + suiteName
414: + ".xml");
415: // save created suite to testbag_ID/xmlresults/suites/TEST-Critical Error.xml
416: testSuiteBean.saveXMLBean(suiteFile);
417:
418: File testbagFile = new File(testbagDir,
419: PEConstants.XMLRESULTS_DIR + File.separator
420: + PEConstants.TESTBAG_XML_FILE);
421: testBagBean.saveXMLBean(testbagFile);
422:
423: // regenerated testbag to include created suite
424: // (Not needed if beans are properly created)
425: // RegenerateXMLTask.regenerateTestBag(testbagDir, true, false);
426: // transform testbag from XML to HTML
427: System.setProperty("xtest.home", getProject().getProperty(
428: "xtest.home"));
429: TransformXMLTask.transformResults(testbagDir, testbagDir);
430: log(
431: "================== addErrorTestBag ========================\n\n",
432: Project.MSG_VERBOSE);
433: }
434:
435: private void executeStart(MConfig.Setup setup)
436: throws BuildException {
437: executeSetup(setup.getName() + "_start", setup.getStartDir(),
438: setup.getStartAntfile(), setup.getStartTarget(), setup
439: .getStartOnBackground(), setup.getStartDelay());
440: }
441:
442: private void executeStop(MConfig.Setup setup) throws BuildException {
443: executeSetup(setup.getName() + "_stop", setup.getStopDir(),
444: setup.getStopAntfile(), setup.getStopTarget(), setup
445: .getStopOnBackground(), setup.getStopDelay());
446: }
447:
448: private void executeSetup(final String name, File dir,
449: String antfile, String targetname, boolean onBackground,
450: int delay) throws BuildException {
451: if (antfile == null && targetname == null)
452: return;
453: final Ant ant = (Ant) getProject().createTask("ant");
454: ant.setOwningTarget(getOwningTarget());
455: ant.setLocation(getLocation());
456: ant.init();
457: ant.setDir(dir);
458: ant.setAntfile(antfile);
459: ant.setTarget(targetname);
460: final File outputfile = getLogFile(name);
461: if (outputfile != null)
462: ant.setOutput(outputfile.getAbsolutePath());
463: if (onBackground) {
464: Thread thread = new Thread() {
465: public void run() {
466: try {
467: ant.execute();
468: } catch (BuildException e) {
469: log("Exception during executiong setup:\n"
470: + e.toString(), Project.MSG_ERR);
471: logError("setup: " + name, null, outputfile, e
472: .toString());
473: }
474: }
475: };
476: thread.start();
477: if (delay != 0) {
478: try {
479: Thread.currentThread().sleep(delay);
480: } catch (InterruptedException e) {
481: throw new BuildException(e);
482: }
483: }
484: } else {
485: try {
486: ant.execute();
487: } catch (BuildException e) {
488: log("Exception during executiong setup:\n"
489: + e.toString(), Project.MSG_ERR);
490: logError("setup: " + name, null, outputfile, e
491: .toString());
492: }
493: }
494: }
495:
496: }
|