Skip to content

test-hunks.py aborts with CalledProcessError when the cfg(test) prefilter has no matches #139

Open

Description

@soarkit
  • Repository: pingdotgg/ts-rust
  • Target commit: 396bf652eed0b77453a67da247dde0d0a7130b0a
  • File: scripts/goport/test-hunks.py:224

Summary

test-hunks.py uses a git() helper that runs subprocesses with check=True, and calls git grep -l -E 'cfg\((all\(.*)?test' as a prefilter for test modules. git grep exits 1 when no file matches, which is a normal “no matches” result, but check=True turns it into an uncaught CalledProcessError at test-hunks.py:314/46. A change whose only test code lives under crates/*/tests/ (no cfg(test) module declaration) therefore crashes the script instead of producing an empty match set and a report.

Affected code

scripts/goport/test-hunks.py:

  216      def fn_text(self, key):
  217          a, b = self.fns[key]
  218          return "\n".join(self.lines[a : b + 1])
  219  
  220      def fn_at(self, k):
  221          return next((key for key, (a, b) in self.fns.items() if a <= k <= b), None)
  222  
  223  
  224  def next_line(starts, off):
  225      lo, hi = 0, len(starts) - 1
  226      while lo < hi:
  227          mid = (lo + hi + 1) // 2
  228          if starts[mid] <= off:
  229              lo = mid
  230          else:
  231              hi = mid - 1
  232      return lo
  233  
  234  
  235  def test_module_files(cwd, rev):
  236      """Paths that a `#[cfg(test)] mod NAME;` declares at REV (path attributes too)."""
  237      out = set()
  238      hits = git(cwd, "grep", "-l", "-E", r"cfg\((all\(.*)?test", rev, "--", "crates/*.rs")
  239      for hit in hits.split():
  240          path = hit.split(":", 1)[1]
  241          text = show(cwd, rev, path) or ""
  242          directory = path.rsplit("/", 1)[0]
  243          stem = path.rsplit("/", 1)[1][:-3]
  244          # A mod.rs, lib.rs, main.rs or *_root.rs declares children in its own dir; other files in dir/stem.
  245          own = stem in ("mod", "lib", "main") or stem.endswith("_root")
  246          for m in MOD_DECL.finditer(mask(text)):
  247              # mask() blanks the path string: read it from the text at the same offsets.
  248              raw = MOD_DECL.match(text, m.start())
  249              if raw and raw.group(1):
  250                  out.add(f"{directory}/{raw.group(1)}")
  251                  continue
  252              base = directory if own else f"{directory}/{stem}"
  253              out.add(f"{base}/{m.group(2)}.rs")
  254              out.add(f"{base}/{m.group(2)}/mod.rs")
  255              # A flat layout (scanner_util.rs declares scanner_test next to it).
  256              out.add(f"{directory}/{m.group(2)}.rs")
  257      return out
  258  
  259  
  260  def main(argv):
  261      if argv[:1] in (["help"], ["-h"], ["--help"]):
  262          print(__doc__.strip())
  263          return 0

Expected behavior

test-hunks.py must accept a valid repository revision even when no #[cfg(test)] mod declarations match, and must not abort outside its documented exit-code contract.

Actual behavior

When git grep finds no matching #[cfg(test)] mod declarations, hits = git(...) aborts via CalledProcessError instead of producing an empty set. The unhandled error prevents the tool from analyzing legal test files under tests/ and violates the documented exit-code contract.

How to reproduce

Run test-hunks.py --base HEAD~1 --head HEAD on a change whose only test code is under crates/*/tests/; the script aborts with CalledProcessError.

Root cause

test-hunks.py uses a git() helper that runs subprocesses with check=True, and calls git grep -l -E 'cfg\((all\(.*)?test' as a prefilter for test modules. git grep exits 1 when no file matches, which is a normal “no matches” result, but check=True turns it into an uncaught CalledProcessError at test-hunks.py:314/46. A change whose only test code lives under crates/*/tests/ (no cfg(test) module declaration) therefore crashes the script instead of producing an empty match set and a report.

Suggested fix

Treat git grep exit 1 as "no matches":

try:
    out = git("grep", "-l", "-E", pattern, "HEAD", "--", "crates/*.rs")
except subprocess.CalledProcessError as exc:
    if exc.returncode != 1: raise
    out = ""

Add a test whose only test code is under crates/*/tests/ and assert the script still emits a report with exit 0.

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