Files
ledger cd3b285a66 spark: repair Q125 line-counter verifier and land its graders
verify_line_counter.sh pinned the pre-Q125 tool at a host path
(/root/.hermes/wizard-outputs/spark/line_counter.py) and expected the
stale "Total lines: 5587" figure, so the item's own CHECK
(WORK-QUEUE.md:13377) reddened: usage-line output, rc 1.

Repair (confined to wizard-work/spark):
- verify_line_counter.sh resolves line_counter.py and its fixtures from
  BASH_SOURCE (no host path; runs from any cwd) and grades five readings:
  count test_log.txt == wc -l == 10; csv test_data.csv == csv-module
  field count == 5; count test_blank.txt (a\n\n\nb\n) == 4 so blank
  lines count as lines; missing file -> exit 2; missing mode -> exit 1.
- test_line_counter.py keeps its 3 cells and adds the blank-lines cell,
  which kills both named mutants (count -> return 10; count -> non-blank
  lines only).
- test_blank.txt: new fixture, exactly printf 'a\n\n\nb\n' (4 lines).
- README.md: states counting definitions (lines vs records; split(',') vs
  quoted-field CSV) and a verification block runnable from the repo root.
- VERIFICATION.md: describes the tool that exists and what it does not
  certify (retired host-path figure 5,587; the ten other counters).

Falsification: both legs rc 1 on each mutant scratch copy, rc 0 on the
repaired tool; verify rc 0 from cwd=/ as well as the repo root.
Q125's own CHECK exits 0 at this HEAD.
2026-10-31 17:55:11 +00:00

66 lines
2.1 KiB
Python

#!/usr/bin/env python3
"""Test script for line_counter.py utility.
Cells:
1. CSV count mode on test_data.csv -> 5 fields.
2. Line count mode on test_log.txt -> 10 lines.
3. Blank lines count as lines: test_blank.txt is `a\n\n\nb\n` -> 4 lines.
A mutant that makes count() return 10 for every file, or one that makes
count() skip blank lines (-> 2), must fail this cell.
4. Missing file -> exit code 2.
"""
import subprocess
import sys
import os
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
def run_test(cmd, expected, description):
"""Run a test command and verify output."""
result = subprocess.run(cmd, capture_output=True, text=True)
actual = result.stdout.strip()
if actual == str(expected) and result.returncode == 0:
print(f"PASS: {description}")
return True
else:
print(f"FAIL: {description}")
print(f" Expected: {expected}, Got: {actual}")
return False
# Test CSV mode with known data
test_csv_pass = run_test(
['python3', f'{BASE_DIR}/line_counter.py', f'{BASE_DIR}/test_data.csv', 'csv'],
5,
"CSV count mode (5 items)"
)
# Test count mode with known lines
test_count_pass = run_test(
['python3', f'{BASE_DIR}/line_counter.py', f'{BASE_DIR}/test_log.txt', 'count'],
10,
"Line count mode (10 lines)"
)
# Test blank lines are lines (kills count->return 10 and count->non-blank-only)
test_blank_pass = run_test(
['python3', f'{BASE_DIR}/line_counter.py', f'{BASE_DIR}/test_blank.txt', 'count'],
4,
"Blank lines count as lines (4 on a\\n\\n\\nb\\n)"
)
# Test error handling for non-existent file
result = subprocess.run(
['python3', f'{BASE_DIR}/line_counter.py', f'{BASE_DIR}/nonexistent.txt', 'count'],
capture_output=True, text=True)
if result.returncode == 2:
print("PASS: Error handling (exit code 2 for missing file)")
error_pass = True
else:
print(f"FAIL: Error handling (expected exit code 2, got {result.returncode})")
error_pass = False
all_pass = test_csv_pass and test_count_pass and test_blank_pass and error_pass
print(f"\nAll tests: {'PASSED' if all_pass else 'FAILED'}")
sys.exit(0 if all_pass else 1)