diff --git a/src/main/java/hudson/plugins/mercurial/MercurialStatus.java b/src/main/java/hudson/plugins/mercurial/MercurialStatus.java index a3c5d678..6cae639f 100644 --- a/src/main/java/hudson/plugins/mercurial/MercurialStatus.java +++ b/src/main/java/hudson/plugins/mercurial/MercurialStatus.java @@ -45,6 +45,8 @@ public class MercurialStatus implements UnprotectedRootAction { public static final String URL_NAME = "mercurial"; + static final int MAX_REPORTED_PROJECTS = 10; + public String getDisplayName() { return Messages.MercurialStatus_mercurial(); } @@ -205,7 +207,12 @@ private HttpResponse handleNotifyCommit(String origin, URI url, final Authentica public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) throws IOException, ServletException { rsp.setStatus(SC_OK); rsp.setContentType("text/plain"); - for (Item p : projects) { + for (int i = 0; i < projects.size(); i++) { + if (i == MAX_REPORTED_PROJECTS) { + rsp.addHeader("Triggered", "<" + (projects.size() - i) + " more>"); + break; + } + Item p = projects.get(i); if (p.hasPermission2(origAuth, Item.READ)) { rsp.addHeader("Triggered", p.getAbsoluteUrl()); } else { diff --git a/src/test/java/hudson/plugins/mercurial/MercurialStatusTest.java b/src/test/java/hudson/plugins/mercurial/MercurialStatusTest.java index dfc2d1a6..a942d59c 100644 --- a/src/test/java/hudson/plugins/mercurial/MercurialStatusTest.java +++ b/src/test/java/hudson/plugins/mercurial/MercurialStatusTest.java @@ -25,16 +25,42 @@ import java.net.URI; import java.net.URISyntaxException; +import java.util.List; +import java.util.stream.Collectors; + +import hudson.FilePath; +import hudson.model.FreeStyleProject; +import hudson.model.Slave; +import hudson.triggers.SCMTrigger; +import org.apache.commons.lang.StringUtils; +import org.jenkinsci.test.acceptance.docker.DockerClassRule; +import org.junit.ClassRule; +import org.junit.Rule; import org.junit.Test; +import org.jvnet.hudson.test.Issue; +import org.jvnet.hudson.test.JenkinsRule; +import org.jvnet.hudson.test.SleepBuilder; + +import static hudson.plugins.mercurial.MercurialStatus.MAX_REPORTED_PROJECTS; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.*; +import com.gargoylesoftware.htmlunit.Page; +import com.gargoylesoftware.htmlunit.WebResponse; +import com.gargoylesoftware.htmlunit.util.NameValuePair; + /** * * @author Sebastian Sdorra */ public class MercurialStatusTest { - - @Test public void testLooselyMatches() throws URISyntaxException { + + @Rule public JenkinsRule j = new JenkinsRule(); + @Rule public MercurialRule m = new MercurialRule(j); + @ClassRule public static DockerClassRule docker = new DockerClassRule<>(MercurialContainer.class); + + @Test public void testLooselyMatches() throws URISyntaxException { assertTrue( MercurialStatus.looselyMatches(new URI("ssh://somehost/"), "ssh://somehost")); assertTrue( MercurialStatus.looselyMatches(new URI("http://somehost"), "http://somehost/")); assertTrue( MercurialStatus.looselyMatches(new URI("http://somehost:80/"), "http://somehost/")); @@ -75,6 +101,44 @@ public class MercurialStatusTest { assertFalse( MercurialStatus.looselyMatches(new URI("http://scm.foocompany.com/hg/foocomponent/"), "${REPO_URL}") ); assertFalse( MercurialStatus.looselyMatches(new URI("http://scm.foocompany.com/hg/foocomponent/"), "$REPO_URL") ); - } - + } + + @Issue("JENKINS-12544") + @Test public void testTriggeredHeadersAreLimited() throws Exception { + m.hg("version"); // test environment needs to be able to run Mercurial + MercurialContainer container = docker.create(); + Slave slave = container.createSlave(j); + m.withNode(slave); + MercurialInstallation inst = container.createInstallation(j, MercurialContainer.Version.HG5, false, false, false, "", slave); + assertNotNull(inst); + m.withInstallation(inst); + FilePath sampleRepo = slave.getRootPath().child("sampleRepo"); + sampleRepo.mkdirs(); + m.hg(sampleRepo, "init"); + sampleRepo.child("a").write("a", "UTF-8"); + m.hg(sampleRepo, "commit", "--addremove", "--message=a-file"); + + String source = "ssh://test@" + container.ipBound(22) + ":" + container.port(22) + "/" + sampleRepo; + + for (int i = 0; i < MAX_REPORTED_PROJECTS + 5; i++) { + FreeStyleProject p = j.createFreeStyleProject("triggeredHeaderTest" + i); + p.setScm(new MercurialSCM( + inst.getName(), + source, + null, null, null, null, false)); + p.addTrigger(new SCMTrigger("")); + p.getBuildersList().add(new SleepBuilder(1000)); + } + + final Page page = j.createWebClient().goTo("mercurial/notifyCommit?url=" + source, "text/plain"); + final WebResponse response = page.getWebResponse(); + assertEquals(200, response.getStatusCode()); + final List headers = response.getResponseHeaders(); + final List triggered = headers.stream().filter(nvp -> nvp.getName().equals("Triggered")).collect(Collectors.toList()); + assertEquals("No headers!", MAX_REPORTED_PROJECTS + 1, triggered.size()); + List headerValues = triggered.stream().map(NameValuePair::getValue).collect(Collectors.toList()); + assertThat(headerValues.get(MAX_REPORTED_PROJECTS), is("<5 more>")); + final String content = response.getContentAsString(); + assertThat(MAX_REPORTED_PROJECTS + 5, is(StringUtils.countMatches(content, "Scheduled polling of "))); + } }