feat: initial commit for export and import
This commit is contained in:
183
test_export_import.py
Executable file
183
test_export_import.py
Executable file
@@ -0,0 +1,183 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user