diff --git a/pom.xml b/pom.xml index 0288cf02..468b4ce7 100644 --- a/pom.xml +++ b/pom.xml @@ -71,6 +71,7 @@ jboss-marshalling,jboss-marshalling-river true 3.0 + false true jboss-marshalling,jboss-marshalling-river jenkinsci/${project.artifactId}-plugin diff --git a/src/test/java/org/jenkinsci/plugins/workflow/support/actions/LogActionImplTest.java b/src/test/java/org/jenkinsci/plugins/workflow/support/actions/LogActionImplTest.java index 61eea337..bfe252de 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/support/actions/LogActionImplTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/support/actions/LogActionImplTest.java @@ -37,20 +37,30 @@ import org.jenkinsci.plugins.workflow.steps.StepContext; import org.jenkinsci.plugins.workflow.steps.StepDescriptor; import org.jenkinsci.plugins.workflow.steps.StepExecution; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.Rule; -import org.jvnet.hudson.test.BuildWatcher; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.TestExtension; +import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension; +import org.jvnet.hudson.test.junit.jupiter.WithJenkins; import org.kohsuke.stapler.DataBoundConstructor; -public class LogActionImplTest { +@WithJenkins +class LogActionImplTest { - @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher(); - @Rule public JenkinsRule r = new JenkinsRule(); + @SuppressWarnings("unused") + @RegisterExtension + private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension(); + private JenkinsRule r; - @Test public void logsAndBlocks() throws Exception { + @BeforeEach + void beforeEach(JenkinsRule rule) { + r = rule; + } + + @Test + void logsAndBlocks() throws Exception { WorkflowJob p = r.createProject(WorkflowJob.class); p.setDefinition(new CpsFlowDefinition("parallel a: {chatty('LBBL') {echo(/atom step in A with $remaining commands to go/)}}, b: {chatty('BL') {echo(/atom step in B with $remaining commands to go/)}}", true)); WorkflowRun b = r.buildAndAssertSuccess(p); @@ -61,27 +71,48 @@ public class LogActionImplTest { r.assertLogContains("atom step in B with 1 commands to go", b); r.assertLogContains("logging from BL with 0 commands to go", b); } + + @SuppressWarnings("unused") public static class ChattyStep extends Step { + public final String pattern; - @DataBoundConstructor public ChattyStep(String pattern) {this.pattern = pattern;} - @Override public StepExecution start(StepContext context) throws Exception { + + @DataBoundConstructor + public ChattyStep(String pattern) {this.pattern = pattern;} + + @Override + public StepExecution start(StepContext context) throws Exception { return new Execution(context, pattern); } - @TestExtension("logsAndBlocks") public static class DescriptorImpl extends StepDescriptor { - @Override public String getFunctionName() {return "chatty";} - @Override public boolean takesImplicitBlockArgument() {return true;} - @Override public Set> getRequiredContext() { + + @SuppressWarnings("unused") + @TestExtension("logsAndBlocks") + public static class DescriptorImpl extends StepDescriptor { + + @Override + public String getFunctionName() {return "chatty";} + + @Override + public boolean takesImplicitBlockArgument() {return true;} + + @Override + public Set> getRequiredContext() { return Collections.singleton(TaskListener.class); } } + private static class Execution extends StepExecution { + + private final String pattern; + private LinkedList commands; // L ~ false to log, B ~ true to run block + Execution(StepContext context, String pattern) { super(context); this.pattern = pattern; } - final String pattern; - LinkedList commands; // L ~ false to log, B ~ true to run block - @Override public boolean start() throws Exception { + + @Override + public boolean start() throws Exception { commands = new LinkedList<>(); for (char c : pattern.toCharArray()) { if (c == 'L') { @@ -94,6 +125,7 @@ private static class Execution extends StepExecution { run(); return false; } + private void run() throws Exception { StepContext context = getContext(); if (commands.isEmpty()) { @@ -105,19 +137,23 @@ private void run() throws Exception { run(); } } + private final class Callback extends BodyExecutionCallback { // not using TailCall since run() sometimes calls onSuccess itself - @Override public void onSuccess(StepContext context, Object result) { + + @Override + public void onSuccess(StepContext context, Object result) { try { run(); } catch (Exception x) { context.onFailure(x); } } - @Override public void onFailure(StepContext context, Throwable t) { + + @Override + public void onFailure(StepContext context, Throwable t) { context.onFailure(t); } } } } - } diff --git a/src/test/java/org/jenkinsci/plugins/workflow/support/actions/PauseActionTest.java b/src/test/java/org/jenkinsci/plugins/workflow/support/actions/PauseActionTest.java index 22a2d7e4..8f1c92a9 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/support/actions/PauseActionTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/support/actions/PauseActionTest.java @@ -26,17 +26,19 @@ import org.jenkinsci.plugins.workflow.flow.FlowExecution; import org.jenkinsci.plugins.workflow.graph.FlowNode; import org.jenkinsci.plugins.workflow.support.actions.PauseAction; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + import org.mockito.Mockito; /** * @author tom.fennelly@gmail.com */ -public class PauseActionTest { +class PauseActionTest { @Test - public void test() throws Exception { + void test() throws Exception { FlowExecution flowExecution = Mockito.mock(FlowExecution.class); FlowNode flowNode = new FlowNode(flowExecution, "1") { @Override @@ -45,35 +47,35 @@ protected String getTypeDisplayName() { } }; - Assert.assertFalse(PauseAction.isPaused(flowNode)); - Assert.assertEquals(0L, PauseAction.getPauseDuration(flowNode)); + assertFalse(PauseAction.isPaused(flowNode)); + assertEquals(0L, PauseAction.getPauseDuration(flowNode)); flowNode.addAction(new PauseAction("P1")); PauseAction firstPause = PauseAction.getCurrentPause(flowNode); - Assert.assertEquals("P1", firstPause.getCause()); - Assert.assertTrue(PauseAction.isPaused(flowNode)); + assertEquals("P1", firstPause.getCause()); + assertTrue(PauseAction.isPaused(flowNode)); Thread.sleep(200); - Assert.assertTrue(PauseAction.getPauseDuration(flowNode) > 100L); + assertTrue(PauseAction.getPauseDuration(flowNode) > 100L); PauseAction.endCurrentPause(flowNode); - Assert.assertFalse(PauseAction.isPaused(flowNode)); + assertFalse(PauseAction.isPaused(flowNode)); long firstPauseDuration = firstPause.getPauseDuration(); Thread.sleep(200); - Assert.assertEquals(firstPauseDuration, PauseAction.getPauseDuration(flowNode)); + assertEquals(firstPauseDuration, PauseAction.getPauseDuration(flowNode)); flowNode.addAction(new PauseAction("P2")); PauseAction secondPause = PauseAction.getCurrentPause(flowNode); - Assert.assertEquals("P2", secondPause.getCause()); - Assert.assertTrue(PauseAction.isPaused(flowNode)); + assertEquals("P2", secondPause.getCause()); + assertTrue(PauseAction.isPaused(flowNode)); Thread.sleep(200); - Assert.assertTrue(PauseAction.getPauseDuration(flowNode) > firstPauseDuration); + assertTrue(PauseAction.getPauseDuration(flowNode) > firstPauseDuration); PauseAction.endCurrentPause(flowNode); - Assert.assertFalse(PauseAction.isPaused(flowNode)); + assertFalse(PauseAction.isPaused(flowNode)); long secondPauseDuration = secondPause.getPauseDuration(); Thread.sleep(200); - Assert.assertEquals((firstPauseDuration + secondPauseDuration), PauseAction.getPauseDuration(flowNode)); + assertEquals((firstPauseDuration + secondPauseDuration), PauseAction.getPauseDuration(flowNode)); } } diff --git a/src/test/java/org/jenkinsci/plugins/workflow/support/concurrent/TimeoutTest.java b/src/test/java/org/jenkinsci/plugins/workflow/support/concurrent/TimeoutTest.java index 4ddeea19..1e38f595 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/support/concurrent/TimeoutTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/support/concurrent/TimeoutTest.java @@ -31,23 +31,26 @@ import java.util.logging.Level; import java.util.stream.IntStream; import jenkins.util.Timer; -import org.junit.Test; -import static org.junit.Assert.*; -import org.junit.Rule; -import org.jvnet.hudson.test.LoggerRule; +import static org.junit.jupiter.api.Assertions.fail; -public class TimeoutTest { +import org.junit.jupiter.api.Test; +import org.jvnet.hudson.test.LogRecorder; - @Rule public LoggerRule logging = new LoggerRule().record(Timeout.class, Level.FINER); - - @Test public void passed() throws Exception { +class TimeoutTest { + + @SuppressWarnings("unused") + private final LogRecorder logging = new LogRecorder().record(Timeout.class, Level.FINER); + + @Test + void passed() throws Exception { try (Timeout timeout = Timeout.limit(5, TimeUnit.SECONDS)) { Thread.sleep(1_000); } Thread.sleep(5_000); } - @Test public void failed() throws Exception { + @Test + void failed() throws Exception { try (Timeout timeout = Timeout.limit(5, TimeUnit.SECONDS)) { Thread.sleep(10_000); fail("should have timed out"); @@ -57,7 +60,8 @@ public class TimeoutTest { Thread.sleep(1_000); } - @Test public void hung() throws Exception { + @Test + void hung() throws Exception { /* see disabled code in Timeout: final AtomicBoolean stop = new AtomicBoolean(); Thread t = Thread.currentThread(); @@ -88,7 +92,8 @@ public class TimeoutTest { */ } - @Test public void starvation() throws Exception { + @Test + void starvation() throws Exception { Map> hangers = new TreeMap<>(); IntStream.range(0, 15).forEachOrdered(i -> hangers.put(i, Timer.get().submit(() -> { try (Timeout timeout = Timeout.limit(5, TimeUnit.SECONDS)) { @@ -105,5 +110,4 @@ public class TimeoutTest { System.err.println("joined #" + hanger.getKey()); } } - } diff --git a/src/test/java/org/jenkinsci/plugins/workflow/support/pickles/ThrowablePickleTest.java b/src/test/java/org/jenkinsci/plugins/workflow/support/pickles/ThrowablePickleTest.java index dec23667..2423e191 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/support/pickles/ThrowablePickleTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/support/pickles/ThrowablePickleTest.java @@ -31,22 +31,28 @@ import org.jenkinsci.plugins.workflow.job.WorkflowJob; import org.jenkinsci.plugins.workflow.job.WorkflowRun; import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.Rule; -import org.jvnet.hudson.test.BuildWatcher; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import org.jvnet.hudson.test.Issue; -import org.jvnet.hudson.test.LoggerRule; -import org.jvnet.hudson.test.JenkinsSessionRule; +import org.jvnet.hudson.test.LogRecorder; +import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension; +import org.jvnet.hudson.test.junit.jupiter.JenkinsSessionExtension; -public class ThrowablePickleTest { +class ThrowablePickleTest { - @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher(); - @Rule public JenkinsSessionRule sessions = new JenkinsSessionRule(); - @Rule public LoggerRule logging = new LoggerRule().record(ThrowablePickle.class, Level.FINE); + @SuppressWarnings("unused") + @RegisterExtension + private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension(); + + @RegisterExtension + private final JenkinsSessionExtension sessions = new JenkinsSessionExtension(); + + @SuppressWarnings("unused") + private final LogRecorder logging = new LogRecorder().record(ThrowablePickle.class, Level.FINE); @Issue("JENKINS-51390") - @Test public void smokes() throws Throwable { + @Test + void smokes() throws Throwable { String beName = BadException.class.getName(); sessions.then(r -> { WorkflowJob p = r.createProject(WorkflowJob.class, "p"); diff --git a/src/test/java/org/jenkinsci/plugins/workflow/support/pickles/serialization/EphemeralPickleResolverTest.java b/src/test/java/org/jenkinsci/plugins/workflow/support/pickles/serialization/EphemeralPickleResolverTest.java index 9d8d8b20..833ee604 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/support/pickles/serialization/EphemeralPickleResolverTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/support/pickles/serialization/EphemeralPickleResolverTest.java @@ -27,8 +27,7 @@ import org.jenkinsci.plugins.workflow.pickles.Pickle; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.ArrayList; import java.util.NoSuchElementException; @@ -36,19 +35,21 @@ import java.util.concurrent.Future; import static java.util.Arrays.*; +import static org.junit.jupiter.api.Assertions.*; /** * @author Kohsuke Kawaguchi */ -public class EphemeralPickleResolverTest extends Assert { +class EphemeralPickleResolverTest { + @Test - public void resolveNothing() throws Exception { + void resolveNothing() throws Exception { ListenableFuture f = new PickleResolver(new ArrayList<>()).rehydrate(); assertSuccessfulCompletion(f); } @Test - public void resolveSomething() throws Exception { + void resolveSomething() throws Exception { TestPickle v1 = new TestPickle(); TestPickle v2 = new TestPickle(); ListenableFuture f = new PickleResolver(asList(v1, v2)).rehydrate(); @@ -64,7 +65,7 @@ public void resolveSomething() throws Exception { * If a resolution of a value fails, the whole thing should fail. */ @Test - public void resolutionFails() throws Exception { + void resolutionFails() throws Exception { TestPickle v1 = new TestPickle(); TestPickle v2 = new TestPickle(); ListenableFuture f = new PickleResolver(asList(v1, v2)).rehydrate(); @@ -79,7 +80,7 @@ public void resolutionFails() throws Exception { f.get(); fail("Expected a failure"); } catch (ExecutionException e) { - assertTrue(e.getCause() instanceof NoSuchElementException); + assertInstanceOf(NoSuchElementException.class, e.getCause()); } } @@ -93,8 +94,9 @@ private void assertSuccessfulCompletion(Future f) throws Exception { f.get(); } - class TestPickle extends Pickle { - SettableFuture f = SettableFuture.create(); + static class TestPickle extends Pickle { + private SettableFuture f = SettableFuture.create(); + @Override public ListenableFuture rehydrate() { return f; diff --git a/src/test/java/org/jenkinsci/plugins/workflow/support/pickles/serialization/PickleResolverTest.java b/src/test/java/org/jenkinsci/plugins/workflow/support/pickles/serialization/PickleResolverTest.java index 9000b9b3..531d0c14 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/support/pickles/serialization/PickleResolverTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/support/pickles/serialization/PickleResolverTest.java @@ -9,32 +9,44 @@ import org.jenkinsci.plugins.workflow.support.pickles.SingleTypedPickleFactory; import org.jenkinsci.plugins.workflow.support.pickles.TryRepeatedly; import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.Test; -import org.jvnet.hudson.test.BuildWatcher; -import org.jvnet.hudson.test.FlagRule; -import org.jvnet.hudson.test.JenkinsSessionRule; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import org.jvnet.hudson.test.TestExtension; +import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension; +import org.jvnet.hudson.test.junit.jupiter.JenkinsSessionExtension; -public class PickleResolverTest { - @ClassRule - public static BuildWatcher watcher = new BuildWatcher(); +class PickleResolverTest { + + @SuppressWarnings("unused") + @RegisterExtension + private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension(); - @Rule - public JenkinsSessionRule sessions = new JenkinsSessionRule(); + @RegisterExtension + private final JenkinsSessionExtension sessions = new JenkinsSessionExtension(); - @Rule - public FlagRule resetPickleResolutionTimeout = new FlagRule<>(() -> PickleResolver.RESOLUTION_TIMEOUT_SECONDS, x -> PickleResolver.RESOLUTION_TIMEOUT_SECONDS = x); + private long resetPickleResolutionTimeout; + + @BeforeEach + void beforeEach() { + resetPickleResolutionTimeout = PickleResolver.RESOLUTION_TIMEOUT_SECONDS; + } + + @AfterEach + void afterEach() { + PickleResolver.RESOLUTION_TIMEOUT_SECONDS = resetPickleResolutionTimeout; + } @Test - public void timeout() throws Throwable { + void timeout() throws Throwable { sessions.then(r -> { var p = r.jenkins.createProject(WorkflowJob.class, "stuckPickle"); p.setDefinition(new CpsFlowDefinition( - "def x = new org.jenkinsci.plugins.workflow.support.pickles.serialization.PickleResolverTest.StuckPickle.Marker()\n" + - "semaphore 'wait'\n" + - "echo x.getClass().getName()", false)); + """ + def x = new org.jenkinsci.plugins.workflow.support.pickles.serialization.PickleResolverTest.StuckPickle.Marker() + semaphore 'wait' + echo x.getClass().getName()""", false)); var b = p.scheduleBuild2(0).waitForStart(); SemaphoreStep.waitForStart("wait/1", b); }); @@ -47,18 +59,25 @@ public void timeout() throws Throwable { }); } + @SuppressWarnings("unused") public static class StuckPickle extends Pickle { + @Override public ListenableFuture rehydrate(FlowExecutionOwner owner) { - return new TryRepeatedly(1) { + return new TryRepeatedly<>(1) { + @Override protected Marker tryResolve() { return null; } - @Override protected FlowExecutionOwner getOwner() { + + @Override + protected FlowExecutionOwner getOwner() { return owner; } - @Override public String toString() { + + @Override + public String toString() { return "StuckPickle for " + owner; } }; @@ -68,7 +87,9 @@ public static class Marker {} @TestExtension("timeout") public static final class Factory extends SingleTypedPickleFactory { - @Override protected Pickle pickle(Marker object) { + + @Override + protected Pickle pickle(Marker object) { return new StuckPickle(); } } diff --git a/src/test/java/org/jenkinsci/plugins/workflow/support/pickles/serialization/RiverWriterTest.java b/src/test/java/org/jenkinsci/plugins/workflow/support/pickles/serialization/RiverWriterTest.java index 63cd42ed..1160c430 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/support/pickles/serialization/RiverWriterTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/support/pickles/serialization/RiverWriterTest.java @@ -33,22 +33,26 @@ import java.util.logging.Level; import static org.hamcrest.Matchers.containsString; import org.jenkinsci.plugins.workflow.flow.FlowExecutionOwner; -import org.junit.Test; import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; -import org.junit.Rule; -import org.junit.rules.TemporaryFolder; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.jvnet.hudson.test.Issue; -import org.jvnet.hudson.test.LoggerRule; +import org.jvnet.hudson.test.LogRecorder; + +class RiverWriterTest { -public class RiverWriterTest { + @SuppressWarnings("unused") + private final LogRecorder logging = new LogRecorder().recordPackage(RiverWriter.class, Level.FINE); - @Rule public TemporaryFolder tmp = new TemporaryFolder(); - @Rule public LoggerRule logging = new LoggerRule().recordPackage(RiverWriter.class, Level.FINE); + @TempDir + private File tmp; - @Test public void trivial() throws Exception { - File f = tmp.newFile(); + @Test + void trivial() throws Exception { + File f = File.createTempFile("junit", null, tmp); FlowExecutionOwner owner = FlowExecutionOwner.dummyOwner(); try (RiverWriter w = new RiverWriter(f, owner, Collections.emptySet())) { w.writeObject(Collections.singletonList("hello world")); @@ -61,8 +65,9 @@ public class RiverWriterTest { } @Issue("JENKINS-26137") - @Test public void errors() throws Exception { - File f = tmp.newFile(); + @Test + void errors() throws Exception { + File f = File.createTempFile("junit", null, tmp); FlowExecutionOwner owner = FlowExecutionOwner.dummyOwner(); try (RiverWriter w = new RiverWriter(f, owner, Collections.emptySet())) { w.writeObject(Collections.singletonList(new NotActuallySerializable())); @@ -82,9 +87,10 @@ public class RiverWriterTest { assertThat(Functions.printThrowable(x), containsString(NotActuallySerializable.class.getName() + ".bad")); } } + private static class NotActuallySerializable implements Serializable { - String good = "OK"; - Object bad = new Object(); + private String good = "OK"; + private Object bad = new Object(); } // TODO pickle resolution diff --git a/src/test/java/org/jenkinsci/plugins/workflow/support/pickles/serialization/SerializationSecurityTest.java b/src/test/java/org/jenkinsci/plugins/workflow/support/pickles/serialization/SerializationSecurityTest.java index 3d596fde..648febd1 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/support/pickles/serialization/SerializationSecurityTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/support/pickles/serialization/SerializationSecurityTest.java @@ -32,94 +32,107 @@ import org.jenkinsci.plugins.workflow.job.WorkflowJob; import org.jenkinsci.plugins.workflow.job.WorkflowRun; import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep; -import org.junit.ClassRule; -import org.junit.Test; -import static org.junit.Assert.*; -import org.junit.Ignore; -import org.junit.Rule; -import org.jvnet.hudson.test.BuildWatcher; + +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import org.jvnet.hudson.test.For; import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; -import org.jvnet.hudson.test.JenkinsSessionRule; +import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension; +import org.jvnet.hudson.test.junit.jupiter.JenkinsSessionExtension; @Issue("SECURITY-699") -public class SerializationSecurityTest { +class SerializationSecurityTest { - @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher(); + @SuppressWarnings("unused") + @RegisterExtension + private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension(); + + @RegisterExtension + private final JenkinsSessionExtension sessions = new JenkinsSessionExtension(); - @Rule public JenkinsSessionRule sessions = new JenkinsSessionRule(); - /** @see SerializableClass#callWriteObject */ @For(RiverWriter.class) - @Test public void writeObjectChecksSandbox() throws Throwable { + @Test + void writeObjectChecksSandbox() throws Throwable { sessions.then(r -> { WorkflowJob p = r.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "class Hack {\n" + - " @NonCPS private void writeObject(ObjectOutputStream out) {\n" + - " Jenkins.instance.systemMessage = 'oops'\n" + - " }\n" + - "}\n" + - "def hack = new Hack()\n" + - "sleep 1\n" + - "echo(/should not still have $hack/)", true)); + """ + class Hack { + @NonCPS private void writeObject(ObjectOutputStream out) { + Jenkins.instance.systemMessage = 'oops' + } + } + def hack = new Hack() + sleep 1 + echo(/should not still have $hack/)""", true)); safe(r, p.scheduleBuild2(0).get()); }); } /** @see SerializableClass#callWriteReplace */ @For(RiverWriter.class) - @Test public void writeReplaceChecksSandbox() throws Throwable { + @Test + void writeReplaceChecksSandbox() throws Throwable { sessions.then(r -> { WorkflowJob p = r.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "class Hack {\n" + - " @NonCPS private Object writeReplace() {\n" + - " Jenkins.instance.systemMessage = 'oops'\n" + - " this\n" + - " }\n" + - "}\n" + - "def hack = new Hack()\n" + - "sleep 1\n" + - "echo(/should not still have $hack/)", true)); + """ + class Hack { + @NonCPS private Object writeReplace() { + Jenkins.instance.systemMessage = 'oops' + this + } + } + def hack = new Hack() + sleep 1 + echo(/should not still have $hack/)""", true)); safe(r, p.scheduleBuild2(0).get()); }); } /** @see RiverMarshaller#doWriteObject */ @For(RiverWriter.class) - @Test public void writeExternalChecksSandbox() throws Throwable { + @Test + void writeExternalChecksSandbox() throws Throwable { sessions.then(r -> { WorkflowJob p = r.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "class Hack implements Externalizable {\n" + - " @NonCPS void writeExternal(ObjectOutput out) {\n" + - " Jenkins.instance.systemMessage = 'oops'\n" + - " }\n" + - " @NonCPS void readExternal(ObjectInput inp) {}\n" + - "}\n" + - "def hack = new Hack()\n" + - "sleep 1\n" + - "echo(/should not still have $hack/)", true)); + """ + class Hack implements Externalizable { + @NonCPS void writeExternal(ObjectOutput out) { + Jenkins.instance.systemMessage = 'oops' + } + @NonCPS void readExternal(ObjectInput inp) {} + } + def hack = new Hack() + sleep 1 + echo(/should not still have $hack/)""", true)); safe(r, p.scheduleBuild2(0).get()); }); } /** @see SerializableClass#callReadObject */ @For(RiverReader.class) - @Test public void readObjectChecksSandbox() throws Throwable { + @Test + void readObjectChecksSandbox() throws Throwable { sessions.then(r -> { WorkflowJob p = r.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "class Hack {\n" + - " @NonCPS private void readObject(ObjectInputStream inp) {\n" + - " Jenkins.instance.systemMessage = 'oops'\n" + - " }\n" + - "}\n" + - "def hack = new Hack()\n" + - "semaphore 'wait'\n" + - "echo(/should not still have $hack/)", true)); + """ + class Hack { + @NonCPS private void readObject(ObjectInputStream inp) { + Jenkins.instance.systemMessage = 'oops' + } + } + def hack = new Hack() + semaphore 'wait' + echo(/should not still have $hack/)""", true)); SemaphoreStep.waitForStart("wait/1", p.scheduleBuild2(0).waitForStart()); }); sessions.then(r -> { @@ -131,18 +144,20 @@ public class SerializationSecurityTest { /** @see SerializableClass#callReadResolve */ @For(RiverReader.class) - @Test public void readResolveChecksSandbox() throws Throwable { + @Test + void readResolveChecksSandbox() throws Throwable { sessions.then(r -> { WorkflowJob p = r.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "class Hack {\n" + - " @NonCPS private Object readResolve() {\n" + - " Jenkins.instance.systemMessage = 'oops'\n" + - " }\n" + - "}\n" + - "def hack = new Hack()\n" + - "semaphore 'wait'\n" + - "echo(/should not still have $hack/)", true)); + """ + class Hack { + @NonCPS private Object readResolve() { + Jenkins.instance.systemMessage = 'oops' + } + } + def hack = new Hack() + semaphore 'wait' + echo(/should not still have $hack/)""", true)); SemaphoreStep.waitForStart("wait/1", p.scheduleBuild2(0).waitForStart()); }); sessions.then(r -> { @@ -153,19 +168,21 @@ public class SerializationSecurityTest { /** @see RiverUnmarshaller#doReadNewObject */ @For(RiverReader.class) - @Test public void readExternalChecksSandbox() throws Throwable { + @Test + void readExternalChecksSandbox() throws Throwable { sessions.then(r -> { WorkflowJob p = r.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "class Hack implements Externalizable {\n" + - " @NonCPS void writeExternal(ObjectOutput out) {}\n" + - " @NonCPS void readExternal(ObjectInput inp) {\n" + - " Jenkins.instance.systemMessage = 'oops'\n" + - " }\n" + - "}\n" + - "def hack = new Hack()\n" + - "semaphore 'wait'\n" + - "echo(/should not still have $hack/)", true)); + """ + class Hack implements Externalizable { + @NonCPS void writeExternal(ObjectOutput out) {} + @NonCPS void readExternal(ObjectInput inp) { + Jenkins.instance.systemMessage = 'oops' + } + } + def hack = new Hack() + semaphore 'wait' + echo(/should not still have $hack/)""", true)); SemaphoreStep.waitForStart("wait/1", p.scheduleBuild2(0).waitForStart()); }); sessions.then(r -> { @@ -176,21 +193,23 @@ public class SerializationSecurityTest { /** @see SerializableClass#callNoArgConstructor */ @For(RiverReader.class) - @Test public void externalizableNoArgConstructorChecksSandbox() throws Throwable { + @Test + void externalizableNoArgConstructorChecksSandbox() throws Throwable { sessions.then(r -> { WorkflowJob p = r.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "class Hack implements Externalizable {\n" + - " Hack(boolean x) {}\n" + - " Hack() {" + - " Jenkins.instance.systemMessage = 'oops'\n" + - " }\n" + - " @NonCPS void writeExternal(ObjectOutput out) {}\n" + - " @NonCPS void readExternal(ObjectInput inp) {}\n" + - "}\n" + - "def hack = new Hack(true)\n" + - "semaphore 'wait'\n" + - "echo(/should not still have $hack/)", true)); + """ + class Hack implements Externalizable { + Hack(boolean x) {} + Hack() {\ + Jenkins.instance.systemMessage = 'oops' + } + @NonCPS void writeExternal(ObjectOutput out) {} + @NonCPS void readExternal(ObjectInput inp) {} + } + def hack = new Hack(true) + semaphore 'wait' + echo(/should not still have $hack/)""", true)); SemaphoreStep.waitForStart("wait/1", p.scheduleBuild2(0).waitForStart()); }); sessions.then(r -> { @@ -204,21 +223,23 @@ public class SerializationSecurityTest { * @see SerializableClass#callObjectInputConstructor */ @For(RiverReader.class) - @Test public void externalizableObjectInputConstructorChecksSandbox() throws Throwable { + @Test + void externalizableObjectInputConstructorChecksSandbox() throws Throwable { sessions.then(r -> { WorkflowJob p = r.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "class Hack implements Externalizable {\n" + - " Hack() {}\n" + - " Hack(ObjectInput inp) {" + - " Jenkins.instance.systemMessage = 'oops'\n" + - " }\n" + - " @NonCPS void writeExternal(ObjectOutput out) {}\n" + - " @NonCPS void readExternal(ObjectInput inp) {}\n" + - "}\n" + - "def hack = new Hack()\n" + - "semaphore 'wait'\n" + - "echo(/should not still have $hack/)", true)); + """ + class Hack implements Externalizable { + Hack() {} + Hack(ObjectInput inp) {\ + Jenkins.instance.systemMessage = 'oops' + } + @NonCPS void writeExternal(ObjectOutput out) {} + @NonCPS void readExternal(ObjectInput inp) {} + } + def hack = new Hack() + semaphore 'wait' + echo(/should not still have $hack/)""", true)); SemaphoreStep.waitForStart("wait/1", p.scheduleBuild2(0).waitForStart()); }); sessions.then(r -> { @@ -227,24 +248,26 @@ public class SerializationSecurityTest { }); } - @Ignore("does not currently work (fails on `new Replacer`), since CpsWhitelist & GroovyClassLoaderWhitelist are not in .all()") - @Test public void harmlessCallsPassSandbox() throws Throwable { + @Disabled("does not currently work (fails on `new Replacer`), since CpsWhitelist & GroovyClassLoaderWhitelist are not in .all()") + @Test + void harmlessCallsPassSandbox() throws Throwable { sessions.then(r -> { WorkflowJob p = r.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "class Fine {\n" + - " @NonCPS private Object writeReplace() {\n" + - " new Replacer()\n" + - " }\n" + - "}\n" + - "class Replacer {\n" + - " @NonCPS private Object readResolve() {\n" + - " 'something safe'\n" + - " }\n" + - "}\n" + - "def fine = new Fine()\n" + - "semaphore 'wait'\n" + - "echo(/but we do have $fine/)", true)); + """ + class Fine { + @NonCPS private Object writeReplace() { + new Replacer() + } + } + class Replacer { + @NonCPS private Object readResolve() { + 'something safe' + } + } + def fine = new Fine() + semaphore 'wait' + echo(/but we do have $fine/)""", true)); SemaphoreStep.waitForStart("wait/1", p.scheduleBuild2(0).waitForStart()); }); sessions.then(r -> { @@ -259,5 +282,4 @@ private static void safe(JenkinsRule r, WorkflowRun b) throws Exception { r.assertLogNotContains("should not still have", b); r.assertLogContains("staticMethod jenkins.model.Jenkins getInstance", b); } - } diff --git a/src/test/java/org/jenkinsci/plugins/workflow/support/steps/build/RunWrapperTest.java b/src/test/java/org/jenkinsci/plugins/workflow/support/steps/build/RunWrapperTest.java index 3d2d2ac6..5d70d90e 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/support/steps/build/RunWrapperTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/support/steps/build/RunWrapperTest.java @@ -41,33 +41,54 @@ import org.jenkinsci.plugins.workflow.job.WorkflowRun; import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep; import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.assertEquals; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.Rule; -import org.jvnet.hudson.test.BuildWatcher; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.MockFolder; -import org.jvnet.hudson.test.JenkinsSessionRule; +import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension; +import org.jvnet.hudson.test.junit.jupiter.JenkinsSessionExtension; @Issue("JENKINS-26834") -public class RunWrapperTest { +class RunWrapperTest { + + @SuppressWarnings("unused") + @RegisterExtension + private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension(); + + @RegisterExtension + private final JenkinsSessionExtension sessions = new JenkinsSessionExtension(); + + private final GitSampleRepoRule sampleRepo1 = new GitSampleRepoRule(); + private final GitSampleRepoRule sampleRepo2 = new GitSampleRepoRule(); - @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher(); - @Rule public JenkinsSessionRule sessions = new JenkinsSessionRule(); - @Rule public GitSampleRepoRule sampleRepo1 = new GitSampleRepoRule(); - @Rule public GitSampleRepoRule sampleRepo2 = new GitSampleRepoRule(); + @BeforeEach + void beforeEach() throws Throwable { + sampleRepo1.before(); + sampleRepo2.before(); + } + + @AfterEach + void afterEach() { + sampleRepo1.after(); + sampleRepo2.after(); + } - @Test public void historyAndPickling() throws Throwable { + @Test + void historyAndPickling() throws Throwable { sessions.then(j -> { WorkflowJob p = j.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "def b0 = currentBuild\n" + - "for (b = b0; b != null; b = b.previousBuild) {\n" + - " semaphore 'basics'\n" + - " echo \"number=${b.number} result=${b.result}\"\n" + - "}", true)); + """ + def b0 = currentBuild + for (b = b0; b != null; b = b.previousBuild) { + semaphore 'basics' + echo "number=${b.number} result=${b.result}" + }""", true)); SemaphoreStep.success("basics/1", null); WorkflowRun b1 = j.buildAndAssertSuccess(p); j.assertLogContains("number=1 result=null", b1); @@ -86,14 +107,16 @@ public class RunWrapperTest { }); } - @Test public void updateSelf() throws Throwable { + @Test + void updateSelf() throws Throwable { sessions.then(j -> { WorkflowJob p = j.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "currentBuild.result = 'UNSTABLE'\n" + - "currentBuild.description = 'manipulated'\n" + - "currentBuild.displayName = 'special'\n" + - "def pb = currentBuild.previousBuild; if (pb != null) {pb.displayName = 'verboten'}", true)); + """ + currentBuild.result = 'UNSTABLE' + currentBuild.description = 'manipulated' + currentBuild.displayName = 'special' + def pb = currentBuild.previousBuild; if (pb != null) {pb.displayName = 'verboten'}""", true)); WorkflowRun b1 = j.buildAndAssertStatus(Result.UNSTABLE, p); assertEquals("manipulated", b1.getDescription()); assertEquals("special", b1.getDisplayName()); @@ -105,8 +128,8 @@ public class RunWrapperTest { }); } - @Issue("JENKINS-30412") - @Test public void getChangeSets() throws Throwable { + @Issue("JENKINS-30412") @Test + void getChangeSets() throws Throwable { sessions.then(j -> { sampleRepo1.init(); sampleRepo2.init(); @@ -146,15 +169,17 @@ public class RunWrapperTest { }); } - @Issue("JENKINS-37366") - @Test public void projectInfoFromCurrentBuild() throws Throwable { + @Issue("JENKINS-37366") @Test + void projectInfoFromCurrentBuild() throws Throwable { sessions.then(j -> { MockFolder folder = j.createFolder("this-folder"); WorkflowJob p = folder.createProject(WorkflowJob.class, "this-job"); p.setDefinition(new CpsFlowDefinition( - "echo \"currentBuild.fullDisplayName='${currentBuild.fullDisplayName}'\"\n" + - "echo \"currentBuild.projectName='${currentBuild.projectName}'\"\n" + - "echo \"currentBuild.fullProjectName='${currentBuild.fullProjectName}'\"\n", true)); + """ + echo "currentBuild.fullDisplayName='${currentBuild.fullDisplayName}'" + echo "currentBuild.projectName='${currentBuild.projectName}'" + echo "currentBuild.fullProjectName='${currentBuild.fullProjectName}'" + """, true)); WorkflowRun b = j.buildAndAssertSuccess(p); { // TODO mojibake until https://github.com/jenkinsci/workflow-job-plugin/pull/89 is released and can be consumed as a test dependency; expect this-folder ยป this-job #1 j.assertLogContains("currentBuild.fullDisplayName='this-folder", b); @@ -165,13 +190,15 @@ public class RunWrapperTest { }); } - @Issue("JENKINS-42952") - @Test public void duration() throws Throwable { + @Issue("JENKINS-42952") @Test + void duration() throws Throwable { sessions.then(j -> { WorkflowJob p = j.createProject(WorkflowJob.class, "this-job"); p.setDefinition(new CpsFlowDefinition( - "echo \"currentBuild.duration='${currentBuild.duration}'\"\n" + - "echo \"currentBuild.durationString='${currentBuild.durationString}'\"\n", true)); + """ + echo "currentBuild.duration='${currentBuild.duration}'" + echo "currentBuild.durationString='${currentBuild.durationString}'" + """, true)); WorkflowRun b = j.buildAndAssertSuccess(p); j.assertLogNotContains("currentBuild.duration='0'", b); j.assertLogNotContains("currentBuild.durationString='" + Messages.Run_NotStartedYet() + "'", b); @@ -179,45 +206,47 @@ public class RunWrapperTest { } - @Issue("JENKINS-37366") - @Test public void getCurrentResult() throws Throwable { + @Issue("JENKINS-37366") @Test + void getCurrentResult() throws Throwable { sessions.then(j -> { MockFolder folder = j.createFolder("this-folder"); WorkflowJob p = folder.createProject(WorkflowJob.class, "current-result-job"); p.setDefinition(new CpsFlowDefinition( - "echo \"initial currentBuild.currentResult='${currentBuild.currentResult}'\"\n" + - "currentBuild.result = 'UNSTABLE'\n" + - "echo \"final currentBuild.currentResult='${currentBuild.currentResult}'\"\n" + - "echo \"resultIsBetterOrEqualTo FAILURE: ${currentBuild.resultIsBetterOrEqualTo('FAILURE')}\"\n" + - "echo \"resultIsWorseOrEqualTo SUCCESS: ${currentBuild.resultIsWorseOrEqualTo('SUCCESS')}\"\n", + """ + echo "initial currentBuild.currentResult='${currentBuild.currentResult}'" + currentBuild.result = 'UNSTABLE' + echo "final currentBuild.currentResult='${currentBuild.currentResult}'" + echo "resultIsBetterOrEqualTo FAILURE: ${currentBuild.resultIsBetterOrEqualTo('FAILURE')}" + echo "resultIsWorseOrEqualTo SUCCESS: ${currentBuild.resultIsWorseOrEqualTo('SUCCESS')}" + """, true)); WorkflowRun b = j.buildAndAssertStatus(Result.UNSTABLE, p); - j.assertLogContains("initial currentBuild.currentResult='" + Result.SUCCESS.toString() + "'", b); - j.assertLogContains("final currentBuild.currentResult='" + Result.UNSTABLE.toString() + "'", b); + j.assertLogContains("initial currentBuild.currentResult='" + Result.SUCCESS + "'", b); + j.assertLogContains("final currentBuild.currentResult='" + Result.UNSTABLE + "'", b); j.assertLogContains("resultIsBetterOrEqualTo FAILURE: true", b); j.assertLogContains("resultIsWorseOrEqualTo SUCCESS: true", b); }); } - @Issue("JENKINS-36528") - @Test public void freestyleEnvVars() throws Throwable { + @Issue("JENKINS-36528") @Test + void freestyleEnvVars() throws Throwable { sessions.then(j -> { WorkflowJob p = j.createProject(WorkflowJob.class, "pipeline-job"); FreeStyleProject f = j.createProject(FreeStyleProject.class, "freestyle-job"); f.addProperty(new ParametersDefinitionProperty(new StringParameterDefinition("param", "default"))); p.setDefinition(new CpsFlowDefinition( - "def b = build(job: 'freestyle-job', parameters: [string(name: 'param', value: 'something')])\n" + - "echo \"b.buildVariables.BUILD_TAG='${b.buildVariables.BUILD_TAG}'\"\n" + - "echo \"b.buildVariables.param='${b.buildVariables.param}'\"\n", true)); + """ + def b = build(job: 'freestyle-job', parameters: [string(name: 'param', value: 'something')]) + echo "b.buildVariables.BUILD_TAG='${b.buildVariables.BUILD_TAG}'" + echo "b.buildVariables.param='${b.buildVariables.param}'" + """, true)); WorkflowRun b = j.buildAndAssertSuccess(p); j.assertLogContains("b.buildVariables.BUILD_TAG='jenkins-freestyle-job-1'", b); j.assertLogContains("b.buildVariables.param='something'", b); }); } - @Test - @Issue("JENKINS-54227") - public void buildCauseTest() throws Throwable { + @Test @Issue("JENKINS-54227") void buildCauseTest() throws Throwable { sessions.then(j -> { WorkflowJob job = j.createProject(WorkflowJob.class, "test"); // test with a single build cause @@ -270,18 +299,19 @@ public void buildCauseTest() throws Throwable { } - @Issue("JENKINS-31576") - @Test - public void upstreamBuilds() throws Throwable { + @Issue("JENKINS-31576") @Test + void upstreamBuilds() throws Throwable { sessions.then(j -> { WorkflowJob first = j.createProject(WorkflowJob.class, "first-job"); WorkflowJob second = j.createProject(WorkflowJob.class, "second-job"); WorkflowJob third = j.createProject(WorkflowJob.class, "third-job"); first.setDefinition(new CpsFlowDefinition("build job: 'second-job'\n", true)); second.setDefinition(new CpsFlowDefinition("build job: 'third-job'\n", true)); - third.setDefinition(new CpsFlowDefinition("currentBuild.upstreamBuilds?.each { b ->\n" + - " echo \"b: ${b.getFullDisplayName()}\"\n" + - "}\n", true)); + third.setDefinition(new CpsFlowDefinition(""" + currentBuild.upstreamBuilds?.each { b -> + echo "b: ${b.getFullDisplayName()}" + } + """, true)); WorkflowRun firstRun = j.buildAndAssertSuccess(first); WorkflowRun secondRun = second.getBuildByNumber(1); @@ -294,9 +324,7 @@ public void upstreamBuilds() throws Throwable { }); } - @Test - @Issue("JENKINS-73421") - public void externalizableId() throws Throwable { + @Test @Issue("JENKINS-73421") void externalizableId() throws Throwable { sessions.then(j -> { WorkflowJob first = j.createProject(WorkflowJob.class, "first-job"); first.setDefinition(new CpsFlowDefinition("echo(/externalizableId=$currentBuild.externalizableId/)", true)); diff --git a/src/test/java/org/jenkinsci/plugins/workflow/support/storage/AbstractStorageTest.java b/src/test/java/org/jenkinsci/plugins/workflow/support/storage/AbstractStorageTest.java index 6acecf69..d181f782 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/support/storage/AbstractStorageTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/support/storage/AbstractStorageTest.java @@ -5,53 +5,59 @@ import org.jenkinsci.plugins.workflow.actions.BodyInvocationAction; import org.jenkinsci.plugins.workflow.actions.LabelAction; import org.jenkinsci.plugins.workflow.graph.AtomNode; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.Test; -import org.jvnet.hudson.test.BuildWatcher; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import org.jvnet.hudson.test.JenkinsRule; +import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension; +import org.jvnet.hudson.test.junit.jupiter.WithJenkins; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + /** * Base test for the storage implementations * @author Sam Van Oort */ -public abstract class AbstractStorageTest { - @ClassRule - public static BuildWatcher buildWatcher = new BuildWatcher(); +@WithJenkins +abstract class AbstractStorageTest { + + @SuppressWarnings("unused") + @RegisterExtension + private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension(); - @Rule - public JenkinsRule j = new JenkinsRule(); + protected JenkinsRule j; - File storageDir; - XmlFile file; + protected File storageDir; + protected XmlFile file; - @Before - public void setup() { + @BeforeEach + void beforeEach(JenkinsRule rule) { + j = rule; File dir = new File(j.jenkins.getRootDir(), "storageTest"); dir.delete(); storageDir = new File(dir, "storage"); file = new XmlFile(new File(dir, "execution.xml")); } - @After - public void teardown() { + @AfterEach + void afterEach() { File dir = new File(j.jenkins.getRootDir(), "storageTest"); dir.delete(); } // Implement me for the implementation we're testing - public abstract FlowNodeStorage instantiateStorage(MockFlowExecution exec, File storageDirectory); + protected abstract FlowNodeStorage instantiateStorage(MockFlowExecution exec, File storageDirectory); /** Tests that basic nodes read and write correctly */ @Test - public void verifyBasicPersist() throws Exception { + void verifyBasicPersist() throws Exception { MockFlowExecution mock = new MockFlowExecution(); FlowNodeStorage storage = instantiateStorage(mock, storageDir); mock.setStorage(storage); @@ -78,15 +84,15 @@ public void verifyBasicPersist() throws Exception { AtomNode deferredSave = new StorageTestUtils.SimpleAtomNode(mock, "deferredSave", notQuiteAsSimple); storage.storeNode(deferredSave, true); deferredSave.addAction(new LabelAction("I was deferred but should still be written")); - assert !storage.isPersistedFully(); + assertFalse(storage.isPersistedFully()); storage.flush(); - assert storage.isPersistedFully(); + assertTrue(storage.isPersistedFully()); // Now we try to read it back MockFlowExecution mock2 = new MockFlowExecution(); FlowNodeStorage storageAfterRead = instantiateStorage(mock2, storageDir); - assert storage.isPersistedFully(); + assertTrue(storage.isPersistedFully()); StorageTestUtils.assertNodesMatch(simple, storageAfterRead.getNode(simple.getId())); StorageTestUtils.assertNodesMatch(notQuiteAsSimple, storageAfterRead.getNode(notQuiteAsSimple.getId())); @@ -96,6 +102,4 @@ public void verifyBasicPersist() throws Exception { // Ensures we can still read the correct node from deferred version StorageTestUtils.assertNodesMatch(storage.getNode(deferredSave.getId()), storage.getNode(deferredSave.getId())); } - - } diff --git a/src/test/java/org/jenkinsci/plugins/workflow/support/storage/BulkFlowNodeStorageTest.java b/src/test/java/org/jenkinsci/plugins/workflow/support/storage/BulkFlowNodeStorageTest.java index e85bdb74..a286989b 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/support/storage/BulkFlowNodeStorageTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/support/storage/BulkFlowNodeStorageTest.java @@ -36,10 +36,11 @@ import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition; import org.jenkinsci.plugins.workflow.cps.nodes.StepStartNode; import org.jenkinsci.plugins.workflow.job.WorkflowJob; -import org.junit.Rule; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.jvnet.hudson.test.JenkinsRule; -import org.jvnet.hudson.test.LoggerRule; +import org.jvnet.hudson.test.LogRecorder; +import org.jvnet.hudson.test.junit.jupiter.WithJenkins; import org.jvnet.hudson.test.recipes.LocalData; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -49,12 +50,21 @@ import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; -public final class BulkFlowNodeStorageTest { +@WithJenkins +class BulkFlowNodeStorageTest { - @Rule public JenkinsRule r = new JenkinsRule(); - @Rule public LoggerRule logger = new LoggerRule().record(RobustReflectionConverter.class, Level.FINE).capture(50); + @SuppressWarnings("unused") + private final LogRecorder logger = new LogRecorder().record(RobustReflectionConverter.class, Level.FINE).capture(50); - @Test public void orderOfEntries() throws Exception { + private JenkinsRule r; + + @BeforeEach + void beforeEach(JenkinsRule rule) { + r = rule; + } + + @Test + void orderOfEntries() throws Exception { var p = r.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition("for (int i = 1; i <= 40; i++) {echo(/step #$i/)}", true)); var b = r.buildAndAssertSuccess(p); @@ -70,7 +80,8 @@ public final class BulkFlowNodeStorageTest { } @LocalData - @Test public void actionDeserializationShouldBeRobust() throws Exception { + @Test + void actionDeserializationShouldBeRobust() throws Exception { /* var p = r.createProject(WorkflowJob.class); p.addProperty(new DurabilityHintJobProperty(FlowDurabilityHint.PERFORMANCE_OPTIMIZED)); diff --git a/src/test/java/org/jenkinsci/plugins/workflow/support/storage/BulkStorageTest.java b/src/test/java/org/jenkinsci/plugins/workflow/support/storage/BulkStorageTest.java index 783088f8..c8175bcd 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/support/storage/BulkStorageTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/support/storage/BulkStorageTest.java @@ -3,24 +3,26 @@ import org.jenkinsci.plugins.workflow.actions.BodyInvocationAction; import org.jenkinsci.plugins.workflow.actions.LabelAction; import org.jenkinsci.plugins.workflow.graph.AtomNode; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; import java.io.File; /** * Actually attempts to test the storage engine */ -public class BulkStorageTest extends AbstractStorageTest { +class BulkStorageTest extends AbstractStorageTest { @Override - public FlowNodeStorage instantiateStorage(MockFlowExecution exec, File storageDirectory) { + protected FlowNodeStorage instantiateStorage(MockFlowExecution exec, File storageDirectory) { return new BulkFlowNodeStorage(exec, storageDir); } /** Tests the bulk-flushing behavior works as advertised. */ @Test - public void testDeferWriteAndFlush() throws Exception { + void testDeferWriteAndFlush() throws Exception { MockFlowExecution mock = new MockFlowExecution(); FlowNodeStorage storage = instantiateStorage(mock, storageDir); mock.setStorage(storage); @@ -49,7 +51,7 @@ public void testDeferWriteAndFlush() throws Exception { storageAfterRead = instantiateStorage(mock2, storageDir); assert storageAfterRead.isPersistedFully(); mock2.setStorage(storageAfterRead); - Assert.assertNull(storageAfterRead.getNode(deferredWriteNode.getId())); + assertNull(storageAfterRead.getNode(deferredWriteNode.getId())); StorageTestUtils.assertNodesMatch(directlyStored, storageAfterRead.getNode(directlyStored.getId())); // Make sure we didn't corrupt old node either // Flush the deferred one and confirm it's on disk now @@ -64,6 +66,6 @@ public void testDeferWriteAndFlush() throws Exception { assert !storage.isPersistedFully(); storageAfterRead = instantiateStorage(mock2, storageDir); mock2.setStorage(storageAfterRead); - Assert.assertEquals(1, storageAfterRead.getNode(deferredWriteNode.getId()).getActions().size()); + assertEquals(1, storageAfterRead.getNode(deferredWriteNode.getId()).getActions().size()); } } diff --git a/src/test/java/org/jenkinsci/plugins/workflow/support/storage/MockFlowExecution.java b/src/test/java/org/jenkinsci/plugins/workflow/support/storage/MockFlowExecution.java index 00e9f745..e3d98542 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/support/storage/MockFlowExecution.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/support/storage/MockFlowExecution.java @@ -25,6 +25,7 @@ class MockFlowExecution extends FlowExecution { List heads = new ArrayList<>(); transient FlowNodeStorage storage; + @SuppressWarnings("unused") MockFlowExecution(@NonNull FlowNodeStorage storage) { this.storage = storage; } diff --git a/src/test/java/org/jenkinsci/plugins/workflow/support/storage/SimpleXStreamStorageTest.java b/src/test/java/org/jenkinsci/plugins/workflow/support/storage/SimpleXStreamStorageTest.java index 05ac1cea..c31fd641 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/support/storage/SimpleXStreamStorageTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/support/storage/SimpleXStreamStorageTest.java @@ -11,31 +11,32 @@ import org.jenkinsci.plugins.workflow.cps.nodes.StepStartNode; import org.jenkinsci.plugins.workflow.graph.AtomNode; import org.jenkinsci.plugins.workflow.job.WorkflowJob; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.jvnet.hudson.test.LoggerRule; +import org.junit.jupiter.api.Test; +import org.jvnet.hudson.test.LogRecorder; import org.jvnet.hudson.test.recipes.LocalData; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; /** * Tries to test the storage engine */ -public class SimpleXStreamStorageTest extends AbstractStorageTest { +class SimpleXStreamStorageTest extends AbstractStorageTest { - @Rule public LoggerRule logger = new LoggerRule().record(RobustReflectionConverter.class, Level.FINE).capture(50); + @SuppressWarnings("unused") + private final LogRecorder logger = new LogRecorder().record(RobustReflectionConverter.class, Level.FINE).capture(50); @Override - public FlowNodeStorage instantiateStorage(MockFlowExecution exec, File storageDirectory) { + protected FlowNodeStorage instantiateStorage(MockFlowExecution exec, File storageDirectory) { return new SimpleXStreamFlowNodeStorage(exec, storageDirectory); } /** Verify that when nodes are explicitly flushed they do write to disk. */ @Test - public void testDeferWriteAndFlush() throws Exception { + void testDeferWriteAndFlush() throws Exception { MockFlowExecution mock = new MockFlowExecution(); FlowNodeStorage storage = instantiateStorage(mock, storageDir); mock.setStorage(storage); @@ -60,8 +61,7 @@ public void testDeferWriteAndFlush() throws Exception { mock2.setStorage(storageAfterRead); StorageTestUtils.assertNodesMatch(directlyStored, storageAfterRead.getNode(directlyStored.getId())); - Assert.assertNull(storageAfterRead.getNode(deferredWriteNode.getId())); - + assertNull(storageAfterRead.getNode(deferredWriteNode.getId())); // Flush the deferred one and confirm it's on disk now storage.flushNode(deferredWriteNode); @@ -75,7 +75,7 @@ public void testDeferWriteAndFlush() throws Exception { assert !storage.isPersistedFully(); storageAfterRead = instantiateStorage(mock2, storageDir); mock2.setStorage(storageAfterRead); - Assert.assertEquals(1, storageAfterRead.getNode(deferredWriteNode.getId()).getActions().size()); + assertEquals(1, storageAfterRead.getNode(deferredWriteNode.getId()).getActions().size()); // Mark node for autopersist and confirm it actually does now by adding a new action storage.autopersist(deferredWriteNode); @@ -87,7 +87,8 @@ public void testDeferWriteAndFlush() throws Exception { } @LocalData - @Test public void actionDeserializationShouldBeRobust() throws Exception { + @Test + void actionDeserializationShouldBeRobust() throws Exception { /* var p = j.createProject(WorkflowJob.class); p.addProperty(new DurabilityHintJobProperty(FlowDurabilityHint.MAX_SURVIVABILITY)); diff --git a/src/test/java/org/jenkinsci/plugins/workflow/support/storage/StorageTestUtils.java b/src/test/java/org/jenkinsci/plugins/workflow/support/storage/StorageTestUtils.java index 634c80ce..62546e9d 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/support/storage/StorageTestUtils.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/support/storage/StorageTestUtils.java @@ -4,10 +4,12 @@ import org.jenkinsci.plugins.workflow.flow.FlowExecution; import org.jenkinsci.plugins.workflow.graph.AtomNode; import org.jenkinsci.plugins.workflow.graph.FlowNode; -import org.junit.Assert; import java.util.List; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; + /** * Utilities for verifying storage * @author Sam Van Oort @@ -15,22 +17,22 @@ class StorageTestUtils { /** Test that the basic fields and the actions for nodes match */ - public static void assertNodesMatch(FlowNode expected, FlowNode actual) throws Exception { - Assert.assertEquals(expected.getId(), actual.getId()); - Assert.assertEquals(expected.getClass().toString(), actual.getClass().toString()); - Assert.assertArrayEquals(expected.getParentIds().toArray(), actual.getParentIds().toArray()); + public static void assertNodesMatch(FlowNode expected, FlowNode actual) { + assertEquals(expected.getId(), actual.getId()); + assertEquals(expected.getClass().toString(), actual.getClass().toString()); + assertArrayEquals(expected.getParentIds().toArray(), actual.getParentIds().toArray()); List expectedActionList = expected.getActions(); List actualActionList = actual.getActions(); - Assert.assertEquals(expectedActionList.size(), actualActionList.size()); + assertEquals(expectedActionList.size(), actualActionList.size()); for (int i=0; i actions) { } SimpleAtomNode(FlowExecution exec, String id) { - super(exec, id, new FlowNode[]{}); + super(exec, id); } } } diff --git a/src/test/java/org/jenkinsci/plugins/workflow/support/visualization/table/FlowGraphTableTest.java b/src/test/java/org/jenkinsci/plugins/workflow/support/visualization/table/FlowGraphTableTest.java index 95aebf32..570c7273 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/support/visualization/table/FlowGraphTableTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/support/visualization/table/FlowGraphTableTest.java @@ -27,31 +27,40 @@ import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.hasSize; +import static org.junit.jupiter.api.Assertions.fail; + import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition; import org.jenkinsci.plugins.workflow.job.WorkflowJob; import org.jenkinsci.plugins.workflow.job.WorkflowRun; import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep; -import static org.junit.Assert.fail; -import org.junit.Rule; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; +import org.jvnet.hudson.test.junit.jupiter.WithJenkins; import org.jvnet.hudson.test.recipes.LocalData; -public class FlowGraphTableTest { +@WithJenkins +class FlowGraphTableTest { + + private JenkinsRule r; - @Rule - public JenkinsRule r = new JenkinsRule(); + @BeforeEach + void beforeEach(JenkinsRule rule) { + r = rule; + } @Test - public void smokes() throws Exception { + void smokes() throws Exception { WorkflowJob p = r.createProject(WorkflowJob.class); p.setDefinition(new CpsFlowDefinition( - "echo('Hello, world!')\n" + - "timeout(time: 1, unit: 'MINUTES') {\n" + - " echo('Hello again, world!')\n" + - "}\n" + - "echo('Goodbye, world!')\n", true)); + """ + echo('Hello, world!') + timeout(time: 1, unit: 'MINUTES') { + echo('Hello again, world!') + } + echo('Goodbye, world!') + """, true)); WorkflowRun b = r.buildAndAssertSuccess(p); FlowGraphTable t = new FlowGraphTable(b.getExecution()); t.build(); @@ -60,20 +69,22 @@ public void smokes() throws Exception { } @Test - public void parallelSmokes() throws Exception { + void parallelSmokes() throws Exception { WorkflowJob p = r.createProject(WorkflowJob.class); p.setDefinition(new CpsFlowDefinition( - "echo('Hello, world!')\n" + - "parallel(one: {\n" + - " timeout(time: 1, unit: 'MINUTES') {\n" + - " echo('Hello, branch one!')\n" + - " }\n" + - "}, two: {\n" + - " timeout(time: 1, unit: 'MINUTES') {\n" + - " echo('Hello, branch two!')\n" + - " }\n" + - "})\n" + - "echo('Goodbye, world!')\n", true)); + """ + echo('Hello, world!') + parallel(one: { + timeout(time: 1, unit: 'MINUTES') { + echo('Hello, branch one!') + } + }, two: { + timeout(time: 1, unit: 'MINUTES') { + echo('Hello, branch two!') + } + }) + echo('Goodbye, world!') + """, true)); WorkflowRun b = r.buildAndAssertSuccess(p); FlowGraphTable t = new FlowGraphTable(b.getExecution()); t.build(); @@ -84,7 +95,7 @@ public void parallelSmokes() throws Exception { @Issue("JENKINS-62545") @LocalData // There is no known way to reproduce the issue from scratch, so we use a fake build with redacted flow node XML files from a real build that had the problem. @Test - public void corruptedFlowGraph() throws Exception { + void corruptedFlowGraph() { WorkflowJob p = r.jenkins.getItemByFullName("test0", WorkflowJob.class); WorkflowRun b = p.getBuildByNumber(1); FlowGraphTable t = new FlowGraphTable(b.getExecution()); @@ -97,25 +108,26 @@ public void corruptedFlowGraph() throws Exception { } @Test - public void rowDisplayName() throws Exception { + void rowDisplayName() throws Exception { WorkflowJob p = r.createProject(WorkflowJob.class); p.setDefinition(new CpsFlowDefinition( - "stage('start') {\n" + - " echo 'some message'\n" + - " def i = 0; retry(3) {\n" + - " if (++i < 3) error 'oops'\n" + - " node {\n" + - " isUnix()\n" + - " }\n" + - " }\n" + - "}\n" + - "stage('main') {\n" + - " parallel quick: {\n" + - " echo 'done'\n" + - " }, slow: {\n" + - " semaphore 'wait'\n" + - " }\n" + - "}", true)); + """ + stage('start') { + echo 'some message' + def i = 0; retry(3) { + if (++i < 3) error 'oops' + node { + isUnix() + } + } + } + stage('main') { + parallel quick: { + echo 'done' + }, slow: { + semaphore 'wait' + } + }""", true)); WorkflowRun b = p.scheduleBuild2(0).waitForStart(); SemaphoreStep.waitForStart("wait/1", b); FlowGraphTable t = new FlowGraphTable(b.getExecution()); @@ -144,5 +156,4 @@ public void rowDisplayName() throws Exception { " parallel block (Branch: slow)", " semaphore")); } - } diff --git a/src/test/java/org/jenkinsci/plugins/workflow/test/steps/BlockSemaphoreStep.java b/src/test/java/org/jenkinsci/plugins/workflow/test/steps/BlockSemaphoreStep.java index e4ba829a..444e59cc 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/test/steps/BlockSemaphoreStep.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/test/steps/BlockSemaphoreStep.java @@ -68,7 +68,8 @@ public State getState() { return state; } - @Override public StepExecution start(final StepContext context) throws Exception { + @Override + public StepExecution start(final StepContext context) throws Exception { this.context = context; return new StepExecution(context) { @Override @@ -128,33 +129,41 @@ public void finishFailure(Throwable t) { context.onFailure(t); } - @Override public StepDescriptor getDescriptor() { + @Override + public StepDescriptor getDescriptor() { return new DescriptorImpl(); } - /* not an @Extension */ private static final class DescriptorImpl extends StepDescriptor { + /* not an @Extension */ + private static final class DescriptorImpl extends StepDescriptor { - @Override public Set> getRequiredContext() { + @Override + public Set> getRequiredContext() { throw new UnsupportedOperationException(); } - @Override public String getFunctionName() { + @Override + public String getFunctionName() { throw new UnsupportedOperationException(); } - @Override public Step newInstance(Map arguments) { + @Override + public Step newInstance(Map arguments) { throw new UnsupportedOperationException(); } - @Override public Map defineArguments(Step step) throws UnsupportedOperationException { + @Override + public Map defineArguments(Step step) throws UnsupportedOperationException { throw new UnsupportedOperationException(); } - @Override public String getDisplayName() { + @Override + public String getDisplayName() { return "Test block step"; } - @Override public boolean takesImplicitBlockArgument() { + @Override + public boolean takesImplicitBlockArgument() { return true; } diff --git a/src/test/java/org/jenkinsci/plugins/workflow/test/steps/SemaphoreStep.java b/src/test/java/org/jenkinsci/plugins/workflow/test/steps/SemaphoreStep.java index 0bacf24c..cadc9c80 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/test/steps/SemaphoreStep.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/test/steps/SemaphoreStep.java @@ -28,6 +28,7 @@ import hudson.model.Run; import java.io.File; import java.io.IOException; +import java.io.Serial; import java.io.Serializable; import java.util.HashMap; import java.util.HashSet; @@ -88,7 +89,8 @@ synchronized int allocateNumber(String id) { private final String id; private final int number; - @DataBoundConstructor public SemaphoreStep(String id) { + @DataBoundConstructor + public SemaphoreStep(String id) { this.id = id; number = State.get().allocateNumber(id); } @@ -171,7 +173,8 @@ public static void waitForStart(@NonNull String k, @CheckForNull Run b) thr } } - @Override public StepExecution start(StepContext context) throws Exception { + @Override + public StepExecution start(StepContext context) throws Exception { return new Execution(context, k()); } @@ -184,7 +187,8 @@ public static class Execution extends AbstractStepExecutionImpl { this.k = k; } - @Override public boolean start() throws Exception { + @Override + public boolean start() throws Exception { State s = State.get(); Object returnValue = null; Throwable error = null; @@ -218,7 +222,8 @@ public static class Execution extends AbstractStepExecutionImpl { return sync; } - @Override public void stop(Throwable cause) throws Exception { + @Override + public void stop(Throwable cause) throws Exception { State s = State.get(); synchronized (s) { s.contexts.remove(k); @@ -227,32 +232,39 @@ public static class Execution extends AbstractStepExecutionImpl { super.stop(cause); } - @Override public String getStatus() { + @Override + public String getStatus() { State s = State.get(); synchronized (s) { return s.contexts.containsKey(k) ? "waiting on " + k : "finished " + k; } } + @Serial private static final long serialVersionUID = 1L; } - @Extension public static final class DescriptorImpl extends StepDescriptor { + @SuppressWarnings("unused") + @Extension + public static final class DescriptorImpl extends StepDescriptor { - @Override public String getFunctionName() { + @Override + public String getFunctionName() { return "semaphore"; } - @Override public String getDisplayName() { + @Override + public String getDisplayName() { return "Test step"; } - @Override public Set> getRequiredContext() { + @Override + public Set> getRequiredContext() { return Set.of(); } - } + @Serial private static final long serialVersionUID = 1L; } diff --git a/src/test/java/org/jenkinsci/plugins/workflow/test/steps/SemaphoreStepTest.java b/src/test/java/org/jenkinsci/plugins/workflow/test/steps/SemaphoreStepTest.java index 648ccac3..296c6189 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/test/steps/SemaphoreStepTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/test/steps/SemaphoreStepTest.java @@ -4,20 +4,29 @@ import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition; import org.jenkinsci.plugins.workflow.job.WorkflowJob; import org.jenkinsci.plugins.workflow.job.WorkflowRun; -import org.junit.Rule; -import org.junit.Test; -import org.jvnet.hudson.test.BuildWatcher; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import org.jvnet.hudson.test.JenkinsRule; +import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension; +import org.jvnet.hudson.test.junit.jupiter.WithJenkins; -public class SemaphoreStepTest { - @Rule - public JenkinsRule j = new JenkinsRule(); +@WithJenkins +class SemaphoreStepTest { - @Rule - public BuildWatcher watcher = new BuildWatcher(); + @SuppressWarnings("unused") + @RegisterExtension + private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension(); + + private JenkinsRule j; + + @BeforeEach + void beforeEach(JenkinsRule rule) { + j = rule; + } @Test - public void hardKill() throws Exception { + void hardKill() throws Exception { WorkflowJob p1 = j.jenkins.createProject(WorkflowJob.class, "p"); p1.setDefinition(new CpsFlowDefinition("echo 'locked!'; semaphore 'wait'")); WorkflowRun b = p1.scheduleBuild2(0).waitForStart(); diff --git a/src/test/java/org/jenkinsci/plugins/workflow/test/steps/SynchronousResumeNotSupportedExceptionTest.java b/src/test/java/org/jenkinsci/plugins/workflow/test/steps/SynchronousResumeNotSupportedExceptionTest.java index 62456099..c283a656 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/test/steps/SynchronousResumeNotSupportedExceptionTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/test/steps/SynchronousResumeNotSupportedExceptionTest.java @@ -9,12 +9,11 @@ import org.jenkinsci.plugins.workflow.steps.StepDescriptor; import org.jenkinsci.plugins.workflow.steps.StepExecution; import org.jenkinsci.plugins.workflow.steps.StepExecutions; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.Test; -import org.jvnet.hudson.test.BuildWatcher; -import org.jvnet.hudson.test.JenkinsSessionRule; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import org.jvnet.hudson.test.TestExtension; +import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension; +import org.jvnet.hudson.test.junit.jupiter.JenkinsSessionExtension; import org.kohsuke.stapler.DataBoundConstructor; import hudson.model.TaskListener; @@ -23,23 +22,24 @@ import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.containsString; -public class SynchronousResumeNotSupportedExceptionTest { +class SynchronousResumeNotSupportedExceptionTest { - @ClassRule - public static BuildWatcher bw = new BuildWatcher(); + @SuppressWarnings("unused") + @RegisterExtension + private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension(); - @Rule - public JenkinsSessionRule rjr = new JenkinsSessionRule(); + @RegisterExtension + private final JenkinsSessionExtension sessions = new JenkinsSessionExtension(); @Test - public void test_SynchronousResumeNotSupportedException_ShouldShowFailedStep_AndSuggestRetry() throws Throwable { - rjr.then(j -> { + void test_SynchronousResumeNotSupportedException_ShouldShowFailedStep_AndSuggestRetry() throws Throwable { + sessions.then(j -> { WorkflowJob p = j.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition("simulatedSleep 20", true)); var run = p.scheduleBuild2(0).waitForStart(); j.waitForMessage("Going to sleep for", run); }); - rjr.then(j -> { + sessions.then(j -> { var b = j.jenkins.getItemByFullName("p", WorkflowJob.class).getBuildByNumber(1); j.waitForCompletion(b); assertThat(b.getLog(), allOf( diff --git a/src/test/java/org/jenkinsci/plugins/workflow/test/steps/input/POSTHyperlinkNoteTest.java b/src/test/java/org/jenkinsci/plugins/workflow/test/steps/input/POSTHyperlinkNoteTest.java index 184c45f1..65466cab 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/test/steps/input/POSTHyperlinkNoteTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/test/steps/input/POSTHyperlinkNoteTest.java @@ -18,13 +18,14 @@ import org.jenkinsci.plugins.workflow.steps.StepExecution; import org.jenkinsci.plugins.workflow.steps.SynchronousStepExecution; import org.jenkinsci.plugins.workflow.support.steps.input.POSTHyperlinkNote; -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.JenkinsRule.WebClient; import org.jvnet.hudson.test.TestExtension; +import org.jvnet.hudson.test.junit.jupiter.WithJenkins; import org.kohsuke.stapler.DataBoundConstructor; import org.htmlunit.HttpMethod; import org.htmlunit.MockWebConnection; @@ -42,38 +43,43 @@ import hudson.model.queue.QueueTaskFuture; import jenkins.model.Jenkins; -public class POSTHyperlinkNoteTest { +@WithJenkins +class POSTHyperlinkNoteTest { - @Rule - public JenkinsRule jr = new JenkinsRule(); + private JenkinsRule r; + + @BeforeEach + void beforeEach(JenkinsRule rule) { + r = rule; + } @Test @Issue("SECURITY-2881") - public void urlsAreSafeFromJavascriptInjection() throws Exception { + void urlsAreSafeFromJavascriptInjection() throws Exception { testSanitization("whatever/'+alert(1)+'"); } @Test - @Ignore("webclient does not support unicode URLS and this is passed as /jenkins/whatever/%F0%9F%99%88%F0%9F%99%89%F0%9F%99%8A%F0%9F%98%80%E2%98%BA") - public void testPassingMultiByteCharacters() throws Exception { + @Disabled("webclient does not support unicode URLS and this is passed as /jenkins/whatever/%F0%9F%99%88%F0%9F%99%89%F0%9F%99%8A%F0%9F%98%80%E2%98%BA") + void testPassingMultiByteCharacters() throws Exception { // this is actually illegal in HTML4 but common -> https://www.w3.org/TR/html40/appendix/notes.html#non-ascii-chars // browsers infer the URL from the charset and then encode the escaped characters... testSanitization("whatever/๐Ÿ™ˆ๐Ÿ™‰๐Ÿ™Š๐Ÿ˜€โ˜บ"); } @Test - public void testPassingSingleByte() throws Exception { + void testPassingSingleByte() throws Exception { testSanitization("whatever/something?withparameter=baa"); } void testSanitization(String fragment) throws Exception { - WorkflowJob project = jr.createProject(WorkflowJob.class); + WorkflowJob project = r.createProject(WorkflowJob.class); project.setDefinition(new CpsFlowDefinition("security2881(params.TEST_URL)\n", true)); project.addProperty(new ParametersDefinitionProperty(new StringParameterDefinition("TEST_URL", "WHOOPS"))); QueueTaskFuture scheduleBuild = project.scheduleBuild2(0, new ParametersAction(new StringParameterValue("TEST_URL", fragment))); - WorkflowRun run = jr.assertBuildStatus(Result.SUCCESS, scheduleBuild); - WebClient wc = jr.createWebClient(); + WorkflowRun run = r.assertBuildStatus(Result.SUCCESS, scheduleBuild); + WebClient wc = r.createWebClient(); HtmlPage page = wc.getPage(run, "console"); HtmlAnchor anchor = page.getAnchorByText("SECURITY-2881"); @@ -95,10 +101,11 @@ void testSanitization(String fragment) throws Exception { assertThat(request.getHttpMethod(), is(HttpMethod.POST)); URL url = request.getUrl(); System.out.println(url.toExternalForm()); - assertThat(url, allOf(hasProperty("host", is(new URL(jr.jenkins.getConfiguredRootUrl()).getHost())), - hasProperty("file", is(jr.contextPath + '/' + fragment)))); + assertThat(url, allOf(hasProperty("host", is(new URL(r.jenkins.getConfiguredRootUrl()).getHost())), + hasProperty("file", is(r.contextPath + '/' + fragment)))); } + @SuppressWarnings("unused") public static class Security2881ConsoleStep extends Step { private final String urlFragment; @@ -116,20 +123,24 @@ public StepExecution start(StepContext context) throws Exception { @TestExtension public static final class DescriptorImpl extends StepDescriptor { - @Override public String getFunctionName() { + @Override + public String getFunctionName() { return "security2881"; } @NonNull - @Override public String getDisplayName() { + @Override + public String getDisplayName() { return "Security2881"; } - @Override public Set> getRequiredContext() { + @Override + public Set> getRequiredContext() { return Collections.singleton(TaskListener.class); } - @Override public String argumentsToString(@NonNull Map namedArgs) { + @Override + public String argumentsToString(@NonNull Map namedArgs) { return null; } }