diff --git a/pom.xml b/pom.xml index fd1607b..85960ee 100644 --- a/pom.xml +++ b/pom.xml @@ -68,6 +68,7 @@ 2.479 ${jenkins.baseline}.3 false + false true @@ -82,6 +83,12 @@ + + org.awaitility + awaitility + 4.3.0 + test + org.mockito mockito-core diff --git a/src/test/java/org/jenkinsci/plugins/workflow/steps/AbstractStepImplTest.java b/src/test/java/org/jenkinsci/plugins/workflow/steps/AbstractStepImplTest.java index 4d11693..4c24880 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/steps/AbstractStepImplTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/steps/AbstractStepImplTest.java @@ -3,11 +3,12 @@ import hudson.Extension; import hudson.model.Node; import jenkins.model.Jenkins; -import static org.junit.Assert.*; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.jvnet.hudson.test.JenkinsRule; +import org.jvnet.hudson.test.junit.jupiter.WithJenkins; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.DataBoundSetter; @@ -21,21 +22,22 @@ * @author Kohsuke Kawaguchi */ @SuppressWarnings("deprecation") // it is all deprecated -public class AbstractStepImplTest { - @Rule - public JenkinsRule j = new JenkinsRule(); +@WithJenkins +class AbstractStepImplTest { + + private JenkinsRule j; @Inject - BogusStep.DescriptorImpl d; + private BogusStep.DescriptorImpl d; - @Before - public void setUp() { + @BeforeEach + void setUp(JenkinsRule rule) { + j = rule; j.getInstance().getInjector().injectMembers(this); } @Test - public void inject() throws Exception { - + void inject() throws Exception { Map r = new HashMap<>(); r.put("a",3); r.put("b","bbb"); @@ -43,10 +45,10 @@ public void inject() throws Exception { r.put("d","ddd"); BogusStep step = (BogusStep) d.newInstance(r); - assertEquals(step.a,3); - assertEquals(step.b,"bbb"); + assertEquals(3, step.a); + assertEquals("bbb", step.b); assertNull(step.c); - assertEquals(step.d,"ddd"); + assertEquals("ddd", step.d); StepContext c = mock(StepContext.class); when(c.get(Node.class)).thenReturn(j.getInstance()); @@ -56,10 +58,12 @@ public void inject() throws Exception { } public static class BogusStep extends AbstractStepImpl { - int a; - String b; - @DataBoundSetter String c; - Object d; + + private int a; + private String b; + @DataBoundSetter + private String c; + private Object d; @DataBoundConstructor public BogusStep(int a, String b) { @@ -92,11 +96,12 @@ public String getDisplayName() { } public static class BogusStepExecution extends AbstractSynchronousStepExecution { + @Inject - Jenkins jenkins; + private Jenkins jenkins; @StepContextParameter - Node n; + private Node n; @Override protected Void run() { diff --git a/src/test/java/org/jenkinsci/plugins/workflow/steps/DynamicContextTest.java b/src/test/java/org/jenkinsci/plugins/workflow/steps/DynamicContextTest.java index 8619b2d..d414833 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/steps/DynamicContextTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/steps/DynamicContextTest.java @@ -25,12 +25,15 @@ package org.jenkinsci.plugins.workflow.steps; import java.io.IOException; -import org.junit.Test; -import static org.junit.Assert.*; +import org.junit.jupiter.api.Test; -public class DynamicContextTest { +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertNotNull; - @Test public void subclassing() throws Exception { +class DynamicContextTest { + + @Test + void subclassing() throws Exception { class Super {} class Sub extends Super {} class Sub2 extends Super {} @@ -48,10 +51,9 @@ class Dyn extends DynamicContext.Typed { } } DynamicContext ctx = new Dyn(); - assertNotNull("can look up via supertype", ctx.get(Super.class, nullContext)); - assertNotNull("can look up via subtype", ctx.get(Sub.class, nullContext)); - assertNull("but not via a mismatched subtype", ctx.get(Sub2.class, nullContext)); - assertNull("nor via an unrelated supertype", ctx.get(Runnable.class, nullContext)); + assertNotNull(ctx.get(Super.class, nullContext), "can look up via supertype"); + assertNotNull(ctx.get(Sub.class, nullContext), "can look up via subtype"); + assertNull(ctx.get(Sub2.class, nullContext), "but not via a mismatched subtype"); + assertNull(ctx.get(Runnable.class, nullContext), "nor via an unrelated supertype"); } - } diff --git a/src/test/java/org/jenkinsci/plugins/workflow/steps/FlowInterruptedExceptionTest.java b/src/test/java/org/jenkinsci/plugins/workflow/steps/FlowInterruptedExceptionTest.java index eadb73f..a5a1cd6 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/steps/FlowInterruptedExceptionTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/steps/FlowInterruptedExceptionTest.java @@ -27,23 +27,23 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import hudson.model.Result; import hudson.model.Run; import jenkins.model.CauseOfInterruption; import org.jenkinsci.plugins.workflow.job.properties.DisableConcurrentBuildsJobProperty; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mock; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; /** * Tests some specific {@link FlowInterruptedException} APIs */ -public class FlowInterruptedExceptionTest { +class FlowInterruptedExceptionTest { @Test - public void getMessageReturnsCauses() { + void getMessageReturnsCauses() { // given Result result = Result.ABORTED; CauseOfInterruption cause1 = new ExceptionCause(new IllegalStateException("something went wrong")); @@ -58,11 +58,11 @@ public void getMessageReturnsCauses() { } @Test - public void toStringContainsCauses() { + void toStringContainsCauses() { // given Result result = Result.FAILURE; - Run run = Mockito.mock(Run.class); - Mockito.when(run.getDisplayName()).thenReturn("fracture.account"); + Run run = mock(Run.class); + when(run.getDisplayName()).thenReturn("fracture.account"); CauseOfInterruption cause = new DisableConcurrentBuildsJobProperty.CancelledCause(run); // when diff --git a/src/test/java/org/jenkinsci/plugins/workflow/steps/GeneralNonBlockingStepExecutionTest.java b/src/test/java/org/jenkinsci/plugins/workflow/steps/GeneralNonBlockingStepExecutionTest.java index e2ec8f0..47c3cb5 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/steps/GeneralNonBlockingStepExecutionTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/steps/GeneralNonBlockingStepExecutionTest.java @@ -24,10 +24,11 @@ package org.jenkinsci.plugins.workflow.steps; +import static org.awaitility.Awaitility.await; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.empty; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertTrue; import hudson.model.Result; import hudson.model.TaskListener; @@ -41,26 +42,41 @@ 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.Before; -import org.junit.ClassRule; -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.Issue; import org.jvnet.hudson.test.JenkinsRule; -import org.jvnet.hudson.test.LoggerRule; +import org.jvnet.hudson.test.LogRecorder; 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 GeneralNonBlockingStepExecutionTest { +@WithJenkins +class GeneralNonBlockingStepExecutionTest { - @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher(); + @SuppressWarnings("unused") + @RegisterExtension + private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension(); - @Rule public JenkinsRule r = new JenkinsRule(); + private static Semaphore startEnter, startExit, endEnter, endExit; + + private final LogRecorder logging = new LogRecorder(); - @Rule public LoggerRule logging = new LoggerRule(); + private JenkinsRule r; + + @BeforeEach + void setUp(JenkinsRule rule) { + r = rule; + startEnter = new Semaphore(0); + startExit = new Semaphore(0); + endEnter = new Semaphore(0); + endExit = new Semaphore(0); + } - @Test public void getStatus() throws Exception { + @Test + void getStatus() throws Exception { WorkflowJob p = r.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition("slowBlock {semaphore 'wait'}", true)); WorkflowRun b = p.scheduleBuild2(0).waitForStart(); @@ -71,9 +87,7 @@ public class GeneralNonBlockingStepExecutionTest { startExit.release(); SemaphoreStep.waitForStart("wait/1", b); assertThat(((CpsFlowExecution) b.getExecution()).getThreadDump().toString(), containsString("at DSL.slowBlock(not currently scheduled, or running blocks)")); - while (b.getExecutor().getAsynchronousExecution().blocksRestart()) { - Thread.sleep(100); // as above - } + await().until(() -> !b.getExecutor().getAsynchronousExecution().blocksRestart()); SemaphoreStep.success("wait/1", null); endEnter.acquire(); assertThat(((CpsFlowExecution) b.getExecution()).getThreadDump().toString(), containsString("at DSL.slowBlock(running in thread: org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution [#")); @@ -83,7 +97,8 @@ public class GeneralNonBlockingStepExecutionTest { r.assertBuildStatusSuccess(r.waitForCompletion(b)); } - @Test public void stop() throws Exception { + @Test + void stop() throws Exception { WorkflowJob p = r.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition("slowBlock {semaphore 'wait'}", true)); logging.record(CpsStepContext.class, Level.WARNING).capture(100); @@ -120,7 +135,8 @@ public class GeneralNonBlockingStepExecutionTest { } @Issue("JENKINS-58878") - @Test public void shouldNotHang() throws Exception { + @Test + void shouldNotHang() throws Exception { int iterations = 50; startExit.release(iterations); // Prevents the semaphores from blocking inside of the slowBlock step. endExit.release(iterations); @@ -134,34 +150,36 @@ public class GeneralNonBlockingStepExecutionTest { r.buildAndAssertSuccess(p); } - private static Semaphore startEnter, startExit, endEnter, endExit; + @SuppressWarnings("unused") + public static final class SlowBlockStep extends Step { - @Before public void semaphores() { - startEnter = new Semaphore(0); - startExit = new Semaphore(0); - endEnter = new Semaphore(0); - endExit = new Semaphore(0); - } + @DataBoundConstructor + public SlowBlockStep() {} - public static final class SlowBlockStep extends Step { - @DataBoundConstructor public SlowBlockStep() {} - @Override public StepExecution start(StepContext context) { + @Override + public StepExecution start(StepContext context) { return new Execution(context, this); } + private static final class Execution extends GeneralNonBlockingStepExecution { private final transient SlowBlockStep step; + Execution(StepContext context, SlowBlockStep step) { super(context); this.step = step; } + private void println(String msg) throws Exception { getContext().get(TaskListener.class).getLogger().println(msg); } - @Override public boolean start() throws Exception { + + @Override + public boolean start() throws Exception { println("starting step"); run(this::doStart); return false; } + private void doStart() throws Exception { println("starting background part of step"); startEnter.release(); @@ -169,8 +187,11 @@ private void doStart() throws Exception { println("starting body"); getContext().newBodyInvoker().withCallback(new Callback()).start(); } + private final class Callback extends TailCall { - @Override protected void finished(StepContext context) throws Exception { + + @Override + protected void finished(StepContext context) throws Exception { println("body completed, starting background end part of step"); endEnter.release(); endExit.acquire(); @@ -178,17 +199,23 @@ private final class Callback extends TailCall { } } } - @TestExtension public static final class DescriptorImpl extends StepDescriptor { - @Override public String getFunctionName() { + @TestExtension + public static final class DescriptorImpl extends StepDescriptor { + + @Override + public String getFunctionName() { return "slowBlock"; } - @Override public Set> getRequiredContext() { + + @Override + public Set> getRequiredContext() { return Collections.singleton(TaskListener.class); } - @Override public boolean takesImplicitBlockArgument() { + + @Override + public boolean takesImplicitBlockArgument() { return true; } } } - } diff --git a/src/test/java/org/jenkinsci/plugins/workflow/steps/MissingContextVariableExceptionTest.java b/src/test/java/org/jenkinsci/plugins/workflow/steps/MissingContextVariableExceptionTest.java index 82635ec..597bdb4 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/steps/MissingContextVariableExceptionTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/steps/MissingContextVariableExceptionTest.java @@ -27,18 +27,25 @@ import hudson.model.Result; import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition; 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.junit.jupiter.WithJenkins; -public final class MissingContextVariableExceptionTest { +@WithJenkins +class MissingContextVariableExceptionTest { - @Rule public JenkinsRule r = new JenkinsRule(); + private JenkinsRule r; - @Test public void message() throws Exception { + @BeforeEach + void setUp(JenkinsRule rule) { + r = rule; + } + + @Test + void message() throws Exception { WorkflowJob p = r.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition("sh 'oops'", true)); r.assertLogContains("Perhaps you forgot to surround the sh step with a step that provides this, such as: node", r.buildAndAssertStatus(Result.FAILURE, p)); } - } diff --git a/src/test/java/org/jenkinsci/plugins/workflow/steps/StepConfigTester.java b/src/test/java/org/jenkinsci/plugins/workflow/steps/StepConfigTester.java index 7a29903..1e50e0a 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/steps/StepConfigTester.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/steps/StepConfigTester.java @@ -30,7 +30,9 @@ import hudson.model.FreeStyleProject; import hudson.tasks.BuildStepDescriptor; import hudson.tasks.Builder; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertEquals; + import org.jvnet.hudson.test.JenkinsRule; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.NoExternalUse; @@ -70,18 +72,25 @@ public S configRoundTrip(S before) throws Exception { @Restricted(NoExternalUse.class) public static final class StepBuilder extends Builder { public final Step s; - @DataBoundConstructor public StepBuilder(Step s) { + + @DataBoundConstructor + public StepBuilder(Step s) { this.s = s; } - @Extension public static final class DescriptorImpl extends BuildStepDescriptor { - @SuppressWarnings("rawtypes") - @Override public boolean isApplicable(Class jobType) { + + @SuppressWarnings("unused") + @Extension + public static final class DescriptorImpl extends BuildStepDescriptor { + + @Override + public boolean isApplicable(Class jobType) { return true; } - @Override public String getDisplayName() { + + @Override + public String getDisplayName() { return "Test step builder"; } } } - } diff --git a/src/test/java/org/jenkinsci/plugins/workflow/steps/StepDescriptorTest.java b/src/test/java/org/jenkinsci/plugins/workflow/steps/StepDescriptorTest.java index f032223..76ea615 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/steps/StepDescriptorTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/steps/StepDescriptorTest.java @@ -24,25 +24,27 @@ package org.jenkinsci.plugins.workflow.steps; -import org.junit.Assert; -import org.junit.Test; - +import org.junit.jupiter.api.Test; import java.util.HashMap; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + import java.util.concurrent.TimeUnit; /** * Tests some specific {@link StepDescriptor} APIs */ -public class StepDescriptorTest { +class StepDescriptorTest { @Test - public void testStringFormattingAllowed() { - Assert.assertFalse(StepDescriptor.isAbleToUseToStringForDisplay(null)); - Assert.assertFalse(StepDescriptor.isAbleToUseToStringForDisplay(new HashMap())); - Assert.assertTrue(StepDescriptor.isAbleToUseToStringForDisplay("cheese")); - Assert.assertTrue(StepDescriptor.isAbleToUseToStringForDisplay(-1)); - Assert.assertTrue(StepDescriptor.isAbleToUseToStringForDisplay(Boolean.FALSE)); - Assert.assertTrue(StepDescriptor.isAbleToUseToStringForDisplay(TimeUnit.MINUTES)); - Assert.assertTrue(StepDescriptor.isAbleToUseToStringForDisplay(new StringBuffer("gopher"))); + void testStringFormattingAllowed() { + assertFalse(StepDescriptor.isAbleToUseToStringForDisplay(null)); + assertFalse(StepDescriptor.isAbleToUseToStringForDisplay(new HashMap())); + assertTrue(StepDescriptor.isAbleToUseToStringForDisplay("cheese")); + assertTrue(StepDescriptor.isAbleToUseToStringForDisplay(-1)); + assertTrue(StepDescriptor.isAbleToUseToStringForDisplay(Boolean.FALSE)); + assertTrue(StepDescriptor.isAbleToUseToStringForDisplay(TimeUnit.MINUTES)); + assertTrue(StepDescriptor.isAbleToUseToStringForDisplay(new StringBuffer("gopher"))); } } diff --git a/src/test/java/org/jenkinsci/plugins/workflow/steps/SynchronousNonBlockingStepExecutionTest.java b/src/test/java/org/jenkinsci/plugins/workflow/steps/SynchronousNonBlockingStepExecutionTest.java index 764aef5..9fb1425 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/steps/SynchronousNonBlockingStepExecutionTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/steps/SynchronousNonBlockingStepExecutionTest.java @@ -5,6 +5,7 @@ import hudson.model.Run; import java.io.File; +import java.io.Serial; import java.io.Serializable; import java.util.HashMap; import java.util.HashSet; @@ -20,33 +21,43 @@ 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.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.Issue; 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; import java.util.Collections; -import static org.junit.Assert.assertTrue; -public class SynchronousNonBlockingStepExecutionTest { +import static org.junit.jupiter.api.Assertions.assertTrue; - @Rule public JenkinsRule j = new JenkinsRule(); +@WithJenkins +class SynchronousNonBlockingStepExecutionTest { - @ClassRule - public static BuildWatcher buildWatcher = new BuildWatcher(); + @SuppressWarnings("unused") + @RegisterExtension + private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension(); + + private JenkinsRule j; + + @BeforeEach + void setUp(JenkinsRule rule) { + j = rule; + } @Test - public void basicNonBlockingStep() throws Exception { + void basicNonBlockingStep() throws Exception { WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p"); - p.setDefinition(new CpsFlowDefinition("node {\n" + - "echo 'First message'\n" + - "syncnonblocking 'wait'\n" + - "echo 'Second message'\n" + - "}", true)); + p.setDefinition(new CpsFlowDefinition(""" + node { + echo 'First message' + syncnonblocking 'wait' + echo 'Second message' + }""", true)); WorkflowRun b = p.scheduleBuild2(0).getStartCondition().get(); // Wait for syncnonblocking to be started @@ -67,7 +78,7 @@ public void basicNonBlockingStep() throws Exception { } System.out.println("Checking flow node added..."); - assertTrue("FlowNode has to be added just when the step starts running", found); + assertTrue(found, "FlowNode has to be added just when the step starts running"); // Check for message the test message sent to context listener System.out.println("Checking build log message present..."); @@ -87,15 +98,15 @@ public void basicNonBlockingStep() throws Exception { j.assertBuildStatusSuccess(b); } - @Test - public void interruptedTest() throws Exception { + void interruptedTest() throws Exception { WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p"); - p.setDefinition(new CpsFlowDefinition("node {\n" + - "echo 'First message'\n" + - "try { syncnonblocking 'wait' } catch(InterruptedException e) { echo 'Interrupted!' }\n" + - "echo 'Second message'\n" + - "}", true)); + p.setDefinition(new CpsFlowDefinition(""" + node { + echo 'First message' + try { syncnonblocking 'wait' } catch(InterruptedException e) { echo 'Interrupted!' } + echo 'Second message' + }""", true)); WorkflowRun b = p.scheduleBuild2(0).getStartCondition().get(); // Wait for syncnonblocking to be started @@ -117,13 +128,14 @@ public void interruptedTest() throws Exception { } @Test - public void parallelTest() throws Exception { + void parallelTest() throws Exception { WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p"); - p.setDefinition(new CpsFlowDefinition("node {\n" + - "echo 'First message'\n" + - "parallel( a: { syncnonblocking 'wait0'; echo 'a branch'; }, b: { semaphore 'wait1'; echo 'b branch'; } )\n" + - "echo 'Second message'\n" + - "}", true)); + p.setDefinition(new CpsFlowDefinition(""" + node { + echo 'First message' + parallel( a: { syncnonblocking 'wait0'; echo 'a branch'; }, b: { semaphore 'wait1'; echo 'b branch'; } ) + echo 'Second message' + }""", true)); WorkflowRun b = p.scheduleBuild2(0).getStartCondition().get(); SynchronousNonBlockingStep.waitForStart("wait0", b); @@ -200,8 +212,9 @@ public static void notify(String id) { } private static class StepExecutionImpl extends SynchronousNonBlockingStepExecution { - - private transient final SynchronousNonBlockingStep step; + @Serial + private static final long serialVersionUID = 1L; + private final transient SynchronousNonBlockingStep step; StepExecutionImpl(SynchronousNonBlockingStep step, StepContext context) { super(context); @@ -231,8 +244,6 @@ protected Void run() throws Exception { return null; } - - private static final long serialVersionUID = 1L; } @TestExtension @@ -252,72 +263,103 @@ public String getDisplayName() { public Set> getRequiredContext() { return Collections.singleton(TaskListener.class); } - } - - private static final long serialVersionUID = 1L; - } - @Test public void errors() throws Exception { + @Test + void errors() throws Exception { WorkflowJob p = j.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition("erroneous()", true)); j.assertLogContains("ought to fail", j.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0))); } + + @SuppressWarnings("unused") public static final class Erroneous extends Step { - @DataBoundConstructor public Erroneous() {} - @Override public StepExecution start(StepContext context) { + + @DataBoundConstructor + public Erroneous() {} + + @Override + public StepExecution start(StepContext context) { return new Exec(context); } + private static final class Exec extends SynchronousNonBlockingStepExecution { + Exec(StepContext context) { super(context); } - @Override protected Void run() { + + @Override + protected Void run() { throw new AssertionError("ought to fail"); } } - @TestExtension("errors") public static final class DescriptorImpl extends StepDescriptor { - @Override public Set> getRequiredContext() { + + @TestExtension("errors") + public static final class DescriptorImpl extends StepDescriptor { + + @Override + public Set> getRequiredContext() { return Collections.emptySet(); } - @Override public String getFunctionName() { + + @Override + public String getFunctionName() { return "erroneous"; } } } @Issue("JENKINS-53305") - @Test public void contextClassLoader() throws Exception { + @Test + void contextClassLoader() throws Exception { WorkflowJob p = j.createProject(WorkflowJob.class, "p"); - p.setDefinition(new CpsFlowDefinition("" + - // Sets the class loader used to invoke steps to null to demonstrate a potential problem. - // I am not sure how this could occur in practice, so this is a very artificial reproduction. - "org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService.ORIGINAL_CONTEXT_CLASS_LOADER.set(null)\n" + - "checkClassLoader()\n", false)); + // Sets the class loader used to invoke steps to null to demonstrate a potential problem. + // I am not sure how this could occur in practice, so this is a very artificial reproduction. + p.setDefinition(new CpsFlowDefinition(""" + org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService.ORIGINAL_CONTEXT_CLASS_LOADER.set(null) + checkClassLoader() + """, false)); j.assertBuildStatus(Result.SUCCESS, p.scheduleBuild2(0)); } + + @SuppressWarnings("unused") public static final class CheckClassLoader extends Step { - @DataBoundConstructor public CheckClassLoader() {} - @Override public StepExecution start(StepContext context) { + + @DataBoundConstructor + public CheckClassLoader() {} + + @Override + public StepExecution start(StepContext context) { return new Exec(context); } + private static final class Exec extends SynchronousNonBlockingStepExecution { + Exec(StepContext context) { super(context); } - @Override protected Void run() { + + @Override + protected Void run() { if (Thread.currentThread().getContextClassLoader() == null) { throw new AssertionError("Context class loader should not be null!"); } return null; } } - @TestExtension("contextClassLoader") public static final class DescriptorImpl extends StepDescriptor { - @Override public Set> getRequiredContext() { + + @TestExtension("contextClassLoader") + public static final class DescriptorImpl extends StepDescriptor { + + @Override + public Set> getRequiredContext() { return Collections.emptySet(); } - @Override public String getFunctionName() { + + @Override + public String getFunctionName() { return "checkClassLoader"; } }