-
Bug
-
Resolution: Unresolved
-
Major
-
None
-
Jenkins version: 2.89.4
Pipeline (workflow-aggregator) => 2.5
Pipeline: API (workflow-api) => 2.26
Pipeline: Basic Steps (workflow-basic-steps) => 2.6
Pipeline: Groovy (workflow-cps) => 2.45
Pipeline: Job (workflow-job) => 2.17
Pipeline: Multibranch (workflow-multibranch) => 2.17
Pipeline: Nodes and Processes (workflow-durable-task-step) => 2.19
Pipeline: SCM Step (workflow-scm-step) => 2.6
Pipeline: Shared Groovy Libraries (workflow-cps-global-lib) => 2.9
Pipeline: Step API (workflow-step-api) => 2.14
Pipeline: Supporting APIs (workflow-support) => 2.18Jenkins version: 2.89.4 Pipeline (workflow-aggregator) => 2.5 Pipeline: API (workflow-api) => 2.26 Pipeline: Basic Steps (workflow-basic-steps) => 2.6 Pipeline: Groovy (workflow-cps) => 2.45 Pipeline: Job (workflow-job) => 2.17 Pipeline: Multibranch (workflow-multibranch) => 2.17 Pipeline: Nodes and Processes (workflow-durable-task-step) => 2.19 Pipeline: SCM Step (workflow-scm-step) => 2.6 Pipeline: Shared Groovy Libraries (workflow-cps-global-lib) => 2.9 Pipeline: Step API (workflow-step-api) => 2.14 Pipeline: Supporting APIs (workflow-support) => 2.18
First, create a pipeline job with this pipeline that contains a class definition:
class Data implements Serializable { final String string Data(final String string) { this.string = Objects.requireNonNull(string) } boolean equals(final other) { if (this.is(other)) { return true } if (getClass() != other.class) { return false } final Data that = (Data) other return string == that.string } int hashCode() { return string.hashCode() } } final d1 = new Data('a') final d2 = new Data('b') final d3 = new Data('c') final s1 = 'a' final s2 = 'b' final s3 = 'c' final s0 = [s1, s2, s3] echo "s1: ${s0.getClass()}" final ss1 = [s1, s2, s3].toSet() echo "ss1: ${ss1.getClass()}" final Set<String> ss2 = [s1, s2, s3] echo "ss2: ${ss2.getClass()}" final Set<String> ss3 = [s1, s2, s3].toSet() echo "ss3: ${ss3.getClass()}" final ss4 = [s1, s2, s3] as Set<String> echo "ss4: ${ss4.getClass()}" final Set<String> ss5 = [s1, s2, s3] as Set<String> echo "ss5: ${ss5.getClass()}" // Is there some issue with hashCodes? // Maps seem to also be affected? //final m1 = [:] //m1[d1] = s1 //echo "Map: ${m1.getClass()}" //echo "${m1.size()}" //echo "Map keys: ${m1.keySet().getClass()}" //echo "Map first key: ${m1.keySet().toList()[0].getClass()}" final d0 = [d1, d2, d3] echo "d0: ${s0.getClass()}" final ds1 = [d1, d2, d3].toSet() echo "ds1: ${ds1.getClass()}" // Fails with: // com.cloudbees.groovy.cps.impl.CpsCallableInvocation //final Set<Data> ds2 = [d1, d2, d3] //echo "ds2: ${ds2.getClass()}" // Fails with: // hudson.remoting.ProxyException: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '97' with class 'java.lang.Integer' to class 'java.util.Set' //final Set<Data> ds3 = [d1, d2, d3].toSet() //echo "ds3: ${ds3.getClass()}" // Fails with: // hudson.remoting.ProxyException: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '97' with class 'java.lang.Integer' to class 'java.util.Set' //final ds4 = [d1, d2, d3] as Set<Data> //echo "ds4: ${ds4.getClass()}" // Fails with: // hudson.remoting.ProxyException: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '97' with class 'java.lang.Integer' to class 'java.util.Set\' //final Set<Data> ds5 = [d1, d2, d3] as Set<Data> //echo "ds5: ${ds5.getClass()}"
Run once, and approve the hashCode() signature since it is not in default whitelist right now:
Uncomment any of the lines under the cases above, build again, and see failure and confusing types. For example, uncommenting the ds3 example above results in this:
[Pipeline] echo s1: class java.util.ArrayList [Pipeline] echo ss1: class java.util.HashSet [Pipeline] echo ss2: class java.util.LinkedHashSet [Pipeline] echo ss3: class java.util.HashSet [Pipeline] echo ss4: class java.util.LinkedHashSet [Pipeline] echo ss5: class java.util.LinkedHashSet [Pipeline] echo d0: class java.util.ArrayList [Pipeline] echo ds1: class java.lang.Integer [Pipeline] End of Pipeline hudson.remoting.ProxyException: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '97' with class 'java.lang.Integer' to class 'java.util.Set' at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.continueCastOnSAM(DefaultTypeTransformation.java:405) at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.continueCastOnNumber(DefaultTypeTransformation.java:319) at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.continueCastOnCollection(DefaultTypeTransformation.java:267) at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.castToType(DefaultTypeTransformation.java:219) at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.castToType(ScriptBytecodeAdapter.java:603) at Unknown.Unknown(Unknown) at ___cps.transform___(Native Method) at com.cloudbees.groovy.cps.impl.LocalVariableBlock$LocalVariable.set(LocalVariableBlock.java:45) at com.cloudbees.groovy.cps.impl.AssignmentBlock$ContinuationImpl.assignAndDone(AssignmentBlock.java:70) at sun.reflect.GeneratedMethodAccessor127.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72) at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:60) at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:109) at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixName(FunctionCallBlock.java:77) at sun.reflect.GeneratedMethodAccessor109.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72) at com.cloudbees.groovy.cps.impl.ConstantBlock.eval(ConstantBlock.java:21) at com.cloudbees.groovy.cps.Next.step(Next.java:83) at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:174) at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:163) at org.codehaus.groovy.runtime.GroovyCategorySupport$ThreadCategoryInfo.use(GroovyCategorySupport.java:122) at org.codehaus.groovy.runtime.GroovyCategorySupport.use(GroovyCategorySupport.java:261) at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:163) at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.access$001(SandboxContinuable.java:19) at org.jenkinsci.plugins.workflow.cps.SandboxContinuable$1.call(SandboxContinuable.java:35) at org.jenkinsci.plugins.workflow.cps.SandboxContinuable$1.call(SandboxContinuable.java:32) at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.GroovySandbox.runInSandbox(GroovySandbox.java:108) at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.run0(SandboxContinuable.java:32) at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:174) at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:331) at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$200(CpsThreadGroup.java:82) at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:243) at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:231) at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:64) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:112) at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748)
Interesting - will investigate.