Skip to content

test(rtl): add generated Arabic fixtures guarding visual-order extraction - #447

Open
mathurshubham wants to merge 1 commit into
firecrawl:mainfrom
mathurshubham:test/rtl-generated-fixtures
Open

test(rtl): add generated Arabic fixtures guarding visual-order extraction#447
mathurshubham wants to merge 1 commit into
firecrawl:mainfrom
mathurshubham:test/rtl-generated-fixtures

Conversation

@mathurshubham

@mathurshubham mathurshubham commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Implements #218: Arabic/RTL regression coverage with fixtures generated at test time — no hosted sample files, no licensing question, and no headless-Chrome dependency in CI.

Why now

#440 just landed geometric visual-order reversal in fix_visual_order_rtl. As #218 points out, RTL bugs are uniquely prone to silent regression: the output looks like text to a reviewer who doesn't read the script, so a revert or refactor that breaks it is invisible in a diff. These tests are the guard.

How the fixtures are generated

Pure Rust, in-test (tests/rtl_generated_tests.rs, no production source touched). make_rtl_pdf(lines, storage) hand-builds a single-page PDF with a byte-accurate xref — the same pattern as the repo's existing make_text_pdf helpers and the same shape as the Hebrew fixtures that landed with #440:

  • A /TrueType font with a /ToUnicode CMap maps single-byte codes to Unicode, so no real Arabic glyph program is embedded.
  • Each token is one Tj with an absolute Tm. Visual-order storage reverses each Arabic run's characters and paints left-to-right (increasing x — the case fix(extract): reverse visual-order RTL text using glyph geometry #440 must reverse). Logical-order storage stores reading order and paints right-to-left (the case fix(extract): reverse visual-order RTL text using glyph geometry #440 must leave alone). Both the geometric vote and restore_embedded_ltr_runs are exercised.
  • Every test word carries a lam-alef pair emitted as a single glyph code mapping to two code points (U+0644 U+0627), covering the multi-character ToUnicode expansion where naive reversal breaks.

Assertions (from #218)

  1. Digit groups survive reordering intact126,248.34 inside an Arabic line must come out unreversed: arabic_visual_order_keeps_digit_group_intact, arabic_logical_order_keeps_digit_group_intact, arabic_digit_group_intact_in_positioned_items.
  2. Multi-char ToUnicode ligature round-triparabic_visual_order_ligature_round_trip, arabic_logical_order_ligature_round_trip.
  3. Negative control — the character-reversed corruptions (مالسلا, مالكلا) must be absent from output: visual_order_negative_control_wrong_output_is_rejected.

Plus visual_and_logical_storage_agree: both storage conventions extract to identical reading order. Both process_pdf_mem (markdown) and extract_text_with_positions_mem (positioned items) are covered.

Revert check

With fix_visual_order_rtl temporarily neutralized (early return), the 4 visual-order tests fail with the expected reversed corruption (e.g. ## لالخ مالسلا مالكلا) while the 3 logical-order/positioned tests still pass — exactly the split the guard should produce. All 7 pass on current main.

Verification

Full cargo test green (1015 lib + 165 integration + 7 new rtl_generated + 3 bin + 2 doc-tests, 0 failures); cargo fmt and cargo clippy -- -D warnings clean.

Out of scope, per the issue discussion: the synthetic wrong-ToUnicode corruption generator (that targets #214's detection feature, not this reversal guard) and Arabic-Indic digit variants (the ASCII digit-group case from the issue is asserted; #440's logic covers both scripts).

Closes #218.


Summary by cubic

Adds generated Arabic/RTL regression tests that synthesize PDFs at test time to guard visual-order text extraction. Prevents silent regressions in fix_visual_order_rtl (#440) without hosting sample files or adding headless browser deps. Closes #218.

  • Review notes
    • Test-only change: new tests/rtl_generated_tests.rs builds single-page PDFs in Rust with a /ToUnicode CMap; exercises both visual and logical storage and restore_embedded_ltr_runs.
    • Assertions per Add RTL/Arabic regression fixtures to CI — generated at test time, nothing to host #218: digit groups (126,248.34) remain unreversed inside RTL lines; lam‑alef (لا) multi-character ToUnicode expansion round-trips; negative control rejects raw reversed forms; both process_pdf_mem and extract_text_with_positions_mem agree; visual and logical storage extract to identical reading order.
    • Guard verified: disabling fix_visual_order_rtl makes visual-order tests fail while logical/positioned tests pass.

Written for commit f856f3f. Summary will update on new commits.

Review in cubic

…tion

There are no Arabic/RTL documents in the test matrix and real ones cannot
be hosted for licensing reasons (issue firecrawl#218). Rather than depend on
headless Chrome in CI, synthesize the PDFs in pure Rust at test time,
reusing the hand-rolled %PDF + ToUnicode CMap approach the repo already
uses for the checked-in Hebrew fixtures from PR firecrawl#440.

The fixtures are the regression guard for firecrawl#440 (visual-order RTL reversal
via glyph geometry): base-alphabet Arabic stored in visual order must
reverse back to logical reading order, while logical-order storage must be
left alone. Both conventions are generated and must extract to the same
logical text. Assertions mirror the three the issue calls out: digit
groups (126,248.34) embedded in an Arabic line survive intact and
unreversed, lam-alef (لا) multi-character ToUnicode expansions round-trip
character-identical, and a negative control rejects the raw stored
(reversed) output so a run of the pipeline without the fix is caught.

Verified the guard fails when fix_visual_order_rtl is neutralized and
passes on current main.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 1 file

Shadow auto-approve: would auto-approve. Adds generated Arabic/RTL regression tests to guard visual-order text extraction logic. This test-only change synthesizes PDFs in-memory to verify digit preservation and ligature handling without modifying production code.

Re-trigger cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add RTL/Arabic regression fixtures to CI — generated at test time, nothing to host

1 participant