Integration tests with Navidrome in podman #10

Closed
opened 2026-05-16 17:55:23 +00:00 by victor · 0 comments
Owner

Overview

Black-box integration tests that invoke the subsonic-duplicates binary as a subprocess against a real Navidrome instance running in podman.

Key decisions

  • Audio files: WAV + ID3v2 tags via hound + id3 crates (pure Rust, no external tools).
  • Adapter access: Tests invoke the CLI binary directly via std::process::Command — no library linking needed.
  • Navidrome image: Pinned to a specific release (e.g. deluan/navidrome:0.53.3).
  • Test execution: Sequential, single container per test run, wipe_library() between tests.
  • Gating: --features integration flag so normal cargo test stays fast.

Directory layout

tests/
├── Cargo.toml                   (workspace member, [[test]] target)
└── src/
    ├── lib.rs                   (OnceLock fixture, module declarations)
    ├── navidrome.rs             (podman start/stop/wipe/scan helpers)
    ├── audio.rs                 (write_tagged_wav)
    ├── cli.rs                   (run_cmd helper: writes config, invokes binary, returns output+exit)
    └── tests/
        ├── sync_basic.rs        (tag reading correctness)
        ├── sync_duplicates.rs   (gradual duplicate addition)
        ├── canonical_change.rs  (pick canonical, then change it)
        ├── ratings.rs           (ratings round-trip via API)
        └── export_playlist.rs   (full round-trip to Navidrome playlist)

Test scenarios

  1. sync_basic — add one track, sync, verify title/artist/album/MBID in the store DB.
  2. sync_duplicates — add tracks gradually (fuzzy match, then MBID match), verify pairs detected.
  3. canonical_change — decide canonical A over B, then change to B over A; verify decisions survive re-sync.
  4. ratings — set ratings via Subsonic API, sync, verify ratings stored; set mismatching ratings, verify sync-ratings finds and fixes them.
  5. export_playlist — full round-trip: find → evaluate → export → verify playlist in Navidrome.

Navidrome container config

podman run --rm -d \
  -p 0:4533 \
  -v <music_dir>:/music:Z \
  -v <data_dir>:/data:Z \
  -e ND_MUSICFOLDER=/music \
  -e ND_DATAFOLDER=/data \
  -e ND_LOGLEVEL=warn \
  -e ND_DEFAULTADMINPASSWORD=testpass \
  -e ND_AUTOIMPORTPLAYLISTS=false \
  -e ND_SESSIONTIMEOUT=24h \
  -e ND_SCANNER_SCHEDULE="@every 1h" \
  docker.io/deluan/navidrome:0.53.3

CLI helper pattern

Each test writes a minimal config.toml to a tempfile::TempDir, then calls:

subsonic-duplicates --config <tmp>/config.toml --db-path <tmp>/store.db <subcommand>

and inspects stdout, exit code, and the SQLite DB via subsonic-duplicates-store.

just target

test-integration:
    cargo test -p subsonic-duplicates-integration --features integration -- --nocapture

Open items

  • Verify Navidrome reads ID3 tags from WAV files (title, artist, album, MBID via UFID frame).
  • Confirm startScan / getScanStatus Subsonic endpoints work reliably in Navidrome 0.53.3.
  • Check whether Navidrome assigns deterministic track IDs across rescans (needed for playlist assertions).
## Overview Black-box integration tests that invoke the `subsonic-duplicates` binary as a subprocess against a real Navidrome instance running in podman. ## Key decisions - **Audio files**: WAV + ID3v2 tags via `hound` + `id3` crates (pure Rust, no external tools). - **Adapter access**: Tests invoke the CLI binary directly via `std::process::Command` — no library linking needed. - **Navidrome image**: Pinned to a specific release (e.g. `deluan/navidrome:0.53.3`). - **Test execution**: Sequential, single container per test run, `wipe_library()` between tests. - **Gating**: `--features integration` flag so normal `cargo test` stays fast. ## Directory layout ``` tests/ ├── Cargo.toml (workspace member, [[test]] target) └── src/ ├── lib.rs (OnceLock fixture, module declarations) ├── navidrome.rs (podman start/stop/wipe/scan helpers) ├── audio.rs (write_tagged_wav) ├── cli.rs (run_cmd helper: writes config, invokes binary, returns output+exit) └── tests/ ├── sync_basic.rs (tag reading correctness) ├── sync_duplicates.rs (gradual duplicate addition) ├── canonical_change.rs (pick canonical, then change it) ├── ratings.rs (ratings round-trip via API) └── export_playlist.rs (full round-trip to Navidrome playlist) ``` ## Test scenarios 1. **sync_basic** — add one track, sync, verify title/artist/album/MBID in the store DB. 2. **sync_duplicates** — add tracks gradually (fuzzy match, then MBID match), verify pairs detected. 3. **canonical_change** — decide canonical A over B, then change to B over A; verify decisions survive re-sync. 4. **ratings** — set ratings via Subsonic API, sync, verify ratings stored; set mismatching ratings, verify `sync-ratings` finds and fixes them. 5. **export_playlist** — full round-trip: find → evaluate → export → verify playlist in Navidrome. ## Navidrome container config ``` podman run --rm -d \ -p 0:4533 \ -v <music_dir>:/music:Z \ -v <data_dir>:/data:Z \ -e ND_MUSICFOLDER=/music \ -e ND_DATAFOLDER=/data \ -e ND_LOGLEVEL=warn \ -e ND_DEFAULTADMINPASSWORD=testpass \ -e ND_AUTOIMPORTPLAYLISTS=false \ -e ND_SESSIONTIMEOUT=24h \ -e ND_SCANNER_SCHEDULE="@every 1h" \ docker.io/deluan/navidrome:0.53.3 ``` ## CLI helper pattern Each test writes a minimal `config.toml` to a `tempfile::TempDir`, then calls: ``` subsonic-duplicates --config <tmp>/config.toml --db-path <tmp>/store.db <subcommand> ``` and inspects stdout, exit code, and the SQLite DB via `subsonic-duplicates-store`. ## just target ```just test-integration: cargo test -p subsonic-duplicates-integration --features integration -- --nocapture ``` ## Open items - Verify Navidrome reads ID3 tags from WAV files (title, artist, album, MBID via `UFID` frame). - Confirm `startScan` / `getScanStatus` Subsonic endpoints work reliably in Navidrome 0.53.3. - Check whether Navidrome assigns deterministic track IDs across rescans (needed for playlist assertions).
Sign in to join this conversation.
No labels
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
victor/subsonic_duplicates#10
No description provided.