# G5 Compression Manual Setup

This is the canonical fixture and execution contract for exactly these 24
tests:

`TC003`, `TC004`, `TC084`-`TC092`, `TC102`-`TC110`, and `TC143`-`TC146`.

The commands and paths here replace placeholder image names, blind corruption
offsets, and non-source-compared reads in the individual test descriptions.
Do not use old images or reports as fixture inputs.

## Host fixture generation

Requirements are `mkfs.erofs`, `dump.erofs`, and `fsck.erofs` 1.8.6. Generate
into a new path; the helper rejects an existing output directory.

```sh
out=/work/build/repo22-g5-fixtures-a
python3 tests/g5_fixtures.py create \
  --output "$out" \
  --erofs-utils-source /path/to/erofs-utils-1.8.6
python3 tests/g5_fixtures.py verify --output "$out"
```

Generate a second fresh directory and require both checksum inventories to be
identical:

```sh
cmp "$out/SHA256SUMS" "$out2/SHA256SUMS"
cmp "$out/SOURCE-SHA256SUMS" "$out2/SOURCE-SHA256SUMS"
```

`fixture-manifest.json` records every mkfs option, source and image hash,
inode/NID/size/layout, compressed map-header offset, advise bits, algorithm
nibbles, extent summaries, partial-reference indexes and physical blocks, and
corruption pcluster/patch ranges. Creation reopens every transformed image and
the separate `verify` command repeats the structured checks.

The partial-reference transformer changes the HEAD pblk, sets
`Z_EROFS_LI_PARTIAL_REF`, and copies the complete source pcluster's
`D0_CBLKCNT`. Corruption is applied only after `dump.erofs` and the byte parser
agree on the target algorithm and physical extent.

## Build matrix

Build on the FreeBSD 15 guest from the exact repo22 baseline source:

```sh
FREEBSD_SRC=/root/repo22-g5/freebsd-src WITH_ZSTDIO=2 ./build.sh
# Must fail with: WITH_ZSTDIO must be 0 or 1

FREEBSD_SRC=/root/repo22-g5/freebsd-src WITH_ZSTDIO=0 ./build.sh
cp build/erofs.ko /root/repo22-g5/erofs-nozstd.ko
nm -u /root/repo22-g5/erofs-nozstd.ko

FREEBSD_SRC=/root/repo22-g5/freebsd-src WITH_ZSTDIO=1 ./build.sh
cp build/erofs.ko /root/repo22-g5/erofs-zstdio.ko
nm -u /root/repo22-g5/erofs-zstdio.ko
```

The disabled module must have no `ZSTD_*` or `bcmp` reference. The enabled
module may reference only the formal FreeBSD ZSTD API names. Load by full path,
obtain the file ID from the matching `kldstat` path row, and unload that ID.

## Manual read pattern

For every image, attach a fresh md provider, mount read-only, compare the full
hash and full bytes where required, and compare every range against the same
offset in the source file. `tests/read_probe.c` provides deterministic `pread`
and errno checks; it is a probe, not a runner.

```sh
unit=$(mdconfig -a -t vnode -f "$image")
mount -t erofs -o ro "/dev/$unit" "$mnt"
sha256 -q "$source"
sha256 -q "$mnt/$name"
cmp "$source" "$mnt/$name"
read_probe pread "$mnt/$name" "$offset" "$length" guest.bin
read_probe pread "$source" "$offset" "$length" source.bin
cmp source.bin guest.bin
umount "$mnt"
mdconfig -d -u "${unit#md}"
```

Use `timeout 20 read_probe expect-error FILE 5` for compressed-stream
corruption. Also compare `control.bin` from the same corrupted image, then
require no mount/md remains and EROFS active allocations return to zero.

## Fixture mapping

| Tests | Image and source contract |
|---|---|
| TC003, TC084, TC089 | `lz4-compact-4k.erofs` or `lz4-full-4k.erofs`; `sources/lz4/compressed.bin` |
| TC085 | `lz4-large.erofs`; 268435456-byte `sources/large/large.bin` |
| TC086, TC087, TC090 | `lz4-compact-64k.erofs`; fixed source offsets |
| TC088 | 4K, 64K, and 256K compact LZ4 images; same source bytes |
| TC091, TC092 | `lz4-ztail.erofs`; inline target plus four edge controls |
| TC004 | `lzma-level6.erofs`; full, middle, and EOF reads |
| TC102-TC104 | distinct DEFLATE level 1, 6, and 9 images |
| TC105-TC107 | distinct ZSTD level 1, 15, and 22 images |
| TC108 | `lzma-large.erofs`; 104857601-byte LZMA level 6 source |
| TC109 | `microlzma-edge.erofs`; actual 1B, 4K, and compressed 16K files |
| TC110, TC144 | LZMA partial/corrupt pair plus same-image `control.bin` |
| TC143 | DEFLATE and ZSTD partial/corrupt pairs plus controls |
| TC145 | both KLDs, LZ4 control, and `zstd-level1.erofs` gate/read |
| TC146 HEAD2 | `head2.erofs` and targeted corrupt copy; boundary from manifest |
| TC146 interlaced | `interlaced.erofs`; first compressed/plain transition from manifest |
| TC146 explicit extent | `extent-attempt.erofs` is negative evidence only; mapped payload remains SHELVED |

TC146 must report HEAD2, interlaced, and explicit extent separately. A normal
full-index image produced with `--max-extent-bytes` is not explicit-extent
coverage.

## Final cleanup

Require zero matching mounts, zero md providers, zero EROFS active allocation,
and no loaded EROFS KLD. Compare pre/post dmesg, verify guest responsiveness,
power off the dedicated VM, and remove Python bytecode caches before commit.
