soulsync/tests/test_canonical_manual_lock.py
BoulderBadgeDad 31637e0096 canonical: recognize musicbrainz as a readable album source (PR #929 follow-up)
#929 added 'musicbrainz' to library_reorganize._ALBUM_ID_COLUMNS but not to the
canonical layer, breaking the equality invariant test (canonical reads exactly what
reorganize reads). add musicbrainz to CANONICAL_ALBUM_SOURCES, and move it from the
'can't pin' param group to the 'pins' group in the manual-lock tests — now consistent,
and forward-compatible with pinning a deliberately-matched MB edition. inert at runtime
today (mb isn't in the manual source selector, so should_pin is never called with it).
540 canonical/reorganize tests green.
2026-06-26 19:04:24 -07:00

99 lines
3.8 KiB
Python

"""#758 — a manual album match pins (and LOCKS) the canonical album version, so
re-resolution / the auto canonical job can't drag it back to the deluxe edition.
Two seams:
- should_pin_manual_canonical (pure): when a manual match should pin canonical.
- set_album_canonical / get_album_canonical (DB): the lock can't be overwritten
by an auto write, but a new manual write still wins.
"""
from __future__ import annotations
from pathlib import Path
import pytest
from core.metadata.canonical_version import (
CANONICAL_ALBUM_SOURCES,
should_pin_manual_canonical,
)
from database.music_database import MusicDatabase
# ---------------------------------------------------------------------------
# should_pin_manual_canonical — pure
# ---------------------------------------------------------------------------
@pytest.mark.parametrize('source', ['spotify', 'itunes', 'deezer', 'discogs', 'hydrabase', 'musicbrainz'])
def test_pins_album_on_recognised_source(source):
assert should_pin_manual_canonical('album', source) is True
@pytest.mark.parametrize('entity', ['artist', 'track'])
def test_does_not_pin_non_album(entity):
assert should_pin_manual_canonical(entity, 'spotify') is False
@pytest.mark.parametrize('source', ['lastfm', 'genius', 'audiodb', 'tidal'])
def test_does_not_pin_source_canonical_cant_read(source):
# No album-version data the canonical tools read → nothing to pin.
assert should_pin_manual_canonical('album', source) is False
def test_sources_stay_in_sync_with_album_id_columns():
# The set must mirror the canonical reader's column map; if a source is
# added there, this fails until CANONICAL_ALBUM_SOURCES is updated.
from core.library_reorganize import _ALBUM_ID_COLUMNS
assert CANONICAL_ALBUM_SOURCES == set(_ALBUM_ID_COLUMNS)
# ---------------------------------------------------------------------------
# set_album_canonical / get_album_canonical — the lock (DB)
# ---------------------------------------------------------------------------
def _insert_album(db, album_id):
conn = db._get_connection()
conn.execute("INSERT OR IGNORE INTO artists (id, name) VALUES ('ar1', 'Artist')")
conn.execute("INSERT INTO albums (id, artist_id, title) VALUES (?, 'ar1', 'Album')", (album_id,))
conn.commit()
conn.close()
@pytest.fixture
def db(tmp_path: Path) -> MusicDatabase:
d = MusicDatabase(database_path=str(tmp_path / "ml.db"))
_insert_album(d, 'al1')
return d
def test_manual_lock_set_and_read(db):
assert db.set_album_canonical('al1', 'spotify', 'REG', 1.0, locked=True) is True
c = db.get_album_canonical('al1')
assert c['source'] == 'spotify' and c['album_id'] == 'REG' and c['locked'] is True
def test_auto_cannot_overwrite_manual_lock(db):
db.set_album_canonical('al1', 'spotify', 'REG', 1.0, locked=True)
# The auto resolve job tries to re-pin the deluxe — must be refused.
assert db.set_album_canonical('al1', 'spotify', 'DELUXE', 0.9, locked=False) is False
c = db.get_album_canonical('al1')
assert c['album_id'] == 'REG' and c['locked'] is True # unchanged
def test_new_manual_match_overrides_existing_pin(db):
db.set_album_canonical('al1', 'spotify', 'OLD', 0.8, locked=False) # auto pin
# User manually picks a different edition — manual always wins.
assert db.set_album_canonical('al1', 'itunes', 'NEW', 1.0, locked=True) is True
c = db.get_album_canonical('al1')
assert c['source'] == 'itunes' and c['album_id'] == 'NEW' and c['locked'] is True
def test_auto_overwrites_auto(db):
db.set_album_canonical('al1', 'spotify', 'A', 0.8, locked=False)
assert db.set_album_canonical('al1', 'spotify', 'B', 0.9, locked=False) is True
assert db.get_album_canonical('al1')['album_id'] == 'B'
def test_unresolved_album_returns_none(db):
_insert_album(db, 'al2')
assert db.get_album_canonical('al2') is None