/* * The MIT License * * Copyright (c) 2010, 2014 Sony Mobile Communications Inc. All rights reserved. * * 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 com.sonyericsson.hudson.plugins.gerrit.trigger.spec; import com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.data.BuildCancellationPolicy; import com.sonymobile.tools.gerrit.gerritevents.dto.events.CommentAdded; import com.sonymobile.tools.gerrit.gerritevents.dto.events.PatchsetCreated; import com.sonyericsson.hudson.plugins.gerrit.trigger.GerritServer; import com.sonyericsson.hudson.plugins.gerrit.trigger.PluginImpl; import com.sonyericsson.hudson.plugins.gerrit.trigger.config.Config; import com.sonyericsson.hudson.plugins.gerrit.trigger.events.ManualPatchsetCreated; import com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.GerritCause; import com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.GerritTrigger; import com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.data.GerritProject; import com.sonyericsson.hudson.plugins.gerrit.trigger.mock.DuplicatesUtil; import com.sonyericsson.hudson.plugins.gerrit.trigger.mock.Setup; import com.sonyericsson.hudson.plugins.gerrit.trigger.mock.TestUtils; import com.sonymobile.tools.gerrit.gerritevents.mock.SshdServerMock; import hudson.model.Cause; import hudson.model.FreeStyleBuild; import hudson.model.FreeStyleProject; import hudson.model.Result; import hudson.model.Run; import hudson.model.TopLevelItem; import org.apache.sshd.SshServer; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.SleepBuilder; import org.jvnet.hudson.test.recipes.LocalData; import java.util.Arrays; import java.util.List; import java.util.Random; import java.util.concurrent.atomic.AtomicReference; import static com.sonymobile.tools.gerrit.gerritevents.mock.SshdServerMock.GERRIT_STREAM_EVENTS; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.fail; //CS IGNORE MagicNumber FOR NEXT 700 LINES. REASON: Testdata. /** * Some full run-through tests from trigger to build finished. * * @author Robert Sandell <robert.sandell@sonyericsson.com> */ public class SpecGerritTriggerHudsonTest { /** * An instance of Jenkins Rule. */ // CS IGNORE VisibilityModifier FOR NEXT 2 LINES. REASON: JenkinsRule. @Rule public final JenkinsRule j = new JenkinsRule(); //TODO Fix the SshdServerMock so that asserts can be done on review commands. private SshServer sshd; private SshdServerMock.KeyPairFiles sshKey; private SshdServerMock serverMock; private GerritServer gerritServer; /** * Runs before test method. * * @throws Exception throw if so. */ @Before public void setUp() throws Exception { sshKey = SshdServerMock.generateKeyPair(); serverMock = new SshdServerMock(); sshd = SshdServerMock.startServer(serverMock); serverMock.returnCommandFor("gerrit ls-projects", SshdServerMock.EofCommandMock.class); serverMock.returnCommandFor(GERRIT_STREAM_EVENTS, SshdServerMock.CommandMock.class); serverMock.returnCommandFor("gerrit review.*", SshdServerMock.EofCommandMock.class); serverMock.returnCommandFor("gerrit approve.*", SshdServerMock.EofCommandMock.class); serverMock.returnCommandFor("gerrit version", SshdServerMock.SendVersionCommand.class); serverMock.returnCommandFor("gerrit approve.*", SshdServerMock.EofCommandMock.class); System.setProperty(PluginImpl.TEST_SSH_KEYFILE_LOCATION_PROPERTY, sshKey.getPrivateKey().getAbsolutePath()); gerritServer = PluginImpl.getFirstServer_(); SshdServerMock.configureFor(sshd, gerritServer, true); } /** * Runs after test method. * * @throws Exception throw if so. */ @After public void tearDown() throws Exception { sshd.stop(true); sshd = null; } /** * Tests that a triggered build in silent start mode does not emit any build started messages. * @throws Exception if so. */ @Test @LocalData public void testTriggeredSilentStartModeBuild() throws Exception { FreeStyleProject project = new TestUtils.JobBuilder(j).silentStartMode(true).build(); serverMock.waitForCommand(GERRIT_STREAM_EVENTS, 2000); gerritServer.triggerEvent(Setup.createPatchsetCreated()); TestUtils.waitForBuilds(project, 1, 20000); List<SshdServerMock.CommandMock> commands = serverMock.getCommandHistory(); for (int i = 0; i < commands.size(); i++) { String command = commands.get(i).getCommand(); assertFalse(command.toLowerCase().contains("build started")); } } /** * Tests that a triggered build without silent start mode does emit build started messages. * @throws Exception if so. */ @Test @LocalData public void testTriggeredNoSilentStartModeBuild() throws Exception { FreeStyleProject project = new TestUtils.JobBuilder(j).name("projectX").silentStartMode(false).build(); serverMock.waitForCommand(GERRIT_STREAM_EVENTS, 2000); gerritServer.triggerEvent(Setup.createPatchsetCreated()); TestUtils.waitForBuilds(project, 1, 20000); try { serverMock.waitForNrCommands("Build Started", 1, 5000); } catch (Exception e) { System.out.println(e.getClass().getName() + ": " + e.getMessage()); e.printStackTrace(); fail("Should not throw exception."); } } /** * Trigger several builds and test that the one in silent start mode does not emit any build started messages * while the ones without silent start mode does. * @throws Exception if so. */ @Test @LocalData public void testTriggeredSilentStartModeMixedBuild() throws Exception { gerritServer.getConfig().setNumberOfSendingWorkerThreads(3); final int nrOfJobs = 3; FreeStyleProject project = DuplicatesUtil.createGerritTriggeredJob(j, "projectX"); project.getBuildersList().add(new SleepBuilder(1000)); project.save(); int nrOfSilentStartJobs = 0; for (int i = 0; i < nrOfJobs; i++) { String name = String.format("project%d", i); FreeStyleProject copyProject = (FreeStyleProject)j.jenkins.copy((TopLevelItem)project, name); boolean mode = (i & 1) == 0; // true for even numbers copyProject.getTrigger(GerritTrigger.class).setSilentStartMode(mode); if (mode) { nrOfSilentStartJobs++; } copyProject.save(); } assertEquals("Wrong number of jobs", nrOfJobs + 1, j.jenkins.getAllItems().size()); serverMock.waitForCommand(GERRIT_STREAM_EVENTS, 2000); gerritServer.triggerEvent(Setup.createPatchsetCreated()); int expectedBuildStarted = nrOfJobs + 1 - nrOfSilentStartJobs; System.out.println("Expected nr of start commands: " + expectedBuildStarted); serverMock.waitForNrCommands("Build Started", expectedBuildStarted, nrOfJobs * 5000); j.waitUntilNoActivity(); for (FreeStyleProject fp : j.jenkins.getAllItems(FreeStyleProject.class)) { assertEquals(1, fp.getLastBuild().getNumber()); } StringBuilder cmdSearch = new StringBuilder("Build Successful[\\s\\S]+projectX/1/[\\s\\S]+SUCCESS[\\s\\S]+"); for (int i = 0; i < nrOfJobs; i++) { cmdSearch.append("project" + i + "/1/[\\s\\S]+SUCCESS[\\s\\S]+"); } System.out.println("Waiting for: " + cmdSearch); serverMock.waitForNrCommands(cmdSearch.toString(), 1, 5000); } /** * Tests to trigger a build with a dynamic plain branch configuration. * @throws Exception if so. */ @Test @LocalData public void testDynamicTriggeredBuildWithPlainBranch() throws Exception { testDynamicTriggeredBuild("=branch"); } /** * Tests to trigger a build with a dynamic ant branch configuration. * @throws Exception if so. */ @Test @LocalData public void testDynamicTriggeredBuildWithAntBranch() throws Exception { testDynamicTriggeredBuild("^**"); } /** * Tests to trigger a build with a dynamic configuration. * @param branchSetting the dynamic branch setting with operator e.g. "^**" or "=branch" * * @throws Exception if so. */ private void testDynamicTriggeredBuild(String branchSetting) throws Exception { ((Config)gerritServer.getConfig()).setDynamicConfigRefreshInterval(1); FreeStyleProject project = DuplicatesUtil.createGerritDynamicTriggeredJob(j, "projectX", branchSetting); serverMock.waitForCommand(GERRIT_STREAM_EVENTS, 2000); waitForDynamicTimer(project, 8000); gerritServer.triggerEvent(Setup.createPatchsetCreated()); TestUtils.waitForBuilds(project, 1); FreeStyleBuild build = project.getLastCompletedBuild(); assertSame(Result.SUCCESS, build.getResult()); } /** * Tests to trigger a build with the same patch set twice. Expecting one build to be scheduled with one cause. * * @throws Exception if so. */ @Test @LocalData public void testDoubleTriggeredBuild() throws Exception { FreeStyleProject project = DuplicatesUtil.createGerritTriggeredJob(j, "projectX"); project.getBuildersList().add(new SleepBuilder(5000)); serverMock.waitForCommand(GERRIT_STREAM_EVENTS, 2000); boolean started = false; gerritServer.triggerEvent(Setup.createPatchsetCreated()); while (!started) { if (project.isBuilding()) { started = true; } Thread.sleep(1000); } gerritServer.triggerEvent(Setup.createPatchsetCreated()); while (project.isBuilding() || project.isInQueue()) { Thread.sleep(1000); } int size = 0; for (FreeStyleBuild build : project.getBuilds()) { assertSame(Result.SUCCESS, build.getResult()); int count = 0; for (Cause cause : build.getCauses()) { if (cause instanceof GerritCause) { count++; assertNotNull(((GerritCause)cause).getContext()); assertNotNull(((GerritCause)cause).getEvent()); } } assertEquals(1, count); size++; } assertEquals(1, size); } /** * Tests to trigger a build from a project with the same patch set twice. * Expecting one build to be scheduled with one cause. * And builds are not triggered if build is not building but other builds triggered by a event is building. * * @throws Exception if so. */ @Test @LocalData public void testDoubleTriggeredBuildWithProjects() throws Exception { FreeStyleProject project1 = DuplicatesUtil.createGerritTriggeredJob(j, "projectX"); FreeStyleProject project2 = DuplicatesUtil.createGerritTriggeredJob(j, "projectY"); project1.getBuildersList().add(new SleepBuilder(5000)); serverMock.waitForCommand(GERRIT_STREAM_EVENTS, 2000); boolean started = false; gerritServer.triggerEvent(Setup.createPatchsetCreated()); while (!started) { if (project1.isBuilding()) { started = true; } Thread.sleep(1000); } gerritServer.triggerEvent(Setup.createPatchsetCreated()); while (project1.isBuilding() || project1.isInQueue()) { Thread.sleep(1000); } int size = 0; for (FreeStyleProject project : Arrays.asList(project1, project2)) { for (FreeStyleBuild build : project.getBuilds()) { assertSame(Result.SUCCESS, build.getResult()); int count = 0; for (Cause cause : build.getCauses()) { if (cause instanceof GerritCause) { count++; assertNotNull(((GerritCause)cause).getContext()); assertNotNull(((GerritCause)cause).getEvent()); } } assertEquals(1, count); size++; } } assertEquals(2, size); } /** * Tests to trigger builds with two different patch sets. Expecting two build to be scheduled with one cause each. * * @throws Exception if so. */ @Test @LocalData public void testDoubleTriggeredBuildsOfDifferentChange() throws Exception { FreeStyleProject project = DuplicatesUtil.createGerritTriggeredJob(j, "projectX"); project.getBuildersList().add(new SleepBuilder(5000)); serverMock.waitForCommand(GERRIT_STREAM_EVENTS, 2000); boolean started = false; gerritServer.triggerEvent(Setup.createPatchsetCreated()); while (!started) { if (project.isBuilding()) { started = true; } Thread.sleep(1000); } PatchsetCreated patchsetCreated = Setup.createPatchsetCreated(); patchsetCreated.getChange().setNumber("2000"); gerritServer.triggerEvent(patchsetCreated); while (project.isBuilding() || project.isInQueue()) { Thread.sleep(1000); } int size = 0; for (FreeStyleBuild build : project.getBuilds()) { assertSame(Result.SUCCESS, build.getResult()); int count = 0; for (Cause cause : build.getCauses()) { if (cause instanceof GerritCause) { count++; assertNotNull(((GerritCause)cause).getContext()); assertNotNull(((GerritCause)cause).getEvent()); } } assertEquals(1, count); size++; } assertEquals(2, size); } /** * Tests to trigger a build from a project with the same patch set twice. * Expecting one build to be scheduled with one cause. * And builds are not triggered if build is not building but other builds triggered by a event is building. * * @throws Exception if so. */ @Test @LocalData public void testTripleTriggeredBuildWithProjects() throws Exception { FreeStyleProject project1 = DuplicatesUtil.createGerritTriggeredJob(j, "projectX"); FreeStyleProject project2 = DuplicatesUtil.createGerritTriggeredJob(j, "projectY"); project1.getBuildersList().add(new SleepBuilder(5000)); serverMock.waitForCommand(GERRIT_STREAM_EVENTS, 2000); boolean started = false; gerritServer.triggerEvent(Setup.createPatchsetCreated()); while (!started) { if (project1.isBuilding()) { started = true; } else { Thread.sleep(1000); } } gerritServer.triggerEvent(Setup.createPatchsetCreated()); while (project1.isBuilding() || project1.isInQueue()) { Thread.sleep(1000); } started = false; gerritServer.triggerEvent(Setup.createPatchsetCreated()); while (!started) { if (project1.isBuilding()) { started = true; } else { Thread.sleep(1000); } } while (project1.isBuilding() || project1.isInQueue()) { Thread.sleep(1000); } int size = 0; for (FreeStyleProject project : Arrays.asList(project1, project2)) { for (FreeStyleBuild build : project.getBuilds()) { assertSame(Result.SUCCESS, build.getResult()); int count = 0; for (Cause cause : build.getCauses()) { if (cause instanceof GerritCause) { count++; assertNotNull(((GerritCause)cause).getContext()); assertNotNull(((GerritCause)cause).getEvent()); } } assertEquals(1, count); size++; } } assertEquals(4, size); } /** * Tests the behavior of the "Build Current Patches Only" functionality when: * - Abort manual patch sets is true. * - Abort new patch sets is false. * * @throws Exception if so. */ @Test @LocalData public void testBuildLatestPatchsetOnlyAbortManual() throws Exception { buildLatestPatchsetOnlyAndReport(true, false, Result.ABORTED, Result.SUCCESS, Result.SUCCESS); } /** * Tests the behavior of the "Build Current Patches Only" functionality when: * - Abort manual patch sets is true. * - Abort new patch sets is true. * * @throws Exception if so. */ @Test @LocalData public void testBuildLatestPatchsetOnlyAbortManualAndNew() throws Exception { buildLatestPatchsetOnlyAndReport(true, true, Result.ABORTED, Result.ABORTED, Result.SUCCESS); } /** * Tests the behavior of the "Build Current Patches Only" functionality when: * - Abort manual patch sets is false. * - Abort new patch sets is false. * * @throws Exception if so. */ @Test @LocalData public void testBuildLatestPatchsetOnlyAbortNeitherManualNorNew() throws Exception { buildLatestPatchsetOnlyAndReport(false, false, Result.SUCCESS, Result.SUCCESS, Result.SUCCESS); } /** * Tests the behavior of the "Build Current Patches Only" functionality when: * - Abort manual patch sets is false. * - Abort new patch sets is true. * * @throws Exception if so. */ @Test @LocalData public void testBuildLatestPatchsetOnlyAbortNew() throws Exception { buildLatestPatchsetOnlyAndReport(false, true, Result.SUCCESS, Result.ABORTED, Result.SUCCESS); } /** * Test the behaviour of "Build Current Patches Only" functionality when: * - Abort manual patch sets is false. * - Abort new patch sets is true. * - 2 changes with different branches trigger builds. * * @throws Exception if so. */ @Test @LocalData public void testBuildLatestPatchsetOnlyNonRelatedChangeCannotAbort() throws Exception { BuildCancellationPolicy policy = gerritServer.getConfig().getBuildCurrentPatchesOnly(); policy.setEnabled(true); policy.setAbortManualPatchsets(false); policy.setAbortNewPatchsets(false); Random rand = new Random(); FreeStyleProject project = DuplicatesUtil.createGerritTriggeredJob(j, "project" + rand.nextInt()); project.getBuildersList().add(new SleepBuilder(2000)); serverMock.waitForCommand(GERRIT_STREAM_EVENTS, 2000); PatchsetCreated firstEvent = Setup.createPatchsetCreated(PluginImpl.DEFAULT_SERVER_NAME, "gerrit-project-1", "refabc"); gerritServer.triggerEvent(firstEvent); PatchsetCreated secondEvent = Setup.createPatchsetCreated(PluginImpl.DEFAULT_SERVER_NAME, "gerrit-project-2", "refabc"); gerritServer.triggerEvent(secondEvent); TestUtils.waitForBuilds(project, 2); //both should succeed since gerrit project not the same assertEquals(Result.SUCCESS, project.getFirstBuild().getResult()); assertEquals(Result.SUCCESS, project.getBuildByNumber(2).getResult()); } /** * Test the behaviour of "Build Current Patches Only" functionality when: * - Abort manual patch sets is false. * - Abort new patch sets is false. * - 2 changes with same gerrit project BUT different branches trigger builds. * * @throws Exception if so. */ @Test @LocalData public void testBuildLatestPatchsetOnlyNonRelatedChangeDifferentBranchCannotAbort() throws Exception { BuildCancellationPolicy policy = gerritServer.getConfig().getBuildCurrentPatchesOnly(); policy.setEnabled(true); policy.setAbortManualPatchsets(false); policy.setAbortNewPatchsets(false); Random rand = new Random(); FreeStyleProject project = DuplicatesUtil.createGerritTriggeredJob(j, "project" + rand.nextInt()); project.getBuildersList().add(new SleepBuilder(2000)); GerritTrigger trigger = project.getTrigger(GerritTrigger.class); trigger.setSilentMode(true); serverMock.waitForCommand(GERRIT_STREAM_EVENTS, 2000); PatchsetCreated firstEvent = Setup.createPatchsetCreated(); firstEvent.getChange().setBranch("abc"); gerritServer.triggerEvent(firstEvent); Thread.sleep(1000); PatchsetCreated secondEvent = Setup.createPatchsetCreated(); secondEvent.getPatchSet().setNumber("2"); secondEvent.getChange().setBranch("def"); gerritServer.triggerEvent(secondEvent); TestUtils.waitForBuilds(project, 2); //both should succeed since branches not the same assertEquals(Result.SUCCESS, project.getFirstBuild().getResult()); assertEquals(Result.SUCCESS, project.getBuildByNumber(2).getResult()); } /** * Helper method to test the behavior of the "Build Current Patches Only" functionality. * Parameterized so that the different combinations can be tested. * @param abortManual true if manual patchsets should be cancelled and be able to cancel builds, false if not. * @param abortNew true if new patchsets should be cancelled when older patchsets are retriggered, false if not. * @param firstExpected expected result for the first build. * @param secondExpected expected result for the second build. * @param thirdExpected expected result for the third build * * @throws Exception if so. */ public void buildLatestPatchsetOnlyAndReport(boolean abortManual, boolean abortNew, Result firstExpected, Result secondExpected, Result thirdExpected) throws Exception { BuildCancellationPolicy policy = gerritServer.getConfig().getBuildCurrentPatchesOnly(); policy.setEnabled(true); policy.setAbortManualPatchsets(abortManual); policy.setAbortNewPatchsets(abortNew); Random rand = new Random(); FreeStyleProject project = DuplicatesUtil.createGerritTriggeredJob(j, "project" + rand.nextInt()); project.getBuildersList().add(new SleepBuilder(2000)); serverMock.waitForCommand(GERRIT_STREAM_EVENTS, 2000); ManualPatchsetCreated firstEvent = Setup.createManualPatchsetCreated(); firstEvent.getPatchSet().setNumber("1"); AtomicReference<Run> firstBuildRef = TestUtils.getFutureBuildToStart(firstEvent); gerritServer.triggerEvent(firstEvent); TestUtils.waitForBuildToStart(firstBuildRef); PatchsetCreated secondEvent = Setup.createPatchsetCreated(); if (null != secondEvent.getPatchSet()) { secondEvent.getPatchSet().setNumber("3"); } gerritServer.triggerEvent(secondEvent); TestUtils.waitForNonManualBuildToStart(project, secondEvent, 10000); PatchsetCreated thirdEvent = Setup.createPatchsetCreated(); if (null != thirdEvent.getPatchSet()) { thirdEvent.getPatchSet().setNumber("2"); } gerritServer.triggerEvent(thirdEvent); TestUtils.waitForBuilds(project, 3); assertEquals(3, project.getLastCompletedBuild().getNumber()); assertSame(firstExpected, project.getFirstBuild().getResult()); assertSame(secondExpected, project.getBuildByNumber(2).getResult()); assertSame(thirdExpected, project.getBuildByNumber(3).getResult()); } /** * Tests that builds are not aborted when "build current patch sets only" is set to false. * * @throws Exception if so. */ @Test @LocalData public void testNotBuildLatestPatchsetOnly() throws Exception { gerritServer.getConfig().getBuildCurrentPatchesOnly().setEnabled(false); FreeStyleProject project = DuplicatesUtil.createGerritTriggeredJob(j, "projectX"); project.getBuildersList().add(new SleepBuilder(2000)); serverMock.waitForCommand(GERRIT_STREAM_EVENTS, 2000); ManualPatchsetCreated firstEvent = Setup.createManualPatchsetCreated(); AtomicReference<Run> firstBuildRef = TestUtils.getFutureBuildToStart(firstEvent); gerritServer.triggerEvent(firstEvent); Run firstBuild = TestUtils.waitForBuildToStart(firstBuildRef); PatchsetCreated secondEvent = Setup.createPatchsetCreated(); if (null != secondEvent.getPatchSet()) { secondEvent.getPatchSet().setNumber("2"); } gerritServer.triggerEvent(secondEvent); TestUtils.waitForBuilds(project, 2); assertEquals(2, project.getLastCompletedBuild().getNumber()); assertSame(Result.SUCCESS, firstBuild.getResult()); assertSame(Result.SUCCESS, project.getFirstBuild().getResult()); assertSame(Result.SUCCESS, project.getLastBuild().getResult()); } /** * Tests that a comment added triggers a build correctly. * * @throws Exception if so. */ @Test @LocalData public void testTriggerOnCommentAdded() throws Exception { gerritServer.getConfig().setCategories(Setup.createCodeReviewVerdictCategoryList()); FreeStyleProject project = DuplicatesUtil.createGerritTriggeredJobForCommentAdded(j, "projectX"); project.getBuildersList().add(new SleepBuilder(2000)); serverMock.waitForCommand(GERRIT_STREAM_EVENTS, 2000); CommentAdded firstEvent = Setup.createCommentAdded(); gerritServer.triggerEvent(firstEvent); TestUtils.waitForBuilds(project, 1); assertEquals(1, project.getLastCompletedBuild().getNumber()); assertSame(Result.SUCCESS, project.getLastCompletedBuild().getResult()); } /** * Tests that two comments added during the same time only triggers one build. * * @throws Exception if so. */ @Test @LocalData public void testDoubleTriggeredOnCommentAdded() throws Exception { gerritServer.getConfig().setCategories(Setup.createCodeReviewVerdictCategoryList()); FreeStyleProject project = DuplicatesUtil.createGerritTriggeredJobForCommentAdded(j, "projectX"); project.getBuildersList().add(new SleepBuilder(2000)); serverMock.waitForCommand(GERRIT_STREAM_EVENTS, 2000); gerritServer.triggerEvent(Setup.createCommentAdded()); gerritServer.triggerEvent(Setup.createCommentAdded()); TestUtils.waitForBuilds(project, 1); assertEquals(1, project.getLastCompletedBuild().getNumber()); assertSame(Result.SUCCESS, project.getLastCompletedBuild().getResult()); } /** /** * Waits for the dynamic trigger cache to be updated. * @param project the project to check the dynamic triggering for. * @param timeoutMs th amount of milliseconds to wait. */ private void waitForDynamicTimer(FreeStyleProject project, int timeoutMs) { long startTime = System.currentTimeMillis(); while (System.currentTimeMillis() - startTime <= timeoutMs) { GerritTrigger trigger = project.getTrigger(GerritTrigger.class); List<GerritProject> dynamicGerritProjects = trigger.getDynamicGerritProjects(); if (dynamicGerritProjects != null && !dynamicGerritProjects.isEmpty()) { return; } } throw new RuntimeException("Timeout!"); } /** * Tests that there are no duplicated listeners when a project is renamed. * * @throws Exception if so. */ @Test @LocalData public void testProjectRename() throws Exception { FreeStyleProject project = DuplicatesUtil.createGerritTriggeredJob(j, "projectX"); serverMock.waitForCommand(GERRIT_STREAM_EVENTS, 2000); gerritServer.triggerEvent(Setup.createPatchsetCreated()); TestUtils.waitForBuilds(project, 1, 60000); project.renameTo("anotherName"); project = j.configRoundtrip(project); gerritServer.triggerEvent(Setup.createPatchsetCreated()); TestUtils.waitForBuilds(project, 2, 60000); } }