[llvm] [LIT][NFC] Fix double slash in GoogleTest format test names (PR #210296)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 10 05:29:30 PDT 2026
https://github.com/kekaczma updated https://github.com/llvm/llvm-project/pull/210296
>From fac7f3a4aaa085e747812e87e5b654294e9ff092 Mon Sep 17 00:00:00 2001
From: Katarzyna Kaczmarska <katarzynax.e.kaczmarska at intel.com>
Date: Fri, 17 Jul 2026 12:40:28 +0200
Subject: [PATCH] [LIT][NFC] Fix double slash in GoogleTest format test names
When test_sub_dirs is empty, split creates [''] causing double slashes in test names like 'Suite :: device//device-test/Name'.
Filter empty strings and use ['.'] as default. Add helper method _make_test_path() to construct paths, omitting '.' subdirectory to produce 'Suite :: device/device-test/Name'.
Test added to verify the fix and prevent regression.
This change improves test name consistency, which is needed for automated CI test result collection and analysis
---
llvm/utils/lit/lit/formats/googletest.py | 32 ++++++-
.../googletest-empty-subdir/device-test.py | 86 +++++++++++++++++++
.../Inputs/googletest-empty-subdir/lit.cfg | 5 ++
.../lit/tests/googletest-empty-subdir.py | 15 ++++
4 files changed, 134 insertions(+), 4 deletions(-)
create mode 100755 llvm/utils/lit/tests/Inputs/googletest-empty-subdir/device-test.py
create mode 100644 llvm/utils/lit/tests/Inputs/googletest-empty-subdir/lit.cfg
create mode 100644 llvm/utils/lit/tests/googletest-empty-subdir.py
diff --git a/llvm/utils/lit/lit/formats/googletest.py b/llvm/utils/lit/lit/formats/googletest.py
index e567cce541beb..89b457f778a54 100644
--- a/llvm/utils/lit/lit/formats/googletest.py
+++ b/llvm/utils/lit/lit/formats/googletest.py
@@ -4,6 +4,7 @@
import shlex
import subprocess
import sys
+from typing import Optional
import lit.Test
import lit.TestRunner
@@ -14,9 +15,17 @@
class GoogleTest(TestFormat):
- def __init__(self, test_sub_dirs, test_suffix, run_under=[], test_prefix=None):
+ def __init__(
+ self,
+ test_sub_dirs: Optional[str],
+ test_suffix: str,
+ run_under=[],
+ test_prefix=None,
+ ):
self.seen_executables = set()
- self.test_sub_dirs = str(test_sub_dirs).split(";")
+ # Split on ";" can create [''] when test_sub_dirs is empty string,
+ # which causes leading slashes in test paths. Filter empty strings.
+ self.test_sub_dirs = [d for d in str(test_sub_dirs).split(";") if d] or ["."]
# On Windows, assume tests will also end in '.exe'.
exe_suffix = str(test_suffix)
@@ -28,6 +37,17 @@ def __init__(self, test_sub_dirs, test_suffix, run_under=[], test_prefix=None):
self.test_prefixes = {test_prefix} if test_prefix else None
self.run_under = run_under
+ def _make_test_path(
+ self, path_in_suite: tuple, subdir: str, fn: str, *extra: str, litConfig=None
+ ) -> tuple:
+ """Construct test path, omitting '.' subdirectory."""
+ components = () if subdir == "." else (subdir,)
+ test_path = path_in_suite + components + (fn,) + extra
+ if litConfig and litConfig.debug:
+ subdir_display = "." if subdir == "." else repr(subdir)
+ litConfig.note(f"GoogleTest path: {test_path} (subdir={subdir_display})")
+ return test_path
+
def get_num_tests(self, path, litConfig, localConfig):
list_test_cmd = self.prepareCmd(
[path, "--gtest_list_tests", "--gtest_filter=-*DISABLED_*"]
@@ -80,11 +100,13 @@ def getTestsInDirectory(self, testSuite, path_in_suite, litConfig, localConfig):
# Create one lit test for each shard.
for idx in range(nshard):
- testPath = path_in_suite + (
+ testPath = self._make_test_path(
+ path_in_suite,
subdir,
fn,
str(idx),
str(nshard),
+ litConfig=litConfig,
)
json_file = (
"-".join(
@@ -106,7 +128,9 @@ def getTestsInDirectory(self, testSuite, path_in_suite, litConfig, localConfig):
gtest_json_file=json_file,
)
else:
- testPath = path_in_suite + (subdir, fn)
+ testPath = self._make_test_path(
+ path_in_suite, subdir, fn, litConfig=litConfig
+ )
json_file = (
"-".join(
[
diff --git a/llvm/utils/lit/tests/Inputs/googletest-empty-subdir/device-test.py b/llvm/utils/lit/tests/Inputs/googletest-empty-subdir/device-test.py
new file mode 100755
index 0000000000000..7a0ade1f10d6f
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/googletest-empty-subdir/device-test.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python
+"""Mock GoogleTest executable for testing lit GoogleTest format.
+
+Simulates GoogleTest discovery (--gtest_list_tests) and execution
+with JSON output. Used by googletest-empty-subdir.py test.
+"""
+
+import os
+import sys
+
+# Number of parts to split GTEST_OUTPUT format ("json:/path/to/file.json")
+# Split at first colon only to handle paths with colons (e.g., Windows C:\\path)
+PROTOCOL_MAX_SPLIT = 1
+
+if len(sys.argv) == 3 and sys.argv[1] == "--gtest_list_tests":
+ if sys.argv[2] != "--gtest_filter=-*DISABLED_*":
+ raise ValueError(f"unexpected argument: {sys.argv[2]}")
+ print(
+ """\
+FirstTest.
+ subTestA
+ subTestB
+SecondTest.
+ subTestC"""
+ )
+ sys.exit(0)
+elif len(sys.argv) != 1:
+ # sharding and json output are specified using environment variables
+ raise ValueError(f"unexpected argument: {' '.join(sys.argv[1:])!r}")
+
+if "GTEST_OUTPUT" not in os.environ:
+ raise ValueError("missing environment variable: GTEST_OUTPUT")
+
+if not os.environ["GTEST_OUTPUT"].startswith("json:"):
+ raise ValueError(f"must emit json output: {os.environ['GTEST_OUTPUT']}")
+
+output = """\
+{
+"random_seed": 123,
+"testsuites": [
+ {
+ "name": "FirstTest",
+ "testsuite": [
+ {
+ "name": "subTestA",
+ "result": "COMPLETED",
+ "time": "0.001s"
+ },
+ {
+ "name": "subTestB",
+ "result": "COMPLETED",
+ "time": "0.001s",
+ "failures": [
+ {
+ "failure": "Test intentionally fails",
+ "type": ""
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "SecondTest",
+ "testsuite": [
+ {
+ "name": "subTestC",
+ "result": "COMPLETED",
+ "time": "0.001s"
+ }
+ ]
+ }
+]
+}"""
+
+json_filename = os.environ["GTEST_OUTPUT"].split(":", PROTOCOL_MAX_SPLIT)[1]
+with open(json_filename, "w", encoding="utf-8") as f:
+ print("[ RUN ] FirstTest.subTestA", flush=True)
+ print("[ OK ] FirstTest.subTestA (1 ms)", flush=True)
+ print("[ RUN ] FirstTest.subTestB", flush=True)
+ print("Test intentionally fails", file=sys.stderr, flush=True)
+ print("[ FAILED ] FirstTest.subTestB (1 ms)", flush=True)
+ print("[ RUN ] SecondTest.subTestC", flush=True)
+ print("[ OK ] SecondTest.subTestC (1 ms)", flush=True)
+ f.write(output)
+
+sys.exit(1)
diff --git a/llvm/utils/lit/tests/Inputs/googletest-empty-subdir/lit.cfg b/llvm/utils/lit/tests/Inputs/googletest-empty-subdir/lit.cfg
new file mode 100644
index 0000000000000..311b617b98a52
--- /dev/null
+++ b/llvm/utils/lit/tests/Inputs/googletest-empty-subdir/lit.cfg
@@ -0,0 +1,5 @@
+import lit.formats
+
+config.name = "googletest-empty-subdir"
+# Tests empty test_sub_dirs to verify no leading/double slashes in names
+config.test_format = lit.formats.GoogleTest("", "-test")
diff --git a/llvm/utils/lit/tests/googletest-empty-subdir.py b/llvm/utils/lit/tests/googletest-empty-subdir.py
new file mode 100644
index 0000000000000..442541a473482
--- /dev/null
+++ b/llvm/utils/lit/tests/googletest-empty-subdir.py
@@ -0,0 +1,15 @@
+# Check that empty test_sub_dirs produces clean test names without double slashes.
+
+# RUN: not %{lit} -v --no-gtest-sharding %{inputs}/googletest-empty-subdir > %t.out
+# RUN: FileCheck < %t.out %s
+
+# CHECK: FAIL: googletest-empty-subdir :: device-test.py
+# CHECK: *** TEST 'googletest-empty-subdir :: device-test.py' FAILED ***
+
+# CHECK: Failed Tests (1):
+# CHECK-NEXT: googletest-empty-subdir :: FirstTest/subTestB
+
+# Verify no double slashes or leading slashes appear in test names
+# CHECK-NOT: :: /FirstTest
+# CHECK-NOT: :: device-test//FirstTest
+# CHECK-NOT: :: //device-test
More information about the llvm-commits
mailing list