pdftract/notes/bf-21hw8.md
jedarden 319f81aaa3 test(bf-21hw8): add bounded predictor tests for PNG and TIFF
Add 4 new tests to verify PNG and TIFF predictor functions use row-by-row
processing with bounded peak memory (2x stride), never pre-allocating full
output buffers inside tests.

- test_png_predictor_budget_enforcement_small_fixture: 200-byte fixture,
  100-byte budget, verifies truncation at row boundary
- test_tiff_predictor_2_budget_enforcement_small_fixture: 160-byte fixture,
  80-byte budget, verifies row-by-row processing for grayscale
- test_png_predictor_multiple_selectors_budget_per_row: 25-byte fixture
  with all PNG selector types, verifies per-row budget checking
- test_tiff_predictor_2_rgb_budget_enforcement: 45-byte RGB fixture,
  verifies multi-byte pixel handling with budget enforcement

All fixtures are under 250 bytes, no full-buffer pre-allocation, tests
mirror the row-by-row discipline from bf-49wmw production fix.

Closes bf-21hw8
2026-05-23 13:35:57 -04:00

71 lines
2.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# bf-21hw8: Bound predictor tests (PNG and TIFF)
## Summary
Added 4 new tests to verify PNG and TIFF predictor functions use row-by-row processing with bounded peak memory (2x stride = 2 × MAX_ROW_BYTES = 128 KB), never pre-allocating full output buffers inside tests.
## Changes Made
### 1. test_png_predictor_budget_enforcement_small_fixture
- **Fixture:** 200 bytes (20 rows × 10 bytes with PNG selector)
- **Budget:** 100 bytes (forces truncation)
- **Verifies:**
- Output never exceeds max_output budget
- Truncation occurs at row boundary
- Peak memory stays at 2x stride (prev_row + current_row)
### 2. test_tiff_predictor_2_budget_enforcement_small_fixture
- **Fixture:** 160 bytes (20 rows × 8 bytes grayscale)
- **Budget:** 80 bytes (half of decoded size)
- **Verifies:**
- Output never exceeds max_output budget
- Truncation occurs at row boundary
- Peak memory stays at 2x stride
### 3. test_png_predictor_multiple_selectors_budget_per_row
- **Fixture:** 25 bytes (5 rows with different PNG selectors: 10/11/12/13/14)
- **Budget:** 6 bytes (2 rows only)
- **Verifies:**
- Budget is checked BEFORE processing each row (per bf-49wmw)
- All PNG selector types respect budget
- Early abort at row boundary
### 4. test_tiff_predictor_2_rgb_budget_enforcement
- **Fixture:** 45 bytes (5 rows × 9 bytes RGB data)
- **Budget:** 18 bytes (2 rows only)
- **Verifies:**
- Multi-byte pixels (RGB) process row-by-row
- Budget enforced per-row
- Correct differencing for multi-component data
## Verification
### Tests PASS
All 4 new tests pass:
```
test_png_predictor_budget_enforcement_small_fixture ... ok
test_tiff_predictor_2_budget_enforcement_small_fixture ... ok
test_png_predictor_multiple_selectors_budget_per_row ... ok
test_tiff_predictor_2_rgb_budget_enforcement ... ok
```
### Code Review
- All fixtures are small (under 250 bytes) - no large buffer allocation
- No `Vec::with_capacity(data.len())` or similar patterns in tests
- Tests use the production `apply_predictor()` function which already implements row-by-row processing (from bf-49wmw)
- Budget assertions verify early truncation occurs
### Production Code (from bf-49wmw) Verified
- `apply_png_predictors()`: Uses `Vec::new()`, grows row-by-row, checks budget before each row
- `apply_tiff_predictor_2()`: Uses `Vec::new()`, grows row-by-row, checks budget before each row
- Peak memory bounded to 2 × MAX_ROW_BYTES (128 KB) regardless of image height
## Acceptance Criteria
- [x] PNG predictor tests use small fixtures (< 250 bytes)
- [x] TIFF predictor 2 tests use small fixtures (< 250 bytes)
- [x] Tests assert row-by-row peak memory (budget enforcement)
- [x] Tests never pre-allocate full second copy of output
- [x] Mirrors bf-49wmw row-by-row discipline
## References
- Production fix: bf-49wmw (row-by-row processing with MAX_ROW_BYTES = 64 KB)
- Test file: crates/pdftract-core/src/parser/stream.rs (predictor_tests module)