diff --git a/pom.xml b/pom.xml index 8adc3d45..04e0a515 100644 --- a/pom.xml +++ b/pom.xml @@ -77,7 +77,7 @@ io.jenkins.tools.bom bom-${jenkins.baseline}.x - 4023.va_eeb_b_4e45f07 + 5054.v620b_5d2b_d5e6 import pom diff --git a/src/test/java/org/jenkinsci/plugins/workflow/BuildQueueTasksTest.java b/src/test/java/org/jenkinsci/plugins/workflow/BuildQueueTasksTest.java index bb0b4c00..2cc6e888 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/BuildQueueTasksTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/BuildQueueTasksTest.java @@ -24,8 +24,8 @@ package org.jenkinsci.plugins.workflow; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import java.util.concurrent.ExecutionException; @@ -34,11 +34,11 @@ 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.Rule; -import org.junit.Test; +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.JenkinsSessionRule; +import org.jvnet.hudson.test.junit.jupiter.JenkinsSessionExtension; import org.xml.sax.SAXException; import org.htmlunit.Page; @@ -48,12 +48,14 @@ import net.sf.json.JSONArray; import net.sf.json.JSONObject; -public class BuildQueueTasksTest { +class BuildQueueTasksTest { - @Rule public JenkinsSessionRule sessions = new JenkinsSessionRule(); + @RegisterExtension + private final JenkinsSessionExtension sessions = new JenkinsSessionExtension(); @Issue("JENKINS-28649") - @Test public void queueAPI() throws Throwable { + @Test + void queueAPI() throws Throwable { // This is implicitly testing ExecutorStepExecution$PlaceholderTask as exported bean sessions.then(j -> { WorkflowJob p = j.createProject(WorkflowJob.class, "p"); @@ -66,7 +68,8 @@ public class BuildQueueTasksTest { } @Issue("JENKINS-28649") - @Test public void queueAPIRestartable() throws Throwable { + @Test + void queueAPIRestartable() throws Throwable { // This is implicitly testing AfterRestartTask as exported bean sessions.then(j -> { WorkflowJob p = j.createProject(WorkflowJob.class, "p"); @@ -84,15 +87,19 @@ public class BuildQueueTasksTest { } @Issue("JENKINS-28649") - @Test public void computerAPI() throws Throwable { + @Test + void computerAPI() throws Throwable { // This is implicitly testing ExecutorStepExecution$PlaceholderTask$PlaceholderExecutable as exported bean sessions.then(j -> { WorkflowJob p = j.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "node {\n" + - " echo 'test'\n " + - " semaphore 'watch'\n " + - "}", true)); + """ + node { + echo 'test' + + semaphore 'watch' + + }""", true)); WorkflowRun b = p.scheduleBuild2(0).getStartCondition().get(); SemaphoreStep.waitForStart("watch/1", b); @@ -128,7 +135,7 @@ private static void assertQueueAPIStatusOKAndAbort(WorkflowRun b, JenkinsRule j) JSONObject o = JSONObject.fromObject(queue.getWebResponse().getContentAsString()); JSONArray items = o.getJSONArray("items"); - // Just check that the request returns HTTP 200 and there is some content. + // Just check that the request returns HTTP 200 and there is some content. // Not going into de the content in this test assertEquals(1, items.size()); diff --git a/src/test/java/org/jenkinsci/plugins/workflow/EnvWorkflowTest.java b/src/test/java/org/jenkinsci/plugins/workflow/EnvWorkflowTest.java index d743339c..3a3b157a 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/EnvWorkflowTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/EnvWorkflowTest.java @@ -34,23 +34,30 @@ 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.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; /** * Verifies that specific environment variables are available. * */ -public class EnvWorkflowTest { +@WithJenkins +class EnvWorkflowTest { - @Rule public JenkinsRule r = new JenkinsRule(); + private JenkinsRule r; + @BeforeEach + void setUp(JenkinsRule rule) { + r = rule; + } /** * Verifies if NODE_NAME environment variable is available on an agent node and on the built-in node. */ - @Test public void isNodeNameAvailable() throws Exception { + @Test + void isNodeNameAvailable() throws Exception { r.createSlave("node-test", "unix fast", null); WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "workflow-test"); @@ -109,7 +116,8 @@ private void matchLabelsInAnyOrder(WorkflowRun run, String regex, String... labe /** * Verifies if EXECUTOR_NUMBER environment variable is available on an agent node and on the built-in node. */ - @Test public void isExecutorNumberAvailable() throws Exception { + @Test + void isExecutorNumberAvailable() throws Exception { r.jenkins.setNumExecutors(1); r.createSlave("node-test", null, null); String builtInNodeLabel = r.jenkins.getSelfLabel().getExpression(); // compatibility with 2.307+ @@ -123,15 +131,18 @@ private void matchLabelsInAnyOrder(WorkflowRun run, String regex, String... labe r.assertLogContains("Executor number on built-in node is 0", r.assertBuildStatusSuccess(p.scheduleBuild2(0))); p.setDefinition(new CpsFlowDefinition( - "node('node-test') {\n" + - " echo \"My number on an agent is ${env.EXECUTOR_NUMBER}\"\n" + - "}\n", + """ + node('node-test') { + echo "My number on an agent is ${env.EXECUTOR_NUMBER}" + } + """, true)); r.assertLogContains("My number on an agent is 0", r.assertBuildStatusSuccess(p.scheduleBuild2(0))); } @Issue("JENKINS-33511") - @Test public void isWorkspaceAvailable() throws Exception { + @Test + void isWorkspaceAvailable() throws Exception { WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p"); String builtInNodeLabel = r.jenkins.getSelfLabel().getExpression(); // compatibility with 2.307+ p.setDefinition(new CpsFlowDefinition("node('" + builtInNodeLabel + "') {echo(/running in ${env.WORKSPACE}/)}", true)); diff --git a/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/DurableTaskStepTest.java b/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/DurableTaskStepTest.java index 57638312..8ca3d035 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/DurableTaskStepTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/DurableTaskStepTest.java @@ -36,7 +36,6 @@ import hudson.slaves.ComputerListener; import java.io.File; import java.time.Duration; -import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import jenkins.slaves.restarter.JnlpSlaveRestarterInstaller; @@ -45,40 +44,43 @@ import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition; import org.jenkinsci.plugins.workflow.job.WorkflowJob; import org.jenkinsci.plugins.workflow.log.FileLogStorage; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.params.Parameter; +import org.junit.jupiter.params.ParameterizedClass; +import org.junit.jupiter.params.provider.ValueSource; import org.jvnet.hudson.test.InboundAgentRule; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.PrefixedOutputStream; -import org.jvnet.hudson.test.RealJenkinsRule; import org.jvnet.hudson.test.TailLog; +import org.jvnet.hudson.test.junit.jupiter.InboundAgentExtension; +import org.jvnet.hudson.test.junit.jupiter.RealJenkinsExtension; -@RunWith(Parameterized.class) -public final class DurableTaskStepTest { - - @Parameterized.Parameters(name = "watching={0}") public static List data() { - return List.of(false, true); - } - - @Parameterized.Parameter public boolean useWatching; +@ParameterizedClass(name = "watching={0}") +@ValueSource(booleans = {true, false}) +class DurableTaskStepTest { private static final Logger LOGGER = Logger.getLogger(DurableTaskStepTest.class.getName()); - @Rule public RealJenkinsRule rr = new RealJenkinsRule(). + @Parameter + private boolean useWatching; + + @RegisterExtension + private final RealJenkinsExtension rr = new RealJenkinsExtension(). javaOptions("-Dorg.jenkinsci.plugins.workflow.support.pickles.ExecutorPickle.timeoutForNodeMillis=" + Duration.ofMinutes(5).toMillis()). // reconnection could be >15s esp. on Windows withColor(PrefixedOutputStream.Color.BLUE). withLogger(DurableTaskStep.class, Level.FINE). withLogger(FileMonitoringTask.class, Level.FINE); - @Rule public InboundAgentRule inboundAgents = new InboundAgentRule(); + @RegisterExtension + private final InboundAgentExtension inboundAgents = new InboundAgentExtension(); - @Test public void scriptExitingAcrossRestart() throws Throwable { + @Test + void scriptExitingAcrossRestart() throws Throwable { rr.javaOptions("-D" + DurableTaskStep.class.getName() + ".USE_WATCHING=" + useWatching); rr.startJenkins(); rr.runRemotely(DurableTaskStepTest::disableJnlpSlaveRestarterInstaller); - inboundAgents.createAgent(rr, InboundAgentRule.Options.newBuilder(). + inboundAgents.createAgent(rr, InboundAgentExtension.Options.newBuilder(). color(PrefixedOutputStream.Color.MAGENTA). label("remote"). withLogger(FileMonitoringTask.class, Level.FINER). @@ -103,7 +105,7 @@ public final class DurableTaskStepTest { * Most users should be using cloud agents, * and this lets us preserve {@link InboundAgentRule.Options.Builder#withLogger(Class, Level)}. */ - private static void disableJnlpSlaveRestarterInstaller(JenkinsRule r) throws Throwable { + private static void disableJnlpSlaveRestarterInstaller(JenkinsRule r) { ComputerListener.all().remove(ExtensionList.lookupSingleton(JnlpSlaveRestarterInstaller.class)); } diff --git a/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ExitDuringShutdownTest.java b/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ExitDuringShutdownTest.java index 0b9ae974..79b50b31 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ExitDuringShutdownTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ExitDuringShutdownTest.java @@ -39,25 +39,28 @@ import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition; import org.jenkinsci.plugins.workflow.job.WorkflowJob; import org.jenkinsci.plugins.workflow.steps.durable_task.exitDuringShutdownTest.FinishProcess; -import static org.junit.Assume.assumeFalse; -import org.junit.Rule; -import org.junit.Test; +import static org.junit.jupiter.api.Assumptions.assumeFalse; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import org.jvnet.hudson.test.PrefixedOutputStream; -import org.jvnet.hudson.test.RealJenkinsRule; import org.jvnet.hudson.test.TailLog; +import org.jvnet.hudson.test.junit.jupiter.RealJenkinsExtension; -public final class ExitDuringShutdownTest { +class ExitDuringShutdownTest { - @Rule public RealJenkinsRule rr = new RealJenkinsRule(). - addSyntheticPlugin(new RealJenkinsRule.SyntheticPlugin(FinishProcess.class).shortName("ExitDuringShutdownTest").header("Plugin-Dependencies", "workflow-cps:0")). + @RegisterExtension + private final RealJenkinsExtension rr = new RealJenkinsExtension(). + addSyntheticPlugin(new RealJenkinsExtension.SyntheticPlugin(FinishProcess.class).shortName("ExitDuringShutdownTest").header("Plugin-Dependencies", "workflow-cps:0")). javaOptions("-Dorg.jenkinsci.plugins.workflow.support.pickles.ExecutorPickle.timeoutForNodeMillis=" + Duration.ofMinutes(5).toMillis()). // reconnection could be >15s esp. on Windows javaOptions("-D" + DurableTaskStep.class.getName() + ".USE_WATCHING=true"). withColor(PrefixedOutputStream.Color.BLUE). withLogger(DurableTaskStep.class, Level.FINE). withLogger(FileMonitoringTask.class, Level.FINE); - @Test public void scriptExitingDuringShutdown() throws Throwable { - assumeFalse("TODO Windows version TBD", Functions.isWindows()); + @Test + void scriptExitingDuringShutdown() throws Throwable { + assumeFalse(Functions.isWindows(), "TODO Windows version TBD"); rr.startJenkins(); try (var tailLog = new TailLog(rr, "p", 1).withColor(PrefixedOutputStream.Color.YELLOW)) { rr.run(r -> { diff --git a/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/PowerShellStepTest.java b/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/PowerShellStepTest.java index 28165218..96955a83 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/PowerShellStepTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/PowerShellStepTest.java @@ -21,56 +21,63 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ - + package org.jenkinsci.plugins.workflow.steps.durable_task; -import org.junit.Rule; -import org.junit.Test; -import org.junit.Before; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import hudson.model.Result; import org.jenkinsci.plugins.workflow.job.WorkflowJob; import org.jenkinsci.plugins.workflow.job.WorkflowRun; -import org.junit.Assume; import org.jvnet.hudson.test.JenkinsRule; import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition; import hudson.Functions; import java.nio.charset.StandardCharsets; +import org.jvnet.hudson.test.junit.jupiter.WithJenkins; -public class PowerShellStepTest { +@WithJenkins +class PowerShellStepTest { - @Rule public JenkinsRule j = new JenkinsRule(); + private JenkinsRule j; // Ensure that powershell exists and is at least version 3 - @Before public void ensurePowerShellSufficientVersion() throws Exception { + @BeforeEach + void setUp(JenkinsRule rule) throws Exception { + j = rule; WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "pretest"); p.setDefinition(new CpsFlowDefinition(Functions.isWindows() ? "node { bat('powershell.exe -ExecutionPolicy Bypass -NonInteractive -Command \"if ($PSVersionTable.PSVersion.Major -ge 3) {exit 0} else {exit 1}\"') }" : "node { sh('powershell -NonInteractive -Command \"if ($PSVersionTable.PSVersion.Major -ge 3) {exit 0} else {exit 1}\"') }", true)); WorkflowRun b = p.scheduleBuild2(0).get(); Result r = b.getResult(); - Assume.assumeTrue("This test should only run if the pretest workflow job succeeded", r == Result.SUCCESS); + assumeTrue(r == Result.SUCCESS, "This test should only run if the pretest workflow job succeeded"); } // Test that a powershell step producing particular output indeed has a log containing that output - @Test public void testOutput() throws Exception { + @Test + void testOutput() throws Exception { WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "foo"); p.setDefinition(new CpsFlowDefinition("node {powershell 'Write-Output \"a moon full of stars and astral cars\"'}", true)); j.assertLogContains("a moon full of stars and astral cars", j.assertBuildStatusSuccess(p.scheduleBuild2(0))); } - + // Test that a powershell step that fails indeed causes the underlying build to fail - @Test public void testFailure() throws Exception { + @Test + void testFailure() throws Exception { WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "bar"); p.setDefinition(new CpsFlowDefinition("node {powershell 'throw \"bogus error\"'}", true)); j.assertLogContains("bogus error", j.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0))); } - - @Test public void testUnicode() throws Exception { + + @Test + void testUnicode() throws Exception { WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "foobar"); p.setDefinition(new CpsFlowDefinition("node {def x = powershell(returnStdout: true, script: 'write-output \"Hëllö Wórld\"'); println x.replace(\"\ufeff\",\"\")}", true)); String log = new String(JenkinsRule.getLog(j.assertBuildStatusSuccess(p.scheduleBuild2(0))).getBytes(), StandardCharsets.UTF_8); - Assume.assumeTrue("Correct UTF-8 output should be produced",log.contains("Hëllö Wórld")); + assumeTrue(log.contains("Hëllö Wórld"),"Correct UTF-8 output should be produced"); } } diff --git a/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ShellStepTest.java b/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ShellStepTest.java index fbc0e7d5..58348d25 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ShellStepTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/steps/durable_task/ShellStepTest.java @@ -2,13 +2,9 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; -import static org.junit.Assume.assumeFalse; -import static org.junit.Assume.assumeTrue; +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assumptions.assumeFalse; +import static org.junit.jupiter.api.Assumptions.assumeTrue; import com.cloudbees.plugins.credentials.CredentialsProvider; import com.cloudbees.plugins.credentials.CredentialsScope; @@ -50,6 +46,7 @@ import java.io.File; import java.io.IOException; import java.io.OutputStream; +import java.io.Serial; import java.io.Serializable; import java.io.StringWriter; import java.io.UncheckedIOException; @@ -99,52 +96,63 @@ import org.jenkinsci.plugins.workflow.support.steps.ExecutorStepExecution; import org.jenkinsci.plugins.workflow.support.visualization.table.FlowGraphTable; import org.jenkinsci.plugins.workflow.support.visualization.table.FlowGraphTable.Row; -import org.junit.Assume; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ErrorCollector; -import org.junit.rules.TemporaryFolder; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.jvnet.hudson.test.BuildWatcher; -import org.jvnet.hudson.test.FlagRule; +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.junit.jupiter.api.io.TempDir; +import org.junit.jupiter.params.Parameter; +import org.junit.jupiter.params.ParameterizedClass; +import org.junit.jupiter.params.provider.ValueSource; 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.SimpleCommandLauncher; 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 org.kohsuke.stapler.DataBoundSetter; -@RunWith(Parameterized.class) -public class ShellStepTest { +@WithJenkins +@ParameterizedClass(name = "watching={0}") +@ValueSource(booleans = {true, false}) +class ShellStepTest { - @Parameterized.Parameters(name = "watching={0}") public static List data() { - return List.of(false, true); - } + @Parameter + private boolean useWatching; - @Parameterized.BeforeParam public static void useWatching(boolean x) { - DurableTaskStep.USE_WATCHING = x; - } + @RegisterExtension + private static final BuildWatcherExtension buildWatcher = new BuildWatcherExtension(); + @TempDir + private File tmp; + + private final LogRecorder logging = new LogRecorder(); + private long watchingRecurrencePeriod; + private boolean useBinaryWrapper; - @Parameterized.Parameter public boolean useWatching; + private JenkinsRule j; - @ClassRule - public static BuildWatcher buildWatcher = new BuildWatcher(); + @BeforeEach + void setUp(JenkinsRule rule) { + j = rule; - @Rule public JenkinsRule j = new JenkinsRule(); - @Rule public TemporaryFolder tmp = new TemporaryFolder(); - @Rule public ErrorCollector errors = new ErrorCollector(); - @Rule public LoggerRule logging = new LoggerRule(); - @Rule public FlagRule watchingRecurrencePeriod = new FlagRule<>(() -> DurableTaskStep.WATCHING_RECURRENCE_PERIOD, x -> DurableTaskStep.WATCHING_RECURRENCE_PERIOD = x); - @Rule public FlagRule useBinaryWrapper = new FlagRule<>(() -> WindowsBatchScript.USE_BINARY_WRAPPER, x -> WindowsBatchScript.USE_BINARY_WRAPPER = x); + DurableTaskStep.USE_WATCHING = useWatching; + watchingRecurrencePeriod = DurableTaskStep.WATCHING_RECURRENCE_PERIOD; + useBinaryWrapper = WindowsBatchScript.USE_BINARY_WRAPPER; + } + + @AfterEach + void tearDown() { + DurableTaskStep.WATCHING_RECURRENCE_PERIOD = watchingRecurrencePeriod; + WindowsBatchScript.USE_BINARY_WRAPPER = useBinaryWrapper; + } /** * Failure in the shell script should mark the step as red */ @Test - public void failureShouldMarkNodeRed() throws Exception { + void failureShouldMarkNodeRed() throws Exception { // job setup WorkflowJob foo = j.jenkins.createProject(WorkflowJob.class, "foo"); foo.setDefinition(new CpsFlowDefinition(Functions.isWindows() ? "node {bat 'whatever'}" : "node {sh 'false'}", true)); @@ -156,9 +164,8 @@ public void failureShouldMarkNodeRed() throws Exception { FlowGraphTable t = new FlowGraphTable(b.getExecution()); t.build(); for (Row r : t.getRows()) { - if (r.getNode() instanceof StepAtomNode) { - StepAtomNode sa = (StepAtomNode) r.getNode(); - if (sa.getDescriptor().getFunctionName().matches("sh|bat")) { + if (r.getNode() instanceof StepAtomNode sa) { + if (sa.getDescriptor().getFunctionName().matches("sh|bat")) { assertSame(BallColor.RED, sa.getIconColor()); found = true; } @@ -170,7 +177,7 @@ public void failureShouldMarkNodeRed() throws Exception { @Issue("JENKINS-52943") @Test - public void stepDescription() throws Exception { + void stepDescription() throws Exception { // job setup WorkflowJob foo = j.jenkins.createProject(WorkflowJob.class, "foo"); foo.setDefinition(new CpsFlowDefinition(Functions.isWindows() ? "node {" + @@ -198,7 +205,7 @@ public void stepDescription() throws Exception { * Abort a running workflow to ensure that the process is terminated. */ @Test - public void abort() throws Exception { + void abort() throws Exception { Path tmp = Files.createTempFile("jenkins","test"); Files.delete(tmp); @@ -237,7 +244,8 @@ public void abort() throws Exception { } @Issue("JENKINS-41339") - @Test public void nodePaths() throws Exception { + @Test + void nodePaths() throws Exception { DumbSlave slave = j.createSlave("slave", null, null); FreeStyleProject f = j.createFreeStyleProject("f"); // the control f.setAssignedNode(slave); @@ -254,24 +262,27 @@ public void abort() throws Exception { j.assertLogContains(Functions.isWindows() ? "Path=C:\\acme\\bin;" : "PATH=/opt/acme/bin:/", j.buildAndAssertSuccess(p)); } - @Test public void launcherDecorator() throws Exception { - Assume.assumeTrue("TODO Windows equivalent TBD", new File("/usr/bin/nice").canExecute()); + @Test + void launcherDecorator() throws Exception { + assumeTrue(new File("/usr/bin/nice").canExecute(), "TODO Windows equivalent TBD"); // https://stackoverflow.com/questions/44811425/nice-command-not-working-on-macos - Assume.assumeFalse("MacOS doesn't implement nice", Platform.isDarwin()); + assumeFalse(Platform.isDarwin(), "MacOS doesn't implement nice"); WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition("node {sh 'echo niceness=`nice`'}", true)); - Assume.assumeThat("test only works if mvn test is not itself niced", JenkinsRule.getLog(j.assertBuildStatusSuccess(p.scheduleBuild2(0))), containsString("niceness=0")); + assumeTrue(JenkinsRule.getLog(j.assertBuildStatusSuccess(p.scheduleBuild2(0))).contains("niceness=0"), "test only works if mvn test is not itself niced"); p.setDefinition(new CpsFlowDefinition("node {nice {sh 'echo niceness=`nice`'}}", true)); j.assertLogContains("niceness=10", j.assertBuildStatusSuccess(p.scheduleBuild2(0))); p.setDefinition(new CpsFlowDefinition("node {nice {nice {sh 'echo niceness=`nice`'}}}", true)); j.assertLogContains("niceness=19", j.assertBuildStatusSuccess(p.scheduleBuild2(0))); } + public static class NiceStep extends Step { @DataBoundConstructor public NiceStep() {} @Override public StepExecution start(StepContext context) { return new Execution(context); } public static class Execution extends StepExecution { + @Serial private static final long serialVersionUID = 1; Execution(StepContext context) { super(context); @@ -285,13 +296,14 @@ public static class Execution extends StepExecution { } } private static class Decorator extends LauncherDecorator implements Serializable { + @Serial private static final long serialVersionUID = 1; @NonNull @Override public Launcher decorate(Launcher launcher, @NonNull Node node) { return launcher.decorateByPrefix("nice"); } } - @TestExtension({"launcherDecorator[watching=false]", "launcherDecorator[watching=true]"}) public static class DescriptorImpl extends StepDescriptor { + @TestExtension("launcherDecorator") public static class DescriptorImpl extends StepDescriptor { @Override public Set> getRequiredContext() { return Collections.emptySet(); } @@ -309,14 +321,16 @@ private static class Decorator extends LauncherDecorator implements Serializable } @Issue("JENKINS-40734") - @Test public void envWithShellChar() throws Exception { + @Test + void envWithShellChar() throws Exception { WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition("node {withEnv(['MONEY=big$$money']) {isUnix() ? sh('echo \"MONEY=$MONEY\"') : bat('echo \"MONEY=%MONEY%\"')}}", true)); j.assertLogContains("MONEY=big$$money", j.buildAndAssertSuccess(p)); } @Issue("JENKINS-26133") - @Test public void configRoundTrip() throws Exception { + @Test + void configRoundTrip() throws Exception { ShellStep s = new ShellStep("echo hello"); s = new StepConfigTester(j).configRoundTrip(s); assertEquals("echo hello", s.getScript()); @@ -354,8 +368,9 @@ private static class Decorator extends LauncherDecorator implements Serializable } @Issue("JENKINS-26133") - @Test public void returnStdout() throws Exception { - Assume.assumeTrue("TODO Windows equivalent TBD", new File("/usr/bin/tr").canExecute()); + @Test + void returnStdout() throws Exception { + assumeTrue(new File("/usr/bin/tr").canExecute(), "TODO Windows equivalent TBD"); WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition("def msg; node {msg = sh(script: 'echo hello world | tr [a-z] [A-Z]', returnStdout: true).trim()}; echo \"it said ${msg}\"", true)); j.assertLogContains("it said HELLO WORLD", j.assertBuildStatusSuccess(p.scheduleBuild2(0))); @@ -364,31 +379,34 @@ private static class Decorator extends LauncherDecorator implements Serializable } @Issue("JENKINS-26133") - @Test public void returnStatus() throws Exception { + @Test + void returnStatus() throws Exception { WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition("node {echo \"truth is ${isUnix() ? sh(script: 'true', returnStatus: true) : bat(script: 'echo', returnStatus: true)} but falsity is ${isUnix() ? sh(script: 'false', returnStatus: true) : bat(script: 'type nonexistent' , returnStatus: true)}\"}", true)); j.assertLogContains("truth is 0 but falsity is 1", j.assertBuildStatusSuccess(p.scheduleBuild2(0))); } - - - @Test public void label() throws Exception { + + + @Test + void label() throws Exception { WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition("node {isUnix() ? sh(script: 'true', label: 'Step with label') : bat(script: 'echo', label: 'Step with label')}", true)); - + WorkflowRun b = j.assertBuildStatus(Result.SUCCESS, p.scheduleBuild2(0).get()); FlowGraphTable t = new FlowGraphTable(b.getExecution()); t.build(); assertThat(t.getRows().stream().map(Row::getDisplayName).toArray(String[]::new), hasItemInArray(containsString("Step with label"))); } - - @Test public void labelShortened() throws Exception { + + @Test + void labelShortened() throws Exception { String singleLabel = "0123456789".repeat(10); String label = singleLabel + singleLabel; - + WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition("node {isUnix() ? sh(script: 'true', label: '" + label + "') : bat(script: 'echo', label: '" + label + "')}", true)); - + WorkflowRun b = j.assertBuildStatus(Result.SUCCESS, p.scheduleBuild2(0).get()); FlowGraphTable t = new FlowGraphTable(b.getExecution()); @@ -397,7 +415,8 @@ private static class Decorator extends LauncherDecorator implements Serializable } @Issue("JENKINS-38381") - @Test public void remoteLogger() throws Exception { + @Test + void remoteLogger() throws Exception { assumeTrue(useWatching); logging.record(DurableTaskStep.class, Level.FINE).record(FileMonitoringTask.class, Level.FINE); assumeFalse(Functions.isWindows()); // TODO create Windows equivalent @@ -408,7 +427,7 @@ private static class Decorator extends LauncherDecorator implements Serializable CredentialsProvider.lookupStores(j.jenkins).iterator().next().addCredentials(Domain.global(), c); DumbSlave s = j.createSlave("remote", null, null); j.waitOnline(s); - j.showAgentLogs(s, logging); + j.showAgentLogs(s, Map.of(DurableTaskStep.class.getName(), Level.FINE, FileMonitoringTask.class.getName(), Level.FINE)); WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p"); String builtInNodeLabel = j.jenkins.getSelfLabel().getName(); // compatibility with 2.307+ p.setDefinition(new CpsFlowDefinition( @@ -430,7 +449,7 @@ private static class Decorator extends LauncherDecorator implements Serializable j.assertLogNotContains(password.toUpperCase(Locale.ENGLISH), b); j.assertLogContains("CURL -U **** HTTP://SERVER/ [master → remote]", b); } - @TestExtension("remoteLogger[watching=true]") public static class LogFile implements LogStorageFactory { + @TestExtension("remoteLogger") public static class LogFile implements LogStorageFactory { @Override public LogStorage forBuild(FlowExecutionOwner b) { final LogStorage base; try { @@ -459,6 +478,7 @@ private static class Decorator extends LauncherDecorator implements Serializable } } private static class RemotableBuildListener extends OutputStreamTaskListener.Default implements BuildListener { + @Serial private static final long serialVersionUID = 1; /** actual implementation */ private final TaskListener delegate; @@ -495,6 +515,7 @@ private RemotableBuildListener(TaskListener delegate, String id) { } return out; } + @Serial private Object writeReplace() { /* To see serialization happening from BourneShellScript.launchWithCookie & FileMonitoringController.watch: Thread.dumpStack(); @@ -505,7 +526,8 @@ private Object writeReplace() { } @Issue("JENKINS-54133") - @Test public void remoteConsoleNotes() throws Exception { + @Test + void remoteConsoleNotes() throws Exception { assumeTrue(useWatching); assumeFalse(Functions.isWindows()); // TODO create Windows equivalent j.createSlave("remote", null, null); @@ -609,9 +631,10 @@ private static final class HelloNote extends ConsoleNote> { } @Issue("JENKINS-31096") - @Test public void encoding() throws Exception { + @Test + void encoding() throws Exception { // Like JenkinsRule.createSlave but passing a system encoding: - Slave remote = new DumbSlave("remote", tmp.getRoot().getAbsolutePath(), + Slave remote = new DumbSlave("remote", tmp.getAbsolutePath(), new SimpleCommandLauncher("'" + System.getProperty("java.home") + "/bin/java' -Dfile.encoding=ISO-8859-2 -jar '" + new File(j.jenkins.getJnlpJars("slave.jar").getURL().toURI()) + "'")); j.jenkins.addNode(remote); j.waitOnline(remote); @@ -632,7 +655,8 @@ private static final class HelloNote extends ConsoleNote> { j.assertLogContains("¡Čau → there!", j.buildAndAssertSuccess(p)); } - @Test public void missingNewline() throws Exception { + @Test + void missingNewline() throws Exception { assumeFalse(Functions.isWindows()); // TODO create Windows equivalent String credentialsId = "creds"; String username = "bob"; @@ -642,7 +666,7 @@ private static final class HelloNote extends ConsoleNote> { DumbSlave s = j.createSlave("remote", null, null); j.waitOnline(s); logging.record(DurableTaskStep.class, Level.FINE).record(FileMonitoringTask.class, Level.FINE); - j.showAgentLogs(s, logging); + j.showAgentLogs(s, Map.of(DurableTaskStep.class.getName(), Level.FINE, FileMonitoringTask.class.getName(), Level.FINE)); WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p"); String builtInNodeLabel = j.jenkins.getSelfLabel().getName(); // compatibility with 2.307+ p.setDefinition(new CpsFlowDefinition( @@ -657,16 +681,17 @@ private static final class HelloNote extends ConsoleNote> { String log = JenkinsRule.getLog(j.buildAndAssertSuccess(p)); for (String node : new String[] {builtInNodeLabel, "remote"}) { for (String mode : new String[] {"with", "missing"}) { - errors.checkThat(log, containsString("node=" + node + " " + mode + " final newline")); + assertThat(log, containsString("node=" + node + " " + mode + " final newline")); } } - errors.checkThat("no blank lines", log, not(containsString("\n\n"))); + assertThat(log, not(containsString("\n\n"))); // TODO more robust to assert against /missing final newline./ in line mode - errors.checkThat(log, not(containsString("missing final newline[Pipeline]"))); + assertThat(log, not(containsString("missing final newline[Pipeline]"))); } @Issue("JENKINS-34021") - @Test public void deadStep() throws Exception { + @Test + void deadStep() throws Exception { logging.record(DurableTaskStep.class, Level.INFO).record(CpsStepContext.class, Level.INFO).capture(100); WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p"); // Test fails on ci.jenkins.io with timeout == 1 on Windows @@ -685,9 +710,10 @@ private static final class HelloNote extends ConsoleNote> { assertNull(record.getThrown()); } } - + @Issue("JENKINS-49707") - @Test public void removingAgentIsFatal() throws Exception { + @Test + void removingAgentIsFatal() throws Exception { logging.record(DurableTaskStep.class, Level.FINE).record(FileMonitoringTask.class, Level.FINE).record(ExecutorStepExecution.class, Level.FINE); DumbSlave s = j.createSlave("remote", null, null); WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p"); @@ -699,7 +725,8 @@ private static final class HelloNote extends ConsoleNote> { j.waitForMessage(new ExecutorStepExecution.RemovedNodeCause().getShortDescription(), b); } - @Test public void permanentlyDisconnectingAgentIsFatal() throws Exception { + @Test + void permanentlyDisconnectingAgentIsFatal() throws Exception { DurableTaskStep.WATCHING_RECURRENCE_PERIOD = Duration.ofSeconds(30).toMillis(); logging.record(DurableTaskStep.class, Level.FINE); var s = j.createSlave("remote", null, null); @@ -713,7 +740,8 @@ private static final class HelloNote extends ConsoleNote> { j.waitForMessage(new ExecutorStepExecution.RemovedNodeTimeoutCause().getShortDescription(), b); } - @Test public void temporarilyDisconnectingAgentIsNotFatal() throws Exception { + @Test + void temporarilyDisconnectingAgentIsNotFatal() throws Exception { DurableTaskStep.WATCHING_RECURRENCE_PERIOD = Duration.ofSeconds(30).toMillis(); WindowsBatchScript.USE_BINARY_WRAPPER = true; logging.record(DurableTaskStep.class, Level.FINE); @@ -734,19 +762,20 @@ private static final class HelloNote extends ConsoleNote> { } @Issue("JENKINS-44521") - @Test public void shouldInvokeLauncherDecoratorForShellStep() throws Exception { + @Test + void shouldInvokeLauncherDecoratorForShellStep() throws Exception { DumbSlave slave = j.createSlave("slave", null, null); - + WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition("node('slave') {isUnix() ? sh('echo INJECTED=$INJECTED') : bat('echo INJECTED=%INJECTED%')}", true)); WorkflowRun run = j.buildAndAssertSuccess(p); - + j.assertLogContains("INJECTED=MYVAR-" + slave.getNodeName(), run); - } @Issue("JENKINS-28822") - @Test public void interruptingAbortsBuild() throws Exception { + @Test + void interruptingAbortsBuild() throws Exception { WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p"); // Test fails unexpectedly on ci.jenkins.io Windows agents with fewer pings p.setDefinition(new CpsFlowDefinition("node {\n" + @@ -764,7 +793,8 @@ private static final class HelloNote extends ConsoleNote> { } @Issue("JENKINS-28822") - @Test public void interruptingAbortsBuildEvenWithReturnStatus() throws Exception { + @Test + void interruptingAbortsBuildEvenWithReturnStatus() throws Exception { WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p"); // Test fails unexpectedly on ci.jenkins.io Windows agents with fewer pings p.setDefinition(new CpsFlowDefinition("node() {\n" + @@ -782,20 +812,22 @@ private static final class HelloNote extends ConsoleNote> { } @Issue("JENKINS-62014") - @Test public void envVarFilters() throws Exception { + @Test + void envVarFilters() throws Exception { EnvVarsFilterGlobalConfiguration.getAllActivatedGlobalRules().add(new RemoveSpecificVariablesFilter("FOO")); EnvVarsFilterGlobalConfiguration.getAllActivatedGlobalRules().add(new VariableContributingFilter("BAZ", "QUX")); WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "node() {\n" + - " withEnv(['FOO=BAR']) {\n" + - " if (isUnix()) {\n" + - " sh('echo FOO=$FOO and BAZ=$BAZ')\n" + - " } else {\n" + - " bat('ECHO FOO=%FOO% and BAZ=%BAZ%')\n" + - " }\n" + - " }\n" + - "}", true)); + """ + node() { + withEnv(['FOO=BAR']) { + if (isUnix()) { + sh('echo FOO=$FOO and BAZ=$BAZ') + } else { + bat('ECHO FOO=%FOO% and BAZ=%BAZ%') + } + } + }""", true)); WorkflowRun b = j.buildAndAssertSuccess(p); j.assertLogContains("FOO=", b); j.assertLogNotContains("FOO=BAR", b); @@ -803,7 +835,8 @@ private static final class HelloNote extends ConsoleNote> { } @Issue("JENKINS-62014") - @Test public void ensureTypes() { + @Test + void ensureTypes() { final List descriptors = BuilderUtil.allDescriptors(); MatcherAssert.assertThat(descriptors , containsInAnyOrder( @@ -822,8 +855,8 @@ private void ensureForWhile(int timeout, T o, Predicate predicate) throws Thread.sleep(100); } } - - @TestExtension({"shouldInvokeLauncherDecoratorForShellStep[watching=false]", "shouldInvokeLauncherDecoratorForShellStep[watching=true]"}) + + @TestExtension("shouldInvokeLauncherDecoratorForShellStep") public static final class MyNodeLauncherDecorator extends LauncherDecorator { @NonNull @@ -833,7 +866,7 @@ public Launcher decorate(@NonNull Launcher lnchr, @NonNull Node node) { Map env = new HashMap<>(); env.put("INJECTED", "MYVAR-" + node.getNodeName()); return lnchr.decorateByEnv(new EnvVars(env)); - } + } } } diff --git a/src/test/java/org/jenkinsci/plugins/workflow/support/steps/AgentErrorConditionTest.java b/src/test/java/org/jenkinsci/plugins/workflow/support/steps/AgentErrorConditionTest.java index aa7768fe..bef43df2 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/support/steps/AgentErrorConditionTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/support/steps/AgentErrorConditionTest.java @@ -24,6 +24,8 @@ package org.jenkinsci.plugins.workflow.support.steps; +import static org.junit.jupiter.api.Assertions.assertEquals; + import hudson.Functions; import hudson.Launcher; import hudson.model.Label; @@ -54,30 +56,32 @@ import org.jenkinsci.plugins.workflow.steps.SynchronousResumeNotSupportedErrorCondition; import org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep; import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep; -import static org.junit.Assert.assertEquals; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.Test; -import org.jvnet.hudson.test.BuildWatcher; -import org.jvnet.hudson.test.InboundAgentRule; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import org.jvnet.hudson.test.Issue; -import org.jvnet.hudson.test.JenkinsSessionRule; -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.InboundAgentExtension; +import org.jvnet.hudson.test.junit.jupiter.JenkinsSessionExtension; import org.kohsuke.stapler.DataBoundConstructor; /** * Tests of retrying {@code node} blocks. */ @Issue("JENKINS-49707") -public class AgentErrorConditionTest { +class AgentErrorConditionTest { - @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher(); - @Rule public JenkinsSessionRule sessions = new JenkinsSessionRule(); - @Rule public InboundAgentRule inboundAgents = new InboundAgentRule(); - @Rule public LoggerRule logging = new LoggerRule(); + @RegisterExtension + private static final BuildWatcherExtension buildWatcher = new BuildWatcherExtension(); + @RegisterExtension + private final JenkinsSessionExtension sessions = new JenkinsSessionExtension(); + @RegisterExtension + private final InboundAgentExtension inboundAgents = new InboundAgentExtension(); + private final LogRecorder logging = new LogRecorder(); - @Test public void retryNodeBlock() throws Throwable { + @Test + void retryNodeBlock() throws Throwable { sessions.then(r -> { logging.record(DurableTaskStep.class, Level.FINE).record(FileMonitoringTask.class, Level.FINE).record(ExecutorStepExecution.class, Level.FINE); Slave s = inboundAgents.createAgent(r, "dumbo1"); @@ -85,11 +89,12 @@ public class AgentErrorConditionTest { r.jenkins.updateNode(s); // to force setLabelString to be honored WorkflowJob p = r.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "retry(count: 2, conditions: [custom()]) {\n" + - " node('dumb') {\n" + - " if (isUnix()) {sh 'sleep 10'} else {bat 'echo + sleep && ping -n 10 localhost'}\n" + - " }\n" + - "}", true)); + """ + retry(count: 2, conditions: [custom()]) { + node('dumb') { + if (isUnix()) {sh 'sleep 10'} else {bat 'echo + sleep && ping -n 10 localhost'} + } + }""", true)); WorkflowRun b = p.scheduleBuild2(0).waitForStart(); r.waitForMessage("+ sleep", b); inboundAgents.stop("dumbo1"); @@ -103,7 +108,8 @@ public class AgentErrorConditionTest { }); } - @Test public void retryNodeBlockSynch() throws Throwable { + @Test + void retryNodeBlockSynch() throws Throwable { sessions.then(r -> { logging.record(ExecutorStepExecution.class, Level.FINE); Slave s = inboundAgents.createAgent(r, "dumbo1"); @@ -111,11 +117,12 @@ public class AgentErrorConditionTest { r.jenkins.updateNode(s); WorkflowJob p = r.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "retry(count: 2, conditions: [custom()]) {\n" + - " node('dumb') {\n" + - " hang()\n" + - " }\n" + - "}", true)); + """ + retry(count: 2, conditions: [custom()]) { + node('dumb') { + hang() + } + }""", true)); WorkflowRun b = p.scheduleBuild2(0).waitForStart(); r.waitForMessage("$ sleep", b); // Immediate kill causes RequestAbortedException from RemoteLauncher.launch, which passes test; @@ -158,17 +165,19 @@ public static final class HangStep extends Step { } } - @Test public void agentOfflineWhenStartingStep() throws Throwable { + @Test + void agentOfflineWhenStartingStep() throws Throwable { sessions.then(r -> { Slave s = r.createSlave(Label.get("remote")); WorkflowJob p = r.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "retry(count: 2, conditions: [custom()]) {\n" + - " node('remote') {\n" + - " semaphore 'wait'\n" + - " pwd()\n" + - " }\n" + - "}", true)); + """ + retry(count: 2, conditions: [custom()]) { + node('remote') { + semaphore 'wait' + pwd() + } + }""", true)); WorkflowRun b = p.scheduleBuild2(0).waitForStart(); SemaphoreStep.waitForStart("wait/1", b); s.toComputer().disconnect(new OfflineCause.UserCause(null, null)); @@ -183,17 +192,19 @@ public static final class HangStep extends Step { }); } - @Test public void queueTaskCancelled() throws Throwable { + @Test + void queueTaskCancelled() throws Throwable { sessions.then(r -> { Slave s = r.createSlave(Label.get("remote")); s.toComputer().setTemporarilyOffline(true, new OfflineCause.UserCause(null, null)); WorkflowJob p = r.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "retry(count: 2, conditions: [custom()]) {\n" + - " node('remote') {\n" + - " isUnix()\n" + - " }\n" + - "}", true)); + """ + retry(count: 2, conditions: [custom()]) { + node('remote') { + isUnix() + } + }""", true)); WorkflowRun b = p.scheduleBuild2(0).waitForStart(); r.waitForMessage("Still waiting to schedule task", b); Queue.Item[] items = Queue.getInstance().getItems(); @@ -205,18 +216,20 @@ public static final class HangStep extends Step { }); } - @Test public void retryUnconditionally() throws Throwable { + @Test + void retryUnconditionally() throws Throwable { sessions.then(r -> { Slave s = inboundAgents.createAgent(r, "dumbo1"); s.setLabelString("dumb"); r.jenkins.updateNode(s); WorkflowJob p = r.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "retry(2) {\n" + - " node('dumb') {\n" + - " if (isUnix()) {sh 'sleep 10'} else {bat 'echo + sleep && ping -n 10 localhost'}\n" + - " }\n" + - "}", true)); + """ + retry(2) { + node('dumb') { + if (isUnix()) {sh 'sleep 10'} else {bat 'echo + sleep && ping -n 10 localhost'} + } + }""", true)); WorkflowRun b = p.scheduleBuild2(0).waitForStart(); r.waitForMessage("+ sleep", b); inboundAgents.stop("dumbo1"); @@ -230,16 +243,18 @@ public static final class HangStep extends Step { }); } - @Test public void overallBuildCancelIgnored() throws Throwable { + @Test + void overallBuildCancelIgnored() throws Throwable { sessions.then(r -> { r.createSlave(Label.get("remote")); WorkflowJob p = r.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "retry(count: 2, conditions: [custom()]) {\n" + - " node('remote') {\n" + - " semaphore 'wait'\n" + - " }\n" + - "}", true)); + """ + retry(count: 2, conditions: [custom()]) { + node('remote') { + semaphore 'wait' + } + }""", true)); WorkflowRun b = p.scheduleBuild2(0).waitForStart(); SemaphoreStep.waitForStart("wait/1", b); b.getExecutor().interrupt(); @@ -248,7 +263,8 @@ public static final class HangStep extends Step { }); } - @Test public void retryNewStepAcrossRestarts() throws Throwable { + @Test + void retryNewStepAcrossRestarts() throws Throwable { logging.record(DurableTaskStep.class, Level.FINE).record(FileMonitoringTask.class, Level.FINE).record(ExecutorStepExecution.class, Level.FINE); sessions.then(r -> { Slave s = inboundAgents.createAgent(r, "dumbo1"); @@ -256,12 +272,13 @@ public static final class HangStep extends Step { r.jenkins.updateNode(s); WorkflowJob p = r.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "retry(count: 2, conditions: [custom()]) {\n" + - " node('dumb') {\n" + - " semaphore 'wait'\n" + - " isUnix()\n" + - " }\n" + - "}", true)); + """ + retry(count: 2, conditions: [custom()]) { + node('dumb') { + semaphore 'wait' + isUnix() + } + }""", true)); WorkflowRun b = p.scheduleBuild2(0).waitForStart(); SemaphoreStep.waitForStart("wait/1", b); }); @@ -281,7 +298,8 @@ public static final class HangStep extends Step { } @Issue("JENKINS-30383") - @Test public void retryNodeBlockSynchAcrossRestarts() throws Throwable { + @Test + void retryNodeBlockSynchAcrossRestarts() throws Throwable { logging.record(ExecutorStepExecution.class, Level.FINE).record(FlowExecutionList.class, Level.FINE); sessions.then(r -> { Slave s = inboundAgents.createAgent(r, "dumbo1"); @@ -289,11 +307,12 @@ public static final class HangStep extends Step { r.jenkins.updateNode(s); WorkflowJob p = r.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "retry(count: 2, conditions: [custom()]) {\n" + - " node('dumb') {\n" + - " waitWithoutAgent()\n" + - " }\n" + - "}", true)); + """ + retry(count: 2, conditions: [custom()]) { + node('dumb') { + waitWithoutAgent() + } + }""", true)); WorkflowRun b = p.scheduleBuild2(0).waitForStart(); r.waitForMessage("Sleeping without agent", b); }); diff --git a/src/test/java/org/jenkinsci/plugins/workflow/support/steps/ExecutorStep2Test.java b/src/test/java/org/jenkinsci/plugins/workflow/support/steps/ExecutorStep2Test.java index 2042792b..75984026 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/support/steps/ExecutorStep2Test.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/support/steps/ExecutorStep2Test.java @@ -55,34 +55,37 @@ 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.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.runners.Parameterized; -import org.jvnet.hudson.test.BuildWatcher; import org.jvnet.hudson.test.Issue; -import org.jvnet.hudson.test.JenkinsSessionRule; -import org.jvnet.hudson.test.LoggerRule; +import org.jvnet.hudson.test.LogRecorder; import org.jvnet.hudson.test.SimpleCommandLauncher; import org.jvnet.hudson.test.TestExtension; +import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension; +import org.jvnet.hudson.test.junit.jupiter.JenkinsSessionExtension; /** * Like {@link ExecutorStepTest} but not using {@link Parameterized} which appears incompatible with {@link TestExtension}. */ -public final class ExecutorStep2Test { +class ExecutorStep2Test { - @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher(); - @Rule public JenkinsSessionRule rr = new JenkinsSessionRule(); - @Rule public LoggerRule logging = new LoggerRule(); + @RegisterExtension + private static final BuildWatcherExtension buildWatcher = new BuildWatcherExtension(); + @RegisterExtension + private final JenkinsSessionExtension rr = new JenkinsSessionExtension(); + private final LogRecorder logging = new LogRecorder(); @Issue("JENKINS-53837") - @Test public void queueTaskOwnerCorrectWhenRestarting() throws Throwable { + @Test + void queueTaskOwnerCorrectWhenRestarting() throws Throwable { rr.then(r -> { ExtensionList.lookupSingleton(PipelineOnlyTaskDispatcher.class); WorkflowJob p = r.createProject(WorkflowJob.class, "p1"); - p.setDefinition(new CpsFlowDefinition("node {\n" + - " semaphore('wait')\n" + - "}", true)); + p.setDefinition(new CpsFlowDefinition(""" + node { + semaphore('wait') + }""", true)); WorkflowRun b = p.scheduleBuild2(0).waitForStart(); SemaphoreStep.waitForStart("wait/1", b); }); @@ -120,7 +123,8 @@ public String getShortDescription() { } } - @Test public void cloud() throws Throwable { + @Test + void cloud() throws Throwable { rr.then(r -> { ExtensionList.lookupSingleton(TestCloud.DescriptorImpl.class); r.jenkins.clouds.add(new TestCloud()); @@ -189,7 +193,8 @@ private TestCloudSlave(String name) throws Exception { } } - @Test public void selfNameVsLabel() throws Throwable { + @Test + void selfNameVsLabel() throws Throwable { logging.recordPackage(ExecutorStepExecution.class, Level.FINE); rr.then(r -> { r.jenkins.setNumExecutors(0); diff --git a/src/test/java/org/jenkinsci/plugins/workflow/support/steps/ExecutorStepDynamicContextTest.java b/src/test/java/org/jenkinsci/plugins/workflow/support/steps/ExecutorStepDynamicContextTest.java index 5ecf1d51..f1a99650 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/support/steps/ExecutorStepDynamicContextTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/support/steps/ExecutorStepDynamicContextTest.java @@ -32,8 +32,8 @@ import static org.hamcrest.Matchers.emptyArray; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.isA; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import hudson.model.Label; import hudson.model.Queue; @@ -53,25 +53,27 @@ 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.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import org.jvnet.hudson.test.Issue; -import org.jvnet.hudson.test.JenkinsSessionRule; -import org.jvnet.hudson.test.LoggerRule; +import org.jvnet.hudson.test.LogRecorder; +import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension; +import org.jvnet.hudson.test.junit.jupiter.JenkinsSessionExtension; -public class ExecutorStepDynamicContextTest { +class ExecutorStepDynamicContextTest { - @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher(); - @Rule public JenkinsSessionRule sessions = new JenkinsSessionRule(); - @Rule public LoggerRule logging = new LoggerRule(); + @RegisterExtension + private static final BuildWatcherExtension buildWatcher = new BuildWatcherExtension(); + @RegisterExtension + private final JenkinsSessionExtension sessions = new JenkinsSessionExtension(); + private final LogRecorder logging = new LogRecorder(); private void commonSetup() { logging.recordPackage(ExecutorStepExecution.class, Level.FINE).record(FlowExecutionList.class, Level.FINE); } - @Test public void canceledQueueItem() throws Throwable { + @Test + void canceledQueueItem() throws Throwable { sessions.then(j -> { DumbSlave s = j.createSlave(Label.get("remote")); WorkflowJob p = j.createProject(WorkflowJob.class, "p"); @@ -101,7 +103,8 @@ private void commonSetup() { * I.E. cases where the {@link RetentionStrategy} is {@link RetentionStrategy#NOOP}. */ @Issue("JENKINS-36013") - @Test public void normalNodeDisappearance() throws Throwable { + @Test + void normalNodeDisappearance() throws Throwable { commonSetup(); sessions.then(j -> { // Start up a build that needs executor and then reboot and take the node offline @@ -129,7 +132,8 @@ private void commonSetup() { } @Issue("JENKINS-36013") - @Test public void parallelNodeDisappearance() throws Throwable { + @Test + void parallelNodeDisappearance() throws Throwable { commonSetup(); sessions.then(j -> { WorkflowJob p = j.createProject(WorkflowJob.class, "p"); @@ -166,7 +170,8 @@ private void commonSetup() { } @Issue("JENKINS-69936") - @Test public void nestedNode() throws Throwable { + @Test + void nestedNode() throws Throwable { sessions.then(j -> { logging.record(ExecutorStepDynamicContext.class, Level.FINE).record(FilePathDynamicContext.class, Level.FINE); DumbSlave alpha = j.createSlave("alpha", null, null); @@ -188,7 +193,8 @@ private void commonSetup() { } @Issue("JENKINS-70528") - @Test public void nestedNodeSameAgent() throws Throwable { + @Test + void nestedNodeSameAgent() throws Throwable { sessions.then(j -> { logging.record(ExecutorStepDynamicContext.class, Level.FINE).record(FilePathDynamicContext.class, Level.FINE); DumbSlave big = new DumbSlave("big", new File(j.jenkins.getRootDir(), "agent-work-dirs/big").getAbsolutePath(), j.createComputerLauncher(null)); @@ -210,7 +216,8 @@ private void commonSetup() { }); } - @Test public void onceRetentionStrategyNodeDisappearance() throws Throwable { + @Test + void onceRetentionStrategyNodeDisappearance() throws Throwable { commonSetup(); sessions.then(j -> { DumbSlave s = j.createSlave(Label.get("ghost")); @@ -228,7 +235,8 @@ private void commonSetup() { }); } - @Test public void cloudNodeDisappearance() throws Throwable { + @Test + void cloudNodeDisappearance() throws Throwable { commonSetup(); sessions.then(j -> { var mockCloud = new MockCloud("mock"); diff --git a/src/test/java/org/jenkinsci/plugins/workflow/support/steps/ExecutorStepExecutionRJRTest.java b/src/test/java/org/jenkinsci/plugins/workflow/support/steps/ExecutorStepExecutionRJRTest.java index 74a79ebe..9d3fdc07 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/support/steps/ExecutorStepExecutionRJRTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/support/steps/ExecutorStepExecutionRJRTest.java @@ -29,9 +29,8 @@ import static org.hamcrest.Matchers.arrayWithSize; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.iterableWithSize; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.time.Duration; @@ -47,26 +46,29 @@ import org.jenkinsci.plugins.workflow.graphanalysis.NodeStepTypePredicate; import org.jenkinsci.plugins.workflow.job.WorkflowJob; import org.jenkinsci.plugins.workflow.support.steps.input.InputAction; -import org.junit.Rule; -import org.junit.Test; -import org.jvnet.hudson.test.InboundAgentRule; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.PrefixedOutputStream; -import org.jvnet.hudson.test.RealJenkinsRule; import org.jvnet.hudson.test.TailLog; +import org.jvnet.hudson.test.junit.jupiter.InboundAgentExtension; +import org.jvnet.hudson.test.junit.jupiter.RealJenkinsExtension; + +class ExecutorStepExecutionRJRTest { -public class ExecutorStepExecutionRJRTest { private static final Logger LOGGER = Logger.getLogger(ExecutorStepExecutionRJRTest.class.getName()); - @Rule public RealJenkinsRule rjr = new RealJenkinsRule().withColor(PrefixedOutputStream.Color.GREEN).withPackageLogger(ExecutorStepExecution.class, Level.FINE).withPackageLogger(FlowExecutionList.class, Level.FINE); + @RegisterExtension + private final RealJenkinsExtension rjr = new RealJenkinsExtension().withColor(PrefixedOutputStream.Color.GREEN).withPackageLogger(ExecutorStepExecution.class, Level.FINE).withPackageLogger(FlowExecutionList.class, Level.FINE); - @Rule - public InboundAgentRule iar = new InboundAgentRule(); + @RegisterExtension + private final InboundAgentExtension iar = new InboundAgentExtension(); - @Test public void restartWhileWaitingForANode() throws Throwable { + @Test + void restartWhileWaitingForANode() throws Throwable { rjr.startJenkins(); try (var tailLog = new TailLog(rjr, "p", 1)) { - iar.createAgent(rjr, InboundAgentRule.Options.newBuilder().name("J").label("mib").color(PrefixedOutputStream.Color.YELLOW).webSocket().build()); + iar.createAgent(rjr, InboundAgentExtension.Options.newBuilder().name("J").label("mib").color(PrefixedOutputStream.Color.YELLOW).webSocket().build()); rjr.runRemotely(ExecutorStepExecutionRJRTest::setupJobAndStart); rjr.stopJenkinsForcibly(); rjr.startJenkins(); diff --git a/src/test/java/org/jenkinsci/plugins/workflow/support/steps/ExecutorStepTest.java b/src/test/java/org/jenkinsci/plugins/workflow/support/steps/ExecutorStepTest.java index edbac15b..6de1a15d 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/support/steps/ExecutorStepTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/support/steps/ExecutorStepTest.java @@ -27,12 +27,8 @@ import static org.awaitility.Awaitility.await; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assumptions.assumeFalse; import com.google.common.base.Predicate; import edu.umd.cs.findbugs.annotations.Nullable; @@ -43,6 +39,7 @@ import hudson.model.Job; import hudson.model.Label; import hudson.model.Queue; +import hudson.model.Queue.LeftItem; import hudson.model.Result; import hudson.model.Run; import hudson.model.Slave; @@ -81,6 +78,16 @@ import jenkins.security.QueueItemAuthenticatorConfiguration; import net.sf.json.JSONArray; import net.sf.json.JSONObject; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.params.Parameter; +import org.junit.jupiter.params.ParameterizedClass; +import org.junit.jupiter.params.provider.ValueSource; +import org.jvnet.hudson.test.LogRecorder; +import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension; +import org.jvnet.hudson.test.junit.jupiter.InboundAgentExtension; +import org.jvnet.hudson.test.junit.jupiter.JenkinsSessionExtension; import org.springframework.security.core.Authentication; import org.apache.commons.io.IOUtils; import org.htmlunit.Page; @@ -102,46 +109,50 @@ import org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep; import org.jenkinsci.plugins.workflow.steps.durable_task.Messages; import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep; -import org.junit.Assume; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.jvnet.hudson.test.BuildWatcher; -import org.jvnet.hudson.test.FlagRule; -import org.jvnet.hudson.test.InboundAgentRule; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; -import org.jvnet.hudson.test.JenkinsSessionRule; -import org.jvnet.hudson.test.LoggerRule; import org.jvnet.hudson.test.MockAuthorizationStrategy; import org.jvnet.hudson.test.MockFolder; /** Tests pertaining to {@code node} and {@code sh} steps. */ -@RunWith(Parameterized.class) -public class ExecutorStepTest { +@ParameterizedClass(name = "watching={0}") +@ValueSource(booleans = {true, false}) +class ExecutorStepTest { - @Parameterized.Parameters(name = "watching={0}") public static List data() { - return List.of(false, true); - } - - @Parameterized.BeforeParam public static void useWatching(boolean x) { - DurableTaskStep.USE_WATCHING = x; - } + private static final Logger LOGGER = Logger.getLogger(ExecutorStepTest.class.getName()); - @Parameterized.Parameter public boolean useWatching; + @Parameter + private boolean useWatching; - private static final Logger LOGGER = Logger.getLogger(ExecutorStepTest.class.getName()); + @RegisterExtension + private static final BuildWatcherExtension buildWatcher = new BuildWatcherExtension(); - @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher(); - @Rule public JenkinsSessionRule sessions = new JenkinsSessionRule(); - @Rule public InboundAgentRule inboundAgents = new InboundAgentRule(); - @Rule public TemporaryFolder tmp = new TemporaryFolder(); + @RegisterExtension + private final JenkinsSessionExtension sessions = new JenkinsSessionExtension(); + @RegisterExtension + private final InboundAgentExtension inboundAgents = new InboundAgentExtension(); + @TempDir + private File tmp; // Currently too noisy due to unrelated warnings; might clear up if test dependencies updated: .record(ExecutorStepExecution.class, Level.FINE) - @Rule public LoggerRule logging = new LoggerRule(); - @Rule public FlagRule nodeTimeout = FlagRule.systemProperty("org.jenkinsci.plugins.workflow.support.pickles.ExecutorPickle.timeoutForNodeMillis"); + private final LogRecorder logging = new LogRecorder(); + private String nodeTimeout; + + @BeforeEach + void setUp() { + DurableTaskStep.USE_WATCHING = useWatching; + nodeTimeout = System.getProperty("org.jenkinsci.plugins.workflow.support.pickles.ExecutorPickle.timeoutForNodeMillis"); + } + + @AfterEach + void tearDown() { + if (nodeTimeout != null) { + System.setProperty("org.jenkinsci.plugins.workflow.support.pickles.ExecutorPickle.timeoutForNodeMillis", nodeTimeout); + } else { + System.clearProperty("org.jenkinsci.plugins.workflow.support.pickles.ExecutorPickle.timeoutForNodeMillis"); + } + } /** * Executes a shell script build on a build agent. @@ -149,7 +160,8 @@ public class ExecutorStepTest { * This ensures that the context variable overrides are working as expected, and * that they are persisted and resurrected. */ - @Test public void buildShellScriptOnSlave() throws Throwable { + @Test + void buildShellScriptOnSlave() throws Throwable { sessions.then(r -> { DumbSlave s = r.createSlave("remote quick", null); s.getNodeProperties().add(new EnvironmentVariablesNodeProperty(new EnvironmentVariablesNodeProperty.Entry("ONSLAVE", "true"))); @@ -191,7 +203,8 @@ public class ExecutorStepTest { * This ensures that the context variable overrides are working as expected, and * that they are persisted and resurrected. */ - @Test public void buildShellScriptWithPersistentProcesses() throws Throwable { + @Test + void buildShellScriptWithPersistentProcesses() throws Throwable { sessions.then(r -> { DumbSlave s = r.createSlave(); Path f1 = r.jenkins.getRootDir().toPath().resolve("test.txt"); @@ -221,8 +234,9 @@ public class ExecutorStepTest { }); } - @Test public void buildShellScriptAcrossRestart() throws Throwable { - Assume.assumeFalse("TODO not sure how to write a corresponding batch script", Functions.isWindows()); + @Test + void buildShellScriptAcrossRestart() throws Throwable { + assumeFalse(Functions.isWindows(), "TODO not sure how to write a corresponding batch script"); sessions.then(r -> { logging.record(DurableTaskStep.class, Level.FINE).record(FileMonitoringTask.class, Level.FINE).record(ExecutorStepDynamicContext.class, Level.FINE).record(ExecutorStepExecution.class, Level.FINE); DumbSlave s = r.createSlave("dumbo", null, null); @@ -260,8 +274,9 @@ public class ExecutorStepTest { } @Issue("JENKINS-52165") - @Test public void shellOutputAcrossRestart() throws Throwable { - Assume.assumeFalse("TODO not sure how to write a corresponding batch script", Functions.isWindows()); + @Test + void shellOutputAcrossRestart() throws Throwable { + assumeFalse(Functions.isWindows(), "TODO not sure how to write a corresponding batch script"); // TODO does not assert anything in watch mode, just informational. // There is no way for FileMonitoringTask.Watcher to know when content has been written through to the sink // other than by periodically flushing output and declining to write lastLocation until after this completes. @@ -298,8 +313,9 @@ public class ExecutorStepTest { }); } - @Test public void buildShellScriptAcrossDisconnect() throws Throwable { - Assume.assumeFalse("TODO not sure how to write a corresponding batch script", Functions.isWindows()); + @Test + void buildShellScriptAcrossDisconnect() throws Throwable { + assumeFalse(Functions.isWindows(), "TODO not sure how to write a corresponding batch script"); sessions.then(r -> { logging.record(DurableTaskStep.class, Level.FINE).record(FileMonitoringTask.class, Level.FINE); Slave s = inboundAgents.createAgent(r, "dumbo"); @@ -341,15 +357,16 @@ public class ExecutorStepTest { @Issue({"JENKINS-41854", "JENKINS-50504"}) @Test - public void contextualizeFreshFilePathAfterAgentReconnection() throws Throwable { - Assume.assumeFalse("TODO not sure how to write a corresponding batch script", Functions.isWindows()); + void contextualizeFreshFilePathAfterAgentReconnection() throws Throwable { + assumeFalse(Functions.isWindows(), "TODO not sure how to write a corresponding batch script"); sessions.then(r -> { logging.record(DurableTaskStep.class, Level.FINE). record(ExecutorStepDynamicContext.class, Level.FINE). record(FileMonitoringTask.class, Level.FINEST). record(WorkspaceList.class, Level.FINE); Slave s = inboundAgents.createAgent(r, "dumbo"); - r.showAgentLogs(s, logging); + r.showAgentLogs(s, Map.of(DurableTaskStep.class.getName(), Level.FINE, ExecutorStepDynamicContext.class.getName(), Level.FINE, + FileMonitoringTask.class.getName(), Level.FINEST, WorkspaceList.class.getName(), Level.FINE)); WorkflowJob p = r.createProject(WorkflowJob.class, "demo"); File f1 = new File(r.jenkins.getRootDir(), "f1"); File f2 = new File(r.jenkins.getRootDir(), "f2"); @@ -397,7 +414,8 @@ public void contextualizeFreshFilePathAfterAgentReconnection() throws Throwable Thread.sleep(100); } LOGGER.info("agent back online"); - r.showAgentLogs(s, logging); + r.showAgentLogs(s, Map.of(DurableTaskStep.class.getName(), Level.FINE, ExecutorStepDynamicContext.class.getName(), Level.FINE, + FileMonitoringTask.class.getName(), Level.FINEST, WorkspaceList.class.getName(), Level.FINE)); assertWorkspaceLocked(computer, workspacePath); assertTrue(f2.isFile()); assertTrue(f1.delete()); @@ -419,7 +437,8 @@ private static void assertWorkspaceLocked(Computer computer, String workspacePat } } - @Test public void buildShellScriptQuick() throws Throwable { + @Test + void buildShellScriptQuick() throws Throwable { sessions.then(r -> { DumbSlave s = r.createSlave(); s.getNodeProperties().add(new EnvironmentVariablesNodeProperty(new EnvironmentVariablesNodeProperty.Entry("ONSLAVE", "true"))); @@ -435,9 +454,10 @@ private static void assertWorkspaceLocked(Computer computer, String workspacePat }); } - @Test public void acquireWorkspace() throws Throwable { + @Test + void acquireWorkspace() throws Throwable { sessions.then(r -> { - String slaveRoot = tmp.newFolder().getPath(); + String slaveRoot = newFolder(tmp, "junit").getPath(); DumbSlave s = new DumbSlave("agent", slaveRoot, r.createComputerLauncher(null)); s.setNumExecutors(2); s.setRetentionStrategy(RetentionStrategy.NOOP); @@ -495,7 +515,8 @@ private static void assertLogMatches(WorkflowRun build, String regexp) throws IO } @Issue("JENKINS-26513") - @Test public void executorStepRestart() throws Throwable { + @Test + void executorStepRestart() throws Throwable { sessions.then(r -> { WorkflowJob p = r.createProject(WorkflowJob.class, "demo"); p.setDefinition(new CpsFlowDefinition("node('special') {echo 'OK ran'}", true)); @@ -511,14 +532,16 @@ private static void assertLogMatches(WorkflowRun build, String regexp) throws IO } @Issue("JENKINS-26130") - @Test public void unrestorableAgent() throws Throwable { + @Test + void unrestorableAgent() throws Throwable { sessions.then(r -> { DumbSlave dumbo = r.createSlave("dumbo", null, null); WorkflowJob p = r.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "node('dumbo') {\n" + - " semaphore 'wait'\n" + - "}", true)); + """ + node('dumbo') { + semaphore 'wait' + }""", true)); WorkflowRun b = p.scheduleBuild2(0).waitForStart(); SemaphoreStep.waitForStart("wait/1", b); dumbo.getComputer().setTemporarilyOffline(true, new OfflineCause.UserCause(User.getUnknown(), "not about to reconnect")); @@ -534,7 +557,8 @@ private static void assertLogMatches(WorkflowRun build, String regexp) throws IO }); } - @Test public void detailsExported() throws Throwable { + @Test + void detailsExported() throws Throwable { sessions.then(r -> { DumbSlave s = r.createSlave(); @@ -570,7 +594,8 @@ private static void assertLogMatches(WorkflowRun build, String regexp) throws IO }); } - @Test public void tailCall() throws Throwable { + @Test + void tailCall() throws Throwable { sessions.then(r -> { WorkflowJob p = r.createProject(WorkflowJob.class, "demo"); p.setDefinition(new CpsFlowDefinition("def r = node {'the result'}; echo \"got ${r}\"", true)); @@ -581,7 +606,8 @@ private static void assertLogMatches(WorkflowRun build, String regexp) throws IO } @Issue("JENKINS-31649") - @Test public void queueTaskVisibility() throws Throwable { + @Test + void queueTaskVisibility() throws Throwable { sessions.then(r -> { r.jenkins.setSecurityRealm(r.createDummySecurityRealm()); r.jenkins.setAuthorizationStrategy(new MockAuthorizationStrategy().grant(Jenkins.ADMINISTER).everywhere().to("admin")); @@ -610,7 +636,8 @@ private static void assertLogMatches(WorkflowRun build, String regexp) throws IO } @Issue("JENKINS-44981") - @Test public void queueItemAction() throws Throwable { + @Test + void queueItemAction() throws Throwable { sessions.then(r -> { final WorkflowJob p = r.createProject(WorkflowJob.class, "demo"); p.setDefinition(new CpsFlowDefinition("node('special') {}", true)); @@ -626,7 +653,7 @@ private static void assertLogMatches(WorkflowRun build, String regexp) throws IO assertEquals(1, items.length); assertEquals(p, items[0].task.getOwnerTask()); // // TODO 2.389+ remove cast - assertEquals(b, ((ExecutorStepExecution.PlaceholderTask) items[0].task).getOwnerExecutable()); + assertEquals(b, items[0].task.getOwnerExecutable()); assertEquals(items[0], QueueItemAction.getQueueItem(executorStartNode)); assertTrue(Queue.getInstance().cancel(items[0])); @@ -636,7 +663,7 @@ private static void assertLogMatches(WorkflowRun build, String regexp) throws IO FlowNode executorStartNode2 = new DepthFirstScanner().findFirstMatch(b.getExecution(), new ExecutorStepWithQueueItemPredicate()); assertNotNull(executorStartNode2); assertEquals(QueueItemAction.QueueState.CANCELLED, QueueItemAction.getNodeState(executorStartNode2)); - assertTrue(QueueItemAction.getQueueItem(executorStartNode2) instanceof Queue.LeftItem); + assertInstanceOf(Queue.LeftItem.class, QueueItemAction.getQueueItem(executorStartNode2)); // Re-run to make sure we actually get an agent and the action is set properly. r.createSlave("special", "special", null); @@ -646,7 +673,7 @@ private static void assertLogMatches(WorkflowRun build, String regexp) throws IO FlowNode executorStartNode3 = new DepthFirstScanner().findFirstMatch(b2.getExecution(), new ExecutorStepWithQueueItemPredicate()); assertNotNull(executorStartNode3); assertEquals(QueueItemAction.QueueState.LAUNCHED, QueueItemAction.getNodeState(executorStartNode3)); - assertTrue(QueueItemAction.getQueueItem(executorStartNode3) instanceof Queue.LeftItem); + assertInstanceOf(Queue.LeftItem.class, QueueItemAction.getQueueItem(executorStartNode3)); FlowNode notExecutorNode = new DepthFirstScanner().findFirstMatch(b.getExecution(), new NotExecutorStepPredicate()); assertNotNull(notExecutorNode); @@ -672,7 +699,8 @@ public boolean apply(@Nullable FlowNode input) { } @Issue("JENKINS-30759") - @Test public void quickNodeBlock() throws Throwable { + @Test + void quickNodeBlock() throws Throwable { sessions.then(r -> { WorkflowJob p = r.createProject(WorkflowJob.class, "demo"); p.setDefinition(new CpsFlowDefinition("for (int i = 0; i < 50; i++) {node {echo \"ran node block #${i}\"}}", true)); @@ -694,24 +722,27 @@ private List getWorkspaceActions(WorkflowRun workflowRun) { } @Issue("JENKINS-36547") - @Test public void reuseNodeFromPreviousRun() throws Throwable { + @Test + void reuseNodeFromPreviousRun() throws Throwable { sessions.then(r -> { createNOnlineAgentWithLabels(r, 5, "foo bar"); WorkflowJob p = r.createProject(WorkflowJob.class, "demo"); - p.setDefinition(new CpsFlowDefinition("node('foo') {\n" + - "}\n", true)); + p.setDefinition(new CpsFlowDefinition(""" + node('foo') { + } + """, true)); WorkflowRun run = r.buildAndAssertSuccess(p); List workspaceActions = getWorkspaceActions(run); - assertEquals(workspaceActions.size(), 1); + assertEquals(1, workspaceActions.size()); String firstNode = workspaceActions.get(0).getNode(); - assertNotEquals(firstNode, ""); + assertNotEquals("", firstNode); WorkflowRun run2 = r.buildAndAssertSuccess(p); workspaceActions = getWorkspaceActions(run2); - assertEquals(workspaceActions.size(), 1); + assertEquals(1, workspaceActions.size()); assertEquals(workspaceActions.get(0).getNode(), firstNode); }); } @@ -725,9 +756,8 @@ private Map mapNodeNameToLogText(WorkflowRun workflowRun) throws FlowGraphWalker walker = new FlowGraphWalker(workflowRun.getExecution()); Map workspaceActionToLogText = new HashMap<>(); for (FlowNode n : walker) { - if (n instanceof StepAtomNode) { - StepAtomNode atomNode = (StepAtomNode) n; - if (atomNode.getDescriptor() instanceof EchoStep.DescriptorImpl) { + if (n instanceof StepAtomNode atomNode) { + if (atomNode.getDescriptor() instanceof EchoStep.DescriptorImpl) { // we're searching for the echo only... LogAction l = atomNode.getAction(LogAction.class); if (l != null) { @@ -754,19 +784,21 @@ private Map mapNodeNameToLogText(WorkflowRun workflowRun) throws @Issue("JENKINS-36547") - @Test public void reuseNodesWithDifferentLabelsFromPreviousRuns() throws Throwable { + @Test + void reuseNodesWithDifferentLabelsFromPreviousRuns() throws Throwable { sessions.then(r -> { createNOnlineAgentWithLabels(r, 1, "foo bar"); WorkflowJob p = r.createProject(WorkflowJob.class, "demo"); p.setDefinition(new CpsFlowDefinition( - "node('foo') {\n" + - " echo \"ran node block foo\"\n" + - "}\n" + - "node('bar') {\n" + - " echo \"ran node block bar\"\n" + - "}\n" + - "", true)); + """ + node('foo') { + echo "ran node block foo" + } + node('bar') { + echo "ran node block bar" + } + """, true)); WorkflowRun run1 = r.buildAndAssertSuccess(p); Map nodeMapping1 = mapNodeNameToLogText(run1); @@ -782,7 +814,8 @@ private Map mapNodeNameToLogText(WorkflowRun workflowRun) throws * of the number of agents in order to get a pass */ @Issue("JENKINS-36547") - @Test public void reuseNodesWithSameLabelsInDifferentReorderedStages() throws Throwable { + @Test + void reuseNodesWithSameLabelsInDifferentReorderedStages() throws Throwable { sessions.then(r -> { // Note: for Jenkins versions > 2.265, the number of agents must be 5. // Older Jenkins versions used 3 agents. @@ -791,36 +824,36 @@ private Map mapNodeNameToLogText(WorkflowRun workflowRun) throws createNOnlineAgentWithLabels(r, totalAgents, "foo bar"); WorkflowJob p = r.createProject(WorkflowJob.class, "demo"); - p.setDefinition(new CpsFlowDefinition("" + - "stage('1') {\n" + - " node('foo') {\n" + - " echo \"ran node block first\"\n" + - " }\n" + - "}\n" + - "stage('2') {\n" + - " node('foo') {\n" + - " echo \"ran node block second\"\n" + - " }\n" + - "}\n" + - "", true)); + p.setDefinition(new CpsFlowDefinition(""" + stage('1') { + node('foo') { + echo "ran node block first" + } + } + stage('2') { + node('foo') { + echo "ran node block second" + } + } + """, true)); WorkflowRun run1 = r.buildAndAssertSuccess(p); Map nodeMapping1 = mapNodeNameToLogText(run1); // if nodeMapping contains only one entry this test actually will not test anything reasonable // possibly the number of agents has to be adjusted in that case - assertEquals(nodeMapping1.size(), 2); - - p.setDefinition(new CpsFlowDefinition("" + - "stage('2') {\n" + - " node('foo') {\n" + - " echo \"ran node block second\"\n" + - " }\n" + - "}\n" + - "stage('1') {\n" + - " node('foo') {\n" + - " echo \"ran node block first\"\n" + - " }\n" + - "}\n" + - "", true)); + assertEquals(2, nodeMapping1.size()); + + p.setDefinition(new CpsFlowDefinition(""" + stage('2') { + node('foo') { + echo "ran node block second" + } + } + stage('1') { + node('foo') { + echo "ran node block first" + } + } + """, true)); WorkflowRun run2 = r.buildAndAssertSuccess(p); Map nodeMapping2 = mapNodeNameToLogText(run2); @@ -834,7 +867,8 @@ private Map mapNodeNameToLogText(WorkflowRun workflowRun) throws * of the number of agents in order to get a pass */ @Issue("JENKINS-36547") - @Test public void reuseNodesWithSameLabelsInParallelStages() throws Throwable { + @Test + void reuseNodesWithSameLabelsInParallelStages() throws Throwable { sessions.then(r -> { createNOnlineAgentWithLabels(r, 4, "foo bar"); @@ -842,48 +876,48 @@ private Map mapNodeNameToLogText(WorkflowRun workflowRun) throws // 1: the second branch shall request the node first and wait inside the node block for the // first branch to acquire the node - p.setDefinition(new CpsFlowDefinition("" + - "def secondBranchReady = false\n" + - "def firstBranchDone = false\n" + - "parallel(1: {\n" + - " waitUntil { secondBranchReady }\n" + - " node('foo') {\n" + - " echo \"ran node block first\"\n" + - " }\n" + - " firstBranchDone = true\n" + - "}, 2: {\n" + - " node('foo') {\n" + - " echo \"ran node block second\"\n" + - " secondBranchReady = true\n" + - " waitUntil { firstBranchDone }\n" + - " }\n" + - "})\n" + - "", true)); + p.setDefinition(new CpsFlowDefinition(""" + def secondBranchReady = false + def firstBranchDone = false + parallel(1: { + waitUntil { secondBranchReady } + node('foo') { + echo "ran node block first" + } + firstBranchDone = true + }, 2: { + node('foo') { + echo "ran node block second" + secondBranchReady = true + waitUntil { firstBranchDone } + } + }) + """, true)); WorkflowRun run1 = r.buildAndAssertSuccess(p); Map nodeMapping1 = mapNodeNameToLogText(run1); // if nodeMapping contains only one entry this test actually will not test anything reasonable // possibly the number of agents has to be adjusted in that case - assertEquals(nodeMapping1.size(), 2); + assertEquals(2, nodeMapping1.size()); // 2: update script to force reversed order for node blocks; shall still pick the same nodes - p.setDefinition(new CpsFlowDefinition("" + - "def firstBranchReady = false\n" + - "def secondBranchDone = false\n" + - "parallel(1: {\n" + - " node('foo') {\n" + - " echo \"ran node block first\"\n" + - " firstBranchReady = true\n" + - " waitUntil { secondBranchDone }\n" + - " }\n" + - "}, 2: {\n" + - " waitUntil { firstBranchReady }\n" + - " node('foo') {\n" + - " echo \"ran node block second\"\n" + - " }\n" + - " secondBranchDone = true\n" + - "})\n" + - "", true)); + p.setDefinition(new CpsFlowDefinition(""" + def firstBranchReady = false + def secondBranchDone = false + parallel(1: { + node('foo') { + echo "ran node block first" + firstBranchReady = true + waitUntil { secondBranchDone } + } + }, 2: { + waitUntil { firstBranchReady } + node('foo') { + echo "ran node block second" + } + secondBranchDone = true + }) + """, true)); WorkflowRun run2 = r.buildAndAssertSuccess(p); Map nodeMapping2 = mapNodeNameToLogText(run2); assertEquals(nodeMapping1, nodeMapping2); @@ -896,61 +930,62 @@ private Map mapNodeNameToLogText(WorkflowRun workflowRun) throws * of the number of agents in order to get a pass */ @Issue("JENKINS-36547") - @Test public void reuseNodesWithSameLabelsInStagesWrappedInsideParallelStages() throws Throwable { + @Test + void reuseNodesWithSameLabelsInStagesWrappedInsideParallelStages() throws Throwable { sessions.then(r -> { createNOnlineAgentWithLabels(r, 4, "foo bar"); WorkflowJob p = r.createProject(WorkflowJob.class, "demo"); - p.setDefinition(new CpsFlowDefinition("" + - "def secondBranchReady = false\n" + - "def firstBranchDone = false\n" + - "parallel(1: {\n" + - " waitUntil { secondBranchReady }\n" + - " stage('stage1') {\n" + - " node('foo') {\n" + - " echo \"ran node block first\"\n" + - " }\n" + - " }\n" + - " firstBranchDone = true\n" + - "}, 2: {\n" + - " stage('stage1') {\n" + - " node('foo') {\n" + - " echo \"ran node block second\"\n" + - " secondBranchReady = true\n" + - " waitUntil { firstBranchDone }\n" + - " }\n" + - " }\n" + - "})\n" + - "", true)); + p.setDefinition(new CpsFlowDefinition(""" + def secondBranchReady = false + def firstBranchDone = false + parallel(1: { + waitUntil { secondBranchReady } + stage('stage1') { + node('foo') { + echo "ran node block first" + } + } + firstBranchDone = true + }, 2: { + stage('stage1') { + node('foo') { + echo "ran node block second" + secondBranchReady = true + waitUntil { firstBranchDone } + } + } + }) + """, true)); WorkflowRun run1 = r.buildAndAssertSuccess(p); Map nodeMapping1 = mapNodeNameToLogText(run1); // if nodeMapping contains only one entry this test actually will not test anything reasonable // possibly the number of agents has to be adjusted in that case - assertEquals(nodeMapping1.size(), 2); + assertEquals(2, nodeMapping1.size()); // update script to force reversed order for node blocks; shall still pick the same nodes - p.setDefinition(new CpsFlowDefinition("" + - "def firstBranchReady = false\n" + - "def secondBranchDone = false\n" + - "parallel(1: {\n" + - " stage('stage1') {\n" + - " node('foo') {\n" + - " echo \"ran node block first\"\n" + - " firstBranchReady = true\n" + - " waitUntil { secondBranchDone }\n" + - " }\n" + - " }\n" + - "}, 2: {\n" + - " waitUntil { firstBranchReady }\n" + - " stage('stage1') {\n" + - " node('foo') {\n" + - " echo \"ran node block second\"\n" + - " }\n" + - " }\n" + - " secondBranchDone = true\n" + - "})\n" + - "", true)); + p.setDefinition(new CpsFlowDefinition(""" + def firstBranchReady = false + def secondBranchDone = false + parallel(1: { + stage('stage1') { + node('foo') { + echo "ran node block first" + firstBranchReady = true + waitUntil { secondBranchDone } + } + } + }, 2: { + waitUntil { firstBranchReady } + stage('stage1') { + node('foo') { + echo "ran node block second" + } + } + secondBranchDone = true + }) + """, true)); WorkflowRun run2 = r.buildAndAssertSuccess(p); Map nodeMapping2 = mapNodeNameToLogText(run2); @@ -959,7 +994,8 @@ private Map mapNodeNameToLogText(WorkflowRun workflowRun) throws } @Issue("JENKINS-36547") - @Test public void reuseNodeInSameRun() throws Throwable { + @Test + void reuseNodeInSameRun() throws Throwable { sessions.then(r -> { createNOnlineAgentWithLabels(r, 5, "foo"); @@ -969,37 +1005,39 @@ private Map mapNodeNameToLogText(WorkflowRun workflowRun) throws Map nodeMapping = mapNodeNameToLogText(run); // if the node was reused every time we'll only have one node mapping entry - assertEquals(nodeMapping.size(), 1); + assertEquals(1, nodeMapping.size()); }); } @Issue("JENKINS-26132") - @Test public void taskDisplayName() throws Throwable { + @Test + void taskDisplayName() throws Throwable { sessions.then(r -> { WorkflowJob p = r.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "stage('one') {\n" + - " node {\n" + - " semaphore 'one'\n" + - " stage('two') {\n" + - " semaphore 'two'\n" + - " }\n" + - " }\n" + - "}\n" + - "stage('three') {\n" + - " node {\n" + - " semaphore 'three'\n" + - " }\n" + - " parallel a: {\n" + - " node {\n" + - " semaphore 'a'\n" + - " }\n" + - " }, b: {\n" + - " node {\n" + - " semaphore 'b'\n" + - " }\n" + - " }\n" + - "}", true)); + """ + stage('one') { + node { + semaphore 'one' + stage('two') { + semaphore 'two' + } + } + } + stage('three') { + node { + semaphore 'three' + } + parallel a: { + node { + semaphore 'a' + } + }, b: { + node { + semaphore 'b' + } + } + }""", true)); WorkflowRun b = p.scheduleBuild2(0).waitForStart(); SemaphoreStep.waitForStart("one/1", b); assertEquals(Collections.singletonList(n(b, "one")), currentLabels(r)); @@ -1038,7 +1076,8 @@ private static List currentLabels(JenkinsRule r) { @Issue("SECURITY-675") - @Test public void authentication() throws Throwable { + @Test + void authentication() throws Throwable { sessions.then(r -> { logging.record(ExecutorStepExecution.class, Level.FINE); Slave s = r.createSlave("remote", null, null); @@ -1072,7 +1111,8 @@ private static List currentLabels(JenkinsRule r) { } @Issue("JENKINS-58900") - @Test public void nodeDisconnectMissingContextVariableException() throws Throwable { + @Test + void nodeDisconnectMissingContextVariableException() throws Throwable { sessions.then(r -> { DumbSlave agent = r.createSlave(); WorkflowJob p = r.createProject(WorkflowJob.class); @@ -1100,8 +1140,7 @@ private static List currentLabels(JenkinsRule r) { } @Test - @Issue("JENKINS-60634") - public void tempDirVariable() throws Throwable { + @Issue("JENKINS-60634") void tempDirVariable() throws Throwable { sessions.then(r -> { WorkflowJob p = r.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition("node {if (isUnix()) {sh 'set -u && touch \"$WORKSPACE_TMP/x\"'} else {bat(/echo ok > \"%WORKSPACE_TMP%\\x\"/)}}", true)); @@ -1111,8 +1150,7 @@ public void tempDirVariable() throws Throwable { } @Test - @Issue("JENKINS-63486") - public void getOwnerTaskPermissions() throws Throwable { + @Issue("JENKINS-63486") void getOwnerTaskPermissions() throws Throwable { sessions.then(r -> { MockFolder f = r.createFolder("f"); WorkflowJob p = f.createProject(WorkflowJob.class, "p"); @@ -1134,7 +1172,8 @@ public void getOwnerTaskPermissions() throws Throwable { }); } - @Test public void getParentExecutable() throws Throwable { + @Test + void getParentExecutable() throws Throwable { sessions.then(r -> { DumbSlave s = r.createSlave(); WorkflowJob p = r.createProject(WorkflowJob.class, "p"); @@ -1150,9 +1189,10 @@ public void getOwnerTaskPermissions() throws Throwable { }); } - @Test public void placeholderTaskInQueueButAssociatedBuildComplete() throws Throwable { + @Test + void placeholderTaskInQueueButAssociatedBuildComplete() throws Throwable { logging.record(ExecutorStepExecution.class, Level.FINE).capture(50); - Path tempQueueFile = tmp.newFile().toPath(); + Path tempQueueFile = File.createTempFile("junit", null, tmp).toPath(); sessions.then(r -> { WorkflowJob p = r.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition("node('custom-label') { }", true)); @@ -1190,7 +1230,8 @@ public void getOwnerTaskPermissions() throws Throwable { }); } - @Test public void restartWhilePlaceholderTaskIsInQueue() throws Throwable { + @Test + void restartWhilePlaceholderTaskIsInQueue() throws Throwable { // Node reconnection takes a while during the second restart. System.setProperty("org.jenkinsci.plugins.workflow.support.pickles.ExecutorPickle.timeoutForNodeMillis", String.valueOf(TimeUnit.SECONDS.toMillis(30))); logging.record(ExecutorStepExecution.class, Level.FINE) @@ -1205,12 +1246,11 @@ public void getOwnerTaskPermissions() throws Throwable { Slave node = (Slave) r.jenkins.getNode("custom-label"); node.setNumExecutors(0); // Make sure the step won't be able to resume. }); - sessions.then(r -> { + sessions.then(r -> // Just wait for ExecutorStepDynamicContext.resume to schedule PlaceholderTask and then restart. await().atMost(15, TimeUnit.SECONDS).until( () -> Stream.of(Queue.getInstance().getItems()).map(item -> item.task).collect(Collectors.toList()), - hasItem(instanceOf(ExecutorStepExecution.PlaceholderTask.class))); - }); + hasItem(instanceOf(ExecutorStepExecution.PlaceholderTask.class)))); sessions.then(r -> { ((Slave) r.jenkins.getNode("custom-label")).setNumExecutors(1); // Allow node step to resume. WorkflowJob p = r.jenkins.getItemByFullName("p", WorkflowJob.class); @@ -1247,4 +1287,13 @@ private void createNOnlineAgentWithLabels(JenkinsRule r, int number, String labe r.waitOnline(agent); } } + + private static File newFolder(File root, String... subDirs) throws IOException { + String subFolder = String.join("/", subDirs); + File result = new File(root, subFolder); + if (!result.mkdirs()) { + throw new IOException("Couldn't create folders " + root); + } + return result; + } } diff --git a/src/test/java/org/jenkinsci/plugins/workflow/support/steps/PushdStepTest.java b/src/test/java/org/jenkinsci/plugins/workflow/support/steps/PushdStepTest.java index 55a602e4..9daaddd4 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/support/steps/PushdStepTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/support/steps/PushdStepTest.java @@ -24,6 +24,8 @@ package org.jenkinsci.plugins.workflow.support.steps; +import static org.junit.jupiter.api.Assertions.assertNotNull; + import hudson.FilePath; import hudson.slaves.DumbSlave; import java.util.logging.Level; @@ -31,21 +33,22 @@ 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.assertNotNull; -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.jvnet.hudson.test.LoggerRule; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.jvnet.hudson.test.LogRecorder; +import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension; +import org.jvnet.hudson.test.junit.jupiter.JenkinsSessionExtension; -public class PushdStepTest { +class PushdStepTest { - @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher(); - @Rule public JenkinsSessionRule sessions = new JenkinsSessionRule(); - @Rule public LoggerRule logging = new LoggerRule().record(FilePathDynamicContext.class, Level.FINE); + @RegisterExtension + private static final BuildWatcherExtension buildWatcher = new BuildWatcherExtension(); + @RegisterExtension + private final JenkinsSessionExtension sessions = new JenkinsSessionExtension(); + private final LogRecorder logging = new LogRecorder().record(FilePathDynamicContext.class, Level.FINE); - @Test public void basics() throws Throwable { + @Test + void basics() throws Throwable { sessions.then(j -> { WorkflowJob p = j.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition("node {dir('subdir') {echo(/now the pwd=${pwd()}/)}}", true)); @@ -53,7 +56,8 @@ public class PushdStepTest { }); } - @Test public void restarting() throws Throwable { + @Test + void restarting() throws Throwable { sessions.then(j -> { j.createSlave("remote", null, null); WorkflowJob p = j.createProject(WorkflowJob.class, "p"); diff --git a/src/test/java/org/jenkinsci/plugins/workflow/support/steps/WorkspaceStepTest.java b/src/test/java/org/jenkinsci/plugins/workflow/support/steps/WorkspaceStepTest.java index 4d04fbb5..742443c5 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/support/steps/WorkspaceStepTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/support/steps/WorkspaceStepTest.java @@ -31,21 +31,33 @@ 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.*; -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.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; + +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.junit.jupiter.BuildWatcherExtension; +import org.jvnet.hudson.test.junit.jupiter.WithJenkins; + +@WithJenkins +class WorkspaceStepTest { + + @RegisterExtension + private static final BuildWatcherExtension buildWatcher = new BuildWatcherExtension(); -public class WorkspaceStepTest { + private JenkinsRule r; - @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher(); - @Rule public JenkinsRule r = new JenkinsRule(); + @BeforeEach + void setUp(JenkinsRule rule) { + r = rule; + } @Issue("JENKINS-26072") - @Test public void customWorkspace() throws Exception { + @Test + void customWorkspace() throws Exception { DumbSlave s = r.createSlave(); WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition("node('" + s.getNodeName() + "') {ws('custom-location') {echo pwd()}}", true)); @@ -53,7 +65,8 @@ public class WorkspaceStepTest { } @Issue("JENKINS-26072") - @Test public void customWorkspaceConcurrency() throws Exception { + @Test + void customWorkspaceConcurrency() throws Exception { // Currently limited to WorkspaceList.allocate: WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p"); // Use the controller as it has 2 executors by default, whereas createSlave hardcodes 1, and I do not want to bother creating an agent by hand: @@ -73,8 +86,7 @@ public class WorkspaceStepTest { } @Test - @Issue("JENKINS-60634") - public void tempDirVariable() throws Exception { + @Issue("JENKINS-60634") void tempDirVariable() throws Exception { WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition("node {ws {if (isUnix()) {sh 'set -u && touch \"$WORKSPACE_TMP/x\"'} else {bat(/echo ok > \"%WORKSPACE_TMP%\\x\"/)}}}", true)); r.buildAndAssertSuccess(p);