# Test Case: FreeBSD ZSTDIO Build Gate

**Test ID**: TC145-zstdio-build-gate

**G5 fixture contract**: Use [G5-MANUAL-SETUP.md](G5-MANUAL-SETUP.md).
Its generated paths, source comparisons, structured corruption offsets, and
cleanup rules supersede placeholder examples in this file.
**Category**: Build / Compression
**Priority**: Critical
**Regression**: Optional-kernel ZSTD symbol references

## Objective
Verify that repo22 uses FreeBSD's formal ZSTD header/API only when `ZSTDIO` is
enabled, emits no ZSTD symbol references otherwise, rejects ZSTD images
accurately in the disabled build, and reads them in the enabled build.

## Preconditions
- FreeBSD 15 source tree used by `build.sh`.
- FreeBSD guest kernel built with ZSTDIO, so the enabled module can resolve the
  official kernel symbols.
- One LZ4 image and one ZSTD image with known SHA256 output.

## Test Steps
1. Build without ZSTDIO and save the module outside `build/`:
   ```sh
   WITH_ZSTDIO=0 ./build.sh
   cp build/erofs.ko /tmp/erofs-nozstd.ko
   ```
2. Verify no unresolved `ZSTD_*` or `bcmp` symbol:
   ```sh
   nm -u /tmp/erofs-nozstd.ko | grep 'ZSTD_' && exit 1 || true
   nm -u /tmp/erofs-nozstd.ko | grep -w bcmp && exit 1 || true
   ```
3. Load the disabled module, read the LZ4 control image, then attempt to mount
   the ZSTD image.
4. Unload by the exact module ID reported by `kldstat`.
5. Build with ZSTDIO:
   ```sh
   WITH_ZSTDIO=1 ./build.sh
   cp build/erofs.ko /tmp/erofs-zstdio.ko
   ```
6. Verify the undefined ZSTD symbols are official API names from
   `<contrib/zstd/lib/zstd.h>` and that `bcmp` is absent.
7. Load the enabled module, mount the same ZSTD image, and verify full SHA256.
8. Unload by exact ID and audit final state.

## Expected Results
- Disabled build: no `ZSTD_*` references, KLD load succeeds, LZ4 reads, and a
  ZSTD image fails mount with `EOPNOTSUPP` and the message
  `ZSTD compression requires ZSTDIO support`.
- Enabled build: KLD load succeeds and the ZSTD SHA256 matches.
- Both modules have no unresolved `bcmp`.
- The build rejects `WITH_ZSTDIO` values other than `0` or `1`.
- No module, mount, or md unit remains after cleanup.
