You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
79 lines
3.3 KiB
79 lines
3.3 KiB
from pathlib import Path
|
|
|
|
import pytest
|
|
import yaml
|
|
|
|
from src.config_loader import load_config
|
|
from src.exceptions import ConfigurationError
|
|
|
|
|
|
DEFAULT = Path(__file__).parents[1] / "config" / "default.yaml"
|
|
|
|
|
|
def write_yaml(tmp_path: Path, values: dict[str, object]) -> Path:
|
|
path = tmp_path / "experiment.yaml"
|
|
path.write_text(yaml.safe_dump(values), encoding="utf-8")
|
|
return path
|
|
|
|
|
|
def test_recursive_merge_and_experiment_precedence(tmp_path: Path) -> None:
|
|
path = write_yaml(tmp_path, {"detector": {"confidence_threshold": 0.8}, "experiment": {"location": "lab"}})
|
|
config = load_config(DEFAULT, path)
|
|
assert config.detector.confidence_threshold == 0.8
|
|
assert config.detector.iou_threshold == 0.5
|
|
assert config.experiment.location == "lab"
|
|
assert config.experiment.experiment_id == "phase1_default"
|
|
|
|
|
|
def test_cli_override_is_last(tmp_path: Path) -> None:
|
|
path = write_yaml(tmp_path, {"detector": {"confidence_threshold": 0.6}})
|
|
config = load_config(DEFAULT, path, {"detector": {"confidence_threshold": 0.7}})
|
|
assert config.detector.confidence_threshold == 0.7
|
|
|
|
|
|
@pytest.mark.parametrize("override", [
|
|
{"detector": {"confidence_threshold": 1.1}},
|
|
{"evaluation_region": {"x1": -0.1}},
|
|
{"evaluation_region": {"x1": 0.9, "x2": 0.8}},
|
|
{"input": {"type": "video", "video_path": None}},
|
|
{"tracker": {"match_thresh": 1.1}},
|
|
{"crossing": {"minimum_track_points": 1}},
|
|
{"performance": {"skip_frames": 1}},
|
|
{"face": {"process_every_n_frames": 0}},
|
|
{"face": {"roi_height_ratio": 1.1}},
|
|
{"face": {"min_detection_confidence": -0.1}},
|
|
{"head_pose": {"ema_alpha": 0.0}},
|
|
{"head_pose": {"max_abs_angle": 0}},
|
|
{"face_logging": {"flush_interval_frames": 0}},
|
|
{"turn_detection": {"signage_yaw_direction": "sideways"}},
|
|
{"turn_detection": {"baseline_strategy": "unknown"}},
|
|
{"turn_detection": {"baseline_min_samples": 0}},
|
|
{"turn_detection": {"subtle_threshold_deg": 25, "weak_threshold_deg": 20}},
|
|
{"turn_detection": {"min_pose_estimation_rate_for_evaluation": 1.1}},
|
|
{"turn_logging": {"flush_interval_frames": 0}},
|
|
{"audio": {"backend": "unknown"}},
|
|
{"audio": {"volume": 1.1}},
|
|
{"audio": {"overlap_policy": "mix"}},
|
|
{"voice_prompt": {"mode": "random"}},
|
|
{"voice_prompt": {"trigger_strategy": "unknown"}},
|
|
{"voice_prompt": {"response_window_sec": 0}},
|
|
{"voice_prompt": {"fixed_position_axis": "z"}},
|
|
{"voice_logging": {"flush_interval_frames": 0}},
|
|
{"person_state": {"min_track_duration_sec": -1}},
|
|
{"person_state_logging": {"flush_interval_frames": 0}},
|
|
{"unified_logging": {"flush_interval_frames": 0}},
|
|
{"analysis": {"alpha": 1.0}},
|
|
{"analysis": {"response_rate_test": "bad"}},
|
|
{"gui": {"preview_max_fps": 0}},
|
|
{"gui": {"enabled": "yes"}},
|
|
{"pilot_diagnostics": {"min_valid_voice_analysis_rate": 1.1}},
|
|
{"pilot_diagnostics": {"max_condition_valid_count_ratio": 0.5}},
|
|
])
|
|
def test_invalid_config(tmp_path: Path, override: dict[str, object]) -> None:
|
|
with pytest.raises(ConfigurationError):
|
|
load_config(DEFAULT, write_yaml(tmp_path, override))
|
|
|
|
|
|
def test_skip_frames_allowed_when_tracker_disabled(tmp_path: Path) -> None:
|
|
path = write_yaml(tmp_path, {"tracker": {"enabled": False}, "performance": {"skip_frames": 2}})
|
|
assert load_config(DEFAULT, path).performance.skip_frames == 2
|
|
|