Test fixture: a throwaway iPod with no hardware #12

Merged
wokoman merged 1 commit from test/ipod-fixture into main 2026-08-28 19:26:49 +02:00
Owner

Tests can now stand up a real, empty iPod in a temporary directory and talk to it exactly as they would a mounted device — parse it, copy a track in, read it back — with no hardware attached and nothing left behind. The code with the worst failure modes was the code with no coverage; this is what the removal and copy tickets are unverifiable without.

FakeIpod::new() calls libgpod's own device initialisation on a temp directory: it seeds the model into a sysinfo file, creates the directory skeleton, adds a master playlist and writes an empty database. No new FFI and no build changes — the binding was already in the itdb_.* allowlist.

Two decisions worth recording.

The fixture is an iPod Video 1st gen (A002), not the Classic the project develops against. Classic 1st gen resolves to ITDB_CHECKSUM_HASH58, which needs a FirewireGuid that a temp directory has no way to supply. Video 1st gen is ITDB_CHECKSUM_NONE, so writes succeed. The consequence is that the checksum path stays hardware-only, as it was.

Drop order comes from declaration order, not from a lifetime. The database handle points into the directory the fixture deletes, so it has to be dropped first; let ipod = FakeIpod::new(); let db = ipod.open(); gives that for free, and the doc comment says why it matters.

Beyond the ticket: db.rs already had a private TempDir and a hand-rolled minimal-database writer in its test module, so the premise that no non-device constructor existed was not quite right. Its four tests move onto the shared fixture and the duplicate is deleted — hence the net −80 lines there. There is one way to make a test database now.

The round trip asserts the copied audio is at the path the reopened database claims, which is the pair of failures the fixture exists to catch. 60 unit tests pass with nothing attached, no new #[ignore], cargo clippy --all-targets clean.

libgpod leaks its database handle on one error path in the initialisation function — when directory creation fails. Upstream, in vendored code, and only on failed fixture setup. Noted, not fixed.

Closes #3.

Tests can now stand up a real, empty iPod in a temporary directory and talk to it exactly as they would a mounted device — parse it, copy a track in, read it back — with no hardware attached and nothing left behind. The code with the worst failure modes was the code with no coverage; this is what the removal and copy tickets are unverifiable without. `FakeIpod::new()` calls libgpod's own device initialisation on a temp directory: it seeds the model into a sysinfo file, creates the directory skeleton, adds a master playlist and writes an empty database. No new FFI and no build changes — the binding was already in the `itdb_.*` allowlist. Two decisions worth recording. **The fixture is an iPod Video 1st gen (`A002`), not the Classic the project develops against.** Classic 1st gen resolves to `ITDB_CHECKSUM_HASH58`, which needs a `FirewireGuid` that a temp directory has no way to supply. Video 1st gen is `ITDB_CHECKSUM_NONE`, so writes succeed. The consequence is that the checksum path stays hardware-only, as it was. **Drop order comes from declaration order, not from a lifetime.** The database handle points into the directory the fixture deletes, so it has to be dropped first; `let ipod = FakeIpod::new(); let db = ipod.open();` gives that for free, and the doc comment says why it matters. Beyond the ticket: `db.rs` already had a private `TempDir` and a hand-rolled minimal-database writer in its test module, so the premise that no non-device constructor existed was not quite right. Its four tests move onto the shared fixture and the duplicate is deleted — hence the net −80 lines there. There is one way to make a test database now. The round trip asserts the copied audio is at the path the reopened database claims, which is the pair of failures the fixture exists to catch. 60 unit tests pass with nothing attached, no new `#[ignore]`, `cargo clippy --all-targets` clean. libgpod leaks its database handle on one error path in the initialisation function — when directory creation fails. Upstream, in vendored code, and only on failed fixture setup. Noted, not fixed. Closes #3.
libgpod initialises a blank device from a plain directory, so the copy and
removal paths — the ones with the worst failure modes and no coverage — can
be tested with nothing plugged in.

The private database fixture in db.rs is deleted in favour of it; there is
one way to make a test database now.

Closes #3.
wokoman deleted branch test/ipod-fixture 2026-08-28 19:26:49 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
wokoman/ironpod!12
No description provided.