199 lines
7.2 KiB
Python
199 lines
7.2 KiB
Python
"""
|
|
Tests for runpod.config module.
|
|
|
|
Tests configuration validation, environment variable loading, and error handling.
|
|
"""
|
|
|
|
import pytest
|
|
from pathlib import Path
|
|
|
|
from runpod.config import RunPodConfig
|
|
|
|
|
|
class TestRunPodConfig:
|
|
"""Tests for RunPodConfig class."""
|
|
|
|
def test_config_creation_with_valid_values(self):
|
|
"""Test creating config with valid values."""
|
|
config = RunPodConfig(
|
|
api_key="test_key_" + "x" * 32,
|
|
volume_id="test_volume_123"
|
|
)
|
|
|
|
assert config.api_key == "test_key_" + "x" * 32
|
|
assert config.volume_id == "test_volume_123"
|
|
assert config.datacenters == ["EUR-IS-1"]
|
|
assert config.default_image == "jgrusewski/foxhunt:latest"
|
|
assert config.default_container_disk_gb == 50
|
|
|
|
def test_config_creation_with_optional_values(self):
|
|
"""Test creating config with optional values."""
|
|
config = RunPodConfig(
|
|
api_key="test_key",
|
|
volume_id="test_volume",
|
|
container_registry_auth_id="auth_123",
|
|
default_image="custom/image:tag",
|
|
default_container_disk_gb=100,
|
|
datacenters=["EUR-IS-1", "EUR-IS-2"]
|
|
)
|
|
|
|
assert config.container_registry_auth_id == "auth_123"
|
|
assert config.default_image == "custom/image:tag"
|
|
assert config.default_container_disk_gb == 100
|
|
assert config.datacenters == ["EUR-IS-1", "EUR-IS-2"]
|
|
|
|
def test_config_validation_missing_api_key(self):
|
|
"""Test validation fails with missing API key."""
|
|
with pytest.raises(ValueError, match="RUNPOD_API_KEY is required"):
|
|
RunPodConfig(api_key="", volume_id="test_volume")
|
|
|
|
def test_config_validation_missing_volume_id(self):
|
|
"""Test validation fails with missing volume ID."""
|
|
with pytest.raises(ValueError, match="RUNPOD_VOLUME_ID is required"):
|
|
RunPodConfig(api_key="test_key", volume_id="")
|
|
|
|
def test_validate_method_returns_errors(self):
|
|
"""Test validate() method returns list of errors."""
|
|
config = RunPodConfig(
|
|
api_key="short", # Too short
|
|
volume_id="invalid-id!", # Invalid characters
|
|
default_container_disk_gb=5, # Too small
|
|
datacenters=[] # Empty
|
|
)
|
|
|
|
errors = config.validate()
|
|
|
|
assert len(errors) == 4
|
|
assert any("too short" in err.lower() for err in errors)
|
|
assert any("invalid" in err.lower() for err in errors)
|
|
assert any("10GB" in err for err in errors)
|
|
assert any("datacenter" in err.lower() for err in errors)
|
|
|
|
def test_validate_method_empty_for_valid_config(self, sample_config):
|
|
"""Test validate() returns empty list for valid config."""
|
|
errors = sample_config.validate()
|
|
assert errors == []
|
|
|
|
@pytest.mark.parametrize("api_key,expected_valid", [
|
|
("test_key_" + "x" * 32, True), # Valid length
|
|
("short", False), # Too short
|
|
])
|
|
def test_api_key_validation(self, api_key, expected_valid):
|
|
"""Test API key validation with different inputs."""
|
|
config = RunPodConfig(
|
|
api_key=api_key,
|
|
volume_id="valid_volume_id"
|
|
)
|
|
|
|
errors = config.validate()
|
|
|
|
if expected_valid:
|
|
assert not any("api_key" in err.lower() for err in errors)
|
|
else:
|
|
assert any("api_key" in err.lower() for err in errors)
|
|
|
|
@pytest.mark.parametrize("volume_id,expected_valid", [
|
|
("se3zdnb5o4", True), # Valid alphanumeric
|
|
("volume123", True), # Valid alphanumeric
|
|
("invalid-volume!", False), # Invalid characters
|
|
])
|
|
def test_volume_id_validation(self, volume_id, expected_valid):
|
|
"""Test volume ID validation with different inputs."""
|
|
config = RunPodConfig(
|
|
api_key="test_key_" + "x" * 32,
|
|
volume_id=volume_id
|
|
)
|
|
|
|
errors = config.validate()
|
|
|
|
if expected_valid:
|
|
assert not any("volume_id" in err.lower() for err in errors)
|
|
else:
|
|
assert any("volume_id" in err.lower() for err in errors)
|
|
|
|
def test_from_env_with_mock_env(self, mock_env, monkeypatch):
|
|
"""Test loading config from environment variables."""
|
|
# Mock the Path resolution to avoid needing actual .env.runpod
|
|
monkeypatch.setattr(
|
|
"runpod.config.Path.exists",
|
|
lambda self: False # Pretend .env.runpod doesn't exist
|
|
)
|
|
|
|
config = RunPodConfig.from_env()
|
|
|
|
assert config.api_key == mock_env["RUNPOD_API_KEY"]
|
|
assert config.volume_id == mock_env["RUNPOD_VOLUME_ID"]
|
|
assert config.container_registry_auth_id == mock_env["RUNPOD_CONTAINER_REGISTRY_AUTH_ID"]
|
|
|
|
def test_from_env_with_file(self, create_env_file):
|
|
"""Test loading config from .env.runpod file."""
|
|
config = RunPodConfig.from_env(str(create_env_file))
|
|
|
|
# Test that config was loaded (values may differ based on actual .env.runpod)
|
|
assert config.api_key # Should not be empty
|
|
assert config.volume_id
|
|
assert len(config.api_key) >= 32 # Should be valid length
|
|
|
|
def test_from_env_missing_file(self, temp_directory):
|
|
"""Test from_env raises error for missing file."""
|
|
missing_file = temp_directory / "nonexistent.env"
|
|
|
|
with pytest.raises(FileNotFoundError, match="Environment file not found"):
|
|
RunPodConfig.from_env(str(missing_file))
|
|
|
|
def test_from_env_missing_credentials(self, monkeypatch):
|
|
"""Test from_env with missing environment variables."""
|
|
# Clear environment variables
|
|
monkeypatch.delenv("RUNPOD_API_KEY", raising=False)
|
|
monkeypatch.delenv("RUNPOD_VOLUME_ID", raising=False)
|
|
|
|
# Mock Path.exists to avoid loading actual .env.runpod
|
|
monkeypatch.setattr(
|
|
"runpod.config.Path.exists",
|
|
lambda self: False
|
|
)
|
|
|
|
with pytest.raises(ValueError, match="RUNPOD_API_KEY is required"):
|
|
RunPodConfig.from_env()
|
|
|
|
def test_default_datacenters(self):
|
|
"""Test default datacenters are set correctly."""
|
|
config = RunPodConfig(
|
|
api_key="test_key",
|
|
volume_id="test_volume"
|
|
)
|
|
|
|
assert config.datacenters == ["EUR-IS-1"]
|
|
|
|
def test_custom_datacenters(self):
|
|
"""Test custom datacenters override default."""
|
|
config = RunPodConfig(
|
|
api_key="test_key",
|
|
volume_id="test_volume",
|
|
datacenters=["US-WEST-1", "US-EAST-1"]
|
|
)
|
|
|
|
assert config.datacenters == ["US-WEST-1", "US-EAST-1"]
|
|
|
|
@pytest.mark.parametrize("disk_size,expected_valid", [
|
|
(50, True), # Valid
|
|
(100, True), # Valid
|
|
(10, True), # Minimum valid
|
|
(5, False), # Too small
|
|
(0, False), # Zero
|
|
])
|
|
def test_container_disk_validation(self, disk_size, expected_valid):
|
|
"""Test container disk size validation."""
|
|
config = RunPodConfig(
|
|
api_key="test_key_" + "x" * 32,
|
|
volume_id="valid_volume",
|
|
default_container_disk_gb=disk_size
|
|
)
|
|
|
|
errors = config.validate()
|
|
|
|
if expected_valid:
|
|
assert not any("disk" in err.lower() for err in errors)
|
|
else:
|
|
assert any("disk" in err.lower() for err in errors)
|