/*
* Copyright 2016 ThoughtWorks, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.thoughtworks.go.domain;
import com.googlecode.junit.ext.JunitExtRunner;
import com.googlecode.junit.ext.RunIf;
import com.thoughtworks.go.buildsession.BuildSession;
import com.thoughtworks.go.buildsession.BuildSessionBasedTestCase;
import com.thoughtworks.go.config.ConfigCache;
import com.thoughtworks.go.config.CruiseConfig;
import com.thoughtworks.go.config.JobConfig;
import com.thoughtworks.go.config.MagicalGoConfigXmlLoader;
import com.thoughtworks.go.domain.buildcause.BuildCause;
import com.thoughtworks.go.domain.builder.Builder;
import com.thoughtworks.go.helper.ConfigFileFixture;
import com.thoughtworks.go.helper.JobInstanceMother;
import com.thoughtworks.go.helper.StageMother;
import com.thoughtworks.go.junitext.EnhancedOSChecker;
import com.thoughtworks.go.plugin.access.pluggabletask.TaskExtension;
import com.thoughtworks.go.remote.work.BuildAssignment;
import com.thoughtworks.go.server.domain.BuildComposer;
import com.thoughtworks.go.server.service.UpstreamPipelineResolver;
import com.thoughtworks.go.server.service.builders.*;
import com.thoughtworks.go.util.ConfigElementImplementationRegistryMother;
import com.thoughtworks.go.util.FileUtil;
import com.thoughtworks.go.util.SystemUtil;
import com.thoughtworks.go.utils.Timeout;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.hamcrest.core.Is;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.springframework.core.io.ClassPathResource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static com.google.common.collect.Iterables.getLast;
import static com.thoughtworks.go.domain.JobResult.*;
import static com.thoughtworks.go.domain.JobState.*;
import static com.thoughtworks.go.junitext.EnhancedOSChecker.DO_NOT_RUN_ON;
import static com.thoughtworks.go.junitext.EnhancedOSChecker.WINDOWS;
import static com.thoughtworks.go.matchers.ConsoleOutMatcher.*;
import static com.thoughtworks.go.matchers.RegexMatcher.matches;
import static com.thoughtworks.go.util.SystemUtil.isWindows;
import static com.thoughtworks.go.util.TestUtils.copyAndClose;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.core.StringContains.containsString;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.MockitoAnnotations.initMocks;
@RunWith(JunitExtRunner.class)
public class BuildComposerTest extends BuildSessionBasedTestCase {
public static final String PIPELINE_NAME = "pipeline1";
public static final String PIPELINE_LABEL = "100";
public static final String STAGE_NAME = "mingle";
public static final String JOB_PLAN_NAME = "run-ant";
private static final int STAGE_COUNTER = 100;
private static final JobIdentifier JOB_IDENTIFIER = new JobIdentifier(PIPELINE_NAME, -3, PIPELINE_LABEL, STAGE_NAME, String.valueOf(STAGE_COUNTER), JOB_PLAN_NAME, 1L);
private static final String SERVER_URL = "somewhere-does-not-matter";
private static final String NANT = "<job name=\"" + JOB_PLAN_NAME + "\">\n"
+ " <tasks>\n"
+ " <nant target=\"-help\"/>\n"
+ " </tasks>\n"
+ "</job>";
private static final String NANT_WITH_WORKINGDIR = "<job name=\"" + JOB_PLAN_NAME + "\">\n"
+ " <tasks>\n"
+ " <nant target=\"-help\" workingdir=\"not-exists\" />\n"
+ " </tasks>\n"
+ "</job>";
private static final String RAKE = "<job name=\"" + JOB_PLAN_NAME + "\">\n"
+ " <tasks>\n"
+ " <rake target=\"--help\"/>\n"
+ " </tasks>\n"
+ "</job>";
private static final String WILL_FAIL = "<job name=\"" + JOB_PLAN_NAME + "\">\n"
+ " <tasks>\n"
+ " <ant target=\"something-not-really-exist\" />\n"
+ " </tasks>\n"
+ "</job>";
private static final String WILL_PASS = "<job name=\"" + JOB_PLAN_NAME + "\">\n"
+ " <tasks>\n"
+ " <exec command=\"echo\">\n"
+ " <arg>hello world</arg>\n"
+ " </exec>\n"
+ " </tasks>\n"
+ "</job>";
private static final String WITH_ENV_VAR = "<job name=\"" + JOB_PLAN_NAME + "\">\n"
+ " <environmentvariables>\n"
+ " <variable name=\"JOB_ENV\">\n"
+ " <value>foobar</value>\n"
+ " </variable>\n"
+ " <variable name=\"" + (isWindows() ? "Path" : "PATH") + "\">\n"
+ " <value>/tmp</value>\n"
+ " </variable>\n"
+ " </environmentvariables>\n"
+ " <tasks>\n"
+ " <ant target=\"-help\" />\n"
+ " </tasks>\n"
+ "</job>";
private static final String WITH_SECRET_ENV_VAR = "<job name=\"" + JOB_PLAN_NAME + "\">\n"
+ " <environmentvariables>\n"
+ " <variable name=\"foo\">\n"
+ " <value>foo(i am a secret)</value>\n"
+ " </variable>\n"
+ " <variable name=\"bar\" secure=\"true\">\n"
+ " <value>i am a secret</value>\n"
+ " </variable>\n"
+ " </environmentvariables>\n"
+ " <tasks>\n"
+ " <ant target=\"-help\" />\n"
+ " </tasks>\n"
+ "</job>";
private static final String SOMETHING_NOT_EXIST = "something-not-exist";
private static final String CMD_NOT_EXIST = "<job name=\"" + JOB_PLAN_NAME + "\">\n"
+ " <tasks>\n"
+ " <exec command=\"" + SOMETHING_NOT_EXIST + "\" />\n"
+ " </tasks>\n"
+ "</job>";
private static final String WILL_NOT_RUN = "<job name=\"" + JOB_PLAN_NAME + "\">\n"
+ " <tasks>\n"
+ " <exec command=\"echo\" args=\"run when status is failed\">\n"
+ " <runif status=\"failed\" />\n"
+ " </exec>\n"
+ " </tasks>\n"
+ "</job>";
private static final String MULTIPLE_TASKS = "<job name=\"" + JOB_PLAN_NAME + "\">\n"
+ " <tasks>\n"
+ " <exec command=\"command-not-found\" >\n"
+ " </exec>\n"
+ " <exec command=\"echo\" args=\"run when status is failed\">\n"
+ " <runif status=\"failed\" />\n"
+ " </exec>\n"
+ " <exec command=\"echo\" args=\"run when status is passed\">\n"
+ " <runif status=\"passed\" />\n"
+ " </exec>\n"
+ " <exec command=\"echo\" args=\"run when status is any\">\n"
+ " <runif status=\"any\" />\n"
+ " </exec>\n"
+ " </tasks>\n"
+ "</job>";
private static final String MULTIPLE_RUN_IFS = "<job name=\"" + JOB_PLAN_NAME + "\">\n"
+ " <tasks>\n"
+ " <exec command=\"echo\" args=\"run when status is failed, passed or cancelled\">\n"
+ " <runif status=\"failed\" />\n"
+ " <runif status=\"passed\" />\n"
+ " </exec>\n"
+ " </tasks>\n"
+ "</job>";
private static final String SLEEP_TEN_SECONDS_ON_UNIX = "<job name=\"" + JOB_PLAN_NAME + "\">\n"
+ " <tasks>\n"
+ " <exec command=\"/bin/sh\">\n"
+ " <arg>-c</arg>\n"
+ " <arg>echo before sleep; sleep 100</arg>\n"
+ " <oncancel>\n"
+ " <exec command=\"/bin/bash\">\n"
+ " <arg>-c</arg>\n"
+ " <arg>echo \"executing on cancel task\"; echo \"done\"</arg>\n"
+ " </exec>\n"
+ " </oncancel>\n"
+ " </exec>\n"
+ " </tasks>\n"
+ "</job>";
private static final String SLEEP_TEN_SECONDS_ON_WINDOWS = "<job name=\"" + JOB_PLAN_NAME + "\">\n"
+ " <tasks>\n"
+ " <exec command=\"echo before sleep & ping 1.1.1.1 -n 1 -w 100000 >NULL\">\n"
+ " <oncancel>\n"
+ " <exec command=\"echo\">\n"
+ " <arg>executing on cancel task</arg>\n"
+ " </exec>\n"
+ " </oncancel>\n"
+ " </exec>\n"
+ " </tasks>\n"
+ "</job>";
private static BuilderFactory builderFactory = new BuilderFactory(new AntTaskBuilder(), new ExecTaskBuilder(), new NantTaskBuilder(), new RakeTaskBuilder(),
new PluggableTaskBuilderCreator(mock(TaskExtension.class)), new KillAllChildProcessTaskBuilder(), new FetchTaskBuilder(), new NullTaskBuilder());
@Mock
private static UpstreamPipelineResolver resolver;
private volatile BuildSession buildSession;
private static String willUpload(String file) {
return "<job name=\"" + JOB_PLAN_NAME + "\">\n"
+ " <artifacts>\n"
+ " <artifact src=\"something-not-there.txt\" dest=\"dist\" />\n"
+ " <artifact src=\"" + file + "\" dest=\"dist\\test\" />\n"
+ " </artifacts>"
+ " <tasks>\n"
+ " <exec command=\"echo\">\n"
+ " <arg>hello world</arg>\n"
+ " </exec>\n"
+ " </tasks>\n"
+ "</job>";
}
private static String willUploadToDest(String file, String dest) {
return "<job name=\"" + JOB_PLAN_NAME + "\">\n"
+ " <artifacts>\n"
+ " <artifact src=\"" + file + "\" dest=\"" + dest + "\" />\n"
+ " </artifacts>"
+ " <tasks>\n"
+ " <exec command=\"echo\">\n"
+ " <arg>hello world</arg>\n"
+ " </exec>\n"
+ " </tasks>\n"
+ "</job>";
}
private static String willUploadTestArtifact(String path, String dest) {
return "<job name=\"" + JOB_PLAN_NAME + "\">\n"
+ " <artifacts>\n"
+ " <test src=\"" + path + "\" dest=\"" + dest + "\" />\n"
+ " </artifacts>"
+ " <tasks>\n"
+ " <exec command=\"echo\">\n"
+ " <arg>hello world</arg>\n"
+ " </exec>\n"
+ " </tasks>\n"
+ "</job>";
}
private String willGenerateProperties(String src, String propertyName, String xpath) {
return "<job name=\"" + JOB_PLAN_NAME + "\">\n"
+ " <properties>\n"
+ " <property name=\"" + propertyName + "\" src=\"" + src + "\" xpath=\"" + xpath + "\" />\n"
+ " </properties>"
+ " <tasks>\n"
+ " <exec command=\"echo\">\n"
+ " <arg>hello world</arg>\n"
+ " </exec>\n"
+ " </tasks>\n"
+ "</job>";
}
@Before
public void setUp() throws Exception {
initMocks(this);
}
@After
public void tearDown() {
verifyNoMoreInteractions(resolver);
}
private void build(String jobXml, String pipelineName, boolean fetchMaterials, boolean cleanWorkingDir) throws Exception {
BuildAssignment assignment = getAssigment(jobXml, pipelineName, fetchMaterials, cleanWorkingDir);
final BuildCommand buildCommand = new BuildComposer(assignment).compose();
buildSession = newBuildSession();
buildSession.setEnv("GO_SERVER_URL", SERVER_URL);
buildSession.build(buildCommand);
}
@Test
public void shouldUpdateBothStatusAndResultWhenBuildHasFailed() throws Exception {
build(WILL_FAIL, PIPELINE_NAME, true, false);
assertThat(statusReporter.status(), is(Arrays.asList(Preparing, Building, Completing, Completed)));
assertThat(getLast(statusReporter.results()), is(Failed));
}
@Test
public void shouldUpdateBothStatusAndResultWhenBuildHasPassed() throws Exception {
build(WILL_PASS, PIPELINE_NAME, true, false);
assertThat(statusReporter.status(), is(Arrays.asList(Preparing, Building, Completing, Completed)));
assertThat(getLast(statusReporter.results()), is(Passed));
}
@Test
public void shouldRunTaskWhenConditionMatches() throws Exception {
build(MULTIPLE_RUN_IFS, PIPELINE_NAME, true, false);
assertThat(console.output(), containsString("[go] Current job status: passed"));
assertThat(console.output(), containsString("[go] Task: echo run when status is failed, passed or cancelled"));
assertThat(console.output(), containsString("run when status is failed, passed or cancelled"));
assertThat(console.output(), not(containsString("Current job status: failed")));
}
@Test
public void shouldNotRunTaskWhichConditionDoesNotMatch() throws Exception {
build(WILL_NOT_RUN, PIPELINE_NAME, true, false);
assertThat(console.output(), not(containsString("run when status is failed")));
}
@Test
public void shouldRunTasksBasedOnConditions() throws Exception {
build(MULTIPLE_TASKS, PIPELINE_NAME, true, false);
assertThat(console.output(), containsString("run when status is failed"));
assertThat(console.output(), printedExcRunIfInfo("command-not-found", "passed"));
assertThat(console.output(), containsString("run when status is any"));
assertThat(console.output(), printedExcRunIfInfo("echo", "run when status is any", "failed"));
assertThat(console.output(), not(containsString("run when status is passed")));
assertThat(console.output(), not(printedExcRunIfInfo("echo", "run when status is passed", "failed")));
assertThat(console.output(), not(containsString("run when status is cancelled")));
assertThat(console.output(), not(printedExcRunIfInfo("echo", "run when status is cancelled", "failed")));
}
@Test
public void shouldReportDirectoryNotExists() throws Exception {
build(NANT_WITH_WORKINGDIR, PIPELINE_NAME, true, false);
assertThat(console.output(), containsString("not-exists\" is not a directory!"));
}
@Test
@RunIf(value = EnhancedOSChecker.class, arguments = {DO_NOT_RUN_ON, WINDOWS})
public void shouldReportErrorWhenComandIsNotExistOnLinux() throws Exception {
build(CMD_NOT_EXIST, PIPELINE_NAME, true, false);
assertThat(console.output(), printedAppsMissingInfoOnUnix(SOMETHING_NOT_EXIST));
assertThat(statusReporter.results(), containsResult(Failed));
}
@Test
@RunIf(value = EnhancedOSChecker.class, arguments = {EnhancedOSChecker.WINDOWS})
public void shouldReportErrorWhenComandIsNotExistOnWindows() throws Exception {
build(CMD_NOT_EXIST, PIPELINE_NAME, true, false);
assertThat(console.output(), printedAppsMissingInfoOnWindows(SOMETHING_NOT_EXIST));
assertThat(statusReporter.results(), containsResult(Failed));
}
@Test
public void shouldReportBuildStatusToConsoleout() throws Exception {
build(WILL_FAIL, PIPELINE_NAME, true, false);
String locator = JOB_IDENTIFIER.buildLocator();
assertThat(console.output(), printedPreparingInfo(locator));
assertThat(console.output(), printedBuildingInfo(locator));
assertThat(console.output(), printedUploadingInfo(locator));
assertThat(console.output(), printedBuildFailed());
assertThat(console.output(), printedJobCompletedInfo(JOB_IDENTIFIER.buildLocatorForDisplay()));
}
@Test
@RunIf(value = EnhancedOSChecker.class, arguments = {EnhancedOSChecker.WINDOWS})
public void nantTest() throws Exception {
build(NANT, PIPELINE_NAME, true, false);
assertThat(console.output(), containsString("Usage : NAnt [options] <target> <target> ..."));
}
@Test
public void rakeTest() throws Exception {
build(RAKE, PIPELINE_NAME, true, false);
assertThat(console.output(), containsString("rake [-f rakefile] {options} targets..."));
}
@Test
public void shouldSkipMaterialUpdateWhenFetchMaterialsIsSetToFalse() throws Exception {
build(WILL_PASS, PIPELINE_NAME, false, false);
assertThat(console.output(), containsString("Start to prepare"));
assertThat(console.output(), not(containsString("Start updating")));
assertThat(console.output(), containsString("Skipping material update since stage is configured not to fetch materials"));
assertThat(statusReporter.status().contains(JobState.Preparing), is(true));
}
@Test
public void shouldUpdateMaterialsWhenFetchMaterialsIsTrue() throws Exception {
build(WILL_PASS, PIPELINE_NAME, true, false);
assertThat(console.output(), containsString("Start to prepare"));
assertThat(console.output(), containsString("Start to update materials"));
assertThat(statusReporter.status().contains(JobState.Preparing), is(true));
}
@Test
public void shouldCreateAgentWorkingDirectoryIfNotExist() throws Exception {
String pipelineName = "pipeline1";
File workingdir = new File(sandbox, "pipelines/" + pipelineName);
assertThat(workingdir.exists(), is(false));
build(WILL_PASS, pipelineName, true, false);
assertThat(console.output(),
not(containsString("Working directory \"" + workingdir.getAbsolutePath() + "\" is not a directory")));
assertThat(statusReporter.results().contains(Passed), is(true));
assertThat(workingdir.exists(), is(true));
}
@Test
public void shouldNotBombWhenCreatingWorkingDirectoryIfCleanWorkingDirectoryFlagIsTrue() throws Exception {
String pipelineName = "p1";
File workingdir = new File(sandbox, "pipelines/" + pipelineName);
assertThat(workingdir.exists(), is(false));
build(WILL_PASS, pipelineName, true, true);
assertThat(console.output(),
not(containsString("Working directory \"" + workingdir.getAbsolutePath() + "\" is not a directory")));
assertThat(statusReporter.results().contains(Passed), is(true));
assertThat(workingdir.exists(), is(true));
}
@Test
public void shouldCreateAgentWorkingDirectoryIfNotExistWhenFetchMaterialsIsFalse() throws Exception {
String pipelineName = "p1";
File workingdir = new File(sandbox, "pipelines/" + pipelineName);
assertThat(workingdir.exists(), is(false));
build(WILL_PASS, pipelineName, false, false);
assertThat(console.output(), not(containsString("Working directory \"" + workingdir.getAbsolutePath() + "\" is not a directory")));
assertThat(statusReporter.results().contains(Passed), is(true));
assertThat(workingdir.exists(), is(true));
}
@Test
public void shouldCleanAgentWorkingDirectoryIfExistsWhenCleanWorkingDirIsTrue() throws Exception {
String pipelineName = "p1";
File workingdir = new File(sandbox, "pipelines/" + pipelineName);
workingdir.mkdirs();
new File(workingdir, "foo").createNewFile();
new File(workingdir, "bar").mkdirs();
assertThat(workingdir.listFiles().length, is(2));
build(WILL_PASS, pipelineName, false, true);
assertThat(statusReporter.results().contains(Passed), is(true));
assertThat(workingdir.exists(), is(true));
assertThat(workingdir.listFiles().length, is(0));
}
@Test
public void shouldReportAgentLocation() throws Exception {
buildVariables.put("agent.location", "far/far/away");
build(WILL_PASS, PIPELINE_NAME, true, false);
assertThat(console.output(), containsString("[far/far/away]"));
}
@Test
public void shouldReportEnvironmentVariables() throws Exception {
build(WITH_ENV_VAR, PIPELINE_NAME, true, false);
assertThat(console.output(), matches("'GO_SERVER_URL' (to|with) value '" + SERVER_URL));
assertThat(console.output(), matches("'GO_PIPELINE_LABEL' (to|with) value '" + PIPELINE_LABEL));
assertThat(console.output(), matches("'GO_PIPELINE_NAME' (to|with) value '" + PIPELINE_NAME));
assertThat(console.output(), matches("'GO_STAGE_NAME' (to|with) value '" + STAGE_NAME));
assertThat(console.output(), matches("'GO_STAGE_COUNTER' (to|with) value '" + STAGE_COUNTER));
assertThat(console.output(), matches("'GO_JOB_NAME' (to|with) value '" + JOB_PLAN_NAME));
assertThat(console.output(), containsString("[go] setting environment variable 'JOB_ENV' to value 'foobar'"));
if (isWindows()) {
assertThat(console.output(), containsString("[go] overriding environment variable 'Path' with value '/tmp'"));
} else {
assertThat(console.output(), containsString("[go] overriding environment variable 'PATH' with value '/tmp'"));
}
}
@Test
public void shouldMaskSecretInEnvironmentVarialbeReport() throws Exception {
build(WITH_SECRET_ENV_VAR, PIPELINE_NAME, true, false);
assertThat(console.output(), containsString("[go] setting environment variable 'foo' to value 'foo(******)'"));
assertThat(console.output(), containsString("[go] setting environment variable 'bar' to value '********'"));
assertThat(console.output(), not(containsString("i am a secret")));
}
@Test
public void shouldRunCancelTaskWhenBuildIsCanceled() throws Exception {
final Exception[] err = {null};
Thread buildThread = new Thread(new Runnable() {
@Override
public void run() {
try {
build(SystemUtil.isWindows() ? SLEEP_TEN_SECONDS_ON_WINDOWS: SLEEP_TEN_SECONDS_ON_UNIX,
PIPELINE_NAME, true, false);
} catch (Exception e) {
err[0] = e;
}
}
});
buildThread.start();
console.waitForContain("before sleep", Timeout.FIVE_SECONDS);
assertTrue(buildSession.cancel(30, TimeUnit.SECONDS));
assertThat(statusReporter.status(), is(Arrays.asList(Preparing, Building, Completed)));
assertThat(statusReporter.results(), is(Collections.singletonList(Cancelled)));
assertThat(console.output(), printedJobCompletedInfo(JOB_IDENTIFIER.buildLocatorForDisplay()));
assertThat(console.output(), printedJobCanceledInfo(JOB_IDENTIFIER.buildLocatorForDisplay()));
assertThat(console.output(), containsString("executing on cancel task"));
buildThread.join();
if (err[0] != null) {
throw err[0];
}
}
@Test
public void shouldReportUploadMessageWhenUpload() throws Exception {
String destFolder = "dest\\test\\sub-folder";
File basedir = new File(sandbox, "pipelines/pipeline1");
basedir.mkdirs();
File artifact = new File(basedir, "artifact");
artifact.createNewFile();
build(willUploadToDest("artifact", destFolder), PIPELINE_NAME, true, false);
assertThat("build should pass, console output is" + console.output(), getLast(statusReporter.results()), is(Passed));
assertThat(artifactsRepository.getFileUploaded().size(), is(1));
assertThat(artifactsRepository.getFileUploaded().get(0).file, is(artifact));
}
@Test
public void shouldFailTheJobWhenFailedToUploadArtifact() throws Exception {
artifactsRepository.setUploadError(new RuntimeException("upload failed"));
build(willUpload("cruise-output/log.xml"), PIPELINE_NAME, true, false);
assertThat(statusReporter.results(), containsResult(Failed));
}
@Test
public void generateReportForNUnit() throws Exception {
File basedir = new File(sandbox, "pipelines/pipeline1/test-reports");
basedir.mkdirs();
InputStream nunitResult = new ClassPathResource(FileUtil.fileseparator() + "data" + FileUtil.fileseparator() + "TestResult.xml").getInputStream();
FileOutputStream testArtifact = new FileOutputStream(new File(basedir, "test-result.xml"));
copyAndClose(nunitResult, testArtifact);
build(willUploadTestArtifact("test-reports", "test-report-dest"), PIPELINE_NAME, false, false);
assertThat(artifactsRepository.getFileUploaded().size(), Is.is(2));
assertThat(artifactsRepository.getFileUploaded().get(0).file, is(basedir));
assertThat(artifactsRepository.getFileUploaded().get(0).destPath, is("test-report-dest"));
assertThat(artifactsRepository.getFileUploaded().get(1).destPath, is("testoutput"));
assertThat(artifactsRepository.propertyValue(TestReportGenerator.TOTAL_TEST_COUNT), is("206"));
assertThat(artifactsRepository.propertyValue(TestReportGenerator.FAILED_TEST_COUNT), is("0"));
assertThat(artifactsRepository.propertyValue(TestReportGenerator.IGNORED_TEST_COUNT), is("0"));
assertThat(artifactsRepository.propertyValue(TestReportGenerator.TEST_TIME), is("NaN"));
}
@Test
public void generateBuildPropertyUsingXPath() throws Exception {
File basedir = new File(sandbox, "pipelines/pipeline1");
String content = "<artifacts>\n"
+ " <artifact src=\"target\\connectfour.jar\" dest=\"dist\\jars\" />\n"
+ " <artifact src=\"target\\test-results\" dest=\"testoutput\" type=\"junit\" />\n"
+ " <artifact src=\"build.xml\" />\n"
+ " </artifacts>\n";
File file = new File(basedir, "xmlfile");
FileUtils.writeStringToFile(file, content, "UTF-8");
build(willGenerateProperties("xmlfile", "artifactsrc", "//artifact/@src"), PIPELINE_NAME, false, false);
assertThat(buildInfo(), getLast(statusReporter.results()), is(Passed));
assertThat(artifactsRepository.propertyValue("artifactsrc"), is("target\\connectfour.jar"));
}
private static BuildAssignment getAssigment(String jobXml, String pipelineName, boolean fetchMaterials, boolean cleanWorkingDir) throws Exception {
CruiseConfig cruiseConfig = new MagicalGoConfigXmlLoader(new ConfigCache(), ConfigElementImplementationRegistryMother.withNoPlugins()).loadConfigHolder(FileUtil.readToEnd(IOUtils.toInputStream(ConfigFileFixture.withJob(jobXml, pipelineName)))).config;
JobConfig jobConfig = cruiseConfig.jobConfigByName(pipelineName, STAGE_NAME, JOB_PLAN_NAME, true);
JobPlan jobPlan = JobInstanceMother.createJobPlan(jobConfig, new JobIdentifier(pipelineName, -2, PIPELINE_LABEL, STAGE_NAME, String.valueOf(STAGE_COUNTER), JOB_PLAN_NAME, 0L),
new DefaultSchedulingContext());
jobPlan.setFetchMaterials(fetchMaterials);
jobPlan.setCleanWorkingDir(cleanWorkingDir);
final Stage stage = StageMother.custom(STAGE_NAME, new JobInstance(JOB_PLAN_NAME));
BuildCause buildCause = BuildCause.createWithEmptyModifications();
final Pipeline pipeline = new Pipeline(pipelineName, buildCause, stage);
pipeline.setLabel(PIPELINE_LABEL);
List<Builder> builder = builderFactory.buildersForTasks(pipeline, jobConfig.getTasks(), resolver);
return BuildAssignment.create(jobPlan,
BuildCause.createWithEmptyModifications(),
builder, pipeline.defaultWorkingFolder()
);
}
}