package hudson.plugins.promoted_builds; import hudson.model.FreeStyleProject; import hudson.model.Items; import hudson.model.ParameterDefinition; import hudson.model.ParametersDefinitionProperty; import hudson.model.Result; import hudson.model.StringParameterDefinition; import hudson.model.FreeStyleBuild; import hudson.plugins.promoted_builds.conditions.SelfPromotionCondition; import hudson.tasks.ArtifactArchiver; import hudson.tasks.BuildTrigger; import hudson.tasks.Fingerprinter; import hudson.tasks.Recorder; import hudson.tasks.Shell; import hudson.plugins.promoted_builds.conditions.DownstreamPassCondition; import net.sf.json.JSONObject; import org.jvnet.hudson.test.HudsonTestCase; import org.kohsuke.stapler.Stapler; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.Callable; import static hudson.plugins.promoted_builds.util.ItemListenerHelper.fireItemListeners; /** * @author Kohsuke Kawaguchi */ public class PromotionProcessTest extends HudsonTestCase { public void test1() throws Exception { FreeStyleProject up = createFreeStyleProject("up"); FreeStyleProject down = createFreeStyleProject(); List<Recorder> recorders = Arrays.asList( new ArtifactArchiver("a.jar", null, false), new Fingerprinter("", true)); // upstream job up.getBuildersList().add(new Shell("date > a.jar")); up.getPublishersList().replaceBy(recorders); // promote if the downstream passes JobPropertyImpl promotion = new JobPropertyImpl(up); up.addProperty(promotion); PromotionProcess proc = promotion.addProcess("promo"); proc.conditions.add(new DownstreamPassCondition(down.getName())); // this is the test job String baseUrl = new WebClient().getContextPath() + "job/up/lastSuccessfulBuild"; down.getBuildersList().add(new Shell( "wget -N "+baseUrl+"/artifact/a.jar \\\n"+ " || curl "+baseUrl+"/artifact/a.jar > a.jar\n"+ "expr $BUILD_NUMBER % 2 - 1\n" // expr exits with non-zero status if result is zero )); down.getPublishersList().replaceBy(recorders); // fire ItemListeners, this includes ArtifactArchiver,Migrator to make this test compatible with jenkins 1.575+ fireItemListeners(); // not yet promoted while the downstream is failing FreeStyleBuild up1 = assertBuildStatusSuccess(up.scheduleBuild2(0).get()); assertBuildStatus(Result.FAILURE,down.scheduleBuild2(0).get()); Thread.sleep(1000); // give it a time to not promote assertEquals(0,proc.getBuilds().size()); // a successful downstream build promotes upstream assertBuildStatusSuccess(down.scheduleBuild2(0).get()); Thread.sleep(1000); // give it a time to promote assertEquals(1,proc.getBuilds().size()); {// verify that it promoted the right stuff Promotion pb = proc.getBuilds().get(0); assertSame(pb.getTarget(),up1); PromotedBuildAction badge = (PromotedBuildAction) up1.getBadgeActions().get(0); assertTrue(badge.contains(proc)); } // make sure the UI persists the setup configRoundtrip(up); } /** * Tests a promotion induced by the pseudo upstream/downstream cause relationship */ public void testPromotionWithoutFingerprint() throws Exception { FreeStyleProject up = createFreeStyleProject("up"); FreeStyleProject down = createFreeStyleProject(); // promote if the downstream passes JobPropertyImpl promotion = new JobPropertyImpl(up); up.addProperty(promotion); PromotionProcess proc = promotion.addProcess("promo"); proc.conditions.add(new DownstreamPassCondition(down.getName())); // trigger downstream automatically to create relationship up.getPublishersList().add(new BuildTrigger(down.getName(), Result.SUCCESS)); hudson.rebuildDependencyGraph(); // this is the downstream job down.getBuildersList().add(new Shell( "expr $BUILD_NUMBER % 2 - 1\n" // expr exits with non-zero status if result is zero )); // not yet promoted while the downstream is failing FreeStyleBuild up1 = assertBuildStatusSuccess(up.scheduleBuild2(0).get()); waitForCompletion(down,1); assertEquals(0,proc.getBuilds().size()); // do it one more time and this time it should work FreeStyleBuild up2 = assertBuildStatusSuccess(up.scheduleBuild2(0).get()); waitForCompletion(down,2); assertEquals(1,proc.getBuilds().size()); {// verify that it promoted the right stuff Promotion pb = proc.getBuilds().get(0); assertSame(pb.getTarget(),up2); PromotedBuildAction badge = (PromotedBuildAction) up2.getBadgeActions().get(0); assertTrue(badge.contains(proc)); } } private void waitForCompletion(FreeStyleProject down, int n) throws Exception { // wait for the build completion while (down.getBuildByNumber(n)==null) Thread.sleep(100); waitUntilNoActivity(); assertFalse(down.getBuildByNumber(n).isBuilding()); } public void testCaptureXml() throws Exception { executeOnServer(new Callable<Object>() { public Object call() throws Exception { JSONObject o = new JSONObject() .accumulate("name", "foo") .accumulate("isVisible", "") .accumulate("icon", "star-gold") .accumulate("conditions",new JSONObject() .accumulate("hudson-plugins-promoted_builds-conditions-SelfPromotionCondition", new JSONObject().accumulate("evenIfUnstable", false))); PromotionProcess p = PromotionProcess.fromJson(Stapler.getCurrentRequest(), o); assertEquals("foo", p.getName()); assertEquals("star-gold", p.getIcon()); assertEquals(1, p.conditions.size()); assertNotNull(p.conditions.get(SelfPromotionCondition.class)); System.out.println(Items.XSTREAM2.toXML(p)); return null; } }); } public void testIsVisibleByDefault() throws Exception { FreeStyleProject project = createFreeStyleProject("project"); JobPropertyImpl jobProperty = new JobPropertyImpl(project); project.addProperty(jobProperty); PromotionProcess promotionProcess = jobProperty.addProcess( "Promotion"); assertTrue(promotionProcess.isVisible()); } public void testIsVisibleFalseReturnsNotVisible() throws Exception{ FreeStyleProject project = createFreeStyleProject("project"); JobPropertyImpl jobProperty = new JobPropertyImpl(project); project.addProperty(jobProperty); PromotionProcess promotionProcess = jobProperty.addProcess( "Promotion"); promotionProcess.isVisible = "false"; assertFalse(promotionProcess.isVisible()); } public void testIsVisibleTrueReturnsVisible() throws Exception{ FreeStyleProject project = createFreeStyleProject("project"); JobPropertyImpl jobProperty = new JobPropertyImpl(project); project.addProperty(jobProperty); PromotionProcess promotionProcess = jobProperty.addProcess( "Promotion"); promotionProcess.isVisible = "true"; assertTrue(promotionProcess.isVisible()); } public void testIsVisibleResolvesDefaultParameterValue() throws Exception{ FreeStyleProject project = createFreeStyleProject("project"); final List<ParameterDefinition> parameters = new ArrayList<ParameterDefinition>(); ParametersDefinitionProperty parametersProperty = new ParametersDefinitionProperty(parameters); parameters.add(new StringParameterDefinition("Visibility", "false")); project.addProperty(parametersProperty); JobPropertyImpl jobProperty = new JobPropertyImpl(project); project.addProperty(jobProperty); PromotionProcess promotionProcess = jobProperty.addProcess( "Promotion"); promotionProcess.isVisible = "${Visibility}"; assertFalse(promotionProcess.isVisible()); } public void testIsVisibleResolvesDefaultParameterValueIndirectly() throws Exception{ FreeStyleProject project = createFreeStyleProject("project"); final List<ParameterDefinition> parameters = new ArrayList<ParameterDefinition>(); ParametersDefinitionProperty parametersProperty = new ParametersDefinitionProperty(parameters); parameters.add(new StringParameterDefinition("IndirectVisibility", "false")); parameters.add(new StringParameterDefinition("Visibility", "${IndirectVisibility}")); project.addProperty(parametersProperty); JobPropertyImpl jobProperty = new JobPropertyImpl(project); project.addProperty(jobProperty); PromotionProcess promotionProcess = jobProperty.addProcess( "Promotion"); promotionProcess.isVisible = "${Visibility}"; assertFalse(promotionProcess.isVisible()); } }