--- name: leapp-validate-globs description: Validate LEAPP artifact path globs against real extraction file listings before committing them. Use when adding or changing a "paths" pattern in __artifacts_v2__, when an artifact returns no rows and the pattern is suspect, or when a vendor has moved a file between OS versions. --- # Validating a path glob A pattern that matches nothing fails silently. The artifact simply reports no data, which is indistinguishable from the app not being present. Never commit a pattern you have not run. ## What you are testing against The matcher is Python `fnmatch`, so reproduce it exactly rather than approximating with `glob` or a regex: - `*` and `**` both span `/`. They are interchangeable. - Matching goes through `os.path.normcase`, so it is **case-sensitive on macOS and Linux** and case-insensitive on Windows. Test the case-sensitive behaviour; it is the stricter one. - The directory, zip, tar and raw image seekers prepend a synthetic `root/`. iLEAPP's iOS-backup seeker does not. ## Method 1: against recorded path listings (fastest) iLEAPP carries real file listings from published research images at `admin/data/filepath-lists/*.csv.zip`, covering several iOS generations. Unzip to a scratch directory, then run each candidate pattern over the path column with `fnmatch.fnmatchcase` and count hits per generation. Run the **old and new** patterns both, and compare. A change that reduces the count on an older image is a regression, not a tightening, unless you meant it. ## Method 2: against a real extraction (authoritative) Instantiate the matching seeker directly, from `scripts/search_files.py` or, for a raw image, `scripts/raw_image.py`, so the semantics are exact by construction, then call `search()` with the pattern. This is the only way to catch a mismatch between what you think the seeker does and what it does. To confirm the artifact then produces the rows you expect, call the artifact function's `.__wrapped__`, exposed by `@artifact_processor`'s `@wraps`, with a mock context providing `get_files_found()` and `get_relative_path()`. `len(data_list)` is the count to record in `sample_data`. ## Patterns that need extra care **Case variants.** Use one bracket class, `*/[Bb]iome/*`, never a tuple of two patterns. A tuple double-counts on Windows, where `normcase` folds both to the same string and the entry point extends `files_found` once per pattern with no dedup. **Vendor moves.** When a file changes location between OS versions, keep the old pattern alongside the new one. Examiners run these tools against extractions going back years. **Over-generic components.** A pattern whose filename component is bare `*`, `**` or `*.*` matches every file at that level and is rejected. Anchor on something real. ## Hygiene Print counts and value shapes from test images, never actual values, and delete anything you extracted when you are done.