/*
* The MIT License
*
* Copyright (c) 2014 IKEDA Yasuyuki
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.plugins.copyartifact;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import java.io.IOException;
import java.util.Arrays;
import java.io.File;
import org.apache.commons.io.FileUtils;
import hudson.Util;
import hudson.maven.MavenModuleSet;
import hudson.model.Cause;
import hudson.model.FreeStyleProject;
import hudson.model.ParameterDefinition;
import hudson.model.ParametersAction;
import hudson.model.StringParameterValue;
import hudson.model.FreeStyleBuild;
import hudson.model.ParametersDefinitionProperty;
import hudson.model.Result;
import hudson.model.StringParameterDefinition;
import hudson.plugins.copyartifact.testutils.CopyArtifactUtil;
import hudson.plugins.copyartifact.testutils.FileWriteBuilder;
import hudson.plugins.copyartifact.testutils.RemoveUpstreamBuilder;
import hudson.tasks.ArtifactArchiver;
import hudson.tasks.BuildTrigger;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.ExtractResourceSCM;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.JenkinsRule.WebClient;
import org.jvnet.hudson.test.SleepBuilder;
import org.jvnet.hudson.test.ToolInstallations;
/**
* Tests for {@link TriggeredBuildSelector}.
* Some of tests of {@link TriggeredBuildSelector} are also in {@link CopyArtifactTest}
*/
public class TriggeredBuildSelectorTest {
@Rule
public JenkinsRule j = new JenkinsRule();
/**
* Tests that web configuration page works correct.
* @throws Exception
*/
@Test
public void testWebConfiguration() throws Exception {
WebClient wc = j.createWebClient();
{
FreeStyleProject p = j.createFreeStyleProject();
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
"${upstream}",
"",
new TriggeredBuildSelector(true, TriggeredBuildSelector.UpstreamFilterStrategy.UseOldest, false),
"",
"",
false,
false,
false
));
p.save();
j.submit(wc.getPage(p, "configure").getFormByName("config"));
p = j.jenkins.getItemByFullName(p.getFullName(), FreeStyleProject.class);
assertNotNull(p);
CopyArtifact copyArtifact = p.getBuildersList().get(CopyArtifact.class);
assertNotNull(p);
assertNotNull(copyArtifact.getBuildSelector());
assertEquals(TriggeredBuildSelector.class, copyArtifact.getBuildSelector().getClass());
TriggeredBuildSelector selector = (TriggeredBuildSelector)copyArtifact.getBuildSelector();
assertTrue(selector.isFallbackToLastSuccessful());
assertEquals(TriggeredBuildSelector.UpstreamFilterStrategy.UseOldest, selector.getUpstreamFilterStrategy());
}
{
FreeStyleProject p = j.createFreeStyleProject();
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
"${upstream}",
"",
new TriggeredBuildSelector(false, TriggeredBuildSelector.UpstreamFilterStrategy.UseNewest, false),
"",
"",
false,
false,
false
));
p.save();
j.submit(wc.getPage(p, "configure").getFormByName("config"));
p = j.jenkins.getItemByFullName(p.getFullName(), FreeStyleProject.class);
assertNotNull(p);
CopyArtifact copyArtifact = p.getBuildersList().get(CopyArtifact.class);
assertNotNull(p);
assertNotNull(copyArtifact.getBuildSelector());
assertEquals(TriggeredBuildSelector.class, copyArtifact.getBuildSelector().getClass());
TriggeredBuildSelector selector = (TriggeredBuildSelector)copyArtifact.getBuildSelector();
assertFalse(selector.isFallbackToLastSuccessful());
assertEquals(TriggeredBuildSelector.UpstreamFilterStrategy.UseNewest, selector.getUpstreamFilterStrategy());
}
{
FreeStyleProject p = j.createFreeStyleProject();
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
"${upstream}",
"",
new TriggeredBuildSelector(true, TriggeredBuildSelector.UpstreamFilterStrategy.UseGlobalSetting, false),
"",
"",
false,
false,
false
));
p.save();
j.submit(wc.getPage(p, "configure").getFormByName("config"));
p = j.jenkins.getItemByFullName(p.getFullName(), FreeStyleProject.class);
assertNotNull(p);
CopyArtifact copyArtifact = p.getBuildersList().get(CopyArtifact.class);
assertNotNull(p);
assertNotNull(copyArtifact.getBuildSelector());
assertEquals(TriggeredBuildSelector.class, copyArtifact.getBuildSelector().getClass());
TriggeredBuildSelector selector = (TriggeredBuildSelector)copyArtifact.getBuildSelector();
assertTrue(selector.isFallbackToLastSuccessful());
assertEquals(TriggeredBuildSelector.UpstreamFilterStrategy.UseGlobalSetting, selector.getUpstreamFilterStrategy());
}
}
@Test
public void testGlobalConfiguration() throws Exception {
WebClient wc = j.createWebClient();
TriggeredBuildSelector.DescriptorImpl d = (TriggeredBuildSelector.DescriptorImpl)j.jenkins.getDescriptorOrDie(TriggeredBuildSelector.class);
{
d.setGlobalUpstreamFilterStrategy(TriggeredBuildSelector.UpstreamFilterStrategy.UseNewest);
j.submit(wc.getPage(j.jenkins, "configure").getFormByName("config"));
assertEquals(TriggeredBuildSelector.UpstreamFilterStrategy.UseNewest, d.getGlobalUpstreamFilterStrategy());
}
{
d.setGlobalUpstreamFilterStrategy(TriggeredBuildSelector.UpstreamFilterStrategy.UseOldest);
j.submit(wc.getPage(j.jenkins, "configure").getFormByName("config"));
assertEquals(TriggeredBuildSelector.UpstreamFilterStrategy.UseOldest, d.getGlobalUpstreamFilterStrategy());
}
}
@Test
public void testUseOldest() throws Exception {
FreeStyleProject upstream = j.createFreeStyleProject();
ParameterDefinition paramDef = new StringParameterDefinition("CONTENT", "foo");
ParametersDefinitionProperty paramsDef = new ParametersDefinitionProperty(paramDef);
upstream.addProperty(paramsDef);
FreeStyleProject downstream = j.createFreeStyleProject();
upstream.getBuildersList().add(new FileWriteBuilder("artifact.txt", "${CONTENT}"));
upstream.getPublishersList().add(new ArtifactArchiver("artifact.txt", "", false, false));
upstream.getPublishersList().add(new BuildTrigger(downstream.getName(), Result.SUCCESS));
downstream.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
upstream.getName(),
"",
new TriggeredBuildSelector(false, TriggeredBuildSelector.UpstreamFilterStrategy.UseOldest, false),
"artifact.txt",
"",
false,
false,
true
));
downstream.setQuietPeriod(5); // this allows upstream trigger can be merged.
upstream.save();
downstream.save();
j.jenkins.rebuildDependencyGraph();
// 3 upstream builds.
j.assertBuildStatusSuccess(upstream.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(new StringParameterValue("CONTENT", "value1"))));
j.assertBuildStatusSuccess(upstream.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(new StringParameterValue("CONTENT", "value2"))));
j.assertBuildStatusSuccess(upstream.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(new StringParameterValue("CONTENT", "value3"))));
// wait till downstream will be triggered and completed
j.waitUntilNoActivity();
FreeStyleBuild b = downstream.getLastBuild();
assertNotNull(b);
j.assertBuildStatusSuccess(b);
assertEquals(
String.format("upstream triggers seem not to be merged into one downstream build. This means quietPeriod of downstream is too short in this environment: %s", b.getCauses()),
3,
Util.filter(b.getCauses(), Cause.UpstreamCause.class).size()
);
assertEquals("value1", b.getWorkspace().child("artifact.txt").readToString());
}
@Test
public void testUseOldestByGlobalSetting() throws Exception {
TriggeredBuildSelector.DescriptorImpl d = (TriggeredBuildSelector.DescriptorImpl)j.jenkins.getDescriptorOrDie(TriggeredBuildSelector.class);
d.setGlobalUpstreamFilterStrategy(TriggeredBuildSelector.UpstreamFilterStrategy.UseOldest);
FreeStyleProject upstream = j.createFreeStyleProject();
ParameterDefinition paramDef = new StringParameterDefinition("CONTENT", "foo");
ParametersDefinitionProperty paramsDef = new ParametersDefinitionProperty(paramDef);
upstream.addProperty(paramsDef);
FreeStyleProject downstream = j.createFreeStyleProject();
upstream.getBuildersList().add(new FileWriteBuilder("artifact.txt", "${CONTENT}"));
upstream.getPublishersList().add(new ArtifactArchiver("artifact.txt", "", false, false));
upstream.getPublishersList().add(new BuildTrigger(downstream.getName(), Result.SUCCESS));
downstream.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
upstream.getName(),
"",
new TriggeredBuildSelector(false, TriggeredBuildSelector.UpstreamFilterStrategy.UseGlobalSetting, false),
"artifact.txt",
"",
false,
false,
true
));
downstream.setQuietPeriod(5); // this allows upstream trigger can be merged.
upstream.save();
downstream.save();
j.jenkins.rebuildDependencyGraph();
// 3 upstream builds.
j.assertBuildStatusSuccess(upstream.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(new StringParameterValue("CONTENT", "value1"))));
j.assertBuildStatusSuccess(upstream.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(new StringParameterValue("CONTENT", "value2"))));
j.assertBuildStatusSuccess(upstream.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(new StringParameterValue("CONTENT", "value3"))));
// wait till downstream will be triggered and completed
j.waitUntilNoActivity();
FreeStyleBuild b = downstream.getLastBuild();
assertNotNull(b);
j.assertBuildStatusSuccess(b);
assertEquals(
String.format("upstream triggers seem not to be merged into one downstream build. This means quietPeriod of downstream is too short in this environment: %s", b.getCauses()),
3,
Util.filter(b.getCauses(), Cause.UpstreamCause.class).size()
);
assertEquals("value1", b.getWorkspace().child("artifact.txt").readToString());
}
@Test
public void testUseNewest() throws Exception {
FreeStyleProject upstream = j.createFreeStyleProject();
ParameterDefinition paramDef = new StringParameterDefinition("CONTENT", "foo");
ParametersDefinitionProperty paramsDef = new ParametersDefinitionProperty(paramDef);
upstream.addProperty(paramsDef);
FreeStyleProject downstream = j.createFreeStyleProject();
upstream.getBuildersList().add(new FileWriteBuilder("artifact.txt", "${CONTENT}"));
upstream.getPublishersList().add(new ArtifactArchiver("artifact.txt", "", false, false));
upstream.getPublishersList().add(new BuildTrigger(downstream.getName(), Result.SUCCESS));
downstream.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
upstream.getName(),
"",
new TriggeredBuildSelector(false, TriggeredBuildSelector.UpstreamFilterStrategy.UseNewest, false),
"artifact.txt",
"",
false,
false,
true
));
downstream.setQuietPeriod(5); // this allows upstream trigger can be merged.
upstream.save();
downstream.save();
j.jenkins.rebuildDependencyGraph();
// 3 upstream builds.
j.assertBuildStatusSuccess(upstream.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(new StringParameterValue("CONTENT", "value1"))));
j.assertBuildStatusSuccess(upstream.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(new StringParameterValue("CONTENT", "value2"))));
j.assertBuildStatusSuccess(upstream.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(new StringParameterValue("CONTENT", "value3"))));
// wait till downstream will be triggered and completed
j.waitUntilNoActivity();
FreeStyleBuild b = downstream.getLastBuild();
assertNotNull(b);
j.assertBuildStatusSuccess(b);
assertEquals(
String.format("upstream triggers seem not to be merged into one downstream build. This means quietPeriod of downstream is too short in this environment: %s", b.getCauses()),
3,
Util.filter(b.getCauses(), Cause.UpstreamCause.class).size()
);
assertEquals("value3", b.getWorkspace().child("artifact.txt").readToString());
}
@Test
public void testUseNewestByGlobalSetting() throws Exception {
TriggeredBuildSelector.DescriptorImpl d = (TriggeredBuildSelector.DescriptorImpl)j.jenkins.getDescriptorOrDie(TriggeredBuildSelector.class);
d.setGlobalUpstreamFilterStrategy(TriggeredBuildSelector.UpstreamFilterStrategy.UseNewest);
FreeStyleProject upstream = j.createFreeStyleProject();
ParameterDefinition paramDef = new StringParameterDefinition("CONTENT", "foo");
ParametersDefinitionProperty paramsDef = new ParametersDefinitionProperty(paramDef);
upstream.addProperty(paramsDef);
FreeStyleProject downstream = j.createFreeStyleProject();
upstream.getBuildersList().add(new FileWriteBuilder("artifact.txt", "${CONTENT}"));
upstream.getPublishersList().add(new ArtifactArchiver("artifact.txt", "", false, false));
upstream.getPublishersList().add(new BuildTrigger(downstream.getName(), Result.SUCCESS));
downstream.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
upstream.getName(),
"",
new TriggeredBuildSelector(false, TriggeredBuildSelector.UpstreamFilterStrategy.UseGlobalSetting, false),
"artifact.txt",
"",
false,
false,
true
));
downstream.setQuietPeriod(5); // this allows upstream trigger can be merged.
upstream.save();
downstream.save();
j.jenkins.rebuildDependencyGraph();
// 3 upstream builds.
j.assertBuildStatusSuccess(upstream.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(new StringParameterValue("CONTENT", "value1"))));
j.assertBuildStatusSuccess(upstream.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(new StringParameterValue("CONTENT", "value2"))));
j.assertBuildStatusSuccess(upstream.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(new StringParameterValue("CONTENT", "value3"))));
// wait till downstream will be triggered and completed
j.waitUntilNoActivity();
FreeStyleBuild b = downstream.getLastBuild();
assertNotNull(b);
j.assertBuildStatusSuccess(b);
assertEquals(
String.format("upstream triggers seem not to be merged into one downstream build. This means quietPeriod of downstream is too short in this environment: %s", b.getCauses()),
3,
Util.filter(b.getCauses(), Cause.UpstreamCause.class).size()
);
assertEquals("value3", b.getWorkspace().child("artifact.txt").readToString());
}
@Test
public void testUseOldestNested() throws Exception {
FreeStyleProject upstream = j.createFreeStyleProject();
ParameterDefinition paramDef = new StringParameterDefinition("CONTENT", "foo");
ParametersDefinitionProperty paramsDef = new ParametersDefinitionProperty(paramDef);
upstream.addProperty(paramsDef);
FreeStyleProject intermediate1 = j.createFreeStyleProject();
FreeStyleProject intermediate2 = j.createFreeStyleProject();
FreeStyleProject downstream = j.createFreeStyleProject();
upstream.getBuildersList().add(new FileWriteBuilder("artifact.txt", "${CONTENT}"));
intermediate1.getPublishersList().add(new BuildTrigger(downstream.getName(), Result.SUCCESS));
intermediate1.setQuietPeriod(5);
upstream.getPublishersList().add(new BuildTrigger(downstream.getName(), Result.SUCCESS));
intermediate2.getPublishersList().add(new BuildTrigger(downstream.getName(), Result.SUCCESS));
intermediate2.setQuietPeriod(5);
upstream.getPublishersList().add(new BuildTrigger(downstream.getName(), Result.SUCCESS));
intermediate1.getPublishersList().add(new BuildTrigger(downstream.getName(), Result.SUCCESS));
downstream.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
upstream.getName(),
"",
new TriggeredBuildSelector(false, TriggeredBuildSelector.UpstreamFilterStrategy.UseOldest, false),
"artifact.txt",
"",
false,
false,
true
));
downstream.setQuietPeriod(5); // this allows upstream trigger can be merged.
upstream.save();
intermediate1.save();
intermediate2.save();
downstream.save();
j.jenkins.rebuildDependencyGraph();
// 2 upstream builds for intermediate1.
upstream.getPublishersList().clear();
upstream.getPublishersList().add(new ArtifactArchiver("artifact.txt", "", false, false));
upstream.getPublishersList().add(new BuildTrigger(intermediate1.getName(), Result.SUCCESS));
upstream.save();
j.jenkins.rebuildDependencyGraph();
j.assertBuildStatusSuccess(upstream.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(new StringParameterValue("CONTENT", "value1"))));
j.assertBuildStatusSuccess(upstream.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(new StringParameterValue("CONTENT", "value2"))));
// 2 upstream builds for intermediate2.
upstream.getPublishersList().clear();
upstream.getPublishersList().add(new ArtifactArchiver("artifact.txt", "", false, false));
upstream.getPublishersList().add(new BuildTrigger(intermediate2.getName(), Result.SUCCESS));
upstream.save();
j.jenkins.rebuildDependencyGraph();
j.assertBuildStatusSuccess(upstream.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(new StringParameterValue("CONTENT", "value3"))));
j.assertBuildStatusSuccess(upstream.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(new StringParameterValue("CONTENT", "value4"))));
// wait till downstream will be triggered and completed
j.waitUntilNoActivity();
assertNotNull(intermediate1.getLastBuild());
j.assertBuildStatusSuccess(intermediate1.getLastBuild());
assertEquals(
String.format("upstream triggers seem not to be merged into one downstream build. This means quietPeriod of intermediate1 is too short in this environment: %s", intermediate1.getLastBuild().getCauses()),
2,
Util.filter(intermediate1.getLastBuild().getCauses(), Cause.UpstreamCause.class).size()
);
assertNotNull(intermediate2.getLastBuild());
j.assertBuildStatusSuccess(intermediate2.getLastBuild());
assertEquals(
String.format("upstream triggers seem not to be merged into one downstream build. This means quietPeriod of intermediate2 is too short in this environment: %s", intermediate2.getLastBuild().getCauses()),
2,
Util.filter(intermediate2.getLastBuild().getCauses(), Cause.UpstreamCause.class).size()
);
FreeStyleBuild b = downstream.getLastBuild();
assertNotNull(b);
j.assertBuildStatusSuccess(b);
assertEquals(
String.format("upstream triggers seem not to be merged into one downstream build. This means quietPeriod of downstream is too short in this environment: %s", b.getCauses()),
2,
Util.filter(b.getCauses(), Cause.UpstreamCause.class).size()
);
assertEquals("value1", b.getWorkspace().child("artifact.txt").readToString());
}
@Test
public void testUseNewestNested() throws Exception {
FreeStyleProject upstream = j.createFreeStyleProject();
ParameterDefinition paramDef = new StringParameterDefinition("CONTENT", "foo");
ParametersDefinitionProperty paramsDef = new ParametersDefinitionProperty(paramDef);
upstream.addProperty(paramsDef);
FreeStyleProject intermediate1 = j.createFreeStyleProject();
FreeStyleProject intermediate2 = j.createFreeStyleProject();
FreeStyleProject downstream = j.createFreeStyleProject();
upstream.getBuildersList().add(new FileWriteBuilder("artifact.txt", "${CONTENT}"));
intermediate1.getPublishersList().add(new BuildTrigger(downstream.getName(), Result.SUCCESS));
intermediate1.setQuietPeriod(5);
upstream.getPublishersList().add(new BuildTrigger(downstream.getName(), Result.SUCCESS));
intermediate2.getPublishersList().add(new BuildTrigger(downstream.getName(), Result.SUCCESS));
intermediate2.setQuietPeriod(5);
upstream.getPublishersList().add(new BuildTrigger(downstream.getName(), Result.SUCCESS));
intermediate1.getPublishersList().add(new BuildTrigger(downstream.getName(), Result.SUCCESS));
downstream.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
upstream.getName(),
"",
new TriggeredBuildSelector(false, TriggeredBuildSelector.UpstreamFilterStrategy.UseNewest, false),
"artifact.txt",
"",
false,
false,
true
));
downstream.setQuietPeriod(5); // this allows upstream trigger can be merged.
upstream.save();
intermediate1.save();
intermediate2.save();
downstream.save();
j.jenkins.rebuildDependencyGraph();
// 2 upstream builds for intermediate1.
upstream.getPublishersList().clear();
upstream.getPublishersList().add(new ArtifactArchiver("artifact.txt", "", false, false));
upstream.getPublishersList().add(new BuildTrigger(intermediate1.getName(), Result.SUCCESS));
upstream.save();
j.jenkins.rebuildDependencyGraph();
j.assertBuildStatusSuccess(upstream.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(new StringParameterValue("CONTENT", "value1"))));
j.assertBuildStatusSuccess(upstream.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(new StringParameterValue("CONTENT", "value2"))));
// 2 upstream builds for intermediate2.
upstream.getPublishersList().clear();
upstream.getPublishersList().add(new ArtifactArchiver("artifact.txt", "", false, false));
upstream.getPublishersList().add(new BuildTrigger(intermediate2.getName(), Result.SUCCESS));
upstream.save();
j.jenkins.rebuildDependencyGraph();
j.assertBuildStatusSuccess(upstream.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(new StringParameterValue("CONTENT", "value3"))));
j.assertBuildStatusSuccess(upstream.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(new StringParameterValue("CONTENT", "value4"))));
// wait till downstream will be triggered and completed
j.waitUntilNoActivity();
assertNotNull(intermediate1.getLastBuild());
j.assertBuildStatusSuccess(intermediate1.getLastBuild());
assertEquals(
String.format("upstream triggers seem not to be merged into one downstream build. This means quietPeriod of intermediate1 is too short in this environment: %s", intermediate1.getLastBuild().getCauses()),
2,
Util.filter(intermediate1.getLastBuild().getCauses(), Cause.UpstreamCause.class).size()
);
assertNotNull(intermediate2.getLastBuild());
j.assertBuildStatusSuccess(intermediate2.getLastBuild());
assertEquals(
String.format("upstream triggers seem not to be merged into one downstream build. This means quietPeriod of intermediate2 is too short in this environment: %s", intermediate2.getLastBuild().getCauses()),
2,
Util.filter(intermediate2.getLastBuild().getCauses(), Cause.UpstreamCause.class).size()
);
FreeStyleBuild b = downstream.getLastBuild();
assertNotNull(b);
j.assertBuildStatusSuccess(b);
assertEquals(
String.format("upstream triggers seem not to be merged into one downstream build. This means quietPeriod of downstream is too short in this environment: %s", b.getCauses()),
2,
Util.filter(b.getCauses(), Cause.UpstreamCause.class).size()
);
assertEquals("value4", b.getWorkspace().child("artifact.txt").readToString());
}
@Test
public void testBackwardCompatibility() throws Exception {
TriggeredBuildSelector.DescriptorImpl d = (TriggeredBuildSelector.DescriptorImpl)j.jenkins.getDescriptorOrDie(TriggeredBuildSelector.class);
d.setGlobalUpstreamFilterStrategy(TriggeredBuildSelector.UpstreamFilterStrategy.UseOldest);
FreeStyleProject upstream = j.createFreeStyleProject();
ParameterDefinition paramDef = new StringParameterDefinition("CONTENT", "foo");
ParametersDefinitionProperty paramsDef = new ParametersDefinitionProperty(paramDef);
upstream.addProperty(paramsDef);
FreeStyleProject downstream = j.createFreeStyleProject();
upstream.getBuildersList().add(new FileWriteBuilder("artifact.txt", "${CONTENT}"));
upstream.getPublishersList().add(new ArtifactArchiver("artifact.txt", "", false, false));
upstream.getPublishersList().add(new BuildTrigger(downstream.getName(), Result.SUCCESS));
downstream.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
upstream.getName(),
"",
new TriggeredBuildSelector(false, null, false),
"artifact.txt",
"",
false,
false,
true
));
downstream.setQuietPeriod(5); // this allows upstream trigger can be merged.
upstream.save();
downstream.save();
j.jenkins.rebuildDependencyGraph();
// 3 upstream builds.
j.assertBuildStatusSuccess(upstream.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(new StringParameterValue("CONTENT", "value1"))));
j.assertBuildStatusSuccess(upstream.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(new StringParameterValue("CONTENT", "value2"))));
j.assertBuildStatusSuccess(upstream.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(new StringParameterValue("CONTENT", "value3"))));
// wait till downstream will be triggered and completed
j.waitUntilNoActivity();
FreeStyleBuild b = downstream.getLastBuild();
assertNotNull(b);
j.assertBuildStatusSuccess(b);
assertEquals(
String.format("upstream triggers seem not to be merged into one downstream build. This means quietPeriod of downstream is too short in this environment: %s", b.getCauses()),
3,
Util.filter(b.getCauses(), Cause.UpstreamCause.class).size()
);
assertEquals("value1", b.getWorkspace().child("artifact.txt").readToString());
}
@Test
public void testIsUseNewest() throws Exception {
// |Descriptor |BuildSelector |Result|
// |:---------------|:---------------|:-----|
// |null |null |false |
// |UseGlobalSetting|UseGlobalSetting|false |
// |UseOldest |UseGlobalSetting|false |
// |UseNewest |UseGlobalSetting|true |
// |UseOldest |UseNewest |true |
// |UseNewest |UseOldest |false |
TriggeredBuildSelector.DescriptorImpl d = (TriggeredBuildSelector.DescriptorImpl)j.jenkins.getDescriptorOrDie(TriggeredBuildSelector.class);
d.setGlobalUpstreamFilterStrategy(null);
assertFalse(new TriggeredBuildSelector(false, null, false).isUseNewest());
d.setGlobalUpstreamFilterStrategy(TriggeredBuildSelector.UpstreamFilterStrategy.UseGlobalSetting);
assertFalse(new TriggeredBuildSelector(false, TriggeredBuildSelector.UpstreamFilterStrategy.UseGlobalSetting, false).isUseNewest());
d.setGlobalUpstreamFilterStrategy(TriggeredBuildSelector.UpstreamFilterStrategy.UseOldest);
assertFalse(new TriggeredBuildSelector(false, TriggeredBuildSelector.UpstreamFilterStrategy.UseGlobalSetting, false).isUseNewest());
d.setGlobalUpstreamFilterStrategy(TriggeredBuildSelector.UpstreamFilterStrategy.UseNewest);
assertTrue(new TriggeredBuildSelector(false, TriggeredBuildSelector.UpstreamFilterStrategy.UseGlobalSetting, false).isUseNewest());
d.setGlobalUpstreamFilterStrategy(TriggeredBuildSelector.UpstreamFilterStrategy.UseOldest);
assertTrue(new TriggeredBuildSelector(false, TriggeredBuildSelector.UpstreamFilterStrategy.UseNewest, false).isUseNewest());
d.setGlobalUpstreamFilterStrategy(TriggeredBuildSelector.UpstreamFilterStrategy.UseNewest);
assertFalse(new TriggeredBuildSelector(false, TriggeredBuildSelector.UpstreamFilterStrategy.UseOldest, false).isUseNewest());
}
private String getDownstreamAfterOverlappingFlow(boolean allowUpstreamDependencies) throws Exception {
//
// upstream | intermediate | downstream
//
// Initital build
// 1 #1 -------.
// 2 '-----> #1 ---------.
// 3 '-----> #1
//
// Direct trigger of intermediate, then upstream
// 4 *---> #2 -------.
// 5 #2 -----. |
// 6 | '-------> #2
// 7 '-------> #3 -----.
// 8 '---------> #3
//
FreeStyleProject upstream = j.createFreeStyleProject("upstream");
ParameterDefinition paramDef = new StringParameterDefinition("CONTENT", "foo");
ParametersDefinitionProperty paramsDef = new ParametersDefinitionProperty(paramDef);
upstream.addProperty(paramsDef);
FreeStyleProject intermediate = j.createFreeStyleProject("intermediate");
FreeStyleProject downstream = j.createFreeStyleProject("downstream");
upstream.getBuildersList().add(new FileWriteBuilder("artifact.txt", "${CONTENT}"));
upstream.getPublishersList().add(new ArtifactArchiver("artifact.txt", "", false, false));
upstream.getPublishersList().add(new BuildTrigger(intermediate.getName(), Result.SUCCESS));
upstream.setQuietPeriod(0);
intermediate.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
upstream.getName(),
"",
new TriggeredBuildSelector(true, TriggeredBuildSelector.UpstreamFilterStrategy.UseGlobalSetting, allowUpstreamDependencies),
"artifact.txt",
"",
false,
false,
true
));
intermediate.getBuildersList().add(new SleepBuilder(1000));
intermediate.getPublishersList().add(new ArtifactArchiver("artifact.txt", "", false, false));
intermediate.getPublishersList().add(new BuildTrigger(downstream.getName(), Result.SUCCESS));
intermediate.setQuietPeriod(0);
downstream.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
upstream.getName(),
"",
new TriggeredBuildSelector(true, TriggeredBuildSelector.UpstreamFilterStrategy.UseGlobalSetting, allowUpstreamDependencies),
"artifact.txt",
"upstream/",
false,
false,
true
));
downstream.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
intermediate.getName(),
"",
new TriggeredBuildSelector(true, TriggeredBuildSelector.UpstreamFilterStrategy.UseGlobalSetting, allowUpstreamDependencies),
"artifact.txt",
"intermediate/",
false,
false,
true
));
downstream.getPublishersList().add(new ArtifactArchiver("upstream/artifact.txt,intermediate/artifact.txt", "", false, false));
downstream.setQuietPeriod(0);
upstream.save();
intermediate.save();
downstream.save();
j.jenkins.rebuildDependencyGraph();
// First (initial) build for each job
j.assertBuildStatusSuccess(upstream.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(new StringParameterValue("CONTENT", "upstreamValue1"))));
j.waitUntilNoActivity();
// Trigger directly an 'intermediate#2' build, which depends on 'upstream#1'
intermediate.scheduleBuild2(0, new Cause.UserCause()).waitForStart();
// 'intermediate#2' build is running. Meanwhile, a new 'upstream#2' is completing and triggers 'intermediate#3':
upstream.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(new StringParameterValue("CONTENT", "upstreamValue2")));
j.waitUntilNoActivity();
assertEquals("Number of upstream builds", 2, upstream.getBuilds().size());
assertEquals("Number of intermediate builds", 3, intermediate.getBuilds().size());
assertEquals("Number of downstream builds", 3, downstream.getBuilds().size());
// Get the 'downstream#2' build ...
FreeStyleBuild downstreamBuild2 = downstream.getBuildByNumber(2);
assertNotNull(downstreamBuild2);
j.assertBuildStatusSuccess(downstreamBuild2);
// ... that were triggered by the directly triggered 'intermediate#2' build.
Cause.UpstreamCause cause = downstreamBuild2.getCause(Cause.UpstreamCause.class);
assertNotNull(cause);
assertEquals("intermediate #2", cause.getUpstreamRun().getFullDisplayName());
// Return artifacts from downstream#2. One of them was copied from 'upstream' that is
// - either the last successful upstream#2 build
// - or upstream#1, which is the same that the triggering intermediate#2 depends on
// depending on the value of allowUpstreamDependencies
String artifactFromUpstream = FileUtils.readFileToString(new File(downstreamBuild2.getArtifactsDir(), "upstream/artifact.txt"), "UTF-8");
String artifactFromIntermediate = FileUtils.readFileToString(new File(downstreamBuild2.getArtifactsDir(), "intermediate/artifact.txt"), "UTF-8");
return artifactFromIntermediate + "," + artifactFromUpstream;
}
@Test
public void testTryUpstreamBuildDisabled() throws Exception {
assertEquals("upstreamValue1,upstreamValue2", getDownstreamAfterOverlappingFlow(false));
}
@Test
public void testTryUpstreamBuildEnabled() throws Exception {
assertEquals("upstreamValue1,upstreamValue1", getDownstreamAfterOverlappingFlow(true));
}
@Issue("JENKINS-18804")
@Test
public void testUpstreamWasRemoved() throws Exception {
// upstream -> downstream
// Remove the build of upstream.
{
FreeStyleProject upstream = j.createFreeStyleProject();
FreeStyleProject downstream = j.createFreeStyleProject();
upstream.getBuildersList().add(new FileWriteBuilder(
"artifact.txt",
"foobar"
));
upstream.getPublishersList().add(new ArtifactArchiver(
"**/*",
"",
false,
false
));
upstream.getPublishersList().add(new BuildTrigger(
downstream.getFullName(),
false
));
downstream.getBuildersList().add(new RemoveUpstreamBuilder());
downstream.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
upstream.getFullName(),
"",
new TriggeredBuildSelector(false, TriggeredBuildSelector.UpstreamFilterStrategy.UseGlobalSetting, false),
"**/*",
"",
"",
false,
true, // This results build succeed even if the upstream build has been removed.
false
));
j.jenkins.rebuildDependencyGraph();
upstream.scheduleBuild2(0);
j.waitUntilNoActivity();
assertNull(upstream.getLastBuild());
j.assertBuildStatusSuccess(downstream.getLastBuild());
}
// upstream -> intermediate -> downstream
// Remove the build of upstream.
{
FreeStyleProject upstream = j.createFreeStyleProject();
FreeStyleProject intermediate = j.createFreeStyleProject();
FreeStyleProject downstream = j.createFreeStyleProject();
upstream.getBuildersList().add(new FileWriteBuilder(
"artifact.txt",
"foobar"
));
upstream.getPublishersList().add(new ArtifactArchiver(
"**/*",
"",
false,
false
));
upstream.getPublishersList().add(new BuildTrigger(
intermediate.getFullName(),
false
));
intermediate.getBuildersList().add(new RemoveUpstreamBuilder());
intermediate.getPublishersList().add(new BuildTrigger(
downstream.getFullName(),
false
));
downstream.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
upstream.getFullName(),
"",
new TriggeredBuildSelector(false, TriggeredBuildSelector.UpstreamFilterStrategy.UseGlobalSetting, false),
"**/*",
"",
"",
false,
true, // This results build succeed even if the upstream build has been removed.
false
));
j.jenkins.rebuildDependencyGraph();
upstream.scheduleBuild2(0);
j.waitUntilNoActivity();
assertNull(upstream.getLastBuild());
j.assertBuildStatusSuccess(intermediate.getLastBuild());
j.assertBuildStatusSuccess(downstream.getLastBuild());
}
// upstream -> intermediate -> downstream
// Remove the build of intermediate.
{
FreeStyleProject upstream = j.createFreeStyleProject();
FreeStyleProject intermediate = j.createFreeStyleProject();
FreeStyleProject downstream = j.createFreeStyleProject();
upstream.getBuildersList().add(new FileWriteBuilder(
"artifact.txt",
"foobar"
));
upstream.getPublishersList().add(new ArtifactArchiver(
"**/*",
"",
false,
false
));
upstream.getPublishersList().add(new BuildTrigger(
intermediate.getFullName(),
false
));
intermediate.getPublishersList().add(new BuildTrigger(
downstream.getFullName(),
false
));
downstream.getBuildersList().add(new RemoveUpstreamBuilder());
downstream.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
upstream.getFullName(),
"",
new TriggeredBuildSelector(false, TriggeredBuildSelector.UpstreamFilterStrategy.UseGlobalSetting, false),
"**/*",
"",
"",
false,
true, // This results build succeed even if the upstream build has been removed.
false
));
j.jenkins.rebuildDependencyGraph();
upstream.scheduleBuild2(0);
j.waitUntilNoActivity();
j.assertBuildStatusSuccess(upstream.getLastBuild());
assertNull(intermediate.getLastBuild());
j.assertBuildStatusSuccess(downstream.getLastBuild());
}
}
@Issue("JENKINS-14653")
@Test
public void testMavenModule() throws Exception {
ToolInstallations.configureDefaultMaven();
MavenModuleSet upstream = createMavenProject();
FreeStyleProject downstream = j.createFreeStyleProject();
upstream.setGoals("clean package");
upstream.setScm(new ExtractResourceSCM(getClass().getResource("maven-job.zip")));
upstream.getPublishersList().add(new BuildTrigger(downstream.getName(), Result.SUCCESS));
downstream.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
String.format("%s/org.jvnet.hudson.main.test.multimod$moduleB", upstream.getName()),
"",
new TriggeredBuildSelector(false, null, false),
"**/*",
"",
"",
false,
false,
false
));
upstream.save();
downstream.save();
j.jenkins.rebuildDependencyGraph();
j.assertBuildStatusSuccess(upstream.scheduleBuild2(0));
j.waitUntilNoActivity();
FreeStyleBuild b = downstream.getLastBuild();
j.assertBuildStatusSuccess(b);
assertTrue(
String.format(
"File not found: files are: %s",
Arrays.asList(b.getWorkspace().list("**/*"))
),
b.getWorkspace().child("org.jvnet.hudson.main.test.multimod/moduleB/1.0-SNAPSHOT/moduleB-1.0-SNAPSHOT.jar").exists()
);
}
/**
* Creates an empty Maven project with an unique name.
*
* @return an empty Maven project with an unique name.
*/
private MavenModuleSet createMavenProject() throws IOException {
MavenModuleSet mavenModuleSet = j.jenkins.createProject(MavenModuleSet.class, "test"+j.jenkins.getItems().size());
mavenModuleSet.setRunHeadless(true);
return mavenModuleSet;
}
}