Java tutorial
/* * The MIT License * * Copyright (c) 2004-2011, Sun Microsystems, Inc., Alan Harder * * 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 hudson.FilePath; import hudson.Launcher; import hudson.matrix.Axis; import hudson.matrix.AxisList; import hudson.matrix.Combination; import hudson.matrix.MatrixBuild; import hudson.matrix.MatrixProject; import hudson.matrix.MatrixRun; import hudson.maven.MavenModuleSet; import hudson.model.AbstractBuild; import hudson.model.Action; import hudson.model.BooleanParameterDefinition; import hudson.model.BooleanParameterValue; import hudson.model.Build; import hudson.model.BuildListener; import hudson.model.Cause.UserCause; import hudson.model.ChoiceParameterDefinition; import hudson.model.Descriptor; import hudson.model.Fingerprint; import hudson.model.FreeStyleBuild; import hudson.model.FreeStyleProject; import hudson.model.Hudson; import hudson.model.Item; import hudson.model.ParametersAction; import hudson.model.ParametersDefinitionProperty; import hudson.model.Result; import hudson.model.StringParameterDefinition; import hudson.model.StringParameterValue; import hudson.security.AuthorizationMatrixProperty; import hudson.security.GlobalMatrixAuthorizationStrategy; import hudson.slaves.DumbSlave; import hudson.slaves.SlaveComputer; import hudson.tasks.ArtifactArchiver; import hudson.tasks.BuildTrigger; import hudson.tasks.Builder; import hudson.util.DescribableList; import hudson.util.FormValidation; import hudson.util.VersionNumber; import java.io.IOException; import java.util.Collections; import org.eclipse.hudson.api.model.IBaseBuildableProject; import org.jvnet.hudson.test.CaptureEnvironmentBuilder; import org.jvnet.hudson.test.ExtractResourceSCM; import org.jvnet.hudson.test.FailureBuilder; import org.jvnet.hudson.test.HudsonTestCase; import org.jvnet.hudson.test.UnstableBuilder; import org.jvnet.hudson.test.recipes.LocalData; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; /** * Test interaction of copyartifact plugin with Jenkins core. * * @author Alan Harder */ public class CopyArtifactTest extends HudsonTestCase { protected void addBuilder(IBaseBuildableProject up, Builder builder) throws IOException { DescribableList<Builder, Descriptor<Builder>> buildersList = up.getBuildersList(); buildersList.add(builder); up.setBuilders(buildersList); } protected void replaceBuilder(IBaseBuildableProject up, Builder newBuilder) throws IOException { DescribableList<Builder, Descriptor<Builder>> buildersList = up.getBuildersList(); buildersList.replace(newBuilder); up.setBuilders(buildersList); } protected void removeBuilder(IBaseBuildableProject up, Class oldBuilder) throws IOException { DescribableList<Builder, Descriptor<Builder>> buildersList = up.getBuildersList(); buildersList.remove(oldBuilder); up.setBuilders(buildersList); } private FreeStyleProject createProject(String otherProject, String filter, String target, boolean stable, boolean flatten, boolean optional) throws IOException { FreeStyleProject p = createFreeStyleProject(); addBuilder(p, new CopyArtifact(otherProject, new StatusBuildSelector(stable), filter, target, flatten, optional)); return p; } private static class ArtifactBuilder extends Builder { @Override public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { // Make some files to archive as artifacts FilePath ws = build.getWorkspace(); ws.child("foo.txt").touch(System.currentTimeMillis()); ws.child("subdir").mkdirs(); ws.child("subdir/subfoo.txt").touch(System.currentTimeMillis()); ws.child("deepfoo/a/b").mkdirs(); ws.child("deepfoo/a/b/c.log").touch(System.currentTimeMillis()); // For matrix tests write one more file: String foo = build.getBuildVariables().get("FOO"); if (foo != null) { ws.child(foo + ".txt").touch(System.currentTimeMillis()); } return true; } } private FreeStyleProject createArtifactProject(String name) throws IOException { FreeStyleProject p = name != null ? createFreeStyleProject(name) : createFreeStyleProject(); addBuilder(p, new ArtifactBuilder()); p.addPublisher(new ArtifactArchiver("**", "", false)); return p; } private FreeStyleProject createArtifactProject() throws IOException { return createArtifactProject(null); } private MatrixProject createMatrixArtifactProject() throws IOException { MatrixProject p = createMatrixProject(); p.setAxes(new AxisList(new Axis("FOO", "one", "two"))); addBuilder(p, new ArtifactBuilder()); p.addPublisher(new ArtifactArchiver("**", "", false)); return p; } private static void assertFile(boolean exists, String path, Build<?, ?> b) throws IOException, InterruptedException { if (b.getWorkspace().child(path).exists() != exists) { assertEquals(path + ": " + getLog(b), exists, !exists); } } public void testMissingProject() throws Exception { FreeStyleProject p = createProject("invalid", "", "", false, false, false); assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0, new UserCause()).get()); } public void testMissingBuild() throws Exception { FreeStyleProject other = createFreeStyleProject(), p = createProject(other.getName(), "", "", false, false, false); assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0, new UserCause()).get()); } public void testMissingStableBuild() throws Exception { FreeStyleProject other = createFreeStyleProject(), p = createProject(other.getName(), "", "", true, false, false); // Make an unstable build in "other" addBuilder(other, new UnstableBuilder()); assertBuildStatus(Result.UNSTABLE, other.scheduleBuild2(0, new UserCause()).get()); assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0, new UserCause()).get()); } public void testMissingArtifact() throws Exception { FreeStyleProject other = createFreeStyleProject(), p = createProject(other.getName(), "*.txt", "", false, false, false); assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get()); assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0, new UserCause()).get()); } public void testCopyAll() throws Exception { FreeStyleProject other = createArtifactProject(), p = createProject(other.getName(), "", "", false, false, false); FreeStyleBuild s = assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get()); FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get(); assertBuildStatusSuccess(b); assertFile(true, "foo.txt", b); assertFile(true, "subdir/subfoo.txt", b); assertFile(true, "deepfoo/a/b/c.log", b); // testing fingerprints String d = b.getWorkspace().child("foo.txt").digest(); Fingerprint f = Hudson.getInstance().getFingerprintMap().get(d); assertSame(f.getOriginal().getRun(), s); assertTrue(f.getRangeSet(p).includes(b.getNumber())); } public void testCopyWithFilter() throws Exception { FreeStyleProject other = createArtifactProject(), p = createProject(other.getName(), "**/bogus*, **/sub*, bogus/**", "", false, false, false); assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get()); FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get(); assertBuildStatusSuccess(b); assertFile(false, "foo.txt", b); assertFile(true, "subdir/subfoo.txt", b); assertFile(false, "deepfoo/a/b/c.log", b); } public void testCopyToTarget() throws Exception { FreeStyleProject other = createArtifactProject(), p = createProject(other.getName(), "deep*/**", "new/deep/dir", true, false, false); assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get()); FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get(); assertBuildStatusSuccess(b); assertFile(false, "foo.txt", b); assertFile(false, "new/deep/dir/foo.txt", b); assertFile(true, "new/deep/dir/deepfoo/a/b/c.log", b); } public void testCopyToSlave() throws Exception { DumbSlave node = createSlave(); SlaveComputer c = node.getComputer(); c.connect(false).get(); // wait until it's connected if (c.isOffline()) { fail("Slave failed to go online: " + c.getLog()); } FreeStyleProject other = createArtifactProject(), p = createProject(other.getName(), "", "", false, false, false); assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get()); p.setAssignedLabel(node.getSelfLabel()); FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get(); assertBuildStatusSuccess(b); assertSame(node, b.getBuiltOn()); assertFile(true, "foo.txt", b); assertFile(true, "subdir/subfoo.txt", b); assertFile(true, "deepfoo/a/b/c.log", b); } public void testParameters() throws Exception { FreeStyleProject other = createArtifactProject(), p = createProject("$PROJSRC", "$BASE/*.txt", "$TARGET/bar", false, false, false); assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get()); FreeStyleBuild b = p .scheduleBuild2(0, new UserCause(), new ParametersAction(new StringParameterValue("PROJSRC", other.getName()), new StringParameterValue("BASE", "*r"), new StringParameterValue("TARGET", "foo"))) .get(); assertBuildStatusSuccess(b); assertFile(false, "foo/bar/foo.txt", b); assertFile(true, "foo/bar/subdir/subfoo.txt", b); } /** * Test copying artifacts from a particular configuration of a matrix job */ public void testMatrixJob() throws Exception { MatrixProject other = createMatrixArtifactProject(); FreeStyleProject p = createProject(other.getName() + "/FOO=two", "", "", true, false, false); assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get()); FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get(); assertBuildStatusSuccess(b); assertFile(true, "foo.txt", b); assertFile(true, "two.txt", b); assertFile(true, "subdir/subfoo.txt", b); assertFile(true, "deepfoo/a/b/c.log", b); } /** * Test artifact copy between matrix jobs, for artifact from matching axis */ public void testMatrixToMatrix() throws Exception { MatrixProject other = createMatrixArtifactProject(), p = createMatrixProject(); p.setAxes(new AxisList(new Axis("FOO", "one", "two"))); // should match other job addBuilder(p, new CopyArtifact(other.getName() + "/FOO=$FOO", new StatusBuildSelector(true), "", "", false, false)); assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get()); MatrixBuild b = p.scheduleBuild2(0, new UserCause()).get(); assertBuildStatusSuccess(b); MatrixRun r = b.getRun(new Combination(Collections.singletonMap("FOO", "one"))); assertFile(true, "one.txt", r); assertFile(false, "two.txt", r); r = b.getRun(new Combination(Collections.singletonMap("FOO", "two"))); assertFile(false, "one.txt", r); assertFile(true, "two.txt", r); } private static class ArchMatrixBuilder extends Builder { @Override public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { // Get matrix axis value String arch = build.getBuildVariables().get("ARCH"); FilePath ws = build.getWorkspace(); ws.child("target").mkdirs(); // One fixed filename: ws.child("target/readme.txt").touch(System.currentTimeMillis()); // Use axis value in one filename: ws.child("target/" + arch + ".out").touch(System.currentTimeMillis()); return true; } } /** * Test copying artifacts from all configurations of a matrix job */ public void testMatrixAll() throws Exception { MatrixProject mp = createMatrixProject(); mp.setAxes(new AxisList(new Axis("ARCH", "sparc", "x86"))); addBuilder(mp, new ArchMatrixBuilder()); mp.addPublisher(new ArtifactArchiver("target/*", "", false)); assertBuildStatusSuccess(mp.scheduleBuild2(0, new UserCause()).get()); FreeStyleProject p = createProject(mp.getName(), "", "", true, false, false); FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get(); assertBuildStatusSuccess(b); assertFile(true, "ARCH=sparc/target/readme.txt", b); assertFile(true, "ARCH=sparc/target/sparc.out", b); assertFile(true, "ARCH=x86/target/readme.txt", b); assertFile(true, "ARCH=x86/target/x86.out", b); } private MavenModuleSet setupMavenJob() throws Exception { configureDefaultMaven(); MavenModuleSet mp = hudson.createProject(MavenModuleSet.class, "test" + hudson.getItems().size()); mp.setGoals("clean package"); mp.setScm(new ExtractResourceSCM(getClass().getResource("maven-job.zip"))); return mp; } private static final VersionNumber MAVEN_POM_CUTOFF = new VersionNumber("1.405"); private static String pomName(String module, String version) { return module + '/' + version + '/' + "pom.xml"; } /** * Test copying from a particular module of a maven job */ public void testMavenJob() throws Exception { MavenModuleSet mp = setupMavenJob(); assertBuildStatusSuccess(mp.scheduleBuild2(0, new UserCause()).get()); FreeStyleProject p = createProject(mp.getName() + "/org.jvnet.hudson.main.test.multimod$moduleB", "", "", true, false, false); FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get(); assertBuildStatusSuccess(b); String dir = "org.jvnet.hudson.main.test.multimod/"; assertFile(true, dir + "moduleB/1.0-SNAPSHOT/moduleB-1.0-SNAPSHOT.jar", b); assertFile(true, dir + pomName("moduleB", "1.0-SNAPSHOT"), b); } /** * Test copying all artifacts from a maven job */ public void testMavenAll() throws Exception { MavenModuleSet mp = setupMavenJob(); assertBuildStatusSuccess(mp.scheduleBuild2(0, new UserCause()).get()); FreeStyleProject p = createProject(mp.getName(), "", "", true, false, false); FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get(); assertBuildStatusSuccess(b); String dir = "org.jvnet.hudson.main.test.multimod/"; assertFile(true, dir + "moduleA/1.0-SNAPSHOT/moduleA-1.0-SNAPSHOT.jar", b); assertFile(true, dir + pomName("moduleA", "1.0-SNAPSHOT"), b); assertFile(true, dir + "moduleB/1.0-SNAPSHOT/moduleB-1.0-SNAPSHOT.jar", b); assertFile(true, dir + pomName("moduleB", "1.0-SNAPSHOT"), b); assertFile(true, dir + "moduleC/1.0-SNAPSHOT/moduleC-1.0-SNAPSHOT.jar", b); assertFile(true, dir + pomName("moduleC", "1.0-SNAPSHOT"), b); // Test with filter p = createProject(mp.getName(), "**/*.jar", "", true, false, false); b = p.scheduleBuild2(0, new UserCause()).get(); assertBuildStatusSuccess(b); assertFile(true, dir + "moduleA/1.0-SNAPSHOT/moduleA-1.0-SNAPSHOT.jar", b); assertFile(false, dir + pomName("moduleA", "1.0-SNAPSHOT"), b); assertFile(true, dir + "moduleB/1.0-SNAPSHOT/moduleB-1.0-SNAPSHOT.jar", b); assertFile(false, dir + pomName("moduleB", "1.0-SNAPSHOT"), b); assertFile(true, dir + "moduleC/1.0-SNAPSHOT/moduleC-1.0-SNAPSHOT.jar", b); assertFile(false, dir + pomName("moduleC", "1.0-SNAPSHOT"), b); } /** * Test copying from maven job where artifacts manually archived instead of * automatic */ public void testMavenJobWithArchivePostBuildStep() throws Exception { MavenModuleSet mp = setupMavenJob(); // Turn off automatic archiving and use a post-build step instead. // Artifacts will be stored with the parent build instead of the child module builds. mp.setIsArchivingDisabled(true); mp.getPublishersList().add(new ArtifactArchiver("moduleB/*.xml", "", false)); assertBuildStatusSuccess(mp.scheduleBuild2(0, new UserCause()).get()); FreeStyleProject p = createProject(mp.getName(), "", "", true, false, false); FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get(); // Archived artifact should be copied: assertFile(true, "moduleB/pom.xml", b); // None of the maven artifacts should be archived or copied: String dir = "org.jvnet.hudson.main.test.multimod/"; assertFile(false, dir + "moduleA/1.0-SNAPSHOT/moduleA-1.0-SNAPSHOT.jar", b); assertFile(false, dir + pomName("moduleA", "1.0-SNAPSHOT"), b); assertFile(false, dir + "moduleB/1.0-SNAPSHOT/moduleB-1.0-SNAPSHOT.jar", b); assertFile(false, dir + pomName("moduleB", "1.0-SNAPSHOT"), b); assertFile(false, dir + "moduleC/1.0-SNAPSHOT/moduleC-1.0-SNAPSHOT.jar", b); assertFile(false, dir + pomName("moduleC", "1.0-SNAPSHOT"), b); } /** * Test copy from workspace instead of artifacts area */ public void testCopyFromWorkspace() throws Exception { FreeStyleProject other = createFreeStyleProject(), p = createFreeStyleProject(); addBuilder(p, new CopyArtifact(other.getName(), new WorkspaceSelector(), "**/*.txt", "", true, false)); // Run a build that places a file in the workspace, but does not archive anything addBuilder(other, new ArtifactBuilder()); assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get()); FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get(); assertBuildStatusSuccess(b); assertFile(true, "foo.txt", b); assertFile(true, "subfoo.txt", b); assertFile(false, "c.log", b); } /** * projectName in CopyArtifact build steps should be updated if a job is * renamed */ public void testJobRename() throws Exception { FreeStyleProject other = createFreeStyleProject(), p = createProject(other.getName(), "", "", true, false, false); assertEquals("before", other.getName(), ((CopyArtifact) p.getBuilders().get(0)).getProjectName()); String newName = other.getName() + "-new"; other.renameTo(newName); assertEquals("after", newName, ((CopyArtifact) p.getBuilders().get(0)).getProjectName()); // Test reference to a matrix configuration MatrixProject otherm = createMatrixProject(), mp = createMatrixProject(); addBuilder(mp, new CopyArtifact(otherm.getName() + "/FOO=$FOO", new SavedBuildSelector(), "", "", false, false)); assertEquals("before", otherm.getName() + "/FOO=$FOO", ((CopyArtifact) mp.getBuilders().get(0)).getProjectName()); otherm.renameTo(newName = otherm.getName() + "-new"); assertEquals("after", newName + "/FOO=$FOO", ((CopyArtifact) mp.getBuilders().get(0)).getProjectName()); } public void testSavedBuildSelector() throws Exception { FreeStyleProject other = createArtifactProject(), p = createFreeStyleProject(); addBuilder(p, new CopyArtifact(other.getName(), new SavedBuildSelector(), "*.txt", "", false, false)); FreeStyleBuild b = other.scheduleBuild2(0, new UserCause(), new ParametersAction(new StringParameterValue("FOO", "buildone"))).get(); assertBuildStatusSuccess(b); assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause())); b.keepLog(true); b = p.scheduleBuild2(0, new UserCause()).get(); assertBuildStatusSuccess(b); assertFile(true, "foo.txt", b); assertFile(true, "buildone.txt", b); assertFile(false, "subdir/subfoo.txt", b); } public void testSpecificBuildSelector() throws Exception { FreeStyleProject other = createArtifactProject(), p = createFreeStyleProject(); SpecificBuildSelector sbs = new SpecificBuildSelector("1"); assertEquals("1", sbs.getBuildNumber()); addBuilder(p, new CopyArtifact(other.getName(), sbs, "*.txt", "", false, false)); assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause(), new ParametersAction(new StringParameterValue("FOO", "buildone"))).get()); assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause())); FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get(); assertBuildStatusSuccess(b); assertFile(true, "foo.txt", b); assertFile(true, "buildone.txt", b); assertFile(false, "subdir/subfoo.txt", b); } public void testSpecificBuildSelectorParameter() throws Exception { FreeStyleProject other = createArtifactProject(), p = createFreeStyleProject(); addBuilder(p, new CopyArtifact(other.getName(), new SpecificBuildSelector("$BAR"), "*.txt", "", false, false)); assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause(), new ParametersAction(new StringParameterValue("FOO", "buildone"))).get()); assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause())); FreeStyleBuild b = p .scheduleBuild2(0, new UserCause(), new ParametersAction(new StringParameterValue("BAR", "1"))) .get(); assertBuildStatusSuccess(b); assertFile(true, "foo.txt", b); assertFile(true, "buildone.txt", b); assertFile(false, "subdir/subfoo.txt", b); } public void testParameterizedBuildSelector() throws Exception { FreeStyleProject other = createArtifactProject(), p = createFreeStyleProject(); ParameterizedBuildSelector pbs = new ParameterizedBuildSelector("PBS"); assertEquals("PBS", pbs.getParameterName()); addBuilder(p, new CopyArtifact(other.getName(), pbs, "*.txt", "", false, false)); FreeStyleBuild b = other.scheduleBuild2(0, new UserCause(), new ParametersAction(new StringParameterValue("FOO", "buildone"))).get(); assertBuildStatusSuccess(b); assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause())); b.keepLog(true); b = p.scheduleBuild2(0, new UserCause(), new ParametersAction( new StringParameterValue("PBS", "<hudson.plugins.copyartifact.SavedBuildSelector/>"))) .get(); assertBuildStatusSuccess(b); assertFile(true, "foo.txt", b); assertFile(true, "buildone.txt", b); assertFile(false, "subdir/subfoo.txt", b); } public void testPermalinkBuildSelector() throws Exception { FreeStyleProject other = createArtifactProject(), p = createFreeStyleProject(); addBuilder(p, new CopyArtifact(other.getName(), new PermalinkBuildSelector("lastStableBuild"), "*.txt", "", false, false)); FreeStyleBuild b = other.scheduleBuild2(0, new UserCause(), new ParametersAction(new StringParameterValue("FOO", "buildone"))).get(); assertBuildStatusSuccess(b); addBuilder(other, new UnstableBuilder()); assertBuildStatus(Result.UNSTABLE, other.scheduleBuild2(0, new UserCause()).get()); b = p.scheduleBuild2(0, new UserCause()).get(); assertBuildStatusSuccess(b); assertFile(true, "foo.txt", b); assertFile(true, "buildone.txt", b); assertFile(false, "subdir/subfoo.txt", b); // Invalid permalink replaceBuilder(p, new CopyArtifact(other.getName(), new PermalinkBuildSelector("fooBuild"), "*.txt", "", false, false)); assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0, new UserCause()).get()); } public void testTriggeredBuildSelector() throws Exception { FreeStyleProject other = createArtifactProject(), p = createFreeStyleProject(); addBuilder(p, new CopyArtifact(other.getName(), new TriggeredBuildSelector(false), "*.txt", "", false, false)); other.addPublisher(new BuildTrigger(p.getFullName(), false)); hudson.rebuildDependencyGraph(); assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause())); // p#1 was triggered, now building. FreeStyleBuild b = p.getBuildByNumber(1); for (int i = 0; b == null && i < 1000; i++) { Thread.sleep(10); b = p.getBuildByNumber(1); } assertNotNull(b); while (b.isBuilding()) { Thread.sleep(10); } assertBuildStatusSuccess(b); assertFile(true, "foo.txt", b); assertFile(false, "subdir/subfoo.txt", b); // Verify error if build not triggered by upstream job: assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0, new UserCause()).get()); // test fallback //run a failing build to make sure the fallback selects the last successful build other.getPublishersList().clear(); addBuilder(other, new FailureBuilder()); assertBuildStatus(Result.FAILURE, other.scheduleBuild2(0, new UserCause()).get()); removeBuilder(p, CopyArtifact.class); addBuilder(p, new CopyArtifact(other.getName(), new TriggeredBuildSelector(true), "*.txt", "", false, false)); assertBuildStatus(Result.SUCCESS, p.scheduleBuild2(0, new UserCause()).get()); } /** * When copying from a particular matrix configuration, the upstream project * is the matrix parent. */ public void testTriggeredBuildSelectorFromMatrix() throws Exception { MatrixProject other = createMatrixArtifactProject(); FreeStyleProject p = createFreeStyleProject(); addBuilder(p, new CopyArtifact(other.getName() + "/FOO=two", new TriggeredBuildSelector(false), "*.txt", "", false, false)); other.addPublisher(new BuildTrigger(p.getFullName(), false)); hudson.rebuildDependencyGraph(); assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get()); // p#1 was triggered, now building. FreeStyleBuild b = p.getBuildByNumber(1); for (int i = 0; b == null && i < 1000; i++) { Thread.sleep(10); b = p.getBuildByNumber(1); } assertNotNull(b); while (b.isBuilding()) { Thread.sleep(10); } assertBuildStatusSuccess(b); assertFile(true, "foo.txt", b); assertFile(true, "two.txt", b); } /** * When copying to a matrix job, need to check the upstream cause of the * matrix parent. */ public void testTriggeredBuildSelectorToMatrix() throws Exception { FreeStyleProject other = createArtifactProject(); MatrixProject p = createMatrixProject(); p.setAxes(new AxisList(new Axis("FOO", "one", "two"))); addBuilder(p, new CopyArtifact(other.getName(), new TriggeredBuildSelector(false), "*.txt", "", false, false)); other.addPublisher(new BuildTrigger(p.getFullName(), false)); hudson.rebuildDependencyGraph(); assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get()); // p#1 was triggered, now building. MatrixBuild b = p.getBuildByNumber(1); for (int i = 0; b == null && i < 1000; i++) { Thread.sleep(10); b = p.getBuildByNumber(1); } assertNotNull(b); while (b.isBuilding()) { Thread.sleep(10); } assertBuildStatusSuccess(b); MatrixRun r = b.getRuns().get(0); assertFile(true, "foo.txt", r); } public void testFlatten() throws Exception { FreeStyleProject other = createArtifactProject(), p = createProject(other.getName(), "", "newdir", false, true, false); assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get()); FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get(); assertBuildStatusSuccess(b); assertFile(true, "newdir/foo.txt", b); assertFile(true, "newdir/subfoo.txt", b); assertFile(true, "newdir/c.log", b); } public void testOptional_MissingProject() throws Exception { // Missing project still fails even when copy is optional FreeStyleProject p = createProject("invalid", "", "", false, false, true); assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0, new UserCause()).get()); } public void testOptional_MissingBuild() throws Exception { FreeStyleProject other = createFreeStyleProject(), p = createProject(other.getName(), "", "", false, false, true); assertBuildStatusSuccess(p.scheduleBuild2(0, new UserCause()).get()); } public void testOptional_MissingArtifact() throws Exception { FreeStyleProject other = createFreeStyleProject(), p = createProject(other.getName(), "*.txt", "", false, false, true); assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get()); assertBuildStatusSuccess(p.scheduleBuild2(0, new UserCause()).get()); } /** * Test that a user is prevented from bypassing permissions on other jobs * when configuring a copyartifact build step. */ // @LocalData // public void testPermission() throws Exception { // executeOnServer(new Callable<Object>() { // public Object call() throws Exception { // assertNull("Job should not be accessible to anonymous", hudson.getItem("testJob")); // assertEquals("Should ignore/clear value for inaccessible project", "", // new CopyArtifact("testJob", null, null, null, false, false).getProjectName()); // return null; // } // }); // // // Login as user with access to testJob: // WebClient wc = createWebClient(); // wc.login("joe", "joe"); // wc.executeOnServer(new Callable<Object>() { // public Object call() throws Exception { // assertEquals("Should allow use of testJob for joe", "testJob", // new CopyArtifact("testJob", null, null, null, false, false).getProjectName()); // return null; // } // }); // } /** * When the source project name is parameterized, cannot check at configure * time whether the project is accessible. In this case, permission check is * done when the build runs. Only jobs accessible to all authenticated users * are allowed. */ @LocalData public void testPermissionWhenParameterized() throws Exception { FreeStyleProject p = createProject("test$JOB", "", "", false, false, false); // Build step should succeed when this parameter expands to a job accessible // to authenticated users (even if triggered by anonymous, as in this case): SecurityContextHolder.clearContext(); FreeStyleBuild b = p .scheduleBuild2(0, new UserCause(), new ParametersAction(new StringParameterValue("JOB", "Job2"))) .get(); assertFile(true, "foo2.txt", b); assertBuildStatusSuccess(b); // Build step should fail for a job not accessible to all authenticated users, // even when accessible to the user starting the job, as in this case: SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("joe", "joe")); b = p.scheduleBuild2(0, new UserCause(), new ParametersAction(new StringParameterValue("JOB", "Job"))) .get(); assertFile(false, "foo.txt", b); assertBuildStatus(Result.FAILURE, b); } // // @LocalData // public void testPermissionWhenParameterizedForMatrixConfig() throws Exception { // // This test fails before Jenkins 1.406 // if (new VersionNumber("1.406").isNewerThan(Hudson.getVersion())) { // return; // Skip // } // FreeStyleProject p = createProject("testMatrix/FOO=$FOO", "", "", false, false, false); // // Build step should succeed when this parameter expands to a job accessible to // // authenticated users, even when selecting a single matrix config, not the parent job: // FreeStyleBuild b = p.scheduleBuild2(0, new UserCause(), // new ParametersAction(new StringParameterValue("FOO", "foo"))).get(); // assertFile(true, "foo.txt", b); // assertBuildStatusSuccess(b); // } // @LocalData // public void testPermissionWhenParameterizedForMavenModule() throws Exception { // // This test fails before Jenkins 1.406 // if (new VersionNumber("1.406").isNewerThan(Hudson.getVersion())) { // return; // Skip // } // MavenModuleSet mp = setupMavenJob(); // mp.addProperty(new AuthorizationMatrixProperty( // Collections.singletonMap(Item.READ, Collections.singleton("authenticated")))); // assertBuildStatusSuccess(mp.scheduleBuild2(0, new UserCause()).get()); // FreeStyleProject p = createProject(mp.getName() + "/org.jvnet.hudson.main.test.multimod$FOO", // "", "", false, false, false); // // Build step should succeed when this parameter expands to a job accessible to // // authenticated users, even when selecting a single maven module, not the parent job: // FreeStyleBuild b = p.scheduleBuild2(0, new UserCause(), // new ParametersAction(new StringParameterValue("FOO", "$moduleA"))).get(); // String dir = "org.jvnet.hudson.main.test.multimod/"; // assertFile(true, dir + "moduleA/1.0-SNAPSHOT/moduleA-1.0-SNAPSHOT.jar", b); // assertFile(true, dir + pomName("moduleA", "1.0-SNAPSHOT"), b); // assertFile(false, dir + "moduleB/1.0-SNAPSHOT/moduleB-1.0-SNAPSHOT.jar", b); // assertFile(false, dir + pomName("moduleB", "1.0-SNAPSHOT"), b); // assertBuildStatusSuccess(b); // } /** * Test that info about selected builds is added into the environment for * later build steps. */ public void testEnvData() throws Exception { // Also test conversion of job name to env var name, only keeping letters: FreeStyleProject other = createArtifactProject("My (Test) Job"), p = createProject(other.getName(), "", "", false, false, false); CaptureEnvironmentBuilder envStep = new CaptureEnvironmentBuilder(); addBuilder(p, envStep); // Bump up the build number a bit: for (int i = 0; i < 3; i++) { other.assignBuildNumber(); } assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause()).get()); FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get(); assertBuildStatusSuccess(b); assertEquals("4", envStep.getEnvVars().get("COPYARTIFACT_BUILD_NUMBER_MY_TEST_JOB")); } /** * Test filtering on parameters, ie. last stable build with parameter * FOO=bar. */ public void testFilterByParameters() throws Exception { FreeStyleProject other = createArtifactProject("Foo job"); other.addProperty(new ParametersDefinitionProperty(new StringParameterDefinition("FOO", ""), new BooleanParameterDefinition("BAR", false, ""), new ChoiceParameterDefinition("BAZ", new String[] { "foo", "bar", "baz" }, ""))); // #1: FOO=foo BAR=false BAZ=baz assertBuildStatusSuccess(other .scheduleBuild2(0, new UserCause(), new ParametersAction(new StringParameterValue("FOO", "foo"), new BooleanParameterValue("BAR", false), new StringParameterValue("BAZ", "baz"))) .get()); // #2: FOO=bar BAR=true BAZ=foo assertBuildStatusSuccess(other .scheduleBuild2(0, new UserCause(), new ParametersAction(new StringParameterValue("FOO", "bar"), new BooleanParameterValue("BAR", true), new StringParameterValue("BAZ", "foo"))) .get()); // #3: FOO=foo BAR=true BAZ=bar assertBuildStatusSuccess(other .scheduleBuild2(0, new UserCause(), new ParametersAction(new StringParameterValue("FOO", "foo"), new BooleanParameterValue("BAR", true), new StringParameterValue("BAZ", "bar"))) .get()); FreeStyleProject p = createProject(other.getName() + "/FOO=bar", "*.txt", "", true, false, false); CaptureEnvironmentBuilder envStep = new CaptureEnvironmentBuilder(); addBuilder(p, envStep); FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get(); assertBuildStatusSuccess(b); assertEquals("2", envStep.getEnvVars().get("COPYARTIFACT_BUILD_NUMBER_FOO_JOB")); p = createProject(other.getName() + "/BAR=false", "*.txt", "", true, false, false); addBuilder(p, envStep); b = p.scheduleBuild2(0, new UserCause()).get(); assertBuildStatusSuccess(b); assertEquals("1", envStep.getEnvVars().get("COPYARTIFACT_BUILD_NUMBER_FOO_JOB")); p = createProject(other.getName() + "/BAZ=foo,BAR=true", "*.txt", "", true, false, false); addBuilder(p, envStep); b = p.scheduleBuild2(0, new UserCause()).get(); assertBuildStatusSuccess(b); assertEquals("2", envStep.getEnvVars().get("COPYARTIFACT_BUILD_NUMBER_FOO_JOB")); p = createProject(other.getName() + "/FOO=foo,BAR=false,BAZ=baz", "*.txt", "", true, false, false); addBuilder(p, envStep); b = p.scheduleBuild2(0, new UserCause()).get(); assertBuildStatusSuccess(b); assertEquals("1", envStep.getEnvVars().get("COPYARTIFACT_BUILD_NUMBER_FOO_JOB")); p = createProject(other.getName() + "/BAZ=bar,FOO=bogus", "*.txt", "", true, false, false); b = p.scheduleBuild2(0, new UserCause()).get(); assertBuildStatus(Result.FAILURE, b); // Test matching other build variables besides parameters p = createProject(other.getName() + "/BUILD_NUMBER=2", "*.txt", "", true, false, false); addBuilder(p, envStep); b = p.scheduleBuild2(0, new UserCause()).get(); assertBuildStatusSuccess(b); assertEquals("2", envStep.getEnvVars().get("COPYARTIFACT_BUILD_NUMBER_FOO_JOB")); // Test coverage for EnvAction boolean ok = false; for (Action a : b.getActions()) { if ("hudson.plugins.copyartifact.CopyArtifact$EnvAction".equals(a.getClass().getName())) { assertNull(a.getIconFileName()); assertNull(a.getDisplayName()); assertNull(a.getUrlName()); ok = true; } } assertTrue(ok); } public void testSavedBuildSelectorWithParameterFilter() throws Exception { FreeStyleProject other = createArtifactProject(), p = createFreeStyleProject(); other.addProperty(new ParametersDefinitionProperty(new StringParameterDefinition("FOO", ""))); FreeStyleBuild b = other.scheduleBuild2(0, new UserCause(), new ParametersAction(new StringParameterValue("FOO", "buildone"))).get(); assertBuildStatusSuccess(b); b.keepLog(true); addBuilder(p, new CopyArtifact(other.getName() + "/FOO=buildone", new SavedBuildSelector(), "*.txt", "", false, false)); assertBuildStatusSuccess(b = other.scheduleBuild2(0, new UserCause()).get()); b.keepLog(true); // Keep #2 too, but it doesn't have FOO=buildone so should not be selected assertBuildStatusSuccess(b = p.scheduleBuild2(0, new UserCause()).get()); assertFile(true, "foo.txt", b); assertFile(true, "buildone.txt", b); assertFile(false, "subdir/subfoo.txt", b); } // Verify build fails if given build# does not match params public void testSpecificBuildSelectorWithParameterFilter() throws Exception { FreeStyleProject other = createArtifactProject(), p = createFreeStyleProject(); other.addProperty(new ParametersDefinitionProperty(new StringParameterDefinition("FOO", ""))); addBuilder(p, new CopyArtifact(other.getName() + "/FOO=bogus", new SpecificBuildSelector("1"), "*.txt", "", false, false)); assertBuildStatusSuccess(other .scheduleBuild2(0, new UserCause(), new ParametersAction(new StringParameterValue("FOO", "foo"))) .get()); assertBuildStatusSuccess(other.scheduleBuild2(0, new UserCause())); FreeStyleBuild b = p.scheduleBuild2(0, new UserCause()).get(); assertBuildStatus(Result.FAILURE, b); assertFile(false, "foo.txt", b); } // Verify BuildSelector defaults to false public void testBuildSelectorDefault() { assertFalse(new BuildSelector() { }.isSelectable(null, null)); } // Test field getters public void testFields() throws Exception { FreeStyleProject p = createFreeStyleProject(); CopyArtifact ca = new CopyArtifact(p.getFullName(), new SavedBuildSelector(), "filter", "target", false, true); assertEquals(p.getFullName(), ca.getProjectName()); assertSame(SavedBuildSelector.class, ca.getBuildSelector().getClass()); assertEquals("filter", ca.getFilter()); assertEquals("target", ca.getTarget()); assertFalse(ca.isFlatten()); assertTrue(ca.isOptional()); ca = new CopyArtifact("foo", null, null, null, true, false); assertTrue(ca.isFlatten()); assertFalse(ca.isOptional()); } public void testFieldValidation() throws Exception { FreeStyleProject p = createFreeStyleProject(); CopyArtifact.DescriptorImpl descriptor = hudson.getDescriptorByType(CopyArtifact.DescriptorImpl.class); assertNotNull(descriptor); // Valid value assertSame(FormValidation.Kind.OK, descriptor.doCheckProjectName(p, p.getFullName()).kind); // Empty value assertSame(FormValidation.Kind.ERROR, descriptor.doCheckProjectName(p, "").kind); // Parameterized value assertSame(FormValidation.Kind.WARNING, descriptor.doCheckProjectName(p, "$FOO").kind); // Filter p.scheduleBuild2(0, new UserCause()).get(); assertSame(FormValidation.Kind.OK, descriptor.doCheckProjectName(p, p.getFullName() + "/BUILD_NUMBER=1").kind); // Filter with invalid param assertSame(FormValidation.Kind.ERROR, descriptor.doCheckProjectName(p, p.getFullName() + "/FOO=1").kind); // Unparseable filter assertSame(FormValidation.Kind.ERROR, descriptor.doCheckProjectName(p, p.getFullName() + "/FOO-1").kind); // Just returns OK if no permission hudson.setAuthorizationStrategy(new GlobalMatrixAuthorizationStrategy()); SecurityContextHolder.clearContext(); assertSame(FormValidation.Kind.OK, descriptor.doCheckProjectName(p, "").kind); // Other descriptor methods assertTrue(descriptor.isApplicable(null)); assertTrue(descriptor.getDisplayName().length() > 0); assertTrue(descriptor.getBuildSelectors().size() > 0); } }