From 1047a2a66c906a41f26d40563d1e4365c4e1157c Mon Sep 17 00:00:00 2001 From: Daniel Beck Date: Wed, 8 Feb 2017 22:11:30 +0100 Subject: [PATCH 01/19] Add Windows build back This will allow PRs to resolve failing tests on Windows --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 1a67c6c585..73bcc7ae51 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -19,7 +19,7 @@ properties([[$class: 'jenkins.model.BuildDiscarderProperty', strategy: [$class: artifactNumToKeepStr: '20']]]) // see https://github.com/jenkins-infra/documentation/blob/master/ci.adoc for information on what node types are available -def buildTypes = ['Linux'] // TODO add 'Windows' +def buildTypes = ['Linux', 'Windows'] def builds = [:] for(i = 0; i < buildTypes.size(); i++) { From d416d8a71e8b6677dc9832652c031b3470f755cd Mon Sep 17 00:00:00 2001 From: Alex Earl Date: Fri, 10 Feb 2017 13:35:14 -0700 Subject: [PATCH 02/19] Fix some tests on Windows. --- .../groovy/hudson/util/TextFileTest.groovy | 6 +- .../cli/AbstractBuildRangeCommand2Test.java | 4 +- .../cli/AbstractBuildRangeCommandTest.java | 80 +++++++++---------- .../java/hudson/cli/ConsoleCommandTest.java | 49 +++++++++--- 4 files changed, 83 insertions(+), 56 deletions(-) diff --git a/test/src/test/groovy/hudson/util/TextFileTest.groovy b/test/src/test/groovy/hudson/util/TextFileTest.groovy index 9347b488a9..0299132fc8 100644 --- a/test/src/test/groovy/hudson/util/TextFileTest.groovy +++ b/test/src/test/groovy/hudson/util/TextFileTest.groovy @@ -44,9 +44,9 @@ class TextFileTest { f.text = getClass().getResource("ascii.txt").text def t = new TextFile(f) - def tail35 = "la, vitae interdum quam rutrum id.\n" - assert t.fastTail(35).equals(tail35) - assert tail35.length()==35 + def tailStr = "la, vitae interdum quam rutrum id." + System.lineSeparator() + assert t.fastTail(tailStr.length()).equals(tailStr) + assert tailStr.length()==(34 + System.lineSeparator().length()) } @Test diff --git a/test/src/test/java/hudson/cli/AbstractBuildRangeCommand2Test.java b/test/src/test/java/hudson/cli/AbstractBuildRangeCommand2Test.java index d2643b2d13..2287fc426a 100644 --- a/test/src/test/java/hudson/cli/AbstractBuildRangeCommand2Test.java +++ b/test/src/test/java/hudson/cli/AbstractBuildRangeCommand2Test.java @@ -106,7 +106,7 @@ public class AbstractBuildRangeCommand2Test { .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs("aProject", "1"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: 1\n")); + assertThat(result.stdout(), containsString("Builds: 1" + System.lineSeparator())); } @Test public void dummyRangeShouldSuccessEvenTheBuildIsStuckInTheQueue() throws Exception { @@ -124,7 +124,7 @@ public class AbstractBuildRangeCommand2Test { .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs("aProject", "1"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: \n")); + assertThat(result.stdout(), containsString("Builds: " + System.lineSeparator())); } } diff --git a/test/src/test/java/hudson/cli/AbstractBuildRangeCommandTest.java b/test/src/test/java/hudson/cli/AbstractBuildRangeCommandTest.java index 50a4cf85cf..cda886fc85 100644 --- a/test/src/test/java/hudson/cli/AbstractBuildRangeCommandTest.java +++ b/test/src/test/java/hudson/cli/AbstractBuildRangeCommandTest.java @@ -119,13 +119,13 @@ public class AbstractBuildRangeCommandTest { .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, String.valueOf(BUILDS+1)); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: \n")); + assertThat(result.stdout(), containsString("Builds: "+System.lineSeparator())); result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, String.valueOf(deleted[0])); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: \n")); + assertThat(result.stdout(), containsString("Builds: "+System.lineSeparator())); } @Test public void dummyRangeNumberSingleShouldSuccess() throws Exception { @@ -134,28 +134,28 @@ public class AbstractBuildRangeCommandTest { .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "1"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: 1\n")); + assertThat(result.stdout(), containsString("Builds: 1"+System.lineSeparator())); // First with plus symbol '+' result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "+1"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: 1\n")); + assertThat(result.stdout(), containsString("Builds: 1"+System.lineSeparator())); // In the middle result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "10"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: 10\n")); + assertThat(result.stdout(), containsString("Builds: 10"+System.lineSeparator())); // In the middle with plus symbol '+' result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "+10"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: 10\n")); + assertThat(result.stdout(), containsString("Builds: 10"+System.lineSeparator())); // Last result = command @@ -163,7 +163,7 @@ public class AbstractBuildRangeCommandTest { .invokeWithArgs(PROJECT_NAME, String.valueOf(BUILDS)); assertThat(result, succeeded()); assertThat(result.stdout(), - containsString(String.format("Builds: %s\n", String.valueOf(BUILDS)))); + containsString(String.format("Builds: %s"+System.lineSeparator(), String.valueOf(BUILDS)))); // Last with the plus symbol '+' result = command @@ -171,7 +171,7 @@ public class AbstractBuildRangeCommandTest { .invokeWithArgs(PROJECT_NAME, '+' + String.valueOf(BUILDS)); assertThat(result, succeeded()); assertThat(result.stdout(), - containsString(String.format("Builds: %s\n", String.valueOf(BUILDS)))); + containsString(String.format("Builds: %s"+System.lineSeparator(), String.valueOf(BUILDS)))); } @Test public void dummyRangeNumberSingleShouldSuccessIfBuildNumberIsZero() throws Exception { @@ -179,13 +179,13 @@ public class AbstractBuildRangeCommandTest { .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "0"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: \n")); + assertThat(result.stdout(), containsString("Builds: "+System.lineSeparator())); result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "+0"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: \n")); + assertThat(result.stdout(), containsString("Builds: "+System.lineSeparator())); } @Test public void dummyRangeNumberSingleShouldFailIfBuildNumberIsNegative() throws Exception { @@ -227,7 +227,7 @@ public class AbstractBuildRangeCommandTest { .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, ""); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: \n")); + assertThat(result.stdout(), containsString("Builds: "+System.lineSeparator())); } @Test public void dummyRangeNumberSingleShouldFailIfBuildNumberIsSpace() throws Exception { @@ -244,7 +244,7 @@ public class AbstractBuildRangeCommandTest { .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, ","); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: \n")); + assertThat(result.stdout(), containsString("Builds: "+System.lineSeparator())); } @Test public void dummyRangeNumberSingleShouldFailIfBuildNumberIsHyphen() throws Exception { @@ -261,40 +261,40 @@ public class AbstractBuildRangeCommandTest { .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "1,2"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: 1,2\n")); + assertThat(result.stdout(), containsString("Builds: 1,2"+System.lineSeparator())); // With plus symbol '+' result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "1,+2,4"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: 1,2,4\n")); + assertThat(result.stdout(), containsString("Builds: 1,2,4"+System.lineSeparator())); // Build specified twice result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "1,1"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: 1,1\n")); + assertThat(result.stdout(), containsString("Builds: 1,1"+System.lineSeparator())); // Build with zero build number result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "0,1,2"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: 1,2\n")); + assertThat(result.stdout(), containsString("Builds: 1,2"+System.lineSeparator())); result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "1,0,2"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: 1,2\n")); + assertThat(result.stdout(), containsString("Builds: 1,2"+System.lineSeparator())); result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "1,2,0"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: 1,2\n")); + assertThat(result.stdout(), containsString("Builds: 1,2"+System.lineSeparator())); } @Test public void dummyRangeNumberMultiShouldSuccessIfSomeBuildDoesNotExist() throws Exception { @@ -302,19 +302,19 @@ public class AbstractBuildRangeCommandTest { .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "1,2,"+deleted[0]); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: 1,2\n")); + assertThat(result.stdout(), containsString("Builds: 1,2"+System.lineSeparator())); result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, String.format("1,%d,%d", deleted[0], deleted[0]+1)); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString(String.format("Builds: 1,%d\n", deleted[0]+1))); + assertThat(result.stdout(), containsString(String.format("Builds: 1,%d"+System.lineSeparator(), deleted[0]+1))); result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, String.format("%d,%d,%d", deleted[0]-1, deleted[0], deleted[0]+1)); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString(String.format("Builds: %d,%d\n", deleted[0]-1, deleted[0]+1))); + assertThat(result.stdout(), containsString(String.format("Builds: %d,%d"+System.lineSeparator(), deleted[0]-1, deleted[0]+1))); } @Test public void dummyRangeNumberMultiShouldFailIfBuildNumberIsNegative() throws Exception { @@ -504,25 +504,25 @@ public class AbstractBuildRangeCommandTest { .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "1-2"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: 1,2\n")); + assertThat(result.stdout(), containsString("Builds: 1,2"+System.lineSeparator())); result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "+1-+2"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: 1,2\n")); + assertThat(result.stdout(), containsString("Builds: 1,2"+System.lineSeparator())); result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "1-1"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: 1\n")); + assertThat(result.stdout(), containsString("Builds: 1"+System.lineSeparator())); result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "+1-+1"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: 1\n")); + assertThat(result.stdout(), containsString("Builds: 1"+System.lineSeparator())); result = command .authorizedTo(Jenkins.READ, Job.READ) @@ -536,49 +536,49 @@ public class AbstractBuildRangeCommandTest { builds += i; next = true; } - assertThat(result.stdout(), containsString("Builds: "+builds+"\n")); + assertThat(result.stdout(), containsString("Builds: "+builds+System.lineSeparator())); result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "+1-+"+deleted[0]); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: "+builds+"\n")); + assertThat(result.stdout(), containsString("Builds: "+builds+System.lineSeparator())); result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "0-1"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: 1\n")); + assertThat(result.stdout(), containsString("Builds: 1"+System.lineSeparator())); result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "+0-+1"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: 1\n")); + assertThat(result.stdout(), containsString("Builds: 1"+System.lineSeparator())); result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "0-2"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: 1,2\n")); + assertThat(result.stdout(), containsString("Builds: 1,2"+System.lineSeparator())); result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "+0-+2"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: 1,2\n")); + assertThat(result.stdout(), containsString("Builds: 1,2"+System.lineSeparator())); result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "0-0"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: \n")); + assertThat(result.stdout(), containsString("Builds: "+System.lineSeparator())); result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "+0-+0"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: \n")); + assertThat(result.stdout(), containsString("Builds: "+System.lineSeparator())); } @Test public void dummyRangeRangeSingleShouldSuccessIfSomeBuildDoesNotExist() throws Exception { @@ -586,19 +586,19 @@ public class AbstractBuildRangeCommandTest { .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, String.format("%d-%d", deleted[0], deleted[0]+1)); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString(String.format("Builds: %d\n", deleted[0] + 1))); + assertThat(result.stdout(), containsString(String.format("Builds: %d"+System.lineSeparator(), deleted[0] + 1))); result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, String.format("%d-%d", deleted[0]-1, deleted[0]+1)); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString(String.format("Builds: %d,%d\n", deleted[0]-1, deleted[0]+1))); + assertThat(result.stdout(), containsString(String.format("Builds: %d,%d"+System.lineSeparator(), deleted[0]-1, deleted[0]+1))); result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, String.format("%d-%d", deleted[0]-1, deleted[0])); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString(String.format("Builds: %d\n", deleted[0]-1))); + assertThat(result.stdout(), containsString(String.format("Builds: %d"+System.lineSeparator(), deleted[0]-1))); } @Test public void dummyRangeRangeSingleShouldFailIfBuildRangeContainsZeroAndNegative() throws Exception { @@ -955,25 +955,25 @@ public class AbstractBuildRangeCommandTest { .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "1-2,3-4"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: 1,2,3,4\n")); + assertThat(result.stdout(), containsString("Builds: 1,2,3,4"+System.lineSeparator())); result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "1-3,3-4"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: 1,2,3,3,4\n")); + assertThat(result.stdout(), containsString("Builds: 1,2,3,3,4"+System.lineSeparator())); result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "1-4,2-3"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: 1,2,3,4,2,3\n")); + assertThat(result.stdout(), containsString("Builds: 1,2,3,4,2,3"+System.lineSeparator())); result = command .authorizedTo(Jenkins.READ, Job.READ) .invokeWithArgs(PROJECT_NAME, "1-2,4-5"); assertThat(result, succeeded()); - assertThat(result.stdout(), containsString("Builds: 1,2,4\n")); + assertThat(result.stdout(), containsString("Builds: 1,2,4"+System.lineSeparator())); } @Extension diff --git a/test/src/test/java/hudson/cli/ConsoleCommandTest.java b/test/src/test/java/hudson/cli/ConsoleCommandTest.java index f48f0fe1ed..80ebec5de5 100644 --- a/test/src/test/java/hudson/cli/ConsoleCommandTest.java +++ b/test/src/test/java/hudson/cli/ConsoleCommandTest.java @@ -24,12 +24,14 @@ package hudson.cli; +import hudson.Functions; import hudson.model.FreeStyleProject; import hudson.model.Item; import hudson.model.Job; import hudson.model.Result; import hudson.model.Run; import hudson.model.labels.LabelAtom; +import hudson.tasks.BatchFile; import hudson.tasks.Shell; import jenkins.model.Jenkins; import org.junit.Before; @@ -156,7 +158,11 @@ public class ConsoleCommandTest { @Test public void consoleShouldSuccessWithLastBuild() throws Exception { FreeStyleProject project = j.createFreeStyleProject("aProject"); - project.getBuildersList().add(new Shell("echo 1")); + if (Functions.isWindows()) { + project.getBuildersList().add(new BatchFile("echo 1")); + } else { + project.getBuildersList().add(new Shell("echo 1")); + } assertThat(project.scheduleBuild2(0).get().getLog(), containsString("echo 1")); final CLICommandInvoker.Result result = command @@ -170,7 +176,11 @@ public class ConsoleCommandTest { @Test public void consoleShouldSuccessWithSpecifiedBuildNumber() throws Exception { FreeStyleProject project = j.createFreeStyleProject("aProject"); - project.getBuildersList().add(new Shell("echo ${BUILD_NUMBER}")); + if (Functions.isWindows()) { + project.getBuildersList().add(new BatchFile("echo %BUILD_NUMBER%")); + } else { + project.getBuildersList().add(new Shell("echo ${BUILD_NUMBER}")); + } assertThat(project.scheduleBuild2(0).get().getLog(), containsString("echo 1")); assertThat(project.scheduleBuild2(0).get().getLog(), containsString("echo 2")); assertThat(project.scheduleBuild2(0).get().getLog(), containsString("echo 3")); @@ -184,10 +194,15 @@ public class ConsoleCommandTest { } @Test public void consoleShouldSuccessWithFollow() throws Exception { - FreeStyleProject project = j.createFreeStyleProject("aProject"); - project.getBuildersList().add(new Shell("echo start - ${BUILD_NUMBER}\nsleep 10s\n" - + "echo after sleep - ${BUILD_NUMBER}")); + if(Functions.isWindows()) { + // the ver >NUL is to reset ERRORLEVEL so we don't fail (ping causes the error) + project.getBuildersList().add(new BatchFile("echo start - %BUILD_NUMBER%\r\n" + + "ping 1.1.1.1 -n 1 -w 10000 >NUL\r\nver >NUL\r\necho after sleep - %BUILD_NUMBER%")); + } else { + project.getBuildersList().add(new Shell("echo start - ${BUILD_NUMBER}\nsleep 10s\n" + + "echo after sleep - ${BUILD_NUMBER}")); + } if (!project.scheduleBuild(0)) { fail("Job wasn't scheduled properly"); } @@ -229,14 +244,18 @@ public class ConsoleCommandTest { @Test public void consoleShouldSuccessWithLastNLines() throws Exception { FreeStyleProject project = j.createFreeStyleProject("aProject"); - project.getBuildersList().add(new Shell("echo 1\necho 2\necho 3\necho 4\necho 5")); + if(Functions.isWindows()) { + project.getBuildersList().add(new BatchFile("echo 1\r\necho 2\r\necho 3\r\necho 4\r\necho 5")); + } else { + project.getBuildersList().add(new Shell("echo 1\necho 2\necho 3\necho 4\necho 5")); + } project.scheduleBuild2(0).get(); assertThat(project.getBuildByNumber(1).getLog(), containsString("echo 1")); assertThat(project.getBuildByNumber(1).getLog(), containsString("echo 5")); final CLICommandInvoker.Result result = command .authorizedTo(Jenkins.READ, Job.READ, Item.BUILD) - .invokeWithArgs("aProject", "1", "-n", "4"); + .invokeWithArgs("aProject", "1", "-n", Functions.isWindows() ? "5" : "4"); assertThat(result, succeeded()); assertThat(result.stdout(), not(containsString("echo 1"))); @@ -246,9 +265,17 @@ public class ConsoleCommandTest { @Test public void consoleShouldSuccessWithLastNLinesAndFollow() throws Exception { FreeStyleProject project = j.createFreeStyleProject("aProject"); - project.getBuildersList().add(new Shell("echo 1\necho 2\necho 3\necho 4\necho 5\n" - + "sleep 10s\n" - + "echo 6\necho 7\necho 8\necho 9")); + if (Functions.isWindows()) { + // the ver >NUL is to reset ERRORLEVEL so we don't fail (ping causes the error) + project.getBuildersList().add(new BatchFile("echo 1\r\necho 2\r\necho 3\r\necho 4\r\necho 5\r\n" + + "ping 1.1.1.1 -n 1 -w 10000 >NUL\r\nver >NUL\r\n" + + "echo 6\r\necho 7\r\necho 8\r\necho 9")); + + } else { + project.getBuildersList().add(new Shell("echo 1\necho 2\necho 3\necho 4\necho 5\n" + + "sleep 10s\n" + + "echo 6\necho 7\necho 8\necho 9")); + } if (!project.scheduleBuild(0)) { fail("Job wasn't scheduled properly"); @@ -270,7 +297,7 @@ public class ConsoleCommandTest { CLICommandInvoker.Result result = command .authorizedTo(Jenkins.READ, Job.READ, Item.BUILD) - .invokeWithArgs("aProject", "1", "-f", "-n", "4"); + .invokeWithArgs("aProject", "1", "-f", "-n", Functions.isWindows() ? "5" : "4"); assertThat(result, succeeded()); assertThat(result.stdout(), not(containsString("echo 1"))); From a5c6a5c688ac5828088a2a2394dc8004e5df5c76 Mon Sep 17 00:00:00 2001 From: Alex Earl Date: Fri, 10 Feb 2017 18:48:07 -0700 Subject: [PATCH 03/19] More fixes for Windows --- .../java/hudson/cli/ReloadJobCommandTest.java | 46 +++++++++++-------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/test/src/test/java/hudson/cli/ReloadJobCommandTest.java b/test/src/test/java/hudson/cli/ReloadJobCommandTest.java index 2e21dc0b91..a012090070 100644 --- a/test/src/test/java/hudson/cli/ReloadJobCommandTest.java +++ b/test/src/test/java/hudson/cli/ReloadJobCommandTest.java @@ -25,8 +25,11 @@ package hudson.cli; import hudson.FilePath; +import hudson.Functions; import hudson.model.FreeStyleProject; import hudson.model.Job; +import hudson.tasks.BatchFile; +import hudson.tasks.Builder; import hudson.tasks.Shell; import jenkins.model.Jenkins; import org.junit.Before; @@ -58,7 +61,7 @@ public class ReloadJobCommandTest { @Test public void reloadJobShouldFailWithoutJobConfigurePermission() throws Exception { FreeStyleProject project = j.createFreeStyleProject("aProject"); - project.getBuildersList().add(new Shell("echo 1")); + project.getBuildersList().add(createScriptBuilder("echo 1")); assertThat(project.scheduleBuild2(0).get().getLog(), containsString("echo 1")); changeProjectOnTheDisc(project, "echo 1", "echo 2"); @@ -77,7 +80,7 @@ public class ReloadJobCommandTest { @Test public void reloadJobShouldFailWithoutJobReadPermission() throws Exception { FreeStyleProject project = j.createFreeStyleProject("aProject"); - project.getBuildersList().add(new Shell("echo 1")); + project.getBuildersList().add(createScriptBuilder("echo 1")); assertThat(project.scheduleBuild2(0).get().getLog(), containsString("echo 1")); changeProjectOnTheDisc(project, "echo 1", "echo 2"); @@ -96,7 +99,7 @@ public class ReloadJobCommandTest { @Test public void reloadJobShouldSucceed() throws Exception { FreeStyleProject project = j.createFreeStyleProject("aProject"); - project.getBuildersList().add(new Shell("echo 1")); + project.getBuildersList().add(createScriptBuilder("echo 1")); assertThat(project.scheduleBuild2(0).get().getLog(), containsString("echo 1")); @@ -134,13 +137,12 @@ public class ReloadJobCommandTest { } @Test public void reloadJobManyShouldSucceed() throws Exception { - FreeStyleProject project1 = j.createFreeStyleProject("aProject1"); - project1.getBuildersList().add(new Shell("echo 1")); + project1.getBuildersList().add(createScriptBuilder("echo 1")); FreeStyleProject project2 = j.createFreeStyleProject("aProject2"); - project2.getBuildersList().add(new Shell("echo 1")); + project2.getBuildersList().add(createScriptBuilder("echo 1")); FreeStyleProject project3 = j.createFreeStyleProject("aProject3"); - project3.getBuildersList().add(new Shell("echo 1")); + project3.getBuildersList().add(createScriptBuilder("echo 1")); assertThat(project1.scheduleBuild2(0).get().getLog(), containsString("echo 1")); assertThat(project2.scheduleBuild2(0).get().getLog(), containsString("echo 1")); @@ -164,9 +166,9 @@ public class ReloadJobCommandTest { @Test public void reloadJobManyShouldFailIfFirstJobDoesNotExist() throws Exception { FreeStyleProject project1 = j.createFreeStyleProject("aProject1"); - project1.getBuildersList().add(new Shell("echo 1")); + project1.getBuildersList().add(createScriptBuilder("echo 1")); FreeStyleProject project2 = j.createFreeStyleProject("aProject2"); - project2.getBuildersList().add(new Shell("echo 1")); + project2.getBuildersList().add(createScriptBuilder("echo 1")); assertThat(project1.scheduleBuild2(0).get().getLog(), containsString("echo 1")); assertThat(project2.scheduleBuild2(0).get().getLog(), containsString("echo 1")); @@ -190,9 +192,9 @@ public class ReloadJobCommandTest { @Test public void reloadJobManyShouldFailIfMiddleJobDoesNotExist() throws Exception { FreeStyleProject project1 = j.createFreeStyleProject("aProject1"); - project1.getBuildersList().add(new Shell("echo 1")); + project1.getBuildersList().add(createScriptBuilder("echo 1")); FreeStyleProject project2 = j.createFreeStyleProject("aProject2"); - project2.getBuildersList().add(new Shell("echo 1")); + project2.getBuildersList().add(createScriptBuilder("echo 1")); assertThat(project1.scheduleBuild2(0).get().getLog(), containsString("echo 1")); assertThat(project2.scheduleBuild2(0).get().getLog(), containsString("echo 1")); @@ -216,9 +218,9 @@ public class ReloadJobCommandTest { @Test public void reloadJobManyShouldFailIfLastJobDoesNotExist() throws Exception { FreeStyleProject project1 = j.createFreeStyleProject("aProject1"); - project1.getBuildersList().add(new Shell("echo 1")); + project1.getBuildersList().add(createScriptBuilder("echo 1")); FreeStyleProject project2 = j.createFreeStyleProject("aProject2"); - project2.getBuildersList().add(new Shell("echo 1")); + project2.getBuildersList().add(createScriptBuilder("echo 1")); assertThat(project1.scheduleBuild2(0).get().getLog(), containsString("echo 1")); assertThat(project2.scheduleBuild2(0).get().getLog(), containsString("echo 1")); @@ -242,9 +244,9 @@ public class ReloadJobCommandTest { @Test public void reloadJobManyShouldFailIfMoreJobsDoNotExist() throws Exception { FreeStyleProject project1 = j.createFreeStyleProject("aProject1"); - project1.getBuildersList().add(new Shell("echo 1")); + project1.getBuildersList().add(createScriptBuilder("echo 1")); FreeStyleProject project2 = j.createFreeStyleProject("aProject2"); - project2.getBuildersList().add(new Shell("echo 1")); + project2.getBuildersList().add(createScriptBuilder("echo 1")); assertThat(project1.scheduleBuild2(0).get().getLog(), containsString("echo 1")); assertThat(project2.scheduleBuild2(0).get().getLog(), containsString("echo 1")); @@ -267,11 +269,10 @@ public class ReloadJobCommandTest { } @Test public void reloadJobManyShouldSucceedEvenAJobIsSpecifiedTwice() throws Exception { - FreeStyleProject project1 = j.createFreeStyleProject("aProject1"); - project1.getBuildersList().add(new Shell("echo 1")); + project1.getBuildersList().add(createScriptBuilder("echo 1")); FreeStyleProject project2 = j.createFreeStyleProject("aProject2"); - project2.getBuildersList().add(new Shell("echo 1")); + project2.getBuildersList().add(createScriptBuilder("echo 1")); assertThat(project1.scheduleBuild2(0).get().getLog(), containsString("echo 1")); assertThat(project2.scheduleBuild2(0).get().getLog(), containsString("echo 1")); @@ -303,4 +304,13 @@ public class ReloadJobCommandTest { FilePath fp = new FilePath(new File(project.getRootDir()+"/config.xml")); fp.write(fp.readToString().replace(oldstr, newstr), null); } + + /** + * Create a script based builder (either Shell or BatchFile) depending on platform + * @param script the contents of the script to run + * @return A Builder instance of either Shell or BatchFile + */ + private Builder createScriptBuilder(String script) { + return Functions.isWindows() ? new BatchFile(script) : new Shell(script); + } } From d3f7550584c1bce98a26d9a452cb65fd44cce076 Mon Sep 17 00:00:00 2001 From: Alex Earl Date: Fri, 10 Feb 2017 21:41:12 -0700 Subject: [PATCH 04/19] Fix more tests on Windows --- .../cli/SetBuildParameterCommandTest.groovy | 25 +++++++++++++++--- .../java/hudson/cli/ConsoleCommandTest.java | 8 +++--- .../cli/SetBuildDescriptionCommandTest.java | 21 ++++++++++++--- .../hudson/model/ParametersAction2Test.java | 5 +++- .../backwardCompatibility.zip | Bin 6559 -> 12505 bytes 5 files changed, 46 insertions(+), 13 deletions(-) diff --git a/test/src/test/groovy/hudson/cli/SetBuildParameterCommandTest.groovy b/test/src/test/groovy/hudson/cli/SetBuildParameterCommandTest.groovy index 24d44d4624..b082cd03e5 100644 --- a/test/src/test/groovy/hudson/cli/SetBuildParameterCommandTest.groovy +++ b/test/src/test/groovy/hudson/cli/SetBuildParameterCommandTest.groovy @@ -1,5 +1,6 @@ package hudson.cli +import hudson.Functions import hudson.Launcher import hudson.model.AbstractBuild import hudson.model.BuildListener @@ -8,6 +9,8 @@ import hudson.model.ParametersDefinitionProperty import hudson.model.ParameterDefinition import hudson.model.Result import hudson.model.StringParameterDefinition +import hudson.tasks.BatchFile +import hudson.tasks.Builder import hudson.tasks.Shell import jenkins.model.JenkinsLocationConfiguration import org.junit.Assert @@ -39,9 +42,9 @@ public class SetBuildParameterCommandTest { }); List pd = [new StringParameterDefinition("a", ""), new StringParameterDefinition("b", "")]; p.addProperty(new ParametersDefinitionProperty(pd)) - p.buildersList.add(new Shell("java -jar cli.jar set-build-parameter a b")) - p.buildersList.add(new Shell("java -jar cli.jar set-build-parameter a x")) - p.buildersList.add(new Shell("java -jar cli.jar set-build-parameter b y")) + p.buildersList.add(createScriptBuilder("java -jar cli.jar set-build-parameter a b")) + p.buildersList.add(createScriptBuilder("java -jar cli.jar set-build-parameter a x")) + p.buildersList.add(createScriptBuilder("java -jar cli.jar set-build-parameter b y")) def r = [:]; @@ -50,10 +53,24 @@ public class SetBuildParameterCommandTest { assert r.equals(["a":"x", "b":"y"]); - p.buildersList.add(new Shell("BUILD_NUMBER=1 java -jar cli.jar set-build-parameter a b")); + if (Functions.isWindows()) { + p.buildersList.add(new BatchFile("set BUILD_NUMBER=1\r\njava -jar cli.jar set-build-parameter a b")) + } else { + p.buildersList.add(new Shell("BUILD_NUMBER=1 java -jar cli.jar set-build-parameter a b")) + } def b2 = j.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0).get()); r = [:]; b.getAction(ParametersAction.class).parameters.each { v -> r[v.name]=v.value } assert r.equals(["a":"x", "b":"y"]); } + + //TODO: determine if this should be pulled out into JenkinsRule or something + /** + * Create a script based builder (either Shell or BatchFile) depending on platform + * @param script the contents of the script to run + * @return A Builder instance of either Shell or BatchFile + */ + private Builder createScriptBuilder(String script) { + return Functions.isWindows() ? new BatchFile(script) : new Shell(script); + } } diff --git a/test/src/test/java/hudson/cli/ConsoleCommandTest.java b/test/src/test/java/hudson/cli/ConsoleCommandTest.java index 80ebec5de5..3f1ad2bd0e 100644 --- a/test/src/test/java/hudson/cli/ConsoleCommandTest.java +++ b/test/src/test/java/hudson/cli/ConsoleCommandTest.java @@ -195,10 +195,11 @@ public class ConsoleCommandTest { @Test public void consoleShouldSuccessWithFollow() throws Exception { FreeStyleProject project = j.createFreeStyleProject("aProject"); + //TODO: do we really want to sleep for 10 seconds? if(Functions.isWindows()) { // the ver >NUL is to reset ERRORLEVEL so we don't fail (ping causes the error) project.getBuildersList().add(new BatchFile("echo start - %BUILD_NUMBER%\r\n" - + "ping 1.1.1.1 -n 1 -w 10000 >NUL\r\nver >NUL\r\necho after sleep - %BUILD_NUMBER%")); + + "timeout /t 10\r\necho after sleep - %BUILD_NUMBER%")); } else { project.getBuildersList().add(new Shell("echo start - ${BUILD_NUMBER}\nsleep 10s\n" + "echo after sleep - ${BUILD_NUMBER}")); @@ -265,12 +266,11 @@ public class ConsoleCommandTest { @Test public void consoleShouldSuccessWithLastNLinesAndFollow() throws Exception { FreeStyleProject project = j.createFreeStyleProject("aProject"); + //TODO: do we really want to sleep for 10 seconds? if (Functions.isWindows()) { // the ver >NUL is to reset ERRORLEVEL so we don't fail (ping causes the error) project.getBuildersList().add(new BatchFile("echo 1\r\necho 2\r\necho 3\r\necho 4\r\necho 5\r\n" - + "ping 1.1.1.1 -n 1 -w 10000 >NUL\r\nver >NUL\r\n" - + "echo 6\r\necho 7\r\necho 8\r\necho 9")); - + + "timeout /t 10\r\necho 6\r\necho 7\r\necho 8\r\necho 9")); } else { project.getBuildersList().add(new Shell("echo 1\necho 2\necho 3\necho 4\necho 5\n" + "sleep 10s\n" diff --git a/test/src/test/java/hudson/cli/SetBuildDescriptionCommandTest.java b/test/src/test/java/hudson/cli/SetBuildDescriptionCommandTest.java index acc4ec7799..3f2931f1aa 100644 --- a/test/src/test/java/hudson/cli/SetBuildDescriptionCommandTest.java +++ b/test/src/test/java/hudson/cli/SetBuildDescriptionCommandTest.java @@ -25,10 +25,13 @@ package hudson.cli; import hudson.FilePath; +import hudson.Functions; import hudson.model.FreeStyleBuild; import hudson.model.FreeStyleProject; import hudson.model.Job; import hudson.model.Run; +import hudson.tasks.BatchFile; +import hudson.tasks.Builder; import hudson.tasks.Shell; import jenkins.model.Jenkins; import org.junit.Before; @@ -61,7 +64,7 @@ public class SetBuildDescriptionCommandTest { @Test public void setBuildDescriptionShouldFailWithoutJobReadPermission() throws Exception { FreeStyleProject project = j.createFreeStyleProject("aProject"); - project.getBuildersList().add(new Shell("echo 1")); + project.getBuildersList().add(createScriptBuilder("echo 1")); assertThat(project.scheduleBuild2(0).get().getLog(), containsString("echo 1")); final CLICommandInvoker.Result result = command @@ -74,7 +77,7 @@ public class SetBuildDescriptionCommandTest { @Test public void setBuildDescriptionShouldFailWithoutRunUpdatePermission1() throws Exception { FreeStyleProject project = j.createFreeStyleProject("aProject"); - project.getBuildersList().add(new Shell("echo 1")); + project.getBuildersList().add(createScriptBuilder("echo 1")); assertThat(project.scheduleBuild2(0).get().getLog(), containsString("echo 1")); final CLICommandInvoker.Result result = command @@ -87,7 +90,7 @@ public class SetBuildDescriptionCommandTest { @Test public void setBuildDescriptionShouldSucceed() throws Exception { FreeStyleProject project = j.createFreeStyleProject("aProject"); - project.getBuildersList().add(new Shell("echo 1")); + project.getBuildersList().add(createScriptBuilder("echo 1")); FreeStyleBuild build = project.scheduleBuild2(0).get(); assertThat(build.getLog(), containsString("echo 1")); assertThat(build.getDescription(), equalTo(null)); @@ -133,7 +136,7 @@ public class SetBuildDescriptionCommandTest { @Test public void setBuildDescriptionShouldFailIfBuildDoesNotExist() throws Exception { FreeStyleProject project = j.createFreeStyleProject("aProject"); - project.getBuildersList().add(new Shell("echo 1")); + project.getBuildersList().add(createScriptBuilder("echo 1")); assertThat(project.scheduleBuild2(0).get().getLog(), containsString("echo 1")); final CLICommandInvoker.Result result = command @@ -145,4 +148,14 @@ public class SetBuildDescriptionCommandTest { assertThat(result.stderr(), containsString("ERROR: No such build #2")); } + //TODO: determine if this should be pulled out into JenkinsRule or something + /** + * Create a script based builder (either Shell or BatchFile) depending on platform + * @param script the contents of the script to run + * @return A Builder instance of either Shell or BatchFile + */ + private Builder createScriptBuilder(String script) { + return Functions.isWindows() ? new BatchFile(script) : new Shell(script); + } + } diff --git a/test/src/test/java/hudson/model/ParametersAction2Test.java b/test/src/test/java/hudson/model/ParametersAction2Test.java index 32a9d59b8f..0eb8c13995 100644 --- a/test/src/test/java/hudson/model/ParametersAction2Test.java +++ b/test/src/test/java/hudson/model/ParametersAction2Test.java @@ -1,6 +1,8 @@ package hudson.model; +import hudson.Functions; import hudson.Launcher; +import hudson.tasks.BatchFile; import hudson.tasks.Builder; import org.junit.Rule; import org.junit.Test; @@ -67,7 +69,8 @@ public class ParametersAction2Test { public void backwardCompatibility() throws Exception { // Local data contains a parameterized job with two parameters (FOO and BAR) and one build // with pre-fix format (generated with 1.609.3) with FOO, BAR and UNDEF. - FreeStyleProject p = j.jenkins.getItemByFullName("parameterized", FreeStyleProject.class); + FreeStyleProject p = j.jenkins.getItemByFullName(Functions.isWindows() ? "parameterized-windows" : "parameterized", FreeStyleProject.class); + FreeStyleBuild b1 = p.getBuildByNumber(1); ParametersAction pa = b1.getAction(ParametersAction.class); hasParameterWithName(pa, "FOO"); diff --git a/test/src/test/resources/hudson/model/ParametersAction2Test/backwardCompatibility.zip b/test/src/test/resources/hudson/model/ParametersAction2Test/backwardCompatibility.zip index 4148761cddb861e646686ba732fdf8918c7b494b..0fe0cea6ff3243f99dc037c5c58b1e766304ba32 100644 GIT binary patch literal 12505 zcmeHNc{tST7a!Zrk|j$>_I+QnWX)FDM)pM6mn>u7LM2OXLP8WmwnCPqQjD#OOVOn$ zTSSydwj@Qr?~J~)n6dQN{XNgk^Ncg|JoCPv_nh=zP+z%XnXZNT6*}-MUba5AFh@T}AD3W92aE-+>-J>9yFfJ1#lyif5EE(r zLaxmh+WEVSDhN8pko5Y4%j>$2gO`PC0`iC73TaC?_83F$Lp&#|3{8a? zc3f65g7TVMPpKsA(YNVlrO`NBFmCpZuA1Q6TLw?|b&V@0X@7eX$lxh8HY-38_b2= z5(i@|s2}uxOZS##vwJ~sZd??W75Y9>c5kf2hcMOWHW}qS*3g@Gm0ARr2}bmvXS-iL zMYcm+)m`@9PnbW%Gn$Y)9klJBe!&YH`<&KbW7n zywE@avZG`1%@%85IfA`&1k1&JzVwmicz}29E6bBw)Z+=IyMA~dnqNtN)@-T}r7gy_;$M}e$8_-F zJEMS|H6P*(gYO0O@>(63%xd}`a*W?96HeU8KyspZ-Zsn8jhf_%n9~47#LUSe$qTYG zx8xo#4vXYmop7j}X=9lmr_KASpKN)>q*Pz7TbKGtWc&BOm;+`{O)ej?J$``t6Z<=M z_D}j|5f6urxq}^pl#6wnh3oeRG0qiPgz`b|CsI~%m%CYL9n=`Eqq=WCa^6o<3aT@@ zkhMyf1rcG2jtPG@3UjWft&MraW7LqMu6$NFC_mLK_hWGyv?Q2JDGJwqdvFp)1S&=lr6BqI=k zloT=w1icAe0_p_7akaz{2=C_3v-k9HazV17#H7`uQGy0O&#;Sj*#{)D^FX%nPYU zl8XCRC8lX$FDN7!1H;1%#uMCgrL^j$9^ZTR7mvc9I(`({E!k>(0&NY=f(*O0{L;QS z3~5Ao`~P|2w$|-L+frJZH?e!tA|7kEB>1$RzI4oV)^HZCsnO@_dguOdBeS%;+tH=) z6Bjh4Gxcur%-vL8Ncv1?rbF>2vrvFT|H|Cc)8jT(?*}GUVa|SXb+OlFWKt_Ma>_oH zHg@z8CoA;v*d1e&P%B~ebK`s(c`1tK;7Dy_>~QyaU)`64iB5s( zRm3mV?|i&9%yrC>qvZqC!Z~c*k(^cTVBK7wo$d;wpu@eW8GBFJrPHo%Iu(sf38g$T z3M~_T@ds?*%o6#%@PO^liFc$E`=BcpHJ{PO^G8ZycJ!sZmxb|FHp=b>4ehLF_{Z-& zuGM68Yk=KPuOmKs-t|Pj){F0PDkzsiAnVf+-{vlLxApZi_OrEfcf?32h(M9pmBiTu z&>|e5h4{AjK&6y?<0l^d5;QgMgd>lKlDj-CWFeA{c%cO$I>>6`T}lG=aNx|lHTOoP zwl?(dia{>b^o&ZyebpJ=iEo#q6Pu`FVSbA2S57JkWsg}%!<5-e*r&xx54~K7br0nx zQ5Gg|tfDYt8BKt}%O4%op-6b2$y`t$s!l=PdY|Wh6Pn?dD(Je!?uB-x4ew>k82(W{x2K=ov$m#l@%*(1ulSaNh?u`d zw_opgWb?X_{o>fJNy}P;+0S;c29bk0GYy@!($3;p^u4)?higyGl+#!8R8iAS?IG!r z?CzZNu{cvDG-Tb;)*Cr|POE~3`3p@pcdvsIZxBb~)3DE7ovv{60W*dM`6J0Q=Xsrz zq|9GAUl_4;64{@YN!f5Z?Ur-cbW-UAUD9sS>E~McH^)htu6`RkEbVw_X zLlnE;l$eF>m@e-bXC(FEP`|h$#x~zyz?&BD{GPRe-)mLyIKy!%w|DPW*a*W_LIfEt zdwOUxUbh%NmGAHkW>%7~79X*=VKHezNPeRWwxmTiaKp0uVU})wjXew56~v0h2H0P%=vG` z9Jya&*DuALEjlJ-l0*~kckKCBV-LESNhk}|BLrB1cx@4TJRF1k)Df+>zCX;)(MO6L z>|h`eT^sDHf<1V7CjPS>La#Hl#$LB~({-2)J7Q&})zXERKz*eGH0=1xZV*v&?af-F z4)q)X%I+^mHQ`>adauMRfkypFcx0tecfrCVsYRNcKJOm(sg^S97AgV@Q`d_xjGe~e z%yq4?ab-WWF1xFx8<~z;r7VV!ndr?{2sOjUR;EUZ0-+rhGmaFn6+7oC4t@@ft*zD#H5Z?iI7nXO2DFjR1tE~+}_@iP4c6RX&f z*c!Wu_;1$@oQGTWEBJa+LODm@HFbq$&JSn9b56J}Sg91MQI}Gzj@370B<;-Y*=cL3 zBazaU=8*b$>WS&%SD)m#KbZVgvrp;vhp;PTQ!Z=7DscQG&BQO#nwr!q{Y*0EOjy-( zX#o}otHurrntlUVeWKT>r0XC=nefGssalT-Q~fP}7J(Y_fKGQcx2X4?`RvfOMqL-# zs2c)}`bVHqCyM_PCVnTqNh35xD~0M??gHJR!*7<1uj*aRZjOD{FTbP}JQ;b_{iJEw z(cqVrInNBIo|Bcerk$WQmJ&@CBF=lATr|hd8P@A3JYHwd9E2YueqM`vMRfDuLdM6~EIkTXCpyqXd1; zys$#-KIPsI?HU5yQUmmVXm+?P>u|dyY8xF`g=;@I%8rkDEb19J#MfU#A9p}!cg?vj zlNrMxmcd8@FD|LJ2f1D=O4YR#Ev*o3UaNCg9cYM2>Fk>nN-yq|HZ)P-QJYmWy{ib3 zCm~b1TR`uZXkS3kbhC=CTA4@SdGc<7B0UPWD_lgoMavs`nL@e*-zFPBXlV=#4Tj%6 zdGLCHV+gb|HAzOtEd(zYn+7d*i=P6USKlyZ-%e z)W5=8vgntx0q2(6{muvfdOldYv)G^6ab<&M=64VM|1|!=-$QQ@TQ=#P2Z7NuDl`Fa5c>vt`ndUe+1jHg3b;{> z3F~`U^GDRZAnq!TjaQ+jmIk^6ga;rS{Z0TeTu1!TtckVpCpm-z`H=v^1c^9OH$xxU zMF2|M0Jbs2XUuKamv?j!%x$@Wy>O?h;+P;|v|d>i*_{M8G9!?ibG*U@SwF{N!2&VC z3xYBNCRqNh;*SUoKq+IMgZzxC(Rwg0EU>uE!G2zhU}C;i$wy*<5^^bTOH3Xt%=T?z zN@AH+>B3DU3MfHzw5IreD*^hB13;t(nl4=5q0IVIQ;Z84Or@=8UByd2T?;IZN{<`F<*ne-MQEdfeQ3n18wJ+Q|-LhLq=0Mv%~fI-uP5)&AA z*o+CR4cvomVtRDHiwVnIB}UEwn4I>_8mB>thQ%FH@L}<6?~YAjG1@FlT-Mqmqis09%qk<8le|AfQ}t4a|@uigge*s$V(C21Edz z0m}7uz#bJ~1|DL74Vwg>b;S=R5x|Eqe=ZlPIw;Yq;~Or3*a#Bp?2v$Fx@9mtVd;Vd2jzOLF@qr|7Pt)aR^S`(2sAV((U7=~#V+rsfPv>m`r^-kpmW

#qt=lKm$*zQGa~k`z}g%85&;tlr0eaFi%0}eVrsFzr{};z mdcQFesyW1m81HNufzT0@2D&7OA6^4{^FXcxD)4b2KK&0~u`37w literal 6559 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 EH{ba8-~a#s From 39a353d36810bedf7edba7126d5466bbdf44d6c7 Mon Sep 17 00:00:00 2001 From: Alex Earl Date: Sat, 11 Feb 2017 12:23:51 -0700 Subject: [PATCH 05/19] More fixes --- .../test/java/hudson/model/ProjectTest.java | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/test/src/test/java/hudson/model/ProjectTest.java b/test/src/test/java/hudson/model/ProjectTest.java index 86cfe2435f..f1395bf2f6 100644 --- a/test/src/test/java/hudson/model/ProjectTest.java +++ b/test/src/test/java/hudson/model/ProjectTest.java @@ -25,8 +25,10 @@ package hudson.model; import com.gargoylesoftware.htmlunit.HttpMethod; import com.gargoylesoftware.htmlunit.WebRequest; +import hudson.*; import hudson.model.queue.QueueTaskFuture; import hudson.security.AccessDeniedException2; +import hudson.tasks.*; import org.acegisecurity.context.SecurityContextHolder; import hudson.security.HudsonPrivateSecurityRealm; import hudson.security.GlobalMatrixAuthorizationStrategy; @@ -38,9 +40,7 @@ import org.jvnet.hudson.reactor.ReactorException; import org.jvnet.hudson.test.FakeChangeLogSCM; import hudson.scm.SCMRevisionState; import hudson.scm.PollingResult; -import hudson.Launcher; import hudson.Launcher.RemoteLauncher; -import hudson.Util; import hudson.scm.NullSCM; import hudson.scm.SCM; import hudson.model.queue.SubTaskContributor; @@ -62,15 +62,13 @@ import java.io.Serializable; import jenkins.scm.DefaultSCMCheckoutStrategyImpl; import jenkins.scm.SCMCheckoutStrategy; import java.io.File; -import hudson.FilePath; + import hudson.slaves.EnvironmentVariablesNodeProperty; -import hudson.EnvVars; import hudson.model.labels.LabelAtom; import hudson.scm.SCMDescriptor; import hudson.slaves.Cloud; import hudson.slaves.DumbSlave; import hudson.slaves.NodeProvisioner; -import hudson.tasks.Shell; import org.jvnet.hudson.test.TestExtension; import java.util.List; import java.util.ArrayList; @@ -81,9 +79,7 @@ import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.JenkinsRule; import static org.junit.Assert.*; -import hudson.tasks.Fingerprinter; -import hudson.tasks.ArtifactArchiver; -import hudson.tasks.BuildTrigger; + import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; @@ -194,7 +190,8 @@ public class ProjectTest { getFilePath = true; assertNotNull("Project should have any workspace because WorkspaceBrowser find some.", p.getSomeWorkspace()); getFilePath = false; - p.getBuildersList().add(new Shell("echo ahoj > some.log")); + String cmd = "echo ahoj > some.log"; + p.getBuildersList().add(Functions.isWindows() ? new BatchFile(cmd) : new Shell(cmd)); j.buildAndAssertSuccess(p); assertNotNull("Project should has any workspace.", p.getSomeWorkspace()); } @@ -202,7 +199,8 @@ public class ProjectTest { @Test public void testGetSomeBuildWithWorkspace() throws Exception{ FreeStyleProject p = j.createFreeStyleProject("project"); - p.getBuildersList().add(new Shell("echo ahoj > some.log")); + String cmd = "echo ahoj > some.log"; + p.getBuildersList().add(Functions.isWindows() ? new BatchFile(cmd) : new Shell(cmd)); assertNull("Project which has never run should not have any build with workspace.", p.getSomeBuildWithWorkspace()); j.buildAndAssertSuccess(p); assertEquals("Last build should have workspace.", p.getLastBuild(), p.getSomeBuildWithWorkspace()); @@ -213,7 +211,8 @@ public class ProjectTest { @Issue("JENKINS-10450") @Test public void workspaceBrowsing() throws Exception { FreeStyleProject p = j.createFreeStyleProject("project"); - p.getBuildersList().add(new Shell("echo ahoj > some.log")); + String cmd = "echo ahoj > some.log"; + p.getBuildersList().add(Functions.isWindows() ? new BatchFile(cmd) : new Shell(cmd)); j.buildAndAssertSuccess(p); JenkinsRule.WebClient wc = j.createWebClient(); wc.goTo("job/project/ws/some.log", "text/plain"); @@ -360,14 +359,14 @@ public class ProjectTest { @Test public void testGetCauseOfBlockage() throws Exception { FreeStyleProject p = j.createFreeStyleProject("project"); - p.getBuildersList().add(new Shell("sleep 10")); + p.getBuildersList().add(Functions.isWindows() ? new BatchFile("timeout /t 10") : new Shell("sleep 10")); QueueTaskFuture b1 = waitForStart(p); assertInstanceOf("Build can not start because previous build has not finished: " + p.getCauseOfBlockage(), p.getCauseOfBlockage(), BlockedBecauseOfBuildInProgress.class); p.getLastBuild().getExecutor().interrupt(); b1.get(); // wait for it to finish FreeStyleProject downstream = j.createFreeStyleProject("project-downstream"); - downstream.getBuildersList().add(new Shell("sleep 10")); + downstream.getBuildersList().add(Functions.isWindows() ? new BatchFile("timeout /t 10") : new Shell("sleep 10")); p.getPublishersList().add(new BuildTrigger(Collections.singleton(downstream), Result.SUCCESS)); Jenkins.getInstance().rebuildDependencyGraph(); p.setBlockBuildWhenDownstreamBuilding(true); @@ -606,7 +605,8 @@ public class ProjectTest { auth.add(Jenkins.READ, user.getId()); Slave slave = j.createOnlineSlave(); project.setAssignedLabel(slave.getSelfLabel()); - project.getBuildersList().add(new Shell("echo hello > change.log")); + String cmd = "echo hello > change.log"; + project.getBuildersList().add(Functions.isWindows()? new BatchFile(cmd) : new Shell(cmd)); j.buildAndAssertSuccess(project); JenkinsRule.WebClient wc = j.createWebClient().login(user.getId(), "password"); WebRequest request = new WebRequest(new URL(wc.getContextPath() + project.getUrl() + "doWipeOutWorkspace"), HttpMethod.POST); From 757997fcbfd234291451a49cadecf87b2a9f3d97 Mon Sep 17 00:00:00 2001 From: Alex Earl Date: Sat, 11 Feb 2017 21:08:17 -0700 Subject: [PATCH 06/19] More test fixes --- .../hudson/tasks/ArtifactArchiverTest.java | 3 +- .../hudson/tools/InstallerTranslatorTest.java | 34 +++++++++++------- .../fingerprintMigration.zip | Bin 1193 -> 1606 bytes 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/test/src/test/java/hudson/tasks/ArtifactArchiverTest.java b/test/src/test/java/hudson/tasks/ArtifactArchiverTest.java index 9ce04280ae..bd24bd1b26 100644 --- a/test/src/test/java/hudson/tasks/ArtifactArchiverTest.java +++ b/test/src/test/java/hudson/tasks/ArtifactArchiverTest.java @@ -26,6 +26,7 @@ package hudson.tasks; import hudson.AbortException; import hudson.FilePath; +import hudson.Functions; import hudson.Launcher; import hudson.Util; import hudson.model.AbstractBuild; @@ -266,7 +267,7 @@ public class ArtifactArchiverTest { @LocalData @Test public void fingerprintMigration() throws Exception { - FreeStyleProject p = j.jenkins.getItemByFullName("sample", FreeStyleProject.class); + FreeStyleProject p = j.jenkins.getItemByFullName(Functions.isWindows() ? "sample-windows" : "sample", FreeStyleProject.class); assertNotNull(p); String xml = p.getConfigFile().asString(); assertFalse(xml, xml.contains("")); diff --git a/test/src/test/java/hudson/tools/InstallerTranslatorTest.java b/test/src/test/java/hudson/tools/InstallerTranslatorTest.java index d38f780972..5319d4e406 100644 --- a/test/src/test/java/hudson/tools/InstallerTranslatorTest.java +++ b/test/src/test/java/hudson/tools/InstallerTranslatorTest.java @@ -24,6 +24,7 @@ package hudson.tools; +import hudson.Functions; import hudson.model.FreeStyleBuild; import hudson.model.FreeStyleProject; import hudson.model.JDK; @@ -32,6 +33,7 @@ import hudson.slaves.DumbSlave; import hudson.slaves.JNLPLauncher; import hudson.slaves.NodeProperty; import hudson.slaves.RetentionStrategy; +import hudson.tasks.BatchFile; import hudson.tasks.Shell; import hudson.util.StreamTaskListener; import java.nio.charset.Charset; @@ -66,38 +68,40 @@ public class InstallerTranslatorTest { @Issue("JENKINS-17667") @Test public void multipleSlavesAndTools() throws Exception { + String jdk1Path = Functions.isWindows() ? "C:\\jdk1" : "/opt/jdk1"; + String jdk2Path = Functions.isWindows() ? "C:\\jdk2" : "/opt/jdk2"; Node slave1 = r.createSlave(); Node slave2 = r.createSlave(); - JDK jdk1 = new JDK("jdk1", null, Collections.singletonList(new InstallSourceProperty(Collections.singletonList(new CommandInstaller(null, "echo installed jdk1", "/opt/jdk1"))))); - JDK jdk2 = new JDK("jdk2", null, Collections.singletonList(new InstallSourceProperty(Collections.singletonList(new CommandInstaller(null, "echo installed jdk2", "/opt/jdk2"))))); + JDK jdk1 = new JDK("jdk1", null, Collections.singletonList(new InstallSourceProperty(Collections.singletonList(Functions.isWindows() ? new BatchCommandInstaller(null, "echo installed jdk1", jdk1Path) : new CommandInstaller(null, "echo installed jdk1", jdk1Path))))); + JDK jdk2 = new JDK("jdk2", null, Collections.singletonList(new InstallSourceProperty(Collections.singletonList(Functions.isWindows() ? new BatchCommandInstaller(null, "echo installed jdk2", jdk2Path) : new CommandInstaller(null, "echo installed jdk2", jdk2Path))))); r.jenkins.getJDKs().add(jdk1); r.jenkins.getJDKs().add(jdk2); FreeStyleProject p = r.createFreeStyleProject(); p.setJDK(jdk1); - p.getBuildersList().add(new Shell("echo $JAVA_HOME")); + p.getBuildersList().add(Functions.isWindows() ? new BatchFile("echo %JAVA_HOME%") : new Shell("echo $JAVA_HOME")); p.setAssignedNode(slave1); FreeStyleBuild b1 = r.buildAndAssertSuccess(p); r.assertLogContains("installed jdk1", b1); - r.assertLogContains("/opt/jdk1", b1); + r.assertLogContains(jdk1Path, b1); p.setJDK(jdk2); FreeStyleBuild b2 = r.buildAndAssertSuccess(p); r.assertLogContains("installed jdk2", b2); - r.assertLogContains("/opt/jdk2", b2); + r.assertLogContains(jdk2Path, b2); FreeStyleBuild b3 = r.buildAndAssertSuccess(p); // An installer is run for every build, and it is up to a CommandInstaller configuration to do any up-to-date check. r.assertLogContains("installed jdk2", b3); - r.assertLogContains("/opt/jdk2", b3); + r.assertLogContains(jdk2Path, b3); p.setAssignedNode(slave2); FreeStyleBuild b4 = r.buildAndAssertSuccess(p); r.assertLogContains("installed jdk2", b4); - r.assertLogContains("/opt/jdk2", b4); + r.assertLogContains(jdk2Path, b4); p.setJDK(jdk1); FreeStyleBuild b5 = r.buildAndAssertSuccess(p); r.assertLogContains("installed jdk1", b5); - r.assertLogContains("/opt/jdk1", b5); + r.assertLogContains(jdk1Path, b5); FreeStyleBuild b6 = r.buildAndAssertSuccess(p); r.assertLogContains("installed jdk1", b6); - r.assertLogContains("/opt/jdk1", b6); + r.assertLogContains(jdk1Path, b6); } @Issue("JENKINS-26940") @@ -113,7 +117,7 @@ public class InstallerTranslatorTest { FreeStyleProject p = r.createFreeStyleProject(); p.setJDK(jdk); - p.getBuildersList().add(new Shell("echo $JAVA_HOME")); + p.getBuildersList().add(Functions.isWindows() ? new BatchFile("echo %JAVA_HOME%") : new Shell("echo $JAVA_HOME")); FreeStyleBuild b1 = r.buildAndAssertSuccess(p); r.assertLogContains(hudson.tools.Messages.CannotBeInstalled(ci.getDescriptor().getDisplayName(), jdk.getName(), r.jenkins.getDisplayName()), b1); r.assertLogContains(hudson.tools.Messages.CannotBeInstalled(bci.getDescriptor().getDisplayName(), jdk.getName(), r.jenkins.getDisplayName()), b1); @@ -122,8 +126,12 @@ public class InstallerTranslatorTest { @Issue("JENKINS-26940") @Test public void testNoMessageLoggedWhenAnyInstallerFound() throws Exception { - final CommandInstaller ci = new CommandInstaller("wrong1", "echo hello", "/opt/jdk"); - final CommandInstaller ci2 = new CommandInstaller("master", "echo hello", "/opt/jdk2"); + final AbstractCommandInstaller ci = Functions.isWindows() + ? new BatchCommandInstaller("wrong1", "echo hello", "C:\\jdk") + : new CommandInstaller("wrong1", "echo hello", "/opt/jdk"); + final AbstractCommandInstaller ci2 = Functions.isWindows() + ? new BatchCommandInstaller("master", "echo hello", "C:\\jdk2") + : new CommandInstaller("master", "echo hello", "/opt/jdk2"); InstallSourceProperty isp = new InstallSourceProperty(Arrays.asList(ci, ci2)); JDK jdk = new JDK("jdk", null, Collections.singletonList(isp)); @@ -132,7 +140,7 @@ public class InstallerTranslatorTest { FreeStyleProject p = r.createFreeStyleProject(); p.setJDK(jdk); - p.getBuildersList().add(new Shell("echo $JAVA_HOME")); + p.getBuildersList().add(Functions.isWindows() ? new BatchFile("echo %JAVA_HOME%") : new Shell("echo $JAVA_HOME")); FreeStyleBuild b1 = r.buildAndAssertSuccess(p); r.assertLogNotContains(ci.getDescriptor().getDisplayName(), b1); } diff --git a/test/src/test/resources/hudson/tasks/ArtifactArchiverTest/fingerprintMigration.zip b/test/src/test/resources/hudson/tasks/ArtifactArchiverTest/fingerprintMigration.zip index 206560069bec5520c64997a5d89bc81384df5dab..b342cc4f471ec6d502bccd2a25c26781403b46a0 100644 GIT binary patch literal 1606 zcmWIWW@Zs#0D<+X-dBmp*&GaqfjVYvR8?Nd$iN`O!oVPhLq~FcURq|lUPW$BZ?JFvZ3CXY-@_$X zcg+#Y-_BSZV*+&Rjj{;wFBTd?x!Ds{9j9FTcE5j<>T=&-rN;NGYgAl!?b`D`^drBF z*JAO_=Rf;zW->8%dR1n4`(IrBAEVuC&TG9s6aQeJopx7Op?{K2y8}a!dalc>RW%~K zZ{!ZFJJ2MSqQ&^SO|xZ{&9TK6*ET$`XOapmlM`*ZHR z>A$8Y*1nBZxGmD#>zQKBsx%H1zvEM{l=k#_6^W!vUXy0Q1dY0=#63qS8H z+B3PNB-mR=Fk<;H;erVosqfZRzm^XwtD7L4*kWGCCst7Mg@8XNL#kv>fgwEWjc8t;7k0<)vx1CGVSFBur zJOxD*)4!oWxtLycs8tdV*IUxo0Bf9{oOV5y{+9OrP#T5zpvWC+J5Q9(KomMyk5g_ws*p= z*fVDT*X^sBKliHo)Y4~cJJ$PmElRpGS>m*!K*JqR>503v=DRTOX5QevVFBw*uLHXh zxfW{if7IwR)v@q@n9;jOe@9YB_hmf}lPbRxfBXZo{(k=ca>YZR|E6o!@8wRJy=bFh zXU=MeCzCAYPOLSmDHmKKbY1qv(w&!I$ZoK6D*Q6%%er?ra+2+nTvsJ4zfZY+N$XOE z+vf)|8TK8U&KFzs3h&o2WD{9-{S!~QMSS^!D;_+{pfUTSWMkytsDJUg-RIZ-4_v_S z>&)ur`AI9@sJmj-%rNn7UP<4*xSwyi(zfo|osWK(*81Mv;F2&m%l|;!qA5Ffzgb)F zar38aUx((=jISHAt~C}r`KhCaJZTENTl`SE! zmwfYg`+jDtLvdK@uUQi8cPtEb%x^!R7Pny8zI&@AfBxMlJ{lKqyH5=VDL*a~T;V7(Qf$r_FD<#0aBfrDjHe_{hd$7CFeqDg(_z zDpvH7O&6|#mr literal 1193 zcma)6O^?$s5cNVqs8=M;QHAJ<1`vmpNVD3dyP_(fic;+nxy~f<*0C*ru)9Zo8dv@g zSHvWZmzK1GR8ixZH*el}#-7ja_xgl9BIMP#pOeAy>+g?ygw*d7(j!-DWn)V#Eg)t} z=DZl)RN~hULXs2wh`xfcT*>k9<>qMl%%%M(N+@#( zwsEt_z%s*iZAp`OdsRc%0D1x%WQL?1Y?@PHA&EQo8jLwK7>BS8wPjVr1hsZND1By? z9HC|O(F?J7`(d!bFe*POTBXi-qz$W@E#sE11Y{xQ-MV(JgktM6&qa1wf}E&pX`KOD zH6|=Q1pO1&C0pwMq3WP&B4>C}U@O|vlw{r*kgib`Bw_z{%#DJ&5)7<6f;{bRIcnE- zv?xJ{jRRdwRTY(43anJo)3fFD{p8DZ5%nlf#z@*?A6ME%Vufhc)yFfA8>r JhL;f`zX5o?gWv!F From 3d778c15415ab80e15827c93ef99d2147c86529b Mon Sep 17 00:00:00 2001 From: Alex Earl Date: Sat, 11 Feb 2017 22:10:33 -0700 Subject: [PATCH 07/19] Fingerprint tests passing --- .../java/hudson/tasks/FingerprinterTest.java | 28 ++++++++++++++---- .../FingerprinterTest/actionSerialization.zip | Bin 2904 -> 6350 bytes 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/test/src/test/java/hudson/tasks/FingerprinterTest.java b/test/src/test/java/hudson/tasks/FingerprinterTest.java index 4e2de32a92..d26ce52d1e 100644 --- a/test/src/test/java/hudson/tasks/FingerprinterTest.java +++ b/test/src/test/java/hudson/tasks/FingerprinterTest.java @@ -26,6 +26,7 @@ package hudson.tasks; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import hudson.Functions; import hudson.Launcher; import hudson.Util; import hudson.XmlFile; @@ -293,14 +294,18 @@ public class FingerprinterTest { @Issue("JENKINS-17125") @LocalData @Test public void actionSerialization() throws Exception { - FreeStyleProject job = j.jenkins.getItemByFullName("j", FreeStyleProject.class); + FreeStyleProject job = j.jenkins.getItemByFullName(Functions.isWindows() ? "j-windows" : "j", FreeStyleProject.class); assertNotNull(job); FreeStyleBuild build = job.getBuildByNumber(2); assertNotNull(build); Fingerprinter.FingerprintAction action = build.getAction(Fingerprinter.FingerprintAction.class); assertNotNull(action); assertEquals(build, action.getBuild()); - assertEquals("{a=2d5fac981a2e865baf0e15db655c7d63}", action.getRecords().toString()); + if (Functions.isWindows()) { + assertEquals("{a=603bc9e16cc05bdbc5e595969f42e3b8}", action.getRecords().toString()); + } else { + assertEquals("{a=2d5fac981a2e865baf0e15db655c7d63}", action.getRecords().toString()); + } j.assertBuildStatusSuccess(job.scheduleBuild2(0)); job._getRuns().purgeCache(); // force build records to be reloaded build = job.getBuildByNumber(3); @@ -309,7 +314,11 @@ public class FingerprinterTest { action = build.getAction(Fingerprinter.FingerprintAction.class); assertNotNull(action); assertEquals(build, action.getBuild()); - assertEquals("{a=f31efcf9afe30617d6c46b919e702822}", action.getRecords().toString()); + if (Functions.isWindows()) { + assertEquals("{a=a97a39fb51de0eee9fd908174dccc304}", action.getRecords().toString()); + } else { + assertEquals("{a=f31efcf9afe30617d6c46b919e702822}", action.getRecords().toString()); + } } @SuppressWarnings("unchecked") @@ -326,7 +335,8 @@ public class FingerprinterTest { j.assertBuildStatusSuccess(p2.scheduleBuild2(0)); j.assertBuildStatusSuccess(p3.scheduleBuild2(0)); - Fingerprint f = j.jenkins._getFingerprint(Util.getDigestOf(singleContents[0]+"\n")); + Fingerprint f = j.jenkins._getFingerprint(Util.getDigestOf(singleContents[0]+System.lineSeparator())); + assertNotNull(f); assertEquals(3,f.getUsages().size()); j.jenkins.rebuildDependencyGraph(); @@ -373,9 +383,15 @@ public class FingerprinterTest { StringBuilder targets = new StringBuilder(); for (int i = 0; i < contents.length; i++) { if (project instanceof MatrixProject) { - ((MatrixProject)project).getBuildersList().add(new Shell("echo " + contents[i] + " > " + files[i])); + ((MatrixProject)project).getBuildersList().add( + Functions.isWindows() + ? new BatchFile("echo " + contents[i] + "> " + files[i]) + : new Shell("echo " + contents[i] + " > " + files[i])); } else { - ((FreeStyleProject)project).getBuildersList().add(new Shell("echo " + contents[i] + " > " + files[i])); + ((FreeStyleProject)project).getBuildersList().add( + Functions.isWindows() + ? new BatchFile("echo " + contents[i] + "> " + files[i]) + : new Shell("echo " + contents[i] + " > " + files[i])); } targets.append(files[i]).append(','); diff --git a/test/src/test/resources/hudson/tasks/FingerprinterTest/actionSerialization.zip b/test/src/test/resources/hudson/tasks/FingerprinterTest/actionSerialization.zip index b56ba95facbd72008542b7dad70a607f205563b2..f18392194c8c5f0d45f2e34cb6d0a979f985b4ac 100644 GIT binary patch literal 6350 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 From 7143554e6081c2b3f1355fb68b15f3c5f1bfe6f3 Mon Sep 17 00:00:00 2001 From: Alex Earl Date: Sun, 12 Feb 2017 11:25:45 -0700 Subject: [PATCH 08/19] Fix some tests and skip some tests. --- test/src/test/java/hudson/PluginManagerTest.java | 2 ++ test/src/test/java/hudson/ProcStarterTest.java | 7 +++++-- test/src/test/java/hudson/ProcTest.java | 4 ++++ .../test/java/hudson/model/labels/LabelExpressionTest.java | 3 +++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/test/src/test/java/hudson/PluginManagerTest.java b/test/src/test/java/hudson/PluginManagerTest.java index e7bb69de1b..b137b89d5b 100644 --- a/test/src/test/java/hudson/PluginManagerTest.java +++ b/test/src/test/java/hudson/PluginManagerTest.java @@ -47,6 +47,7 @@ import net.sf.json.JSONObject; import org.apache.commons.io.FileUtils; import org.apache.tools.ant.filters.StringInputStream; import static org.junit.Assert.*; +import static org.junit.Assume.assumeFalse; import org.junit.Rule; import org.junit.Test; @@ -453,6 +454,7 @@ public class PluginManagerTest { } @Test public void uploadDependencyResolution() throws Exception { + assumeFalse("TODO: Implement this test for Windows", Functions.isWindows()); PersistedList sites = r.jenkins.getUpdateCenter().getSites(); sites.clear(); URL url = PluginManagerTest.class.getResource("/plugins/upload-test-update-center.json"); diff --git a/test/src/test/java/hudson/ProcStarterTest.java b/test/src/test/java/hudson/ProcStarterTest.java index d88f30f722..901aa7e012 100644 --- a/test/src/test/java/hudson/ProcStarterTest.java +++ b/test/src/test/java/hudson/ProcStarterTest.java @@ -103,7 +103,8 @@ public class ProcStarterTest { @Override public Environment setUp(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException { - Launcher.ProcStarter starter = launcher.launch().cmds("echo", "Hello"); + String[] cmds = Functions.isWindows() ? new String[] { "cmd.exe", "/C", "echo", "Hello" } : new String[] { "echo", "Hello" }; + Launcher.ProcStarter starter = launcher.launch().cmds(cmds); starter.start(); starter.join(); return new Environment() { @@ -148,7 +149,9 @@ public class ProcStarterTest { @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { - Launcher.ProcStarter starter = launcher.launch().cmds("echo", "Hello").pwd(new File("/this/path/doesnt/exist")); + String[] cmds = Functions.isWindows() ? new String[] { "cmd.exe", "/C", "echo", "Hello" } : new String[] { "echo", "Hello" }; + String path = Functions.isWindows() ? "C:\\this\\path\\doesn't\\exist" : "/this/path/doesnt/exist"; + Launcher.ProcStarter starter = launcher.launch().cmds(cmds).pwd(new File(path)); starter.start(); starter.join(); return true; diff --git a/test/src/test/java/hudson/ProcTest.java b/test/src/test/java/hudson/ProcTest.java index c3eebe20a0..4f7133ccff 100644 --- a/test/src/test/java/hudson/ProcTest.java +++ b/test/src/test/java/hudson/ProcTest.java @@ -2,6 +2,7 @@ package hudson; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; +import static org.junit.Assume.assumeFalse; import hudson.Launcher.LocalLauncher; import hudson.Launcher.RemoteLauncher; @@ -37,6 +38,7 @@ public class ProcTest { */ @Test public void remoteProcOutputSync() throws Exception { + assumeFalse("TODO: Implement this test for Windows", Functions.isWindows()); VirtualChannel ch = createSlaveChannel(); // keep the pipe fairly busy @@ -96,11 +98,13 @@ public class ProcTest { @Test public void ioPumpingWithLocalLaunch() throws Exception { + assumeFalse("TODO: Implement this test for Windows", Functions.isWindows()); doIoPumpingTest(new LocalLauncher(new StreamTaskListener(System.out, Charset.defaultCharset()))); } @Test public void ioPumpingWithRemoteLaunch() throws Exception { + assumeFalse("TODO: Implement this test for Windows", Functions.isWindows()); doIoPumpingTest(new RemoteLauncher( new StreamTaskListener(System.out, Charset.defaultCharset()), createSlaveChannel(), true)); diff --git a/test/src/test/java/hudson/model/labels/LabelExpressionTest.java b/test/src/test/java/hudson/model/labels/LabelExpressionTest.java index 057d80d994..e6a2fb45ba 100644 --- a/test/src/test/java/hudson/model/labels/LabelExpressionTest.java +++ b/test/src/test/java/hudson/model/labels/LabelExpressionTest.java @@ -24,8 +24,10 @@ package hudson.model.labels; import static org.junit.Assert.*; +import static org.junit.Assume.assumeFalse; import antlr.ANTLRException; +import hudson.Functions; import hudson.Launcher; import hudson.model.AbstractBuild; import hudson.model.AbstractProject; @@ -189,6 +191,7 @@ public class LabelExpressionTest { @Test public void dataCompatibilityWithHostNameWithWhitespace() throws Exception { + assumeFalse("Windows can't have paths with colons, skipping", Functions.isWindows()); DumbSlave slave = new DumbSlave("abc def (xyz) : test", "dummy", j.createTmpDir().getPath(), "1", Mode.NORMAL, "", j.createComputerLauncher(null), RetentionStrategy.NOOP, Collections.EMPTY_LIST); j.jenkins.addNode(slave); From 3c4186fc018190a96e34ebc9f814c107572ae1f5 Mon Sep 17 00:00:00 2001 From: Alex Earl Date: Sun, 12 Feb 2017 18:41:37 -0700 Subject: [PATCH 09/19] More ignores --- .../hudson/util/SecretRewriterTest.groovy | 4 + .../java/jenkins/model/RunIdMigratorTest.java | 9 + .../java/jenkins/util/VirtualFileTest.java | 4 + .../hudson/model/AbstractProjectTest.groovy | 182 ++++++++++-------- .../test/java/hudson/PluginManagerTest.java | 1 + .../hudson/cli/DeleteBuildsCommandTest.java | 3 + .../src/test/java/hudson/model/QueueTest.java | 8 +- 7 files changed, 135 insertions(+), 76 deletions(-) diff --git a/core/src/test/groovy/hudson/util/SecretRewriterTest.groovy b/core/src/test/groovy/hudson/util/SecretRewriterTest.groovy index b748703ac1..a429bef54e 100644 --- a/core/src/test/groovy/hudson/util/SecretRewriterTest.groovy +++ b/core/src/test/groovy/hudson/util/SecretRewriterTest.groovy @@ -2,6 +2,7 @@ package hudson.util import com.trilead.ssh2.crypto.Base64 import hudson.FilePath +import hudson.Functions import jenkins.security.ConfidentialStoreRule import org.junit.Rule import org.junit.Test @@ -9,6 +10,8 @@ import org.junit.rules.TemporaryFolder import javax.crypto.Cipher +import static org.junit.Assume.assumeFalse + /** * * @@ -77,6 +80,7 @@ class SecretRewriterTest { */ @Test void recursionDetection() { + assumeFalse("Symlinks don't work on Windows very well", Functions.isWindows()) def sw = new SecretRewriter(); def st = StreamTaskListener.fromStdout() diff --git a/core/src/test/java/jenkins/model/RunIdMigratorTest.java b/core/src/test/java/jenkins/model/RunIdMigratorTest.java index f51d0299b8..71a3e47832 100644 --- a/core/src/test/java/jenkins/model/RunIdMigratorTest.java +++ b/core/src/test/java/jenkins/model/RunIdMigratorTest.java @@ -24,6 +24,7 @@ package jenkins.model; +import hudson.Functions; import hudson.Util; import hudson.util.StreamTaskListener; import java.io.File; @@ -38,6 +39,8 @@ import java.util.logging.Level; import org.apache.commons.io.FileUtils; import org.junit.Test; import static org.junit.Assert.*; +import static org.junit.Assume.assumeFalse; + import org.junit.Before; import org.junit.BeforeClass; import org.junit.Rule; @@ -79,6 +82,7 @@ public class RunIdMigratorTest { } @Test public void legacy() throws Exception { + assumeFalse("Symlinks don't work well on Windows", Functions.isWindows()); write("2014-01-02_03-04-05/build.xml", "\n\n ok\n 99\n ok\n"); link("99", "2014-01-02_03-04-05"); link("lastFailedBuild", "-1"); @@ -97,6 +101,7 @@ public class RunIdMigratorTest { } @Test public void reRunMigration() throws Exception { + assumeFalse("Symlinks don't work well on Windows", Functions.isWindows()); write("2014-01-02_03-04-04/build.xml", "\n 98\n"); link("98", "2014-01-02_03-04-04"); write("99/build.xml", "\n\n ok\n 1388649845000\n ok\n"); @@ -108,6 +113,7 @@ public class RunIdMigratorTest { } @Test public void reverseImmediately() throws Exception { + assumeFalse("Symlinks don't work well on Windows", Functions.isWindows()); File root = dir; dir = new File(dir, "jobs/somefolder/jobs/someproject/promotions/OK/builds"); write("99/build.xml", "\n\n ok\n 2014-01-02_03-04-05\n 1388649845000\n ok\n"); @@ -120,6 +126,7 @@ public class RunIdMigratorTest { } @Test public void reverseAfterNewBuilds() throws Exception { + assumeFalse("Symlinks don't work well on Windows", Functions.isWindows()); File root = dir; dir = new File(dir, "jobs/someproject/modules/test$test/builds"); write("1/build.xml", "\n\n ok\n 1388649845000\n ok\n"); @@ -130,6 +137,7 @@ public class RunIdMigratorTest { } @Test public void reverseMatrixAfterNewBuilds() throws Exception { + assumeFalse("Symlinks don't work well on Windows", Functions.isWindows()); File root = dir; dir = new File(dir, "jobs/someproject/Environment=prod/builds"); write("1/build.xml", "\n\n ok\n 1388649845000\n ok\n"); @@ -140,6 +148,7 @@ public class RunIdMigratorTest { } @Test public void reverseMavenAfterNewBuilds() throws Exception { + assumeFalse("Symlinks don't work well on Windows", Functions.isWindows()); File root = dir; dir = new File(dir, "jobs/someproject/test$test/builds"); write("1/build.xml", "\n\n ok\n 1388649845000\n ok\n"); diff --git a/core/src/test/java/jenkins/util/VirtualFileTest.java b/core/src/test/java/jenkins/util/VirtualFileTest.java index 46bfecd8d6..c45f45109c 100644 --- a/core/src/test/java/jenkins/util/VirtualFileTest.java +++ b/core/src/test/java/jenkins/util/VirtualFileTest.java @@ -24,6 +24,7 @@ package jenkins.util; +import hudson.Functions; import hudson.Util; import hudson.model.TaskListener; import java.io.File; @@ -32,6 +33,8 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.junit.Test; import static org.junit.Assert.*; +import static org.junit.Assume.assumeFalse; + import org.junit.Rule; import org.junit.rules.TemporaryFolder; import org.jvnet.hudson.test.Issue; @@ -42,6 +45,7 @@ public class VirtualFileTest { @Issue("SECURITY-162") @Test public void outsideSymlinks() throws Exception { + assumeFalse("Symlinks don't work well on Windows", Functions.isWindows()); File ws = tmp.newFolder("ws"); FileUtils.write(new File(ws, "safe"), "safe"); Util.createSymlink(ws, "safe", "supported", TaskListener.NULL); diff --git a/test/src/test/groovy/hudson/model/AbstractProjectTest.groovy b/test/src/test/groovy/hudson/model/AbstractProjectTest.groovy index 8c50f37f92..3a69232505 100644 --- a/test/src/test/groovy/hudson/model/AbstractProjectTest.groovy +++ b/test/src/test/groovy/hudson/model/AbstractProjectTest.groovy @@ -27,6 +27,7 @@ import com.gargoylesoftware.htmlunit.ElementNotFoundException import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException; import com.gargoylesoftware.htmlunit.HttpMethod import com.gargoylesoftware.htmlunit.WebRequest; +import hudson.tasks.BatchFile; import hudson.tasks.BuildStepMonitor; import hudson.tasks.Recorder; import com.gargoylesoftware.htmlunit.html.HtmlPage @@ -48,9 +49,10 @@ import hudson.triggers.TriggerDescriptor; import hudson.util.StreamTaskListener; import hudson.util.OneShotEvent import jenkins.model.Jenkins -import org.junit.Assert; -import org.jvnet.hudson.test.HudsonTestCase -import org.jvnet.hudson.test.Issue; +import org.junit.Rule +import org.junit.Test; +import org.jvnet.hudson.test.Issue +import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.TestExtension; import org.jvnet.hudson.test.recipes.PresetData; import org.jvnet.hudson.test.recipes.PresetData.DataSet @@ -59,15 +61,22 @@ import org.junit.Assume; import org.jvnet.hudson.test.MockFolder import org.kohsuke.args4j.CmdLineException +import static org.junit.Assert.fail +import static org.junit.Assert.assertEquals; + /** * @author Kohsuke Kawaguchi */ -public class AbstractProjectTest extends HudsonTestCase { +public class AbstractProjectTest { + + @Rule public JenkinsRule j = new JenkinsRule(); + + @Test public void testConfigRoundtrip() { - def project = createFreeStyleProject(); - def l = jenkins.getLabel("foo && bar"); + def project = j.createFreeStyleProject(); + def l = j.jenkins.getLabel("foo && bar"); project.assignedLabel = l; - configRoundtrip((Item) project); + j.configRoundtrip((Item) project); assert l == project.getAssignedLabel(); } @@ -75,9 +84,10 @@ public class AbstractProjectTest extends HudsonTestCase { /** * Tests the workspace deletion. */ + @Test public void testWipeWorkspace() { - def project = createFreeStyleProject(); - project.buildersList.add(new Shell("echo hello")); + def project = j.createFreeStyleProject(); + project.buildersList.add(Functions.isWindows() ? new BatchFile("echo hello") : new Shell("echo hello")); def b = project.scheduleBuild2(0).get(); @@ -91,17 +101,18 @@ public class AbstractProjectTest extends HudsonTestCase { /** * Makes sure that the workspace deletion is protected. */ + @Test @PresetData(DataSet.NO_ANONYMOUS_READACCESS) public void testWipeWorkspaceProtected() { - def project = createFreeStyleProject(); - project.getBuildersList().add(new Shell("echo hello")); + def project = j.createFreeStyleProject(); + project.getBuildersList().add(Functions.isWindows() ? new BatchFile("echo hello") : new Shell("echo hello")); def b = project.scheduleBuild2(0).get(); assert b.getWorkspace().exists(): "Workspace should exist by now"; // make sure that the action link is protected - com.gargoylesoftware.htmlunit.WebClient wc = createWebClient(); + com.gargoylesoftware.htmlunit.WebClient wc = j.createWebClient(); try { wc.getPage(new WebRequest(new URL(wc.getContextPath() + project.getUrl() + "doWipeOutWorkspace"), HttpMethod.POST)); fail("Expected HTTP status code 403") @@ -114,16 +125,17 @@ public class AbstractProjectTest extends HudsonTestCase { * Makes sure that the workspace deletion link is not provided * when the user doesn't have an access. */ + @Test @PresetData(DataSet.ANONYMOUS_READONLY) public void testWipeWorkspaceProtected2() { - ((GlobalMatrixAuthorizationStrategy) jenkins.getAuthorizationStrategy()).add(AbstractProject.WORKSPACE,"anonymous"); + ((GlobalMatrixAuthorizationStrategy) j.jenkins.getAuthorizationStrategy()).add(AbstractProject.WORKSPACE,"anonymous"); // make sure that the deletion is protected in the same way testWipeWorkspaceProtected(); // there shouldn't be any "wipe out workspace" link for anonymous user - def webClient = createWebClient(); - HtmlPage page = webClient.getPage(jenkins.getItem("test0")); + def webClient = j.createWebClient(); + HtmlPage page = webClient.getPage(j.jenkins.getItem("test0")); page = (HtmlPage)page.getAnchorByText("Workspace").click(); try { @@ -138,11 +150,12 @@ public class AbstractProjectTest extends HudsonTestCase { /** * Tests the <optionalBlock @field> round trip behavior by using {@link AbstractProject#concurrentBuild} */ + @Test public void testOptionalBlockDataBindingRoundtrip() { - def p = createFreeStyleProject(); + def p = j.createFreeStyleProject(); [true,false].each { b -> p.concurrentBuild = b; - submit(createWebClient().getPage(p,"configure").getFormByName("config")); + j.submit(j.createWebClient().getPage(p,"configure").getFormByName("config")); assert b==p.isConcurrentBuild(); } } @@ -150,20 +163,21 @@ public class AbstractProjectTest extends HudsonTestCase { /** * Tests round trip configuration of the blockBuildWhenUpstreamBuilding field */ + @Test @Issue("JENKINS-4423") public void testConfiguringBlockBuildWhenUpstreamBuildingRoundtrip() { - def p = createFreeStyleProject(); + def p = j.createFreeStyleProject(); p.blockBuildWhenUpstreamBuilding = false; - def form = createWebClient().getPage(p, "configure").getFormByName("config"); + def form = j.createWebClient().getPage(p, "configure").getFormByName("config"); def input = form.getInputByName("blockBuildWhenUpstreamBuilding"); assert !input.isChecked(): "blockBuildWhenUpstreamBuilding check box is checked."; input.setChecked(true); - submit(form); + j.submit(form); assert p.blockBuildWhenUpstreamBuilding: "blockBuildWhenUpstreamBuilding was not updated from configuration form"; - form = createWebClient().getPage(p, "configure").getFormByName("config"); + form = j.createWebClient().getPage(p, "configure").getFormByName("config"); input = form.getInputByName("blockBuildWhenUpstreamBuilding"); assert input.isChecked(): "blockBuildWhenUpstreamBuilding check box is not checked."; } @@ -172,12 +186,13 @@ public class AbstractProjectTest extends HudsonTestCase { * Unless the concurrent build option is enabled, polling and build should be mutually exclusive * to avoid allocating unnecessary workspaces. */ + @Test @Issue("JENKINS-4202") public void testPollingAndBuildExclusion() { final OneShotEvent sync = new OneShotEvent(); - final FreeStyleProject p = createFreeStyleProject(); - def b1 = buildAndAssertSuccess(p); + final FreeStyleProject p = j.createFreeStyleProject(); + def b1 = j.buildAndAssertSuccess(p); p.scm = new NullSCM() { @Override @@ -217,7 +232,7 @@ public class AbstractProjectTest extends HudsonTestCase { // release the polling sync.signal(); - def b2 = assertBuildStatusSuccess(f); + def b2 = j.assertBuildStatusSuccess(f); // they should have used the same workspace. assert b1.workspace == b2.workspace; @@ -226,11 +241,12 @@ public class AbstractProjectTest extends HudsonTestCase { } } + @Test @Issue("JENKINS-1986") public void testBuildSymlinks() { Assume.assumeFalse("If we're on Windows, don't bother doing this", Functions.isWindows()); - def job = createFreeStyleProject(); + def job = j.createFreeStyleProject(); job.buildersList.add(new Shell("echo \"Build #\$BUILD_NUMBER\"\n")); def build = job.scheduleBuild2(0, new Cause.UserCause()).get(); File lastSuccessful = new File(job.rootDir, "lastSuccessful"), @@ -260,12 +276,13 @@ public class AbstractProjectTest extends HudsonTestCase { assert s.contains("Build #" + buildNumber + "\n") : "link should point to build #$buildNumber, but link was: ${Util.resolveSymlink(file, TaskListener.NULL)}\nand log was:\n$s"; } + @Test @Issue("JENKINS-2543") public void testSymlinkForPostBuildFailure() { Assume.assumeFalse("If we're on Windows, don't bother doing this", Functions.isWindows()); // Links should be updated after post-build actions when final build result is known - def job = createFreeStyleProject(); + def job = j.createFreeStyleProject(); job.buildersList.add(new Shell("echo \"Build #\$BUILD_NUMBER\"\n")); def build = job.scheduleBuild2(0, new Cause.UserCause()).get(); assert Result.SUCCESS == build.result; @@ -284,25 +301,27 @@ public class AbstractProjectTest extends HudsonTestCase { } /* TODO too slow, seems capable of causing testWorkspaceLock to time out: + @Test @Issue("JENKINS-15156") public void testGetBuildAfterGC() { - FreeStyleProject job = createFreeStyleProject(); + FreeStyleProject job = j.createFreeStyleProject(); job.scheduleBuild2(0, new Cause.UserIdCause()).get(); - jenkins.queue.clearLeftItems(); + j.jenkins.queue.clearLeftItems(); MemoryAssert.assertGC(new WeakReference(job.getLastBuild())); assert job.lastBuild != null; } */ + @Test @Issue("JENKINS-17137") public void testExternalBuildDirectorySymlinks() { - // TODO when using JUnit 4 add: Assume.assumeFalse(Functions.isWindows()); // symlinks may not be available - def form = createWebClient().goTo("configure").getFormByName("config"); - def builds = createTmpDir(); + Assume.assumeFalse(Functions.isWindows()); // symlinks may not be available + def form = j.createWebClient().goTo("configure").getFormByName("config"); + def builds = j.createTmpDir(); form.getInputByName("_.rawBuildsDir").valueAttribute = builds.toString() + "/\${ITEM_FULL_NAME}"; - submit(form); + j.submit(form); assert builds.toString() + "/\${ITEM_FULL_NAME}" == jenkins.getRawBuildsDir(); - def p = jenkins.createProject(MockFolder.class, "d").createProject(FreeStyleProject.class, "p"); + def p = j.jenkins.createProject(MockFolder.class, "d").createProject(FreeStyleProject.class, "p"); def b1 = p.scheduleBuild2(0).get(); def link = new File(p.rootDir, "lastStable"); assert link.exists(); @@ -325,14 +344,15 @@ public class AbstractProjectTest extends HudsonTestCase { } } + @Test @Issue("JENKINS-17138") public void testExternalBuildDirectoryRenameDelete() { - def form = createWebClient().goTo("configure").getFormByName("config"); - def builds = createTmpDir(); + def form = j.createWebClient().goTo("configure").getFormByName("config"); + def builds = j.createTmpDir(); form.getInputByName("_.rawBuildsDir").setValueAttribute(builds.toString() + "/\${ITEM_FULL_NAME}"); - submit(form); - assert builds.toString() + "/\${ITEM_FULL_NAME}" == jenkins.rawBuildsDir; - def p = jenkins.createProject(MockFolder.class, "d").createProject(FreeStyleProject.class, "prj"); + j.submit(form); + assert builds.toString() + "/\${ITEM_FULL_NAME}" == j.jenkins.rawBuildsDir; + def p = j.jenkins.createProject(MockFolder.class, "d").createProject(FreeStyleProject.class, "prj"); def b = p.scheduleBuild2(0).get(); def oldBuildDir = new File(builds, "d/prj"); assert new File(oldBuildDir, b.id) == b.rootDir; @@ -345,30 +365,32 @@ public class AbstractProjectTest extends HudsonTestCase { assert !b.rootDir.isDirectory(); } + @Test @Issue("JENKINS-18678") public void testRenameJobLostBuilds() throws Exception { - def p = createFreeStyleProject("initial"); - assertBuildStatusSuccess(p.scheduleBuild2(0)); + def p = j.createFreeStyleProject("initial"); + j.assertBuildStatusSuccess(p.scheduleBuild2(0)); assertEquals(1, p.getBuilds().size()); p.renameTo("edited"); p._getRuns().purgeCache(); assertEquals(1, p.getBuilds().size()); - def d = jenkins.createProject(MockFolder.class, "d"); + def d = j.jenkins.createProject(MockFolder.class, "d"); Items.move(p, d); - assertEquals(p, jenkins.getItemByFullName("d/edited")); + assertEquals(p, j.jenkins.getItemByFullName("d/edited")); p._getRuns().purgeCache(); assertEquals(1, p.getBuilds().size()); d.renameTo("d2"); - p = jenkins.getItemByFullName("d2/edited"); + p = j.jenkins.getItemByFullName("d2/edited"); p._getRuns().purgeCache(); assertEquals(1, p.getBuilds().size()); } + @Test @Issue("JENKINS-17575") public void testDeleteRedirect() { - createFreeStyleProject("j1"); + j.createFreeStyleProject("j1"); assert "" == deleteRedirectTarget("job/j1"); - createFreeStyleProject("j2"); + j.createFreeStyleProject("j2"); Jenkins.getInstance().addView(new AllView("v1")); assert "view/v1/" == deleteRedirectTarget("view/v1/job/j2"); MockFolder d = Jenkins.getInstance().createProject(MockFolder.class, "d"); @@ -381,19 +403,20 @@ public class AbstractProjectTest extends HudsonTestCase { } private String deleteRedirectTarget(String job) { - def wc = createWebClient(); + def wc = j.createWebClient(); String base = wc.getContextPath(); String loc = wc.getPage(wc.addCrumb(new WebRequest(new URL(base + job + "/doDelete"), HttpMethod.POST))).getUrl().toString(); assert loc.startsWith(base): loc; return loc.substring(base.length()); } + @Test @Issue("JENKINS-18407") public void testQueueSuccessBehavior() { // prevent any builds to test the behaviour - jenkins.numExecutors = 0; + j.jenkins.numExecutors = 0; - def p = createFreeStyleProject() + def p = j.createFreeStyleProject() def f = p.scheduleBuild2(0) assert f!=null; def g = p.scheduleBuild2(0) @@ -406,26 +429,27 @@ public class AbstractProjectTest extends HudsonTestCase { /** * Do the same as {@link #testQueueSuccessBehavior()} but over HTTP */ + @Test @Issue("JENKINS-18407") public void testQueueSuccessBehaviorOverHTTP() { // prevent any builds to test the behaviour - jenkins.numExecutors = 0; + j.jenkins.numExecutors = 0; - def p = createFreeStyleProject() - def wc = createWebClient(); + def p = j.createFreeStyleProject() + def wc = j.createWebClient(); - def rsp = wc.getPage("${getURL()}${p.url}build").webResponse + def rsp = wc.getPage("${j.getURL()}${p.url}build").webResponse assert rsp.statusCode==201; assert rsp.getResponseHeaderValue("Location")!=null; - def rsp2 = wc.getPage("${getURL()}${p.url}build").webResponse + def rsp2 = wc.getPage("${j.getURL()}${p.url}build").webResponse assert rsp2.statusCode==201; assert rsp.getResponseHeaderValue("Location")==rsp2.getResponseHeaderValue("Location") p.makeDisabled(true) try { - wc.getPage("${getURL()}${p.url}build") + wc.getPage("${j.getURL()}${p.url}build") fail(); } catch (FailingHttpStatusCodeException e) { // request should fail @@ -436,51 +460,56 @@ public class AbstractProjectTest extends HudsonTestCase { * We used to store {@link AbstractProject#triggers} as {@link Vector}, so make sure * we can still read back the configuration from that. */ + @Test public void testVectorTriggers() { - AbstractProject j = jenkins.createProjectFromXML("foo", getClass().getResourceAsStream("AbstractProjectTest/vectorTriggers.xml")) - assert j.triggers().size()==1 - def t = j.triggers()[0] + AbstractProject p = j.jenkins.createProjectFromXML("foo", getClass().getResourceAsStream("AbstractProjectTest/vectorTriggers.xml")) + assert p.triggers().size()==1 + def t = p.triggers()[0] assert t.class==SCMTrigger.class; assert t.spec=="*/10 * * * *" } + @Test @Issue("JENKINS-18813") public void testRemoveTrigger() { - AbstractProject j = jenkins.createProjectFromXML("foo", getClass().getResourceAsStream("AbstractProjectTest/vectorTriggers.xml")) + AbstractProject p = j.jenkins.createProjectFromXML("foo", getClass().getResourceAsStream("AbstractProjectTest/vectorTriggers.xml")) - TriggerDescriptor SCM_TRIGGER_DESCRIPTOR = Hudson.instance.getDescriptorOrDie(SCMTrigger.class) - j.removeTrigger(SCM_TRIGGER_DESCRIPTOR); - assert j.triggers().size()==0 + TriggerDescriptor SCM_TRIGGER_DESCRIPTOR = j.jenkins.getDescriptorOrDie(SCMTrigger.class) + p.removeTrigger(SCM_TRIGGER_DESCRIPTOR); + assert p.triggers().size()==0 } + @Test @Issue("JENKINS-18813") public void testAddTriggerSameType() { - AbstractProject j = jenkins.createProjectFromXML("foo", getClass().getResourceAsStream("AbstractProjectTest/vectorTriggers.xml")) + AbstractProject p = j.jenkins.createProjectFromXML("foo", getClass().getResourceAsStream("AbstractProjectTest/vectorTriggers.xml")) def newTrigger = new SCMTrigger("H/5 * * * *") - j.addTrigger(newTrigger); + p.addTrigger(newTrigger); - assert j.triggers().size()==1 - def t = j.triggers()[0] + assert p.triggers().size()==1 + def t = p.triggers()[0] assert t.class==SCMTrigger.class; assert t.spec=="H/5 * * * *" } + @Test @Issue("JENKINS-18813") public void testAddTriggerDifferentType() { - AbstractProject j = jenkins.createProjectFromXML("foo", getClass().getResourceAsStream("AbstractProjectTest/vectorTriggers.xml")) + AbstractProject p = j.jenkins.createProjectFromXML("foo", getClass().getResourceAsStream("AbstractProjectTest/vectorTriggers.xml")) def newTrigger = new TimerTrigger("20 * * * *") - j.addTrigger(newTrigger); + p.addTrigger(newTrigger); - assert j.triggers().size()==2 - def t = j.triggers()[1] + assert p.triggers().size()==2 + def t = p.triggers()[1] assert t == newTrigger } + @Test @Issue("JENKINS-10615") public void testWorkspaceLock() { - def p = createFreeStyleProject() + def p = j.createFreeStyleProject() p.concurrentBuild = true; def e1 = new OneShotEvent(), e2=new OneShotEvent() def done = new OneShotEvent() @@ -522,9 +551,10 @@ public class AbstractProjectTest extends HudsonTestCase { /** * Trying to POST to config.xml by a different job type should fail. */ + @Test public void testConfigDotXmlSubmissionToDifferentType() { - jenkins.crumbIssuer = null - def p = createFreeStyleProject() + j.jenkins.crumbIssuer = null + def p = j.createFreeStyleProject() HttpURLConnection con = postConfigDotXml(p, "") @@ -542,7 +572,7 @@ public class AbstractProjectTest extends HudsonTestCase { } private HttpURLConnection postConfigDotXml(FreeStyleProject p, String xml) { - HttpURLConnection con = new URL(getURL(), "job/${p.name}/config.xml").openConnection() + HttpURLConnection con = new URL(j.getURL(), "job/${p.name}/config.xml").openConnection() con.requestMethod = "POST" con.setRequestProperty("Content-Type", "application/xml") con.doOutput = true @@ -552,13 +582,15 @@ public class AbstractProjectTest extends HudsonTestCase { return con } + @Test @Issue("JENKINS-27549") public void testLoadingWithNPEOnTriggerStart() { - AbstractProject project = jenkins.createProjectFromXML("foo", getClass().getResourceAsStream("AbstractProjectTest/npeTrigger.xml")) + AbstractProject project = j.jenkins.createProjectFromXML("foo", getClass().getResourceAsStream("AbstractProjectTest/npeTrigger.xml")) assert project.triggers().size() == 1 } + @Test @Issue("JENKINS-30742") public void testResolveForCLI() { try { @@ -568,7 +600,7 @@ public class AbstractProjectTest extends HudsonTestCase { assert e.getMessage().contentEquals("No such job \u2018never_created\u2019 exists."); } - AbstractProject project = jenkins.createProject(FreeStyleProject.class, "never_created"); + AbstractProject project = j.jenkins.createProject(FreeStyleProject.class, "never_created"); try { AbstractProject not_found = AbstractProject.resolveForCLI("never_created1"); fail("Exception should occur before!"); diff --git a/test/src/test/java/hudson/PluginManagerTest.java b/test/src/test/java/hudson/PluginManagerTest.java index b137b89d5b..5cef4301d2 100644 --- a/test/src/test/java/hudson/PluginManagerTest.java +++ b/test/src/test/java/hudson/PluginManagerTest.java @@ -210,6 +210,7 @@ public class PluginManagerTest { } @Test public void prevalidateConfig() throws Exception { + assumeFalse("TODO: Implement this test on Windows", Functions.isWindows()); PersistedList sites = r.jenkins.getUpdateCenter().getSites(); sites.clear(); URL url = PluginManagerTest.class.getResource("/plugins/tasks-update-center.json"); diff --git a/test/src/test/java/hudson/cli/DeleteBuildsCommandTest.java b/test/src/test/java/hudson/cli/DeleteBuildsCommandTest.java index 59d338c2d6..0b111edd87 100644 --- a/test/src/test/java/hudson/cli/DeleteBuildsCommandTest.java +++ b/test/src/test/java/hudson/cli/DeleteBuildsCommandTest.java @@ -24,6 +24,7 @@ package hudson.cli; +import hudson.Functions; import hudson.model.ExecutorTest; import hudson.model.FreeStyleProject; import hudson.model.Job; @@ -43,6 +44,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; +import static org.junit.Assume.assumeFalse; /** * @author pjanouse @@ -135,6 +137,7 @@ public class DeleteBuildsCommandTest { } @Test public void deleteBuildsShouldSuccessEvenTheBuildIsRunning() throws Exception { + assumeFalse("You can't delete files that are in use on Windows", Functions.isWindows()); FreeStyleProject project = j.createFreeStyleProject("aProject"); ExecutorTest.startBlockingBuild(project); assertThat(((FreeStyleProject) j.jenkins.getItem("aProject")).getBuilds(), hasSize(1)); diff --git a/test/src/test/java/hudson/model/QueueTest.java b/test/src/test/java/hudson/model/QueueTest.java index 3370145f9f..7b7329e581 100644 --- a/test/src/test/java/hudson/model/QueueTest.java +++ b/test/src/test/java/hudson/model/QueueTest.java @@ -30,6 +30,7 @@ import com.gargoylesoftware.htmlunit.html.HtmlForm; import com.gargoylesoftware.htmlunit.html.HtmlFormUtil; import com.gargoylesoftware.htmlunit.html.HtmlPage; import com.gargoylesoftware.htmlunit.xml.XmlPage; +import hudson.Functions; import hudson.Launcher; import hudson.XmlFile; import hudson.matrix.Axis; @@ -62,6 +63,7 @@ import hudson.slaves.DummyCloudImpl; import hudson.slaves.NodeProperty; import hudson.slaves.NodePropertyDescriptor; import hudson.slaves.NodeProvisionerRule; +import hudson.tasks.BatchFile; import hudson.tasks.BuildTrigger; import hudson.tasks.Shell; import hudson.triggers.SCMTrigger.SCMTriggerCause; @@ -378,7 +380,11 @@ public class QueueTest { m.addProperty(new ParametersDefinitionProperty( new StringParameterDefinition("FOO","value") )); - m.getBuildersList().add(new Shell("sleep 3")); + if (Functions.isWindows()) { + m.getBuildersList().add(new BatchFile("timeout /t 3")); + } else { + m.getBuildersList().add(new Shell("sleep 3")); + } m.setAxes(new AxisList(new TextAxis("DoesntMatter", "aaa","bbb"))); List> futures = new ArrayList>(); From 251a2ea09c50a94a39382b9f63f9d54379957f17 Mon Sep 17 00:00:00 2001 From: Alex Earl Date: Sun, 12 Feb 2017 20:56:48 -0700 Subject: [PATCH 10/19] Fix missing "j." before jenkins --- test/src/test/groovy/hudson/model/AbstractProjectTest.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/src/test/groovy/hudson/model/AbstractProjectTest.groovy b/test/src/test/groovy/hudson/model/AbstractProjectTest.groovy index 3a69232505..55294aa0c5 100644 --- a/test/src/test/groovy/hudson/model/AbstractProjectTest.groovy +++ b/test/src/test/groovy/hudson/model/AbstractProjectTest.groovy @@ -320,7 +320,7 @@ public class AbstractProjectTest { def builds = j.createTmpDir(); form.getInputByName("_.rawBuildsDir").valueAttribute = builds.toString() + "/\${ITEM_FULL_NAME}"; j.submit(form); - assert builds.toString() + "/\${ITEM_FULL_NAME}" == jenkins.getRawBuildsDir(); + assert builds.toString() + "/\${ITEM_FULL_NAME}" == j.jenkins.getRawBuildsDir(); def p = j.jenkins.createProject(MockFolder.class, "d").createProject(FreeStyleProject.class, "p"); def b1 = p.scheduleBuild2(0).get(); def link = new File(p.rootDir, "lastStable"); From 23d374687c3e4f8b7be50eb9e1f17538ed95149b Mon Sep 17 00:00:00 2001 From: Alex Earl Date: Mon, 13 Feb 2017 08:35:19 -0700 Subject: [PATCH 11/19] Try /nobreak for timeout command. --- .../test/java/hudson/cli/AbstractBuildRangeCommand2Test.java | 4 +++- test/src/test/java/hudson/cli/ConsoleCommandTest.java | 5 ++--- test/src/test/java/hudson/model/ProjectTest.java | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/test/src/test/java/hudson/cli/AbstractBuildRangeCommand2Test.java b/test/src/test/java/hudson/cli/AbstractBuildRangeCommand2Test.java index 2287fc426a..91d67efb49 100644 --- a/test/src/test/java/hudson/cli/AbstractBuildRangeCommand2Test.java +++ b/test/src/test/java/hudson/cli/AbstractBuildRangeCommand2Test.java @@ -25,10 +25,12 @@ package hudson.cli; import hudson.Extension; +import hudson.Functions; import hudson.model.AbstractBuild; import hudson.model.FreeStyleProject; import hudson.model.Job; import hudson.model.labels.LabelAtom; +import hudson.tasks.BatchFile; import hudson.tasks.Shell; import jenkins.model.Jenkins; import org.junit.Before; @@ -88,7 +90,7 @@ public class AbstractBuildRangeCommand2Test { @Test public void dummyRangeShouldSuccessEvenTheBuildIsRunning() throws Exception { FreeStyleProject project = j.createFreeStyleProject("aProject"); - project.getBuildersList().add(new Shell("echo 1\nsleep 10s")); + project.getBuildersList().add(Functions.isWindows() ? new BatchFile("echo 1\r\ntimeout /t 10 /nobreak") : new Shell("echo 1\nsleep 10s")); assertThat("Job wasn't scheduled properly", project.scheduleBuild(0), equalTo(true)); // Wait until classProject is started (at least 1s) diff --git a/test/src/test/java/hudson/cli/ConsoleCommandTest.java b/test/src/test/java/hudson/cli/ConsoleCommandTest.java index 3f1ad2bd0e..9ef83a768b 100644 --- a/test/src/test/java/hudson/cli/ConsoleCommandTest.java +++ b/test/src/test/java/hudson/cli/ConsoleCommandTest.java @@ -197,9 +197,8 @@ public class ConsoleCommandTest { FreeStyleProject project = j.createFreeStyleProject("aProject"); //TODO: do we really want to sleep for 10 seconds? if(Functions.isWindows()) { - // the ver >NUL is to reset ERRORLEVEL so we don't fail (ping causes the error) project.getBuildersList().add(new BatchFile("echo start - %BUILD_NUMBER%\r\n" - + "timeout /t 10\r\necho after sleep - %BUILD_NUMBER%")); + + "timeout /t 10 /nobreak\r\necho after sleep - %BUILD_NUMBER%")); } else { project.getBuildersList().add(new Shell("echo start - ${BUILD_NUMBER}\nsleep 10s\n" + "echo after sleep - ${BUILD_NUMBER}")); @@ -270,7 +269,7 @@ public class ConsoleCommandTest { if (Functions.isWindows()) { // the ver >NUL is to reset ERRORLEVEL so we don't fail (ping causes the error) project.getBuildersList().add(new BatchFile("echo 1\r\necho 2\r\necho 3\r\necho 4\r\necho 5\r\n" - + "timeout /t 10\r\necho 6\r\necho 7\r\necho 8\r\necho 9")); + + "timeout /t 10 /nobreak\r\necho 6\r\necho 7\r\necho 8\r\necho 9")); } else { project.getBuildersList().add(new Shell("echo 1\necho 2\necho 3\necho 4\necho 5\n" + "sleep 10s\n" diff --git a/test/src/test/java/hudson/model/ProjectTest.java b/test/src/test/java/hudson/model/ProjectTest.java index f1395bf2f6..b0aeb6fc5c 100644 --- a/test/src/test/java/hudson/model/ProjectTest.java +++ b/test/src/test/java/hudson/model/ProjectTest.java @@ -359,14 +359,14 @@ public class ProjectTest { @Test public void testGetCauseOfBlockage() throws Exception { FreeStyleProject p = j.createFreeStyleProject("project"); - p.getBuildersList().add(Functions.isWindows() ? new BatchFile("timeout /t 10") : new Shell("sleep 10")); + p.getBuildersList().add(Functions.isWindows() ? new BatchFile("timeout /t 10 /nobreak") : new Shell("sleep 10")); QueueTaskFuture b1 = waitForStart(p); assertInstanceOf("Build can not start because previous build has not finished: " + p.getCauseOfBlockage(), p.getCauseOfBlockage(), BlockedBecauseOfBuildInProgress.class); p.getLastBuild().getExecutor().interrupt(); b1.get(); // wait for it to finish FreeStyleProject downstream = j.createFreeStyleProject("project-downstream"); - downstream.getBuildersList().add(Functions.isWindows() ? new BatchFile("timeout /t 10") : new Shell("sleep 10")); + downstream.getBuildersList().add(Functions.isWindows() ? new BatchFile("timeout /t 10 /nobreak") : new Shell("sleep 10")); p.getPublishersList().add(new BuildTrigger(Collections.singleton(downstream), Result.SUCCESS)); Jenkins.getInstance().rebuildDependencyGraph(); p.setBlockBuildWhenDownstreamBuilding(true); From 9491f776e9c633850c928c3dbd60e7184018527d Mon Sep 17 00:00:00 2001 From: Alex Earl Date: Mon, 13 Feb 2017 09:53:07 -0700 Subject: [PATCH 12/19] Replace timeout with ping solution (Thanks Windows) --- .../test/java/hudson/cli/AbstractBuildRangeCommand2Test.java | 2 +- test/src/test/java/hudson/cli/ConsoleCommandTest.java | 4 ++-- test/src/test/java/hudson/model/ProjectTest.java | 4 ++-- test/src/test/java/hudson/model/QueueTest.java | 4 +++- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/test/src/test/java/hudson/cli/AbstractBuildRangeCommand2Test.java b/test/src/test/java/hudson/cli/AbstractBuildRangeCommand2Test.java index 91d67efb49..8d682801ce 100644 --- a/test/src/test/java/hudson/cli/AbstractBuildRangeCommand2Test.java +++ b/test/src/test/java/hudson/cli/AbstractBuildRangeCommand2Test.java @@ -90,7 +90,7 @@ public class AbstractBuildRangeCommand2Test { @Test public void dummyRangeShouldSuccessEvenTheBuildIsRunning() throws Exception { FreeStyleProject project = j.createFreeStyleProject("aProject"); - project.getBuildersList().add(Functions.isWindows() ? new BatchFile("echo 1\r\ntimeout /t 10 /nobreak") : new Shell("echo 1\nsleep 10s")); + project.getBuildersList().add(Functions.isWindows() ? new BatchFile("echo 1\r\nping -n 10 127.0.01 >nul") : new Shell("echo 1\nsleep 10s")); assertThat("Job wasn't scheduled properly", project.scheduleBuild(0), equalTo(true)); // Wait until classProject is started (at least 1s) diff --git a/test/src/test/java/hudson/cli/ConsoleCommandTest.java b/test/src/test/java/hudson/cli/ConsoleCommandTest.java index 9ef83a768b..1f4033e0c2 100644 --- a/test/src/test/java/hudson/cli/ConsoleCommandTest.java +++ b/test/src/test/java/hudson/cli/ConsoleCommandTest.java @@ -198,7 +198,7 @@ public class ConsoleCommandTest { //TODO: do we really want to sleep for 10 seconds? if(Functions.isWindows()) { project.getBuildersList().add(new BatchFile("echo start - %BUILD_NUMBER%\r\n" - + "timeout /t 10 /nobreak\r\necho after sleep - %BUILD_NUMBER%")); + + "ping -n 10 127.0.0.1 >nul\r\necho after sleep - %BUILD_NUMBER%")); } else { project.getBuildersList().add(new Shell("echo start - ${BUILD_NUMBER}\nsleep 10s\n" + "echo after sleep - ${BUILD_NUMBER}")); @@ -269,7 +269,7 @@ public class ConsoleCommandTest { if (Functions.isWindows()) { // the ver >NUL is to reset ERRORLEVEL so we don't fail (ping causes the error) project.getBuildersList().add(new BatchFile("echo 1\r\necho 2\r\necho 3\r\necho 4\r\necho 5\r\n" - + "timeout /t 10 /nobreak\r\necho 6\r\necho 7\r\necho 8\r\necho 9")); + + "ping -n 10 127.0.0.1 >nul\r\necho 6\r\necho 7\r\necho 8\r\necho 9")); } else { project.getBuildersList().add(new Shell("echo 1\necho 2\necho 3\necho 4\necho 5\n" + "sleep 10s\n" diff --git a/test/src/test/java/hudson/model/ProjectTest.java b/test/src/test/java/hudson/model/ProjectTest.java index b0aeb6fc5c..da7ea74185 100644 --- a/test/src/test/java/hudson/model/ProjectTest.java +++ b/test/src/test/java/hudson/model/ProjectTest.java @@ -359,14 +359,14 @@ public class ProjectTest { @Test public void testGetCauseOfBlockage() throws Exception { FreeStyleProject p = j.createFreeStyleProject("project"); - p.getBuildersList().add(Functions.isWindows() ? new BatchFile("timeout /t 10 /nobreak") : new Shell("sleep 10")); + p.getBuildersList().add(Functions.isWindows() ? new BatchFile("ping -n 10 127.0.0.1 >nul") : new Shell("sleep 10")); QueueTaskFuture b1 = waitForStart(p); assertInstanceOf("Build can not start because previous build has not finished: " + p.getCauseOfBlockage(), p.getCauseOfBlockage(), BlockedBecauseOfBuildInProgress.class); p.getLastBuild().getExecutor().interrupt(); b1.get(); // wait for it to finish FreeStyleProject downstream = j.createFreeStyleProject("project-downstream"); - downstream.getBuildersList().add(Functions.isWindows() ? new BatchFile("timeout /t 10 /nobreak") : new Shell("sleep 10")); + downstream.getBuildersList().add(Functions.isWindows() ? new BatchFile("ping -n 10 127.0.0.1 >nul") : new Shell("sleep 10")); p.getPublishersList().add(new BuildTrigger(Collections.singleton(downstream), Result.SUCCESS)); Jenkins.getInstance().rebuildDependencyGraph(); p.setBlockBuildWhenDownstreamBuilding(true); diff --git a/test/src/test/java/hudson/model/QueueTest.java b/test/src/test/java/hudson/model/QueueTest.java index 7b7329e581..834171ff5d 100644 --- a/test/src/test/java/hudson/model/QueueTest.java +++ b/test/src/test/java/hudson/model/QueueTest.java @@ -120,6 +120,7 @@ import java.util.concurrent.atomic.AtomicInteger; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.*; +import static org.junit.Assume.assumeFalse; /** * @author Kohsuke Kawaguchi @@ -376,12 +377,13 @@ public class QueueTest { @Issue("JENKINS-8790") @Test public void flyweightTasks() throws Exception { + //assumeFalse("This doesn't currently work on Windows", Functions.isWindows()); MatrixProject m = r.jenkins.createProject(MatrixProject.class, "p"); m.addProperty(new ParametersDefinitionProperty( new StringParameterDefinition("FOO","value") )); if (Functions.isWindows()) { - m.getBuildersList().add(new BatchFile("timeout /t 3")); + m.getBuildersList().add(new BatchFile("ping -n 3 127.0.0.1 >nul")); } else { m.getBuildersList().add(new Shell("sleep 3")); } From 3d38ec9fddd11126c11345bc5dd48e19779ceaab Mon Sep 17 00:00:00 2001 From: Alex Earl Date: Mon, 13 Feb 2017 12:09:45 -0700 Subject: [PATCH 13/19] Remove commented code --- test/src/test/java/hudson/model/QueueTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/test/src/test/java/hudson/model/QueueTest.java b/test/src/test/java/hudson/model/QueueTest.java index 834171ff5d..1bab23d98e 100644 --- a/test/src/test/java/hudson/model/QueueTest.java +++ b/test/src/test/java/hudson/model/QueueTest.java @@ -377,7 +377,6 @@ public class QueueTest { @Issue("JENKINS-8790") @Test public void flyweightTasks() throws Exception { - //assumeFalse("This doesn't currently work on Windows", Functions.isWindows()); MatrixProject m = r.jenkins.createProject(MatrixProject.class, "p"); m.addProperty(new ParametersDefinitionProperty( new StringParameterDefinition("FOO","value") From f604102bb6c22f6253819b642f484dedf284dd6e Mon Sep 17 00:00:00 2001 From: Alex Earl Date: Mon, 13 Feb 2017 14:55:37 -0700 Subject: [PATCH 14/19] Update to use EchoCommand from test harness and some formatting. --- .../hudson/util/ArgumentListBuilder2Test.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/test/src/test/java/hudson/util/ArgumentListBuilder2Test.java b/test/src/test/java/hudson/util/ArgumentListBuilder2Test.java index b5e4564b0b..c2f06e1e9c 100644 --- a/test/src/test/java/hudson/util/ArgumentListBuilder2Test.java +++ b/test/src/test/java/hudson/util/ArgumentListBuilder2Test.java @@ -28,6 +28,7 @@ import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import static org.junit.Assume.assumeTrue; import hudson.Functions; import hudson.Launcher.LocalLauncher; @@ -45,6 +46,7 @@ import com.google.common.base.Joiner; import java.io.ByteArrayOutputStream; import java.io.StringWriter; +import java.net.URL; /** * @author Kohsuke Kawaguchi @@ -90,9 +92,18 @@ public class ArgumentListBuilder2Test { } public String echoArgs(String... arguments) throws Exception { - ArgumentListBuilder args = new ArgumentListBuilder(JavaEnvUtils.getJreExecutable("java"), "-cp", "target/test-classes/", "hudson.util.EchoCommand"); - args.add(arguments); - args = args.toWindowsCommand(); + String testHarnessJar = Class.forName("hudson.util.EchoCommand") + .getProtectionDomain() + .getCodeSource() + .getLocation() + .getFile() + .replaceAll("^/", ""); + + ArgumentListBuilder args = new ArgumentListBuilder( + JavaEnvUtils.getJreExecutable("java").replaceAll("^\"|\"$", ""), + "-cp", testHarnessJar, "hudson.util.EchoCommand") + .add(arguments) + .toWindowsCommand(); ByteArrayOutputStream out = new ByteArrayOutputStream(); final StreamTaskListener listener = new StreamTaskListener(out); From 223151ea8b0afebe7141b3ad0cc5ee1af1d39cd1 Mon Sep 17 00:00:00 2001 From: Alex Earl Date: Tue, 14 Feb 2017 14:06:22 -0700 Subject: [PATCH 15/19] Fix parsing so that the test can complete. --- .../security/security218/ysoserial/payloads/JRMPClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/src/test/java/jenkins/security/security218/ysoserial/payloads/JRMPClient.java b/test/src/test/java/jenkins/security/security218/ysoserial/payloads/JRMPClient.java index a50f1fc947..e749bc9c43 100644 --- a/test/src/test/java/jenkins/security/security218/ysoserial/payloads/JRMPClient.java +++ b/test/src/test/java/jenkins/security/security218/ysoserial/payloads/JRMPClient.java @@ -79,7 +79,7 @@ public class JRMPClient extends PayloadRunner implements ObjectPayload String host; int port; int sep = command.indexOf(':'); - if ( sep < 0 ) { + if ( sep < 0 || ((sep+1) < command.length() && !Character.isDigit(command.charAt(sep+1)))) { port = new Random().nextInt(65535); host = command; } From 30bac622a8528ba5faaa55adf6987342f95fb1f0 Mon Sep 17 00:00:00 2001 From: Alex Earl Date: Wed, 15 Feb 2017 11:55:03 -0700 Subject: [PATCH 16/19] This is really just to get another build. --- test/src/test/java/jenkins/security/Security232Test.java | 1 + 1 file changed, 1 insertion(+) diff --git a/test/src/test/java/jenkins/security/Security232Test.java b/test/src/test/java/jenkins/security/Security232Test.java index 26ff457c4a..ee9881867d 100644 --- a/test/src/test/java/jenkins/security/Security232Test.java +++ b/test/src/test/java/jenkins/security/Security232Test.java @@ -164,6 +164,7 @@ public class Security232Test { long o2 = Long.parseLong(parts[ 1 ], 16); short o3 = Short.parseShort(parts[ 2 ], 16); + // Need to find Windows equivalent. exploit(new InetSocketAddress(isa.getAddress(), jrmpPort), obj, o1, o2, o3, new CommonsCollections1(), "touch " + pwned); } From 6e5225c06b45a3e196c8647dd30275234e57a54c Mon Sep 17 00:00:00 2001 From: Daniel Beck Date: Mon, 20 Feb 2017 17:24:31 +0100 Subject: [PATCH 17/19] [FIX JENKINS-41864] Add warning for rare dates Previously, impossible dates caused 100% CPU while Jenkins was trying to find the previous/next occurrence of the date. --- .../main/java/hudson/scheduler/CronTab.java | 13 ++++++++ .../RareOrImpossibleDateException.java | 31 +++++++++++++++++++ .../java/hudson/triggers/TimerTrigger.java | 19 +++++++----- .../hudson/triggers/Messages.properties | 2 ++ 4 files changed, 58 insertions(+), 7 deletions(-) create mode 100644 core/src/main/java/hudson/scheduler/RareOrImpossibleDateException.java diff --git a/core/src/main/java/hudson/scheduler/CronTab.java b/core/src/main/java/hudson/scheduler/CronTab.java index d289dc32ef..9c17bb40e6 100644 --- a/core/src/main/java/hudson/scheduler/CronTab.java +++ b/core/src/main/java/hudson/scheduler/CronTab.java @@ -328,8 +328,14 @@ public final class CronTab { * This method modifies the given calendar and returns the same object. */ public Calendar ceil(Calendar cal) { + Calendar twoYearsFuture = (Calendar) cal.clone(); + twoYearsFuture.add(Calendar.YEAR, 2); OUTER: while (true) { + if (cal.compareTo(twoYearsFuture) > 0) { + // we went at least two years into the future + throw new RareOrImpossibleDateException(); + } for (CalendarField f : CalendarField.ADJUST_ORDER) { int cur = f.valueOf(cal); int next = f.ceil(this,cur); @@ -380,8 +386,15 @@ public final class CronTab { * This method modifies the given calendar and returns the same object. */ public Calendar floor(Calendar cal) { + Calendar twoYearsAgo = (Calendar) cal.clone(); + twoYearsAgo.add(Calendar.YEAR, -2); + OUTER: while (true) { + if (cal.compareTo(twoYearsAgo) < 0) { + // we went at least two years into the past + throw new RareOrImpossibleDateException(); + } for (CalendarField f : CalendarField.ADJUST_ORDER) { int cur = f.valueOf(cal); int next = f.floor(this,cur); diff --git a/core/src/main/java/hudson/scheduler/RareOrImpossibleDateException.java b/core/src/main/java/hudson/scheduler/RareOrImpossibleDateException.java new file mode 100644 index 0000000000..c45d18f808 --- /dev/null +++ b/core/src/main/java/hudson/scheduler/RareOrImpossibleDateException.java @@ -0,0 +1,31 @@ +/* + * The MIT License + * + * Copyright (c) 2017 CloudBees, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package hudson.scheduler; + +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; + +@Restricted(NoExternalUse.class) +public class RareOrImpossibleDateException extends RuntimeException { +} diff --git a/core/src/main/java/hudson/triggers/TimerTrigger.java b/core/src/main/java/hudson/triggers/TimerTrigger.java index 4380c0797c..da844fa6b6 100644 --- a/core/src/main/java/hudson/triggers/TimerTrigger.java +++ b/core/src/main/java/hudson/triggers/TimerTrigger.java @@ -32,6 +32,7 @@ import hudson.model.Cause; import hudson.model.Item; import hudson.scheduler.CronTabList; import hudson.scheduler.Hash; +import hudson.scheduler.RareOrImpossibleDateException; import hudson.util.FormValidation; import java.text.DateFormat; import java.util.ArrayList; @@ -104,13 +105,17 @@ public class TimerTrigger extends Trigger { } private void updateValidationsForNextRun(Collection validations, CronTabList ctl) { - Calendar prev = ctl.previous(); - Calendar next = ctl.next(); - if (prev != null && next != null) { - DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL); - validations.add(FormValidation.ok(Messages.TimerTrigger_would_last_have_run_at_would_next_run_at(fmt.format(prev.getTime()), fmt.format(next.getTime())))); - } else { - validations.add(FormValidation.warning(Messages.TimerTrigger_no_schedules_so_will_never_run())); + try { + Calendar prev = ctl.previous(); + Calendar next = ctl.next(); + if (prev != null && next != null) { + DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL); + validations.add(FormValidation.ok(Messages.TimerTrigger_would_last_have_run_at_would_next_run_at(fmt.format(prev.getTime()), fmt.format(next.getTime())))); + } else { + validations.add(FormValidation.warning(Messages.TimerTrigger_no_schedules_so_will_never_run())); + } + } catch (RareOrImpossibleDateException ex) { + validations.add(FormValidation.warning(Messages.TimerTrigger_the_specified_cron_tab_is_rare_or_impossible())); } } } diff --git a/core/src/main/resources/hudson/triggers/Messages.properties b/core/src/main/resources/hudson/triggers/Messages.properties index d01e59aec9..c82efebf15 100644 --- a/core/src/main/resources/hudson/triggers/Messages.properties +++ b/core/src/main/resources/hudson/triggers/Messages.properties @@ -29,5 +29,7 @@ TimerTrigger.MissingWhitespace=You appear to be missing whitespace between * and TimerTrigger.no_schedules_so_will_never_run=No schedules so will never run TimerTrigger.TimerTriggerCause.ShortDescription=Started by timer TimerTrigger.would_last_have_run_at_would_next_run_at=Would last have run at {0}; would next run at {1}. +TimerTrigger.the_specified_cron_tab_is_rare_or_impossible=This cron tab will match dates only rarely (e.g. February 29) or \ + never (e.g. June 31), so this job may be triggered very rarely, if at all. Trigger.init=Initializing timer for triggers SCMTrigger.AdministrativeMonitorImpl.DisplayName=Too Many SCM Polling Threads From 513d7e03c78a2893e30cae940ae1d00c4b35b962 Mon Sep 17 00:00:00 2001 From: Alex Earl Date: Thu, 23 Feb 2017 06:08:58 -0700 Subject: [PATCH 18/19] Fix ip address --- .../test/java/hudson/cli/AbstractBuildRangeCommand2Test.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/src/test/java/hudson/cli/AbstractBuildRangeCommand2Test.java b/test/src/test/java/hudson/cli/AbstractBuildRangeCommand2Test.java index 8d682801ce..bea2d8de8a 100644 --- a/test/src/test/java/hudson/cli/AbstractBuildRangeCommand2Test.java +++ b/test/src/test/java/hudson/cli/AbstractBuildRangeCommand2Test.java @@ -90,7 +90,7 @@ public class AbstractBuildRangeCommand2Test { @Test public void dummyRangeShouldSuccessEvenTheBuildIsRunning() throws Exception { FreeStyleProject project = j.createFreeStyleProject("aProject"); - project.getBuildersList().add(Functions.isWindows() ? new BatchFile("echo 1\r\nping -n 10 127.0.01 >nul") : new Shell("echo 1\nsleep 10s")); + project.getBuildersList().add(Functions.isWindows() ? new BatchFile("echo 1\r\nping -n 10 127.0.0.1 >nul") : new Shell("echo 1\nsleep 10s")); assertThat("Job wasn't scheduled properly", project.scheduleBuild(0), equalTo(true)); // Wait until classProject is started (at least 1s) From d1c21484c3658b93bffa4de51749ab60b2c4ff11 Mon Sep 17 00:00:00 2001 From: Daniel Beck Date: Sat, 25 Feb 2017 20:56:25 +0100 Subject: [PATCH 19/19] [JENKINS-41864] More Javadoc, rephrase warning message --- .../main/java/hudson/scheduler/CronTab.java | 10 +++++++-- .../RareOrImpossibleDateException.java | 22 +++++++++++++++++++ .../hudson/triggers/Messages.properties | 2 +- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/hudson/scheduler/CronTab.java b/core/src/main/java/hudson/scheduler/CronTab.java index 9c17bb40e6..81fa5075c9 100644 --- a/core/src/main/java/hudson/scheduler/CronTab.java +++ b/core/src/main/java/hudson/scheduler/CronTab.java @@ -326,6 +326,9 @@ public final class CronTab { * See {@link #ceil(long)}. * * This method modifies the given calendar and returns the same object. + * + * @throws RareOrImpossibleDateException if the date isn't hit in the 2 years after it indicates an impossible + * (e.g. Jun 31) date, or at least a date too rare to be useful. This addresses JENKINS-41864 and was added in TODO */ public Calendar ceil(Calendar cal) { Calendar twoYearsFuture = (Calendar) cal.clone(); @@ -333,7 +336,7 @@ public final class CronTab { OUTER: while (true) { if (cal.compareTo(twoYearsFuture) > 0) { - // we went at least two years into the future + // we went too far into the future throw new RareOrImpossibleDateException(); } for (CalendarField f : CalendarField.ADJUST_ORDER) { @@ -384,6 +387,9 @@ public final class CronTab { * See {@link #floor(long)} * * This method modifies the given calendar and returns the same object. + * + * @throws RareOrImpossibleDateException if the date isn't hit in the 2 years before it indicates an impossible + * (e.g. Jun 31) date, or at least a date too rare to be useful. This addresses JENKINS-41864 and was added in TODO */ public Calendar floor(Calendar cal) { Calendar twoYearsAgo = (Calendar) cal.clone(); @@ -392,7 +398,7 @@ public final class CronTab { OUTER: while (true) { if (cal.compareTo(twoYearsAgo) < 0) { - // we went at least two years into the past + // we went too far into the past throw new RareOrImpossibleDateException(); } for (CalendarField f : CalendarField.ADJUST_ORDER) { diff --git a/core/src/main/java/hudson/scheduler/RareOrImpossibleDateException.java b/core/src/main/java/hudson/scheduler/RareOrImpossibleDateException.java index c45d18f808..7bd9d2562f 100644 --- a/core/src/main/java/hudson/scheduler/RareOrImpossibleDateException.java +++ b/core/src/main/java/hudson/scheduler/RareOrImpossibleDateException.java @@ -26,6 +26,28 @@ package hudson.scheduler; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.NoExternalUse; +import java.util.Calendar; + +/** + * This exception is thrown when trying to determine the previous or next occurrence of a given date determines + * that it's not happened, or going to happen, within some time period (e.g. within the next year). + * + *

This can typically have a few different reasons:

+ * + *
    + *
  • The date is impossible. For example, June 31 does never happen, so 0 0 31 6 * will never happen
  • + *
  • The date happens only rarely + *
      + *
    • February 29 being the obvious one
    • + *
    • Cron tab patterns specifying all of month, day of month, and day of week can also occur so rarely to trigger this exception
    • + *
    + *
  • + *
+ * + * @see CronTab#floor(Calendar) + * @see CronTab#ceil(Calendar) + * @since TODO + */ @Restricted(NoExternalUse.class) public class RareOrImpossibleDateException extends RuntimeException { } diff --git a/core/src/main/resources/hudson/triggers/Messages.properties b/core/src/main/resources/hudson/triggers/Messages.properties index c82efebf15..245b3c4de4 100644 --- a/core/src/main/resources/hudson/triggers/Messages.properties +++ b/core/src/main/resources/hudson/triggers/Messages.properties @@ -29,7 +29,7 @@ TimerTrigger.MissingWhitespace=You appear to be missing whitespace between * and TimerTrigger.no_schedules_so_will_never_run=No schedules so will never run TimerTrigger.TimerTriggerCause.ShortDescription=Started by timer TimerTrigger.would_last_have_run_at_would_next_run_at=Would last have run at {0}; would next run at {1}. -TimerTrigger.the_specified_cron_tab_is_rare_or_impossible=This cron tab will match dates only rarely (e.g. February 29) or \ +TimerTrigger.the_specified_cron_tab_is_rare_or_impossible=This schedule will match dates only rarely (e.g. February 29) or \ never (e.g. June 31), so this job may be triggered very rarely, if at all. Trigger.init=Initializing timer for triggers SCMTrigger.AdministrativeMonitorImpl.DisplayName=Too Many SCM Polling Threads