325 lines
13 KiB
Python
325 lines
13 KiB
Python
"""Tests for the config module."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import subprocess
|
|
import sys
|
|
|
|
|
|
def test_config_defaults() -> None:
|
|
"""Test that config loads with expected default values."""
|
|
env_str = ""
|
|
for k, v in {
|
|
"DISCORD_TOKEN": "test-token",
|
|
"CHAT_ENDPOINT": "https://chat.example.com/v1",
|
|
"COMPLETION_ENDPOINT": "https://completion.example.com/v1",
|
|
"IMAGE_GEN_ENDPOINT": "https://image.example.com/v1",
|
|
"IMAGE_EDIT_ENDPOINT": "https://image-edit.example.com/v1",
|
|
"EMBEDDING_ENDPOINT": "https://embedding.example.com/v1",
|
|
"CHAT_MODEL": "test-chat-model",
|
|
"COMPLETION_MODEL": "test-completion-model",
|
|
"IMAGE_GEN_MODEL": "test-image-model",
|
|
"IMAGE_EDIT_MODEL": "test-image-edit-model",
|
|
"EMBEDDING_MODEL": "test-embedding-model",
|
|
"CHAT_ENDPOINT_KEY": "test-key",
|
|
"COMPLETION_ENDPOINT_KEY": "test-completion-key",
|
|
"IMAGE_GEN_ENDPOINT_KEY": "test-image-key",
|
|
"IMAGE_EDIT_ENDPOINT_KEY": "test-image-edit-key",
|
|
"EMBEDDING_ENDPOINT_KEY": "test-embedding-key",
|
|
"MAX_COMPLETION_TOKENS": "1000",
|
|
"MAX_HISTORY_MESSAGES": "1000",
|
|
"SIMILARITY_THRESHOLD": "0.7",
|
|
"TOP_K_RESULTS": "5",
|
|
"TTS_MODEL_PATH": "/tmp/test-model.onnx",
|
|
"TTS_VOICES_PATH": "/tmp/test-voices.bin",
|
|
"TTS_VOICE": "af_sarah",
|
|
"TTS_SPEED": "1.0",
|
|
"DB_PATH": ":memory:",
|
|
}.items():
|
|
env_str += f'os.environ["{k}"] = "{v}"\n'
|
|
|
|
code = f"""
|
|
import sys
|
|
sys.path.insert(0, "/var/home/ducoterra/Projects/vibe_discord_bots")
|
|
import os
|
|
os.environ.clear()
|
|
os.environ["PATH"] = "/usr/bin:/bin"
|
|
{env_str}
|
|
import vibe_bot.config
|
|
assert vibe_bot.config.DISCORD_TOKEN == "test-token"
|
|
assert vibe_bot.config.CHAT_ENDPOINT == "https://chat.example.com/v1"
|
|
assert vibe_bot.config.COMPLETION_ENDPOINT == "https://completion.example.com/v1"
|
|
assert vibe_bot.config.IMAGE_GEN_ENDPOINT == "https://image.example.com/v1"
|
|
assert vibe_bot.config.IMAGE_EDIT_ENDPOINT == "https://image-edit.example.com/v1"
|
|
assert vibe_bot.config.EMBEDDING_ENDPOINT == "https://embedding.example.com/v1"
|
|
assert vibe_bot.config.CHAT_MODEL == "test-chat-model"
|
|
assert vibe_bot.config.COMPLETION_MODEL == "test-completion-model"
|
|
assert vibe_bot.config.IMAGE_GEN_MODEL == "test-image-model"
|
|
assert vibe_bot.config.IMAGE_EDIT_MODEL == "test-image-edit-model"
|
|
assert vibe_bot.config.EMBEDDING_MODEL == "test-embedding-model"
|
|
assert vibe_bot.config.MAX_COMPLETION_TOKENS == 1000
|
|
assert vibe_bot.config.MAX_HISTORY_MESSAGES == 1000
|
|
assert vibe_bot.config.SIMILARITY_THRESHOLD == 0.7
|
|
assert vibe_bot.config.TOP_K_RESULTS == 5
|
|
assert vibe_bot.config.TTS_MODEL_PATH == "/tmp/test-model.onnx"
|
|
assert vibe_bot.config.TTS_VOICES_PATH == "/tmp/test-voices.bin"
|
|
assert vibe_bot.config.TTS_VOICE == "af_sarah"
|
|
assert vibe_bot.config.TTS_SPEED == 1.0
|
|
print("OK")
|
|
"""
|
|
|
|
result = subprocess.run( # noqa: PLW1510, S603
|
|
[sys.executable, "-c", code],
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=30,
|
|
)
|
|
assert result.returncode == 0, f"Subprocess failed: {result.stderr}"
|
|
|
|
|
|
def _run_config_check(env_vars: dict[str, str], expected_error: str) -> None:
|
|
"""Run a subprocess that imports config and checks for expected RuntimeError."""
|
|
env_str = ""
|
|
for k, v in env_vars.items():
|
|
env_str += f'os.environ["{k}"] = "{v}"\n'
|
|
|
|
code = f"""
|
|
import sys
|
|
sys.path.insert(0, "/var/home/ducoterra/Projects/vibe_discord_bots")
|
|
import os
|
|
os.environ.clear()
|
|
os.environ["PATH"] = "/usr/bin:/bin"
|
|
{env_str}
|
|
try:
|
|
import vibe_bot.config
|
|
print("NO_ERROR")
|
|
except RuntimeError as e:
|
|
print(f"ERROR: {{e}}")
|
|
except Exception as e:
|
|
print(f"OTHER: {{type(e).__name__}}: {{e}}")
|
|
"""
|
|
|
|
result = subprocess.run( # noqa: PLW1510, S603
|
|
[sys.executable, "-c", code],
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=30,
|
|
)
|
|
output = result.stdout.strip()
|
|
assert (
|
|
output.startswith("ERROR:") and expected_error in output
|
|
), f"Expected error '{expected_error}' but got: {output}"
|
|
|
|
|
|
def test_config_missing_discord_token() -> None:
|
|
"""Test that RuntimeError is raised when DISCORD_TOKEN is missing."""
|
|
env: dict[str, str] = {
|
|
"DISCORD_TOKEN": "",
|
|
"CHAT_ENDPOINT": "https://chat.example.com/v1",
|
|
"COMPLETION_ENDPOINT": "https://completion.example.com/v1",
|
|
"IMAGE_GEN_ENDPOINT": "https://image.example.com/v1",
|
|
"IMAGE_EDIT_ENDPOINT": "https://image-edit.example.com/v1",
|
|
"EMBEDDING_ENDPOINT": "https://embedding.example.com/v1",
|
|
"CHAT_MODEL": "test-chat-model",
|
|
"COMPLETION_MODEL": "test-completion-model",
|
|
"IMAGE_GEN_MODEL": "test-image-model",
|
|
"IMAGE_EDIT_MODEL": "test-image-edit-model",
|
|
"EMBEDDING_MODEL": "test-embedding-model",
|
|
}
|
|
_run_config_check(env, "DISCORD_TOKEN required")
|
|
|
|
|
|
def test_config_missing_chat_endpoint() -> None:
|
|
"""Test that RuntimeError is raised when CHAT_ENDPOINT is missing."""
|
|
env: dict[str, str] = {
|
|
"DISCORD_TOKEN": "test-token",
|
|
"CHAT_ENDPOINT": "",
|
|
"COMPLETION_ENDPOINT": "https://completion.example.com/v1",
|
|
"IMAGE_GEN_ENDPOINT": "https://image.example.com/v1",
|
|
"IMAGE_EDIT_ENDPOINT": "https://image-edit.example.com/v1",
|
|
"EMBEDDING_ENDPOINT": "https://embedding.example.com/v1",
|
|
"CHAT_MODEL": "test-chat-model",
|
|
"COMPLETION_MODEL": "test-completion-model",
|
|
"IMAGE_GEN_MODEL": "test-image-model",
|
|
"IMAGE_EDIT_MODEL": "test-image-edit-model",
|
|
"EMBEDDING_MODEL": "test-embedding-model",
|
|
}
|
|
_run_config_check(env, "CHAT_ENDPOINT required")
|
|
|
|
|
|
def test_config_missing_completion_endpoint() -> None:
|
|
"""Test that RuntimeError is raised when COMPLETION_ENDPOINT is missing."""
|
|
env: dict[str, str] = {
|
|
"DISCORD_TOKEN": "test-token",
|
|
"CHAT_ENDPOINT": "https://chat.example.com/v1",
|
|
"COMPLETION_ENDPOINT": "",
|
|
"IMAGE_GEN_ENDPOINT": "https://image.example.com/v1",
|
|
"IMAGE_EDIT_ENDPOINT": "https://image-edit.example.com/v1",
|
|
"EMBEDDING_ENDPOINT": "https://embedding.example.com/v1",
|
|
"CHAT_MODEL": "test-chat-model",
|
|
"COMPLETION_MODEL": "test-completion-model",
|
|
"IMAGE_GEN_MODEL": "test-image-model",
|
|
"IMAGE_EDIT_MODEL": "test-image-edit-model",
|
|
"EMBEDDING_MODEL": "test-embedding-model",
|
|
}
|
|
_run_config_check(env, "COMPLETION_ENDPOINT required")
|
|
|
|
|
|
def test_config_missing_image_gen_endpoint() -> None:
|
|
"""Test that RuntimeError is raised when IMAGE_GEN_ENDPOINT is missing."""
|
|
env: dict[str, str] = {
|
|
"DISCORD_TOKEN": "test-token",
|
|
"CHAT_ENDPOINT": "https://chat.example.com/v1",
|
|
"COMPLETION_ENDPOINT": "https://completion.example.com/v1",
|
|
"IMAGE_GEN_ENDPOINT": "",
|
|
"IMAGE_EDIT_ENDPOINT": "https://image-edit.example.com/v1",
|
|
"EMBEDDING_ENDPOINT": "https://embedding.example.com/v1",
|
|
"CHAT_MODEL": "test-chat-model",
|
|
"COMPLETION_MODEL": "test-completion-model",
|
|
"IMAGE_GEN_MODEL": "test-image-model",
|
|
"IMAGE_EDIT_MODEL": "test-image-edit-model",
|
|
"EMBEDDING_MODEL": "test-embedding-model",
|
|
}
|
|
_run_config_check(env, "IMAGE_GEN_ENDPOINT required")
|
|
|
|
|
|
def test_config_missing_image_edit_endpoint() -> None:
|
|
"""Test that RuntimeError is raised when IMAGE_EDIT_ENDPOINT is missing."""
|
|
env: dict[str, str] = {
|
|
"DISCORD_TOKEN": "test-token",
|
|
"CHAT_ENDPOINT": "https://chat.example.com/v1",
|
|
"COMPLETION_ENDPOINT": "https://completion.example.com/v1",
|
|
"IMAGE_GEN_ENDPOINT": "https://image.example.com/v1",
|
|
"IMAGE_EDIT_ENDPOINT": "",
|
|
"EMBEDDING_ENDPOINT": "https://embedding.example.com/v1",
|
|
"CHAT_MODEL": "test-chat-model",
|
|
"COMPLETION_MODEL": "test-completion-model",
|
|
"IMAGE_GEN_MODEL": "test-image-model",
|
|
"IMAGE_EDIT_MODEL": "test-image-edit-model",
|
|
"EMBEDDING_MODEL": "test-embedding-model",
|
|
}
|
|
_run_config_check(env, "IMAGE_EDIT_ENDPOINT required")
|
|
|
|
|
|
def test_config_missing_embedding_endpoint() -> None:
|
|
"""Test that RuntimeError is raised when EMBEDDING_ENDPOINT is missing."""
|
|
env: dict[str, str] = {
|
|
"DISCORD_TOKEN": "test-token",
|
|
"CHAT_ENDPOINT": "https://chat.example.com/v1",
|
|
"COMPLETION_ENDPOINT": "https://completion.example.com/v1",
|
|
"IMAGE_GEN_ENDPOINT": "https://image.example.com/v1",
|
|
"IMAGE_EDIT_ENDPOINT": "https://image-edit.example.com/v1",
|
|
"EMBEDDING_ENDPOINT": "",
|
|
"CHAT_MODEL": "test-chat-model",
|
|
"COMPLETION_MODEL": "test-completion-model",
|
|
"IMAGE_GEN_MODEL": "test-image-model",
|
|
"IMAGE_EDIT_MODEL": "test-image-edit-model",
|
|
"EMBEDDING_MODEL": "test-embedding-model",
|
|
}
|
|
_run_config_check(env, "EMBEDDING_ENDPOINT required")
|
|
|
|
|
|
def test_config_missing_chat_model() -> None:
|
|
"""Test that RuntimeError is raised when CHAT_MODEL is missing."""
|
|
env: dict[str, str] = {
|
|
"DISCORD_TOKEN": "test-token",
|
|
"CHAT_ENDPOINT": "https://chat.example.com/v1",
|
|
"COMPLETION_ENDPOINT": "https://completion.example.com/v1",
|
|
"IMAGE_GEN_ENDPOINT": "https://image.example.com/v1",
|
|
"IMAGE_EDIT_ENDPOINT": "https://image-edit.example.com/v1",
|
|
"EMBEDDING_ENDPOINT": "https://embedding.example.com/v1",
|
|
"CHAT_MODEL": "",
|
|
"COMPLETION_MODEL": "test-completion-model",
|
|
"IMAGE_GEN_MODEL": "test-image-model",
|
|
"IMAGE_EDIT_MODEL": "test-image-edit-model",
|
|
"EMBEDDING_MODEL": "test-embedding-model",
|
|
}
|
|
_run_config_check(env, "CHAT_MODEL required")
|
|
|
|
|
|
def test_config_missing_completion_model() -> None:
|
|
"""Test that RuntimeError is raised when COMPLETION_MODEL is missing."""
|
|
env: dict[str, str] = {
|
|
"DISCORD_TOKEN": "test-token",
|
|
"CHAT_ENDPOINT": "https://chat.example.com/v1",
|
|
"COMPLETION_ENDPOINT": "https://completion.example.com/v1",
|
|
"IMAGE_GEN_ENDPOINT": "https://image.example.com/v1",
|
|
"IMAGE_EDIT_ENDPOINT": "https://image-edit.example.com/v1",
|
|
"EMBEDDING_ENDPOINT": "https://embedding.example.com/v1",
|
|
"CHAT_MODEL": "test-chat-model",
|
|
"COMPLETION_MODEL": "",
|
|
"IMAGE_GEN_MODEL": "test-image-model",
|
|
"IMAGE_EDIT_MODEL": "test-image-edit-model",
|
|
"EMBEDDING_MODEL": "test-embedding-model",
|
|
}
|
|
_run_config_check(env, "COMPLETION_MODEL required")
|
|
|
|
|
|
def test_config_missing_image_gen_model() -> None:
|
|
"""Test that RuntimeError is raised when IMAGE_GEN_MODEL is missing."""
|
|
env: dict[str, str] = {
|
|
"DISCORD_TOKEN": "test-token",
|
|
"CHAT_ENDPOINT": "https://chat.example.com/v1",
|
|
"COMPLETION_ENDPOINT": "https://completion.example.com/v1",
|
|
"IMAGE_GEN_ENDPOINT": "https://image.example.com/v1",
|
|
"IMAGE_EDIT_ENDPOINT": "https://image-edit.example.com/v1",
|
|
"EMBEDDING_ENDPOINT": "https://embedding.example.com/v1",
|
|
"CHAT_MODEL": "test-chat-model",
|
|
"COMPLETION_MODEL": "test-completion-model",
|
|
"IMAGE_GEN_MODEL": "",
|
|
"IMAGE_EDIT_MODEL": "test-image-edit-model",
|
|
"EMBEDDING_MODEL": "test-embedding-model",
|
|
}
|
|
_run_config_check(env, "IMAGE_GEN_MODEL required")
|
|
|
|
|
|
def test_config_missing_image_edit_model() -> None:
|
|
"""Test that RuntimeError is raised when IMAGE_EDIT_MODEL is missing."""
|
|
env: dict[str, str] = {
|
|
"DISCORD_TOKEN": "test-token",
|
|
"CHAT_ENDPOINT": "https://chat.example.com/v1",
|
|
"COMPLETION_ENDPOINT": "https://completion.example.com/v1",
|
|
"IMAGE_GEN_ENDPOINT": "https://image.example.com/v1",
|
|
"IMAGE_EDIT_ENDPOINT": "https://image-edit.example.com/v1",
|
|
"EMBEDDING_ENDPOINT": "https://embedding.example.com/v1",
|
|
"CHAT_MODEL": "test-chat-model",
|
|
"COMPLETION_MODEL": "test-completion-model",
|
|
"IMAGE_GEN_MODEL": "test-image-model",
|
|
"IMAGE_EDIT_MODEL": "",
|
|
"EMBEDDING_MODEL": "test-embedding-model",
|
|
}
|
|
_run_config_check(env, "IMAGE_EDIT_MODEL required")
|
|
|
|
|
|
def test_config_missing_embedding_model() -> None:
|
|
"""Test that RuntimeError is raised when EMBEDDING_MODEL is missing."""
|
|
env: dict[str, str] = {
|
|
"DISCORD_TOKEN": "test-token",
|
|
"CHAT_ENDPOINT": "https://chat.example.com/v1",
|
|
"COMPLETION_ENDPOINT": "https://completion.example.com/v1",
|
|
"IMAGE_GEN_ENDPOINT": "https://image.example.com/v1",
|
|
"IMAGE_EDIT_ENDPOINT": "https://image-edit.example.com/v1",
|
|
"EMBEDDING_ENDPOINT": "https://embedding.example.com/v1",
|
|
"CHAT_MODEL": "test-chat-model",
|
|
"COMPLETION_MODEL": "test-completion-model",
|
|
"IMAGE_GEN_MODEL": "test-image-model",
|
|
"IMAGE_EDIT_MODEL": "test-image-edit-model",
|
|
"EMBEDDING_MODEL": "",
|
|
}
|
|
_run_config_check(env, "EMBEDDING_MODEL required")
|
|
|
|
|
|
def test_config_logging_exists() -> None:
|
|
"""Test that logging is configured in config module."""
|
|
from vibe_bot.config import logger
|
|
|
|
assert logger is not None
|
|
assert logger.name == "vibe_bot.config"
|
|
|
|
|
|
def test_config_embedding_dimension() -> None:
|
|
"""Test that EMBEDDING_DIMENSION has expected default value."""
|
|
from vibe_bot.config import EMBEDDING_DIMENSION
|
|
|
|
assert EMBEDDING_DIMENSION == 2048
|