# Testing CHDSharp ships a **558-test** xUnit suite plus a deterministic 30-file corpus covering every format version, codec, map type, and parent/child combination. Tests run on `net8.0`, `net9.0`, and `net10.0`. --- ## Test tiers | Tier | Project | Description | |------|---------|-------------| | Unit | `CHDSharpTest` | Header/API tests, checksum test vectors, TOC parsing edge cases, error mapping, bounds validation, Huffman/FLAC/LZMA primitives, extraction, metadata, parity features. | | Corpus | `CHDSharpTest` | Runs `CheckFile` (deep) and `ReadHunk` against **30 deterministic CHD fixtures** in `TestData/`, driven by `manifest.json` (expected version, parent links, expected pass/fail). | | Integration | `CHDSharpTest` | End-to-end CLI tests (`CliIntegrationTests`): directory scan, `--random`, `--list`, `--parent`. | | Interactive | `CHDSharpTester` | WPF app that batch-verifies folders and **cross-checks against `chdman`** (header info, deep verify, SHA1, random-access extraction, codec decode, parent chains). | | Encoder unit | `CHDSharpEncoderTest` | Tests for the `CHDSharpEncoder` creation library: endian/CRC/SHA1/deflate primitives, Huffman + V5 map compression, header, CUE/GDI/ISO/TOC parsers, metadata writer, per-hunk ratio logging. | | Encoder validation | `CHDSharpEncoderTest` | Cross-validation of encoder output against `chdman.exe` v0.288 (`info`, `verify`, `extractraw`, `createcd`, `createraw`) and the CHDSharpLib reader — including **100 MB+ raw/CD round-trips** and byte-for-byte file comparison with `chdman createraw`. | --- ## Test classes | Class | Covers | |-------|--------| | `HeaderAndApiTests` | Magic/version detection, `CheckHeader`, `IsChdFile`, open/read error paths | | `ReadHeaderTests` | `Chd.ReadHeader`/`ReadHeaderAsync` full header DTO (libchdr `chd_read_header` parity): all versions, field parity with an opened `ChdFile`, codec slots, child/parent hashes, V1 geometry, error paths, stream leave-open, async | | `ProgressReportingTests` | `IProgress` on `CheckFile`, `CheckFileWithParent`, `ReadAllBytes`, `EnumerateHunks`, `ExtractToDirectory`: per-hunk report counts, monotonicity, final totals, ordered parallel reports, backward-compatible defaults | | `CancellationTokenTests` | `CancellationToken` on all public APIs: pre-cancelled throws for `Open`/`Read`/`ReadHunk`/`ReadAllBytes`/`ExtractToDirectory`/`CheckFile`/`CheckFileWithParent`, cancelled-task async twins, mid-run cancellation of the parallel pipeline, OCE never swallowed by extraction | | `ChecksumTests` | CRC-32 / CRC-16 test vectors | | `CdRomAddressTests` | `CdRomAddress` MSF↔LBA conversion: BCD vectors, lead-in boundaries, 99-minute BCD limit, invalid-BCD throws, round trips | | `ReadSectorTests` | `ReadSector`/`ReadSectorMsf`/`ReadFrame` against the CD corpus (V3/V4/V5, cdlz/cdfl): sector/frame reads match the decompressed image, all-frames concatenation equals the whole image, MSF↔LBA equivalence, buffer/range error paths, non-CD rejection | | `TrackInfoTests` / `TrackInfoEdgeCaseTests` | TOC parsing across `CHTR`, `CHT2`, `CHCD`, `CHGD`, `CHGT`; GD-ROM pad frames; binary track parsing | | `CorpusTests` | Deep verification + open/read on all 30 fixtures | | `SecondCompressedTests` | V3/V4 `ZLIB_PLUS` secondary-codec hunks | | `ExtractTests` / `TrackInfoTests` | Extraction, CUE/GDI generation, reporting | | `ParityFeaturesTests` | `GetMetadata`, `Precache`, V1/V2 synthesized GDDD, `OpenAsync` overloads | | `LargeFileTests` | Synthetic uncompressed V5 CHD with a 20 GiB declared image: open, random access past 4 GiB (stored hunk + zero hunks), `ReadAllBytes` 2 GiB guard. Verifies libchdr #147 (sources > 10 GB). | | `LruCacheTests` | `ChdFile.CacheSize` / `ConfigureCache` multi-hunk LRU cache (libchdr #36): default size, lower-bounding, cross-hunk correctness, eviction/promotion, cache reconfiguration, parent-referenced hunk caching. | | `ChdApiTests`, `ChdFileTests`, `ChdTocParserTests`, `ChdCommonTests`, `ModelTests`, `UtilityTests`, `BigEndianTests`, `BoundsValidationTests`, `ExceptionHandlingTests`, `HuffmanDecoderTests`, `EccVerifyTests`, `CliAdditionalTests` | Remaining units | --- ## The corpus `CHDSharpTest/TestData/` contains 30 CHD files generated by `CHDSharpTestGen`: | Version | Files | Coverage | |---------|-------|----------| | V1 | 1 | zlib (legacy `hdcomp`) | | V2 | 1 | zlib (synthesized V1→V2) | | V3 | 4 | zlib, CD, A/V laserdisc, parent chain | | V4 | 5 | zlib, uncompressed, CD, A/V laserdisc, parent chain | | V5 | 19 | zlib, lzma, huff, flac, zstd, multi-codec, uncompressed, tiny (expected failure), odd-size, parent, compressed-map child, uncompressed-map child, unaligned-hunk child, CD cdzl/cdlz/cdfl/cdzs/default, laserdisc avhuff (mono + **stereo**) | `manifest.json` drives the corpus tests: each entry declares the expected version, optional parent file, and whether the fixture is expected to verify (`"ok"`) or fail (`"invalid"`). > The **stereo AVHuff fixture** (`v5_av_stereo.chd`) is a regression test for the laserdisc extraction bug — it fails to decompress with any decoder configured with the wrong (non-mono) FLAC channel count. --- ## Running the tests ```bash # Everything (all target frameworks) dotnet test # One framework dotnet test -f net10.0 # One class / filter dotnet test --filter "FullyQualifiedName~CorpusTests" dotnet test --filter "FullyQualifiedName~ParityFeatures" # Detailed console output dotnet test -v detailed # The encoder suite only (CHDSharpEncoderTest; requires chdman.exe next to the test assembly) dotnet test CHDSharpEncoderTest/ dotnet test CHDSharpEncoderTest/ --filter "FullyQualifiedName~LargeFileValidationTests" ``` The encoder validation tests use `chdman.exe` (MAME 0.288), resolved from the test output directory or `CHDSharpTester/`; if it is unavailable those tests skip. ### Regenerating the corpus `CHDSharpTestGen` builds source images deterministically (seeded PRNG) and drives **vintage `chdman`/`hdcomp` binaries** to produce the fixtures — regenerating yields **byte-identical** files. ```bash # Prerequisites: chdman binaries in CHDSharpTest/chdman/: # hdcomp_v1.exe (~MAME 0.77, V1) # chdman_v3.exe (~MAME 0.130, V3) # chdman_v4.exe (~MAME 0.145, V4) # chdman_v5.exe (MAME 0.288, V5) dotnet run --project CHDSharpTestGen ``` Extra generator flags: `--avitest` (AVI passthrough test), `--hunkdebug ` (inspect a single FLAC-hunked V5 CHD). --- ## The WPF tester (`CHDSharpTester`) An interactive tool that: - batch-verifies directories of CHDs with the same logic as `chdman verify`, - displays header info, compression breakdown, SHA1/MD5, and per-codec stats, - performs random-access extraction and compares against `chdman extractraw`, - exercises parent/child chains. ```bash dotnet run --project CHDSharpTester ``` It requires the `chdman` binaries in `CHDSharpTest/chdman/` for cross-checks. --- ## Golden rules for contributors 1. **Every new feature needs a test** — corpus fixture for format-level behavior, unit test for API-level behavior. 2. **Corpus fixtures must be deterministic** — regenerate via `CHDSharpTestGen`, never hand-edit binaries. 3. **New fixtures must be registered in `manifest.json`** with the correct expected version and pass/fail status. 4. All 468 tests must pass on **all three TFMs** before merging.