This is an automated email from the ASF dual-hosted git repository.
uros-b pushed a commit to branch branch-4.x
in repository https://gitbox.apache.org/repos/asf/spark.git
The following commit(s) were added to refs/heads/branch-4.x by this push:
new 3f803bc0b144 [SPARK-58689][CORE][TEST] Add tests for SparkStringUtils
padding and abbreviation helpers
3f803bc0b144 is described below
commit 3f803bc0b14415fb87eb8cc7428b4a320aef6d68
Author: Uros <[email protected]>
AuthorDate: Tue Aug 18 09:36:35 2026 +0000
[SPARK-58689][CORE][TEST] Add tests for SparkStringUtils padding and
abbreviation helpers
### What changes were proposed in this pull request?
Adds `SparkStringUtilsSuite`, covering `isBlank`/`isNotBlank`, `leftPad`,
both `rightPad` overloads, both `abbreviate` overloads, `strip`, and
`stringToSeq`.
### Why are the changes needed?
`SparkStringUtils` currently has no test suite, while the sibling utilities
in the same module (`SparkErrorUtilsSuite`, `SparkFileUtilsSuite`,
`VersionUtilsSuite`, ...) each have one. The helpers are not incidental:
`leftPad`/`rightPad` format the column output of `Dataset.show`, and
`abbreviate` is used to build Kubernetes application-name labels. The methods
arrived across a series of changes that replaced Apache Commons and Guava
equivalents, and none of those added direct tests.
The three-argument `rightPad(str, width, padStr)` holds the most
error-prone arithmetic in the file (pad repetition plus truncation of the final
repetition) and currently has no caller, so it had no coverage of any kind.
### Does this PR introduce _any_ user-facing change?
No. Tests only.
### How was this patch tested?
This is the test. Every expected value was derived by executing the current
implementations rather than computed by hand, including the pad-truncation
cases (`rightPad("a", 4, "xy")` is `"axyx"`) and the null pass-through paths.
The suite was run locally: 6 tests, 27 assertions, all passing.
The suite extends `AnyFunSuite` with the `scalastyle:ignore funsuite`
marker, matching every sibling suite in this module; `common/utils` does not
depend on `spark-core`, so `SparkFunSuite` is not available here.
### Was this patch authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Opus 4.8)
Closes #57890 from uros-b/test-sparkstringutils.
Authored-by: Uros <[email protected]>
Signed-off-by: Uros Bojanic <[email protected]>
(cherry picked from commit 6e695dd878a9eeacefe99fc40ae89944a58e91c1)
Signed-off-by: Uros Bojanic <[email protected]>
---
.../apache/spark/util/SparkStringUtilsSuite.scala | 85 ++++++++++++++++++++++
1 file changed, 85 insertions(+)
diff --git
a/common/utils/src/test/scala/org/apache/spark/util/SparkStringUtilsSuite.scala
b/common/utils/src/test/scala/org/apache/spark/util/SparkStringUtilsSuite.scala
new file mode 100644
index 000000000000..93fb4a745d44
--- /dev/null
+++
b/common/utils/src/test/scala/org/apache/spark/util/SparkStringUtilsSuite.scala
@@ -0,0 +1,85 @@
+/*
+ * 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 SparkStringUtilsSuite extends AnyFunSuite { // scalastyle:ignore funsuite
+
+ test("isBlank treats null and whitespace-only strings as blank") {
+ assert(SparkStringUtils.isBlank(null))
+ assert(SparkStringUtils.isBlank(""))
+ assert(SparkStringUtils.isBlank(" "))
+ assert(!SparkStringUtils.isBlank("a"))
+ assert(SparkStringUtils.isNotBlank("a"))
+ assert(!SparkStringUtils.isNotBlank(" "))
+ }
+
+ test("leftPad and rightPad pad with spaces up to the requested width") {
+ assert(SparkStringUtils.leftPad("hi", 5) === " hi")
+ assert(SparkStringUtils.rightPad("hi", 5) === "hi ")
+ // A width that is not larger than the input is a no-op, and null is
passed through.
+ assert(SparkStringUtils.leftPad("hello", 5) === "hello")
+ assert(SparkStringUtils.rightPad("hello", 3) === "hello")
+ assert(SparkStringUtils.leftPad(null, 5) === null)
+ assert(SparkStringUtils.rightPad(null, 5) === null)
+ }
+
+ test("rightPad repeats the pad string and truncates the last repetition") {
+ assert(SparkStringUtils.rightPad("x", 6, "*") === "x*****")
+ assert(SparkStringUtils.rightPad("a", 5, "xy") === "axyxy")
+ // Only the first character of the final "xy" fits within the width.
+ assert(SparkStringUtils.rightPad("a", 4, "xy") === "axyx")
+ assert(SparkStringUtils.rightPad("hello", 3, "*") === "hello")
+ assert(SparkStringUtils.rightPad(null, 5, "*") === null)
+ }
+
+ test("rightPad with an empty pad string fails when padding is required") {
+ // The pad length is used as a divisor, so an empty pad string divides by
zero.
+ // Documented here rather than guarded, since callers are expected to pass
a
+ // non-empty pad string.
+ intercept[ArithmeticException] {
+ SparkStringUtils.rightPad("a", 5, "")
+ }
+ // No padding is needed in these cases, so the divisor is never reached.
+ assert(SparkStringUtils.rightPad("hello", 5, "") === "hello")
+ assert(SparkStringUtils.rightPad("hello", 3, "") === "hello")
+ assert(SparkStringUtils.rightPad(null, 5, "") === null)
+ }
+
+ test("abbreviate truncates with the marker and leaves short inputs
untouched") {
+ assert(SparkStringUtils.abbreviate("hello world", 8) === "hello...")
+ assert(SparkStringUtils.abbreviate("abc", 8) === "abc")
+ assert(SparkStringUtils.abbreviate("abcdefgh", "..", 4) === "ab..")
+ // An empty marker makes abbreviate a plain truncation.
+ assert(SparkStringUtils.abbreviate("abcdefgh", "", 3) === "abc")
+ assert(SparkStringUtils.abbreviate(null, 5) === null)
+ assert(SparkStringUtils.abbreviate("abc", null, 2) === null)
+ }
+
+ test("strip removes the given prefix and suffix when present") {
+ assert(SparkStringUtils.strip("\"path\"", "\"") === "path")
+ assert(SparkStringUtils.strip("path", "\"") === "path")
+ assert(SparkStringUtils.strip(null, "\"") === null)
+ assert(SparkStringUtils.strip("path", null) === "path")
+ }
+
+ test("stringToSeq trims entries and drops empty ones") {
+ assert(SparkStringUtils.stringToSeq(" a, b ,,c ") === Seq("a", "b", "c"))
+ assert(SparkStringUtils.stringToSeq("") === Seq.empty)
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]