"""Tests for sidecar manifest parsing — Issue #2.""" import pytest import tempfile import os from pathlib import Path from sidecar.manifest import load_manifest, validate_profile class TestValidateProfile: """Tests for manifest profile validation.""" def test_valid_profile(self): profile = { "id": "qwen-3-8b", "name": "Qwen 3 8B", "model_path": "/home/bigt/AI/llm/qwen/qwen3-8b-q4.gguf", "flags": {"n_ctx": 8192, "n_gpu_layers": 35}, } result = validate_profile(profile) assert result["id"] == "qwen-3-8b" assert result["name"] == "Qwen 3 8B" assert result["model_path"] == "/home/bigt/AI/llm/qwen/qwen3-8b-q4.gguf" assert result["flags"] == {"n_ctx": 8192, "n_gpu_layers": 35} def test_valid_profile_no_flags(self): profile = {"id": "test-model", "name": "Test", "model_path": "/path/to/model.gguf"} result = validate_profile(profile) assert result["id"] == "test-model" assert result["flags"] == {} def test_missing_id_raises(self): profile = {"name": "Test", "model_path": "/path"} with pytest.raises(ValueError, match="Missing required field: id"): validate_profile(profile) def test_missing_name_raises(self): profile = {"id": "test", "model_path": "/path"} with pytest.raises(ValueError, match="Missing required field: name"): validate_profile(profile) def test_missing_model_path_raises(self): profile = {"id": "test", "name": "Test"} with pytest.raises(ValueError, match="Missing required field: model_path"): validate_profile(profile) def test_flags_defaults_to_empty_dict(self): profile = {"id": "test", "name": "Test", "model_path": "/path"} result = validate_profile(profile) assert result["flags"] == {} class TestLoadManifest: """Tests for manifest YAML loading.""" def test_empty_manifest_returns_empty_list(self, tmp_path): manifest_file = tmp_path / "manifest.yaml" manifest_file.write_text("[]\n") result = load_manifest(str(manifest_file)) assert result == [] def test_empty_file_returns_empty_list(self, tmp_path): manifest_file = tmp_path / "manifest.yaml" manifest_file.write_text("") result = load_manifest(str(manifest_file)) assert result == [] def test_valid_manifest(self, tmp_path): manifest_file = tmp_path / "manifest.yaml" manifest_file.write_text( "- id: qwen-3-8b\n" " name: \"Qwen 3 8B\"\n" " model_path: /home/bigt/AI/llm/qwen/qwen3-8b-q4.gguf\n" " flags:\n" " n_ctx: 8192\n" " n_gpu_layers: 35\n" "- id: qwen-3-8b-long\n" " name: \"Qwen 3 8B (Long Context)\"\n" " model_path: /home/bigt/AI/llm/qwen/qwen3-8b-q4.gguf\n" " flags:\n" " n_ctx: 32768\n" " n_gpu_layers: 20\n" ) result = load_manifest(str(manifest_file)) assert len(result) == 2 assert result[0]["id"] == "qwen-3-8b" assert result[1]["name"] == "Qwen 3 8B (Long Context)" assert result[1]["flags"]["n_ctx"] == 32768 def test_invalid_yaml_returns_none(self, tmp_path): manifest_file = tmp_path / "manifest.yaml" manifest_file.write_text("{{{{invalid yaml:::\n") result = load_manifest(str(manifest_file)) assert result is None def test_non_existent_file_returns_none(self, tmp_path): result = load_manifest(str(tmp_path / "nonexistent.yaml")) assert result is None def test_file_does_not_exist_returns_none(self): result = load_manifest("/tmp/does_not_exist_12345.yaml") assert result is None