File size: 3,128 Bytes
76db545
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""
Unit tests for the engine layer: WhisperBackbone, AdapterManager, Transcriber.
These tests use mocks so they run without GPU or downloaded model weights.
"""
from __future__ import annotations

from unittest.mock import MagicMock, patch

import numpy as np
import pytest


class TestWhisperBackbone:
    def test_raises_before_load(self, tmp_path):
        """Accessing model or processor before load() should raise RuntimeError."""
        import yaml

        config = {"model": {"id": "openai/whisper-large-v3-turbo"}, "training": {}, "audio": {}, "paths": {}}
        config_path = tmp_path / "base_config.yaml"
        config_path.write_text(yaml.dump(config))

        from src.engine.whisper_base import WhisperBackbone

        backbone = WhisperBackbone(str(config_path))
        with pytest.raises(RuntimeError):
            _ = backbone.model
        with pytest.raises(RuntimeError):
            _ = backbone.processor

    def test_model_id_read_from_config(self, tmp_path):
        import yaml

        config = {"model": {"id": "test-model-id"}, "training": {}, "audio": {}, "paths": {}}
        config_path = tmp_path / "base_config.yaml"
        config_path.write_text(yaml.dump(config))

        from src.engine.whisper_base import WhisperBackbone

        backbone = WhisperBackbone(str(config_path))
        assert backbone.model_id == "test-model-id"


class TestAdapterManager:
    def _make_mock_model(self):
        mock_model = MagicMock()
        mock_model.peft_config = {}
        return mock_model

    def test_register_missing_path(self, tmp_path):
        """Registering a non-existent path should log a warning but not raise."""
        from src.engine.adapter_manager import AdapterManager

        model = self._make_mock_model()
        manager = AdapterManager(model, {})
        # Should not raise
        manager.register("bam", str(tmp_path / "nonexistent"))
        assert "bam" in manager.list_available()

    def test_list_available(self, tmp_path):
        from src.engine.adapter_manager import AdapterManager

        bam_path = tmp_path / "bam"
        bam_path.mkdir()
        ful_path = tmp_path / "ful"
        ful_path.mkdir()

        model = self._make_mock_model()
        manager = AdapterManager(model, {})
        manager.register("bam", str(bam_path))
        manager.register("ful", str(ful_path))

        available = manager.list_available()
        assert "bam" in available
        assert "ful" in available

    def test_unregistered_language_raises(self):
        from src.engine.adapter_manager import AdapterManager

        model = self._make_mock_model()
        manager = AdapterManager(model, {})
        with pytest.raises(KeyError):
            manager.load_adapter("xyz")


class TestTranscriptionResult:
    def test_dataclass_fields(self):
        from src.engine.transcriber import TranscriptionResult

        result = TranscriptionResult(
            text="test",
            language="bam",
            duration_s=5.0,
            processing_time_ms=120,
        )
        assert result.text == "test"
        assert result.confidence is None