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 _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
