/*
* 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.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import hudson.model.AbstractProject;
import hudson.model.Cause;
import hudson.model.FreeStyleProject;
import hudson.model.FreeStyleBuild;
import hudson.model.Item;
import hudson.model.ParametersAction;
import hudson.model.ParametersDefinitionProperty;
import hudson.model.StringParameterDefinition;
import hudson.model.StringParameterValue;
import hudson.model.User;
import hudson.model.Result;
import hudson.plugins.copyartifact.testutils.CopyArtifactUtil;
import jenkins.model.Jenkins;
import hudson.FilePath;
import hudson.plugins.copyartifact.testutils.FileWriteBuilder;
import hudson.security.Permission;
import hudson.security.AuthorizationMatrixProperty;
import hudson.security.ProjectMatrixAuthorizationStrategy;
import hudson.tasks.ArtifactArchiver;
import hudson.tasks.BuildTrigger;
import hudson.tasks.Fingerprinter;
import hudson.util.FormValidation;
import org.acegisecurity.Authentication;
import org.acegisecurity.context.SecurityContextHolder;
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.MockFolder;
import com.google.common.collect.Sets;
/**
*
*/
public class DownstreamBuildSelectorTest {
@Rule
public JenkinsRule j = new JenkinsRule();
@Test
public void testConfiguration() throws Exception {
final String UPSTREAM_PROJECT_NAME = "${UPSTREAM_PROJECT_NAME}";
final String UPSTREAM_BUILD_NUMBER = "${UPSTREAM_BUILD_NUMBER}";
FreeStyleProject p = j.createFreeStyleProject();
p.getBuildersList().add(
CopyArtifactUtil.createCopyArtifact(
"${PROJECT}",
"",
new DownstreamBuildSelector(
UPSTREAM_PROJECT_NAME,
UPSTREAM_BUILD_NUMBER
),
"**/*",
"",
"",
false,
false,
true
)
);
p.save();
// Test that the configuration preserved when updated from the web page.
// This is helpful to find a bug in jelly files.
j.submit(j.createWebClient().getPage(p, "configure").getFormByName("config"));
p = j.jenkins.getItemByFullName(p.getFullName(), FreeStyleProject.class);
assertNotNull(p);
CopyArtifact ca = p.getBuildersList().get(CopyArtifact.class);
assertNotNull(ca);
assertEquals(DownstreamBuildSelector.class, ca.getBuildSelector().getClass());
DownstreamBuildSelector selector = (DownstreamBuildSelector)ca.getBuildSelector();
assertEquals(UPSTREAM_PROJECT_NAME, selector.getUpstreamProjectName());
assertEquals(UPSTREAM_BUILD_NUMBER, selector.getUpstreamBuildNumber());
}
@Test
public void testPerformSuccess() throws Exception {
FreeStyleProject upstream = j.createFreeStyleProject();
FreeStyleProject downstream = j.createFreeStyleProject();
upstream.getBuildersList().add(new FileWriteBuilder("artifact.txt", "${BUILD_TAG}"));
upstream.getPublishersList().add(new ArtifactArchiver(
"artifact.txt",
"",
false,
false
));
upstream.getPublishersList().add(new Fingerprinter("", true));
upstream.getPublishersList().add(new BuildTrigger(downstream.getFullName(), Result.SUCCESS.toString()));
downstream.getBuildersList().add(new FileWriteBuilder("artifact2.txt", "${BUILD_ID}"));
downstream.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
upstream.getFullName(),
"",
new TriggeredBuildSelector(
false,
TriggeredBuildSelector.UpstreamFilterStrategy.UseNewest,
false
),
"**/*",
"",
"",
false,
false,
true // important! required to have Jenkins track builds.
));
downstream.getPublishersList().add(new ArtifactArchiver(
"artifact2.txt",
"",
false,
false
));
upstream.save();
downstream.save();
j.jenkins.rebuildDependencyGraph();;
// upstreamBuild1 -> downstreamBuild1
// upstreamBuild2 -> downstreamBuild2
// upstreamBuild3 -> downstreamBuild3
FreeStyleBuild upstreamBuild1 = upstream.scheduleBuild2(0).get();
upstreamBuild1.setDisplayName("upstreamBuild1");
j.waitUntilNoActivity();
FreeStyleBuild downstreamBuild1 = downstream.getLastBuild();
assertEquals(upstreamBuild1, downstreamBuild1.getUpstreamRelationshipBuild(upstream));
j.assertBuildStatusSuccess(upstreamBuild1);
j.assertBuildStatusSuccess(downstreamBuild1);
FreeStyleBuild upstreamBuild2 = upstream.scheduleBuild2(0).get();
upstreamBuild2.setDisplayName("upstreamBuild2");
j.waitUntilNoActivity();
FreeStyleBuild downstreamBuild2 = downstream.getLastBuild();
assertEquals(upstreamBuild2, downstreamBuild2.getUpstreamRelationshipBuild(upstream));
j.assertBuildStatusSuccess(upstreamBuild2);
j.assertBuildStatusSuccess(downstreamBuild2);
FreeStyleBuild upstreamBuild3 = upstream.scheduleBuild2(0).get();
upstreamBuild3.setDisplayName("upstreamBuild3");
j.waitUntilNoActivity();
FreeStyleBuild downstreamBuild3 = downstream.getLastBuild();
assertEquals(upstreamBuild3, downstreamBuild3.getUpstreamRelationshipBuild(upstream));
j.assertBuildStatusSuccess(upstreamBuild3);
j.assertBuildStatusSuccess(downstreamBuild3);
// copies from downstream2, which is a downstream of upstreamBuild2.
// specify with a build number.
// not use variables.
{
FreeStyleProject p = j.createFreeStyleProject();
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
downstream.getFullName(),
"",
new DownstreamBuildSelector(
upstream.getFullName(),
Integer.toString(upstreamBuild2.getNumber())
),
"**/*",
"",
"",
false,
false,
true
));
FreeStyleBuild b = p.scheduleBuild2(0).get();
j.assertBuildStatusSuccess(b);
FilePath artifact = b.getWorkspace().child("artifact2.txt");
assertTrue(artifact.exists());
assertEquals(downstreamBuild2.getId(), artifact.readToString());
}
// copies from downstream1, which is a downstream of upstreamBuild1.
// specify with a build id.
// use variables.
{
FreeStyleProject p = j.createFreeStyleProject();
p.addProperty(new ParametersDefinitionProperty(
new StringParameterDefinition("UPSTREAM_PROJECT_NAME", ""),
new StringParameterDefinition("UPSTREAM_BUILD_NUMBER", "")
));
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
downstream.getFullName(),
"",
new DownstreamBuildSelector(
"${UPSTREAM_PROJECT_NAME}",
"${UPSTREAM_BUILD_NUMBER}"
),
"**/*",
"",
"",
false,
false,
true
));
FreeStyleBuild b = p.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(
new StringParameterValue("UPSTREAM_PROJECT_NAME", upstream.getFullName()),
new StringParameterValue("UPSTREAM_BUILD_NUMBER", upstreamBuild1.getId())
)).get();
j.assertBuildStatusSuccess(b);
FilePath artifact = b.getWorkspace().child("artifact2.txt");
assertTrue(artifact.exists());
assertEquals(downstreamBuild1.getId(), artifact.readToString());
}
// copies from downstream3, which is a downstream of upstreamBuild3.
// specify with a display name.
// use variables.
{
FreeStyleProject p = j.createFreeStyleProject();
p.addProperty(new ParametersDefinitionProperty(
new StringParameterDefinition("UPSTREAM_PROJECT_NAME", ""),
new StringParameterDefinition("UPSTREAM_BUILD_NUMBER", "")
));
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
downstream.getFullName(),
"",
new DownstreamBuildSelector(
"${UPSTREAM_PROJECT_NAME}",
"${UPSTREAM_BUILD_NUMBER}"
),
"**/*",
"",
"",
false,
false,
true
));
FreeStyleBuild b = p.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(
new StringParameterValue("UPSTREAM_PROJECT_NAME", upstream.getFullName()),
new StringParameterValue("UPSTREAM_BUILD_NUMBER", "upstreamBuild3")
)).get();
j.assertBuildStatusSuccess(b);
FilePath artifact = b.getWorkspace().child("artifact2.txt");
assertTrue(artifact.exists());
assertEquals(downstreamBuild3.getId(), artifact.readToString());
}
}
@Test
public void testPerformFailure() throws Exception {
FreeStyleProject upstream = j.createFreeStyleProject();
FreeStyleProject downstream = j.createFreeStyleProject();
upstream.getBuildersList().add(new FileWriteBuilder("artifact.txt", "${BUILD_TAG}"));
upstream.getPublishersList().add(new ArtifactArchiver(
"artifact.txt",
"",
false,
false
));
upstream.getPublishersList().add(new Fingerprinter("", true));
upstream.getPublishersList().add(new BuildTrigger(downstream.getFullName(), Result.SUCCESS.toString()));
downstream.getBuildersList().add(new FileWriteBuilder("artifact2.txt", "${BUILD_ID}"));
downstream.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
upstream.getFullName(),
"",
new TriggeredBuildSelector(
false,
TriggeredBuildSelector.UpstreamFilterStrategy.UseNewest,
false
),
"**/*",
"",
"",
false,
false,
true // important! required to have Jenkins track builds.
));
downstream.getPublishersList().add(new ArtifactArchiver(
"artifact2.txt",
"",
false,
false
));
upstream.save();
downstream.save();
j.jenkins.rebuildDependencyGraph();;
// upstreamBuild1 -> downstreamBuild1
// upstreamBuild2 -> (nothing)
FreeStyleBuild upstreamBuild1 = upstream.scheduleBuild2(0).get();
upstreamBuild1.setDisplayName("upstreamBuild1");
j.waitUntilNoActivity();
FreeStyleBuild downstreamBuild1 = downstream.getLastBuild();
assertEquals(upstreamBuild1, downstreamBuild1.getUpstreamRelationshipBuild(upstream));
j.assertBuildStatusSuccess(upstreamBuild1);
j.assertBuildStatusSuccess(downstreamBuild1);
FreeStyleBuild upstreamBuild2 = upstream.scheduleBuild2(0).get();
upstreamBuild2.setDisplayName("upstreamBuild2");
j.waitUntilNoActivity();
FreeStyleBuild downstreamBuild2 = downstream.getLastBuild();
assertEquals(upstreamBuild2, downstreamBuild2.getUpstreamRelationshipBuild(upstream));
j.assertBuildStatusSuccess(upstreamBuild2);
j.assertBuildStatusSuccess(downstreamBuild2);
downstreamBuild2.delete();
downstreamBuild2 = null;
FreeStyleProject p = j.createFreeStyleProject();
p.addProperty(new ParametersDefinitionProperty(
new StringParameterDefinition("UPSTREAM_PROJECT_NAME", ""),
new StringParameterDefinition("UPSTREAM_BUILD_NUMBER", "")
));
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
downstream.getFullName(),
"",
new DownstreamBuildSelector(
"${UPSTREAM_PROJECT_NAME}",
"${UPSTREAM_BUILD_NUMBER}"
),
"**/*",
"",
"",
false,
true,
// Look! As this is an optional, the build doesn't fail even if the build is not found.
// This allows us to find exceptions.
true
));
// upstreamProjectName is empty
{
FreeStyleBuild b = p.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(
new StringParameterValue("UPSTREAM_PROJECT_NAME", " "),
new StringParameterValue("UPSTREAM_BUILD_NUMBER", "2")
)).get();
j.assertBuildStatusSuccess(b);
assertEquals(Collections.emptyList(), b.getWorkspace().list());
}
// upstreamBuildNumber is empty
{
FreeStyleBuild b = p.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(
new StringParameterValue("UPSTREAM_PROJECT_NAME", upstream.getFullName()),
new StringParameterValue("UPSTREAM_BUILD_NUMBER", " ")
)).get();
j.assertBuildStatusSuccess(b);
assertEquals(Collections.emptyList(), b.getWorkspace().list());
}
// upstreamProjectName is invalid
{
FreeStyleBuild b = p.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(
new StringParameterValue("UPSTREAM_PROJECT_NAME", "Nosuchproject"),
new StringParameterValue("UPSTREAM_BUILD_NUMBER", "2")
)).get();
j.assertBuildStatusSuccess(b);
assertEquals(Collections.emptyList(), b.getWorkspace().list());
}
// upstreamBuildNumber is invalid
{
FreeStyleBuild b = p.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(
new StringParameterValue("UPSTREAM_PROJECT_NAME", upstream.getFullName()),
new StringParameterValue("UPSTREAM_BUILD_NUMBER", "NoSuchBuild")
)).get();
j.assertBuildStatusSuccess(b);
assertEquals(Collections.emptyList(), b.getWorkspace().list());
}
// No downstream
{
FreeStyleBuild b = p.scheduleBuild2(0, new Cause.UserCause(), new ParametersAction(
new StringParameterValue("UPSTREAM_PROJECT_NAME", upstream.getFullName()),
new StringParameterValue("UPSTREAM_BUILD_NUMBER", "upstreamBuild2")
)).get();
j.assertBuildStatusSuccess(b);
assertEquals(Collections.emptyList(), b.getWorkspace().list());
}
}
@Test
public void testPerformRelative() throws Exception {
// folder1/upstream -> folder2/downstream
// folder1/folder3/copier copies
// from folder2/downstream (../../folder2/downstream)
// which is a downstream of folder1/upstream (../upstream)
MockFolder folder1 = j.jenkins.createProject(MockFolder.class, "folder1");
MockFolder folder2 = j.jenkins.createProject(MockFolder.class, "folder2");
MockFolder folder3 = folder1.createProject(MockFolder.class, "folder3");
FreeStyleProject upstream = folder1.createProject(FreeStyleProject.class, "upstream");
FreeStyleProject downstream = folder2.createProject(FreeStyleProject.class, "downstream");
FreeStyleProject copier = folder3.createProject(FreeStyleProject.class, "copier");
upstream.getBuildersList().add(new FileWriteBuilder("artifact.txt", "${BUILD_TAG}"));
upstream.getPublishersList().add(new ArtifactArchiver(
"artifact.txt",
"",
false,
false
));
upstream.getPublishersList().add(new Fingerprinter("", true));
upstream.getPublishersList().add(new BuildTrigger("../folder2/downstream", Result.SUCCESS.toString()));
downstream.getBuildersList().add(new FileWriteBuilder("artifact2.txt", "${BUILD_ID}"));
downstream.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
"../folder1/upstream",
"",
new TriggeredBuildSelector(
false,
TriggeredBuildSelector.UpstreamFilterStrategy.UseNewest,
false
),
"**/*",
"",
"",
false,
false,
true // important! required to have Jenkins track builds.
));
downstream.getPublishersList().add(new ArtifactArchiver(
"artifact2.txt",
"",
false,
false
));
upstream.save();
downstream.save();
j.jenkins.rebuildDependencyGraph();
// upstreamBuild -> downstreamBuild
FreeStyleBuild upstreamBuild = upstream.scheduleBuild2(0).get();
j.waitUntilNoActivity();
FreeStyleBuild downstreamBuild = downstream.getLastBuild();
assertEquals(upstreamBuild, downstreamBuild.getUpstreamRelationshipBuild(upstream));
j.assertBuildStatusSuccess(upstreamBuild);
j.assertBuildStatusSuccess(downstreamBuild);
copier.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
"../../folder2/downstream",
"",
new DownstreamBuildSelector(
"../upstream",
Integer.toString(upstreamBuild.getNumber())
),
"**/*",
"",
"",
false,
false,
true
));
FreeStyleBuild b = copier.scheduleBuild2(0).get();
j.assertBuildStatusSuccess(b);
FilePath artifact = b.getWorkspace().child("artifact2.txt");
assertTrue(artifact.exists());
assertEquals(downstreamBuild.getId(), artifact.readToString());
}
@Test
public void testCheckUpstreamProjectName() throws Exception {
DownstreamBuildSelector.DescriptorImpl d = (DownstreamBuildSelector.DescriptorImpl)j.jenkins.getDescriptorOrDie(DownstreamBuildSelector.class);
ProjectMatrixAuthorizationStrategy pmas = new ProjectMatrixAuthorizationStrategy();
pmas.add(Jenkins.READ, "devel");
j.jenkins.setSecurityRealm(j.createDummySecurityRealm());
j.jenkins.setAuthorizationStrategy(pmas);
// project1
// folder1/project2
// folder1/project3 cannot read from devel
MockFolder folder1 = j.jenkins.createProject(MockFolder.class, "folder1");
FreeStyleProject project1 = j.createFreeStyleProject("project1");
{
Map<Permission, Set<String>> map = new HashMap<Permission, Set<String>>();
map.put(Item.READ, Sets.newHashSet("devel"));
project1.addProperty(new AuthorizationMatrixProperty(map));
}
FreeStyleProject project2 = folder1.createProject(FreeStyleProject.class, "project2");
{
Map<Permission, Set<String>> map = new HashMap<Permission, Set<String>>();
map.put(Item.READ, Sets.newHashSet("devel"));
project2.addProperty(new AuthorizationMatrixProperty(map));
}
FreeStyleProject project3 = folder1.createProject(FreeStyleProject.class, "project3");
assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamProjectName(project1, null).kind);
assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamProjectName(project1, "").kind);
assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamProjectName(project1, " ").kind);
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(project1, "$VAR").kind);
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(project1, "FOO${VAR}").kind);
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(project1, "Project\\$").kind); // limitation
assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamProjectName(project1, "nosuchproject").kind);
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(project1, "folder1/project2").kind);
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(project2, "../project1").kind);
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(project2, "project3").kind);
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(project2, "/folder1/project3").kind);
//JENKINS-32526: Check that it behaves gracefully for an unknown context
assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamProjectName(null, null).kind);
assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamProjectName(null, "").kind);
assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamProjectName(null, " ").kind);
//Ancestor null
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "nosuchproject").kind);
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "$VAR").kind);
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "FOO${VAR}").kind);
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "Project\\$").kind); // limitation
//Only relative path from Root works
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "folder1/project2").kind);
// permission check
Authentication a = Jenkins.getAuthentication();
try {
SecurityContextHolder.getContext().setAuthentication(User.get("devel").impersonate());
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(project2, "../project1").kind);
assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamProjectName(project2, "project3").kind);
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "/project1").kind);
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamProjectName(null, "project3").kind);
} finally {
SecurityContextHolder.getContext().setAuthentication(a);
}
}
@Test
public void testCheckUpstreamBuildNumber() throws Exception {
DownstreamBuildSelector.DescriptorImpl d = (DownstreamBuildSelector.DescriptorImpl)j.jenkins.getDescriptorOrDie(DownstreamBuildSelector.class);
ProjectMatrixAuthorizationStrategy pmas = new ProjectMatrixAuthorizationStrategy();
pmas.add(Jenkins.READ, "devel");
j.jenkins.setSecurityRealm(j.createDummySecurityRealm());
j.jenkins.setAuthorizationStrategy(pmas);
// project1
// project2
// build1
// project3 cannot read from devel
FreeStyleProject project1 = j.createFreeStyleProject("project1");
{
Map<Permission, Set<String>> map = new HashMap<Permission, Set<String>>();
map.put(Item.READ, Sets.newHashSet("devel"));
project1.addProperty(new AuthorizationMatrixProperty(map));
}
FreeStyleProject project2 = j.createFreeStyleProject("project2");
{
Map<Permission, Set<String>> map = new HashMap<Permission, Set<String>>();
map.put(Item.READ, Sets.newHashSet("devel"));
project2.addProperty(new AuthorizationMatrixProperty(map));
}
FreeStyleBuild build1 = project2.scheduleBuild2(0).get();
FreeStyleProject project3 = j.createFreeStyleProject("project3");
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(project1, "", Integer.toString(build1.getNumber())).kind);
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(project1, "$VAR", Integer.toString(build1.getNumber())).kind);
assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamBuildNumber(project1, "project2", null).kind);
assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamBuildNumber(project1, "project2", "").kind);
assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamBuildNumber(project1, "project2", " ").kind);
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(project1, "project2", "FOO${VAR}").kind);
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(project1, "project2", "\\${VAR}").kind); // limitation
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(project1, "project2", Integer.toString(build1.getNumber())).kind);
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(project1, "project2", build1.getId()).kind);
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(project1, "project2", build1.getDisplayName()).kind);
assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamBuildNumber(project1, "project2", "9999").kind);
assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamBuildNumber(project1, "project2", "NosuchBuild").kind);
//JENKINS-32526: Check that it behaves gracefully for an unknown context
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(null, "", Integer.toString(build1.getNumber())).kind);
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(null, "$VAR", Integer.toString(build1.getNumber())).kind);
assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamBuildNumber(null, "project2", null).kind);
assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamBuildNumber(null, "project2", "").kind);
assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamBuildNumber(null, "project2", " ").kind);
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(null, "project2", "FOO${VAR}").kind);
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(null, "project2", "\\${VAR}").kind); // limitation
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(null, "project2", Integer.toString(build1.getNumber())).kind);
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(null, "project2", build1.getId()).kind);
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(null, "project2", build1.getDisplayName()).kind);
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(null, "project2", "9999").kind);
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(null, "project2", "NosuchBuild").kind);
// permission check
Authentication a = Jenkins.getAuthentication();
try {
SecurityContextHolder.getContext().setAuthentication(User.get("devel").impersonate());
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(project1, "project3", "nosuchbuild").kind); // limitation
assertEquals(FormValidation.Kind.OK, d.doCheckUpstreamBuildNumber(null, "project3", "nosuchbuild").kind);
} finally {
SecurityContextHolder.getContext().setAuthentication(a);
}
}
@Test
public void testAutoCompleteUpstreamProjectName() throws Exception {
DownstreamBuildSelector.DescriptorImpl d = (DownstreamBuildSelector.DescriptorImpl) j.jenkins.getDescriptorOrDie(DownstreamBuildSelector.class);
ProjectMatrixAuthorizationStrategy pmas = new ProjectMatrixAuthorizationStrategy();
pmas.add(Jenkins.READ, "devel");
j.jenkins.setSecurityRealm(j.createDummySecurityRealm());
j.jenkins.setAuthorizationStrategy(pmas);
// project1
// project2 cannot read from devel
FreeStyleProject project1 = j.createFreeStyleProject("project1");
{
Map<Permission, Set<String>> map = new HashMap<Permission, Set<String>>();
map.put(Item.READ, Sets.newHashSet("devel"));
project1.addProperty(new AuthorizationMatrixProperty(map));
}
FreeStyleProject project2 = j.createFreeStyleProject("project2");
//Check Empty strings
testAutoCompleteUpstreamProjectName(new String [] {project1.getName(), project2.getName()}, "", project1, d);
//Check simple matching string
testAutoCompleteUpstreamProjectName(new String [] {project1.getName(), project2.getName()}, "proj", project1, d);
//Check non matching string
testAutoCompleteUpstreamProjectName(new String [] {}, "FOO", project1, d);
//Check matching string
testAutoCompleteUpstreamProjectName(new String [] {project1.getName()}, "project1", project2, d);
}
private void testAutoCompleteUpstreamProjectName(
String [] expectedValues,
String value,
AbstractProject project,
DownstreamBuildSelector.DescriptorImpl d) {
Set<String> actualValues = new TreeSet<String>(d.doAutoCompleteUpstreamProjectName(value, project).getValues());
assertArrayEquals(expectedValues, actualValues.toArray(new String [actualValues.size()]));
//JENKINS-32526: Auto-completion disabled if no context
actualValues = new TreeSet<String>(d.doAutoCompleteUpstreamProjectName(value, null).getValues());
assertArrayEquals(new String[] {}, actualValues.toArray(new String [actualValues.size()]));
}
@Test
public void testCheckUpstreamProjectNameForWorkflow() throws Exception {
FreeStyleProject context = j.createFreeStyleProject();
WorkflowJob target = j.jenkins.createProject(WorkflowJob.class, "workflow-test");
DownstreamBuildSelector.DescriptorImpl d = (DownstreamBuildSelector.DescriptorImpl)j.jenkins.getDescriptorOrDie(DownstreamBuildSelector.class);
// DownstreamBuildSelector is not applicable to workflow.
assertEquals(FormValidation.Kind.ERROR, d.doCheckUpstreamProjectName(context, target.getFullName()).kind);
}
@Test
public void testUpstreamIsWorkflow() throws Exception {
WorkflowJob upstream = j.jenkins.createProject(WorkflowJob.class, "upstream");
upstream.setDefinition(new CpsFlowDefinition(
"node {"
+ "writeFile text: \"${env.BUILD_TAG}\", file: 'upstream_artifact.txt'; "
+ "step([$class: 'ArtifactArchiver', artifacts: 'upstream_artifact.txt'])"
+ "}",
true
));
WorkflowRun upstreamBuild = j.assertBuildStatusSuccess(upstream.scheduleBuild2(0));
FreeStyleProject downstream = j.createFreeStyleProject();
CopyArtifact ca = new CopyArtifact(upstream.getFullName());
ca.setFingerprintArtifacts(true);
ca.setFilter("upstream_artifact.txt");
downstream.getBuildersList().add(ca);
downstream.getBuildersList().add(new FileWriteBuilder("downstream_artifact.txt", "${BUILD_TAG}"));
ArtifactArchiver aa = new ArtifactArchiver("downstream_artifact.txt");
aa.setAllowEmptyArchive(false);
aa.setFingerprint(true);
downstream.getPublishersList().add(aa);
FreeStyleBuild downstreamBuild = j.assertBuildStatusSuccess(downstream.scheduleBuild2(0));
FreeStyleProject p = j.createFreeStyleProject();
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
downstream.getFullName(),
"",
new DownstreamBuildSelector(
upstream.getFullName(),
Integer.toString(upstreamBuild.getNumber())
),
"**/*",
"",
"",
false,
false,
true
));
// fail as DownstreamBuildSelector doesn't support workflow upstream.
FreeStyleBuild b = j.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0).get());
// to see expected log is recorded.
//System.out.println(b.getLog());
}
@Test
public void testDownstreamIsWorkflow() throws Exception {
FreeStyleProject upstream = j.createFreeStyleProject();
upstream.getBuildersList().add(new FileWriteBuilder("upstream_artifact.txt", "${BUILD_TAG}"));
ArtifactArchiver aa = new ArtifactArchiver("upstream_artifact.txt");
aa.setAllowEmptyArchive(false);
aa.setFingerprint(true);
upstream.getPublishersList().add(aa);
FreeStyleBuild upstreamBuild = j.assertBuildStatusSuccess(upstream.scheduleBuild2(0));
WorkflowJob downstream = j.jenkins.createProject(WorkflowJob.class, "downstream");
downstream.setDefinition(new CpsFlowDefinition(
"node {"
+ "step([$class: 'CopyArtifact', projectName: '" + upstream.getFullName() + "', filter: 'upstream_artifact.txt', fingerprintAritfacts: true]);"
+ "writeFile text: \"${env.BUILD_TAG}\", file: 'downstream_artifact.txt'; "
+ "step([$class: 'ArtifactArchiver', artifacts: 'downstream_artifact.txt'])"
+ "}",
true
));
WorkflowRun downstreamBuild = j.assertBuildStatusSuccess(downstream.scheduleBuild2(0));
FreeStyleProject p = j.createFreeStyleProject();
p.getBuildersList().add(CopyArtifactUtil.createCopyArtifact(
downstream.getFullName(),
"",
new DownstreamBuildSelector(
upstream.getFullName(),
Integer.toString(upstreamBuild.getNumber())
),
"**/*",
"",
"",
false,
false,
true
));
// fail as DownstreamBuildSelector doesn't support workflow downstream.
FreeStyleBuild b = j.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0).get());
// to see expected log is recorded.
//System.out.println(b.getLog());
}
}