Skip to content

Commit 04efea7

Browse files
test-impact: a script test runs by bare interpreter only when it guards its own entry
An unguarded script test that no package script or usage line names was handed to node or npx tsx, which undid #1570 (a file nothing runs is said so). It still counts and is selected; only a file with require.main === module, import.meta.main or a __main__ guard gets its interpreter as the command. Co-authored-by: axiomcode-bot[bot] <334110751+axiomcode-bot[bot]@users.noreply.github.com>
1 parent d3bda87 commit 04efea7

5 files changed

Lines changed: 29 additions & 5 deletions

File tree

‎plugins/axiomcode/skills/axiomcode/scripts/axiomcode-test-impact‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1430,8 +1430,9 @@ def js_plan(repo, files):
14301430
cmd = _script_for(repo, pkg, f[len(pkg) + 1:] if pkg else f)
14311431
if cmd:
14321432
singles.append((pkg, cmd))
1433-
elif graph_sql.script_test_file(f, _read(os.path.join(repo, f), 400_000)):
1434-
# a script test no package script or usage line names runs under its interpreter, never a guessed framework
1433+
elif graph_sql.script_test_file(f, t := _read(os.path.join(repo, f), 400_000)) and graph_sql.script_main_guard(f, t):
1434+
# a script test no package script or usage line names runs under its interpreter only when it guards its
1435+
# own entry; an unguarded one is named as run by nothing (#1570), never a guessed framework or interpreter
14351436
singles.append(('', f"{'npx tsx' if f.endswith(('.ts', '.mts', '.cts', '.tsx')) else 'node'} {shlex.quote(f)}"))
14361437
else:
14371438
unrun.append(f)

‎plugins/axiomcode/skills/axiomcode/scripts/graph_sql.py‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,20 @@ def script_test_file(rel, text):
576576
return False
577577

578578

579+
# Being a script test says it is a test (counted, selected), not what runs it. Only a file that guards its own entry
580+
# (`require.main === module`, `import.meta.main`, `__name__ == '__main__'`) says it is meant to run under its bare
581+
# interpreter; an unguarded one with no package script or usage line naming it is said to be run by nothing (#1570),
582+
# never handed to an interpreter the project may not have (tsx).
583+
JS_SCRIPT_MAIN = re.compile(r'\brequire\.main\s*===?\s*module\b|\bmodule\s*===?\s*require\.main\b|\bimport\.meta\.main\b')
584+
585+
586+
def script_main_guard(rel, text):
587+
"""whether the script test `rel` guards its own entry, so its interpreter is the command that runs it"""
588+
if not text: return False
589+
if rel.endswith('.py'): return PY_SCRIPT_MAIN.search(text) is not None
590+
return rel.endswith(JS_SCRIPT_EXT) and JS_SCRIPT_MAIN.search(text) is not None
591+
592+
579593
def script_tests(rows, text_of, tm):
580594
"""the module symbols among `rows` ((id, kind, file) of is_test symbols) that are script tests; a file holding a
581595
test in `tm` is its framework's, never a script"""

‎tests/cases/javascript/script-runner-is-a-test/case.json‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,18 @@
66
"avoid": ["helpers.js (script", "0 of"]},
77
{"why": "the runner counts in the summary line: before, the walk reached it and the count said 0 of 0",
88
"run": ["impact", "normalize"],
9-
"want": ["tests: 3 of 3 test method(s)"]},
9+
"want": ["tests: 4 of 4 test method(s)"]},
1010
{"why": "CONTROL: a runner's setup file has top-level code that reaches the change, and is still not a script test",
1111
"run": ["impact", "normalize", "--tests"],
1212
"avoid": ["setup.js (script", "node src/test/setup.js"]},
13-
{"why": "a runner no package script names is run by its interpreter, never by a guessed framework",
13+
{"why": "a runner no package script names, guarded by `require.main === module`, is run by its interpreter, never by a guessed framework",
1414
"run": ["impact", "shout", "--tests"],
1515
"want": ["smoke.js (script: node src/test/smoke.js)", "text.test.js"],
1616
"avoid": ["run.js"]},
17+
{"why": "CONTROL: an unguarded script nothing names still counts as a test, but no interpreter is guessed for it (#1570)",
18+
"run": ["impact", "shout", "--tests"],
19+
"want": ["loose.js (script: no command found"],
20+
"avoid": ["node src/test/loose.js"]},
1721
{"why": "CONTROL: a helper imported by a framework test is not a script test, and the framework test keeps its selection",
1822
"run": ["impact", "sample", "--tests"],
1923
"want": ["text.test.js"],
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
const { shout } = require('../lib/text');
2+
3+
console.log(shout('loose'));
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
const { shout } = require('../lib/text');
22

3-
console.log(shout('smoke'));
3+
if (require.main === module) {
4+
console.log(shout('smoke'));
5+
}

0 commit comments

Comments
 (0)