This is an automated email from the ASF dual-hosted git repository.
github-merge-queue[bot] pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/texera.git
The following commit(s) were added to refs/heads/main by this push:
new 4c9d30a132 test(config): add unit test coverage for the remaining
config objects (#6094)
4c9d30a132 is described below
commit 4c9d30a132672b9a0e8ecfe1d480a473dae16e4d
Author: Xinyuan Lin <[email protected]>
AuthorDate: Sat Jul 4 01:27:46 2026 -0700
test(config): add unit test coverage for the remaining config objects
(#6094)
### What changes were proposed in this PR?
Add unit test coverage for the remaining `common/config` objects,
selected from the Codecov report (all 0%). No production-code changes.
| File | Codecov before | What the tests pin |
| --- | --- | --- |
| `UdfConfig.scala` | 0% | python/R path + log handler defaults from
udf.conf |
| `DefaultsConfig.scala` | 0% | the `reinit` flag and the flattened
`allDefaults` short-key/value map from default.conf |
| `ComputingUnitConfig.scala` | 0% | local/sharing enabled flags |
| `LLMConfig.scala` | 0% | LiteLLM base URL + master key |
| `PekkoConfig.scala` | 0% | actor/serialization, remote/artery, and
cluster/failure-detector settings from cluster.conf (no ActorSystem
started) |
| `PythonUtils.scala` | 0% | `getPythonExecutable` blank→`python3`
fallback and trimmed-path branch |
Reading each value forces resolution from the backing `.conf`;
env/system-property-overridable values are guarded on the override being
unset (mirroring `StorageConfigSpec`).
### Any related issues, documentation, discussions?
Follow-up to the review feedback on #6043: prioritize tests that fill
uncovered code paths.
### How was this PR tested?
- `sbt "Config/testOnly *UdfConfigSpec *DefaultsConfigSpec
*ComputingUnitConfigSpec *LLMConfigSpec *PekkoConfigSpec
*PythonUtilsSpec"` — 13 tests, all green
- `sbt "Config/Test/scalafmtCheck"` and `sbt "Config/scalafixAll
--check"` — clean
### Was this PR authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Opus 4.8 [1M context])
---
.../common/config/ComputingUnitConfigSpec.scala | 43 ++++++++++++
.../texera/common/config/DefaultsConfigSpec.scala | 52 ++++++++++++++
.../texera/common/config/LLMConfigSpec.scala | 39 +++++++++++
.../texera/common/config/PekkoConfigSpec.scala | 79 ++++++++++++++++++++++
.../texera/common/config/PythonUtilsSpec.scala | 52 ++++++++++++++
.../texera/common/config/UdfConfigSpec.scala | 53 +++++++++++++++
6 files changed, 318 insertions(+)
diff --git
a/common/config/src/test/scala/org/apache/texera/common/config/ComputingUnitConfigSpec.scala
b/common/config/src/test/scala/org/apache/texera/common/config/ComputingUnitConfigSpec.scala
new file mode 100644
index 0000000000..40608acf1c
--- /dev/null
+++
b/common/config/src/test/scala/org/apache/texera/common/config/ComputingUnitConfigSpec.scala
@@ -0,0 +1,43 @@
+/*
+ * 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.texera.common.config
+
+import org.scalatest.flatspec.AnyFlatSpec
+import org.scalatest.matchers.should.Matchers
+
+/**
+ * Spec for [[ComputingUnitConfig]]. Reading each value forces resolution
from computing-unit.conf,
+ * so a renamed or mistyped key surfaces here as a ConfigException. Both
flags carry a `${?ENV}`
+ * override, so exact-value assertions are guarded.
+ */
+class ComputingUnitConfigSpec extends AnyFlatSpec with Matchers {
+
+ private def ifUnset(name: String)(assertion: => Any): Unit =
+ if (!sys.env.contains(name) && !sys.props.contains(name)) assertion
+
+ "ComputingUnitConfig" should "resolve the local/sharing flags from
computing-unit.conf" in {
+ ifUnset("COMPUTING_UNIT_LOCAL_ENABLED")(
+ ComputingUnitConfig.localComputingUnitEnabled shouldBe true
+ )
+ ifUnset("COMPUTING_UNIT_SHARING_ENABLED")(
+ ComputingUnitConfig.sharingComputingUnitEnabled shouldBe false
+ )
+ }
+}
diff --git
a/common/config/src/test/scala/org/apache/texera/common/config/DefaultsConfigSpec.scala
b/common/config/src/test/scala/org/apache/texera/common/config/DefaultsConfigSpec.scala
new file mode 100644
index 0000000000..3da26e1ff8
--- /dev/null
+++
b/common/config/src/test/scala/org/apache/texera/common/config/DefaultsConfigSpec.scala
@@ -0,0 +1,52 @@
+/*
+ * 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.texera.common.config
+
+import org.scalatest.flatspec.AnyFlatSpec
+import org.scalatest.matchers.should.Matchers
+
+/**
+ * Spec for [[DefaultsConfig]]. Reading each value forces resolution from
default.conf, so a
+ * renamed or mistyped key surfaces here as a ConfigException. The `reinit`
flag carries a
+ * `${?ENV}` override, so its exact-value assertion is guarded.
+ */
+class DefaultsConfigSpec extends AnyFlatSpec with Matchers {
+
+ private def ifUnset(name: String)(assertion: => Any): Unit =
+ if (!sys.env.contains(name) && !sys.props.contains(name)) assertion
+
+ "DefaultsConfig.reinit" should "default the reset-to-defaults flag to false"
in {
+ ifUnset("CONFIG_SERVICE_ALWAYS_RESET_CONFIGURATIONS_TO_DEFAULT_VALUES")(
+ DefaultsConfig.reinit shouldBe false
+ )
+ }
+
+ "DefaultsConfig.allDefaults" should "flatten default.conf into
short-key/value entries" in {
+ val defaults = DefaultsConfig.allDefaults
+ defaults should not be empty
+ // scalar leaves are flattened to their last path segment
+ ifUnset("DATASET_SINGLE_FILE_UPLOAD_MAX_SIZE_MIB")(
+ defaults.get("single_file_upload_max_size_mib") shouldBe Some("20")
+ )
+ ifUnset("GUI_TABS_HUB_ENABLED")(defaults.get("hub_enabled") shouldBe
Some("true"))
+ // every value is rendered as a String
+ defaults.values.foreach(_ shouldBe a[String])
+ }
+}
diff --git
a/common/config/src/test/scala/org/apache/texera/common/config/LLMConfigSpec.scala
b/common/config/src/test/scala/org/apache/texera/common/config/LLMConfigSpec.scala
new file mode 100644
index 0000000000..ee64a32300
--- /dev/null
+++
b/common/config/src/test/scala/org/apache/texera/common/config/LLMConfigSpec.scala
@@ -0,0 +1,39 @@
+/*
+ * 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.texera.common.config
+
+import org.scalatest.flatspec.AnyFlatSpec
+import org.scalatest.matchers.should.Matchers
+
+/**
+ * Spec for [[LLMConfig]]. Reading each value forces resolution from
llm.conf, so a renamed or
+ * mistyped key surfaces here as a ConfigException. Both values carry a
`${?ENV}` override, so
+ * exact-value assertions are guarded.
+ */
+class LLMConfigSpec extends AnyFlatSpec with Matchers {
+
+ private def ifUnset(name: String)(assertion: => Any): Unit =
+ if (!sys.env.contains(name) && !sys.props.contains(name)) assertion
+
+ "LLMConfig" should "resolve the LiteLLM base URL and master key from
llm.conf" in {
+ ifUnset("LITELLM_BASE_URL")(LLMConfig.baseUrl shouldBe
"http://0.0.0.0:4000")
+ ifUnset("LITELLM_MASTER_KEY")(LLMConfig.masterKey shouldBe "")
+ }
+}
diff --git
a/common/config/src/test/scala/org/apache/texera/common/config/PekkoConfigSpec.scala
b/common/config/src/test/scala/org/apache/texera/common/config/PekkoConfigSpec.scala
new file mode 100644
index 0000000000..13282f286d
--- /dev/null
+++
b/common/config/src/test/scala/org/apache/texera/common/config/PekkoConfigSpec.scala
@@ -0,0 +1,79 @@
+/*
+ * 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.texera.common.config
+
+import org.scalatest.flatspec.AnyFlatSpec
+import org.scalatest.matchers.should.Matchers
+
+/**
+ * Spec for [[PekkoConfig]]. Reading keys off the returned config forces
resolution of cluster.conf
+ * (merged with the Typesafe default application config), so a renamed or
mistyped key surfaces here
+ * as a ConfigException. The log level carries a `${?ENV}` override, so its
assertion is guarded.
+ */
+class PekkoConfigSpec extends AnyFlatSpec with Matchers {
+
+ "PekkoConfig.pekkoConfig" should "load the actor/serialization settings from
cluster.conf" in {
+ val config = PekkoConfig.pekkoConfig
+ config.getString("pekko.actor.provider") shouldBe "cluster"
+ config.getBoolean("pekko.actor.allow-java-serialization") shouldBe false
+ config.getBoolean("pekko.actor.enable-additional-serialization-bindings")
shouldBe true
+ config.getString(
+ "pekko.actor.serializers.kryo"
+ ) shouldBe "io.altoo.serialization.kryo.pekko.PekkoKryoSerializer"
+ config.getStringList("pekko.loggers").get(0) shouldBe
"org.apache.pekko.event.slf4j.Slf4jLogger"
+ config.getString(
+ "pekko.logging-filter"
+ ) shouldBe "org.apache.pekko.event.slf4j.Slf4jLoggingFilter"
+ }
+
+ it should "expose the remote/artery transport settings" in {
+ val config = PekkoConfig.pekkoConfig
+ config.getString("pekko.remote.artery.transport") shouldBe "tcp"
+ config.getString("pekko.remote.artery.canonical.hostname") shouldBe
"0.0.0.0"
+ config.getInt("pekko.remote.artery.canonical.port") shouldBe 0
+ config.getBytes("pekko.remote.artery.advanced.maximum-frame-size")
shouldBe 31457280L
+ config.getBytes("pekko.remote.artery.advanced.maximum-large-frame-size")
shouldBe 125829120L
+ }
+
+ it should "expose the cluster and failure-detector settings" in {
+ val config = PekkoConfig.pekkoConfig
+ config.getStringList("pekko.cluster.seed-nodes").size shouldBe 0
+ config.getString(
+ "pekko.cluster.downing-provider-class"
+ ) shouldBe "org.apache.pekko.cluster.sbr.SplitBrainResolverProvider"
+ config.getString("pekko.cluster.gossip-interval") shouldBe "10s"
+
config.getString("pekko.cluster.failure-detector.acceptable-heartbeat-pause")
shouldBe "50s"
+ config.getString(
+ "pekko-kryo-serialization.kryo-initializer"
+ ) shouldBe "org.apache.texera.amber.engine.common.AmberKryoInitializer"
+ }
+
+ it should "resolve the log levels" in {
+ val config = PekkoConfig.pekkoConfig
+ // ${?TEXERA_SERVICE_LOG_LEVEL} can be satisfied by an OS env var or a JVM
system property
+ if (
+ !sys.env
+ .contains("TEXERA_SERVICE_LOG_LEVEL") &&
!sys.props.contains("TEXERA_SERVICE_LOG_LEVEL")
+ ) {
+ config.getString("pekko.loglevel") shouldBe "INFO"
+ }
+ config.getString("pekko.stdout-loglevel") shouldBe "INFO"
+ }
+}
diff --git
a/common/config/src/test/scala/org/apache/texera/common/config/PythonUtilsSpec.scala
b/common/config/src/test/scala/org/apache/texera/common/config/PythonUtilsSpec.scala
new file mode 100644
index 0000000000..2878041b34
--- /dev/null
+++
b/common/config/src/test/scala/org/apache/texera/common/config/PythonUtilsSpec.scala
@@ -0,0 +1,52 @@
+/*
+ * 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.texera.common.config
+
+import org.scalatest.flatspec.AnyFlatSpec
+import org.scalatest.matchers.should.Matchers
+
+/**
+ * Spec for [[PythonUtils]]. `getPythonExecutable` falls back to "python3"
when the configured
+ * python path is blank, else returns the trimmed path. The blank-path
default depends on
+ * UDF_PYTHON_PATH, so the exact-value assertion is guarded on that override
being unset.
+ */
+class PythonUtilsSpec extends AnyFlatSpec with Matchers {
+
+ "PythonUtils.getPythonExecutable" should "fall back to python3 when no
python path is configured" in {
+ // ${?UDF_PYTHON_PATH} can be satisfied by an OS env var or a JVM system
property
+ val overrideValue =
+ sys.env.get("UDF_PYTHON_PATH").orElse(sys.props.get("UDF_PYTHON_PATH"))
+ if (overrideValue.forall(_.trim.isEmpty)) {
+ PythonUtils.getPythonExecutable shouldBe "python3"
+ }
+ }
+
+ it should "never return a blank or untrimmed executable" in {
+ val executable = PythonUtils.getPythonExecutable
+ executable should not be empty
+ executable shouldBe executable.trim
+ }
+
+ it should "match its own fallback logic against the backing UdfConfig value"
in {
+ val expected =
+ if (UdfConfig.pythonPath.trim.isEmpty) "python3" else
UdfConfig.pythonPath.trim
+ PythonUtils.getPythonExecutable shouldBe expected
+ }
+}
diff --git
a/common/config/src/test/scala/org/apache/texera/common/config/UdfConfigSpec.scala
b/common/config/src/test/scala/org/apache/texera/common/config/UdfConfigSpec.scala
new file mode 100644
index 0000000000..5490268747
--- /dev/null
+++
b/common/config/src/test/scala/org/apache/texera/common/config/UdfConfigSpec.scala
@@ -0,0 +1,53 @@
+/*
+ * 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.texera.common.config
+
+import org.scalatest.flatspec.AnyFlatSpec
+import org.scalatest.matchers.should.Matchers
+
+/**
+ * Spec for [[UdfConfig]]. Reading each value forces resolution from
udf.conf, so a renamed or
+ * mistyped key surfaces here as a ConfigException. Every value carries a
`${?ENV}` override, so
+ * exact-value assertions are guarded on the override being absent from env
and system properties.
+ */
+class UdfConfigSpec extends AnyFlatSpec with Matchers {
+
+ private def ifUnset(name: String)(assertion: => Any): Unit =
+ if (!sys.env.contains(name) && !sys.props.contains(name)) assertion
+
+ "UdfConfig" should "resolve the python and R defaults from udf.conf" in {
+ ifUnset("UDF_PYTHON_PATH")(UdfConfig.pythonPath shouldBe "")
+ ifUnset("UDF_R_PATH")(UdfConfig.rPath shouldBe "")
+ ifUnset("UDF_PYTHON_LOG_STREAMHANDLER_LEVEL")(
+ UdfConfig.pythonLogStreamHandlerLevel shouldBe "INFO"
+ )
+
ifUnset("UDF_PYTHON_LOG_FILEHANDLER_DIR")(UdfConfig.pythonLogFileHandlerDir
shouldBe "/tmp/")
+
ifUnset("UDF_PYTHON_LOG_FILEHANDLER_LEVEL")(UdfConfig.pythonLogFileHandlerLevel
shouldBe "INFO")
+ }
+
+ it should "resolve the non-empty log format strings" in {
+ ifUnset("UDF_PYTHON_LOG_STREAMHANDLER_FORMAT")(
+ UdfConfig.pythonLogStreamHandlerFormat should not be empty
+ )
+ ifUnset("UDF_PYTHON_LOG_FILEHANDLER_FORMAT")(
+ UdfConfig.pythonLogFileHandlerFormat should not be empty
+ )
+ }
+}