pdftract/notes/bf-4votp.md
jedarden c49b8e36d4 docs(bf-4votp): document fixtures directory structure
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
2026-07-06 19:52:08 -04:00

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

53 symlinks exist, primarily in the profiles/ directory:

  1. 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
  2. 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 documentation
  • PROVENANCE.md - Source/origin tracking
  • no-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

  1. Flat hierarchy - Max depth of 2 levels makes navigation simple
  2. No empty directories - All categories contain files
  3. Clear naming - Directory names self-document their purpose
  4. Logical organization - Grouped by feature/test type

Potential Issues

  1. Symlink complexity - 53 symlinks could complicate:

    • File discovery algorithms
    • Test fixture copying/archiving
    • Docker volume mounts (symlink handling varies)

    The symlinks from profiles/ to classifier/ are intentional for test reuse but may break tools that don't follow symlinks.

  2. 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/)
  3. Mixed content at root level - 7 PDFs at the root (sample.pdf, test-minimal.pdf, etc.) lack clear categorization

Recommendations for Discovery Implementation

  1. Follow symlinks - Use followSymlinks: true or equivalent when walking the directory tree
  2. Handle grepcorpus specially - Consider batching or streaming for the 1,000-PDF directory
  3. Canonicalize paths - Resolve symlinks to their targets before deduplication
  4. 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.