From 090bc3951a035bf470f22457282a85ecbdbe6341 Mon Sep 17 00:00:00 2001 From: strangelookingnerd <49242855+strangelookingnerd@users.noreply.github.com> Date: Tue, 12 Aug 2025 11:21:42 +0200 Subject: [PATCH 1/4] Migrate tests to JUnit5 * Migrate annotations and imports * Migrate assertions * Remove public visibility for test classes and methods * Minor code cleanup --- pom.xml | 2 +- ...abilityHintBranchPropertyWorkflowTest.java | 46 +++-- .../multibranch/GitDirectorySCMNavigator.java | 18 +- .../multibranch/JobPropertyStepTest.java | 181 ++++++++++-------- .../NoTriggerBranchPropertyWorkflowTest.java | 30 ++- .../multibranch/ReadTrustedStepTest.java | 65 +++++-- .../multibranch/RepairBranchPropertyTest.java | 39 ++-- .../multibranch/ReplayActionTest.java | 58 ++++-- .../multibranch/ResolveScmStepTest.java | 30 +-- .../workflow/multibranch/SCMBinderTest.java | 126 +++++++----- .../workflow/multibranch/SCMVarTest.java | 111 ++++++----- .../WorkflowBranchProjectFactoryTest.java | 46 +++-- ...WorkflowMultiBranchProjectFactoryTest.java | 98 ++++++++-- .../WorkflowMultiBranchProjectTest.java | 68 ++++--- 14 files changed, 587 insertions(+), 331 deletions(-) diff --git a/pom.xml b/pom.xml index e1448373..a9dd09ae 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ THE SOFTWARE. org.jenkins-ci.plugins plugin - 5.18 + 5.19 org.jenkins-ci.plugins.workflow diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/DurabilityHintBranchPropertyWorkflowTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/DurabilityHintBranchPropertyWorkflowTest.java index cb5b2b4d..709940e6 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/DurabilityHintBranchPropertyWorkflowTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/DurabilityHintBranchPropertyWorkflowTest.java @@ -32,31 +32,42 @@ import jenkins.branch.NoTriggerOrganizationFolderProperty; import jenkins.plugins.git.GitSCMSource; import jenkins.plugins.git.GitSampleRepoRule; +import jenkins.plugins.git.junit.jupiter.WithGitSampleRepo; import org.jenkinsci.plugins.workflow.flow.DurabilityHintProvider; import org.jenkinsci.plugins.workflow.flow.FlowDurabilityHint; import org.jenkinsci.plugins.workflow.flow.GlobalDefaultFlowDurabilityLevel; import org.jenkinsci.plugins.workflow.job.WorkflowJob; import org.jenkinsci.plugins.workflow.job.WorkflowRun; import org.jenkinsci.plugins.workflow.job.properties.DurabilityHintJobProperty; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; +import org.jvnet.hudson.test.junit.jupiter.WithJenkins; import static org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProjectTest.scheduleAndFindBranchProject; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; /** * Integration test for {@link NoTriggerBranchProperty} and {@link NoTriggerOrganizationFolderProperty}. */ @Issue("JENKINS-32396") -public class DurabilityHintBranchPropertyWorkflowTest { +@WithJenkins +@WithGitSampleRepo +class DurabilityHintBranchPropertyWorkflowTest { - @Rule public JenkinsRule r = new JenkinsRule(); - @Rule public GitSampleRepoRule sampleRepo = new GitSampleRepoRule(); + private JenkinsRule r; + private GitSampleRepoRule sampleRepo; + + @BeforeEach + void setUp(JenkinsRule rule, GitSampleRepoRule repo) { + r = rule; + sampleRepo = repo; + } @Test - public void configRoundtrip() throws Exception { + void configRoundtrip() throws Exception { WorkflowMultiBranchProject mp = r.jenkins.createProject(WorkflowMultiBranchProject.class, "p"); BranchSource bs = new BranchSource(new GitSCMSource(null, sampleRepo.toString(), "", "*", "", false)); mp.getSourcesList().add(bs); @@ -70,11 +81,12 @@ public void configRoundtrip() throws Exception { break; } } - Assert.assertNotNull(prop); - Assert.assertEquals(FlowDurabilityHint.SURVIVABLE_NONATOMIC, prop.getHint()); + assertNotNull(prop); + assertEquals(FlowDurabilityHint.SURVIVABLE_NONATOMIC, prop.getHint()); } - @Test public void durabilityHintByPropertyStep() throws Exception { + @Test + void durabilityHintByPropertyStep() throws Exception { sampleRepo.init(); sampleRepo.write("Jenkinsfile", "properties([durabilityHint('" + FlowDurabilityHint.SURVIVABLE_NONATOMIC.getName()+"')])\n"+ @@ -82,28 +94,26 @@ public void configRoundtrip() throws Exception { sampleRepo.git("add", "Jenkinsfile"); sampleRepo.git("commit", "--all", "--message=flow"); - WorkflowMultiBranchProject mp = r.jenkins.createProject(WorkflowMultiBranchProject.class, "p"); mp.getSourcesList().add(new BranchSource(new GitSCMSource(null, sampleRepo.toString(), "", "*", "", false))); WorkflowJob p = scheduleAndFindBranchProject(mp, "master"); r.waitUntilNoActivity(); WorkflowRun b1 = p.getLastBuild(); - Assert.assertEquals(Result.SUCCESS, b1.getResult()); + assertEquals(Result.SUCCESS, b1.getResult()); DurabilityHintJobProperty prop = p.getProperty(DurabilityHintJobProperty.class); - Assert.assertEquals(FlowDurabilityHint.SURVIVABLE_NONATOMIC, prop.getHint()); + assertEquals(FlowDurabilityHint.SURVIVABLE_NONATOMIC, prop.getHint()); } @Test @Issue("JENKINS-48826") - public void durabilityHintByBranchProperty() throws Exception { + void durabilityHintByBranchProperty() throws Exception { sampleRepo.init(); sampleRepo.write("Jenkinsfile", "echo 'whynot'"); sampleRepo.git("add", "Jenkinsfile"); sampleRepo.git("commit", "--all", "--message=flow"); - WorkflowMultiBranchProject mp = r.jenkins.createProject(WorkflowMultiBranchProject.class, "p"); BranchSource bs = new BranchSource(new GitSCMSource(null, sampleRepo.toString(), "", "*", "", false)); mp.getSourcesList().add(bs); @@ -111,15 +121,15 @@ public void durabilityHintByBranchProperty() throws Exception { WorkflowJob p = scheduleAndFindBranchProject(mp, "master"); r.waitUntilNoActivity(); - Assert.assertEquals(FlowDurabilityHint.SURVIVABLE_NONATOMIC, DurabilityHintProvider.suggestedFor(p)); + assertEquals(FlowDurabilityHint.SURVIVABLE_NONATOMIC, DurabilityHintProvider.suggestedFor(p)); WorkflowRun b1 = p.getLastBuild(); - Assert.assertEquals(Result.SUCCESS, b1.getResult()); + assertEquals(Result.SUCCESS, b1.getResult()); // Ensure when we remove the property, branches see that on the next build bs.setStrategy(new DefaultBranchPropertyStrategy(new BranchProperty[]{})); p = scheduleAndFindBranchProject(mp, "master"); r.waitUntilNoActivity(); - Assert.assertEquals(GlobalDefaultFlowDurabilityLevel.getDefaultDurabilityHint(), DurabilityHintProvider.suggestedFor(mp.getItems().iterator().next())); + assertEquals(GlobalDefaultFlowDurabilityLevel.getDefaultDurabilityHint(), DurabilityHintProvider.suggestedFor(mp.getItems().iterator().next())); } } diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/GitDirectorySCMNavigator.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/GitDirectorySCMNavigator.java index 85a88328..12c69c24 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/GitDirectorySCMNavigator.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/GitDirectorySCMNavigator.java @@ -33,6 +33,7 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.regex.Matcher; import java.util.regex.Pattern; import jenkins.plugins.git.GitSCMSource; @@ -40,11 +41,12 @@ import jenkins.scm.api.SCMNavigatorDescriptor; import jenkins.scm.api.SCMSourceObserver; import org.apache.commons.io.IOUtils; -import static org.junit.Assert.assertFalse; import org.jenkinsci.Symbol; import org.kohsuke.stapler.DataBoundConstructor; +import static org.junit.jupiter.api.Assertions.assertFalse; + /** * Sample provider which scans a directory for Git checkouts. */ @@ -52,7 +54,8 @@ public class GitDirectorySCMNavigator extends SCMNavigator { private final String directory; - @DataBoundConstructor public GitDirectorySCMNavigator(String directory) { + @DataBoundConstructor + public GitDirectorySCMNavigator(String directory) { this.directory = directory; } @@ -66,7 +69,8 @@ protected String id() { return directory; } - @Override public void visitSources(SCMSourceObserver observer) throws IOException, InterruptedException { + @Override + public void visitSources(SCMSourceObserver observer) throws IOException, InterruptedException { TaskListener listener = observer.getListener(); File[] kids = new File(directory).listFiles(); if (kids == null) { @@ -89,7 +93,7 @@ protected String id() { continue; } String origin = kid.getAbsolutePath(); // fallback - for (String line : IOUtils.readLines(new ByteArrayInputStream(baos.toByteArray()))) { + for (String line : IOUtils.readLines(new ByteArrayInputStream(baos.toByteArray()), StandardCharsets.UTF_8)) { Matcher m = ORIGIN.matcher(line); if (m.matches()) { origin = m.group(1); @@ -109,11 +113,13 @@ protected String id() { public static class DescriptorImpl extends SCMNavigatorDescriptor { @NonNull - @Override public String getDisplayName() { + @Override + public String getDisplayName() { return "Directory of Git checkouts"; } - @Override public SCMNavigator newInstance(String name) { + @Override + public SCMNavigator newInstance(String name) { return null; } diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/JobPropertyStepTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/JobPropertyStepTest.java index e365706b..04c0521b 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/JobPropertyStepTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/JobPropertyStepTest.java @@ -53,6 +53,7 @@ import jenkins.plugins.git.GitSCMSource; import jenkins.plugins.git.GitBranchSCMHead; import jenkins.plugins.git.GitSampleRepoRule; +import jenkins.plugins.git.junit.jupiter.WithGitSampleRepo; import jenkins.plugins.git.traits.BranchDiscoveryTrait; import jenkins.triggers.ReverseBuildTrigger; import jenkins.scm.api.SCMHead; @@ -75,40 +76,49 @@ import org.jenkinsci.plugins.workflow.steps.StepConfigTester; import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.*; -import org.junit.After; -import org.junit.Assert; -import org.junit.ClassRule; -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; -import org.jvnet.hudson.test.BuildWatcher; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +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.BuildWatcherExtension; +import org.jvnet.hudson.test.junit.jupiter.WithJenkins; import org.jvnet.hudson.test.recipes.LocalData; import org.kohsuke.stapler.NoStaplerConstructorException; import static org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProjectTest.scheduleAndFindBranchProject; @Issue("JENKINS-30519") -public class JobPropertyStepTest { - - @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher(); - @Rule public JenkinsRule r = new JenkinsRule(); - @Rule public GitSampleRepoRule sampleRepo = new GitSampleRepoRule(); +@WithJenkins +@WithGitSampleRepo +class JobPropertyStepTest { + + @SuppressWarnings("unused") + private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension(); + private JenkinsRule r; + private GitSampleRepoRule sampleRepo; + + @BeforeEach + void setUp(JenkinsRule rule, GitSampleRepoRule repo) { + r = rule; + sampleRepo = repo; + } /** * Needed to ensure that we get a fresh {@code MockTrigger#startsAndStops} with each test run. Has to be *after* rather than * *before* to avoid weird ordering issues with {@code @LocalData}. */ - @After - public void resetStartsAndStops() { + @AfterEach + void tearDown() { MockTrigger.startsAndStops = new ArrayList<>(); } @SuppressWarnings("rawtypes") - @Test public void configRoundTripParameters() throws Exception { + @Test + void configRoundTripParameters() throws Exception { List properties = Collections.singletonList(new ParametersDefinitionProperty(new BooleanParameterDefinition("flag", true, null))); // TODO *ParameterDefinition.description ought to be defaulted to null: new SnippetizerTester(r).assertRoundTrip(new JobPropertyStep(properties), "properties([parameters([booleanParam(defaultValue: true, name: 'flag')])])"); @@ -130,7 +140,7 @@ public void resetStartsAndStops() { @Issue("JENKINS-51290") @Test - public void testPreviousBuildFailedHard() throws Exception { + void testPreviousBuildFailedHard() throws Exception { WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p"); // First we simulate a build that has resulted in a null execution @@ -140,7 +150,7 @@ public void testPreviousBuildFailedHard() throws Exception { Field f = run.getClass().getDeclaredField("execution"); f.setAccessible(true); f.set(run, null); - Assert.assertNull(run.getExecution()); + assertNull(run.getExecution()); // Verify build runs cleanly p.setDefinition(new CpsFlowDefinition("properties([buildDiscarder(logRotator(numToKeepStr: '1'))])", true)); @@ -148,7 +158,8 @@ public void testPreviousBuildFailedHard() throws Exception { } @SuppressWarnings("rawtypes") - @Test public void configRoundTripBuildDiscarder() throws Exception { + @Test + void configRoundTripBuildDiscarder() throws Exception { List properties = Collections.singletonList(new BuildDiscarderProperty(new LogRotator(1, 2, -1, 3))); // TODO structural form of LogRotator is awful; confusion between integer and string types, and failure to handle default values: @@ -169,7 +180,8 @@ public void testPreviousBuildFailedHard() throws Exception { } @Issue("JENKINS-35698") - @Test public void useParameter() throws Exception { + @Test + void useParameter() throws Exception { sampleRepo.init(); sampleRepo.write("Jenkinsfile", "properties([parameters([string(name: 'myparam', defaultValue: 'default value')])])\n" + @@ -233,9 +245,10 @@ public void testPreviousBuildFailedHard() throws Exception { r.assertLogContains("value bar", b9); } - @Ignore("TODO does not currently work; b2 says subsequently received #1") + @Disabled("TODO does not currently work; b2 says subsequently received #1") @Issue("JENKINS-70680") - @Test public void changingParameterDefault() throws Exception { + @Test + void changingParameterDefault() throws Exception { sampleRepo.init(); sampleRepo.write("Jenkinsfile", "properties([parameters([string(name: 'x', defaultValue: '#1')])]); echo(/initially received $params.x/)"); sampleRepo.git("add", "Jenkinsfile"); @@ -260,7 +273,8 @@ public void testPreviousBuildFailedHard() throws Exception { } @Issue({"JENKINS-27295", "https://www.jenkins.io/security/advisory/2016-05-11/#arbitrary-build-parameters-are-passed-to-build-scripts-as-environment-variables"}) - @Test public void triggerWithParameter() throws Exception { + @Test + void triggerWithParameter() throws Exception { WorkflowJob p = r.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition("properties([parameters([string(name: 'myparam')])]); echo(/got $params.myparam though the env var is $env.myparam/)", true)); r.assertLogContains("got the value though the env var is null", r.assertBuildStatusSuccess(p.scheduleBuild2(0, new ParametersAction(new StringParameterValue("myparam", "the value"))))); @@ -268,14 +282,15 @@ public void testPreviousBuildFailedHard() throws Exception { @Issue("JENKINS-26143") @Test - public void testChoiceParameterSnippetizer() throws Exception { + void testChoiceParameterSnippetizer() throws Exception { //new SnippetizerTester(r).assertGenerateSnippet(); new SnippetizerTester(r).assertRoundTrip(new JobPropertyStep(Collections.singletonList(new ParametersDefinitionProperty(new ChoiceParameterDefinition("paramName", new String[]{"foo", "bar", "baz"}, "test")))), "properties([parameters([choice(choices: ['foo', 'bar', 'baz'], description: 'test', name: 'paramName')])])"); } @SuppressWarnings("deprecation") // RunList.size - @Test public void useBuildDiscarder() throws Exception { + @Test + void useBuildDiscarder() throws Exception { sampleRepo.init(); sampleRepo.write("Jenkinsfile", "properties([buildDiscarder(logRotator(numToKeepStr: '1'))])"); sampleRepo.git("add", "Jenkinsfile"); @@ -298,7 +313,8 @@ public void testChoiceParameterSnippetizer() throws Exception { } @Issue("JENKINS-44848") - @Test public void onlyRemoveJenkinsfileProperties() throws Exception { + @Test + void onlyRemoveJenkinsfileProperties() throws Exception { WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p"); p.addProperty(new DisableConcurrentBuildsJobProperty()); @@ -339,7 +355,7 @@ public void testChoiceParameterSnippetizer() throws Exception { @Issue("JENKINS-44848") @LocalData @Test - public void trackerPropertyUpgrade() throws Exception { + void trackerPropertyUpgrade() throws Exception { WorkflowJob p = r.jenkins.getItemByFullName("trackerPropertyUpgrade", WorkflowJob.class); assertNotNull(p); WorkflowRun b1 = p.getLastBuild(); @@ -359,7 +375,8 @@ public void trackerPropertyUpgrade() throws Exception { } @Issue("JENKINS-34547") - @Test public void concurrentBuildProperty() throws Exception { + @Test + void concurrentBuildProperty() throws Exception { WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p"); // Verify the base case behavior. p.setDefinition(new CpsFlowDefinition("semaphore 'hang'", true)); @@ -404,7 +421,8 @@ public void trackerPropertyUpgrade() throws Exception { } @Issue("JENKINS-34005") - @Test public void triggersProperty() throws Exception { + @Test + void triggersProperty() throws Exception { WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p"); // Verify the base case behavior. p.setDefinition(new CpsFlowDefinition("echo 'foo'", true)); @@ -418,8 +436,10 @@ public void trackerPropertyUpgrade() throws Exception { // Now add a trigger. p.setDefinition(new CpsFlowDefinition( - "properties([pipelineTriggers([\n" - + " cron('@daily'), [$class: 'MockTrigger']])])\n" + "echo 'foo'", + """ + properties([pipelineTriggers([ + cron('@daily'), [$class: 'MockTrigger']])]) + echo 'foo'""", true)); WorkflowRun b = r.assertBuildStatusSuccess(p.scheduleBuild2(0)); @@ -457,7 +477,8 @@ public void trackerPropertyUpgrade() throws Exception { } @Issue("JENKINS-37731") - @Test public void scmTriggerProperty() throws Exception { + @Test + void scmTriggerProperty() throws Exception { WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p"); // Verify the base case behavior. p.setDefinition(new CpsFlowDefinition("echo 'foo'", true)); @@ -473,14 +494,16 @@ public void trackerPropertyUpgrade() throws Exception { // Looking for core versions 2.21 and later for the proper pollScm symbol, rather than the broken scm symbol. if (SymbolLookup.getSymbolValue(SCMTrigger.class).contains("pollSCM")) { p.setDefinition(new CpsFlowDefinition( - "properties([pipelineTriggers([\n" - + " pollSCM(scmpoll_spec: '@daily', ignorePostCommitHooks: true), [$class: 'MockTrigger']])])\n" - + "echo 'foo'", true)); + """ + properties([pipelineTriggers([ + pollSCM(scmpoll_spec: '@daily', ignorePostCommitHooks: true), [$class: 'MockTrigger']])]) + echo 'foo'""", true)); } else { p.setDefinition(new CpsFlowDefinition( - "properties([pipelineTriggers([pollSCM(scmpoll_spec: '@daily', ignorePostCommitHooks: true),\n" - + " [$class: 'MockTrigger']])])\n" - + "echo 'foo'", true)); + """ + properties([pipelineTriggers([pollSCM(scmpoll_spec: '@daily', ignorePostCommitHooks: true), + [$class: 'MockTrigger']])]) + echo 'foo'""", true)); } WorkflowRun b = r.assertBuildStatusSuccess(p.scheduleBuild2(0)); @@ -518,7 +541,8 @@ public void trackerPropertyUpgrade() throws Exception { assertEquals("[null, false, null]", MockTrigger.startsAndStops.toString()); } - @Test public void scmAndEmptyTriggersProperty() throws Exception { + @Test + void scmAndEmptyTriggersProperty() throws Exception { WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p"); // Verify the base case behavior. p.setDefinition(new CpsFlowDefinition("echo 'foo'", true)); @@ -561,7 +585,7 @@ public void trackerPropertyUpgrade() throws Exception { @Issue("JENKINS-37477") @Test - public void generateHelpTrigger() throws Exception { + void generateHelpTrigger() throws Exception { DescribableModel model = new DescribableModel<>(PipelineTriggersJobProperty.class); assertNotNull(model); @@ -601,16 +625,17 @@ private void recurseOnModel(DescribableModel model) throws Exception { @Issue("JENKINS-37477") @Test - public void configRoundTripTrigger() throws Exception { + void configRoundTripTrigger() throws Exception { List properties = Collections.singletonList(new PipelineTriggersJobProperty(Collections.singletonList(new TimerTrigger("@daily")))); - String snippetJson = "{'propertiesMap': {\n" + - " 'stapler-class-bag': 'true',\n" + - " 'org-jenkinsci-plugins-workflow-job-properties-PipelineTriggersJobProperty': {'triggers': {\n" + - " 'stapler-class-bag': 'true',\n" + - " 'hudson-triggers-TimerTrigger': {'spec': '@daily'}\n" + - " }}},\n" + - " 'stapler-class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep',\n" + - " '$class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep'}"; + String snippetJson = """ + {'propertiesMap': { + 'stapler-class-bag': 'true', + 'org-jenkinsci-plugins-workflow-job-properties-PipelineTriggersJobProperty': {'triggers': { + 'stapler-class-bag': 'true', + 'hudson-triggers-TimerTrigger': {'spec': '@daily'} + }}}, + 'stapler-class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep', + '$class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep'}"""; new SnippetizerTester(r).assertGenerateSnippet(snippetJson, "properties([pipelineTriggers([cron('@daily')])])", null); new SnippetizerTester(r).assertRoundTrip(new JobPropertyStep(properties), "properties([pipelineTriggers([cron('@daily')])])"); @@ -618,16 +643,17 @@ public void configRoundTripTrigger() throws Exception { @Issue("JENKINS-37721") @Test - public void configRoundTripSCMTrigger() throws Exception { + void configRoundTripSCMTrigger() throws Exception { List properties = Collections.singletonList(new PipelineTriggersJobProperty(Collections.singletonList(new SCMTrigger("@daily")))); - String snippetJson = "{'propertiesMap': {\n" + - " 'stapler-class-bag': 'true',\n" + - " 'org-jenkinsci-plugins-workflow-job-properties-PipelineTriggersJobProperty': {'triggers': {\n" + - " 'stapler-class-bag': 'true',\n" + - " 'hudson-triggers-SCMTrigger': {'scmpoll_spec': '@daily', 'ignorePostCommitHooks': false }\n" + - " }}},\n" + - " 'stapler-class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep',\n" + - " '$class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep'}"; + String snippetJson = """ + {'propertiesMap': { + 'stapler-class-bag': 'true', + 'org-jenkinsci-plugins-workflow-job-properties-PipelineTriggersJobProperty': {'triggers': { + 'stapler-class-bag': 'true', + 'hudson-triggers-SCMTrigger': {'scmpoll_spec': '@daily', 'ignorePostCommitHooks': false } + }}}, + 'stapler-class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep', + '$class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep'}"""; new SnippetizerTester(r).assertGenerateSnippet(snippetJson, "properties([pipelineTriggers([pollSCM('@daily')])])", null); new SnippetizerTester(r).assertRoundTrip(new JobPropertyStep(properties), "properties([pipelineTriggers([pollSCM('@daily')])])"); @@ -635,24 +661,25 @@ public void configRoundTripSCMTrigger() throws Exception { @Issue("JENKINS-34464") @Test - public void configRoundTripReverseBuildTrigger() throws Exception { + void configRoundTripReverseBuildTrigger() throws Exception { List properties = Collections.singletonList(new PipelineTriggersJobProperty(Collections.singletonList(new ReverseBuildTrigger("some-job", Result.UNSTABLE)))); - String snippetJson = "{'propertiesMap': {\n" + - " 'stapler-class-bag': 'true',\n" + - " 'org-jenkinsci-plugins-workflow-job-properties-PipelineTriggersJobProperty': {'triggers': {\n" + - " 'stapler-class-bag': 'true',\n" + - " 'jenkins-triggers-ReverseBuildTrigger': { 'threshold': 'UNSTABLE', 'upstreamProjects': 'some-job'}\n" + - " }}},\n" + - " 'stapler-class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep',\n" + - " '$class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep'}"; + String snippetJson = """ + {'propertiesMap': { + 'stapler-class-bag': 'true', + 'org-jenkinsci-plugins-workflow-job-properties-PipelineTriggersJobProperty': {'triggers': { + 'stapler-class-bag': 'true', + 'jenkins-triggers-ReverseBuildTrigger': { 'threshold': 'UNSTABLE', 'upstreamProjects': 'some-job'} + }}}, + 'stapler-class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep', + '$class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep'}"""; new SnippetizerTester(r).assertGenerateSnippet(snippetJson, "properties([pipelineTriggers([upstream(threshold: 'UNSTABLE', upstreamProjects: 'some-job')])])", null); new SnippetizerTester(r).assertRoundTrip(new JobPropertyStep(properties), "properties([pipelineTriggers([upstream(threshold: 'UNSTABLE', upstreamProjects: 'some-job')])])"); } @Issue("JENKINS-37005") - @Test - public void noPropertiesWarnings() throws Exception { + @Test + void noPropertiesWarnings() throws Exception { sampleRepo.init(); sampleRepo.write("Jenkinsfile", "echo \"branch=${env.BRANCH_NAME}\"\n" + "properties([disableConcurrentBuilds()])"); @@ -682,7 +709,8 @@ public void noPropertiesWarnings() throws Exception { } @Issue("JENKINS-37219") - @Test public void disableTriggers() throws Exception { + @Test + void disableTriggers() throws Exception { sampleRepo.init(); sampleRepo.write("Jenkinsfile", "properties([overrideIndexTriggers(false)])"); sampleRepo.git("add", "Jenkinsfile"); @@ -727,12 +755,13 @@ public void noPropertiesWarnings() throws Exception { @Issue("JENKINS-37219") @Test - public void snippetGeneratorOverrideIndexing() throws Exception { - String snippetJson = "{'propertiesMap':\n" + - "{'stapler-class-bag': 'true', 'jenkins-branch-OverrideIndexTriggersJobProperty': \n" + - "{'specified': true, 'enableTriggers': true}},\n" + - "'stapler-class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep',\n" + - "'$class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep'}"; + void snippetGeneratorOverrideIndexing() throws Exception { + String snippetJson = """ + {'propertiesMap': + {'stapler-class-bag': 'true', 'jenkins-branch-OverrideIndexTriggersJobProperty': + {'specified': true, 'enableTriggers': true}}, + 'stapler-class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep', + '$class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep'}"""; new SnippetizerTester(r).assertGenerateSnippet(snippetJson, "properties([overrideIndexTriggers(true)])", null); } diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/NoTriggerBranchPropertyWorkflowTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/NoTriggerBranchPropertyWorkflowTest.java index 2ef8b1bd..a2ff50d2 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/NoTriggerBranchPropertyWorkflowTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/NoTriggerBranchPropertyWorkflowTest.java @@ -34,26 +34,39 @@ import jenkins.branch.OrganizationFolder; import jenkins.plugins.git.GitSCMSource; import jenkins.plugins.git.GitSampleRepoRule; +import jenkins.plugins.git.junit.jupiter.WithGitSampleRepo; import jenkins.scm.impl.SingleSCMNavigator; import org.jenkinsci.plugins.workflow.job.WorkflowJob; import org.jenkinsci.plugins.workflow.job.WorkflowRun; -import org.junit.Test; -import static org.junit.Assert.*; -import org.junit.Rule; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertEquals; + +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; /** * Integration test for {@link NoTriggerBranchProperty} and {@link NoTriggerOrganizationFolderProperty}. */ @Issue("JENKINS-32396") -public class NoTriggerBranchPropertyWorkflowTest { +@WithJenkins +@WithGitSampleRepo +class NoTriggerBranchPropertyWorkflowTest { + + private JenkinsRule r; + private GitSampleRepoRule sampleRepo; - @Rule public JenkinsRule r = new JenkinsRule(); - @Rule public GitSampleRepoRule sampleRepo = new GitSampleRepoRule(); + @BeforeEach + void setUp(JenkinsRule rule, GitSampleRepoRule repo) { + r = rule; + sampleRepo = repo; + } @Issue("JENKINS-30206") - @Test public void singleRepo() throws Exception { + @Test + void singleRepo() throws Exception { round1(); WorkflowMultiBranchProject p = r.jenkins.createProject(WorkflowMultiBranchProject.class, "p"); BranchSource branchSource = new BranchSource(new GitSCMSource("source-id", sampleRepo.toString(), "", "*", "", false)); @@ -94,7 +107,8 @@ public class NoTriggerBranchPropertyWorkflowTest { assertEquals(4, newfeature.getNextBuildNumber()); } - @Test public void organizationFolder() throws Exception { + @Test + void organizationFolder() throws Exception { round1(); OrganizationFolder top = r.jenkins.createProject(OrganizationFolder.class, "top"); top.getProperties().add(new NoTriggerOrganizationFolderProperty("(?!release.*).*")); diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/ReadTrustedStepTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/ReadTrustedStepTest.java index 4a0fdaad..1f822cc5 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/ReadTrustedStepTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/ReadTrustedStepTest.java @@ -29,33 +29,52 @@ import jenkins.branch.BranchSource; import jenkins.plugins.git.GitSampleRepoRule; import jenkins.plugins.git.GitStep; +import jenkins.plugins.git.junit.jupiter.WithGitSampleRepo; import org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition; 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.Test; -import static org.junit.Assert.*; -import org.junit.ClassRule; -import org.junit.Rule; -import org.jvnet.hudson.test.BuildWatcher; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import org.jvnet.hudson.test.FlagRule; -import static org.junit.Assume.assumeFalse; +import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension; +import org.jvnet.hudson.test.junit.jupiter.WithJenkins; -public class ReadTrustedStepTest { +import static org.junit.jupiter.api.Assumptions.assumeFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertEquals; - @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher(); - @Rule public JenkinsRule r = new JenkinsRule(); - @Rule public GitSampleRepoRule sampleRepo = new GitSampleRepoRule(); - @Rule public FlagRule heavyweightCheckoutFlag = new FlagRule<>(() -> SCMBinder.USE_HEAVYWEIGHT_CHECKOUT, v -> { SCMBinder.USE_HEAVYWEIGHT_CHECKOUT = v; }); +@WithJenkins +@WithGitSampleRepo +class ReadTrustedStepTest { - @Test public void smokes() throws Exception { + @SuppressWarnings("unused") + private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension(); + private boolean heavyweightCheckoutFlag; + private JenkinsRule r; + private GitSampleRepoRule sampleRepo; + + @BeforeEach + void setUp(JenkinsRule rule, GitSampleRepoRule repo) { + r = rule; + sampleRepo = repo; + heavyweightCheckoutFlag = SCMBinder.USE_HEAVYWEIGHT_CHECKOUT; + } + + @AfterEach + void tearDown() { + SCMBinder.USE_HEAVYWEIGHT_CHECKOUT = heavyweightCheckoutFlag; + } + + @Test + void smokes() throws Exception { sampleRepo.init(); sampleRepo.write("Jenkinsfile", "echo \"said ${readTrusted 'message'}\""); sampleRepo.write("message", "how do you do"); @@ -98,7 +117,8 @@ public class ReadTrustedStepTest { r.assertLogContains("Obtained message from ", b); } - @Test public void exactRevision() throws Exception { + @Test + void exactRevision() throws Exception { sampleRepo.init(); sampleRepo.write("Jenkinsfile", "node {checkout scm; semaphore 'wait1'; def alpha = readTrusted 'alpha'; semaphore 'wait2'; echo \"first got ${alpha} then ${readTrusted 'beta'} vs. disk ${readFile 'alpha'} then ${readFile 'beta'}\"}"); sampleRepo.write("alpha", "1"); @@ -135,7 +155,8 @@ public class ReadTrustedStepTest { r.assertLogContains("now got 2 then 2 vs. disk 2 then 2", r.assertBuildStatusSuccess(r.waitForCompletion(b))); } - @Test public void evaluate() throws Exception { + @Test + void evaluate() throws Exception { sampleRepo.init(); sampleRepo.write("Jenkinsfile", "evaluate readTrusted('lib.groovy')"); sampleRepo.write("lib.groovy", "echo 'trustworthy library'"); @@ -167,7 +188,8 @@ public class ReadTrustedStepTest { } @Issue("JENKINS-31386") - @Test public void nonMultibranch() throws Exception { + @Test + void nonMultibranch() throws Exception { sampleRepo.init(); sampleRepo.write("Jenkinsfile", "echo \"said ${readTrusted 'message'}\""); sampleRepo.write("message", "how do you do"); @@ -182,7 +204,8 @@ public class ReadTrustedStepTest { } @Issue("JENKINS-42817") - @Test public void nonMultibranchHeavyweight() throws Exception { + @Test + void nonMultibranchHeavyweight() throws Exception { SCMBinder.USE_HEAVYWEIGHT_CHECKOUT = true; try { sampleRepo.init(); @@ -203,7 +226,7 @@ public class ReadTrustedStepTest { } @Test - public void pathTraversalRejected() throws Exception { + void pathTraversalRejected() throws Exception { SCMBinder.USE_HEAVYWEIGHT_CHECKOUT = true; sampleRepo.init(); sampleRepo.write("Jenkinsfile", "node { checkout scm; echo \"${readTrusted '../../secrets/master.key'}\"}"); @@ -224,7 +247,7 @@ public void pathTraversalRejected() throws Exception { @Issue("SECURITY-2491") @Test - public void symlinksInReadTrustedCannotEscapeWorkspaceContext() throws Exception { + void symlinksInReadTrustedCannotEscapeWorkspaceContext() throws Exception { assumeFalse(Functions.isWindows()); // On Windows, the symlink is treated as a regular file, so there is no vulnerability, but the behavior is different. SCMBinder.USE_HEAVYWEIGHT_CHECKOUT = true; sampleRepo.init(); @@ -246,7 +269,7 @@ public void symlinksInReadTrustedCannotEscapeWorkspaceContext() throws Exception @Issue("SECURITY-2491") @Test - public void symlinksInUntrustedRevisionCannotEscapeWorkspace() throws Exception { + void symlinksInUntrustedRevisionCannotEscapeWorkspace() throws Exception { assumeFalse(Functions.isWindows()); // On Windows, the symlink is treated as a regular file, so there is no vulnerability, but the behavior is different. SCMBinder.USE_HEAVYWEIGHT_CHECKOUT = true; sampleRepo.init(); @@ -274,7 +297,7 @@ public void symlinksInUntrustedRevisionCannotEscapeWorkspace() throws Exception @Issue("SECURITY-2491") @Test - public void symlinksInNonMultibranchCannotEscapeWorkspaceContextViaReadTrusted() throws Exception { + void symlinksInNonMultibranchCannotEscapeWorkspaceContextViaReadTrusted() throws Exception { assumeFalse(Functions.isWindows()); // On Windows, the symlink is treated as a regular file, so there is no vulnerability, but the behavior is different. SCMBinder.USE_HEAVYWEIGHT_CHECKOUT = true; sampleRepo.init(); diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/RepairBranchPropertyTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/RepairBranchPropertyTest.java index 18e7b6d3..724feb41 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/RepairBranchPropertyTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/RepairBranchPropertyTest.java @@ -37,28 +37,27 @@ import jenkins.scm.impl.mock.MockSCMDiscoverBranches; import jenkins.scm.impl.mock.MockSCMNavigator; import org.jenkinsci.plugins.workflow.job.WorkflowJob; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; +import org.jvnet.hudson.test.junit.jupiter.WithJenkins; import org.jvnet.hudson.test.recipes.LocalData; import java.io.IOException; -import static junit.framework.TestCase.assertEquals; -import static junit.framework.TestCase.assertNotNull; -import static junit.framework.TestCase.assertNull; -import static junit.framework.TestCase.assertTrue; +import static org.junit.jupiter.api.Assertions.*; -public class RepairBranchPropertyTest { +@WithJenkins +class RepairBranchPropertyTest { - @Rule - public JenkinsRule j = new JenkinsRule(); + private JenkinsRule j; private MockSCMController controller; - @Before - public void setUp() throws IOException { + @BeforeEach + void setUp(JenkinsRule rule) throws IOException { + j = rule; setup(MockSCMController.create()); } @@ -70,8 +69,9 @@ void setup(MockSCMController co) throws IOException { "echo 'hello'".getBytes()); } - @Test @Issue("JENKINS-55116") - public void removedProperty() throws Exception { + @Test + @Issue("JENKINS-55116") + void removedProperty() throws Exception { OrganizationFolder org = j.createProject(OrganizationFolder.class, "org"); org.getNavigators().add(new MockSCMNavigator(controller.getId(), new MockSCMDiscoverBranches())); org.save(); @@ -99,8 +99,9 @@ public void removedProperty() throws Exception { assertTrue(repo.getPrimaryView().contains((TopLevelItem)master)); } - @Test @Issue("JENKINS-55116") - public void removedPropertyLastBuildCorrupt() throws Exception { + @Test + @Issue("JENKINS-55116") + void removedPropertyLastBuildCorrupt() throws Exception { OrganizationFolder org = j.createProject(OrganizationFolder.class, "org"); org.getNavigators().add(new MockSCMNavigator(controller.getId(), new MockSCMDiscoverBranches())); org.save(); @@ -136,8 +137,10 @@ public void removedPropertyLastBuildCorrupt() throws Exception { assertTrue(repo.getPrimaryView().contains((TopLevelItem)master)); } - @Test @LocalData @Issue("JENKINS-55116") - public void removedPropertyAtStartup() throws Exception { + @Test + @LocalData + @Issue("JENKINS-55116") + void removedPropertyAtStartup() throws Exception { MockSCMController cont = MockSCMController.recreate("9ea2ef21-aa07-4973-a942-6c4c4c7851d1"); setup(cont); OrganizationFolder org = j.jenkins.getItem("org", j.jenkins, OrganizationFolder.class); diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/ReplayActionTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/ReplayActionTest.java index 28089529..034d1674 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/ReplayActionTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/ReplayActionTest.java @@ -29,6 +29,7 @@ import hudson.security.ACL; import hudson.security.ACLContext; import java.io.File; +import java.io.IOException; import java.util.Collections; import jenkins.branch.BranchProperty; import jenkins.branch.BranchSource; @@ -39,28 +40,41 @@ import jenkins.plugins.git.GitSCMSource; import jenkins.plugins.git.GitSampleRepoRule; import jenkins.plugins.git.GitStep; +import jenkins.plugins.git.junit.jupiter.WithGitSampleRepo; import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition; import org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition; import org.jenkinsci.plugins.workflow.cps.replay.ReplayAction; import org.jenkinsci.plugins.workflow.job.WorkflowJob; import org.jenkinsci.plugins.workflow.job.WorkflowRun; -import org.junit.Test; -import static org.junit.Assert.*; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.rules.TemporaryFolder; -import org.jvnet.hudson.test.BuildWatcher; +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.MockAuthorizationStrategy; +import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension; +import org.jvnet.hudson.test.junit.jupiter.WithJenkins; + +@WithJenkins +@WithGitSampleRepo +class ReplayActionTest { -public class ReplayActionTest { + @SuppressWarnings("unused") + private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension(); + @TempDir + private File tmp; + private JenkinsRule r; + private GitSampleRepoRule sampleRepo; - @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher(); - @Rule public JenkinsRule r = new JenkinsRule(); - @Rule public GitSampleRepoRule sampleRepo = new GitSampleRepoRule(); - @Rule public TemporaryFolder tmp = new TemporaryFolder(); + @BeforeEach + void setUp(JenkinsRule rule, GitSampleRepoRule repo) { + r = rule; + sampleRepo = repo; + } - @Test public void scriptFromSCM() throws Exception { + @Test + void scriptFromSCM() throws Exception { sampleRepo.init(); sampleRepo.write("Jenkinsfile", "node {checkout scm; echo \"loaded ${readFile 'file'}\"}"); sampleRepo.git("add", "Jenkinsfile"); @@ -81,7 +95,8 @@ public class ReplayActionTest { r.assertLogContains("this time loaded subsequent content", b); } - @Test public void multibranch() throws Exception { + @Test + void multibranch() throws Exception { sampleRepo.init(); sampleRepo.write("Jenkinsfile", "node {checkout scm; echo readFile('file')}"); sampleRepo.write("file", "initial content"); @@ -105,8 +120,9 @@ public class ReplayActionTest { r.assertLogContains("INITIAL CONTENT", b2); } - @Test public void permissions() throws Exception { - File clones = tmp.newFolder(); + @Test + void permissions() throws Exception { + File clones = newFolder(tmp, "junit"); sampleRepo.init(); sampleRepo.write("Jenkinsfile", ""); sampleRepo.git("add", "Jenkinsfile"); @@ -143,10 +159,11 @@ public class ReplayActionTest { p.setDefinition(new CpsFlowDefinition("", false)); b1 = p.scheduleBuild2(0).get(); assertTrue(canReplay(b1, "admin")); - assertFalse("not sandboxed, so only safe for admins", canReplay(b1, "dev1")); + assertFalse(canReplay(b1, "dev1"), "not sandboxed, so only safe for admins"); assertFalse(canReplay(b1, "dev2")); assertFalse(canReplay(b1, "dev3")); } + private static boolean canReplay(WorkflowRun b, String user) { final ReplayAction a = b.getAction(ReplayAction.class); try (ACLContext context = ACL.as(User.getById(user, true))) { @@ -154,4 +171,13 @@ private static boolean canReplay(WorkflowRun b, String user) { } } + 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/multibranch/ResolveScmStepTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/ResolveScmStepTest.java index b339ea9f..6475a69b 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/ResolveScmStepTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/ResolveScmStepTest.java @@ -29,25 +29,31 @@ import jenkins.scm.impl.mock.MockSCMController; import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition; import org.jenkinsci.plugins.workflow.job.WorkflowJob; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.jvnet.hudson.test.JenkinsRule; +import org.jvnet.hudson.test.junit.jupiter.WithJenkins; -public class ResolveScmStepTest { +@WithJenkins +class ResolveScmStepTest { - @ClassRule - public static JenkinsRule j = new JenkinsRule(); + private static JenkinsRule j; - @Before - public void cleanOutAllItems() throws Exception { + @BeforeAll + static void setUp(JenkinsRule rule) { + j = rule; + } + + @BeforeEach + void setUp() throws Exception { for (TopLevelItem i : j.getInstance().getItems()) { i.delete(); } } @Test - public void given_existingHeadName_when_invoked_then_existingHeadNameReturned() throws Exception { + void given_existingHeadName_when_invoked_then_existingHeadNameReturned() throws Exception { try (MockSCMController c = MockSCMController.create()) { c.createRepository("repo"); c.createBranch("repo", "foo"); @@ -66,7 +72,7 @@ public void given_existingHeadName_when_invoked_then_existingHeadNameReturned() } @Test - public void given_nonExistingHeadName_when_invokedIgnoringErrors_then_nullReturned() throws Exception { + void given_nonExistingHeadName_when_invokedIgnoringErrors_then_nullReturned() throws Exception { try (MockSCMController c = MockSCMController.create()) { c.createRepository("repo"); c.createBranch("repo", "foo"); @@ -83,7 +89,7 @@ public void given_nonExistingHeadName_when_invokedIgnoringErrors_then_nullReturn } @Test - public void given_nonExistingHeadName_when_invoked_then_abortThrown() throws Exception { + void given_nonExistingHeadName_when_invoked_then_abortThrown() throws Exception { try (MockSCMController c = MockSCMController.create()) { c.createRepository("repo"); c.createBranch("repo", "foo"); @@ -104,7 +110,7 @@ public void given_nonExistingHeadName_when_invoked_then_abortThrown() throws Exc } @Test - public void given_nonExistingHeadName_when_invokedWithDefault_then_defaultReturned() throws Exception { + void given_nonExistingHeadName_when_invokedWithDefault_then_defaultReturned() throws Exception { try (MockSCMController c = MockSCMController.create()) { c.createRepository("repo"); c.createBranch("repo", "manchu"); diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/SCMBinderTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/SCMBinderTest.java index 1699c113..b49cd91c 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/SCMBinderTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/SCMBinderTest.java @@ -45,42 +45,56 @@ import jenkins.plugins.git.GitBranchSCMRevision; import jenkins.plugins.git.GitSCMSource; import jenkins.plugins.git.GitSampleRepoRule; +import jenkins.plugins.git.junit.jupiter.WithGitSampleRepo; import jenkins.scm.api.SCMHead; import jenkins.scm.api.SCMRevision; import jenkins.scm.api.SCMRevisionAction; import jenkins.scm.api.SCMSourceDescriptor; + +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; +import org.junit.jupiter.api.BeforeEach; +import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension; +import org.jvnet.hudson.test.junit.jupiter.WithJenkins; import org.springframework.security.core.Authentication; import org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval; 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.Test; -import static org.junit.Assert.*; -import org.junit.ClassRule; -import org.junit.Rule; -import org.jvnet.hudson.test.BuildWatcher; +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; -public class SCMBinderTest { +@WithJenkins +@WithGitSampleRepo +class SCMBinderTest { - @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher(); - @Rule public JenkinsRule r = new JenkinsRule(); - @Rule public GitSampleRepoRule sampleGitRepo = new GitSampleRepoRule(); + @SuppressWarnings("unused") + private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension(); + private JenkinsRule r; + private GitSampleRepoRule sampleRepo; - @Test public void exactRevisionGit() throws Exception { - sampleGitRepo.init(); + @BeforeEach + void setUp(JenkinsRule rule, GitSampleRepoRule repo) { + r = rule; + sampleRepo = repo; + } + + @Test + void exactRevisionGit() throws Exception { + sampleRepo.init(); ScriptApproval sa = ScriptApproval.get(); sa.approveSignature("staticField hudson.model.Items XSTREAM2"); sa.approveSignature("method com.thoughtworks.xstream.XStream toXML java.lang.Object"); - sampleGitRepo.write("Jenkinsfile", "echo hudson.model.Items.XSTREAM2.toXML(scm); semaphore 'wait'; node {checkout scm; echo readFile('file')}"); - sampleGitRepo.write("file", "initial content"); - sampleGitRepo.git("add", "Jenkinsfile"); - sampleGitRepo.git("commit", "--all", "--message=flow"); + sampleRepo.write("Jenkinsfile", "echo hudson.model.Items.XSTREAM2.toXML(scm); semaphore 'wait'; node {checkout scm; echo readFile('file')}"); + sampleRepo.write("file", "initial content"); + sampleRepo.git("add", "Jenkinsfile"); + sampleRepo.git("commit", "--all", "--message=flow"); WorkflowMultiBranchProject mp = r.jenkins.createProject(WorkflowMultiBranchProject.class, "p"); - mp.getSourcesList().add(new BranchSource(new GitSCMSource(null, sampleGitRepo.toString(), "", "*", "", false))); + mp.getSourcesList().add(new BranchSource(new GitSCMSource(null, sampleRepo.toString(), "", "*", "", false))); WorkflowJob p = WorkflowMultiBranchProjectTest.scheduleAndFindBranchProject(mp, "master"); SemaphoreStep.waitForStart("wait/1", null); WorkflowRun b1 = p.getLastBuild(); @@ -88,11 +102,11 @@ public class SCMBinderTest { assertEquals(1, b1.getNumber()); assertRevisionAction(b1); r.assertLogContains("Obtained Jenkinsfile from ", b1); - sampleGitRepo.write("Jenkinsfile", "node {checkout scm; echo readFile('file').toUpperCase()}"); - sampleGitRepo.write("file", "subsequent content"); - sampleGitRepo.git("commit", "--all", "--message=tweaked"); + sampleRepo.write("Jenkinsfile", "node {checkout scm; echo readFile('file').toUpperCase()}"); + sampleRepo.write("file", "subsequent content"); + sampleRepo.git("commit", "--all", "--message=tweaked"); SemaphoreStep.success("wait/1", null); - sampleGitRepo.notifyCommit(r); + sampleRepo.notifyCommit(r); WorkflowRun b2 = p.getLastBuild(); assertEquals(2, b2.getNumber()); r.assertLogContains("initial content", r.waitForCompletion(b1)); @@ -127,39 +141,41 @@ public static void assertRevisionAction(WorkflowRun build) { } } - @Test public void deletedJenkinsfile() throws Exception { - sampleGitRepo.init(); - sampleGitRepo.write("Jenkinsfile", "node { echo 'Hello World' }"); - sampleGitRepo.git("add", "Jenkinsfile"); - sampleGitRepo.git("commit", "--all", "--message=flow"); + @Test + void deletedJenkinsfile() throws Exception { + sampleRepo.init(); + sampleRepo.write("Jenkinsfile", "node { echo 'Hello World' }"); + sampleRepo.git("add", "Jenkinsfile"); + sampleRepo.git("commit", "--all", "--message=flow"); WorkflowMultiBranchProject mp = r.jenkins.createProject(WorkflowMultiBranchProject.class, "p"); - mp.getSourcesList().add(new BranchSource(new GitSCMSource(null, sampleGitRepo.toString(), "", "*", "", false))); + mp.getSourcesList().add(new BranchSource(new GitSCMSource(null, sampleRepo.toString(), "", "*", "", false))); WorkflowJob p = WorkflowMultiBranchProjectTest.scheduleAndFindBranchProject(mp, "master"); assertEquals(1, mp.getItems().size()); r.waitUntilNoActivity(); WorkflowRun b1 = p.getLastBuild(); assertEquals(1, b1.getNumber()); - sampleGitRepo.git("rm", "Jenkinsfile"); - sampleGitRepo.git("commit", "--all", "--message=remove"); + sampleRepo.git("rm", "Jenkinsfile"); + sampleRepo.git("commit", "--all", "--message=remove"); WorkflowRun b2 = r.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0).get()); r.assertLogContains("Jenkinsfile not found", b2); } @Issue("JENKINS-40521") - @Test public void deletedBranch() throws Exception { + @Test + void deletedBranch() throws Exception { r.jenkins.setSecurityRealm(r.createDummySecurityRealm()); - sampleGitRepo.init(); + sampleRepo.init(); // TODO GitSCMSource offers no way to set a GitSCMExtension such as CleanBeforeCheckout; work around with deleteDir // (without cleaning, b2 will succeed since the workspace will still have a cached origin/feature ref) - sampleGitRepo.write("Jenkinsfile", "node {deleteDir(); checkout scm; echo 'Hello World'}"); - sampleGitRepo.git("add", "Jenkinsfile"); - sampleGitRepo.git("commit", "--all", "--message=flow"); - sampleGitRepo.git("checkout", "-b", "feature"); - sampleGitRepo.write("somefile", "stuff"); - sampleGitRepo.git("add", "somefile"); - sampleGitRepo.git("commit", "--all", "--message=tweaked"); + sampleRepo.write("Jenkinsfile", "node {deleteDir(); checkout scm; echo 'Hello World'}"); + sampleRepo.git("add", "Jenkinsfile"); + sampleRepo.git("commit", "--all", "--message=flow"); + sampleRepo.git("checkout", "-b", "feature"); + sampleRepo.write("somefile", "stuff"); + sampleRepo.git("add", "somefile"); + sampleRepo.git("commit", "--all", "--message=tweaked"); WorkflowMultiBranchProject mp = r.jenkins.createProject(WorkflowMultiBranchProject.class, "p"); - mp.getSourcesList().add(new BranchSource(new GitSCMSource(null, sampleGitRepo.toString(), "", "*", "", false))); + mp.getSourcesList().add(new BranchSource(new GitSCMSource(null, sampleRepo.toString(), "", "*", "", false))); mp.setOrphanedItemStrategy(new DefaultOrphanedItemStrategy(false, "", "")); WorkflowJob p = WorkflowMultiBranchProjectTest.scheduleAndFindBranchProject(mp, "feature"); assertEquals(2, mp.getItems().size()); @@ -169,8 +185,8 @@ public static void assertRevisionAction(WorkflowRun build) { Authentication auth = User.getById("dev", true).impersonate2(); assertFalse(p.getACL().hasPermission2(auth, Item.DELETE)); assertTrue(p.isBuildable()); - sampleGitRepo.git("checkout", "master"); - sampleGitRepo.git("branch", "-D", "feature"); + sampleRepo.git("checkout", "master"); + sampleRepo.git("branch", "-D", "feature"); { // TODO AbstractGitSCMSource.retrieve(SCMHead, TaskListener) is incorrect: after fetching remote refs into the cache, // the origin/feature ref remains locally even though it has been deleted upstream, since only the other overload prunes stale remotes: Util.deleteRecursive(new File(r.jenkins.getRootDir(), "caches")); @@ -189,14 +205,15 @@ public static void assertRevisionAction(WorkflowRun build) { assertEquals(1, mp.getItems().size()); } - @Test public void untrustedRevisions() throws Exception { - sampleGitRepo.init(); - sampleGitRepo.write("Jenkinsfile", "node {checkout scm; echo readFile('file')}"); - sampleGitRepo.write("file", "initial content"); - sampleGitRepo.git("add", "Jenkinsfile"); - sampleGitRepo.git("commit", "--all", "--message=flow"); + @Test + void untrustedRevisions() throws Exception { + sampleRepo.init(); + sampleRepo.write("Jenkinsfile", "node {checkout scm; echo readFile('file')}"); + sampleRepo.write("file", "initial content"); + sampleRepo.git("add", "Jenkinsfile"); + sampleRepo.git("commit", "--all", "--message=flow"); WorkflowMultiBranchProject mp = r.jenkins.createProject(WorkflowMultiBranchProject.class, "p"); - mp.getSourcesList().add(new BranchSource(new WarySource(null, sampleGitRepo.toString(), "", "*", "", false))); + mp.getSourcesList().add(new BranchSource(new WarySource(null, sampleRepo.toString(), "", "*", "", false))); WorkflowJob p = WorkflowMultiBranchProjectTest.scheduleAndFindBranchProject(mp, "master"); r.waitUntilNoActivity(); WorkflowRun b = p.getLastBuild(); @@ -206,10 +223,10 @@ public static void assertRevisionAction(WorkflowRun build) { r.assertBuildStatusSuccess(b); r.assertLogContains("initial content", b); String branch = "some-other-branch-from-Norway"; - sampleGitRepo.git("checkout", "-b", branch); - sampleGitRepo.write("Jenkinsfile", "error 'ALL YOUR BUILD STEPS ARE BELONG TO US'"); - sampleGitRepo.write("file", "subsequent content"); - sampleGitRepo.git("commit", "--all", "--message=big evil laugh"); + sampleRepo.git("checkout", "-b", branch); + sampleRepo.write("Jenkinsfile", "error 'ALL YOUR BUILD STEPS ARE BELONG TO US'"); + sampleRepo.write("file", "subsequent content"); + sampleRepo.git("commit", "--all", "--message=big evil laugh"); p = WorkflowMultiBranchProjectTest.scheduleAndFindBranchProject(mp, branch); r.waitUntilNoActivity(); b = p.getLastBuild(); @@ -221,11 +238,13 @@ public static void assertRevisionAction(WorkflowRun build) { r.assertLogContains("subsequent content", b); r.assertLogContains("not trusting", b); } + public static class WarySource extends GitSCMSource { public WarySource(String id, String remote, String credentialsId, String includes, String excludes, boolean ignoreOnPushNotifications) { super(id, remote, credentialsId, includes, excludes, ignoreOnPushNotifications); } - @Override public SCMRevision getTrustedRevision(@NonNull SCMRevision revision, @NonNull TaskListener listener) throws IOException, InterruptedException { + @Override + public SCMRevision getTrustedRevision(@NonNull SCMRevision revision, @NonNull TaskListener listener) throws IOException, InterruptedException { String branch = revision.getHead().getName(); if (branch.equals("master")) { return revision; @@ -234,7 +253,8 @@ public WarySource(String id, String remote, String credentialsId, String include return fetch(new SCMHead("master"), listener); } } - @Override public SCMSourceDescriptor getDescriptor() { + @Override + public SCMSourceDescriptor getDescriptor() { return Jenkins.get().getDescriptorByType(GitSCMSource.DescriptorImpl.class); } } diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/SCMVarTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/SCMVarTest.java index ee308b1e..d3326679 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/SCMVarTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/SCMVarTest.java @@ -28,8 +28,11 @@ import hudson.model.Run; import hudson.model.TaskListener; import java.io.File; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.Arrays; +import java.util.List; + import jenkins.branch.BranchProperty; import jenkins.branch.BranchSource; import jenkins.branch.DefaultBranchPropertyStrategy; @@ -37,6 +40,7 @@ import jenkins.plugins.git.GitSCMSource; import jenkins.plugins.git.GitSampleRepoRule; import jenkins.plugins.git.GitStep; +import jenkins.plugins.git.junit.jupiter.WithGitSampleRepo; import org.apache.commons.io.FileUtils; import org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition; import org.jenkinsci.plugins.workflow.job.WorkflowJob; @@ -45,29 +49,40 @@ import org.jenkinsci.plugins.workflow.libs.LibraryConfiguration; import org.jenkinsci.plugins.workflow.libs.LibraryRetriever; import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep; -import org.junit.Test; -import static org.junit.Assert.*; -import org.junit.ClassRule; -import org.junit.Rule; -import org.jvnet.hudson.test.BuildWatcher; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertEquals; + +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.JenkinsSessionRule; +import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension; +import org.jvnet.hudson.test.junit.jupiter.JenkinsSessionExtension; -public class SCMVarTest { +@WithGitSampleRepo +class SCMVarTest { - @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher(); - @Rule public JenkinsSessionRule story = new JenkinsSessionRule(); - @Rule public GitSampleRepoRule sampleGitRepo = new GitSampleRepoRule(); + @SuppressWarnings("unused") + private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension(); + @RegisterExtension + private final JenkinsSessionExtension story = new JenkinsSessionExtension(); + private GitSampleRepoRule sampleRepo; + + @BeforeEach + void setUp(GitSampleRepoRule repo) { + sampleRepo = repo; + } - @Test public void scmPickle() throws Throwable { + @Test + void scmPickle() throws Throwable { story.then(j -> { - sampleGitRepo.init(); - sampleGitRepo.write("Jenkinsfile", "def _scm = scm; semaphore 'wait'; node {checkout _scm; echo readFile('file')}"); - sampleGitRepo.write("file", "initial content"); - sampleGitRepo.git("add", "Jenkinsfile"); - sampleGitRepo.git("commit", "--all", "--message=flow"); + sampleRepo.init(); + sampleRepo.write("Jenkinsfile", "def _scm = scm; semaphore 'wait'; node {checkout _scm; echo readFile('file')}"); + sampleRepo.write("file", "initial content"); + sampleRepo.git("add", "Jenkinsfile"); + sampleRepo.git("commit", "--all", "--message=flow"); WorkflowMultiBranchProject mp = j.jenkins.createProject(WorkflowMultiBranchProject.class, "p"); - mp.getSourcesList().add(new BranchSource(new GitSCMSource(null, sampleGitRepo.toString(), "", "*", "", false), new DefaultBranchPropertyStrategy(new BranchProperty[0]))); + mp.getSourcesList().add(new BranchSource(new GitSCMSource(null, sampleRepo.toString(), "", "*", "", false), new DefaultBranchPropertyStrategy(new BranchProperty[0]))); WorkflowJob p = WorkflowMultiBranchProjectTest.scheduleAndFindBranchProject(mp, "master"); SemaphoreStep.waitForStart("wait/1", null); WorkflowRun b1 = p.getLastBuild(); @@ -86,37 +101,40 @@ public class SCMVarTest { } @Issue("JENKINS-30222") - @Test public void globalVariable() throws Throwable { + @Test + void globalVariable() throws Throwable { story.then(j -> { // Set up a standardJob definition: File lib = new File(Jenkins.get().getRootDir(), "somelib"); LibraryConfiguration cfg = new LibraryConfiguration("somelib", new LocalRetriever(lib)); cfg.setImplicit(true); cfg.setDefaultVersion("fixed"); - GlobalLibraries.get().setLibraries(Arrays.asList(cfg)); + GlobalLibraries.get().setLibraries(List.of(cfg)); File vars = new File(lib, "vars"); Files.createDirectories(vars.toPath()); FileUtils.writeStringToFile(new File(vars, "standardJob.groovy"), - "def call(body) {\n" + - " def config = [:]\n" + - " body.resolveStrategy = Closure.DELEGATE_FIRST\n" + - " body.delegate = config\n" + - " body()\n" + - " node {\n" + - " checkout scm\n" + - " echo \"loaded ${readFile config.file}\"\n" + - " }\n" + - "}\n"); + """ + def call(body) { + def config = [:] + body.resolveStrategy = Closure.DELEGATE_FIRST + body.delegate = config + body() + node { + checkout scm + echo "loaded ${readFile config.file}" + } + } + """, StandardCharsets.UTF_8); // Then a project using it: - sampleGitRepo.init(); - sampleGitRepo.write("Jenkinsfile", "standardJob {file = 'resource'}"); - sampleGitRepo.write("resource", "resource content"); - sampleGitRepo.git("add", "Jenkinsfile"); - sampleGitRepo.git("add", "resource"); - sampleGitRepo.git("commit", "--all", "--message=flow"); + sampleRepo.init(); + sampleRepo.write("Jenkinsfile", "standardJob {file = 'resource'}"); + sampleRepo.write("resource", "resource content"); + sampleRepo.git("add", "Jenkinsfile"); + sampleRepo.git("add", "resource"); + sampleRepo.git("commit", "--all", "--message=flow"); // And run: WorkflowMultiBranchProject mp = j.jenkins.createProject(WorkflowMultiBranchProject.class, "p"); - mp.getSourcesList().add(new BranchSource(new GitSCMSource(null, sampleGitRepo.toString(), "", "*", "", false), new DefaultBranchPropertyStrategy(new BranchProperty[0]))); + mp.getSourcesList().add(new BranchSource(new GitSCMSource(null, sampleRepo.toString(), "", "*", "", false), new DefaultBranchPropertyStrategy(new BranchProperty[0]))); WorkflowJob p = WorkflowMultiBranchProjectTest.scheduleAndFindBranchProject(mp, "master"); WorkflowRun b = j.assertBuildStatusSuccess(p.scheduleBuild2(0)); j.assertLogContains("loaded resource content", b); @@ -129,24 +147,27 @@ private static final class LocalRetriever extends LibraryRetriever { LocalRetriever(File lib) { this.lib = lib; } - @Override public void retrieve(String name, String version, boolean changelog, FilePath target, Run run, TaskListener listener) throws Exception { + @Override + public void retrieve(String name, String version, boolean changelog, FilePath target, Run run, TaskListener listener) throws Exception { new FilePath(lib).copyRecursiveTo(target); } - @Override public void retrieve(String name, String version, FilePath target, Run run, TaskListener listener) throws Exception { + @Override + public void retrieve(String name, String version, FilePath target, Run run, TaskListener listener) throws Exception { retrieve(name, version, false, target, run, listener); } } @Issue("JENKINS-31386") - @Test public void standaloneProject() throws Throwable { + @Test + void standaloneProject() throws Throwable { story.then(j -> { - sampleGitRepo.init(); - sampleGitRepo.write("Jenkinsfile", "node {checkout scm; echo readFile('file')}"); - sampleGitRepo.write("file", "some content"); - sampleGitRepo.git("add", "Jenkinsfile"); - sampleGitRepo.git("commit", "--all", "--message=flow"); + sampleRepo.init(); + sampleRepo.write("Jenkinsfile", "node {checkout scm; echo readFile('file')}"); + sampleRepo.write("file", "some content"); + sampleRepo.git("add", "Jenkinsfile"); + sampleRepo.git("commit", "--all", "--message=flow"); WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p"); - p.setDefinition(new CpsScmFlowDefinition(new GitStep(sampleGitRepo.toString()).createSCM(), "Jenkinsfile")); + p.setDefinition(new CpsScmFlowDefinition(new GitStep(sampleRepo.toString()).createSCM(), "Jenkinsfile")); WorkflowRun b = j.assertBuildStatusSuccess(p.scheduleBuild2(0)); j.assertLogContains("some content", b); }); diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowBranchProjectFactoryTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowBranchProjectFactoryTest.java index 31732f08..0b116a43 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowBranchProjectFactoryTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowBranchProjectFactoryTest.java @@ -29,36 +29,49 @@ import jenkins.branch.BranchSource; import jenkins.plugins.git.GitSCMSource; import jenkins.plugins.git.GitSampleRepoRule; +import jenkins.plugins.git.junit.jupiter.WithGitSampleRepo; import jenkins.plugins.git.traits.BranchDiscoveryTrait; import org.jenkinsci.plugins.workflow.job.WorkflowJob; import org.jenkinsci.plugins.workflow.job.WorkflowRun; import static org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProjectTest.scheduleAndFindBranchProject; -import org.junit.Test; -import static org.junit.Assert.*; -import org.junit.ClassRule; -import org.junit.Rule; -import org.jvnet.hudson.test.BuildWatcher; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertEquals; + +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.JenkinsSessionRule; +import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension; +import org.jvnet.hudson.test.junit.jupiter.JenkinsSessionExtension; + +@WithGitSampleRepo +class WorkflowBranchProjectFactoryTest { -public class WorkflowBranchProjectFactoryTest { + @SuppressWarnings("unused") + private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension(); + @RegisterExtension + private final JenkinsSessionExtension story = new JenkinsSessionExtension(); + private GitSampleRepoRule sampleRepo; - @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher(); - @Rule public JenkinsSessionRule story = new JenkinsSessionRule(); - @Rule public GitSampleRepoRule sampleRepo = new GitSampleRepoRule(); + @BeforeEach + void setUp(GitSampleRepoRule repo) { + sampleRepo = repo; + } @Issue("JENKINS-30744") - @Test public void slashyBranches() throws Throwable { + @Test + void slashyBranches() throws Throwable { story.then(j -> { sampleRepo.init(); sampleRepo.git("checkout", "-b", "dev/main"); String script = - "echo \"branch=${env.BRANCH_NAME}\"\n" + - "node {\n" + - " checkout scm\n" + - " echo \"workspace=${pwd().replaceFirst('.+dev', 'dev')}\"\n" + - "}"; + """ + echo "branch=${env.BRANCH_NAME}" + node { + checkout scm + echo "workspace=${pwd().replaceFirst('.+dev', 'dev')}" + }"""; sampleRepo.write("Jenkinsfile", script); sampleRepo.git("add", "Jenkinsfile"); sampleRepo.git("commit", "--all", "--message=flow"); @@ -88,6 +101,7 @@ public class WorkflowBranchProjectFactoryTest { verifyProject(j, p); }); } + private static void verifyProject(JenkinsRule j, WorkflowJob p) throws Exception { assertEquals("dev%2Fmain", p.getName()); assertEquals("dev/main", p.getDisplayName()); diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectFactoryTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectFactoryTest.java index 6563c7c7..f3d5779d 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectFactoryTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectFactoryTest.java @@ -30,35 +30,89 @@ import hudson.security.ACL; import hudson.security.FullControlOnceLoggedInAuthorizationStrategy; import java.io.File; +import java.io.IOException; import java.util.List; import jenkins.branch.MultiBranchProject; import jenkins.branch.OrganizationFolder; import jenkins.plugins.git.GitSampleRepoRule; +import jenkins.plugins.git.junit.jupiter.GitSampleRepoExtension; import jenkins.scm.api.SCMSource; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.*; +import org.junit.jupiter.api.io.TempDir; +import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension; +import org.jvnet.hudson.test.junit.jupiter.WithJenkins; import org.springframework.security.core.Authentication; + +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; import org.jenkinsci.plugins.workflow.job.WorkflowJob; import org.jenkinsci.plugins.workflow.job.WorkflowRun; -import static org.junit.Assert.*; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.jvnet.hudson.test.BuildWatcher; +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; -public class WorkflowMultiBranchProjectFactoryTest { +@WithJenkins +@ExtendWith(WorkflowMultiBranchProjectFactoryTest.MultiGitSampleRepoExtension.class) +class WorkflowMultiBranchProjectFactoryTest { + + @SuppressWarnings("unused") + private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension(); + @TempDir + private File tmp; + private JenkinsRule r; - @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher(); - @Rule public JenkinsRule r = new JenkinsRule(); - @Rule public GitSampleRepoRule sampleRepo1 = new GitSampleRepoRule(); - @Rule public GitSampleRepoRule sampleRepo2 = new GitSampleRepoRule(); - @Rule public GitSampleRepoRule sampleRepo3 = new GitSampleRepoRule(); - @Rule public TemporaryFolder tmp = new TemporaryFolder(); + private GitSampleRepoRule sampleRepo1; + private GitSampleRepoRule sampleRepo2; + private GitSampleRepoRule sampleRepo3; - @Test public void smokes() throws Exception { - File clones = tmp.newFolder(); + /** + * Enables creation of multiple repos per test class. + */ + static class MultiGitSampleRepoExtension extends GitSampleRepoExtension { + private static final ExtensionContext.Namespace NAMESPACE = ExtensionContext.Namespace.create(MultiGitSampleRepoExtension.class); + private static final String KEY = "git-sample-repo-"; + private static int counter = 0; + + @Override + public void afterEach(ExtensionContext context) { + while (counter > 0) { + GitSampleRepoRule rule = context.getStore(NAMESPACE).remove(KEY + counter, GitSampleRepoRule.class); + if (rule != null) { + rule.after(); + } + counter--; + } + } + + @Override + public GitSampleRepoRule resolveParameter(ParameterContext parameterContext, ExtensionContext context) { + counter++; + GitSampleRepoRule rule = context.getStore(NAMESPACE).getOrComputeIfAbsent(KEY + counter, key -> new GitSampleRepoRule(), GitSampleRepoRule.class); + if (rule != null) { + try { + rule.before(); + } catch (Throwable t) { + throw new ParameterResolutionException(t.getMessage(), t); + } + } + return rule; + } + } + + @BeforeEach + void setUp(JenkinsRule rule, GitSampleRepoRule repo1, GitSampleRepoRule repo2, GitSampleRepoRule repo3) { + r = rule; + sampleRepo1 = repo1; + sampleRepo2 = repo2; + sampleRepo3 = repo3; + } + + @Test + void smokes() throws Exception { + File clones = newFolder(tmp, "junit"); sampleRepo1.init(); sampleRepo1.write(WorkflowBranchProjectFactory.SCRIPT, "echo 'ran one'"); sampleRepo1.git("add", WorkflowBranchProjectFactory.SCRIPT); @@ -125,10 +179,11 @@ public class WorkflowMultiBranchProjectFactoryTest { } @Issue("JENKINS-34561") - @Test public void configuredScriptName() throws Exception { + @Test + void configuredScriptName() throws Exception { String alternativeJenkinsFileName = "alternative_Jenkinsfile_name.groovy"; - File clones = tmp.newFolder(); + File clones = newFolder(tmp, "junit"); sampleRepo1.init(); sampleRepo1.write(WorkflowBranchProjectFactory.SCRIPT, "echo 'echo from " + WorkflowBranchProjectFactory.SCRIPT + "'"); @@ -187,4 +242,13 @@ public class WorkflowMultiBranchProjectFactoryTest { assertEquals(1, b1.getNumber()); r.assertLogContains("echo from alternative_Jenkinsfile_name", b1); } + + 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/multibranch/WorkflowMultiBranchProjectTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectTest.java index 86d2af83..164ec6f0 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectTest.java @@ -54,6 +54,7 @@ import jenkins.plugins.git.GitSCMSource; import jenkins.plugins.git.GitBranchSCMHead; import jenkins.plugins.git.GitSampleRepoRule; +import jenkins.plugins.git.junit.jupiter.WithGitSampleRepo; import jenkins.plugins.git.traits.BranchDiscoveryTrait; import jenkins.scm.api.SCMHead; import jenkins.scm.api.SCMSource; @@ -62,26 +63,33 @@ import static org.hamcrest.Matchers.*; import org.jenkinsci.plugins.workflow.job.WorkflowJob; import org.jenkinsci.plugins.workflow.job.WorkflowRun; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.Test; -import org.jvnet.hudson.test.BuildWatcher; +import static org.junit.jupiter.api.Assertions.*; + +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.TestExtension; +import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension; +import org.jvnet.hudson.test.junit.jupiter.WithJenkins; + +@WithJenkins +@WithGitSampleRepo +class WorkflowMultiBranchProjectTest { -public class WorkflowMultiBranchProjectTest { + @SuppressWarnings("unused") + private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension(); + private JenkinsRule r; + private GitSampleRepoRule sampleRepo; - @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher(); - @Rule public JenkinsRule r = new JenkinsRule(); - @Rule public GitSampleRepoRule sampleRepo = new GitSampleRepoRule(); + @BeforeEach + void setUp(JenkinsRule rule, GitSampleRepoRule repo) { + r = rule; + sampleRepo = repo; + } - @Test public void basicBranches() throws Exception { + @Test + void basicBranches() throws Exception { sampleRepo.init(); sampleRepo.write("Jenkinsfile", "echo \"branch=${env.BRANCH_NAME}\"; node {checkout scm; echo readFile('file')}"); sampleRepo.write("file", "initial content"); @@ -140,7 +148,8 @@ static void showIndexing(@NonNull WorkflowMultiBranchProject mp) throws Exceptio } @Issue({"JENKINS-32396", "JENKINS-32670"}) - @Test public void visibleBranchProperties() throws Exception { + @Test + void visibleBranchProperties() throws Exception { WorkflowMultiBranchProject p = r.jenkins.createProject(WorkflowMultiBranchProject.class, "p"); Set> propertyTypes = new HashSet<>(); for (BranchPropertyDescriptor d : DescriptorVisibilityFilter.apply(p, BranchPropertyDescriptor.all())) { @@ -162,7 +171,8 @@ static void showIndexing(@NonNull WorkflowMultiBranchProject mp) throws Exceptio } @SuppressWarnings("rawtypes") - @Test public void applicableSCMs() throws Exception { + @Test + void applicableSCMs() throws Exception { final WorkflowMultiBranchProject mp = r.jenkins.createProject(WorkflowMultiBranchProject.class, "p"); List scmTypes = new ArrayList<>(); List> scmDescriptors = SingleSCMSource.DescriptorImpl.getSCMDescriptors(mp); @@ -179,21 +189,26 @@ static void showIndexing(@NonNull WorkflowMultiBranchProject mp) throws Exceptio assertThat(html, not(containsString("OldSCM"))); */ } + public static class OldSCM extends SCM { - @Override public ChangeLogParser createChangeLogParser() {return null;} - @TestExtension("applicableSCMs") public static class DescriptorImpl extends SCMDescriptor { + @Override + public ChangeLogParser createChangeLogParser() {return null;} + @TestExtension("applicableSCMs") + public static class DescriptorImpl extends SCMDescriptor { public DescriptorImpl() { super(null); } @NonNull - @Override public String getDisplayName() { + @Override + public String getDisplayName() { return "OldSCM"; } } } @Issue("JENKINS-32179") - @Test public void conflictingBranches() throws Exception { + @Test + void conflictingBranches() throws Exception { sampleRepo.init(); sampleRepo.write("Jenkinsfile", ""); sampleRepo.git("add", "Jenkinsfile"); @@ -221,16 +236,20 @@ public DescriptorImpl() { // mp.getIndexing().writeWholeLogTo(System.out); // assertEquals("[p, p/master]", ExtensionList.lookup(Listener.class).get(0).names.toString()); } - @TestExtension("conflictingBranches") public static class Listener extends ItemListener { + + @TestExtension("conflictingBranches") + public static class Listener extends ItemListener { List names = new ArrayList<>(); - @Override public void onCreated(Item item) { + @Override + public void onCreated(Item item) { names.add(item.getFullName()); } } @Issue("JENKINS-34561") - @Test public void configuredScriptNameBranches() throws Exception { + @Test + void configuredScriptNameBranches() throws Exception { sampleRepo.init(); WorkflowMultiBranchProject mp = r.jenkins.createProject(WorkflowMultiBranchProject.class, "p"); @@ -275,7 +294,8 @@ public DescriptorImpl() { } @Issue("JENKINS-72613") - @Test public void reloadMangledName() throws Exception { + @Test + void reloadMangledName() throws Exception { r.jenkins.setQuietPeriod(0); sampleRepo.init(); sampleRepo.write("Jenkinsfile", "echo 'on master'"); From 365d87beb37827a19eee251f7a76b292fb019052 Mon Sep 17 00:00:00 2001 From: strangelookingnerd <49242855+strangelookingnerd@users.noreply.github.com> Date: Fri, 24 Oct 2025 21:25:39 +0200 Subject: [PATCH 2/4] Change class visibility to public --- .../multibranch/WorkflowMultiBranchProjectFactoryTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectFactoryTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectFactoryTest.java index f3d5779d..065cc0b6 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectFactoryTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectFactoryTest.java @@ -56,7 +56,7 @@ @WithJenkins @ExtendWith(WorkflowMultiBranchProjectFactoryTest.MultiGitSampleRepoExtension.class) -class WorkflowMultiBranchProjectFactoryTest { +public class WorkflowMultiBranchProjectFactoryTest { @SuppressWarnings("unused") private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension(); From f2fe8295c6899ee1108b9452b0a5d4a71887d63a Mon Sep 17 00:00:00 2001 From: strangelookingnerd <49242855+strangelookingnerd@users.noreply.github.com> Date: Fri, 24 Oct 2025 21:26:43 +0200 Subject: [PATCH 3/4] Revert --- .../multibranch/WorkflowMultiBranchProjectFactoryTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectFactoryTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectFactoryTest.java index 065cc0b6..f3d5779d 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectFactoryTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectFactoryTest.java @@ -56,7 +56,7 @@ @WithJenkins @ExtendWith(WorkflowMultiBranchProjectFactoryTest.MultiGitSampleRepoExtension.class) -public class WorkflowMultiBranchProjectFactoryTest { +class WorkflowMultiBranchProjectFactoryTest { @SuppressWarnings("unused") private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension(); From 187a21949e89d9b1c3d5cd2099eaa382957a4be7 Mon Sep 17 00:00:00 2001 From: strangelookingnerd <49242855+strangelookingnerd@users.noreply.github.com> Date: Fri, 24 Oct 2025 21:27:07 +0200 Subject: [PATCH 4/4] Change WorkflowMultiBranchProjectTest to public --- .../workflow/multibranch/WorkflowMultiBranchProjectTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectTest.java index 164ec6f0..d27f83eb 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectTest.java @@ -75,7 +75,7 @@ @WithJenkins @WithGitSampleRepo -class WorkflowMultiBranchProjectTest { +public class WorkflowMultiBranchProjectTest { @SuppressWarnings("unused") private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension();