# Test Verification Suite for Technical Roadmap 22_CLIENT_DESK.md import os import pytest import numpy as np from fastapi import HTTPException from app.core.dsp_utils import find_zero_crossing, apply_micro_crossfade from app.core.vst_engine import render_midi_events_to_audio from app.api.v1.auth import enforce_password_changed def test_kpi_1_zero_crossing_detection(): """Kiểm thử Zero-Crossing: Cắt lát nhạc bằng AI Cut ở mốc giây lẻ (22_CLIENT_DESK.md §5).""" sr = 44100 # Generate 1 second sine wave at 440 Hz t = np.linspace(0, 1.0, sr) signal = np.sin(2 * np.pi * 440 * t) target_time = 0.1234 # Odd time offset zc_time = find_zero_crossing(signal, sr, target_time, window_seconds=0.04) assert zc_time is not None zc_sample = int(zc_time * sr) # Verify physical sign inversion x[i] * x[i+1] <= 0 if 0 <= zc_sample < len(signal) - 1: assert signal[zc_sample] * signal[zc_sample + 1] <= 0.05 print(f"Zero crossing test passed: target {target_time}s -> zc {zc_time}s") def test_kpi_2_micro_crossfade_splicing(): """Kiểm thử Micro-Crossfade (10ms) tại hai đầu điểm ráp nối để triệt tiêu click/pop.""" sr = 44100 original = np.ones(sr, dtype=np.float32) * 0.5 edited = np.ones(sr // 2, dtype=np.float32) * 0.8 start_sample = sr // 4 output = apply_micro_crossfade(original, edited, start_sample, fade_len_ms=10, sr=sr) assert len(output) == len(original) # Check smooth transition at start assert 0.49 <= output[start_sample] <= 0.81 print("Micro-crossfade splicing test passed.") def test_kpi_3_vst_synth_midi_rendering(): """Kiểm thử Docker VSTi: Gửi chuỗi MIDI nốt và nạp synth tổng hợp ra mảng Stereo.""" midi_events = [ {"note": 60, "start_beat": 0.0, "duration_beats": 1.0, "velocity": 100}, # C4 {"note": 64, "start_beat": 1.0, "duration_beats": 1.0, "velocity": 90}, # E4 {"note": 67, "start_beat": 2.0, "duration_beats": 2.0, "velocity": 110} # G4 ] audio_array = render_midi_events_to_audio(midi_events, sr=44100, bpm=120.0) assert isinstance(audio_array, np.ndarray) assert audio_array.shape[0] == 2 # Stereo channels (L, R) assert audio_array.shape[1] > 0 assert np.max(np.abs(audio_array)) > 0.01 print(f"VSTi MIDI rendering test passed: stereo output shape {audio_array.shape}") def test_kpi_4_auth_security_must_change_password(): """Kiểm thử Bảo Mật Auth: Đăng nhập tài khoản mặc định và gọi API (22_CLIENT_DESK.md §5).""" user_must_change = {"user_id": "test_user_1", "must_change_password": True} user_password_changed = {"user_id": "test_user_2", "must_change_password": False} # Should raise HTTP 403 Forbidden when must_change_password = True with pytest.raises(HTTPException) as exc_info: enforce_password_changed(user_must_change) assert exc_info.value.status_code == 403 # Should pass without error when must_change_password = False enforce_password_changed(user_password_changed) print("Auth Security 403 Forbidden test passed.") def test_kpi_5_storage_quota_calculation(): """Kiểm thử Quota: S_used + S_new <= S_limit.""" s_limit_mb = 500 s_used_mb = 480 s_new_mb = 30 # Total = 510MB > 500MB limit total = s_used_mb + s_new_mb is_quota_exceeded = total > s_limit_mb assert is_quota_exceeded is True print("Storage Quota calculation test passed.") def test_kpi_6_shift_click_range_anchor_math(): """Kiểm thử Shift+Click: Bôi chọn cục bộ [min(T_anchor, T_end), max(T_anchor, T_end)].""" t_anchor = 5.4 t_end = 2.1 sel_start = min(t_anchor, t_end) sel_end = max(t_anchor, t_end) assert sel_start == 2.1 assert sel_end == 5.4 print("Shift+Click range anchor math test passed.")