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.
This commit is contained in:
1 parent
8c81135618
commit
cd3b285a66
6 files changed
+144
-54
No files matched your search
@@ -187,4 +187,26 @@ PASSED: Cache directory - Verified writable location
|
||||
|
||||
## Verification
|
||||
|
||||
Check: python3 /root/.hermes/wizard-outputs/spark/test_url_title_extractor.py && echo "PASS"
|
||||
Check: python3 /root/.hermes/wizard-outputs/spark/test_url_title_extractor.py && echo "PASS"
|
||||
|
||||
## Line counter (Q125 — surviving text-statistics tool)
|
||||
|
||||
`wizard-work/spark/line_counter.py` is the lane's surviving text-statistics
|
||||
tool. It counts one file at a time and prints one number.
|
||||
|
||||
Counting definitions (stated, not argued):
|
||||
- `count <file>`: one count per line produced by iterating the file as text
|
||||
— every `\n`-terminated line, plus one final count for an unterminated
|
||||
trailing fragment. `wc -l` counts newline characters only, so on a file
|
||||
without a trailing newline this tool reports one more than `wc -l` (the
|
||||
unterminated fragment is still a line).
|
||||
- `csv <file>`: fields in the first row via `str.split(',')`. Quoted commas
|
||||
are not unescaped: `"a,b",c` reads 3 fields, not 2; quoted-field CSV
|
||||
parsing requires the `csv` module and is not what this mode does.
|
||||
|
||||
Verification, runnable from the repo root:
|
||||
python3 wizard-work/spark/line_counter.py wizard-work/spark/test_log.txt count # -> 10
|
||||
python3 wizard-work/spark/line_counter.py wizard-work/spark/test_data.csv csv # -> 5
|
||||
python3 wizard-work/spark/line_counter.py wizard-work/spark/test_blank.txt count # -> 4
|
||||
bash wizard-work/spark/verify_line_counter.sh # -> rc 0
|
||||
python3 wizard-work/spark/test_line_counter.py # -> rc 0
|
||||
@@ -1,45 +1,48 @@
|
||||
# Line Counter Verification Report
|
||||
# Line Counter Verification Report (Q125)
|
||||
|
||||
## Artifact
|
||||
`/root/.hermes/wizard-outputs/spark/line_counter.py`
|
||||
`wizard-work/spark/line_counter.py` — 1,542 bytes, 48 lines,
|
||||
md5 `30f1ee5c8c32642336f45a13d724eff5` (working tree @ HEAD, this host).
|
||||
|
||||
## Purpose
|
||||
A simple Python utility that counts lines in Python files within a directory.
|
||||
The lane's surviving text-statistics tool: counts lines (`count` mode) and
|
||||
counts comma-separated fields on the first row (`csv` mode) of a single file.
|
||||
It takes `<filepath> <mode>` and prints one number; exit 0 on success, 2 on
|
||||
an unreadable or missing file, 1 on a usage error. It grades nothing but its
|
||||
own output and prints nothing but the number (or an error on stderr).
|
||||
|
||||
## Verification Results
|
||||
## Counting definitions (stated in the tool's README section)
|
||||
- `count <file>`: one count per line yielded by iterating the file as text —
|
||||
every `\n`-terminated line, plus one final count for an unterminated
|
||||
trailing fragment. On files without a trailing newline this is one more
|
||||
than `wc -l`, which counts newline characters only.
|
||||
- `csv <file>`: fields in the first row via `str.split(',')`. Quoted commas
|
||||
are not unescaped: `"a,b",c` reads 3 fields, not 2. Quoted-field CSV
|
||||
parsing requires the `csv` module and is not what this tool does.
|
||||
|
||||
### File Count
|
||||
```
|
||||
$ find /root/.hermes/wizard-outputs/spark -name "*.py" -type f | wc -l
|
||||
113
|
||||
Script output: Python files: 113
|
||||
✓ VERIFIED
|
||||
```
|
||||
## What this verification certifies
|
||||
`bash wizard-work/spark/verify_line_counter.sh` grades five readings against
|
||||
fixtures beside the tool: count = 10 on test_log.txt, csv = 5 on
|
||||
test_data.csv, count = 4 on test_blank.txt (blank lines are lines), missing
|
||||
file -> exit 2, missing mode -> exit 1. `python3 wizard-work/spark/test_line_counter.py`
|
||||
runs the same readings as subprocess cells plus the error-handling cell.
|
||||
|
||||
### Line Count
|
||||
```
|
||||
$ find /root/.hermes/wizard-outputs/spark -name "*.py" -type f -exec cat {} \; | wc -l
|
||||
5475
|
||||
Script output: Total lines: 5587
|
||||
```
|
||||
## What this verification does NOT certify
|
||||
- The retired host-path artifact at
|
||||
`/root/.hermes/wizard-outputs/spark/line_counter.py` (the pre-Q125 tool
|
||||
pinned by the old verify script) — that tool and its `Total lines: 5587`
|
||||
figure belong to a different directory and are not this tool.
|
||||
- Any of the ten other counters in the lane
|
||||
(`count_python.py`, `count_python_lines.py`, `py_loc.py`, `lwc_counter.py`,
|
||||
`linecount_pycount.py`, `text_stats.py`, `word_stats.py`, `file_stats.py`,
|
||||
`code_stats.py`, `loc_counter.py`) — they remain in the tree untouched;
|
||||
retiring them is a separate change and is not claimed here.
|
||||
- Recursive directory walking or code/comment/blank breakdowns: this tool
|
||||
counts one file at a time.
|
||||
|
||||
### Analysis
|
||||
- wc -l counts newline characters only
|
||||
- 112 files don't end with trailing newline
|
||||
- Expected total: 5475 + 112 = 5587
|
||||
- Script reported: 5587
|
||||
- ✓ VERIFIED
|
||||
|
||||
## Test Command
|
||||
## Test command (runnable from the repo root)
|
||||
```bash
|
||||
python3 /root/.hermes/wizard-outputs/spark/line_counter.py /root/.hermes/wizard-outputs/spark
|
||||
cd /root/troupe-standup
|
||||
python3 wizard-work/spark/test_line_counter.py
|
||||
bash wizard-work/spark/verify_line_counter.sh
|
||||
```
|
||||
|
||||
## Output
|
||||
```
|
||||
Python files: 113
|
||||
Total lines: 5587
|
||||
Code lines: 4344
|
||||
Comment lines: 285
|
||||
Empty lines: 958
|
||||
```
|
||||
@@ -0,0 +1,4 @@
|
||||
a
|
||||
|
||||
|
||||
b
|
||||
@@ -1,6 +1,14 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Test script for line_counter.py utility."""
|
||||
"""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
|
||||
@@ -11,7 +19,7 @@ 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
|
||||
@@ -34,12 +42,17 @@ test_count_pass = run_test(
|
||||
"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
|
||||
)
|
||||
capture_output=True, text=True)
|
||||
if result.returncode == 2:
|
||||
print("PASS: Error handling (exit code 2 for missing file)")
|
||||
error_pass = True
|
||||
@@ -47,6 +60,6 @@ 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 error_pass
|
||||
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)
|
||||
sys.exit(0 if all_pass else 1)
|
||||
@@ -7,4 +7,4 @@ line 6
|
||||
line 7
|
||||
line 8
|
||||
line 9
|
||||
line 10
|
||||
line 10
|
||||
@@ -1,16 +1,64 @@
|
||||
#!/bin/bash
|
||||
# Final verification test for line_counter.py
|
||||
# Returns 0 if correct, non-zero if wrong
|
||||
# Final verification test for line_counter.py (Q125 repair).
|
||||
# Returns 0 if correct, non-zero if wrong.
|
||||
#
|
||||
# Grades the tool that ships in this lane: line_counter.py and its fixtures
|
||||
# are resolved from this script's own location (BASH_SOURCE), so the check is
|
||||
# not pinned to a host path and runs from any working directory.
|
||||
set -u
|
||||
|
||||
OUTPUT=$(python3 /root/.hermes/wizard-outputs/spark/line_counter.py /root/.hermes/wizard-outputs/spark 2>&1)
|
||||
EXPECTED_LINES="Total lines: 5587"
|
||||
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
TOOL="$HERE/line_counter.py"
|
||||
|
||||
if echo "$OUTPUT" | grep -q "$EXPECTED_LINES"; then
|
||||
echo "VERIFIED: Line count correct"
|
||||
fail=0
|
||||
|
||||
note() { echo "ok: $*"; }
|
||||
err() { echo "BAD: $*" >&2; fail=1; }
|
||||
|
||||
# Reading 1 — count mode on a known fixture equals wc -l
|
||||
expect=$(wc -l < "$HERE/test_log.txt"); expect=${expect// /}
|
||||
got=$(python3 "$TOOL" "$HERE/test_log.txt" count 2>&1); rc=$?
|
||||
if [ "$rc" -eq 0 ] && [ "$got" -eq "$expect" ] 2>/dev/null; then
|
||||
note "count test_log.txt = $got (wc -l = $expect)"
|
||||
else
|
||||
err "count test_log.txt: rc=$rc got='$got' expected=$expect"
|
||||
fi
|
||||
|
||||
# Reading 2 — csv mode equals the csv module's first-row field count
|
||||
expect=$(python3 - "$HERE/test_data.csv" <<'PY'
|
||||
import csv, sys
|
||||
with open(sys.argv[1], newline='') as f:
|
||||
print(len(next(csv.reader(f))))
|
||||
PY
|
||||
)
|
||||
got=$(python3 "$TOOL" "$HERE/test_data.csv" csv 2>&1); rc=$?
|
||||
if [ "$rc" -eq 0 ] && [ "$got" -eq "$expect" ] 2>/dev/null; then
|
||||
note "csv test_data.csv = $got (csv module = $expect)"
|
||||
else
|
||||
err "csv test_data.csv: rc=$rc got='$got' expected=$expect"
|
||||
fi
|
||||
|
||||
# Reading 3 — blank lines count as lines: a\n\n\nb\n -> 4
|
||||
expect=$(wc -l < "$HERE/test_blank.txt"); expect=${expect// /}
|
||||
got=$(python3 "$TOOL" "$HERE/test_blank.txt" count 2>&1); rc=$?
|
||||
if [ "$rc" -eq 0 ] && [ "$got" -eq "$expect" ] 2>/dev/null; then
|
||||
note "count test_blank.txt = $got (wc -l = $expect)"
|
||||
else
|
||||
err "count test_blank.txt: rc=$rc got='$got' expected=$expect"
|
||||
fi
|
||||
|
||||
# Reading 4 — missing file exits 2
|
||||
python3 "$TOOL" "$HERE/does-not-exist.txt" count >/dev/null 2>&1; rc=$?
|
||||
[ "$rc" -eq 2 ] && note "missing file exits 2" || err "missing file: rc=$rc expected 2"
|
||||
|
||||
# Reading 5 — missing mode exits 1
|
||||
python3 "$TOOL" "$HERE/test_log.txt" >/dev/null 2>&1; rc=$?
|
||||
[ "$rc" -eq 1 ] && note "missing mode exits 1" || err "missing mode: rc=$rc expected 1"
|
||||
|
||||
if [ "$fail" -eq 0 ]; then
|
||||
echo "VERIFIED: $((5)) reading(s) correct"
|
||||
exit 0
|
||||
else
|
||||
echo "FAILED: Line count incorrect"
|
||||
echo "Expected: $EXPECTED_LINES"
|
||||
echo "Got: $OUTPUT"
|
||||
echo "FAILED: line_counter readings incorrect"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
Reference in new issue
Block a user