Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,7 @@ public Map<String, Object> customInstantiate(@NonNull Map<String, Object> argume

private static List<String> toKeyValueList(Map<?, ?> map) {
return map.entrySet().stream()
.filter(e -> e.getKey() instanceof String)
.collect(Collectors.toMap(e -> (String)e.getKey(), e -> e.getValue() == null ? "" : e.getValue().toString()))
.entrySet().stream()
.map(m -> m.getKey() + "=" + m.getValue())
.map(m -> m.getKey() + "=" + (m.getValue() == null ? "" : m.getValue().toString()))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.map(m -> m.getKey() + "=" + (m.getValue() == null ? "" : m.getValue().toString()))
.map(m -> (String) m.getKey() + "=" + (m.getValue() == null ? "" : m.getValue().toString()))

since non-String keys would be bogus

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IDE consider this a redundant cast and wants to remove it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then your IDE is wrong and you should ignore it. You should be able to have a test demonstrating a failure from some bogus thing like

withEnv([new Object(): 'x']) {}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This case is not supported:

WorkflowScript: 2: illegal colon after argument expression;
  solution: a complex label expression before a colon must be parenthesized @ line 2, column 72.
  D: true, E: null, new Object(): 'x']) {

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe

withEnv([(new Object()): 'x']) {}

then, whatever the syntax is. At worst

def m = [:]
m.put(new Object(), 'x')
withEnv(m) {}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd argue your asking for trouble

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK forget new Object(), just some arbitrary object key which is not a String. new URL('http://nowhere.net/') for example is whitelisted.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Than you get into java.lang.ClassCastException: java.net.URL cannot be cast to java.lang.String 🤔

Properly better to call toString instead of trying to cast the object

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then you get into java.lang.ClassCastException

Exactly what I was requesting with 8d385a2.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

.collect(Collectors.toList());
}
}
Expand Down
123 changes: 22 additions & 101 deletions src/test/java/org/jenkinsci/plugins/workflow/steps/EnvStepTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,36 +83,6 @@ public class EnvStepTest {
});
}

@Test public void mapOverriding() {
story.addStep(new Statement() {
@Override public void evaluate() throws Throwable {
WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "p");
p.setDefinition(new CpsFlowDefinition(
"env.CUSTOM = 'initial'\n" +
"env.FOOPATH = node {isUnix() ? '/opt/foos' : 'C:\\\\foos'}\n" +
"env.NULLED = 'outside'\n" +
"node {\n" +
" withEnv([CUSTOM: 'override', NOVEL: 'val', BUILD_TAG: 'custom', NULLED: null, 'FOOPATH+BALL': isUnix() ? '/opt/ball' : 'C:\\\\ball']) {\n" +
" isUnix() ? sh('echo inside CUSTOM=$CUSTOM NOVEL=$NOVEL BUILD_TAG=$BUILD_TAG NULLED=$NULLED FOOPATH=$FOOPATH:') : bat('echo inside CUSTOM=%CUSTOM% NOVEL=%NOVEL% BUILD_TAG=%BUILD_TAG% NULLED=%NULLED% FOOPATH=%FOOPATH%;')\n" +
" echo \"groovy NULLED=${env.NULLED}\"\n" +
" }\n" +
" isUnix() ? sh('echo outside CUSTOM=$CUSTOM NOVEL=$NOVEL NULLED=outside') : bat('echo outside CUSTOM=%CUSTOM% NOVEL=%NOVEL% NULLED=outside')\n" +
"}", true));
WorkflowRun b = story.j.assertBuildStatusSuccess(p.scheduleBuild2(0));
story.j.assertLogContains(Functions.isWindows() ? "inside CUSTOM=override NOVEL=val BUILD_TAG=custom NULLED= FOOPATH=C:\\ball;C:\\foos;" : "inside CUSTOM=override NOVEL=val BUILD_TAG=custom NULLED= FOOPATH=/opt/ball:/opt/foos:", b);
story.j.assertLogContains("groovy NULLED=null", b);
story.j.assertLogContains("outside CUSTOM=initial NOVEL= NULLED=outside", b);
List<FlowNode> coreStepNodes = new DepthFirstScanner().filteredNodes(
b.getExecution(),
Predicates.and(
new NodeStepTypePredicate("withEnv"),
n -> n instanceof StepStartNode && !((StepStartNode) n).isBody()));
assertThat(coreStepNodes, Matchers.hasSize(1));
assertEquals("CUSTOM, NOVEL, BUILD_TAG, NULLED, FOOPATH+BALL", ArgumentsAction.getStepArgumentsAsString(coreStepNodes.get(0)));
}
});
}

@Test public void parallel() {
story.addStep(new Statement() {
@Override public void evaluate() throws Throwable {
Expand All @@ -135,28 +105,6 @@ public class EnvStepTest {
});
}

@Test public void mapParallel() {
story.addStep(new Statement() {
@Override public void evaluate() throws Throwable {
WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "p");
p.setDefinition(new CpsFlowDefinition(
"parallel a: {\n" +
" node {withEnv([TOOL: 'aloc']) {semaphore 'a'; isUnix() ? sh('echo a TOOL=$TOOL') : bat('echo a TOOL=%TOOL%')}}\n" +
"}, b: {\n" +
" node {withEnv([TOOL: 'bloc']) {semaphore 'b'; isUnix() ? sh('echo b TOOL=$TOOL') : bat('echo b TOOL=%TOOL%')}}\n" +
"}", true));
WorkflowRun b = p.scheduleBuild2(0).getStartCondition().get();
SemaphoreStep.waitForStart("a/1", b);
SemaphoreStep.waitForStart("b/1", b);
SemaphoreStep.success("a/1", null);
SemaphoreStep.success("b/1", null);
story.j.assertBuildStatusSuccess(story.j.waitForCompletion(b));
story.j.assertLogContains("a TOOL=aloc", b);
story.j.assertLogContains("b TOOL=bloc", b);
}
});
}

@Test public void restarting() {
story.addStep(new Statement() {
@Override public void evaluate() throws Throwable {
Expand Down Expand Up @@ -192,41 +140,6 @@ public class EnvStepTest {
});
}

@Test public void mapRestarting() {
story.addStep(new Statement() {
@Override public void evaluate() throws Throwable {
WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "p");
p.setDefinition(new CpsFlowDefinition(
"def show(which) {\n" +
" echo \"groovy ${which} ${env.TESTVAR}:\"\n" +
" isUnix() ? sh(\"echo shell ${which} \\$TESTVAR:\") : bat(\"echo shell ${which} %TESTVAR%:\")\n" +
"}\n" +
"node {\n" +
" withEnv([TESTVAR: 'val']) {\n" +
" show 'before'\n" +
" semaphore 'restarting'\n" +
" show 'after'\n" +
" }\n" +
" show 'outside'\n" +
"}", true));
WorkflowRun b = p.scheduleBuild2(0).getStartCondition().get();
SemaphoreStep.waitForStart("restarting/1", b);
}
});
story.addStep(new Statement() {
@Override public void evaluate() throws Throwable {
SemaphoreStep.success("restarting/1", null);
WorkflowRun b = story.j.assertBuildStatusSuccess(story.j.waitForCompletion(story.j.jenkins.getItemByFullName("p", WorkflowJob.class).getLastBuild()));
story.j.assertLogContains("groovy before val:", b);
story.j.assertLogContains("shell before val:", b);
story.j.assertLogContains("groovy after val:", b);
story.j.assertLogContains("shell after val:", b);
story.j.assertLogContains("groovy outside null:", b);
story.j.assertLogContains("shell outside :", b);
}
});
}

@Test public void nested() {
story.addStep(new Statement() {
@Override public void evaluate() throws Throwable {
Expand All @@ -245,40 +158,48 @@ public class EnvStepTest {
});
}

@Test public void mapNumbersNested() {
@Test public void mapArguments() {
story.addStep(new Statement() {
@Override public void evaluate() throws Throwable {
WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "p");
p.setDefinition(new CpsFlowDefinition(
"node {\n" +
" withEnv([A: 1]) {\n" +
" withEnv([B: 2]) {\n" +
" withEnv([C: true]) {\n" +
" isUnix() ? sh('echo A=$A B=$B C=$C') : bat('echo A=%A% B=%B% C=%C%')\n" +
" }\n" +
" }\n" +
" withEnv(a: 1, b: 2, c: 'hello world', d: true) {\n" +
" echo \"a=$a b=$b c=$c d=$d\"" +
" }\n" +
"}", true));
WorkflowRun b = story.j.assertBuildStatusSuccess(p.scheduleBuild2(0));
story.j.assertLogContains("A=1 B=2 C=true", b);
story.j.assertLogContains("a=1 b=2 c=hello world d=true", b);
List<FlowNode> coreStepNodes = new DepthFirstScanner().filteredNodes(
b.getExecution(),
Predicates.and(
new NodeStepTypePredicate("withEnv"),
n -> n instanceof StepStartNode && !((StepStartNode) n).isBody()));
assertThat(coreStepNodes, Matchers.hasSize(1));
assertEquals("a, b, c, d", ArgumentsAction.getStepArgumentsAsString(coreStepNodes.get(0)));
}
});
}

@Test public void mapNested() {
@Test public void mapArgumentsAsMap() {
story.addStep(new Statement() {
@Override public void evaluate() throws Throwable {
WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "p");
p.setDefinition(new CpsFlowDefinition(
"node {\n" +
" withEnv([A: 'one']) {\n" +
" withEnv([B: 'two']) {\n" +
" isUnix() ? sh('echo A=$A B=$B') : bat('echo A=%A% B=%B%')\n" +
" }\n" +
" withEnv([A: 1, B: 2, C: 'hello world', D: true]) {\n" +
" echo \"A=$A B=$B C=$C D=$D\"\n" +
" }\n" +
"}", true));
WorkflowRun b = story.j.assertBuildStatusSuccess(p.scheduleBuild2(0));
story.j.assertLogContains("A=one B=two", b);
story.j.assertLogContains("A=1 B=2 C=hello world D=true", b);
List<FlowNode> coreStepNodes = new DepthFirstScanner().filteredNodes(
b.getExecution(),
Predicates.and(
new NodeStepTypePredicate("withEnv"),
n -> n instanceof StepStartNode && !((StepStartNode) n).isBody()));
assertThat(coreStepNodes, Matchers.hasSize(1));
assertEquals("A, B, C, D", ArgumentsAction.getStepArgumentsAsString(coreStepNodes.get(0)));
}
});
}
Expand Down