File size: 3,051 Bytes
ce84147
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import io
import json
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parents[1]))

import numpy as np
import soundfile as sf
from fastapi.testclient import TestClient

from app import app
from pipeline_runner import PipelineParams


def wav_bytes() -> io.BytesIO:
    sr = 22050
    t = np.arange(int(sr * 0.25)) / sr
    y = 0.15 * np.sin(2 * np.pi * 220 * t) * np.exp(-t * 10)
    buf = io.BytesIO()
    sf.write(buf, y, sr, format="WAV")
    buf.seek(0)
    return buf


def test_mapping_coerces_browser_form_values() -> None:
    params = PipelineParams.from_mapping({
        "stem": "all",
        "subdivision": "16",
        "demucs_shifts": "0",
        "demucs_overlap": "0.25",
        "target_min": "2",
        "target_max": "6",
        "synthesize": "false",
        "quantize_midi": "true",
        "use_disk_cache": "1",
    })
    assert params.subdivision == 16
    assert params.demucs_shifts == 0
    assert params.demucs_overlap == 0.25
    assert params.target_min == 2
    assert params.target_max == 6
    assert params.synthesize is False
    assert params.quantize_midi is True
    assert params.use_disk_cache is True


def test_invalid_subdivision_is_actionable() -> None:
    try:
        PipelineParams.from_mapping({"subdivision": "12"})
    except ValueError as exc:
        assert "subdivision must be one of 4, 8, 16, 32, 64" in str(exc)
    else:
        raise AssertionError("invalid subdivision was accepted")


def test_jobs_endpoint_accepts_string_subdivision_from_browser_select() -> None:
    client = TestClient(app)
    params = {
        "stem": "all",
        "subdivision": "16",
        "demucs_shifts": "0",
        "synthesize": "false",
        "use_disk_cache": "false",
    }
    response = client.post(
        "/api/jobs",
        files={"file": ("tiny.wav", wav_bytes(), "audio/wav")},
        data={"params": json.dumps(params)},
    )
    assert response.status_code == 202, response.text
    payload = response.json()
    assert payload["params"]["subdivision"] == 16
    assert payload["params"]["demucs_shifts"] == 0
    assert payload["params"]["synthesize"] is False
    assert payload["params"]["use_disk_cache"] is False


def test_jobs_endpoint_reports_bad_parameter_as_visible_detail() -> None:
    client = TestClient(app)
    response = client.post(
        "/api/jobs",
        files={"file": ("tiny.wav", wav_bytes(), "audio/wav")},
        data={"params": json.dumps({"subdivision": "12"})},
    )
    assert response.status_code == 400
    payload = response.json()
    assert "Invalid extraction parameter" in payload["detail"]
    assert "subdivision must be one of 4, 8, 16, 32, 64" in payload["detail"]


if __name__ == "__main__":
    test_mapping_coerces_browser_form_values()
    test_invalid_subdivision_is_actionable()
    test_jobs_endpoint_accepts_string_subdivision_from_browser_select()
    test_jobs_endpoint_reports_bad_parameter_as_visible_detail()
    print("parameter validation and API error visibility contract passed")