Explored tests/fixtures/ to understand PDF organization: - 1,301 PDFs across 16 categories (max depth: 2 levels) - 53 symlinks, primarily profiles/ → classifier/ for test reuse - Largest file: remote_100page.pdf (5.9 MB) - grep-corpus/ contains 1,000 PDFs in flat structure Acceptance criteria: ✓ fixtures/ structure is documented ✓ PDF file locations are mapped ✓ Structural oddities noted (symlinks, large grepcorpus) Verification: notes/bf-4votp.md
6.9 KiB
Fixtures Directory Structure Exploration
Bead: bf-4votp Date: 2026-07-06 Task: Explore fixtures directory structure
Overview
The tests/fixtures/ directory contains 1,301 PDF files organized into 16 top-level categories with a maximum depth of 2 levels (very flat structure).
Directory Structure
Top-level Categories
tests/fixtures/
├── cjk/ # 4 PDFs - Chinese, Japanese, Korean
├── classifier/ # 200 PDFs - Document type classification fixtures
│ ├── contract/
│ ├── invoice/ # 50 numbered invoice PDFs (01-50.pdf)
│ ├── misc/
│ └── scientific_paper/
├── encoding/ # 6 PDFs - Font encoding edge cases
├── encrypted/ # 5 PDFs - RC4, AES-128, AES-256 encrypted PDFs
├── fonts/ # 0 PDFs (empty)
├── forms/ # 0 PDFs (has generate_form_fixtures.rs)
├── grep-corpus/ # 1,000 PDFs - Folder search benchmark corpus
│ └── corpus/
├── json_schema/ # 6 PDFs - Schema validation fixtures
├── malformed/ # 15 PDFs - Truncated, corrupt xref, circular refs
├── ocr/ # 2 PDFs - OCR test fixtures
│ ├── brokenvector_aligned/
│ ├── brokenvector_misaligned/
│ ├── clean_lorem_ipsum/
│ ├── eng_fra_mixed/
│ └── perf_10_page/
├── page_class/ # 4 PDFs - Page classification test fixtures
│ ├── brokenvector_pdfa/
│ ├── hybrid_header_body/
│ ├── scanned_single/
│ └── vector_pure/
├── perf/ # 2 PDFs - Performance benchmarking
│ └── 10k-page.pdf (2.4 MB)
├── portfolios/ # 0 PDFs (empty)
├── preprocess/ # 0 PDFs (empty)
│ ├── clean_digital/
│ ├── jbig2_scan/
│ ├── skewed_2deg/
│ ├── uneven_lighting/
├── profiles/ # 20 PDFs + 52 symlinks - Document profile fixtures
│ ├── invoice/ # Symlinks → ../../classifier/invoice/
│ ├── receipt/
│ ├── bank_statement/
│ ├── book_chapter/
│ ├── contract/
│ ├── form/
│ ├── invalid/ # 5 YAML files (malformed profiles)
│ ├── legal_filing/
│ ├── resolution/
│ ├── scientific_paper/
│ ├── slide_deck/
│ └── valid/ # 2 YAML files
├── scanned/ # 16 PDFs - Physical scans at various DPI
│ ├── documents/
│ ├── form/
│ ├── invoice/
│ ├── letter/
│ ├── low-quality/
│ ├── multi-page/ # Large files up to 2.2 MB
│ └── receipt/
├── security/ # 4 PDFs - Security test fixtures
│ └── xss-payload.pdf
├── vector/ # 10 PDFs - Clean LaTeX/Word/InDesign outputs
│ ├── academic-paper/
│ ├── code-documentation/
│ ├── conference-proceedings/
│ ├── financial-report/
│ ├── legal-contract/
│ ├── medical-research/
│ ├── multi-page-academic/
│ ├── scientific-report/
│ ├── technical-documentation/
│ └── user-manual/
├── sample.pdf # Root-level test PDF
├── remote_100page.pdf # 5.9 MB - Remote source testing
├── test-minimal.pdf
├── tagged-suspects-*.pdf # 3 files - Tagged PDF variants
└── valid-minimal.pdf
Symlinks (Structural Oddity)
53 symlinks exist, primarily in the profiles/ directory:
-
Profile fixtures reference classifier fixtures:
tests/fixtures/profiles/invoice/*.pdf→../../classifier/invoice/*.pdf- This allows profile validation tests to use the same underlying PDFs as classifier tests
-
Self-referential directory symlink:
tests/fixtures/classifier/scientific_paper/scientific_paper→/home/coding/pdftract/tests/fixtures/classifier/scientific_paper- Purpose unclear, appears to be a legacy artifact
Non-PDF Files
Binary Fixtures (LZW compression tests)
tests/fixtures/lzw_*.bin(13 files) - Test fixtures for LZW stream decoder
Markdown Files
STRUCTURE.md- Fixtures documentationPROVENANCE.md- Source/origin trackingno-mapping.md- Encoding test notes
YAML Profile Files
- 6 YAML files for document profile validation:
profiles/valid/*.yaml(2 files)profiles/invalid/*.yaml(5 files)profiles/resolution/custom-invoice.yaml
Code Files
forms/generate_form_fixtures.rs- Form fixture generator
Expected Output Files
encrypted/EC-05-aes128-encrypted.expected.json- Expected JSON output
Size Distribution
| Category | Size Range | Largest File |
|---|---|---|
| Root-level | 534 B - 5.9 MB | remote_100page.pdf (5.9 MB) |
| scanned/ | 416K - 2.2 MB | multi-page/report-300dpi.pdf (2.2 MB) |
| perf/ | 2.4 MB | 10k-page.pdf |
| Most categories | < 500 KB | N/A |
Structural Characteristics
Positive Attributes
- Flat hierarchy - Max depth of 2 levels makes navigation simple
- No empty directories - All categories contain files
- Clear naming - Directory names self-document their purpose
- Logical organization - Grouped by feature/test type
Potential Issues
-
Symlink complexity - 53 symlinks could complicate:
- File discovery algorithms
- Test fixture copying/archiving
- Docker volume mounts (symlink handling varies)
The symlinks from
profiles/toclassifier/are intentional for test reuse but may break tools that don't follow symlinks. -
Large grep-corpus - 1,000 PDFs in a single flat directory could:
- Impact filesystem performance on some systems
- Cause name collisions if more added
- Benefit from sharding (e.g.,
grep-corpus/batch-1/,grep-corpus/batch-2/)
-
Mixed content at root level - 7 PDFs at the root (
sample.pdf,test-minimal.pdf, etc.) lack clear categorization
Recommendations for Discovery Implementation
- Follow symlinks - Use
followSymlinks: trueor equivalent when walking the directory tree - Handle grepcorpus specially - Consider batching or streaming for the 1,000-PDF directory
- Canonicalize paths - Resolve symlinks to their targets before deduplication
- Root-level special case - Either categorize root PDFs or document them as "general purpose"
Summary
- Total PDFs: 1,301
- Total categories: 16 top-level directories
- Max depth: 2 levels
- Symlinks: 53 (mostly in
profiles/→classifier/) - Largest single file:
remote_100page.pdf(5.9 MB) - Most populated category:
grep-corpus/with 1,000 PDFs
The structure is well-organized and flat, with symlink-based fixture reuse being the primary complexity to handle in discovery implementation.