This is an automated email from the ASF dual-hosted git repository.

sarutak pushed a commit to branch branch-4.2
in repository https://gitbox.apache.org/repos/asf/spark.git


The following commit(s) were added to refs/heads/branch-4.2 by this push:
     new 83363394b51f [SPARK-57081][TESTS] Fix percent-encoding issue in 
SparkTestUtils classpath handling
83363394b51f is described below

commit 83363394b51f7c95805652edf653328efef4724d
Author: Kousuke Saruta <[email protected]>
AuthorDate: Thu May 28 21:20:53 2026 +0900

    [SPARK-57081][TESTS] Fix percent-encoding issue in SparkTestUtils classpath 
handling
    
    ### What changes were proposed in this pull request?
    This PR replaces `URL.getFile()` with `new File(url.toURI).getPath` (or 
`new File(url.toURI)`) in `SparkTestUtils.scala` to correctly handle classpath 
URLs containing percent-encoded characters (e.g., spaces encoded as `%20`).
    
    Four call sites are fixed:
    - `createCompiledClass`
    - `createJarWithJavaSources`
    - `createJarWithScalaSources`
    - `expandManifestClasspath`
    
    Additionally, a new test suite `SparkTestUtilsSuite` is added to cover both 
this fix and the `expandManifestClasspath` logic introduced in #55564.
    
    ### Why are the changes needed?
    `URL.getFile()` returns a percent-encoded string. When a classpath URL 
contains spaces or special characters (e.g., `C:\Program Files\...` or CI 
environments with spaces in paths), the encoded string (e.g., 
`/path%20with%20spaces/lib.jar`) is passed directly to the compiler or `new 
File(...)`, which fails to resolve the actual file. Using `url.toURI` properly 
decodes the path.
    
    Without this change, tests which use `SparkTestUtils` fails if the 
repository is in the path containing white spaces.
    ```
    $ build/sbt 'core/testOnly 
org.apache.spark.executor.ClassLoaderIsolationSuite
    ...
    
    [info] - SPARK-51537 Executor isolation avoids reloading plugin jars *** 
FAILED *** (1 second, 674 milliseconds)
    [info]   java.lang.AssertionError: assertion failed: Compiled file not 
found: /private/space containing path/spark/core/TestExecutorPlugin.class
    
    ...
    ```
    
    ### Does this PR introduce _any_ user-facing change?
    No.
    
    ### How was this patch tested?
    Confirmed `ClassLoaderIsolationSuite` passed even if the repository is in a 
space containing path.
    
    ### Was this patch authored or co-authored using generative AI tooling?
    Generated-by: Claude (via Kiro CLI, auto model selection)
    
    Closes #56125 from sarutak/fix-percent-encoding-issue.
    
    Authored-by: Kousuke Saruta <[email protected]>
    Signed-off-by: Kousuke Saruta <[email protected]>
    (cherry picked from commit 7961cefdc861f23bb35015b2af350cb497ce4e16)
    Signed-off-by: Kousuke Saruta <[email protected]>
---
 .../org/apache/spark/util/SparkTestUtils.scala     | 11 ++++----
 .../apache/spark/util/SparkTestUtilsSuite.scala    | 30 ++++++++++++++++++++++
 2 files changed, 36 insertions(+), 5 deletions(-)

diff --git 
a/common/utils/src/main/scala/org/apache/spark/util/SparkTestUtils.scala 
b/common/utils/src/main/scala/org/apache/spark/util/SparkTestUtils.scala
index fa5f99a1aae2..0af0e0f6de45 100644
--- a/common/utils/src/main/scala/org/apache/spark/util/SparkTestUtils.scala
+++ b/common/utils/src/main/scala/org/apache/spark/util/SparkTestUtils.scala
@@ -53,8 +53,8 @@ private[spark] trait SparkTestUtils {
       Seq(
         "-classpath",
         classpathUrls
-          .map {
-            _.getFile
+          .map { u =>
+            new File(u.toURI).getPath
           }
           .mkString(File.pathSeparator))
     } else {
@@ -123,7 +123,8 @@ private[spark] trait SparkTestUtils {
 
     val options = Seq("-d", classDir.getAbsolutePath) ++ (
       if (classpathUrls.nonEmpty) {
-        Seq("-classpath", 
classpathUrls.map(_.getFile).mkString(File.pathSeparator))
+        Seq("-classpath",
+          classpathUrls.map(u => new 
File(u.toURI).getPath).mkString(File.pathSeparator))
       } else Seq.empty
     )
 
@@ -177,7 +178,7 @@ private[spark] trait SparkTestUtils {
     // on Windows to work around CMD's command-line length limit and by some 
build/CI
     // tools. Expand any such JARs before invoking scalac so the classpath is 
complete.
     val expandedClasspath = classpathUrls.flatMap(expandManifestClasspath)
-    val cpStr = expandedClasspath.map(_.getFile).mkString(File.pathSeparator)
+    val cpStr = expandedClasspath.map(u => new 
File(u.toURI).getPath).mkString(File.pathSeparator)
     val args = Array("-classpath", cpStr, "-d", classDir.getAbsolutePath) ++
       sourceFiles.map(_.getAbsolutePath)
 
@@ -216,7 +217,7 @@ private[spark] trait SparkTestUtils {
    * original URL unchanged.
    */
   private[spark] def expandManifestClasspath(url: URL): Seq[URL] = {
-    val file = new File(url.getFile)
+    val file = new File(url.toURI)
     if (!file.exists() || !file.getName.endsWith(".jar")) return Seq(url)
     try {
       val jarFile = new JarFile(file)
diff --git 
a/common/utils/src/test/scala/org/apache/spark/util/SparkTestUtilsSuite.scala 
b/common/utils/src/test/scala/org/apache/spark/util/SparkTestUtilsSuite.scala
new file mode 100644
index 000000000000..10a599739f6c
--- /dev/null
+++ 
b/common/utils/src/test/scala/org/apache/spark/util/SparkTestUtilsSuite.scala
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.spark.util
+
+import org.scalatest.funsuite.AnyFunSuite // scalastyle:ignore funsuite
+
+class SparkTestUtilsSuite extends AnyFunSuite with SparkTestUtils { // 
scalastyle:ignore funsuite
+
+  test("SPARK-57081: createCompiledClass with spaces in classpath") {
+    val dir = SparkFileUtils.createTempDir(namePrefix = "path with spaces")
+    val sourceFile = new JavaSourceFromString("Hello", "public class Hello {}")
+    val result = createCompiledClass("Hello", dir, sourceFile, 
Seq(dir.toURI.toURL))
+    assert(result.exists(), s"Compiled class file should exist at 
${result.getPath}")
+  }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to