Skip to content

test-hunks.py misses files declared by #[cfg(any(test))] #143

Open

Description

@soarkit
  • 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions