Files
SonicForgeStudio/tests/test_desk_verification.py
T

94 lines
3.8 KiB
Python

# 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.")