diff --git a/pom.xml b/pom.xml index e5d6b2df4..ab13c2a44 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.jenkins-ci.plugins plugin - 5.18 + 5.27 docker-workflow @@ -35,6 +35,8 @@ ${jenkins.baseline}.3 true jenkinsci/${project.artifactId}-plugin + + true diff --git a/src/test/java/org/jenkinsci/plugins/docker/workflow/DockerDSLTest.java b/src/test/java/org/jenkinsci/plugins/docker/workflow/DockerDSLTest.java index fed2135a9..9629fd386 100644 --- a/src/test/java/org/jenkinsci/plugins/docker/workflow/DockerDSLTest.java +++ b/src/test/java/org/jenkinsci/plugins/docker/workflow/DockerDSLTest.java @@ -26,7 +26,6 @@ import hudson.EnvVars; import hudson.Launcher; import hudson.model.Result; -import hudson.tools.ToolProperty; import hudson.util.StreamTaskListener; import hudson.util.VersionNumber; import org.apache.commons.io.FileUtils; @@ -36,14 +35,12 @@ 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.runners.model.Statement; -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.JenkinsRule; -import org.jvnet.hudson.test.RestartableJenkinsRule; +import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension; +import org.jvnet.hudson.test.junit.jupiter.JenkinsSessionExtension; import java.io.File; import java.io.FileNotFoundException; @@ -60,37 +57,39 @@ import static org.hamcrest.core.StringRegularExpression.matchesRegex; import static org.jenkinsci.plugins.docker.workflow.DockerTestUtil.assumeDocker; import static org.jenkinsci.plugins.docker.workflow.DockerTestUtil.assumeNotWindows; -import static org.junit.Assert.assertEquals; -import static org.junit.Assume.assumeTrue; +import static org.junit.jupiter.api.Assumptions.assumeTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; -public class DockerDSLTest { +class DockerDSLTest { - @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher(); - @Rule public RestartableJenkinsRule story = new RestartableJenkinsRule(); + @SuppressWarnings("unused") + @RegisterExtension + private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension(); + @RegisterExtension + private final JenkinsSessionExtension story = new JenkinsSessionExtension(); - @Test public void firstDoNoHarm() { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + void firstDoNoHarm() throws Throwable { + story.then(r -> { assumeDocker(); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition("semaphore 'wait'", true)); WorkflowRun b = p.scheduleBuild2(0).waitForStart(); SemaphoreStep.waitForStart("wait/1", b); } - }); - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { - WorkflowJob p = story.j.jenkins.getItemByFullName("prj", WorkflowJob.class); + ); + story.then(r -> { + WorkflowJob p = r.jenkins.getItemByFullName("prj", WorkflowJob.class); WorkflowRun b = p.getLastBuild(); assertEquals(Collections.emptySet(), grep(b.getRootDir(), "org.jenkinsci.plugins.docker.workflow.Docker")); SemaphoreStep.success("wait/1", null); - story.j.assertBuildStatusSuccess(story.j.waitForCompletion(b)); + r.assertBuildStatusSuccess(r.waitForCompletion(b)); } - }); + ); } // TODO copied from BindingStepTest, should be made into a utility in Jenkins test harness perhaps (or JenkinsRuleExt as a first step) private static Set grep(File dir, String text) throws IOException { - Set matches = new TreeSet(); + Set matches = new TreeSet<>(); grep(dir, text, "", matches); return matches; } @@ -116,343 +115,348 @@ private static void grep(File dir, String text, String prefix, Set match } - @Test public void inside() { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + void inside() throws Throwable { + story.then(r -> { assumeDocker(); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( - "def r = docker.image('httpd:2.4.62').inside {\n" + - " semaphore 'wait'\n" + - " sh 'cat /usr/local/apache2/conf/extra/httpd-userdir.conf'\n" + - " 42\n" + - "}; echo \"the answer is ${r}\"", true)); + """ + def r = docker.image('httpd:2.4.62').inside { + semaphore 'wait' + sh 'cat /usr/local/apache2/conf/extra/httpd-userdir.conf' + 42 + }; echo "the answer is ${r}\"""", true)); WorkflowRun b = p.scheduleBuild2(0).waitForStart(); SemaphoreStep.waitForStart("wait/1", b); } - }); - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + ); + story.then(r -> { SemaphoreStep.success("wait/1", null); - WorkflowJob p = story.j.jenkins.getItemByFullName("prj", WorkflowJob.class); + WorkflowJob p = r.jenkins.getItemByFullName("prj", WorkflowJob.class); WorkflowRun b = p.getLastBuild(); - story.j.assertLogContains("Require method GET POST OPTIONS", story.j.assertBuildStatusSuccess(story.j.waitForCompletion(b))); - story.j.assertLogContains("the answer is 42", b); + r.assertLogContains("Require method GET POST OPTIONS", r.assertBuildStatusSuccess(r.waitForCompletion(b))); + r.assertLogContains("the answer is 42", b); } - }); + ); } @Issue("JENKINS-37987") - @Test public void entrypoint() { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + void entrypoint() throws Throwable { + story.then(r -> { assumeDocker(); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "p"); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "docker.image('maven:3.9.9-eclipse-temurin-17').inside {\n" + - " sh 'mvn -version'\n" + - "}", true)); + """ + docker.image('maven:3.9.9-eclipse-temurin-17').inside { + sh 'mvn -version' + }""", true)); - story.j.assertBuildStatusSuccess(p.scheduleBuild2(0)); + r.assertBuildStatusSuccess(p.scheduleBuild2(0)); } - }); + ); } - @Test public void endpoints() { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + void endpoints() throws Throwable { + story.then(r -> { assumeNotWindows(); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( - "docker.withServer('tcp://host:1234') {\n" + - " docker.withRegistry('https://docker.my.com/') {\n" + - " semaphore 'wait'\n" + - " sh 'echo would be connecting to $DOCKER_HOST'\n" + - " echo \"image name is ${docker.image('whatever').imageName()}\"\n" + - " }\n" + - "}", true)); + """ + docker.withServer('tcp://host:1234') { + docker.withRegistry('https://docker.my.com/') { + semaphore 'wait' + sh 'echo would be connecting to $DOCKER_HOST' + echo "image name is ${docker.image('whatever').imageName()}" + } + }""", true)); WorkflowRun b = p.scheduleBuild2(0).waitForStart(); SemaphoreStep.waitForStart("wait/1", b); } - }); - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + ); + story.then(r -> { SemaphoreStep.success("wait/1", null); - WorkflowJob p = story.j.jenkins.getItemByFullName("prj", WorkflowJob.class); - WorkflowRun b = story.j.assertBuildStatusSuccess(story.j.waitForCompletion(p.getLastBuild())); - story.j.assertLogContains("would be connecting to tcp://host:1234", b); - story.j.assertLogContains("image name is docker.my.com/whatever", b); + WorkflowJob p = r.jenkins.getItemByFullName("prj", WorkflowJob.class); + WorkflowRun b = r.assertBuildStatusSuccess(r.waitForCompletion(p.getLastBuild())); + r.assertLogContains("would be connecting to tcp://host:1234", b); + r.assertLogContains("image name is docker.my.com/whatever", b); } - }); + ); } - @Test public void runArgs() { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + void runArgs() throws Throwable { + story.then(r -> { assumeDocker(); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( - "node {\n" + - " def img = docker.image('httpd:2.4.62')\n" + - " img.run().stop()\n" + - " img.run('--memory-swap=-1').stop()\n" + - " img.withRun {}\n" + - " img.withRun('--memory-swap=-1') {}\n" + - " img.inside {}\n" + - " img.inside('--memory-swap=-1') {}\n" + - "}", true)); - story.j.assertBuildStatusSuccess(p.scheduleBuild2(0)); + """ + node { + def img = docker.image('httpd:2.4.62') + img.run().stop() + img.run('--memory-swap=-1').stop() + img.withRun {} + img.withRun('--memory-swap=-1') {} + img.inside {} + img.inside('--memory-swap=-1') {} + }""", true)); + r.assertBuildStatusSuccess(p.scheduleBuild2(0)); } - }); + ); } - @Test public void withRun() { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + void withRun() throws Throwable { + story.then(r -> { assumeDocker(); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( - "def r = docker.image('httpd:2.4.62').withRun {c ->\n" + - " semaphore 'wait'\n" + - " sh \"docker exec ${c.id} cat /usr/local/apache2/conf/extra/httpd-userdir.conf\"\n" + - " 42\n" + - "}; echo \"the answer is ${r}\"", true)); + """ + def r = docker.image('httpd:2.4.62').withRun {c -> + semaphore 'wait' + sh "docker exec ${c.id} cat /usr/local/apache2/conf/extra/httpd-userdir.conf" + 42 + }; echo "the answer is ${r}\"""", true)); WorkflowRun b = p.scheduleBuild2(0).waitForStart(); SemaphoreStep.waitForStart("wait/1", b); } - }); - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + ); + story.then(r -> { SemaphoreStep.success("wait/1", null); - WorkflowJob p = story.j.jenkins.getItemByFullName("prj", WorkflowJob.class); + WorkflowJob p = r.jenkins.getItemByFullName("prj", WorkflowJob.class); WorkflowRun b = p.getLastBuild(); - story.j.assertLogContains("Require method GET POST OPTIONS", story.j.assertBuildStatusSuccess(story.j.waitForCompletion(b))); - story.j.assertLogContains("the answer is 42", b); + r.assertLogContains("Require method GET POST OPTIONS", r.assertBuildStatusSuccess(r.waitForCompletion(b))); + r.assertLogContains("the answer is 42", b); } - }); + ); } - @Test public void withRunCommand() { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + void withRunCommand() throws Throwable { + story.then(r -> { assumeDocker(); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( " docker.image('maven:3.9.9-eclipse-temurin-17').withRun(\"--entrypoint mvn\", \"-version\") {c ->\n" + " sh \"docker logs ${c.id}\"" + "}", true)); - story.j.assertBuildStatusSuccess(p.scheduleBuild2(0)); + r.assertBuildStatusSuccess(p.scheduleBuild2(0)); } - }); + ); } - @Test public void build() { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + void build() throws Throwable { + story.then(r -> { assumeDocker(); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( - "node {\n" + - " writeFile file: 'stuff1', text: 'hello'\n" + - " writeFile file: 'stuff2', text: 'world'\n" + - " writeFile file: 'stuff3', text: env.BUILD_NUMBER\n" + - " writeFile file: 'Dockerfile', text: '# This is a test.\\n\\nFROM hello-world\\nCOPY stuff1 /\\nCOPY stuff2 /\\nCOPY stuff3 /\\n'\n" + - " def built = docker.build 'hello-world-stuff'\n" + - " echo \"built ${built.id}\"\n" + - "}", true)); - WorkflowRun b = story.j.assertBuildStatusSuccess(p.scheduleBuild2(0)); + """ + node { + writeFile file: 'stuff1', text: 'hello' + writeFile file: 'stuff2', text: 'world' + writeFile file: 'stuff3', text: env.BUILD_NUMBER + writeFile file: 'Dockerfile', text: '# This is a test.\\n\\nFROM hello-world\\nCOPY stuff1 /\\nCOPY stuff2 /\\nCOPY stuff3 /\\n' + def built = docker.build 'hello-world-stuff' + echo "built ${built.id}" + }""", true)); + WorkflowRun b = r.assertBuildStatusSuccess(p.scheduleBuild2(0)); DockerClient client = new DockerClient(new Launcher.LocalLauncher(StreamTaskListener.NULL), null, null); String descendantImageId1 = client.inspect(new EnvVars(), "hello-world-stuff", ".Id"); - story.j.assertLogContains("built hello-world-stuff", b); - story.j.assertLogContains(descendantImageId1.replaceFirst("^sha256:", "").substring(0, 12), b); + r.assertLogContains("built hello-world-stuff", b); + r.assertLogContains(descendantImageId1.replaceFirst("^sha256:", "").substring(0, 12), b); - b = story.j.assertBuildStatusSuccess(p.scheduleBuild2(0)); + b = r.assertBuildStatusSuccess(p.scheduleBuild2(0)); String descendantImageId2 = client.inspect(new EnvVars(), "hello-world-stuff", ".Id"); - story.j.assertLogContains("built hello-world-stuff", b); - story.j.assertLogContains(descendantImageId2.replaceFirst("^sha256:", "").substring(0, 12), b); + r.assertLogContains("built hello-world-stuff", b); + r.assertLogContains(descendantImageId2.replaceFirst("^sha256:", "").substring(0, 12), b); } - }); + ); } - @Test public void buildWithMultiStage() { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + void buildWithMultiStage() throws Throwable { + story.then(r -> { assumeDocker(DockerTestUtil.DockerOsMode.LINUX, new VersionNumber("17.05")); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( - "node {\n" + - " sh 'mkdir -p child'\n" + - " writeFile file: 'child/stuff1', text: 'hello'\n" + - " writeFile file: 'child/stuff2', text: 'world'\n" + - " writeFile file: 'child/stuff3', text: env.BUILD_NUMBER\n" + - " writeFile file: 'child/Dockerfile.other', " + - "text: '# This is a test.\\n" + - "\\n" + - "FROM hello-world AS one\\n" + - "ARG stuff4=4\\n" + - "ARG stuff5=5\\n" + - "COPY stuff1 /\\n" + - "FROM scratch\\n" + - "COPY --from=one /stuff1 /\\n" + - "COPY stuff2 /\\nCOPY stuff3 /\\n'\n" + - " def built = docker.build 'hello-world-stuff-arguments', '-f child/Dockerfile.other --build-arg stuff4=build4 --build-arg stuff5=build5 child'\n" + - " echo \"built ${built.id}\"\n" + - "}", true)); + """ + node { + sh 'mkdir -p child' + writeFile file: 'child/stuff1', text: 'hello' + writeFile file: 'child/stuff2', text: 'world' + writeFile file: 'child/stuff3', text: env.BUILD_NUMBER + writeFile file: 'child/Dockerfile.other', \ + text: '# This is a test.\\n\\nFROM hello-world AS one\\nARG stuff4=4\\nARG stuff5=5\\nCOPY stuff1 /\\nFROM scratch\\nCOPY --from=one /stuff1 /\\nCOPY stuff2 /\\nCOPY stuff3 /\\n' + def built = docker.build 'hello-world-stuff-arguments', '-f child/Dockerfile.other --build-arg stuff4=build4 --build-arg stuff5=build5 child' + echo "built ${built.id}" + }""", true)); // Note the absence '--pull' in the above docker build ags as compared to other tests. // This is due to a Docker bug: https://github.com/docker/for-mac/issues/1751 // It can be re-added when that is fixed - WorkflowRun b = story.j.assertBuildStatusSuccess(p.scheduleBuild2(0)); + WorkflowRun b = r.assertBuildStatusSuccess(p.scheduleBuild2(0)); DockerClient client = new DockerClient(new Launcher.LocalLauncher(StreamTaskListener.NULL), null, null); String descendantImageId1 = client.inspect(new EnvVars(), "hello-world-stuff-arguments", ".Id"); - story.j.assertLogContains("built hello-world-stuff-arguments", b); - story.j.assertLogNotContains(" --no-cache ", b); - story.j.assertLogContains(descendantImageId1.replaceFirst("^sha256:", "").substring(0, 12), b); - story.j.assertLogContains(" --build-arg stuff4=build4 ", b); - story.j.assertLogContains(" --build-arg stuff5=build5 ", b); + r.assertLogContains("built hello-world-stuff-arguments", b); + r.assertLogNotContains(" --no-cache ", b); + r.assertLogContains(descendantImageId1.replaceFirst("^sha256:", "").substring(0, 12), b); + r.assertLogContains(" --build-arg stuff4=build4 ", b); + r.assertLogContains(" --build-arg stuff5=build5 ", b); } - }); + ); } - @Test public void buildArguments() { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + void buildArguments() throws Throwable { + story.then(r -> { assumeDocker(); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( - "node {\n" + - " sh 'mkdir -p child'\n" + - " writeFile file: 'child/stuff1', text: 'hello'\n" + - " writeFile file: 'child/stuff2', text: 'world'\n" + - " writeFile file: 'child/stuff3', text: env.BUILD_NUMBER\n" + - " writeFile file: 'child/Dockerfile.other', text: '# This is a test.\\n\\nFROM hello-world\\nARG stuff4=4\\nARG stuff5=5\\nCOPY stuff1 /\\nCOPY stuff2 /\\nCOPY stuff3 /\\n'\n" + - " def built = docker.build 'hello-world-stuff-arguments', '-f child/Dockerfile.other --pull --build-arg stuff4=build4 --build-arg stuff5=build5 child'\n" + - " echo \"built ${built.id}\"\n" + - "}", true)); + """ + node { + sh 'mkdir -p child' + writeFile file: 'child/stuff1', text: 'hello' + writeFile file: 'child/stuff2', text: 'world' + writeFile file: 'child/stuff3', text: env.BUILD_NUMBER + writeFile file: 'child/Dockerfile.other', text: '# This is a test.\\n\\nFROM hello-world\\nARG stuff4=4\\nARG stuff5=5\\nCOPY stuff1 /\\nCOPY stuff2 /\\nCOPY stuff3 /\\n' + def built = docker.build 'hello-world-stuff-arguments', '-f child/Dockerfile.other --pull --build-arg stuff4=build4 --build-arg stuff5=build5 child' + echo "built ${built.id}" + }""", true)); - WorkflowRun b = story.j.assertBuildStatusSuccess(p.scheduleBuild2(0)); + WorkflowRun b = r.assertBuildStatusSuccess(p.scheduleBuild2(0)); DockerClient client = new DockerClient(new Launcher.LocalLauncher(StreamTaskListener.NULL), null, null); String descendantImageId1 = client.inspect(new EnvVars(), "hello-world-stuff-arguments", ".Id"); - story.j.assertLogContains("built hello-world-stuff-arguments", b); - story.j.assertLogContains(" --pull ", b); - story.j.assertLogNotContains(" --no-cache ", b); - story.j.assertLogContains(descendantImageId1.replaceFirst("^sha256:", "").substring(0, 12), b); - story.j.assertLogContains(" --build-arg stuff4=build4 ", b); - story.j.assertLogContains(" --build-arg stuff5=build5 ", b); + r.assertLogContains("built hello-world-stuff-arguments", b); + r.assertLogContains(" --pull ", b); + r.assertLogNotContains(" --no-cache ", b); + r.assertLogContains(descendantImageId1.replaceFirst("^sha256:", "").substring(0, 12), b); + r.assertLogContains(" --build-arg stuff4=build4 ", b); + r.assertLogContains(" --build-arg stuff5=build5 ", b); } - }); + ); } - @Test public void withTool() { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + void withTool() throws Throwable { + story.then(r -> { assumeDocker(); assumeTrue(new File("/usr/bin/docker").canExecute()); // TODO generalize to find docker in $PATH - story.j.jenkins.getDescriptorByType(DockerTool.DescriptorImpl.class).setInstallations(new DockerTool("default", "/usr", Collections.>emptyList())); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + r.jenkins.getDescriptorByType(DockerTool.DescriptorImpl.class).setInstallations(new DockerTool("default", "/usr", Collections.emptyList())); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( - "docker.withTool('default') {\n" + - " docker.image('httpd:2.4.62').withRun {}\n" + - " sh 'echo PATH=$PATH'\n" + - "}", true)); - story.j.assertLogContains("PATH=/usr/bin:", story.j.assertBuildStatusSuccess(p.scheduleBuild2(0))); + """ + docker.withTool('default') { + docker.image('httpd:2.4.62').withRun {} + sh 'echo PATH=$PATH' + }""", true)); + r.assertLogContains("PATH=/usr/bin:", r.assertBuildStatusSuccess(p.scheduleBuild2(0))); } - }); + ); } - @Test public void tag() { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + void tag() throws Throwable { + story.then(r -> { assumeDocker(); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( - "node {\n" + - " try { sh 'docker rmi busybox:test' } catch (Exception e) {}\n" + - " def busybox = docker.image('busybox');\n" + - " busybox.pull();\n" + - " // tag it\n" + - " busybox.tag('test', /* ignored but to test that the argument is accepted */false);\n" + - " // retag it\n" + - " busybox.tag('test');\n" + - "}", true)); - WorkflowRun b = story.j.assertBuildStatusSuccess(p.scheduleBuild2(0)); + """ + node { + try { sh 'docker rmi busybox:test' } catch (Exception e) {} + def busybox = docker.image('busybox'); + busybox.pull(); + // tag it + busybox.tag('test', /* ignored but to test that the argument is accepted */false); + // retag it + busybox.tag('test'); + }""", true)); + WorkflowRun b = r.assertBuildStatusSuccess(p.scheduleBuild2(0)); } - }); + ); } - @Test @Issue("SECURITY-1878") public void tagInjection() { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + @Issue("SECURITY-1878") + void tagInjection() throws Throwable { + story.then(r -> { assumeDocker(); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( - "node {\n" + - " try { sh 'docker rmi busybox:test' } catch (Exception e) {}\n" + - " def busybox = docker.image('busybox');\n" + - " busybox.pull();\n" + - " // tag it\n" + - " busybox.tag(\"test\\necho haxored\", false);\n" + - "}", true)); - WorkflowRun b = story.j.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0)); + """ + node { + try { sh 'docker rmi busybox:test' } catch (Exception e) {} + def busybox = docker.image('busybox'); + busybox.pull(); + // tag it + busybox.tag("test\\necho haxored", false); + }""", true)); + WorkflowRun b = r.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0)); final String log = JenkinsRule.getLog(b); assertThat(log, not(matchesRegex("^haxored"))); assertThat(log, containsString("ERROR: Tag must follow the pattern")); } - }); + ); } - @Test @Issue("JENKINS-57366") public void imageInjectionOr() { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + @Issue("JENKINS-57366") + void imageInjectionOr() throws Throwable { + story.then(r -> { assumeDocker(); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( - "node {\n" + - " try { sh 'docker rmi busybox:test' } catch (Exception e) {}\n" + - " def busybox = docker.image('busybox|echo haxored');\n" + - " busybox.pull();\n" + - "}", true)); - WorkflowRun b = story.j.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0)); + """ + node { + try { sh 'docker rmi busybox:test' } catch (Exception e) {} + def busybox = docker.image('busybox|echo haxored'); + busybox.pull(); + }""", true)); + WorkflowRun b = r.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0)); final String log = JenkinsRule.getLog(b); assertThat(log, not(matchesRegex("^haxored"))); assertThat(log, containsString("ERROR: Name must follow the pattern")); } - }); + ); } - @Test public void run() { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + void run() throws Throwable { + story.then(r -> { assumeDocker(); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( - "node {\n" + - " def busybox = docker.image('busybox');\n" + - " busybox.run('--tty', 'echo \"Hello\"').stop();\n" + - "}", true)); - WorkflowRun b = story.j.assertBuildStatusSuccess(p.scheduleBuild2(0)); - story.j.assertLogContains("Hello", b); + """ + node { + def busybox = docker.image('busybox'); + busybox.run('--tty', 'echo "Hello"').stop(); + }""", true)); + WorkflowRun b = r.assertBuildStatusSuccess(p.scheduleBuild2(0)); + r.assertLogContains("Hello", b); } - }); + ); } - @Test public void port(){ - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + void port() throws Throwable { + story.then(r -> { assumeDocker(); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( - "node {\n" + - " def img = docker.image('httpd:2.4.62')\n" + - " def port = img.withRun('-p 12345:80') { c -> c.port(80) }\n" + - " echo \"container running on ${port}\"" + - "}", true)); - WorkflowRun r = story.j.assertBuildStatusSuccess(p.scheduleBuild2(0)); - story.j.assertLogContains("container running on 0.0.0.0:12345", r); + """ + node { + def img = docker.image('httpd:2.4.62') + def port = img.withRun('-p 12345:80') { c -> c.port(80) } + echo "container running on ${port}"\ + }""", true)); + WorkflowRun run = r.assertBuildStatusSuccess(p.scheduleBuild2(0)); + r.assertLogContains("container running on 0.0.0.0:12345", run); } - }); + ); } } diff --git a/src/test/java/org/jenkinsci/plugins/docker/workflow/DockerTestUtil.java b/src/test/java/org/jenkinsci/plugins/docker/workflow/DockerTestUtil.java index 0469cd727..b65aef97a 100644 --- a/src/test/java/org/jenkinsci/plugins/docker/workflow/DockerTestUtil.java +++ b/src/test/java/org/jenkinsci/plugins/docker/workflow/DockerTestUtil.java @@ -28,9 +28,9 @@ import hudson.Launcher; import hudson.util.StreamTaskListener; import hudson.util.VersionNumber; -import org.junit.Assume; import java.io.ByteArrayOutputStream; + import java.io.File; import java.io.IOException; import java.util.Arrays; @@ -41,15 +41,21 @@ import java.util.regex.Pattern; import org.jenkinsci.plugins.docker.commons.tools.DockerTool; +import org.junit.AssumptionViolatedException; +import org.opentest4j.TestAbortedException; + +import static org.junit.jupiter.api.Assumptions.assumeFalse; +import static org.junit.jupiter.api.Assumptions.assumeTrue; /** * @author tom.fennelly@gmail.com */ public class DockerTestUtil { - public static String DEFAULT_MINIMUM_VERSION = "1.3"; + + public static final String DEFAULT_MINIMUM_VERSION = "1.3"; // Major Windows kernel versions. See https://hub.docker.com/r/microsoft/windows-nanoserver - private static List MAJOR_WINDOWS_KERNEL_VERSIONS = Arrays.asList( + private static final List MAJOR_WINDOWS_KERNEL_VERSIONS = Arrays.asList( "10.0.17763.6659", // 1809 "10.0.18363.1556", // 1909 "10.0.19041.1415", // 2004 @@ -63,6 +69,14 @@ public enum DockerOsMode { WINDOWS } + public static void assumeDockerJUnit4() throws Exception { + try { + assumeDocker(); + } catch (TestAbortedException ex) { + throw new AssumptionViolatedException(ex.getMessage()); + } + } + public static void assumeDocker() throws Exception { assumeDocker(DockerOsMode.LINUX, new VersionNumber(DEFAULT_MINIMUM_VERSION)); } @@ -79,7 +93,7 @@ public static void assumeDocker(DockerOsMode osMode, VersionNumber minimumVersio .cmds(DockerTool.getExecutable(null, null, null, null), "ps") .start() .joinWithTimeout(DockerClient.CLIENT_TIMEOUT, TimeUnit.SECONDS, localLauncher.getListener()); - Assume.assumeTrue("Docker working", status == 0); + assumeTrue(status == 0, "Docker working"); ByteArrayOutputStream out = new ByteArrayOutputStream(); status = localLauncher .launch() @@ -88,25 +102,25 @@ public static void assumeDocker(DockerOsMode osMode, VersionNumber minimumVersio .start() .joinWithTimeout(DockerClient.CLIENT_TIMEOUT, TimeUnit.SECONDS, localLauncher.getListener()); DockerOsMode cmdOsMode = DockerOsMode.valueOf(out.toString().trim().toUpperCase()); - Assume.assumeTrue("Docker working", status == 0); - Assume.assumeTrue("Docker os mode " + osMode, osMode == cmdOsMode); + assumeTrue(status == 0, "Docker working"); + assumeTrue(osMode == cmdOsMode, "Docker os mode " + osMode); } catch (IOException x) { - Assume.assumeNoException("have Docker installed", x); + assumeTrue(false, "have Docker installed: " + x); } DockerClient dockerClient = new DockerClient(localLauncher, null, null); - Assume.assumeFalse("Docker version not < " + minimumVersion.toString(), dockerClient.version().isOlderThan(minimumVersion)); + assumeFalse(dockerClient.version().isOlderThan(minimumVersion), "Docker version not < " + minimumVersion.toString()); } - public static void assumeWindows() throws Exception { - Assume.assumeTrue(System.getProperty("os.name").toLowerCase().contains("windows")); + public static void assumeWindows() { + assumeTrue(System.getProperty("os.name").toLowerCase().contains("windows")); } - public static void assumeNotWindows() throws Exception { - Assume.assumeFalse(System.getProperty("os.name").toLowerCase().contains("windows")); + public static void assumeNotWindows() { + assumeFalse(System.getProperty("os.name").toLowerCase().contains("windows")); } - public static void assumeDrive(char drive) throws Exception { - Assume.assumeTrue(new File(drive + ":/").exists()); + public static void assumeDrive(char drive) { + assumeTrue(new File(drive + ":/").exists()); } public static String getWindowsKernelVersion() throws Exception { diff --git a/src/test/java/org/jenkinsci/plugins/docker/workflow/DockerUtilsTest.java b/src/test/java/org/jenkinsci/plugins/docker/workflow/DockerUtilsTest.java index abfb40683..eabaaa8d7 100644 --- a/src/test/java/org/jenkinsci/plugins/docker/workflow/DockerUtilsTest.java +++ b/src/test/java/org/jenkinsci/plugins/docker/workflow/DockerUtilsTest.java @@ -24,23 +24,23 @@ package org.jenkinsci.plugins.docker.workflow; import hudson.FilePath; -import org.hamcrest.collection.IsCollectionWithSize; -import org.hamcrest.core.IsCollectionContaining; import org.hamcrest.core.IsEqual; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; +import org.junit.jupiter.api.Test; import java.io.File; import java.io.IOException; import java.util.Map; -public class DockerUtilsTest { +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasItems; +import static org.hamcrest.Matchers.hasSize; +import static org.junit.jupiter.api.Assertions.assertThrows; - @Rule public final ExpectedException exception = ExpectedException.none(); +class DockerUtilsTest { - @Test public void parseBuildArgs() throws IOException, InterruptedException { + @Test + void parseBuildArgs() throws Exception { FilePath dockerfilePath = new FilePath(new File("src/test/resources/Dockerfile-withArgs")); Dockerfile dockerfile = new Dockerfile(dockerfilePath); @@ -50,12 +50,13 @@ public class DockerUtilsTest { final String commandLine = "docker build -t hello-world --build-arg "+key+"="+imageToUpdate; Map buildArgs = DockerUtils.parseBuildArgs(dockerfile, commandLine); - Assert.assertThat(buildArgs.keySet(), IsCollectionWithSize.hasSize(1)); - Assert.assertThat(buildArgs.keySet(), IsCollectionContaining.hasItems(key)); - Assert.assertThat(buildArgs.get(key), IsEqual.equalTo(imageToUpdate)); + assertThat(buildArgs.keySet(), hasSize(1)); + assertThat(buildArgs.keySet(), hasItems(key)); + assertThat(buildArgs.get(key), equalTo(imageToUpdate)); } - @Test public void parseBuildArgsWithDefaults() throws IOException, InterruptedException { + @Test + void parseBuildArgsWithDefaults() throws Exception { Dockerfile dockerfile = getDockerfileDefaultArgs(); @@ -65,13 +66,14 @@ public class DockerUtilsTest { final String commandLine = "docker build -t hello-world"; Map buildArgs = DockerUtils.parseBuildArgs(dockerfile, commandLine); - Assert.assertThat(buildArgs.keySet(), IsCollectionWithSize.hasSize(2)); - Assert.assertThat(buildArgs.keySet(), IsCollectionContaining.hasItems(key_registry, key_tag)); - Assert.assertThat(buildArgs.get(key_registry), IsEqual.equalTo(registry)); - Assert.assertThat(buildArgs.get(key_tag), IsEqual.equalTo("latest")); + assertThat(buildArgs.keySet(), hasSize(2)); + assertThat(buildArgs.keySet(), hasItems(key_registry, key_tag)); + assertThat(buildArgs.get(key_registry), equalTo(registry)); + assertThat(buildArgs.get(key_tag), equalTo("latest")); } - @Test public void parseBuildArgsOverridingDefaults() throws IOException, InterruptedException { + @Test + void parseBuildArgsOverridingDefaults() throws Exception { Dockerfile dockerfile = getDockerfileDefaultArgs(); @@ -83,37 +85,40 @@ public class DockerUtilsTest { " --build-arg "+key_registry+"="+registry; Map buildArgs = DockerUtils.parseBuildArgs(dockerfile, commandLine); - Assert.assertThat(buildArgs.keySet(), IsCollectionWithSize.hasSize(2)); - Assert.assertThat(buildArgs.keySet(), IsCollectionContaining.hasItems(key_registry, key_tag)); - Assert.assertThat(buildArgs.get(key_registry), IsEqual.equalTo(registry)); - Assert.assertThat(buildArgs.get(key_tag), IsEqual.equalTo(tag)); + assertThat(buildArgs.keySet(), hasSize(2)); + assertThat(buildArgs.keySet(), hasItems(key_registry, key_tag)); + assertThat(buildArgs.get(key_registry), equalTo(registry)); + assertThat(buildArgs.get(key_tag), IsEqual.equalTo(tag)); } - @Test public void parseBuildArgWithKeyAndEqual() throws IOException, InterruptedException { + @Test + void parseBuildArgWithKeyAndEqual() { final String commandLine = "docker build -t hello-world --build-arg key="; Map buildArgs = DockerUtils.parseBuildArgs(null, commandLine); - Assert.assertThat(buildArgs.keySet(), IsCollectionWithSize.hasSize(1)); - Assert.assertThat(buildArgs.keySet(), IsCollectionContaining.hasItems("key")); - Assert.assertThat(buildArgs.get("key"), IsEqual.equalTo("")); + assertThat(buildArgs.keySet(), hasSize(1)); + assertThat(buildArgs.keySet(), hasItems("key")); + assertThat(buildArgs.get("key"), equalTo("")); } - @Test public void parseInvalidBuildArg() throws IOException, InterruptedException { + @Test + void parseInvalidBuildArg() { final String commandLine = "docker build -t hello-world --build-arg"; - exception.expect(IllegalArgumentException.class); - DockerUtils.parseBuildArgs(null, commandLine); + assertThrows(IllegalArgumentException.class, () -> + DockerUtils.parseBuildArgs(null, commandLine)); } - @Test public void parseInvalidBuildArgWithKeyOnly() throws IOException, InterruptedException { + @Test + void parseInvalidBuildArgWithKeyOnly() { final String commandLine = "docker build -t hello-world --build-arg key"; - exception.expect(IllegalArgumentException.class); - DockerUtils.parseBuildArgs(null, commandLine); + assertThrows(IllegalArgumentException.class, () -> + DockerUtils.parseBuildArgs(null, commandLine)); } - private Dockerfile getDockerfileDefaultArgs() throws IOException, InterruptedException { + private Dockerfile getDockerfileDefaultArgs() throws Exception { FilePath dockerfilePath = new FilePath(new File("src/test/resources/Dockerfile-defaultArgs")); return new Dockerfile(dockerfilePath); } diff --git a/src/test/java/org/jenkinsci/plugins/docker/workflow/DockerfileTest.java b/src/test/java/org/jenkinsci/plugins/docker/workflow/DockerfileTest.java index 74c2fd241..90fea8144 100644 --- a/src/test/java/org/jenkinsci/plugins/docker/workflow/DockerfileTest.java +++ b/src/test/java/org/jenkinsci/plugins/docker/workflow/DockerfileTest.java @@ -24,30 +24,33 @@ package org.jenkinsci.plugins.docker.workflow; import hudson.FilePath; -import org.hamcrest.collection.IsCollectionWithSize; -import org.hamcrest.core.IsCollectionContaining; -import org.hamcrest.core.IsEqual; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import java.io.File; import java.io.IOException; -public class DockerfileTest { +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasItems; +import static org.hamcrest.Matchers.hasSize; + +class DockerfileTest { private FilePath dockerfilePath; - @Before public void setUp() { + @BeforeEach + void setUp() { dockerfilePath = new FilePath(new File("src/test/resources/Dockerfile-defaultArgs")); } - @Test public void parseDockerfile() throws IOException, InterruptedException { + @Test + void parseDockerfile() throws Exception { Dockerfile dockerfile = new Dockerfile(dockerfilePath); - Assert.assertThat(dockerfile.getFroms(), IsCollectionWithSize.hasSize(1)); - Assert.assertThat(dockerfile.getFroms().getLast(), IsEqual.equalTo("${REGISTRY_URL}hello-world:${TAG}")); - Assert.assertThat(dockerfile.getArgs().keySet(), IsCollectionWithSize.hasSize(2)); - Assert.assertThat(dockerfile.getArgs().keySet(), IsCollectionContaining.hasItems("REGISTRY_URL", "TAG")); + assertThat(dockerfile.getFroms(), hasSize(1)); + assertThat(dockerfile.getFroms().getLast(), equalTo("${REGISTRY_URL}hello-world:${TAG}")); + assertThat(dockerfile.getArgs().keySet(), hasSize(2)); + assertThat(dockerfile.getArgs().keySet(), hasItems("REGISTRY_URL", "TAG")); } } diff --git a/src/test/java/org/jenkinsci/plugins/docker/workflow/FromFingerprintStepTest.java b/src/test/java/org/jenkinsci/plugins/docker/workflow/FromFingerprintStepTest.java index df97eafcd..8419647fa 100644 --- a/src/test/java/org/jenkinsci/plugins/docker/workflow/FromFingerprintStepTest.java +++ b/src/test/java/org/jenkinsci/plugins/docker/workflow/FromFingerprintStepTest.java @@ -33,20 +33,22 @@ 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.runners.model.Statement; -import org.jvnet.hudson.test.RestartableJenkinsRule; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.jvnet.hudson.test.junit.jupiter.JenkinsSessionExtension; import static org.jenkinsci.plugins.docker.workflow.DockerTestUtil.assumeDocker; -import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotNull; -public class FromFingerprintStepTest { - @Rule public RestartableJenkinsRule story = new RestartableJenkinsRule(); +class FromFingerprintStepTest { + + @RegisterExtension + private final JenkinsSessionExtension story = new JenkinsSessionExtension(); private static final String BUSYBOX_IMAGE = "quay.io/prometheus/busybox:latest"; - @Test public void build() throws Exception { + @Test + void build() throws Throwable { String dockerFile = "" + "FROM "+ BUSYBOX_IMAGE +"\\n" + "RUN echo 1"; @@ -64,24 +66,22 @@ public class FromFingerprintStepTest { assertBuild("build", script, BUSYBOX_IMAGE); } - private void assertBuild(final String projectName, final String pipelineCode, final String fromImage) throws Exception { - story.addStep(new Statement() { - @Override - public void evaluate() throws Throwable { + private void assertBuild(final String projectName, final String pipelineCode, final String fromImage) throws Throwable { + story.then(r -> { assumeDocker(); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, projectName); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, projectName); p.setDefinition(new CpsFlowDefinition(pipelineCode, true)); - WorkflowRun b = story.j.assertBuildStatusSuccess(p.scheduleBuild2(0)); + WorkflowRun b = r.assertBuildStatusSuccess(p.scheduleBuild2(0)); DockerClient client = new DockerClient(new LocalLauncher(StreamTaskListener.NULL), null, null); String ancestorImageId = client.inspect(new EnvVars(), fromImage, ".Id"); - story.j.assertLogContains(ancestorImageId.replaceFirst("^sha256:", "").substring(0, 12), b); + r.assertLogContains(ancestorImageId.replaceFirst("^sha256:", "").substring(0, 12), b); Fingerprint f = DockerFingerprints.of(ancestorImageId); assertNotNull(f); DockerDescendantFingerprintFacet descendantFacet = f.getFacet(DockerDescendantFingerprintFacet.class); assertNotNull(descendantFacet); } - }); + ); } } diff --git a/src/test/java/org/jenkinsci/plugins/docker/workflow/ImageNameTokensTest.java b/src/test/java/org/jenkinsci/plugins/docker/workflow/ImageNameTokensTest.java index 48deadb00..0998dd435 100644 --- a/src/test/java/org/jenkinsci/plugins/docker/workflow/ImageNameTokensTest.java +++ b/src/test/java/org/jenkinsci/plugins/docker/workflow/ImageNameTokensTest.java @@ -23,45 +23,46 @@ */ package org.jenkinsci.plugins.docker.workflow; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; /** * @author tom.fennelly@gmail.com */ -public class ImageNameTokensTest { - +class ImageNameTokensTest { + @Test - public void test_no_tag() { + void test_no_tag() { ImageNameTokens name = new ImageNameTokens("busybox"); - Assert.assertEquals("busybox", name.userAndRepo); - Assert.assertEquals("latest", name.tag); + assertEquals("busybox", name.userAndRepo); + assertEquals("latest", name.tag); } - + @Test - public void test_empty_tag() { + void test_empty_tag() { ImageNameTokens name = new ImageNameTokens("busybox:"); - Assert.assertEquals("busybox", name.userAndRepo); - Assert.assertEquals("latest", name.tag); + assertEquals("busybox", name.userAndRepo); + assertEquals("latest", name.tag); } - + @Test - public void test_with_tag() { + void test_with_tag() { ImageNameTokens name = new ImageNameTokens("busybox:staging"); - Assert.assertEquals("busybox", name.userAndRepo); - Assert.assertEquals("staging", name.tag); + assertEquals("busybox", name.userAndRepo); + assertEquals("staging", name.tag); name = new ImageNameTokens("spring-petclinic:1"); - Assert.assertEquals("spring-petclinic", name.userAndRepo); - Assert.assertEquals("1", name.tag); + assertEquals("spring-petclinic", name.userAndRepo); + assertEquals("1", name.tag); name = new ImageNameTokens("examplecorp/spring-petclinic:1"); - Assert.assertEquals("examplecorp/spring-petclinic", name.userAndRepo); - Assert.assertEquals("1", name.tag); + assertEquals("examplecorp/spring-petclinic", name.userAndRepo); + assertEquals("1", name.tag); } } diff --git a/src/test/java/org/jenkinsci/plugins/docker/workflow/RegistryEndpointStepTest.java b/src/test/java/org/jenkinsci/plugins/docker/workflow/RegistryEndpointStepTest.java index f1928c976..0ce793b2a 100644 --- a/src/test/java/org/jenkinsci/plugins/docker/workflow/RegistryEndpointStepTest.java +++ b/src/test/java/org/jenkinsci/plugins/docker/workflow/RegistryEndpointStepTest.java @@ -53,17 +53,22 @@ import org.jenkinsci.plugins.workflow.steps.StepExecution; import static org.jenkinsci.plugins.docker.workflow.DockerTestUtil.assumeNotWindows; -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 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.LogRecorder; import org.jvnet.hudson.test.MockAuthorizationStrategy; import org.jvnet.hudson.test.MockQueueItemAuthenticator; import org.jvnet.hudson.test.TestExtension; +import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension; +import org.jvnet.hudson.test.junit.jupiter.JenkinsSessionExtension; import org.kohsuke.stapler.DataBoundConstructor; +import java.io.Serial; import java.io.Serializable; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -76,22 +81,22 @@ import org.jenkinsci.plugins.structs.describable.DescribableModel; import org.jenkinsci.plugins.workflow.support.pickles.FilePathPickle; import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep; -import org.junit.ClassRule; -import org.jvnet.hudson.test.BuildWatcher; -import org.jvnet.hudson.test.JenkinsSessionRule; -import org.jvnet.hudson.test.LoggerRule; import test.ssh_agent.OutboundAgent; public class RegistryEndpointStepTest { - @Rule public final JenkinsSessionRule rr = new JenkinsSessionRule(); - @Rule public LoggerRule logging = new LoggerRule(); - @ClassRule public static BuildWatcher bw = new BuildWatcher(); + @RegisterExtension + private final JenkinsSessionExtension story = new JenkinsSessionExtension(); + private final LogRecorder logging = new LogRecorder(); + @SuppressWarnings("unused") + @RegisterExtension + private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension(); @Issue("JENKINS-51395") - @Test public void configRoundTrip() throws Throwable { + @Test + void configRoundTrip() throws Throwable { logging.record(DescribableModel.class, Level.FINE); - rr.then(r -> { + story.then(r -> { { // Recommended syntax. SnippetizerTester st = new SnippetizerTester(r); RegistryEndpointStep step = new RegistryEndpointStep(new DockerRegistryEndpoint("https://myreg/", null)); @@ -131,21 +136,22 @@ public class RegistryEndpointStepTest { } @Test - public void stepExecutionWithCredentials() throws Throwable { + void stepExecutionWithCredentials() throws Throwable { assumeNotWindows(); - rr.then(r -> { + story.then(r -> { IdCredentials registryCredentials = new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, "registryCreds", null, "me", "s3cr3t"); CredentialsProvider.lookupStores(r.jenkins).iterator().next().addCredentials(Domain.global(), registryCredentials); WorkflowJob p = r.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( - "node {\n" + - " mockDockerLogin {\n" + - " withDockerRegistry(url: 'https://my-reg:1234', credentialsId: 'registryCreds') {\n" + - " }\n" + - " }\n" + - "}", true)); + """ + node { + mockDockerLogin { + withDockerRegistry(url: 'https://my-reg:1234', credentialsId: 'registryCreds') { + } + } + }""", true)); WorkflowRun b = r.buildAndAssertSuccess(p); r.assertBuildStatusSuccess(r.waitForCompletion(b)); r.assertLogContains("docker login -u me -p ******** https://my-reg:1234", b); @@ -154,10 +160,10 @@ public void stepExecutionWithCredentials() throws Throwable { } @Test - public void stepExecutionWithCredentialsAndQueueItemAuthenticator() throws Throwable { + void stepExecutionWithCredentialsAndQueueItemAuthenticator() throws Throwable { assumeNotWindows(); - rr.then(r -> { + story.then(r -> { r.getInstance().setSecurityRealm(r.createDummySecurityRealm()); MockAuthorizationStrategy auth = new MockAuthorizationStrategy() .grant(Jenkins.READ).everywhere().to("alice", "bob") @@ -170,12 +176,13 @@ public void stepExecutionWithCredentialsAndQueueItemAuthenticator() throws Throw IdCredentials registryCredentials = new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, "registryCreds", null, "me", "s3cr3t"); CredentialsProvider.lookupStores(r.jenkins).iterator().next().addCredentials(Domain.global(), registryCredentials); - String script = "node {\n" + - " mockDockerLogin {\n" + - " withDockerRegistry(url: 'https://my-reg:1234', credentialsId: 'registryCreds') {\n" + - " }\n" + - " }\n" + - "}"; + String script = """ + node { + mockDockerLogin { + withDockerRegistry(url: 'https://my-reg:1234', credentialsId: 'registryCreds') { + } + } + }"""; WorkflowJob p1 = r.createProject(WorkflowJob.class, "prj1"); p1.setDefinition(new CpsFlowDefinition(script, true)); WorkflowJob p2 = r.createProject(WorkflowJob.class, "prj2"); @@ -200,10 +207,11 @@ public void stepExecutionWithCredentialsAndQueueItemAuthenticator() throws Throw } @Issue("JENKINS-75679") - @Test public void noFilePathPickle() throws Throwable { + @Test + void noFilePathPickle() throws Throwable { try (var agent = new OutboundAgent()) { var connectionDetails = agent.start(); - rr.then(r -> { + story.then(r -> { OutboundAgent.createAgent(r, "remote", connectionDetails); var registryCredentials = new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, "registryCreds", null, "me", "s3cr3t"); CredentialsProvider.lookupStores(r.jenkins).iterator().next().addCredentials(Domain.global(), registryCredentials); @@ -223,8 +231,8 @@ public void stepExecutionWithCredentialsAndQueueItemAuthenticator() throws Throw }); @SuppressWarnings("deprecation") var verboten = FilePathPickle.class.getName(); - assertThat(StringEscapeUtils.escapeJava(Files.readString(rr.getHome().toPath().resolve("jobs/p/builds/1/program.dat"), StandardCharsets.ISO_8859_1)), not(containsString(verboten))); - rr.then(r -> { + assertThat(StringEscapeUtils.escapeJava(Files.readString(story.getHome().toPath().resolve("jobs/p/builds/1/program.dat"), StandardCharsets.ISO_8859_1)), not(containsString(verboten))); + story.then(r -> { var b = r.jenkins.getItemByFullName("p", WorkflowJob.class).getBuildByNumber(1); SemaphoreStep.success("wait/1", null); r.assertBuildStatusSuccess(r.waitForCompletion(b)); @@ -245,6 +253,8 @@ public StepExecution start(StepContext stepContext) { } public static class Execution extends StepExecution { + + @Serial private static final long serialVersionUID = 1; private final transient MockLauncherStep step; @@ -254,7 +264,8 @@ public static class Execution extends StepExecution { this.step = step; } - @Override public boolean start() throws Exception { + @Override + public boolean start() throws Exception { getContext().newBodyInvoker(). withContext(BodyInvoker.mergeLauncherDecorators(getContext().get(LauncherDecorator.class), new Decorator())). withCallback(BodyExecutionCallback.wrap(getContext())). @@ -267,28 +278,40 @@ public void stop(@NonNull Throwable throwable) { } } + private static class Decorator extends LauncherDecorator implements Serializable { + + @Serial private static final long serialVersionUID = 1; + @NonNull - @Override public Launcher decorate(@NonNull Launcher launcher, @NonNull Node node) { + @Override + public Launcher decorate(@NonNull Launcher launcher, @NonNull Node node) { return launcher.decorateByPrefix("true"); } } - @TestExtension public static class DescriptorImpl extends StepDescriptor { + + @TestExtension + public static class DescriptorImpl extends StepDescriptor { @Override public Set> getRequiredContext() { return ImmutableSet.of(Launcher.class); } - @Override public String getFunctionName() { + @Override + public String getFunctionName() { return "mockDockerLogin"; } + @NonNull - @Override public String getDisplayName() { + @Override + public String getDisplayName() { return "Mock Docker Login"; } - @Override public boolean takesImplicitBlockArgument() { + + @Override + public boolean takesImplicitBlockArgument() { return true; } } diff --git a/src/test/java/org/jenkinsci/plugins/docker/workflow/ServerEndpointStepTest.java b/src/test/java/org/jenkinsci/plugins/docker/workflow/ServerEndpointStepTest.java index c62add786..c337cb376 100644 --- a/src/test/java/org/jenkinsci/plugins/docker/workflow/ServerEndpointStepTest.java +++ b/src/test/java/org/jenkinsci/plugins/docker/workflow/ServerEndpointStepTest.java @@ -44,33 +44,37 @@ import org.jenkinsci.plugins.workflow.steps.StepConfigTester; import org.jenkinsci.plugins.workflow.structs.DescribableHelper; import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep; -import org.junit.Test; import static org.jenkinsci.plugins.docker.workflow.DockerTestUtil.assumeNotWindows; -import static org.junit.Assert.*; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.runners.model.Statement; -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.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import org.jvnet.hudson.test.MockAuthorizationStrategy; import org.jvnet.hudson.test.MockQueueItemAuthenticator; -import org.jvnet.hudson.test.RestartableJenkinsRule; +import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension; +import org.jvnet.hudson.test.junit.jupiter.JenkinsSessionExtension; + +class ServerEndpointStepTest { -public class ServerEndpointStepTest { + @SuppressWarnings("unused") + @RegisterExtension + private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension(); + @RegisterExtension + private final JenkinsSessionExtension story = new JenkinsSessionExtension(); - @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher(); - @Rule public RestartableJenkinsRule story = new RestartableJenkinsRule(); - @Test public void configRoundTrip() { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + void configRoundTrip() throws Throwable { + story.then(r -> { IdCredentials serverCredentials = new DockerServerCredentials(CredentialsScope.GLOBAL, "serverCreds", null, "clientKey", "clientCertificate", "serverCaCertificate"); - CredentialsProvider.lookupStores(story.j.jenkins).iterator().next().addCredentials(Domain.global(), serverCredentials); - StepConfigTester sct = new StepConfigTester(story.j); - Map serverConfig = new TreeMap(); + CredentialsProvider.lookupStores(r.jenkins).iterator().next().addCredentials(Domain.global(), serverCredentials); + StepConfigTester sct = new StepConfigTester(r); + Map serverConfig = new TreeMap<>(); serverConfig.put("uri", "tcp://host:2375"); serverConfig.put("credentialsId", serverCredentials.getId()); - Map config = Collections.singletonMap("server", serverConfig); + Map config = Collections.singletonMap("server", serverConfig); ServerEndpointStep step = DescribableHelper.instantiate(ServerEndpointStep.class, config); step = sct.configRoundTrip(step); DockerServerEndpoint server = step.getServer(); @@ -79,84 +83,87 @@ public class ServerEndpointStepTest { assertEquals(serverCredentials.getId(), server.getCredentialsId()); assertEquals(config, DescribableHelper.uninstantiate(step)); } - }); + ); } - @Test public void variables() { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + void variables() throws Throwable { + story.then(r -> { assumeNotWindows(); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( - "node {\n" + - " withDockerServer(server: [uri: 'tcp://host:1234']) {\n" + - " semaphore 'wait'\n" + - " sh 'echo would be connecting to $DOCKER_HOST'\n" + - " }\n" + - "}", true)); + """ + node { + withDockerServer(server: [uri: 'tcp://host:1234']) { + semaphore 'wait' + sh 'echo would be connecting to $DOCKER_HOST' + } + }""", true)); WorkflowRun b = p.scheduleBuild2(0).waitForStart(); SemaphoreStep.waitForStart("wait/1", b); } - }); - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + ); + story.then(r -> { SemaphoreStep.success("wait/1", null); - WorkflowJob p = story.j.jenkins.getItemByFullName("prj", WorkflowJob.class); + WorkflowJob p = r.jenkins.getItemByFullName("prj", WorkflowJob.class); WorkflowRun b = p.getLastBuild(); - story.j.assertLogContains("would be connecting to tcp://host:1234", story.j.assertBuildStatusSuccess(story.j.waitForCompletion(b))); + r.assertLogContains("would be connecting to tcp://host:1234", r.assertBuildStatusSuccess(r.waitForCompletion(b))); } - }); + ); } - @Test public void stepExecutionWithCredentials() { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + void stepExecutionWithCredentials() throws Throwable { + story.then(r -> { assumeNotWindows(); IdCredentials serverCredentials = new DockerServerCredentials(CredentialsScope.GLOBAL, "serverCreds", null, "clientKey", "clientCertificate", "serverCaCertificate"); - CredentialsProvider.lookupStores(story.j.jenkins).iterator().next().addCredentials(Domain.global(), serverCredentials); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + CredentialsProvider.lookupStores(r.jenkins).iterator().next().addCredentials(Domain.global(), serverCredentials); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( - "node {\n" + - " withDockerServer(server: [uri: 'tcp://host:1234', credentialsId: 'serverCreds']) {\n" + - " sh 'echo would be connecting to $DOCKER_HOST'\n" + - " sh 'echo DOCKER_TLS_VERIFY=$DOCKER_TLS_VERIFY'\n" + - " sh 'echo DOCKER_CERT_PATH=$DOCKER_CERT_PATH is not empty'\n" + - " }\n" + - "}", true)); - WorkflowRun b = story.j.buildAndAssertSuccess(p); - story.j.assertLogContains("would be connecting to tcp://host:1234", b); - story.j.assertLogContains("DOCKER_TLS_VERIFY=1", b); - story.j.assertLogNotContains("DOCKER_CERT_PATH= is not empty", b); + """ + node { + withDockerServer(server: [uri: 'tcp://host:1234', credentialsId: 'serverCreds']) { + sh 'echo would be connecting to $DOCKER_HOST' + sh 'echo DOCKER_TLS_VERIFY=$DOCKER_TLS_VERIFY' + sh 'echo DOCKER_CERT_PATH=$DOCKER_CERT_PATH is not empty' + } + }""", true)); + WorkflowRun b = r.buildAndAssertSuccess(p); + r.assertLogContains("would be connecting to tcp://host:1234", b); + r.assertLogContains("DOCKER_TLS_VERIFY=1", b); + r.assertLogNotContains("DOCKER_CERT_PATH= is not empty", b); } - }); + ); } - - @Test public void stepExecutionWithCredentialsAndQueueItemAuthenticator() throws Exception { + + @Test + void stepExecutionWithCredentialsAndQueueItemAuthenticator() throws Throwable { assumeNotWindows(); story.then(r -> { - story.j.getInstance().setSecurityRealm(story.j.createDummySecurityRealm()); + r.getInstance().setSecurityRealm(r.createDummySecurityRealm()); MockAuthorizationStrategy auth = new MockAuthorizationStrategy() .grant(Jenkins.READ).everywhere().to("alice", "bob") .grant(Computer.BUILD).everywhere().to("alice", "bob") // Item.CONFIGURE implies Credentials.USE_ITEM, which is what CredentialsProvider.findCredentialById // uses when determining whether to include item-scope credentials in the search. .grant(Item.CONFIGURE).everywhere().to("alice"); - story.j.getInstance().setAuthorizationStrategy(auth); + r.getInstance().setAuthorizationStrategy(auth); IdCredentials serverCredentials = new DockerServerCredentials(CredentialsScope.GLOBAL, "serverCreds", null, "clientKey", "clientCertificate", "serverCaCertificate"); - CredentialsProvider.lookupStores(story.j.jenkins).iterator().next().addCredentials(Domain.global(), serverCredentials); - - String script = "node {\n" + - " withDockerServer(server: [uri: 'tcp://host:1234', credentialsId: 'serverCreds']) {\n" + - " sh 'echo would be connecting to $DOCKER_HOST'\n" + - " sh 'echo DOCKER_TLS_VERIFY=$DOCKER_TLS_VERIFY'\n" + - " sh 'echo DOCKER_CERT_PATH=$DOCKER_CERT_PATH is not empty'\n" + - " }\n" + - "}"; - WorkflowJob p1 = story.j.jenkins.createProject(WorkflowJob.class, "prj1"); + CredentialsProvider.lookupStores(r.jenkins).iterator().next().addCredentials(Domain.global(), serverCredentials); + + String script = """ + node { + withDockerServer(server: [uri: 'tcp://host:1234', credentialsId: 'serverCreds']) { + sh 'echo would be connecting to $DOCKER_HOST' + sh 'echo DOCKER_TLS_VERIFY=$DOCKER_TLS_VERIFY' + sh 'echo DOCKER_CERT_PATH=$DOCKER_CERT_PATH is not empty' + } + }"""; + WorkflowJob p1 = r.jenkins.createProject(WorkflowJob.class, "prj1"); p1.setDefinition(new CpsFlowDefinition(script, true)); - WorkflowJob p2 = story.j.jenkins.createProject(WorkflowJob.class, "prj2"); + WorkflowJob p2 = r.jenkins.createProject(WorkflowJob.class, "prj2"); p2.setDefinition(new CpsFlowDefinition(script, true)); QueueItemAuthenticatorConfiguration.get() @@ -169,16 +176,16 @@ public class ServerEndpointStepTest { p2.getFullName(), User.getById("bob", true).impersonate2())); // Alice has Credentials.USE_ITEM permission and should be able to use the credential. - WorkflowRun b1 = story.j.buildAndAssertSuccess(p1); - story.j.assertLogContains("would be connecting to tcp://host:1234", b1); - story.j.assertLogContains("DOCKER_TLS_VERIFY=1", b1); - story.j.assertLogNotContains("DOCKER_CERT_PATH= is not empty", b1); + WorkflowRun b1 = r.buildAndAssertSuccess(p1); + r.assertLogContains("would be connecting to tcp://host:1234", b1); + r.assertLogContains("DOCKER_TLS_VERIFY=1", b1); + r.assertLogNotContains("DOCKER_CERT_PATH= is not empty", b1); // Bob does not have Credentials.USE_ITEM permission and should not be able to use the credential. - WorkflowRun b2 = story.j.buildAndAssertSuccess(p2); - story.j.assertLogContains("would be connecting to tcp://host:1234", b2); - story.j.assertLogContains("DOCKER_TLS_VERIFY=\n", b2); - story.j.assertLogContains("DOCKER_CERT_PATH= is not empty", b2); + WorkflowRun b2 = r.buildAndAssertSuccess(p2); + r.assertLogContains("would be connecting to tcp://host:1234", b2); + r.assertLogContains("DOCKER_TLS_VERIFY=\n", b2); + r.assertLogContains("DOCKER_CERT_PATH= is not empty", b2); }); } diff --git a/src/test/java/org/jenkinsci/plugins/docker/workflow/WithContainerStepTest.java b/src/test/java/org/jenkinsci/plugins/docker/workflow/WithContainerStepTest.java index d2b084239..48847d075 100644 --- a/src/test/java/org/jenkinsci/plugins/docker/workflow/WithContainerStepTest.java +++ b/src/test/java/org/jenkinsci/plugins/docker/workflow/WithContainerStepTest.java @@ -33,11 +33,11 @@ import hudson.model.Result; import hudson.model.TaskListener; import hudson.slaves.DumbSlave; -import hudson.tools.ToolProperty; import hudson.util.ArgumentListBuilder; import hudson.util.Secret; import hudson.util.StreamTaskListener; import java.io.File; +import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.Collections; import java.util.logging.Level; @@ -49,8 +49,7 @@ import java.util.concurrent.TimeUnit; import org.apache.commons.fileupload.FileItem; import org.apache.commons.io.FileUtils; -import org.hamcrest.Matchers; -import static org.hamcrest.Matchers.is; + import org.jenkinsci.lib.configprovider.ConfigProvider; import org.jenkinsci.lib.configprovider.model.Config; import org.jenkinsci.plugins.configfiles.custom.CustomConfig; @@ -68,213 +67,223 @@ import org.jenkinsci.plugins.workflow.steps.StepExecution; import org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution; import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep; -import org.junit.Assume; -import static org.junit.Assume.assumeTrue; -import org.junit.ClassRule; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.Rule; -import org.junit.rules.TemporaryFolder; -import org.junit.runners.model.Statement; -import org.jvnet.hudson.test.BuildWatcher; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.api.io.TempDir; import org.jvnet.hudson.test.Issue; -import org.jvnet.hudson.test.LoggerRule; -import org.jvnet.hudson.test.RestartableJenkinsRule; +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; import org.kohsuke.stapler.DataBoundConstructor; -public class WithContainerStepTest { +class WithContainerStepTest { - @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher(); - @Rule public RestartableJenkinsRule story = new RestartableJenkinsRule(); - @Rule public TemporaryFolder tmp = new TemporaryFolder(); - @Rule public LoggerRule logging = new LoggerRule(); - - @Test public void configRoundTrip() { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @SuppressWarnings("unused") + @RegisterExtension + private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension(); + @RegisterExtension + private final JenkinsSessionExtension story = new JenkinsSessionExtension(); + @TempDir + private File tmp; + private final LogRecorder logging = new LogRecorder(); + + @Test + void configRoundTrip() throws Throwable { + story.then(r -> { WithContainerStep s1 = new WithContainerStep("java"); s1.setArgs("--link db:db"); - story.j.assertEqualDataBoundBeans(s1, new StepConfigTester(story.j).configRoundTrip(s1)); - story.j.jenkins.getDescriptorByType(DockerTool.DescriptorImpl.class).setInstallations(new DockerTool("docker15", "/usr/local/docker15", Collections.>emptyList())); + r.assertEqualDataBoundBeans(s1, new StepConfigTester(r).configRoundTrip(s1)); + r.jenkins.getDescriptorByType(DockerTool.DescriptorImpl.class).setInstallations(new DockerTool("docker15", "/usr/local/docker15", Collections.emptyList())); s1.setToolName("docker15"); - story.j.assertEqualDataBoundBeans(s1, new StepConfigTester(story.j).configRoundTrip(s1)); + r.assertEqualDataBoundBeans(s1, new StepConfigTester(r).configRoundTrip(s1)); } - }); + ); } - @Test public void basics() { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + void basics() throws Throwable { + story.then(r -> { DockerTestUtil.assumeDocker(); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( - "node {\n" + - " withDockerContainer('httpd:2.4.59') {\n" + - " sh 'cp /usr/local/apache2/conf/extra/httpd-userdir.conf .; ls -la'\n" + - " }\n" + - " sh 'ls -la; cat *.conf'\n" + - "}", true)); - WorkflowRun b = story.j.assertBuildStatusSuccess(p.scheduleBuild2(0)); - story.j.assertLogContains("Require method GET POST OPTIONS", b); + """ + node { + withDockerContainer('httpd:2.4.59') { + sh 'cp /usr/local/apache2/conf/extra/httpd-userdir.conf .; ls -la' + } + sh 'ls -la; cat *.conf' + }""", true)); + WorkflowRun b = r.assertBuildStatusSuccess(p.scheduleBuild2(0)); + r.assertLogContains("Require method GET POST OPTIONS", b); } - }); + ); } - @Issue("JENKINS-37719") @Ignore //Not working locally for cert release - @Test public void hungDaemon() { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Issue("JENKINS-37719") + @Disabled("Not working locally for cert release") + @Test + void hungDaemon() throws Throwable { + story.then(r -> { DockerTestUtil.assumeDocker(); Process proc = new ProcessBuilder("sudo", "pgrep", "dockerd").inheritIO().start(); proc.waitFor(15, TimeUnit.SECONDS); - Assume.assumeThat("we are in an interactive environment and can pause dockerd", proc.exitValue(), Matchers.is(0)); + assumeTrue(proc.exitValue() == 0, "we are in an interactive environment and can pause dockerd"); logging.record("org.jenkinsci.plugins.workflow.support.concurrent.Timeout", Level.FINE); // TODO use Timeout.class when workflow-support 2.13+ - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( - "node {\n" + - " timeout(time: 20, unit: 'SECONDS') {\n" + - " withDockerContainer('httpd:2.4.59') {\n" + - " sh 'sleep infinity'\n" + - " }\n" + - " }\n" + - "}", true)); + """ + node { + timeout(time: 20, unit: 'SECONDS') { + withDockerContainer('httpd:2.4.59') { + sh 'sleep infinity' + } + } + }""", true)); int origTimeout = DockerClient.CLIENT_TIMEOUT; DockerClient.CLIENT_TIMEOUT = 10; try { WorkflowRun b = p.scheduleBuild2(0).waitForStart(); - story.j.waitForMessage("+ sleep infinity", b); + r.waitForMessage("+ sleep infinity", b); proc = new ProcessBuilder("sudo", "killall", "-STOP", "dockerd").inheritIO().start(); proc.waitFor(15, TimeUnit.SECONDS); - Assume.assumeThat("could suspend dockerd", proc.exitValue(), Matchers.is(0)); + assumeTrue(proc.exitValue() == 0, "could suspend dockerd"); try { - story.j.assertBuildStatus(Result.ABORTED, story.j.waitForCompletion(b)); + r.assertBuildStatus(Result.ABORTED, r.waitForCompletion(b)); } finally { proc = new ProcessBuilder("sudo", "killall", "-CONT", "dockerd").inheritIO().start(); proc.waitFor(15, TimeUnit.SECONDS); - Assume.assumeThat("could resume dockerd", proc.exitValue(), Matchers.is(0)); + assumeTrue(proc.exitValue() == 0, "could resume dockerd"); } } finally { DockerClient.CLIENT_TIMEOUT = origTimeout; } } - }); + ); } - @Test public void stop() { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + void stop() throws Throwable { + story.then(r -> { DockerTestUtil.assumeDocker(); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( - "node {\n" + - " withDockerContainer('ubuntu:kinetic-20220602') {\n" + - " sh 'trap \\'echo got SIGTERM\\' TERM; trap \\'echo exiting; exit 99\\' EXIT; echo sleeping now with JENKINS_SERVER_COOKIE=$JENKINS_SERVER_COOKIE; sleep 999'\n" + - " }\n" + - "}", true)); + """ + node { + withDockerContainer('ubuntu:kinetic-20220602') { + sh 'trap \\'echo got SIGTERM\\' TERM; trap \\'echo exiting; exit 99\\' EXIT; echo sleeping now with JENKINS_SERVER_COOKIE=$JENKINS_SERVER_COOKIE; sleep 999' + } + }""", true)); WorkflowRun b = p.scheduleBuild2(0).waitForStart(); - story.j.waitForMessage("sleeping now", b); + r.waitForMessage("sleeping now", b); b.doStop(); - story.j.assertBuildStatus(Result.ABORTED, story.j.waitForCompletion(b)); - story.j.assertLogContains("script returned exit code 99", b); + r.assertBuildStatus(Result.ABORTED, r.waitForCompletion(b)); + r.assertLogContains("script returned exit code 99", b); } - }); + ); } - @Test public void death() { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + void death() throws Throwable { + story.then(r -> { DockerTestUtil.assumeDocker(); logging.record(BourneShellScript.class, Level.FINE); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( - "node {\n" + - " withDockerContainer('httpd:2.4.54-alpine') {\n" + - " sh \"set -e; sleep 5; ps -e -o pid,args | egrep '${pwd tmp: true}/durable-.+/script.sh' | fgrep -v grep | sort -n | tr -s ' ' | cut -d ' ' -f2 | xargs kill -9\"\n" + - " }\n" + - "}", true)); + """ + node { + withDockerContainer('httpd:2.4.54-alpine') { + sh "set -e; sleep 5; ps -e -o pid,args | egrep '${pwd tmp: true}/durable-.+/script.sh' | fgrep -v grep | sort -n | tr -s ' ' | cut -d ' ' -f2 | xargs kill -9" + } + }""", true)); Field hci = BourneShellScript.class.getDeclaredField("HEARTBEAT_CHECK_INTERVAL"); hci.setAccessible(true); int orig = (int) hci.get(null); hci.set(null, 5); try { - WorkflowRun b = story.j.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0).get()); - story.j.assertLogContains("script returned exit code -1", b); + WorkflowRun b = r.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0).get()); + r.assertLogContains("script returned exit code -1", b); } finally { hci.set(null, orig); } } - }); + ); } - @Test public void restart() { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + void restart() throws Throwable { + story.then(r -> { DockerTestUtil.assumeDocker(); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( - "node {\n" + - " withDockerContainer('httpd:2.4.59') {\n" + - " semaphore 'wait'\n" + - " sh 'cat /usr/local/apache2/conf/extra/httpd-userdir.conf'\n" + - " }\n" + - "}", true)); + """ + node { + withDockerContainer('httpd:2.4.59') { + semaphore 'wait' + sh 'cat /usr/local/apache2/conf/extra/httpd-userdir.conf' + } + }""", true)); WorkflowRun b = p.scheduleBuild2(0).waitForStart(); SemaphoreStep.waitForStart("wait/1", b); } - }); - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + ); + story.then(r -> { SemaphoreStep.success("wait/1", null); - WorkflowJob p = story.j.jenkins.getItemByFullName("prj", WorkflowJob.class); + WorkflowJob p = r.jenkins.getItemByFullName("prj", WorkflowJob.class); WorkflowRun b = p.getLastBuild(); - story.j.assertLogContains("Require method GET POST OPTIONS", story.j.assertBuildStatusSuccess(story.j.waitForCompletion(b))); + r.assertLogContains("Require method GET POST OPTIONS", r.assertBuildStatusSuccess(r.waitForCompletion(b))); } - }); + ); } @Issue("JENKINS-32943") - @Test public void fileCredentials() throws Exception { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + void fileCredentials() throws Throwable { + story.then(r -> { DockerTestUtil.assumeDocker(); - File f = tmp.newFile("some-file"); - FileUtils.write(f, "some-content\n"); + File f = newFile(tmp, "some-file"); + FileUtils.write(f, "some-content\n", StandardCharsets.UTF_8); FileItem fi = new FileParameterValue.FileItemImpl(f); FileCredentialsImpl fc = new FileCredentialsImpl(CredentialsScope.GLOBAL, "secretfile", "", fi, fi.getName(), (SecretBytes) null); - CredentialsProvider.lookupStores(story.j.jenkins).iterator().next().addCredentials(Domain.global(), fc); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + CredentialsProvider.lookupStores(r.jenkins).iterator().next().addCredentials(Domain.global(), fc); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( - "node {\n" + - " withDockerContainer('ubuntu') {\n" + - " withCredentials([file(credentialsId: 'secretfile', variable: 'FILE')]) {\n" + - " sh 'cat \"$FILE\"'\n" + - " }\n" + - " }\n" + - " withCredentials([file(credentialsId: 'secretfile', variable: 'FILE')]) {\n" + - " withDockerContainer('ubuntu') {\n" + - " sh 'tr \"a-z\" \"A-Z\" < \"$FILE\"'\n" + - " }\n" + - " }\n" + - "}", true)); - WorkflowRun b = story.j.assertBuildStatusSuccess(p.scheduleBuild2(0)); - story.j.assertLogContains("some-content", b); - story.j.assertLogContains("SOME-CONTENT", b); + """ + node { + withDockerContainer('ubuntu') { + withCredentials([file(credentialsId: 'secretfile', variable: 'FILE')]) { + sh 'cat "$FILE"' + } + } + withCredentials([file(credentialsId: 'secretfile', variable: 'FILE')]) { + withDockerContainer('ubuntu') { + sh 'tr "a-z" "A-Z" < "$FILE"' + } + } + }""", true)); + WorkflowRun b = r.assertBuildStatusSuccess(p.scheduleBuild2(0)); + r.assertLogContains("some-content", b); + r.assertLogContains("SOME-CONTENT", b); } - }); + ); } @Issue("JENKINS-27152") - @Test public void configFile() throws Exception { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + void configFile() throws Throwable { + story.then(r -> { DockerTestUtil.assumeDocker(); - ConfigProvider configProvider = story.j.jenkins.getExtensionList(ConfigProvider.class).get(CustomConfig.CustomConfigProvider.class); + ConfigProvider configProvider = r.jenkins.getExtensionList(ConfigProvider.class).get(CustomConfig.CustomConfigProvider.class); String id = configProvider.getProviderId() + "myfile"; Config config = new CustomConfig(id, "My File", "", "some-content"); configProvider.save(config); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( "node {\n" + " withDockerContainer('ubuntu') {\n" + @@ -288,87 +297,100 @@ public class WithContainerStepTest { " }\n" + " }\n" + "}", true)); - WorkflowRun b = story.j.assertBuildStatusSuccess(p.scheduleBuild2(0)); - story.j.assertLogContains("some-content", b); - story.j.assertLogContains("SOME-CONTENT", b); + WorkflowRun b = r.assertBuildStatusSuccess(p.scheduleBuild2(0)); + r.assertLogContains("some-content", b); + r.assertLogContains("SOME-CONTENT", b); } - }); + ); } @Issue("JENKINS-33510") - @Test public void cd() throws Exception { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + void cd() throws Throwable { + story.then(r -> { DockerTestUtil.assumeDocker(DockerTestUtil.DockerOsMode.LINUX, new VersionNumber("17.12")); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( - "node {\n" + - " withDockerContainer('ubuntu') {\n" + - " sh 'mkdir subdir && echo somecontent > subdir/file'\n" + - " dir('subdir') {\n" + - " sh 'pwd; tr \"a-z\" \"A-Z\" < file'\n" + - " }\n" + - " }\n" + - "}", true)); - WorkflowRun b = story.j.assertBuildStatusSuccess(p.scheduleBuild2(0)); - story.j.assertLogContains("SOMECONTENT", b); + """ + node { + withDockerContainer('ubuntu') { + sh 'mkdir subdir && echo somecontent > subdir/file' + dir('subdir') { + sh 'pwd; tr "a-z" "A-Z" < file' + } + } + }""", true)); + WorkflowRun b = r.assertBuildStatusSuccess(p.scheduleBuild2(0)); + r.assertLogContains("SOMECONTENT", b); } - }); + ); } - @Ignore("TODO reproducible") + @Disabled("TODO reproducible") @Issue("JENKINS-40101") - @Test public void wheezy() { - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + @Test + void wheezy() throws Throwable { + story.then(r -> { DockerTestUtil.assumeDocker(); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( - "node {\n" + - " withDockerContainer('debian:wheezy') {\n" + - " sh 'sleep 30s && echo ran OK'\n" + - " }\n" + - "}", true)); - WorkflowRun b = story.j.assertBuildStatusSuccess(p.scheduleBuild2(0)); - story.j.assertLogContains("ran OK", b); + """ + node { + withDockerContainer('debian:wheezy') { + sh 'sleep 30s && echo ran OK' + } + }""", true)); + WorkflowRun b = r.assertBuildStatusSuccess(p.scheduleBuild2(0)); + r.assertLogContains("ran OK", b); } - }); + ); } @Issue("JENKINS-56674") - @Test public void envMasking() { + @Test + void envMasking() throws Throwable { story.then(r -> { DockerTestUtil.assumeDocker(); WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "node {\n" + - " withDockerContainer('ubuntu') {\n" + - " stepWithLauncher false\n" + - " stepWithLauncher true\n" + - " }\n" + - "}", true)); - WorkflowRun b = story.j.assertBuildStatusSuccess(p.scheduleBuild2(0)); - story.j.assertLogContains("hello from some step", b); - story.j.assertLogContains("goodbye from ******** step", b); - story.j.assertLogContains("goodbye from mystery step", b); - story.j.assertLogNotContains("s3cr3t", b); + """ + node { + withDockerContainer('ubuntu') { + stepWithLauncher false + stepWithLauncher true + } + }""", true)); + WorkflowRun b = r.assertBuildStatusSuccess(p.scheduleBuild2(0)); + r.assertLogContains("hello from some step", b); + r.assertLogContains("goodbye from ******** step", b); + r.assertLogContains("goodbye from mystery step", b); + r.assertLogNotContains("s3cr3t", b); }); } + public static final class StepWithLauncher extends Step { public final boolean masking; - @DataBoundConstructor public StepWithLauncher(boolean masking) { + + @DataBoundConstructor + public StepWithLauncher(boolean masking) { this.masking = masking; } - @Override public StepExecution start(StepContext context) throws Exception { + + @Override + public StepExecution start(StepContext context) throws Exception { return new Execution(context, masking); } + private static final class Execution extends SynchronousNonBlockingStepExecution { private final boolean masking; + Execution(StepContext context, boolean masking) { super(context); this.masking = masking; } - @Override protected Void run() throws Exception { + + @Override + protected Void run() throws Exception { Launcher.ProcStarter ps = getContext().get(Launcher.class).launch(); ps.envs("SENSITIVE=s3cr3t"); if (masking) { @@ -383,18 +405,25 @@ private static final class Execution extends SynchronousNonBlockingStepExecution return null; } } - @TestExtension("envMasking") public static final class DescriptorImpl extends StepDescriptor { - @Override public String getFunctionName() { + + @TestExtension("envMasking") + public static final class DescriptorImpl extends StepDescriptor { + + @Override + public String getFunctionName() { return "stepWithLauncher"; } - @Override public Set> getRequiredContext() { + + @Override + public Set> getRequiredContext() { return ImmutableSet.of(Launcher.class, TaskListener.class); } } } @Issue("JENKINS-52264") - @Test public void removeInvalidEnvVars() throws IOException { + @Test + void removeInvalidEnvVars() throws Throwable { story.then(r -> { DockerTestUtil.assumeDocker(); WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p"); @@ -408,30 +437,39 @@ private static final class Execution extends SynchronousNonBlockingStepExecution " removeInvalidEnvVarsStep([\"=\", \"PATH=ignored_value\", \"other=with_path_and_empty\"]) \n" + //both invalid variables " }\n" + "}", true)); - WorkflowRun b = story.j.assertBuildStatusSuccess(p.scheduleBuild2(0)); - story.j.assertLogContains("working with empty environment.", b); - story.j.assertLogContains("only_valid_value", b); - story.j.assertLogContains("with_empty_var", b); - story.j.assertLogContains("with_path", b); - story.j.assertLogContains("with_path_and_empty", b); - story.j.assertLogNotContains("ignored_value", b); + WorkflowRun b = r.assertBuildStatusSuccess(p.scheduleBuild2(0)); + r.assertLogContains("working with empty environment.", b); + r.assertLogContains("only_valid_value", b); + r.assertLogContains("with_empty_var", b); + r.assertLogContains("with_path", b); + r.assertLogContains("with_path_and_empty", b); + r.assertLogNotContains("ignored_value", b); }); } + public static final class RemoveInvalidEnvVarsStep extends Step { public final Collection envVars; - @DataBoundConstructor public RemoveInvalidEnvVarsStep(Collection envVars) { + + @DataBoundConstructor + public RemoveInvalidEnvVarsStep(Collection envVars) { this.envVars = envVars; } - @Override public StepExecution start(StepContext context) throws Exception { + + @Override + public StepExecution start(StepContext context) throws Exception { return new Execution(context, envVars); } + private static final class Execution extends SynchronousNonBlockingStepExecution { private final Collection envVars; + Execution(StepContext context, Collection envVars) { super(context); this.envVars = envVars; } - @Override protected Void run() throws Exception { + + @Override + protected Void run() throws Exception { Launcher.ProcStarter ps = getContext().get(Launcher.class).launch(); ps.envs(envVars.toArray(new String[0])); ArgumentListBuilder args = new ArgumentListBuilder("sh", "-c"); @@ -450,21 +488,28 @@ private static final class Execution extends SynchronousNonBlockingStepExecution return null; } } - @TestExtension("removeInvalidEnvVars") public static final class DescriptorImpl extends StepDescriptor { - @Override public String getFunctionName() { + + @TestExtension("removeInvalidEnvVars") + public static final class DescriptorImpl extends StepDescriptor { + + @Override + public String getFunctionName() { return "removeInvalidEnvVarsStep"; } - @Override public Set> getRequiredContext() { + + @Override + public Set> getRequiredContext() { return ImmutableSet.of(Launcher.class, TaskListener.class); } } } @Issue("JENKINS-64608") - @Test public void runningInsideContainer() throws Throwable { + @Test + void runningInsideContainer() throws Throwable { story.then(r -> { DockerTestUtil.assumeDocker(); - assumeTrue("have docker.sock", new File("/var/run/docker.sock").exists()); + assumeTrue(new File("/var/run/docker.sock").exists(), "have docker.sock"); TaskListener taskListener = StreamTaskListener.fromStderr(); Launcher.LocalLauncher launcher = new Launcher.LocalLauncher(taskListener); int status = launcher.launch().stdout(taskListener). @@ -472,48 +517,55 @@ private static final class Execution extends SynchronousNonBlockingStepExecution cmds(DockerTool.getExecutable(null, null, null, null), "build", "-t", "agent-with-docker", "."). start(). joinWithTimeout(DockerClient.CLIENT_TIMEOUT, TimeUnit.SECONDS, taskListener); - Assume.assumeThat("Built agent-with-docker image", status, is(0)); + assumeTrue(status == 0, "Built agent-with-docker image"); DumbSlave s = new DumbSlave("dockerized", "/home/jenkins/agent", new SimpleCommandLauncher("docker run -i --rm --init -v /var/run/docker.sock:/var/run/docker.sock agent-with-docker java -jar /usr/share/jenkins/agent.jar")); r.jenkins.addNode(s); r.waitOnline(s); WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p"); p.setDefinition(new CpsFlowDefinition( - "node('dockerized') {\n" + - " sh 'which docker && docker version'\n" + - " withDockerContainer('httpd:2.4.59') {\n" + - " sh 'cp /usr/local/apache2/conf/extra/httpd-userdir.conf .; ls -la'\n" + - " }\n" + - " sh 'ls -la; cat *.conf'\n" + - "}", true)); + """ + node('dockerized') { + sh 'which docker && docker version' + withDockerContainer('httpd:2.4.59') { + sh 'cp /usr/local/apache2/conf/extra/httpd-userdir.conf .; ls -la' + } + sh 'ls -la; cat *.conf' + }""", true)); WorkflowRun b = r.buildAndAssertSuccess(p); r.assertLogContains("dockerized seems to be running inside container ", b); }); } - @Ignore("TODO currently broken in CI") + @Disabled("TODO currently broken in CI") @Issue("JENKINS-75102") - @Test public void windowsRunningWindowsContainerSpaceInPath() { + @Test + void windowsRunningWindowsContainerSpaceInPath() throws Throwable { // Launching batch scripts through cmd /c in docker exec gets tricky with special characters // By default, the path of the temporary Jenkins install and workspace have a space in a folder name and a prj@tmp folder - story.addStep(new Statement() { - @Override public void evaluate() throws Throwable { + story.then(r -> { DockerTestUtil.assumeWindows(); DockerTestUtil.assumeDocker(DockerTestUtil.DockerOsMode.WINDOWS); // Kernel must match when running Windows containers on docker on Windows String releaseTag = DockerTestUtil.getWindowsImageTag(); - WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "prj"); p.setDefinition(new CpsFlowDefinition( "node {\n" + " withDockerContainer('mcr.microsoft.com/windows/nanoserver:" + releaseTag + "') { \n" + " bat 'echo ran OK' \n" + " }\n" + "}", true)); - WorkflowRun b = story.j.assertBuildStatusSuccess(p.scheduleBuild2(0)); - story.j.assertLogContains("ran OK", b); + WorkflowRun b = r.assertBuildStatusSuccess(p.scheduleBuild2(0)); + r.assertLogContains("ran OK", b); } - }); + ); + } + + private static File newFile(File parent, String child) throws Exception { + File result = new File(parent, child); + assertTrue(result.createNewFile(), "Could not create " + result); + return result; } } diff --git a/src/test/java/org/jenkinsci/plugins/docker/workflow/client/ControlGroupTest.java b/src/test/java/org/jenkinsci/plugins/docker/workflow/client/ControlGroupTest.java index f075d2d56..320da7a55 100644 --- a/src/test/java/org/jenkinsci/plugins/docker/workflow/client/ControlGroupTest.java +++ b/src/test/java/org/jenkinsci/plugins/docker/workflow/client/ControlGroupTest.java @@ -1,19 +1,20 @@ package org.jenkinsci.plugins.docker.workflow.client; import com.google.common.base.Optional; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Test; -import java.io.IOException; import java.io.StringReader; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + /** * @author Nicolas De Loof */ -public class ControlGroupTest { +class ControlGroupTest { @Test - public void test_cgroup_string_matching() throws IOException { + void test_cgroup_string_matching() throws Exception { final String[] possibleCgroupStrings = new String[] { "2:cpu:/docker/3dd988081e7149463c043b5d9c57d7309e079c5e9290f91feba1cc45a04d6a5b", @@ -31,8 +32,8 @@ public void test_cgroup_string_matching() throws IOException { for (final String possibleCgroupString : possibleCgroupStrings) { final Optional containerId = ControlGroup.getContainerId(new StringReader(possibleCgroupString)); - Assert.assertTrue("pattern didn't match containerId " + possibleCgroupString, containerId.isPresent()); - Assert.assertEquals("3dd988081e7149463c043b5d9c57d7309e079c5e9290f91feba1cc45a04d6a5b", containerId.get()); + assertTrue(containerId.isPresent(), "pattern didn't match containerId " + possibleCgroupString); + assertEquals("3dd988081e7149463c043b5d9c57d7309e079c5e9290f91feba1cc45a04d6a5b", containerId.get()); } } diff --git a/src/test/java/org/jenkinsci/plugins/docker/workflow/client/DockerClientTest.java b/src/test/java/org/jenkinsci/plugins/docker/workflow/client/DockerClientTest.java index 0fdc5880e..8dfcd2ed1 100644 --- a/src/test/java/org/jenkinsci/plugins/docker/workflow/client/DockerClientTest.java +++ b/src/test/java/org/jenkinsci/plugins/docker/workflow/client/DockerClientTest.java @@ -25,14 +25,16 @@ import org.jenkinsci.plugins.docker.workflow.DockerTestUtil; import hudson.EnvVars; + +import static org.junit.jupiter.api.Assertions.*; + import hudson.Launcher; import hudson.model.TaskListener; import hudson.util.StreamTaskListener; import hudson.util.VersionNumber; import org.jenkinsci.plugins.docker.commons.fingerprint.ContainerRecord; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import java.io.IOException; import java.util.Collections; @@ -40,12 +42,12 @@ /** * @author tom.fennelly@gmail.com */ -public class DockerClientTest { +class DockerClientTest { private DockerClient dockerClient; - - @Before - public void setup() throws Exception { + + @BeforeEach + void setup() throws Exception { DockerTestUtil.assumeDocker(); // Set stuff up for the test @@ -56,44 +58,44 @@ public void setup() throws Exception { } @Test - public void test_run() throws IOException, InterruptedException { + void test_run() throws Exception { // Pin to a specific sha256 hash of the image to avoid any potential issues with the image changing in the future. // Original image tag: docker:20.10.9-dind String image = "docker.io/library/docker@sha256:d842418d21545fde57c2512681d9bdc4ce0e54f2e0305a293ee20a9b6166932b"; EnvVars launchEnv = DockerTestUtil.newDockerLaunchEnv(); String containerId = - dockerClient.run(launchEnv, image, null, null, Collections.emptyMap(), Collections.emptyList(), new EnvVars(), + dockerClient.run(launchEnv, image, null, null, Collections.emptyMap(), Collections.emptyList(), new EnvVars(), dockerClient.whoAmI(), "cat"); - Assert.assertEquals(64, containerId.length()); + assertEquals(64, containerId.length()); ContainerRecord containerRecord = dockerClient.getContainerRecord(launchEnv, containerId); - Assert.assertEquals(dockerClient.inspect(launchEnv, image, ".Id"), containerRecord.getImageId()); - Assert.assertTrue(containerRecord.getContainerName().length() > 0); - Assert.assertTrue(containerRecord.getHost().length() > 0); - Assert.assertTrue(containerRecord.getCreated() > 1000000000000L); + assertEquals(dockerClient.inspect(launchEnv, image, ".Id"), containerRecord.getImageId()); + assertFalse(containerRecord.getContainerName().isEmpty()); + assertFalse(containerRecord.getHost().isEmpty()); + assertTrue(containerRecord.getCreated() > 1000000000000L); // Check that an anonymous volume was created mounted at /var/lib/docker - Assert.assertEquals(Collections.singletonList("/var/lib/docker"), dockerClient.getVolumes(launchEnv, containerId)); + assertEquals(Collections.singletonList("/var/lib/docker"), dockerClient.getVolumes(launchEnv, containerId)); String anonymousVolumeName = dockerClient.inspect(launchEnv, containerId, "range .Mounts }}{{ .Name }}{{ end"); - Assert.assertEquals(64, anonymousVolumeName.length()); + assertEquals(64, anonymousVolumeName.length()); // Also test that the stop works and cleans up after itself - Assert.assertNotNull(dockerClient.inspect(launchEnv, containerId, ".Name")); + assertNotNull(dockerClient.inspect(launchEnv, containerId, ".Name")); dockerClient.stop(launchEnv, containerId); - Assert.assertNull(dockerClient.inspect(launchEnv, containerId, ".Name")); + assertNull(dockerClient.inspect(launchEnv, containerId, ".Name")); // Check that the anonymous volume was removed - Assert.assertNull(dockerClient.inspect(launchEnv, anonymousVolumeName, ".Name")); + assertNull(dockerClient.inspect(launchEnv, anonymousVolumeName, ".Name")); } @Test - public void test_valid_version() { + void test_valid_version() { VersionNumber dockerVersion = DockerClient.parseVersionNumber("Docker version 1.5.0, build a8a31ef"); - Assert.assertFalse(dockerVersion.isOlderThan(new VersionNumber("1.1"))); - Assert.assertFalse(dockerVersion.isOlderThan(new VersionNumber("1.5"))); - Assert.assertTrue(dockerVersion.isOlderThan(new VersionNumber("1.10"))); + assertFalse(dockerVersion.isOlderThan(new VersionNumber("1.1"))); + assertFalse(dockerVersion.isOlderThan(new VersionNumber("1.5"))); + assertTrue(dockerVersion.isOlderThan(new VersionNumber("1.10"))); } - + @Test - public void test_invalid_version() { - Assert.assertNull(DockerClient.parseVersionNumber("xxx")); + void test_invalid_version() { + assertNull(DockerClient.parseVersionNumber("xxx")); } } diff --git a/src/test/java/org/jenkinsci/plugins/docker/workflow/client/WindowsDockerClientTest.java b/src/test/java/org/jenkinsci/plugins/docker/workflow/client/WindowsDockerClientTest.java index a822c7cb6..70be393a2 100644 --- a/src/test/java/org/jenkinsci/plugins/docker/workflow/client/WindowsDockerClientTest.java +++ b/src/test/java/org/jenkinsci/plugins/docker/workflow/client/WindowsDockerClientTest.java @@ -6,18 +6,20 @@ import hudson.util.StreamTaskListener; import org.jenkinsci.plugins.docker.commons.fingerprint.ContainerRecord; import org.jenkinsci.plugins.docker.workflow.DockerTestUtil; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; import java.util.Collections; -public class WindowsDockerClientTest { +class WindowsDockerClientTest { private DockerClient dockerClient; - @Before - public void setup() { + @BeforeEach + void setup() { TaskListener taskListener = StreamTaskListener.fromStderr(); Launcher.LocalLauncher launcher = new Launcher.LocalLauncher(taskListener); @@ -25,7 +27,7 @@ public void setup() { } @Test - public void test_run() throws Exception { + void test_run() throws Exception { DockerTestUtil.assumeDocker(); EnvVars launchEnv = DockerTestUtil.newDockerLaunchEnv(); String containerId = dockerClient.run( @@ -39,17 +41,17 @@ public void test_run() throws Exception { dockerClient.whoAmI(), "cat"); - Assert.assertEquals(64, containerId.length()); + assertEquals(64, containerId.length()); ContainerRecord containerRecord = dockerClient.getContainerRecord(launchEnv, containerId); - Assert.assertEquals(dockerClient.inspect(launchEnv, "busybox", ".Id"), containerRecord.getImageId()); - Assert.assertTrue(containerRecord.getContainerName().length() > 0); - Assert.assertTrue(containerRecord.getHost().length() > 0); - Assert.assertTrue(containerRecord.getCreated() > 1000000000000L); - Assert.assertEquals(Collections.emptyList(), dockerClient.getVolumes(launchEnv, containerId)); + assertEquals(dockerClient.inspect(launchEnv, "busybox", ".Id"), containerRecord.getImageId()); + assertFalse(containerRecord.getContainerName().isEmpty()); + assertFalse(containerRecord.getHost().isEmpty()); + assertTrue(containerRecord.getCreated() > 1000000000000L); + assertEquals(Collections.emptyList(), dockerClient.getVolumes(launchEnv, containerId)); // Also test that the stop works and cleans up after itself - Assert.assertNotNull(dockerClient.inspect(launchEnv, containerId, ".Name")); + assertNotNull(dockerClient.inspect(launchEnv, containerId, ".Name")); dockerClient.stop(launchEnv, containerId); - Assert.assertNull(dockerClient.inspect(launchEnv, containerId, ".Name")); + assertNull(dockerClient.inspect(launchEnv, containerId, ".Name")); } } diff --git a/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/DeclarativeDockerUtilsTest.java b/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/DeclarativeDockerUtilsTest.java index 85f1a0eb1..da5864c36 100644 --- a/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/DeclarativeDockerUtilsTest.java +++ b/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/DeclarativeDockerUtilsTest.java @@ -36,15 +36,16 @@ import hudson.model.Descriptor.FormException; import hudson.model.Slave; import org.jenkinsci.plugins.docker.commons.credentials.DockerRegistryEndpoint; + import org.jenkinsci.plugins.docker.workflow.DockerTestUtil; import org.jenkinsci.plugins.pipeline.modeldefinition.AbstractModelDefTest; import org.junit.Assume; import org.junit.BeforeClass; import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.collection.IsCollectionWithSize.hasSize; import static org.hamcrest.core.IsInstanceOf.instanceOf; -import static org.junit.Assert.assertThat; /** * Tests {@link DeclarativeDockerUtils}. @@ -177,7 +178,7 @@ public void grandParentOverride() throws Exception { @Test public void runsOnCorrectSlave() throws Exception { - DockerTestUtil.assumeDocker(); + DockerTestUtil.assumeDockerJUnit4(); Slave s = j.createOnlineSlave(); s.setLabelString("notthis"); env(s).put("DOCKER_INDICATOR", "WRONG").set(); @@ -193,7 +194,7 @@ public void runsOnCorrectSlave() throws Exception { @Test public void runsOnSpecifiedSlave() throws Exception { - DockerTestUtil.assumeDocker(); + DockerTestUtil.assumeDockerJUnit4(); Slave s = j.createOnlineSlave(); s.setLabelString("thisspec"); env(s).put("DOCKER_INDICATOR", "SPECIFIED").set(); diff --git a/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/DockerAgentTest.java b/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/DockerAgentTest.java index ed44e650f..e9fd2aaea 100644 --- a/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/DockerAgentTest.java +++ b/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/DockerAgentTest.java @@ -33,7 +33,6 @@ import java.util.List; import org.jenkinsci.plugins.docker.workflow.DockerTestUtil; import org.jenkinsci.plugins.pipeline.modeldefinition.AbstractModelDefTest; -import static org.jenkinsci.plugins.pipeline.modeldefinition.AbstractModelDefTest.j; import static org.junit.Assume.assumeThat; import org.junit.BeforeClass; import org.junit.Ignore; @@ -97,7 +96,7 @@ public void agentDockerWithoutContainerPerStage() throws Exception { @Test public void agentDockerDontReuseNode() throws Exception { - DockerTestUtil.assumeDocker(); + DockerTestUtil.assumeDockerJUnit4(); expect(Result.FAILURE, "org/jenkinsci/plugins/docker/workflow/declarative/agentDockerDontReuseNode") .logContains("The answer is 42") @@ -109,7 +108,7 @@ public void agentDockerDontReuseNode() throws Exception { @Issue("JENKINS-41605") @Test public void agentInStageAutoCheckout() throws Exception { - DockerTestUtil.assumeDocker(); + DockerTestUtil.assumeDockerJUnit4(); expect("org/jenkinsci/plugins/docker/workflow/declarative/agentInStageAutoCheckout") .logContains("The answer is 42", @@ -133,7 +132,7 @@ public void agentDockerWithEmptyDockerArgs() throws Exception { @Issue("JENKINS-41950") @Test public void nonExistentDockerImage() throws Exception { - DockerTestUtil.assumeDocker(); + DockerTestUtil.assumeDockerJUnit4(); expect(Result.FAILURE, "org/jenkinsci/plugins/docker/workflow/declarative/nonExistentDockerImage") .logContains("ERROR: script returned exit code 1", @@ -144,7 +143,7 @@ public void nonExistentDockerImage() throws Exception { @Test public void fromDockerfile() throws Exception { - DockerTestUtil.assumeDocker(); + DockerTestUtil.assumeDockerJUnit4(); sampleRepo.write("Dockerfile", "FROM ubuntu:noble\n\nRUN echo 'HI THERE' > /hi-there\n\n"); sampleRepo.git("init"); @@ -163,7 +162,7 @@ public void fromDockerfile() throws Exception { @Test public void userHandbookDockerfile() throws Exception { assumeThat("TODO currently failing", System.getenv("CI"), not(is("true"))); - DockerTestUtil.assumeDocker(); + DockerTestUtil.assumeDockerJUnit4(); sampleRepo.write("Dockerfile", "FROM node:22.13.0-alpine\nRUN apk add -U subversion\n"); sampleRepo.git("init"); @@ -178,7 +177,7 @@ public void userHandbookDockerfile() throws Exception { @Test public void additionalDockerBuildArgs() throws Exception { - DockerTestUtil.assumeDocker(); + DockerTestUtil.assumeDockerJUnit4(); sampleRepo.write("Dockerfile", "FROM ubuntu:noble\n\nARG someArg=thisArgHere\n\nRUN echo \"hi there, $someArg\" > /hi-there\n\n"); sampleRepo.git("init"); @@ -197,7 +196,7 @@ public void additionalDockerBuildArgs() throws Exception { @Issue("JENKINS-57162") @Test public void additionalDockerBuildArgsImageHash() throws Exception { - DockerTestUtil.assumeDocker(); + DockerTestUtil.assumeDockerJUnit4(); sampleRepo.write("Dockerfile", "FROM ubuntu:noble\n\nARG someArg=thisArgHere\n\nRUN echo \"hi there, $someArg\" > /hi-there\n\n"); sampleRepo.git("init"); @@ -224,7 +223,7 @@ public void additionalDockerBuildArgsImageHash() throws Exception { @Issue("JENKINS-41668") @Test public void fromDockerfileInOtherDir() throws Exception { - DockerTestUtil.assumeDocker(); + DockerTestUtil.assumeDockerJUnit4(); sampleRepo.write("subdir/Dockerfile", "FROM ubuntu:noble\n\nRUN echo 'HI THERE' > /hi-there\n\n"); sampleRepo.git("init"); @@ -242,7 +241,7 @@ public void fromDockerfileInOtherDir() throws Exception { @Issue("JENKINS-42286") @Test public void dirSepInDockerfileName() throws Exception { - DockerTestUtil.assumeDocker(); + DockerTestUtil.assumeDockerJUnit4(); sampleRepo.write("subdir/Dockerfile", "FROM ubuntu:noble\n\nRUN echo 'HI THERE' > /hi-there\n\n"); sampleRepo.git("init"); @@ -259,7 +258,7 @@ public void dirSepInDockerfileName() throws Exception { @Test public void fromDockerfileNoArgs() throws Exception { - DockerTestUtil.assumeDocker(); + DockerTestUtil.assumeDockerJUnit4(); sampleRepo.write("Dockerfile", "FROM ubuntu:noble\n\nRUN echo 'HI THERE' > /hi-there\n\n"); sampleRepo.git("init"); @@ -275,7 +274,7 @@ public void fromDockerfileNoArgs() throws Exception { @Test public void fromAlternateDockerfile() throws Exception { - DockerTestUtil.assumeDocker(); + DockerTestUtil.assumeDockerJUnit4(); sampleRepo.write("Dockerfile.alternate", "FROM ubuntu:noble\n\nRUN echo 'HI THERE' > /hi-there\n\n"); sampleRepo.git("init"); sampleRepo.git("add", "Dockerfile.alternate"); @@ -304,7 +303,7 @@ public void agentDockerGlobalThenLabel() throws Exception { @Issue("JENKINS-47106") @Test public void dockerPullLocalImage() throws Exception { - DockerTestUtil.assumeDocker(); + DockerTestUtil.assumeDockerJUnit4(); sampleRepo.write("Dockerfile", "FROM ubuntu:noble\n\nRUN echo 'HI THERE' > /hi-there\n\n"); sampleRepo.git("init"); @@ -321,7 +320,7 @@ public void dockerPullLocalImage() throws Exception { } private void agentDocker(final String jenkinsfile, String... additionalLogContains) throws Exception { - DockerTestUtil.assumeDocker(); + DockerTestUtil.assumeDockerJUnit4(); List logContains = new ArrayList<>(); logContains.add("[Pipeline] { (foo)"); @@ -329,7 +328,7 @@ private void agentDocker(final String jenkinsfile, String... additionalLogContai logContains.addAll(Arrays.asList(additionalLogContains)); expect(jenkinsfile) - .logContains(logContains.toArray(new String[logContains.size()])) + .logContains(logContains.toArray(new String[0])) .go(); } diff --git a/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/DockerBasicModelDefTest.java b/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/DockerBasicModelDefTest.java index e74923e2a..fea59cf0d 100644 --- a/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/DockerBasicModelDefTest.java +++ b/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/DockerBasicModelDefTest.java @@ -51,7 +51,7 @@ public static void setUpAgent() throws Exception { @Test public void dockerGlobalVariable() throws Exception { - DockerTestUtil.assumeDocker(); + DockerTestUtil.assumeDockerJUnit4(); expect("org/jenkinsci/plugins/docker/workflow/declarative/dockerGlobalVariable") .logContains("[Pipeline] { (foo)", "image: ubuntu") diff --git a/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/DockerDirectiveGeneratorTest.java b/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/DockerDirectiveGeneratorTest.java index 4de16b30c..16f515a76 100644 --- a/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/DockerDirectiveGeneratorTest.java +++ b/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/DockerDirectiveGeneratorTest.java @@ -42,36 +42,40 @@ import org.jenkinsci.plugins.pipeline.modeldefinition.generator.DirectiveGenerator; import org.jenkinsci.plugins.structs.describable.DescribableModel; import org.jenkinsci.plugins.structs.describable.DescribableParameter; -import static org.junit.Assert.assertEquals; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.ToolInstallations; +import org.jvnet.hudson.test.junit.jupiter.WithJenkins; /** * Adapted from {@link org.jenkinsci.plugins.pipeline.modeldefinition.generator.DirectiveGeneratorTest}. */ -public class DockerDirectiveGeneratorTest { +@WithJenkins +class DockerDirectiveGeneratorTest { - @ClassRule - public static JenkinsRule r = new JenkinsRule(); + private static JenkinsRule r; - @BeforeClass - public static void setUp() throws Exception { + @BeforeAll + static void setUp(JenkinsRule rule) throws Exception { + r = rule; ToolInstallations.configureMaven3(); } @Test - public void simpleAgentDocker() throws Exception { + void simpleAgentDocker() throws Exception { AgentDirective agent = new AgentDirective(new DockerPipeline("some-image")); - assertGenerateDirective(agent, "agent {\n" + - " docker 'some-image'\n" + - "}"); + assertGenerateDirective(agent, """ + agent { + docker 'some-image' + }"""); } @Test - public void fullAgentDocker() throws Exception { + void fullAgentDocker() throws Exception { DockerPipeline dockerPipeline = new DockerPipeline("some-image"); dockerPipeline.setAlwaysPull(true); dockerPipeline.setArgs("--some-arg"); @@ -82,31 +86,33 @@ public void fullAgentDocker() throws Exception { dockerPipeline.setRegistryUrl("http://some.where"); AgentDirective agent = new AgentDirective(dockerPipeline); - assertGenerateDirective(agent, "agent {\n" + - " docker {\n" + - " alwaysPull true\n" + - " args '--some-arg'\n" + - " customWorkspace 'some/path'\n" + - " image 'some-image'\n" + - " label 'some-label'\n" + - " registryCredentialsId 'some-cred-id'\n" + - " registryUrl 'http://some.where'\n" + - " reuseNode true\n" + - " }\n" + - "}"); + assertGenerateDirective(agent, """ + agent { + docker { + alwaysPull true + args '--some-arg' + customWorkspace 'some/path' + image 'some-image' + label 'some-label' + registryCredentialsId 'some-cred-id' + registryUrl 'http://some.where' + reuseNode true + } + }"""); } @Test - public void simpleAgentDockerfile() throws Exception { + void simpleAgentDockerfile() throws Exception { AgentDirective agent = new AgentDirective(new DockerPipelineFromDockerfile()); - assertGenerateDirective(agent, "agent {\n" + - " dockerfile true\n" + - "}"); + assertGenerateDirective(agent, """ + agent { + dockerfile true + }"""); } @Test - public void fullAgentDockerfile() throws Exception { + void fullAgentDockerfile() throws Exception { DockerPipelineFromDockerfile dp = new DockerPipelineFromDockerfile(); dp.setAdditionalBuildArgs("--additional-arg"); dp.setDir("some-sub/dir"); @@ -116,16 +122,17 @@ public void fullAgentDockerfile() throws Exception { dp.setLabel("some-label"); AgentDirective agent = new AgentDirective(dp); - assertGenerateDirective(agent, "agent {\n" + - " dockerfile {\n" + - " additionalBuildArgs '--additional-arg'\n" + - " args '--some-arg'\n" + - " customWorkspace '/custom/workspace'\n" + - " dir 'some-sub/dir'\n" + - " filename 'NotDockerfile'\n" + - " label 'some-label'\n" + - " }\n" + - "}"); + assertGenerateDirective(agent, """ + agent { + dockerfile { + additionalBuildArgs '--additional-arg' + args '--some-arg' + customWorkspace '/custom/workspace' + dir 'some-sub/dir' + filename 'NotDockerfile' + label 'some-label' + } + }"""); } private void assertGenerateDirective(@NonNull AbstractDirective desc, @NonNull String responseText) throws Exception { @@ -135,7 +142,7 @@ private void assertGenerateDirective(@NonNull AbstractDirective desc, @NonNull S // Then submit the form with the appropriate JSON (we generate it from the directive, but it matches the form JSON exactly) JenkinsRule.WebClient wc = r.createWebClient(); WebRequest wrs = new WebRequest(new URL(r.getURL(), DirectiveGenerator.GENERATE_URL), HttpMethod.POST); - List params = new ArrayList(); + List params = new ArrayList<>(); params.add(new NameValuePair("json", staplerJsonForDescr(desc).toString())); // WebClient.addCrumb *replaces* rather than *adds*: params.add(new NameValuePair(r.jenkins.getCrumbIssuer().getDescriptor().getCrumbRequestField(), r.jenkins.getCrumbIssuer().getCrumb((ServletRequest) null))); diff --git a/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/DockerPostStageTest.java b/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/DockerPostStageTest.java index a2f5920a4..15ca09866 100644 --- a/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/DockerPostStageTest.java +++ b/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/DockerPostStageTest.java @@ -37,7 +37,7 @@ public class DockerPostStageTest extends AbstractModelDefTest { @Issue("JENKINS-46276") @Test public void withAgentNoneAndAgentDocker() throws Exception { - DockerTestUtil.assumeDocker(); + DockerTestUtil.assumeDockerJUnit4(); expect("org/jenkinsci/plugins/docker/workflow/declarative/withAgentNoneAndAgentDocker") .logNotContains("Required context class hudson.FilePath is missing").go(); } diff --git a/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/DockerScriptStepTest.java b/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/DockerScriptStepTest.java index 4df55a8d7..691b0f014 100644 --- a/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/DockerScriptStepTest.java +++ b/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/DockerScriptStepTest.java @@ -46,7 +46,7 @@ public static void setUpAgent() throws Exception { @Test public void dockerGlobalVariableInScript() throws Exception { - DockerTestUtil.assumeDocker(); + DockerTestUtil.assumeDockerJUnit4(); expect("org/jenkinsci/plugins/docker/workflow/declarative/dockerGlobalVariableInScript") .logContains("[Pipeline] { (foo)", "image: ubuntu") diff --git a/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/GlobalConfigTest.java b/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/GlobalConfigTest.java index fb4369d8d..99cdddf60 100644 --- a/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/GlobalConfigTest.java +++ b/src/test/java/org/jenkinsci/plugins/docker/workflow/declarative/GlobalConfigTest.java @@ -28,54 +28,49 @@ import hudson.ExtensionList; import hudson.diagnosis.OldDataMonitor; import java.util.Collections; -import org.junit.Test; -import static org.junit.Assert.*; -import org.junit.Rule; -import org.junit.runners.model.Statement; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import org.jvnet.hudson.test.Issue; -import org.jvnet.hudson.test.RestartableJenkinsRule; +import org.jvnet.hudson.test.junit.jupiter.JenkinsSessionExtension; import org.jvnet.hudson.test.recipes.LocalData; -public class GlobalConfigTest { +class GlobalConfigTest { - @Rule - public RestartableJenkinsRule story = new RestartableJenkinsRule(); + @RegisterExtension + private final JenkinsSessionExtension story = new JenkinsSessionExtension(); @Issue("JENKINS-42027") @Test - public void globalConfigPersists() throws Exception { - story.addStep(new Statement() { - @Override - public void evaluate() throws Throwable { + void globalConfigPersists() throws Throwable { + story.then(r -> { GlobalConfig.get().setDockerLabel("config_docker"); GlobalConfig.get().save(); } - }); + ); - story.addStep(new Statement() { - @Override - public void evaluate() throws Throwable { - assertEquals("config_docker", GlobalConfig.get().getDockerLabel()); - } - }); + story.then(r -> assertEquals("config_docker", GlobalConfig.get().getDockerLabel()) + ); } @Issue("https://github.com/jenkinsci/docker-workflow-plugin/pull/202#issuecomment-597156438") @LocalData @Test - public void oldPackages() { + void oldPackages() throws Throwable { story.then(r -> { - assertEquals("GlobalConfig is translated", "docker", GlobalConfig.get().getDockerLabel()); + assertEquals("docker", GlobalConfig.get().getDockerLabel(), "GlobalConfig is translated"); assertEquals("https://myreg/", GlobalConfig.get().getRegistry().getUrl()); assertEquals("myreg", GlobalConfig.get().getRegistry().getCredentialsId()); Folder d = r.jenkins.getItemByFullName("d", Folder.class); assertNotNull(d); FolderConfig c = d.getProperties().get(FolderConfig.class); - assertNotNull("FolderConfig is translated", c); + assertNotNull(c, "FolderConfig is translated"); assertEquals("dokker", c.getDockerLabel()); assertEquals("https://yourreg/", c.getRegistry().getUrl()); assertEquals("yourreg", c.getRegistry().getCredentialsId()); - assertEquals("there is no old data", Collections.emptySet(), ExtensionList.lookupSingleton(OldDataMonitor.class).getData().keySet()); + assertEquals(Collections.emptySet(), ExtensionList.lookupSingleton(OldDataMonitor.class).getData().keySet(), "there is no old data"); }); }