Repository navigation
Description
- Repository:
pingdotgg/ts-rust - Target commit:
3f370aaf5fdcf141504d6ebab9b14fc4b6ff3af4 - File:
scripts/goport/test-hunks.py:17
Summary
The test-module prefilter regex only matches cfg(test) and cfg(all(...test)); it does not match cfg(any(test)). A file declared with #[cfg(any(test))] mod any_helpers; is therefore excluded from test_mods, and its test-only lines are attributed to production in the --all report. The attribute predicate is a legal and common way to mark test-only modules, so the prefilter is narrower than the compiler's actual test gating.
Affected code
scripts/goport/test-hunks.py:
9 BASE (default origin/main) and HEAD (default HEAD), and HEAD. For each file with a test change it prints:
10
11 new tests test fns (#[test]) that HEAD adds
12 removed tests test fns that the base has and HEAD does not
13 changed tests test fns of both whose text differs, with their removed and added line counts
14 changed helpers other test code (a mock, a helper fn) that HEAD changes, by enclosing item
15 removed lines each removed or changed line of base test code, with its enclosing fn (as int95's tool did)
16
17 Test code is a file under a tests/ dir, a file that a test-only `mod NAME;` declares, and the item after a
18 test-only attribute: #[test], #[tokio::test], or a #[cfg(P)] whose P holds only in a test build (test,
19 all(..., test, ...), any(test, ...) with test-only arguments; not(test) is production). An item with an item
20 keyword (fn, mod, impl, use, let, ...) ends at the `;` or `}` that closes it. A field, a variant, a match arm
21 or a parameter (no item keyword) also ends at a `,`. Any item ends before a close bracket that takes the depth
22 below 0 (the struct, literal or match that holds it closes there). Only (), [] and {} are brackets, so a
23 field type split over lines inside <...> ends early. A test fn is a #[test] fn or the fn of a test macro
24 call (`child_test! { fn name() {...} }`). Comments, strings and char literals do not count toward the
25 brackets. Production lines of a hunk are counted per file and not listed; with --all, files with only
26 production changes are listed too. A test fn is keyed by its name and its place among fns of that name in
27 the file.
28
29 selftest checks these rules on small Rust cases (the regions, the test fns, the test-only mod declarations)
Expected behavior
A test-only module declaration guarded by #[cfg(any(test))] is recognized as test code and added to test_mods.
Actual behavior
scripts/goport/test-hunks.py's test_module_files builds candidate hits with git grep -l -E r"cfg\\((all\\(.*)?test", which does not match a legal #[cfg(any(test))] mod NAME; declaration even though test_only accepts any(test); the file is omitted from test_mods and its test-only contents are classified as production.
How to reproduce
Run test-hunks.py --all on a change adding #[cfg(any(test))] mod any_helpers;; the file is reported as production lines.
Root cause
The test-module prefilter regex only matches cfg(test) and cfg(all(...test)); it does not match cfg(any(test)). A file declared with #[cfg(any(test))] mod any_helpers; is therefore excluded from test_mods, and its test-only lines are attributed to production in the --all report. The attribute predicate is a legal and common way to mark test-only modules, so the prefilter is narrower than the compiler's actual test gating.
Suggested fix
Extend the prefilter to cfg(any(...test...)), e.g.
TEST_CFG = re.compile(r"cfg\((?:all\([^)]*)?(?:any\([^)]*)?test")and add a fixture with #[cfg(any(test))] mod any_helpers; asserting the file lands in test_mods.
Activity