183 lines
6.7 KiB
Python
Executable File
183 lines
6.7 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Test d'intégration : export + import des cues Mixxx via les modules mixxx_export et mixxx_import.
|
|
Nécessite que mixxx_export.py et mixxx_import_gui.py (ou mixxx_import.py) soient dans le même répertoire,
|
|
ou ajustez les imports.
|
|
"""
|
|
|
|
import sqlite3
|
|
import tempfile
|
|
import os
|
|
import json
|
|
from pathlib import Path
|
|
import subprocess
|
|
import sys
|
|
|
|
# ------------------------------------------------------------
|
|
# 1. Créer une base Mixxx temporaire avec les bonnes tables
|
|
# ------------------------------------------------------------
|
|
def create_temp_db(db_path: Path):
|
|
con = sqlite3.connect(db_path)
|
|
con.executescript("""
|
|
CREATE TABLE track_locations (
|
|
id INTEGER PRIMARY KEY,
|
|
location TEXT,
|
|
filename TEXT,
|
|
directory TEXT,
|
|
filesize INTEGER,
|
|
fs_deleted INTEGER DEFAULT 0,
|
|
needs_verification INTEGER DEFAULT 0
|
|
);
|
|
CREATE TABLE library (
|
|
id INTEGER PRIMARY KEY,
|
|
artist TEXT,
|
|
title TEXT,
|
|
album TEXT,
|
|
genre TEXT,
|
|
tracknumber INTEGER,
|
|
year INTEGER,
|
|
duration REAL,
|
|
samplerate INTEGER,
|
|
bitrate INTEGER,
|
|
channels INTEGER,
|
|
bpm REAL,
|
|
key TEXT,
|
|
rating INTEGER,
|
|
comment TEXT,
|
|
location INTEGER REFERENCES track_locations(id) -- clé manquante dans l'exemple précédent
|
|
);
|
|
CREATE TABLE cues (
|
|
id INTEGER PRIMARY KEY,
|
|
track_id INTEGER,
|
|
type INTEGER,
|
|
position REAL,
|
|
length REAL,
|
|
hotcue INTEGER,
|
|
label TEXT,
|
|
color INTEGER
|
|
);
|
|
CREATE TABLE IF NOT EXISTS Playlists (
|
|
id INTEGER PRIMARY KEY,
|
|
name TEXT,
|
|
position INTEGER,
|
|
hidden INTEGER DEFAULT 0,
|
|
date_created TEXT,
|
|
date_modified TEXT
|
|
);
|
|
CREATE TABLE IF NOT EXISTS PlaylistTracks (
|
|
id INTEGER PRIMARY KEY,
|
|
playlist_id INTEGER,
|
|
track_id INTEGER,
|
|
position INTEGER,
|
|
pl_datetime_added TEXT
|
|
);
|
|
""")
|
|
con.commit()
|
|
return con
|
|
|
|
# ------------------------------------------------------------
|
|
# 2. Insérer des données de test
|
|
# ------------------------------------------------------------
|
|
def populate_test_data(con, audio_file_path: Path):
|
|
# Une piste "test.flac"
|
|
tl_id = 1
|
|
con.execute("""
|
|
INSERT INTO track_locations (id, location, filename, directory, filesize)
|
|
VALUES (?, ?, ?, ?, ?)
|
|
""", (tl_id, str(audio_file_path), audio_file_path.name, str(audio_file_path.parent), 12345))
|
|
con.execute("""
|
|
INSERT INTO library (id, artist, title, album, genre, year, duration, location)
|
|
VALUES (?, 'Test', 'Ma Chanson', '', '', 2025, 200, ?)
|
|
""", (tl_id, tl_id)) # location pointe vers track_locations.id
|
|
# Deux hot cues
|
|
con.execute("INSERT INTO cues (track_id, type, position, length, hotcue, label, color) VALUES (?,1,10.5,0,1,'Intro',16744448)", (tl_id,))
|
|
con.execute("INSERT INTO cues (track_id, type, position, length, hotcue, label, color) VALUES (?,1,45.0,0,2,'Drop',0xFF8000)", (tl_id,))
|
|
# Une boucle (type=4)
|
|
con.execute("INSERT INTO cues (track_id, type, position, length, hotcue, label, color) VALUES (?,4,60.0,15.0,-1,'',0)", (tl_id,))
|
|
con.commit()
|
|
|
|
# ------------------------------------------------------------
|
|
# 3. Fonctions de test
|
|
# ------------------------------------------------------------
|
|
def run_export(db_path: Path, output_dir: Path):
|
|
# Utiliser le module mixxx_export directement
|
|
import mixxx_export
|
|
mixxx_export.export_cues(db_path, output_dir)
|
|
|
|
def run_import(music_dir: Path, db_path: Path, dry_run=False):
|
|
# Utiliser le module mixxx_import (v2)
|
|
import mixxx_import
|
|
mixxx_import.import_cues_v2(music_dir, db_path, dry_run=dry_run, log_callback=print)
|
|
|
|
def main():
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
tmp = Path(tmpdir)
|
|
db_path = tmp / "test_mixxxdb.sqlite"
|
|
audio_dir = tmp / "music"
|
|
audio_dir.mkdir()
|
|
audio_file = audio_dir / "test.flac"
|
|
audio_file.write_text("fake audio") # fichier factice
|
|
|
|
# 1. Créer DB et peupler
|
|
con = create_temp_db(db_path)
|
|
populate_test_data(con, audio_file)
|
|
con.close()
|
|
|
|
# 2. Exporter les cues dans un sous-dossier
|
|
export_dir = tmp / "export"
|
|
export_dir.mkdir()
|
|
run_export(db_path, export_dir)
|
|
expected_json = export_dir / "test.flac.mixxx"
|
|
assert expected_json.exists(), "Le fichier .mixxx n'a pas été créé"
|
|
|
|
with open(expected_json, "r") as f:
|
|
data = json.load(f)
|
|
assert data["version"] == 1
|
|
assert data["filename"] == "test.flac"
|
|
assert len(data["cues"]) == 3
|
|
print("[PASS] Export OK")
|
|
|
|
# 3. Préparer l'import : copier le .mixxx dans le dossier audio
|
|
import_audio_dir = tmp / "import"
|
|
import_audio_dir.mkdir()
|
|
import_audio_file = import_audio_dir / "test.flac"
|
|
import_audio_file.write_text("fake audio") # recréer le fichier audio
|
|
import_json = import_audio_dir / "test.flac.mixxx"
|
|
import_json.write_text(expected_json.read_text())
|
|
|
|
# Créer une nouvelle DB vierge pour l'import (même structure)
|
|
fresh_db = tmp / "fresh_mixxxdb.sqlite"
|
|
create_temp_db(fresh_db).close()
|
|
|
|
# 4. Importer
|
|
run_import(import_audio_dir, fresh_db, dry_run=False)
|
|
|
|
# 5. Vérifier que les cues ont été insérés
|
|
con = sqlite3.connect(fresh_db)
|
|
con.row_factory = sqlite3.Row
|
|
# Vérifier la piste
|
|
tl = con.execute("SELECT * FROM track_locations WHERE filename='test.flac'").fetchone()
|
|
assert tl is not None, "Piste non importée"
|
|
track_id = tl["id"]
|
|
# Vérifier les cues
|
|
cues = con.execute("SELECT * FROM cues WHERE track_id=?", (track_id,)).fetchall()
|
|
assert len(cues) == 3, f"Nombre de cues incorrect : {len(cues)} au lieu de 3"
|
|
# Vérifier les types
|
|
types = {c["type"] for c in cues}
|
|
assert types == {1, 4}, f"Types de cues inattendus: {types}"
|
|
print("[PASS] Import OK")
|
|
|
|
# 6. Test dry-run
|
|
# Créer une autre DB vide pour simuler
|
|
dry_db = tmp / "dry_db.sqlite"
|
|
create_temp_db(dry_db).close()
|
|
run_import(import_audio_dir, dry_db, dry_run=True)
|
|
con = sqlite3.connect(dry_db)
|
|
cues_dry = con.execute("SELECT count(*) FROM cues").fetchone()[0]
|
|
assert cues_dry == 0, "Le dry-run a écrit des données !"
|
|
print("[PASS] Dry-run OK")
|
|
|
|
print("\n✅ Tous les tests ont réussi !")
|
|
|
|
if __name__ == "__main__":
|
|
main() |