package hudson.plugins.promoted_builds;
import hudson.AbortException;
import hudson.FilePath;
import hudson.Launcher;
import hudson.model.AbstractBuild;
import hudson.model.BuildListener;
import hudson.model.Descriptor;
import hudson.model.FreeStyleBuild;
import hudson.model.FreeStyleProject;
import hudson.model.Job;
import hudson.model.Result;
import hudson.plugins.promoted_builds.conditions.DownstreamPassCondition;
import hudson.tasks.ArtifactArchiver;
import hudson.tasks.Fingerprinter;
import hudson.tasks.Recorder;
import org.jvnet.hudson.test.HudsonTestCase;
import org.jvnet.hudson.test.TestBuilder;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import static hudson.plugins.promoted_builds.util.ItemListenerHelper.fireItemListeners;
public class KeepBuildForeverActionTest extends HudsonTestCase {
public void testCanMarkBuildKeepForever() throws Exception {
FreeStyleProject upJob = createProject("up");
upJob.getBuildersList().add(successfulBuilder());
FreeStyleProject downJob = createProject("down");
downJob.getBuildersList().add(successfulBuilder());
PromotionProcess promotionJob = createDownstreamSuccessPromotion(upJob, downJob);
promotionJob.getBuildSteps().add(new KeepBuildForeverAction());
// fire ItemListeners, this includes ArtifactArchiver,Migrator to make this test compatible with jenkins 1.575+
fireItemListeners();
FreeStyleBuild upBuild = assertBuildStatusSuccess(upJob.scheduleBuild2(0).get());
assertFalse(upBuild.isKeepLog());
assertBuildStatusSuccess(downJob.scheduleBuild2(0).get());
waitForBuild(promotionJob, 1);
assertTrue(upBuild.isKeepLog());
}
public void testDoesNotMarkBuildIfPromotionNotGoodEnough() throws Exception {
FreeStyleProject upJob = createProject("up");
upJob.getBuildersList().add(successfulBuilder());
FreeStyleProject downJob = createProject("down");
downJob.getBuildersList().add(successfulBuilder());
PromotionProcess promotionJob = createDownstreamSuccessPromotion(upJob, downJob);
promotionJob.getBuildSteps().add(new FixedResultBuilder(Result.FAILURE));
promotionJob.getBuildSteps().add(new KeepBuildForeverAction());
// fire ItemListeners, this includes ArtifactArchiver,Migrator to make this test compatible with jenkins 1.575+
fireItemListeners();
FreeStyleBuild upBuild = assertBuildStatusSuccess(upJob.scheduleBuild2(0).get());
assertFalse(upBuild.isKeepLog());
assertBuildStatusSuccess(downJob.scheduleBuild2(0).get());
waitForBuild(promotionJob, 1);
assertFalse(upBuild.isKeepLog());
}
public void testDoesNotCareAboutResultOfOriginalBuild() throws Exception {
FreeStyleProject upJob = createProject("up");
upJob.getBuildersList().add(new FixedResultBuilder(Result.FAILURE));
FreeStyleProject downJob = createProject("down");
downJob.getBuildersList().add(successfulBuilder());
PromotionProcess promotionJob = createDownstreamSuccessPromotion(upJob, downJob);
promotionJob.getBuildSteps().add(new KeepBuildForeverAction());
// fire ItemListeners, this includes ArtifactArchiver,Migrator to make this test compatible with jenkins 1.575+
fireItemListeners();
FreeStyleBuild upBuild = assertBuildStatus(Result.FAILURE, upJob.scheduleBuild2(0).get());
assertFalse(upBuild.isKeepLog());
assertBuildStatusSuccess(downJob.scheduleBuild2(0).get());
waitForBuild(promotionJob, 1);
assertTrue(upBuild.isKeepLog());
}
public void testDoesNotMarkBuildIfBuildNotPromotion() throws Exception {
FreeStyleProject job = createProject("job");
job.getBuildersList().add(successfulBuilder());
job.getPublishersList().add(new KeepBuildForeverAction());
// fire ItemListeners, this includes ArtifactArchiver,Migrator to make this test compatible with jenkins 1.575+
fireItemListeners();
FreeStyleBuild build = assertBuildStatus(Result.FAILURE, job.scheduleBuild2(0).get());
assertFalse(build.isKeepLog());
}
private void waitForBuild(final Job job, final int buildNumber) throws Exception {
waitFor(new WaitCondition() {
public boolean isMet() {
return (job.getBuildByNumber(buildNumber) != null) && !job.getBuildByNumber(buildNumber).isBuilding();
}
}, 2000);
}
private void waitFor(final WaitCondition condition, long timeout) throws Exception {
Thread waiter = new Thread() {
public void run() {
try {
while (!condition.isMet()) {
Thread.sleep(100);
}
} catch (InterruptedException ie) { }
}
};
waiter.start();
waiter.join(timeout);
if (waiter.isAlive()) {
waiter.interrupt();
}
if (!condition.isMet())
fail("Condition not met");
}
private PromotionProcess createDownstreamSuccessPromotion(FreeStyleProject upStream, FreeStyleProject downStream)
throws Descriptor.FormException, IOException {
JobPropertyImpl promotionProperty = new JobPropertyImpl(upStream);
upStream.addProperty(promotionProperty);
PromotionProcess promotionJob = promotionProperty.addProcess("promotion");
promotionJob.conditions.add(new DownstreamPassCondition(downStream.getName()));
return promotionJob;
}
private FreeStyleProject createProject(String name) throws Exception {
FreeStyleProject project = createFreeStyleProject(name);
project.getPublishersList().replaceBy(createFingerprinters());
return project;
}
private List<Recorder> createFingerprinters() {
return Arrays.asList(
new ArtifactArchiver("*", null, false),
new Fingerprinter("", true)
);
}
private FixedResultBuilder successfulBuilder() {
return new FixedResultBuilder(Result.SUCCESS);
}
public interface WaitCondition {
boolean isMet();
}
public static class FixedResultBuilder extends TestBuilder {
private Result buildResult;
FixedResultBuilder(Result buildResult) {
this.buildResult = buildResult;
}
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener)
throws InterruptedException, IOException {
FilePath workspace = build.getWorkspace();
if (workspace == null) {
throw new AbortException("Workspace is null in " + FixedResultBuilder.class.getName());
}
workspace.child("my.file").write("Hello world!", "UTF-8");
build.setResult(buildResult);
return true;
}
}
}