The eight test files Q98 leaves open (plus test_bfs.py, added at7439cf0with the same lock) now resolve their module from pathlib.Path(__file__).resolve().parent instead of /root/.hermes/wizard-outputs/<lane>. tools/import_resolve_check.py --repo . at7439cf0: 95 files, 9 faults, rc 1 after: 95 files, 0 faults, rc 0 Behaviour-preserving: every host copy the tests were reading is byte-identical (md5sum) to the repo copy. Three absolute literals in spark/test_validator.py that the static leg does not grade (load_json(...) argument strings at pre-fix lines 12/16/25) are re-pointed too. ledger/test_scratch_manifest.py was red before any edit (str ROOT vs gen_manifest ROOT.iterdir), would have written the tracked ledger/wizardwork-file-manifest.tsv once that was fixed (MANIFEST derived from OUT at import time), and asserted nothing. It now re-points ROOT/OUT/MANIFEST, guards MANIFEST inside a tempfile.mkdtemp(), and asserts the exact manifest row. Non-vacuity: scratch/q98b/poison_probe.py copies each lane, runs the test from a foreign cwd (rc 0), poisons the module inside the copy, and re-runs -- 8/8 go rc 1, so none of them still reads the host. Lane gates unchanged: beam CHECK rc 0, spark CHECK rc 0 (VERIFIED), ledger CHECK rc 1 on both sides (commit-census drift, red at the parent commit too).
77 lines
2.9 KiB
Python
77 lines
2.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Verification tests for counter_util.py"""
|
|
|
|
import pathlib
|
|
import sys
|
|
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent))
|
|
|
|
from counter_util import count_words, count_items, most_common, counter_to_dict, extract_counter_description
|
|
from collections import Counter
|
|
|
|
def test_word_counting():
|
|
"""Test word counting functionality."""
|
|
text = "the quick brown fox jumps over the lazy dog the fox is quick"
|
|
c = count_words(text)
|
|
assert counter_to_dict(c)['the'] == 3, "Word count 'the' failed"
|
|
assert counter_to_dict(c)['fox'] == 2, "Word count 'fox' failed"
|
|
assert most_common(c, 3) == [('the', 3), ('quick', 2), ('fox', 2)], "Most common failed"
|
|
return True
|
|
|
|
def test_counter_missing_key():
|
|
"""Test that Counter returns 0 for missing keys."""
|
|
items = ['a', 'b', 'a', 'c']
|
|
c = count_items(items)
|
|
assert c['a'] == 2, "Counter 'a' count failed"
|
|
assert c['missing'] == 0, "Counter should return 0 for missing keys"
|
|
return True
|
|
|
|
def test_counter_operations():
|
|
"""Test Counter arithmetic operations."""
|
|
c1 = Counter(['a', 'b', 'a'])
|
|
c2 = Counter(['a', 'b', 'b'])
|
|
assert counter_to_dict(c1 + c2)['a'] == 3, "Addition failed"
|
|
assert counter_to_dict(c1 & c2)['a'] == 1, "Intersection failed"
|
|
assert counter_to_dict(c1 | c2)['b'] == 2, "Union failed"
|
|
return True
|
|
|
|
def test_extraction():
|
|
"""Test documentation extraction from actual web-extracted format."""
|
|
# This matches the actual format from docs.python.org/web_extract
|
|
doc_content = """| `namedtuple()` | factory function for creating tuple subclasses with named fields |
|
|
| `deque` | list-like container with fast appends and pops on either end |
|
|
| `ChainMap` | dict-like class for creating a single view of multiple mappings |
|
|
| `Counter` | dict subclass for counting [hashable](https://docs.python.org/3/glossary.html) objects |"""
|
|
|
|
result = extract_counter_description(doc_content)
|
|
# Should extract description mentioning Counter
|
|
assert 'Counter' in result['description'] or 'description' in result, "Extraction failed - no content"
|
|
return True
|
|
|
|
if __name__ == "__main__":
|
|
tests = [
|
|
("word_counting", test_word_counting),
|
|
("counter_missing_key", test_counter_missing_key),
|
|
("counter_operations", test_counter_operations),
|
|
("extraction", test_extraction),
|
|
]
|
|
|
|
passed = 0
|
|
failed = 0
|
|
|
|
for name, test in tests:
|
|
try:
|
|
if test():
|
|
print(f"PASS: {name}")
|
|
passed += 1
|
|
else:
|
|
print(f"FAIL: {name}")
|
|
failed += 1
|
|
except AssertionError as e:
|
|
print(f"FAIL: {name} - {e}")
|
|
failed += 1
|
|
except Exception as e:
|
|
print(f"ERROR: {name} - {e}")
|
|
failed += 1
|
|
|
|
print(f"\nResults: {passed} passed, {failed} failed")
|
|
sys.exit(0 if failed == 0 else 1) |