Skip to content

Commit 7eef130

Browse files
authored
Fix beamTestPipelineOptions quote loss on Windows for ValidatesRunner tasks (#39365)
On Windows, Gradle passes -DbeamTestPipelineOptions=<compact JSON> to the forked test JVM unquoted, so the Windows C runtime strips the JSON quotes and TestPipeline fails to parse the options; every test in the task fails at TestPipeline.create(). Consolidate the existing Windows quoting treatment (BEAM-10682, BEAM-11365) into a shared helper and use it in createPortableValidatesRunnerTask and createCrossLanguageValidatesRunnerTask. On non-Windows platforms the emitted JSON is unchanged. Fixes #39332
1 parent b6cf0e9 commit 7eef130

1 file changed

Lines changed: 15 additions & 8 deletions

File tree

buildSrc/src/main/groovy/org/apache/beam/gradle/BeamModulePlugin.groovy

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,17 @@ class BeamModulePlugin implements Plugin<Project> {
9696
}
9797
}
9898

99+
// Serializes pipeline options to JSON for the beamTestPipelineOptions system property.
100+
// On Windows each option is wrapped in literal quotes so the JSON survives the quote
101+
// stripping applied to the forked test JVM's command line.
102+
// See https://github.com/apache/beam/issues/39332.
103+
static def toBeamTestPipelineOptionsJson(def options) {
104+
if (System.properties['os.name'].toLowerCase().contains('windows')) {
105+
return JsonOutput.toJson(options.collect { "\"$it\"" })
106+
}
107+
return JsonOutput.toJson(options)
108+
}
109+
99110
/** A class defining the set of configurable properties accepted by applyJavaNature. */
100111
static class JavaNatureConfiguration {
101112
/** Controls whether the spotbugs plugin is enabled and configured. */
@@ -2249,12 +2260,8 @@ class BeamModulePlugin implements Plugin<Project> {
22492260
}
22502261
}
22512262

2252-
// Windows handles quotation marks differently
2253-
if (pipelineOptionsString && System.properties['os.name'].toLowerCase().contains('windows')) {
2254-
def allOptionsListFormatted = allOptionsList.collect { "\"$it\"" }
2255-
pipelineOptionsStringFormatted = JsonOutput.toJson(allOptionsListFormatted)
2256-
} else if (pipelineOptionsString) {
2257-
pipelineOptionsStringFormatted = JsonOutput.toJson(allOptionsList)
2263+
if (pipelineOptionsString) {
2264+
pipelineOptionsStringFormatted = toBeamTestPipelineOptionsJson(allOptionsList)
22582265
}
22592266

22602267
systemProperties.beamTestPipelineOptions = pipelineOptionsStringFormatted ?: pipelineOptionsString
@@ -2691,7 +2698,7 @@ class BeamModulePlugin implements Plugin<Project> {
26912698
if (config.jobServerConfig) {
26922699
beamTestPipelineOptions.add("--jobServerConfig=${config.jobServerConfig}")
26932700
}
2694-
config.systemProperties.put("beamTestPipelineOptions", JsonOutput.toJson(beamTestPipelineOptions))
2701+
config.systemProperties.put("beamTestPipelineOptions", toBeamTestPipelineOptionsJson(beamTestPipelineOptions))
26952702
project.tasks.register(name, Test) {
26962703
group = "Verification"
26972704
description = "Validates the PortableRunner with JobServer ${config.jobServerDriver}"
@@ -2857,7 +2864,7 @@ class BeamModulePlugin implements Plugin<Project> {
28572864
def javaTask = project.tasks.register(config.name+"JavaUsing"+sdk, Test) {
28582865
group = "Verification"
28592866
description = "Validates runner for cross-language capability of using ${sdk} transforms from Java SDK"
2860-
systemProperty "beamTestPipelineOptions", JsonOutput.toJson(config.javaPipelineOptions)
2867+
systemProperty "beamTestPipelineOptions", toBeamTestPipelineOptionsJson(config.javaPipelineOptions)
28612868
systemProperty "expansionJar", expansionJar
28622869
systemProperty "expansionPort", port
28632870
systemProperty "semiPersistDir", config.semiPersistDir

0 commit comments

Comments
 (0)