/********************************************************************************
* CruiseControl, a Continuous Integration Toolkit
* Copyright (c) 2001, ThoughtWorks, Inc.
* 200 E. Randolph, 25th Floor
* Chicago, IL 60601 USA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* + Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* + Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* + Neither the name of ThoughtWorks, Inc., CruiseControl, nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
********************************************************************************/
package net.sourceforge.cruisecontrol.builders;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import junit.framework.TestCase;
import net.sourceforge.cruisecontrol.BuilderTest;
import net.sourceforge.cruisecontrol.CruiseControlException;
import net.sourceforge.cruisecontrol.testutil.TestUtil;
import net.sourceforge.cruisecontrol.testutil.TestUtil.FilesToDelete;
import net.sourceforge.cruisecontrol.util.IO;
import net.sourceforge.cruisecontrol.util.Util;
import org.jdom.Element;
public class AntBuilderTest extends TestCase {
private final FilesToDelete filesToDelete = new FilesToDelete();
private AntBuilder builder;
private static final String UNIX_PATH = "/usr/java/jdk1.5.0/lib/tools.jar:"
+ "/home/joris/java/cruisecontrol-2.2/main/dist/cruisecontrol.jar:"
+ "/home/joris/java/cruisecontrol-2.2/main/lib/log4j.jar:"
+ "/home/joris/java/cruisecontrol-2.2/main/lib/jdom.jar:"
+ "/home/joris/java/cruisecontrol-2.2/main/lib/ant:"
+ "/home/joris/java/cruisecontrol-2.2/main/lib/ant/ant.jar:"
+ "/home/joris/java/cruisecontrol-2.2/main/lib/ant/ant-launcher.jar:"
+ "/home/joris/java/cruisecontrol-2.2/main/lib/xerces.jar:"
+ "/home/joris/java/cruisecontrol-2.2/main/lib/xalan.jar:"
+ "/home/joris/java/cruisecontrol-2.2/main/lib/jakarta-oro-2.0.8.jar:"
+ "/home/joris/java/cruisecontrol-2.2/main/lib/mail.jar:"
+ "/home/joris/java/cruisecontrol-2.2/main/lib/junit.jar:"
+ "/home/joris/java/cruisecontrol-2.2/main/lib/activation.jar:"
+ "/home/joris/java/cruisecontrol-2.2/main/lib/commons-net-1.1.0.jar:"
+ "/home/joris/java/cruisecontrol-2.2/main/lib/starteam-sdk.jar:"
+ "/home/joris/java/cruisecontrol-2.2/main/lib/mx4j.jar:"
+ "/home/joris/java/cruisecontrol-2.2/main/lib/mx4j-tools.jar:"
+ "/home/joris/java/cruisecontrol-2.2/main/lib/mx4j-remote.jar:"
+ "/home/joris/java/cruisecontrol-2.2/main/lib/smack.jar:.";
private static final String WINDOWS_PATH = "C:\\Progra~1\\IBM\\WSAD\\tools.jar;"
+ "C:\\Java\\cruisecontrol-2.2\\main\\bin\\\\..\\dist\\cruisecontrol.jar;"
+ "C:\\Java\\cruisecontrol-2.2\\main\\bin\\\\..\\lib\\log4j.jar;"
+ "C:\\Java\\cruisecontrol-2.2\\main\\bin\\\\..\\lib\\jdom.jar;"
+ "C:\\Java\\cruisecontrol-2.2\\main\\bin\\\\..\\lib\\ant;"
+ "C:\\Java\\cruisecontrol-2.2\\main\\bin\\\\..\\lib\\ant\\ant.jar;"
+ "C:\\Java\\cruisecontrol-2.2\\main\\bin\\\\..\\lib\\ant\\ant-launcher.jar;"
+ "C:\\Java\\cruisecontrol-2.2\\main\\bin\\\\..\\lib\\xerces.jar;"
+ "C:\\Java\\cruisecontrol-2.2\\main\\bin\\\\..\\lib\\xalan.jar;"
+ "C:\\Java\\cruisecontrol-2.2\\main\\bin\\\\..\\lib\\jakarta-oro-2.0.8.jar;"
+ "C:\\Java\\cruisecontrol-2.2\\main\\bin\\\\..\\lib\\mail.jar;"
+ "C:\\Java\\cruisecontrol-2.2\\main\\bin\\\\..\\lib\\junit.jar;"
+ "C:\\Java\\cruisecontrol-2.2\\main\\bin\\\\..\\lib\\activation.jar;"
+ "C:\\Java\\cruisecontrol-2.2\\main\\bin\\\\..\\lib\\commons-net-1.1.0.jar;"
+ "C:\\Java\\cruisecontrol-2.2\\main\\bin\\\\..\\lib\\starteam-sdk.jar;"
+ "C:\\Java\\cruisecontrol-2.2\\main\\bin\\\\..\\lib\\mx4j.jar;"
+ "C:\\Java\\cruisecontrol-2.2\\main\\bin\\\\..\\lib\\mx4j-tools.jar;"
+ "C:\\Java\\cruisecontrol-2.2\\main\\bin\\\\..\\lib\\mx4j-remote.jar;"
+ "C:\\Java\\cruisecontrol-2.2\\main\\bin\\\\..\\lib\\smack.jar;"
+ "C:\\Java\\cruisecontrol-2.2\\main\\bin\\\\..\\lib\\comm.jar;"
+ "C:\\Java\\cruisecontrol-2.2\\main\\bin\\\\..\\lib\\x10.jar;.";
protected void setUp() throws Exception {
builder = new AntBuilder();
builder.setTarget("target");
builder.setBuildFile("buildfile");
AntBuilder unixBuilder = new AntBuilder() {
protected String getSystemClassPath() {
return UNIX_PATH;
}
};
unixBuilder.setTarget("target");
unixBuilder.setBuildFile("buildfile");
AntBuilder windowsBuilder = new AntBuilder() {
protected String getSystemClassPath() {
return WINDOWS_PATH;
}
};
windowsBuilder.setTarget("target");
windowsBuilder.setBuildFile("buildfile");
// builder.build() will create an antBuilderOutput.log file when isLiveOutput=true, so clean it up.
filesToDelete.add(new File(AntOutputLogger.DEFAULT_OUTFILE_NAME));
}
public void tearDown() {
filesToDelete.delete();
builder = null;
}
public void testValidate() {
builder = new AntBuilder();
try {
builder.validate();
} catch (CruiseControlException e) {
fail("antbuilder has no required attributes");
}
builder.setTime("0100");
builder.setBuildFile("buildfile");
builder.setTarget("target");
try {
builder.validate();
} catch (CruiseControlException e) {
fail("validate should not throw exceptions when options are set.");
}
}
public void testValidateShouldThrowExceptionWhenSaveLogDirDoesntExist() {
builder.setSaveLogDir("I/hope/this/dir/does/not/exist/");
try {
builder.validate();
fail();
} catch (CruiseControlException expected) {
}
}
public void testValidateShouldThrowExceptionWhenMultipleAndTimeAreBothSet() {
builder.setTime("0100");
builder.setMultiple(2);
try {
builder.validate();
fail();
} catch (CruiseControlException expected) {
}
}
public void testValidateAntHomeNotExist() {
builder = new AntBuilder();
builder.setAntHome("/this/directory/doesnt/exist");
try {
builder.validate();
fail("validate should throw exceptions when the specified anthome doesn't exist");
} catch (CruiseControlException e) {
assertTrue("wrong exception caught [" + e.getMessage() + "]", e
.getMessage().indexOf(
"'antHome' must exist and be a directory") >= 0);
}
}
public void testValidateAntHomeExistButNoAntScript() {
builder = new AntBuilder();
builder.setAntHome("/");
try {
builder.validate();
fail("validate should throw exceptions when the specified anthome doesn't contain the antscript");
} catch (CruiseControlException e) {
assertTrue(
"wrong exception caught [" + e.getMessage() + "]",
e.getMessage().indexOf(
"'antHome' must contain an ant execution script") >= 0);
}
}
public void testValidateAntHomeAndAntscriptSet() {
builder = new AntBuilder();
builder.setAntHome("/");
builder.setAntScript("foo.bat");
try {
builder.validate();
fail("validate should throw exceptions when anthome and antscript are both set");
} catch (CruiseControlException e) {
assertTrue(
"wrong exception caught [" + e.getMessage() + "]",
e.getMessage().indexOf(
"'antHome' and 'antscript' cannot both be set") >= 0);
}
}
public void testShouldAddDashboardLoggerJarToCommandLine() throws Exception {
assertFalse(AntBuilder.shouldAddDashboardLoggerJarToCommandLine(false, false));
assertFalse(AntBuilder.shouldAddDashboardLoggerJarToCommandLine(false, true));
assertFalse(AntBuilder.shouldAddDashboardLoggerJarToCommandLine(true, false));
assertTrue(AntBuilder.shouldAddDashboardLoggerJarToCommandLine(true, true));
}
public void testValidateIsLiveOutput() throws Exception {
builder = new AntBuilder();
assertTrue("Wrong default value for LiveOutput", builder.isLiveOutput());
assertNull("Wrong default value for progressLoggerLib", builder.getProgressLoggerLib());
final File fakeProgressLoggerLibJar = AntScriptTest.createFakeProgressLoggerLib();
filesToDelete.add(fakeProgressLoggerLibJar);
builder.setLiveOutput(false);
builder.validate();
builder.setLiveOutput(true);
builder.validate(); // should pass since fakeProgressLoggerLibJar exists
final String dummyLoggerLib = "dummyLoggerLib";
builder.setProgressLoggerLib(dummyLoggerLib);
// should pass since default useLogger is false (see AntBuilder.isDashboardLoggerRequired())
builder.validate();
builder.setUseLogger(true);
try {
builder.validate();
fail("Non-existant overriden progressLoggerLib should have failed.");
} catch (CruiseControlException e) {
assertTrue(e.getMessage().startsWith("File specified ["));
}
// Now run tests without fakeProgressLoggerLibJar
builder.setUseLogger(false);
assertTrue("failed to delete fakeProgressLoggerLibJar: " + fakeProgressLoggerLibJar.getAbsolutePath(),
fakeProgressLoggerLibJar.delete());
// reset to default
builder.setProgressLoggerLib(null);
builder.setLiveOutput(false);
builder.validate();
builder.setLiveOutput(true);
// should pass since default useLogger is false (see AntBuilder.isDashboardLoggerRequired())
builder.validate();
builder.setUseLogger(true);
try {
builder.validate();
fail("Missing default progressLoggerLib should have failed.");
} catch (AntScript.ProgressLibLocatorException e) {
assertTrue(e.getMessage().startsWith("The progressLoggerLib jar file does not exist where expected: "));
}
builder.setProgressLoggerLib(dummyLoggerLib);
try {
builder.validate();
fail("Non-existant overriden progressLoggerLib should have failed.");
} catch (CruiseControlException e) {
assertTrue(e.getMessage().startsWith("File specified ["));
}
}
public void testGetCommandLineArgs_DebugAndQuiet() {
builder.setUseDebug(true);
builder.setUseQuiet(true);
try {
builder.validate();
fail("validate() should throw CruiseControlException when both useDebug and useQuiet are true");
} catch (CruiseControlException expected) {
}
}
public void testGetAntLogAsElement() throws CruiseControlException {
Element buildLogElement = new Element("build");
File logFile = new File(TestUtil.getTargetDir(), "_tempAntLog.xml");
filesToDelete.add(logFile);
IO.write(logFile,
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<?xml-stylesheet "
+ "type=\"text/xsl\" href=\"log.xsl\"?>\n<build></build>");
assertEquals(
buildLogElement.toString(),
builder.getAntLogAsElement(logFile).toString());
}
public void testGetAntLogAsElement_NoLogFile() {
File doesNotExist = new File("blah blah blah does not exist");
try {
builder.getAntLogAsElement(doesNotExist);
fail();
} catch (CruiseControlException expected) {
assertEquals("ant logfile " + doesNotExist.getAbsolutePath() + " does not exist.", expected.getMessage());
}
}
public void testBuild() throws Exception {
final File buildFile = File.createTempFile("testbuild", ".xml", TestUtil.getTargetDir());
writeBuildFile(buildFile, 0);
filesToDelete.add(buildFile);
builder.setBuildFile(buildFile.getAbsolutePath());
builder.setTempFile("notLog.xml");
builder.setTarget("init");
builder.validate();
final Map<String, String> buildProperties = BuilderTest.createPropsWithProjectName("testproject");
Element buildElement = builder.build(buildProperties, null);
int initCount = getInitCount(buildElement);
assertEquals(1, initCount);
builder.setTarget("init init");
buildElement = builder.build(buildProperties, null);
initCount = getInitCount(buildElement);
assertEquals(2, initCount);
}
private static void writeBuildFile(final File buildFile, final int sleepSeconds) throws CruiseControlException {
final StringBuilder contents = new StringBuilder();
contents.append("<project name='testbuild' default='init'>");
contents.append("<target name='init'><echo message='called testbulid.xml init target'/></target>");
contents.append("<target name='time.out'><sleep seconds='").append(sleepSeconds).append("'/></target>");
contents.append("</project>");
IO.write(buildFile, contents.toString());
}
private int getInitCount(final Element buildElement) {
int initFoundCount = 0;
final Iterator targetIterator = buildElement.getChildren("target").iterator();
String name;
while (targetIterator.hasNext()) {
name = ((Element) targetIterator.next()).getAttributeValue("name");
if (name.equals("init")) {
initFoundCount++;
}
}
return initFoundCount;
}
public void testBuildTimeout() throws Exception {
final File buildFile = File.createTempFile("testbuild", ".xml", TestUtil.getTargetDir());
final int buildSleepSecs = 2;
writeBuildFile(buildFile, buildSleepSecs);
filesToDelete.add(buildFile);
builder.setBuildFile(buildFile.getAbsolutePath());
builder.setTarget("time.out");
final int testTimeoutSecs = buildSleepSecs / 2;
builder.setTimeout(testTimeoutSecs);
builder.setUseDebug(true);
builder.setUseLogger(true);
builder.setLiveOutput(false); // required to bypass Dashboard logger
builder.validate();
final Map<String, String> buildProperties = new HashMap<String, String>();
final long startTime = System.currentTimeMillis();
filesToDelete.add(new File(TestUtil.getTargetDir(), "log.xml"));
Element buildElement = builder.build(buildProperties, null);
final long elapsedMillis = System.currentTimeMillis() - startTime;
assertTrue(buildElement.getAttributeValue("error").indexOf("timeout") >= 0);
assertTrue("Too much time has elapsed (" + elapsedMillis + " millis) for AntBuilder timeout of "
+ testTimeoutSecs + " secs.",
elapsedMillis < ((testTimeoutSecs + 3) * 1000L));
// test we don't fail when there is no ant log file
builder.setTimeout(1);
builder.setUseDebug(false);
builder.setUseLogger(false);
builder.setTempFile("shouldNot.xml");
buildElement = builder.build(buildProperties, null);
assertTrue(buildElement.getAttributeValue("error").indexOf("timeout") >= 0);
}
public void testSaveAntLog() throws IOException {
final String originalDirName = "target";
filesToDelete.add(new File(TestUtil.getTargetDir(), originalDirName));
final String logName = "log.xml";
final String saveDirName = "target/reports/ant";
builder.setSaveLogDir(saveDirName);
builder.setTempFile(logName);
final File originalDir = new File(originalDirName);
final File originalLog = new File(originalDir, logName);
Util.doMkDirs(originalDir);
originalLog.createNewFile();
final File saveDir = new File(saveDirName);
final File savedLog = new File(saveDir, logName);
Util.doMkDirs(saveDir);
savedLog.delete();
builder.saveAntLog(originalLog);
assertTrue(savedLog.exists());
savedLog.delete();
builder.setSaveLogDir("");
builder.saveAntLog(originalLog);
assertFalse(savedLog.exists());
builder.setSaveLogDir(null);
builder.saveAntLog(originalLog);
assertFalse(savedLog.exists());
}
public void testFindAntScriptNonWindows() throws CruiseControlException {
builder.setAntHome("/foo/bar");
assertEquals("/foo/bar/bin/ant", builder.findAntScript(false));
}
public void testFindAntScriptWindows() throws CruiseControlException {
builder.setAntHome("c:\\foo\\bar");
assertEquals("c:\\foo\\bar\\bin\\ant.bat", builder.findAntScript(true));
}
public void testFindAntScriptWindowsNoAntHome() {
try {
builder.findAntScript(false);
fail("expected exception");
} catch (CruiseControlException expected) {
//expected...
}
try {
builder.findAntScript(true);
fail("expected exception");
} catch (CruiseControlException expected) {
//expected...
}
}
public void testValidateBuildFileWorksForNonDefaultDirectory() throws IOException, CruiseControlException {
final File antworkdir = new File("antworkdir");
antworkdir.mkdir();
antworkdir.deleteOnExit();
final File file = File.createTempFile("build", ".xml", antworkdir);
file.deleteOnExit();
filesToDelete.add(file);
filesToDelete.add(antworkdir);
builder.setAntWorkingDir(antworkdir.getAbsolutePath());
builder.setBuildFile(file.getName());
builder.validateBuildFileExists();
builder.setBuildFile(file.getAbsolutePath());
builder.validateBuildFileExists();
file.delete();
try {
builder.validateBuildFileExists();
fail();
} catch (CruiseControlException expected) {
}
builder.setBuildFile(file.getName());
try {
builder.validateBuildFileExists();
fail();
} catch (CruiseControlException expected) {
}
}
public void testValidateBuildFileNonAbsFileWithDifferentAntWorkDir()
throws IOException, CruiseControlException {
// this use case occurs for paths like "/tools/build.xml" on winz, where "/" will be on the current drive.
// in such cases where config must build on multiple OS's, and we don't want to configure paths twice for each.
// for example: antworkdir = /project
// buildfile = /tools/build.xml - not absolute on Winz, but will be found by Ant
// assuming the following file exists: c:\tools\build.xml
final File antworkdir = new File("antworkdir");
antworkdir.mkdir();
antworkdir.deleteOnExit();
final File buildfileDir = new File("tools");
buildfileDir.mkdir();
buildfileDir.deleteOnExit();
final File file = File.createTempFile("build", ".xml", buildfileDir);
file.deleteOnExit();
filesToDelete.add(file);
filesToDelete.add(buildfileDir);
filesToDelete.add(antworkdir);
builder.setAntWorkingDir(antworkdir.getAbsolutePath());
builder.setBuildFile(buildfileDir.getName() + "/" + file.getName());
builder.validateBuildFileExists();
builder.setBuildFile(file.getAbsolutePath());
builder.validateBuildFileExists();
file.delete();
try {
builder.validateBuildFileExists();
fail();
} catch (CruiseControlException expected) {
}
builder.setBuildFile(file.getName());
try {
builder.validateBuildFileExists();
fail();
} catch (CruiseControlException expected) {
}
}
public void testRealBuild() throws IOException, CruiseControlException {
File tempDir = new File(System.getProperty("java.io.tmpdir"));
File tempSubdir = new File(tempDir, "cruisecontroltest" + System.currentTimeMillis());
tempSubdir.mkdir();
filesToDelete.add(tempSubdir);
File buildFile = new File(tempSubdir, "build.xml");
createFakeProjectInTempDir(tempSubdir, buildFile);
builder.setBuildFile(buildFile.getAbsolutePath());
builder.setTarget("all");
builder.setTempFile("notLog.xml");
builder.validate();
final Map<String, String> buildProperties = BuilderTest.createPropsWithProjectName("test1");
builder.build(buildProperties, null);
//Now verify a JUnit report was created
File htmlJUnitReportFile = new File(tempSubdir, "reports/html/index.html");
assertTrue("JUnit HTML Report was not created", htmlJUnitReportFile.exists());
}
// @todo Remove when deprecated methods get/setShowAntOutput are removed.
@SuppressWarnings("deprecation")
public void testSetShowAntOutputLinkedToSetLiveOutput() {
assertTrue(builder.isLiveOutput());
assertTrue(builder.getShowAntOutput());
builder.setShowAntOutput(false);
assertFalse(builder.isLiveOutput());
assertFalse(builder.getShowAntOutput());
builder.setLiveOutput(true);
assertTrue(builder.isLiveOutput());
assertTrue(builder.getShowAntOutput());
}
private void createFakeProjectInTempDir(File dir, File buildFile) throws CruiseControlException {
File srcDir = new File(dir, "src");
File srcPackageDir = new File(srcDir, "apackage");
writeSimpleClassFile(srcPackageDir);
File testDir = new File(dir, "test");
File testPackageDir = new File(testDir, "apackage");
writeSimpleTestFile(testPackageDir);
writeSimpleBuildFile(buildFile);
}
private void writeSimpleClassFile(final File srcPackageDir) throws CruiseControlException {
srcPackageDir.mkdirs();
final File simpleClassFile = new File(srcPackageDir, "Simple.java");
final StringBuilder contents = new StringBuilder();
contents.append("package apackage;");
contents.append("public class Simple {");
contents.append(" public void call() {}");
contents.append("}");
IO.write(simpleClassFile, contents.toString());
}
private void writeSimpleTestFile(final File testPackageDir) throws CruiseControlException {
testPackageDir.mkdirs();
final File simpleTestFile = new File(testPackageDir, "SimpleTest.java");
final StringBuilder contents = new StringBuilder();
contents.append("package apackage;");
contents.append("import junit.framework.TestCase;");
contents.append("public class SimpleTest extends TestCase {");
contents.append(" public void testSimple() {");
contents.append(" Simple simple = new Simple();");
contents.append(" simple.call();");
contents.append(" }");
contents.append("}");
IO.write(simpleTestFile, contents.toString());
}
private void writeSimpleBuildFile(final File buildFile) throws CruiseControlException {
/*
* This compiles the Simple and SimpleTest classes, runs JUnit, and generates a junitreport
*/
final StringBuilder contents = new StringBuilder();
contents.append("<project name='Simple' basedir='.' default='all'>\n");
contents.append(" <target name='all'>\n");
contents.append(" <mkdir dir='build' />\n");
contents.append(" <path id='test.classpath'>\n");
contents.append(" <pathelement location='build' />\n");
contents.append(" </path>\n");
// For whatever reason, rpm versions of Ant on Fedora fail with: Error starting modern compiler
// unless we add fork="yes" to the javac line.
// Also, Fedora requires the 'ant-trax' package to build the unit test report, otherwise you get the error:
// Errors while applying transformations:
// java.lang.ClassNotFoundException: org.apache.tools.ant.taskdefs.optional.TraXLiaison
// Here's my list of rpm ant
// packages needed the CC unit tests to work:
// ant.i386 1.7.0-1jpp.4.fc9 installed
// ant-junit.i386 1.7.0-1jpp.4.fc9 installed
// ant-nodeps.i386 1.7.0-1jpp.4.fc9 installed
// ant-scripts.i386 1.7.0-1jpp.4.fc9 installed
// ant-trax.i386 1.7.0-1jpp.4.fc9 installed
// contents.append(" <javac srcdir='src' destdir='build' />\n");
// contents.append(" <javac srcdir='test' destdir='build' classpathref='test.classpath' />\n");
contents.append(" <javac srcdir='src' destdir='build' fork='yes' />\n");
contents.append(" <javac srcdir='test' destdir='build' classpathref='test.classpath' fork='yes' />\n");
contents.append(" <mkdir dir='reports/xml' />");
contents.append(" <junit fork='yes'>\n");
contents.append(" <classpath>\n");
contents.append(" <path refid='test.classpath' />\n");
contents.append(" </classpath>\n");
contents.append(" <formatter type='xml' />\n");
contents.append(" <batchtest fork='yes' todir='reports/xml'>\n");
contents.append(" <fileset dir='build'>\n");
contents.append(" <include name='**/*Test*.class' />\n");
contents.append(" </fileset>\n");
contents.append(" </batchtest>\n");
contents.append(" </junit>\n");
contents.append(" <junitreport>\n");
contents.append(" <fileset dir='reports/xml'>\n");
contents.append(" <include name='TEST-*.xml'/>\n");
contents.append(" </fileset>\n");
contents.append(" <report format='frames' todir='reports/html' />\n");
contents.append(" </junitreport>\n");
contents.append(" </target>\n");
contents.append("\n");
contents.append("</project>\n");
IO.write(buildFile, contents.toString());
}
}