Skip to content

Commit ede9176

Browse files
committed
CpsFlowExecution, CpsScriptTest: mvn spotless:apply
Signed-off-by: Jim Klimov <[email protected]>
1 parent 095ff23 commit ede9176

File tree

2 files changed

+102
-84
lines changed

2 files changed

+102
-84
lines changed

plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsFlowExecution.java

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,9 @@
125125
import jenkins.model.Jenkins;
126126
import jenkins.util.SystemProperties;
127127
import net.jcip.annotations.GuardedBy;
128+
import org.codehaus.groovy.GroovyBugError;
128129
import org.codehaus.groovy.control.ErrorCollector;
129130
import org.codehaus.groovy.control.MultipleCompilationErrorsException;
130-
import org.codehaus.groovy.GroovyBugError;
131131
import org.jboss.marshalling.Unmarshaller;
132132
import org.jboss.marshalling.reflect.SerializableClassRegistry;
133133
import org.jenkinsci.plugins.workflow.actions.ErrorAction;
@@ -485,7 +485,8 @@ Timing time(TimingKind kind) {
485485

486486
static final Logger TIMING_LOGGER = Logger.getLogger(CpsFlowExecution.class.getName() + ".timing");
487487

488-
static final Logger METHOD_TOO_LARGE_LOGGER = Logger.getLogger(CpsFlowExecution.class.getName() + ".MethodTooLargeLogging");
488+
static final Logger METHOD_TOO_LARGE_LOGGER =
489+
Logger.getLogger(CpsFlowExecution.class.getName() + ".MethodTooLargeLogging");
489490

490491
void logTimings() {
491492
if (TIMING_LOGGER.isLoggable(Level.FINE)) {
@@ -691,12 +692,12 @@ protected static Throwable reportSuspectedMethodTooLarge(Throwable x) {
691692

692693
for (int i = 0; i < ecCount; i++) {
693694
Exception ex = ec.getException(i);
694-
if (ex == null)
695-
continue;
695+
if (ex == null) continue;
696696

697-
METHOD_TOO_LARGE_LOGGER.log(Level.FINE,
698-
"CpsFlowExecution.reportSuspectedMethodTooLarge: " +
699-
"Collected Exception #" + i + ": " + ex.toString());
697+
METHOD_TOO_LARGE_LOGGER.log(
698+
Level.FINE,
699+
"CpsFlowExecution.reportSuspectedMethodTooLarge: " + "Collected Exception #" + i + ": "
700+
+ ex.toString());
700701
if (ex.getClass().getSimpleName().equals("MethodTooLargeException")) {
701702
mtlEx = ex;
702703
break;
@@ -785,15 +786,22 @@ protected static Throwable reportSuspectedMethodTooLarge(Throwable x) {
785786

786787
// For this matcher, caught patterns of interest include:
787788
// * alphanumeric-only token: step (global variable) from a Jenkins shared library
788-
// groovyjarjarasm.asm.MethodTooLargeException: Method too large: cloudBranch.___cps___586328 ()Lcom/cloudbees/groovy/cps/impl/CpsFunction;
789+
// groovyjarjarasm.asm.MethodTooLargeException:
790+
// Method too large: cloudBranch.___cps___586328
791+
// ()Lcom/cloudbees/groovy/cps/impl/CpsFunction;
789792
// * ... or a name generated by this plugin for pipeline script
790793
// (variants detailed below):
791-
// groovyjarjarasm.asm.MethodTooLargeException: Method too large: WorkflowScript.___cps___20692 ()Lcom/cloudbees/groovy/cps/impl/CpsFunction;
794+
// groovyjarjarasm.asm.MethodTooLargeException:
795+
// Method too large: WorkflowScript.___cps___20692
796+
// ()Lcom/cloudbees/groovy/cps/impl/CpsFunction;
792797
// * alphanumeric token with slashes: class from a Jenkins shared library
793-
// groovyjarjarasm.asm.MethodTooLargeException: Method too large: com/myproject/ci/BranchResync.___cps___679414 ()Lcom/cloudbees/groovy/cps/impl/CpsFunction;
798+
// groovyjarjarasm.asm.MethodTooLargeException:
799+
// Method too large: com/myproject/ci/BranchResync.___cps___679414
800+
// ()Lcom/cloudbees/groovy/cps/impl/CpsFunction;
794801
// Note that we do not include a "." character, so any ".run", ".pipeline()"
795802
// or ".groovy" suffix is not in overflowedClassName* strings.
796-
final Pattern MTLE_CLASSNAME_PATTERN = Pattern.compile("^.*MethodTooLargeException.*: ([^\\s.]+)\\.___cps___\\d+.*$");
803+
final Pattern MTLE_CLASSNAME_PATTERN =
804+
Pattern.compile("^.*MethodTooLargeException.*: ([^\\s.]+)\\.___cps___\\d+.*$");
797805

798806
// Collect text of just the start of original exception
799807
// (at least CpsCompilationErrorsException carries the
@@ -809,7 +817,8 @@ protected static Throwable reportSuspectedMethodTooLarge(Throwable x) {
809817
// * "*.groovy:LINENUM": possible path through Jenkins shared library
810818
// (if pipeline and some steps/classes are okay, and call one too big)
811819
// * later would add overflowedClassNameShort if/when we detect one
812-
Pattern CLASSNAME_MENTIONS_PATTERN = Pattern.compile("^\\s+at .*(WorkflowScript.*|Script\\d+|\\.groovy):\\d+\\).*$");
820+
Pattern CLASSNAME_MENTIONS_PATTERN =
821+
Pattern.compile("^\\s+at .*(WorkflowScript.*|Script\\d+|\\.groovy):\\d+\\).*$");
813822
// Used in a few checks later for the "Script<NUM>" case:
814823
Pattern CLASSNAME_SCRIPTNUM_PATTERN = Pattern.compile("^Script\\d+$");
815824

@@ -832,7 +841,8 @@ protected static Throwable reportSuspectedMethodTooLarge(Throwable x) {
832841

833842
String[] overflowedClassNameSplit = overflowedClassName.split("/");
834843
if (overflowedClassNameSplit.length > 1) {
835-
overflowedClassNameShort = overflowedClassNameSplit[overflowedClassNameSplit.length - 1];
844+
overflowedClassNameShort =
845+
overflowedClassNameSplit[overflowedClassNameSplit.length - 1];
836846
} else {
837847
overflowedClassNameShort = overflowedClassName;
838848
}
@@ -847,7 +857,8 @@ protected static Throwable reportSuspectedMethodTooLarge(Throwable x) {
847857

848858
// Update the matching pattern in case we manage
849859
// to spot our problematic source in the stack trace
850-
CLASSNAME_MENTIONS_PATTERN = Pattern.compile("^\\s+at .*(WorkflowScript.*|Script\\d+|" + overflowedClassNameShort + ".*|\\.groovy):\\d+\\).*$");
860+
CLASSNAME_MENTIONS_PATTERN = Pattern.compile("^\\s+at .*(WorkflowScript.*|Script\\d+|"
861+
+ overflowedClassNameShort + ".*|\\.groovy):\\d+\\).*$");
851862
continue;
852863
} catch (Throwable ignored) {
853864
}
@@ -864,7 +875,8 @@ protected static Throwable reportSuspectedMethodTooLarge(Throwable x) {
864875
String overflowedClassNameReport;
865876
if (overflowedClassName == null) {
866877
overflowedClassNameReport = "WorkflowScript (the pipeline script) or one of its constituents";
867-
} else if (overflowedClassName.equals("WorkflowScript") || CLASSNAME_SCRIPTNUM_PATTERN.matcher(overflowedClassName).find()) {
878+
} else if (overflowedClassName.equals("WorkflowScript")
879+
|| CLASSNAME_SCRIPTNUM_PATTERN.matcher(overflowedClassName).find()) {
868880
overflowedClassNameReport = overflowedClassName + " (the pipeline script)";
869881
} else if (overflowedClassName.contains("/")) {
870882
// quote the step/class name pretty:
@@ -887,28 +899,30 @@ protected static Throwable reportSuspectedMethodTooLarge(Throwable x) {
887899
actionableMsg.append(" (and other issues)");
888900
}
889901
actionableMsg.append("; please refactor to simplify code structure");
890-
if (overflowedClassNameReport.contains("WorkflowScript") || CLASSNAME_SCRIPTNUM_PATTERN.matcher(overflowedClassName).find())
902+
if (overflowedClassNameReport.contains("WorkflowScript")
903+
|| CLASSNAME_SCRIPTNUM_PATTERN.matcher(overflowedClassName).find()) {
891904
actionableMsg.append(" and/or move logic to a Jenkins Shared Library");
905+
}
892906
if (xMsgStart.length() > 0) {
893-
actionableMsg
894-
.append(":\n-----\n")
895-
.append(xMsgStart.toString());
907+
actionableMsg.append(":\n-----\n").append(xMsgStart.toString());
896908
}
897909
if (overflowedClassNameBreadcrumbs.length() > 0) {
898910
actionableMsg
899-
.append("\nGroovy code trail (mentions of pipeline WorkflowScript and/or your JSL in larger stack trace):\n")
911+
.append(
912+
"\nGroovy code trail (mentions of pipeline WorkflowScript and/or your JSL in larger stack trace):\n")
900913
.append(overflowedClassNameBreadcrumbs);
901914
}
902915
if (xMsgStart.length() > 0) {
903-
if (!(actionableMsg.substring(actionableMsg.length() - 1).equals("\n")))
916+
if (!(actionableMsg.substring(actionableMsg.length() - 1).equals("\n"))) {
904917
actionableMsg.append("\n");
918+
}
905919
actionableMsg.append("-----");
906920
}
907921

908922
// Make a full note in server log
909-
METHOD_TOO_LARGE_LOGGER.log(Level.FINER,
910-
"CpsFlowExecution.reportSuspectedMethodTooLarge: full original Throwable message:\n"
911-
+ xStr);
923+
METHOD_TOO_LARGE_LOGGER.log(
924+
Level.FINER,
925+
"CpsFlowExecution.reportSuspectedMethodTooLarge: full original Throwable message:\n" + xStr);
912926

913927
if (ecCount > 1) {
914928
// Not squashing with explicit MethodTooLargeException
@@ -921,7 +935,8 @@ protected static Throwable reportSuspectedMethodTooLarge(Throwable x) {
921935
// build console, but let the full context be found in
922936
// server log with some dedication. Note it is seen at
923937
// a different logging verbosity level.
924-
METHOD_TOO_LARGE_LOGGER.log(Level.FINE,
938+
METHOD_TOO_LARGE_LOGGER.log(
939+
Level.FINE,
925940
"CpsFlowExecution.reportSuspectedMethodTooLarge: detected details of MethodTooLargeException:\n"
926941
+ mtlEx.getMessage());
927942

@@ -931,7 +946,7 @@ protected static Throwable reportSuspectedMethodTooLarge(Throwable x) {
931946
.append(METHOD_TOO_LARGE_LOGGER.getName())
932947
.append(" is required)");
933948

934-
//return new RuntimeException(actionableMsg.toString(), mtlEx);
949+
// return new RuntimeException(actionableMsg.toString(), mtlEx);
935950
RuntimeException rtex = new RuntimeException(actionableMsg.toString(), null);
936951

937952
// Avoid having a huge stack trace leading to this pretty log-printer
@@ -946,7 +961,7 @@ protected static Throwable reportSuspectedMethodTooLarge(Throwable x) {
946961

947962
// Considered passing original context,
948963
// but it is shown by ultimate job log :(
949-
//rtex.addSuppressed(mtlEx);
964+
// rtex.addSuppressed(mtlEx);
950965

951966
return rtex;
952967
}
@@ -974,10 +989,8 @@ private CpsScript parseScript() throws IOException {
974989
// wrapped into further exception, for actionable
975990
// logging in the job.
976991
Throwable t = CpsFlowExecution.reportSuspectedMethodTooLarge(x);
977-
if (t instanceof RuntimeException)
978-
throw (RuntimeException)t;
979-
if (t instanceof Error)
980-
throw (Error)t;
992+
if (t instanceof RuntimeException) throw (RuntimeException) t;
993+
if (t instanceof Error) throw (Error) t;
981994

982995
// NOTE: In practice we should not get here, due
983996
// to practical type of "x" and what of it is

plugin/src/test/java/org/jenkinsci/plugins/workflow/cps/CpsScriptTest.java

Lines changed: 58 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ public void blockRun() throws Exception {
105105
"Scripts not permitted to use method groovy.lang.Script run java.io.File java.lang.String[]", b);
106106
}
107107

108-
@Test public void methodTooLargeExceptionFabricated() throws Exception {
108+
@Test
109+
public void methodTooLargeExceptionFabricated() throws Exception {
109110
// Fabricate a MethodTooLargeException which "normally" happens when evaluated
110111
// groovy script becomes a Java class too large for Java to handle internally.
111112
// In Jenkins practice this can happen not only due to large singular pipelines
@@ -115,16 +116,19 @@ public void blockRun() throws Exception {
115116
WorkflowJob p = r.createProject(WorkflowJob.class);
116117
// sandbox == false to allow creation of the exception here:
117118
p.setDefinition(new CpsFlowDefinition(
118-
"import groovyjarjarasm.asm.MethodTooLargeException;\n\n" +
119-
"throw new MethodTooLargeException('className', 'methodName', 'methodDescriptor', 65535);"
120-
, false));
119+
"import groovyjarjarasm.asm.MethodTooLargeException;\n\n"
120+
+ "throw new MethodTooLargeException('className', 'methodName', 'methodDescriptor', 65535);",
121+
false));
121122
WorkflowRun b = r.buildAndAssertStatus(Result.FAILURE, p);
122-
r.assertLogContains("groovyjarjarasm.asm.MethodTooLargeException: Method too large: className.methodName methodDescriptor", b);
123+
r.assertLogContains(
124+
"groovyjarjarasm.asm.MethodTooLargeException: Method too large: className.methodName methodDescriptor",
125+
b);
123126
r.assertLogContains("at WorkflowScript.run(WorkflowScript:3)", b);
124127
r.assertLogContains("at ___cps.transform___(Native Method)", b);
125128
}
126129

127-
@Test public void methodTooLargeExceptionRealistic() throws Exception {
130+
@Test
131+
public void methodTooLargeExceptionRealistic() throws Exception {
128132
// See comments above. Here we try to really induce a "method too large"
129133
// condition by abusing the nesting of exception-handling, too many stages
130134
// or methods, and whatever else we can throw at it.
@@ -158,26 +162,27 @@ public void blockRun() throws Exception {
158162
}
159163
sbMethods.append("}\n");
160164

161-
p.setDefinition(new CpsFlowDefinition(sbMethods.toString() +
162-
"pipeline {\n" +
163-
" agent none;\n" +
164-
" stages {\n" +
165-
" stage ('Test stage') {\n" +
166-
" steps {\n" +
167-
" script {\n" +
168-
" echo 'BEGINNING TEST IN PIPELINE';\n" +
169-
" method();\n" +
170-
" echo 'ENDED TEST IN PIPELINE';\n" +
171-
" }\n" +
172-
" }\n" +
173-
" }\n" +
174-
sbStages.toString() +
175-
" }\n" +
176-
"}\n" +
177-
"echo 'BEGINNING TEST OUT OF PIPELINE';\n" +
178-
"method();\n" +
179-
"echo 'ENDED TEST OUT OF PIPELINE';\n"
180-
, true));
165+
p.setDefinition(new CpsFlowDefinition(
166+
sbMethods.toString()
167+
+ "pipeline {\n"
168+
+ " agent none;\n"
169+
+ " stages {\n"
170+
+ " stage ('Test stage') {\n"
171+
+ " steps {\n"
172+
+ " script {\n"
173+
+ " echo 'BEGINNING TEST IN PIPELINE';\n"
174+
+ " method();\n"
175+
+ " echo 'ENDED TEST IN PIPELINE';\n"
176+
+ " }\n"
177+
+ " }\n"
178+
+ " }\n"
179+
+ sbStages.toString()
180+
+ " }\n"
181+
+ "}\n"
182+
+ "echo 'BEGINNING TEST OUT OF PIPELINE';\n"
183+
+ "method();\n"
184+
+ "echo 'ENDED TEST OUT OF PIPELINE';\n",
185+
true));
181186

182187
WorkflowRun b = p.scheduleBuild2(0).get();
183188

@@ -191,33 +196,33 @@ public void blockRun() throws Exception {
191196
// "Prettier" explanation added by CpsFlowExecution.parseScript():
192197
r.assertLogContains("FAILED to parse WorkflowScript (the pipeline script) due to MethodTooLargeException", b);
193198

194-
/*
195-
// Report as of release 3880.vb_ef4b_5cfd270 (Feb 2024)
196-
// and same pattern seen since at least Jun 2022 (note
197-
// that numbers after ___cps___ differ from job to job):
198-
199-
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
200-
General error during class generation: Method too large: WorkflowScript.___cps___1 ()Lcom/cloudbees/groovy/cps/impl/CpsFunction;
201-
202-
groovyjarjarasm.asm.MethodTooLargeException: Method too large: WorkflowScript.___cps___1 ()Lcom/cloudbees/groovy/cps/impl/CpsFunction;
203-
at groovyjarjarasm.asm.MethodWriter.computeMethodInfoSize(MethodWriter.java:2087)
204-
at groovyjarjarasm.asm.ClassWriter.toByteArray(ClassWriter.java:447)
205-
at org.codehaus.groovy.control.CompilationUnit$17.call(CompilationUnit.java:850)
206-
at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1087)
207-
at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:624)
208-
at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:602)
209-
at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:579)
210-
at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:323)
211-
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:293)
212-
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.GroovySandbox$Scope.parse(GroovySandbox.java:163)
213-
at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.doParse(CpsGroovyShell.java:190)
214-
at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.reparse(CpsGroovyShell.java:175)
215-
at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.parseScript(CpsFlowExecution.java:637)
216-
at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.start(CpsFlowExecution.java:583)
217-
at org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:335)
218-
at hudson.model.ResourceController.execute(ResourceController.java:101)
219-
at hudson.model.Executor.run(Executor.java:442)
220-
*/
199+
/*
200+
// Report as of release 3880.vb_ef4b_5cfd270 (Feb 2024)
201+
// and same pattern seen since at least Jun 2022 (note
202+
// that numbers after ___cps___ differ from job to job):
203+
204+
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
205+
General error during class generation: Method too large: WorkflowScript.___cps___1 ()Lcom/cloudbees/groovy/cps/impl/CpsFunction;
206+
207+
groovyjarjarasm.asm.MethodTooLargeException: Method too large: WorkflowScript.___cps___1 ()Lcom/cloudbees/groovy/cps/impl/CpsFunction;
208+
at groovyjarjarasm.asm.MethodWriter.computeMethodInfoSize(MethodWriter.java:2087)
209+
at groovyjarjarasm.asm.ClassWriter.toByteArray(ClassWriter.java:447)
210+
at org.codehaus.groovy.control.CompilationUnit$17.call(CompilationUnit.java:850)
211+
at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1087)
212+
at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:624)
213+
at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:602)
214+
at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:579)
215+
at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:323)
216+
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:293)
217+
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.GroovySandbox$Scope.parse(GroovySandbox.java:163)
218+
at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.doParse(CpsGroovyShell.java:190)
219+
at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.reparse(CpsGroovyShell.java:175)
220+
at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.parseScript(CpsFlowExecution.java:637)
221+
at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.start(CpsFlowExecution.java:583)
222+
at org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:335)
223+
at hudson.model.ResourceController.execute(ResourceController.java:101)
224+
at hudson.model.Executor.run(Executor.java:442)
225+
*/
221226

222227
r.assertLogContains("Method too large: WorkflowScript.___cps___", b);
223228
r.assertLogContains("()Lcom/cloudbees/groovy/cps/impl/CpsFunction;", b);

0 commit comments

Comments
 (0)