[Lldb-commits] [lldb] 94337fb - [lldb/test] Fix variant double-expansion in LLDBTestCaseFactory (#200943)

via lldb-commits lldb-commits at lists.llvm.org
Mon Jun 1 15:53:58 PDT 2026


Author: Med Ismail Bennani
Date: 2026-06-01T15:53:53-07:00
New Revision: 94337fb6b2d5935cdaa9abecdba8274924119dcc

URL: https://github.com/llvm/llvm-project/commit/94337fb6b2d5935cdaa9abecdba8274924119dcc
DIFF: https://github.com/llvm/llvm-project/commit/94337fb6b2d5935cdaa9abecdba8274924119dcc.diff

LOG: [lldb/test] Fix variant double-expansion in LLDBTestCaseFactory (#200943)

LLDBTestCaseFactory generates the actual test methods that get run: for
every `test*` method on a TestBase subclass, it stamps out one copy per
debug-info format (dwarf, dsym, ...) and, if a variant like
swift_clang's clang/noclang is registered, one copy per variant value on
top. When two test methods in the same class have names that share a
prefix and the longer one is declared first in the file, the shorter
method's expansion ends up re-stamping every copy already produced for
the longer one.

The variant-expansion helper decides what to copy by name-prefix match:
when processing `test_expr`, it grabs `test_expr`, `test_expr_dwarf`,
`test_expr_dsym`, ... and produces a clang/noclang suffix for each one.
The factory was handing it the full running dict of already-synthesized
methods, so by the time `test_expr`'s turn came, the dict also held
`test_expr_stripped_dwarf` and `test_expr_stripped_dsym` from
`test_expr_stripped`. Those names start with `test_expr_` too, so they
pick up a second clang/noclang suffix and inherit `test_expr`'s
xfail/skip predicates.

HiddenIvarsTestCase trips this twice in a row (test_expr_stripped before
test_expr; test_frame_variable_stripped before test_frame_variable).
Upstream `_test_variants` is empty so the bug is latent on mainline, but
any registered variant exposes it.

With swift_clang (values clang/noclang) registered, test_expr_stripped +
test_expr should produce eight methods (4 dwarf/dsym × 2 clang/noclang
per original). Before this patch the factory emits twelve, four of them
junk:

```
  test_expr_stripped_dsym_clang_clang
  test_expr_stripped_dsym_clang_noclang
  test_expr_stripped_dsym_noclang_clang
  test_expr_stripped_dsym_noclang_noclang
  test_expr_stripped_dwarf_clang_clang
  test_expr_stripped_dwarf_clang_noclang
  test_expr_stripped_dwarf_noclang_clang
  test_expr_stripped_dwarf_noclang_noclang
  test_expr_dsym_clang
  test_expr_dsym_noclang
  test_expr_dwarf_clang
  test_expr_dwarf_noclang
```

Track each method's expansion in a local dict and merge it back into the
shared dict only once that method is fully processed, so the variant
helper never sees another method's copies.

Added: 
    

Modified: 
    lldb/packages/Python/lldbsuite/test/lldbtest.py

Removed: 
    


################################################################################
diff  --git a/lldb/packages/Python/lldbsuite/test/lldbtest.py b/lldb/packages/Python/lldbsuite/test/lldbtest.py
index 47f33b8f003a0..ff2362713fe9c 100644
--- a/lldb/packages/Python/lldbsuite/test/lldbtest.py
+++ b/lldb/packages/Python/lldbsuite/test/lldbtest.py
@@ -2019,6 +2019,11 @@ def no_reason(*args, **kwargs):
             if attrname.startswith("test") and not getattr(
                 attrvalue, "__no_debug_info_test__", False
             ):
+                # Track only the entries created by THIS attrname so that
+                # variant expansion doesn't accidentally double-expand entries
+                # from a sibling test method whose name happens to be a strict
+                # prefix of attrname (e.g. test_foo vs test_foo_bar).
+                this_attr_entries = {}
                 # Create debug info variants unless NO_DEBUG_INFO_TESTCASE
                 if not original_testcase.NO_DEBUG_INFO_TESTCASE:
                     # If any debug info categories were explicitly tagged, assume that list to be
@@ -2067,24 +2072,32 @@ def test_method(self, attrvalue=attrvalue):
                         if skip_reason:
                             test_method = unittest.skip(skip_reason)(test_method)
 
-                        newattrs[method_name] = test_method
+                        this_attr_entries[method_name] = test_method
                 else:
-                    # NO_DEBUG_INFO_TESTCASE — put method in newattrs for variant expansion
-                    newattrs[attrname] = attrvalue
-
-                # Expand test variants (e.g. additional variant dimensions)
+                    # NO_DEBUG_INFO_TESTCASE — put method in this_attr_entries
+                    # for variant expansion.
+                    this_attr_entries[attrname] = attrvalue
+
+                # Expand test variants only on the entries we just created
+                # for this attrname, not on the whole newattrs dict (which
+                # would double-expand sibling methods whose names share a
+                # prefix).
                 for variant in _test_variants:
                     if variant.should_expand(attrvalue):
                         xfail_fns = getattr(attrvalue, "__variant_xfail__", {})
                         skip_fns = getattr(attrvalue, "__variant_skip__", {})
-                        newattrs = _expand_test_variants(
+                        this_attr_entries = _expand_test_variants(
                             attrname,
-                            newattrs,
+                            this_attr_entries,
                             variant,
                             xfail_fns=xfail_fns,
                             skip_fns=skip_fns,
                         )
 
+                # Merge this attrname's variant-expanded entries into
+                # newattrs.
+                newattrs.update(this_attr_entries)
+
             else:
                 newattrs[attrname] = attrvalue
 


        


More information about the lldb-commits mailing list