Binary parsers benefit from a testing approach that combines small deterministic tests with larger corpus-based validation.
Unit tests cover narrow pieces of logic and live next to the code they test. Handler tests
call process directly on a handcrafted [u8; 128], without going through the parser or
building an ExtensionLibrary. Parser tests construct minimal valid EDID byte arrays and
assert on specific error and warning conditions.
This keeps failures localized: a failing test in base.rs can only mean BaseBlockHandler
is broken.
A single integration test in capabilities/mod.rs verifies that the full pipeline wires
together correctly — that with_standard_handlers() registers the handlers and that
capabilities_from_edid invokes them. It does not duplicate the field-level assertions
that belong in handler unit tests.
PIAF should maintain a fixture corpus containing:
- valid EDID captures,
- malformed inputs,
- edge cases,
- truncated or corrupted data.
These fixtures make it easier to improve the parser without unintentionally changing behavior.
A suggested layout:
testdata/
├── valid/
├── invalid/
└── edge/
Fuzzing is strongly recommended for the parser.
Important expectations:
- no panics,
- no uncontrolled memory growth,
- invalid input results in controlled errors or warnings,
- unknown structures do not break parsing invariants.
Two fuzz targets live in fuzz/fuzz_targets/:
parse_edid— exercises the full dynamic pipeline: raw bytes →parse_edid→capabilities_from_edid.capabilities_static— exercises the static (no-alloc) pipeline: raw bytes →parse_edid→capabilities_from_edid_static.
Both are set up using cargo-fuzz with libFuzzer. cargo-fuzz requires nightly; the library itself stays on stable.
Runs until Ctrl+C. Useful for interactive testing:
cargo +nightly fuzz run parse_edid
cargo +nightly fuzz run capabilities_static
Any crashes are written to fuzz/artifacts/<target>/.
Run for a fixed duration (e.g. one hour), then minimise and commit the resulting corpus:
cargo +nightly fuzz run parse_edid -- -max_total_time=3600
cargo +nightly fuzz run capabilities_static -- -max_total_time=3600
After the run completes, deduplicate the corpus down to a minimal covering set:
cargo +nightly fuzz cmin parse_edid
cargo +nightly fuzz cmin capabilities_static
The minimised corpus lives in fuzz/corpus/<target>/ and should be committed so that subsequent runs — locally and in CI — start from a richer base.
The fuzz workflow (.github/workflows/fuzz.yml) runs a 60-second smoke test on every push and pull request, and a 1-hour deep run on a weekly schedule. The corpus is cached between runs using GitHub Actions cache. Crash artifacts are uploaded automatically on failure.
PIAF should be strict about structural integrity, but practical about diagnostics.
The test suite should reflect that balance by checking both:
- outright rejection of invalid core structure,
- graceful handling of unusual or partially malformed optional content.
As the fixture corpus grows, it should become a source of confidence for refactoring, extension support, and improvements to the normalization layer.