[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