diff --git a/src/main/java/com/cloudbees/hudson/plugins/folder/computed/DefaultOrphanedItemStrategy.java b/src/main/java/com/cloudbees/hudson/plugins/folder/computed/DefaultOrphanedItemStrategy.java index d843d8d6..06edee31 100644 --- a/src/main/java/com/cloudbees/hudson/plugins/folder/computed/DefaultOrphanedItemStrategy.java +++ b/src/main/java/com/cloudbees/hudson/plugins/folder/computed/DefaultOrphanedItemStrategy.java @@ -191,7 +191,7 @@ public int compare(I i1, I i2) { return (ms2 < ms1) ? -1 : ((ms2 == ms1) ? 0 : 1); // TODO Java 7+: Long.compare(ms2, ms1); } }); - for (Iterator iterator = candidates.iterator(); iterator.hasNext();) { + CANDIDATES: for (Iterator iterator = candidates.iterator(); iterator.hasNext();) { I item = iterator.next(); for (Job job : item.getAllJobs()) { // Enumerating all builds is inefficient. But we will most likely delete this job anyway, @@ -200,11 +200,13 @@ public int compare(I i1, I i2) { if (build.isBuilding()) { listener.getLogger().printf("Will not remove %s as %s is still in progress%n", item.getDisplayName(), build.getFullDisplayName()); iterator.remove(); + continue CANDIDATES; } String whyKeepLog = build.getWhyKeepLog(); if (whyKeepLog != null) { listener.getLogger().printf("Will not remove %s as %s is marked to not be removed: %s%n", item.getDisplayName(), build.getFullDisplayName(), whyKeepLog); iterator.remove(); + continue CANDIDATES; } } } diff --git a/src/test/java/com/cloudbees/hudson/plugins/folder/computed/ComputedFolderTest.java b/src/test/java/com/cloudbees/hudson/plugins/folder/computed/ComputedFolderTest.java index abc45369..814e6d3f 100644 --- a/src/test/java/com/cloudbees/hudson/plugins/folder/computed/ComputedFolderTest.java +++ b/src/test/java/com/cloudbees/hudson/plugins/folder/computed/ComputedFolderTest.java @@ -59,22 +59,22 @@ public class ComputedFolderTest { @Test public void duplicateEntries() throws Exception { SampleComputedFolder d = r.jenkins.createProject(SampleComputedFolder.class, "d"); - d.recompute(); + d.recompute(Result.SUCCESS); d.assertItemNames(1); d.kids.addAll(Arrays.asList("A", "B", "A", "C")); - d.recompute(); + d.recompute(Result.SUCCESS); d.assertItemNames(2, "A", "B", "C"); assertEquals("[A, B, C]", d.created.toString()); - d.recompute(); + d.recompute(Result.SUCCESS); d.assertItemNames(3, "A", "B", "C"); assertEquals("[A, B, C]", d.created.toString()); d.kids.remove("B"); - d.recompute(); + d.recompute(Result.SUCCESS); d.assertItemNames(4, "A", "C"); assertEquals("[A, B, C]", d.created.toString()); assertEquals("[B]", d.deleted.toString()); d.kids.addAll(Arrays.asList("D", "B")); - d.recompute(); + d.recompute(Result.SUCCESS); d.assertItemNames(5, "A", "B", "C", "D"); assertEquals("[A, B, C, D, B]", d.created.toString()); assertEquals("[B]", d.deleted.toString()); @@ -90,17 +90,13 @@ public void abortException() throws Exception { SampleComputedFolder d = r.jenkins.createProject(SampleComputedFolder.class, "d"); d.setDisplayName("My Folder"); d.kids.addAll(Arrays.asList("A", "B")); - d.recompute(); + d.recompute(Result.SUCCESS); d.assertItemNames(1, "A", "B"); d.kids.add("Z"); d.kids.remove("A"); - d.recompute(); + // Despite its name, AbortException is intended to be FAILURE, not ABORTED which would be InterruptedException. + String log = d.recompute(Result.FAILURE); d.assertItemNames(2, "A", "B"); - FolderComputation computation = d.getComputation(); - assertEquals(Result.FAILURE, computation.getResult()); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - computation.writeWholeLogTo(baos); - String log = baos.toString(); assertTrue(log, log.contains("not adding Z")); assertFalse(log, log.contains(SampleComputedFolder.class.getName())); } @@ -110,26 +106,30 @@ public void abortException() throws Exception { public void runningBuild() throws Exception { SampleComputedFolder d = r.jenkins.createProject(SampleComputedFolder.class, "d"); d.kids.addAll(Arrays.asList("A", "B")); - d.recompute(); + d.recompute(Result.SUCCESS); d.assertItemNames(1, "A", "B"); d.getItem("B").getBuildersList().add(new SleepBuilder(Long.MAX_VALUE)); + d.getItem("B").setConcurrentBuild(true); FreeStyleBuild b1 = d.getItem("B").scheduleBuild2(0).waitForStart(); + FreeStyleBuild b2 = d.getItem("B").scheduleBuild2(0).waitForStart(); d.kids.remove("B"); - d.recompute(); + d.recompute(Result.SUCCESS); d.assertItemNames(2, "A", "B"); - assertTrue(b1.isBuilding()); - b1.doStop(); - r.assertBuildStatus(Result.ABORTED, r.waitForCompletion(b1)); - d.recompute(); + for (FreeStyleBuild b : new FreeStyleBuild[] {b1, b2}) { + assertTrue(b.isBuilding()); + b.doStop(); + r.assertBuildStatus(Result.ABORTED, r.waitForCompletion(b)); + } + d.recompute(Result.SUCCESS); d.assertItemNames(3, "A"); FreeStyleBuild a1 = d.getItem("A").scheduleBuild2(0).get(); FreeStyleBuild a2 = d.getItem("A").scheduleBuild2(0).get(); a1.keepLog(true); d.kids.remove("A"); - d.recompute(); + d.recompute(Result.SUCCESS); d.assertItemNames(4, "A"); a1.keepLog(false); - d.recompute(); + d.recompute(Result.SUCCESS); d.assertItemNames(5); } @@ -203,9 +203,8 @@ protected Collection orphanedItems(Collection d, Result result) throws Exception { + d.scheduleBuild2(0).getFuture().get(); + FolderComputation computation = d.getComputation(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + computation.writeWholeLogTo(baos); + String log = baos.toString(); + assertEquals(log, result, computation.getResult()); + return log; + } + @SuppressWarnings({"unchecked", "rawtypes"}) public static class SecondOrderComputedFolder extends ComputedFolder { @@ -260,16 +269,16 @@ protected void computeChildren(ChildObserver observer, Tas } - void assertItemNames(String... names) throws Exception { - scheduleBuild2(0).getFuture().get(); - getComputation().writeWholeLogTo(System.out); + String assertItemNames(String... names) throws Exception { + String log = doRecompute(this, Result.SUCCESS); Set actual = new TreeSet(); for (SampleComputedFolder d : getItems()) { - d.recompute(); + d.recompute(Result.SUCCESS); d.assertItemNames(d.round, d.kids.toArray(new String[0])); actual.add(d.getName()); } assertEquals(new TreeSet(Arrays.asList(names)).toString(), actual.toString()); + return log; } @TestExtension