- parsers/ package: rust / python / go / typescript / generic
- parser registry with language+recipe -> fallback resolution
- fingerprint hash (kind+file+line+code) for cross-run dedup
- runner.py post-exec hook: parse log, persist findings, count on job row
(extraction runs before mark_job_finished so callers polling on terminal
status see findings_count populated atomically)
- db.insert_finding / list_findings / increment_findings_count DAOs already
shipped in wave 1; wired here
- GET /jobs/{id}/findings now returns real data (server route already
shipped; was returning empty list because nothing populated the table)
- tests/test_parsers/: 6 modules + 11 fixtures (rust/python/go/typescript)
- tests/test_runner_findings.py: 3 integration tests
- README: tick steps 2-6, add Findings section
Suite: 108 passing (62 wave-1 + 46 new).
Spec: memory/spec-crafting-table.md
36 lines
1 KiB
Python
36 lines
1 KiB
Python
"""GenericParser fallback unit tests."""
|
|
from __future__ import annotations
|
|
|
|
from crafting_table.parsers.generic import GenericParser
|
|
from crafting_table.parsers import find_parser
|
|
|
|
|
|
def test_generic_zero_exit_no_findings():
|
|
out = GenericParser.parse("any output", 0, "build")
|
|
assert out == []
|
|
|
|
|
|
def test_generic_nonzero_exit_emits_one_finding():
|
|
out = GenericParser.parse("oops", 1, "build")
|
|
assert len(out) == 1
|
|
f = out[0]
|
|
assert f.kind == "recipe_fail"
|
|
assert f.severity == "warn"
|
|
assert f.code == "exit_1"
|
|
assert "build" in f.message
|
|
assert "1" in f.message
|
|
|
|
|
|
def test_generic_matches_anything():
|
|
assert GenericParser.matches("anylang", "anyrecipe") is True
|
|
|
|
|
|
def test_registry_falls_back_to_generic_for_unknown_lang():
|
|
cls = find_parser("ruby", "audit")
|
|
assert cls is GenericParser
|
|
|
|
|
|
def test_registry_falls_back_to_generic_for_unknown_recipe():
|
|
# Rust parser declines unknown recipes; resolver should drop to generic.
|
|
cls = find_parser("rust", "deploy")
|
|
assert cls is GenericParser
|