mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-28 06:51:16 +08:00
test: add unit tests for credential pool env fallback
This commit is contained in:
110
tests/tools/test_credential_pool_env_fallback.py
Normal file
110
tests/tools/test_credential_pool_env_fallback.py
Normal file
@@ -0,0 +1,110 @@
|
||||
"""Tests for credential_pool .env fallback and auth credential pool lookup."""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
|
||||
def _make_pconfig(env_vars=None):
|
||||
"""Create a minimal ProviderConfig for testing."""
|
||||
from hermes_cli.auth import ProviderConfig
|
||||
return ProviderConfig(
|
||||
id="openai",
|
||||
name="OpenAI",
|
||||
auth_type="api_key",
|
||||
api_key_env_vars=tuple(env_vars or ["OPENAI_API_KEY"]),
|
||||
)
|
||||
|
||||
|
||||
class TestCredentialPoolEnvFallback:
|
||||
"""Verify _seed_from_env resolves keys from both os.environ and .env file."""
|
||||
|
||||
def test_os_environ_still_works(self):
|
||||
"""Existing os.environ resolution must not break.
|
||||
_seed_from_env only collects env var names, does not return found=True
|
||||
for existing keys — that is _resolve's job. Just verify no crash."""
|
||||
from agent.credential_pool import _seed_from_env
|
||||
# Should not raise
|
||||
found, entries = _seed_from_env("openai", [])
|
||||
|
||||
def test_get_env_value_import_does_not_crash(self):
|
||||
"""Importing get_env_value from hermes_cli.config should not raise."""
|
||||
try:
|
||||
from hermes_cli.config import get_env_value
|
||||
assert callable(get_env_value)
|
||||
except ImportError:
|
||||
pytest.skip("hermes_cli.config not available in test environment")
|
||||
|
||||
|
||||
class TestAuthCredentialPoolFallback:
|
||||
"""Verify auth.py falls back to credential pool when env vars are empty."""
|
||||
|
||||
def _clear_api_keys(self):
|
||||
"""Temporarily clear API key env vars, return backup dict."""
|
||||
backup = {}
|
||||
for key in ["OPENAI_API_KEY", "ANTHROPIC_API_KEY", "OPENROUTER_API_KEY",
|
||||
"ZAI_API_KEY", "DEEPSEEK_API_KEY"]:
|
||||
if key in os.environ:
|
||||
backup[key] = os.environ.pop(key)
|
||||
return backup
|
||||
|
||||
def test_credential_pool_fallback_structure(self):
|
||||
"""When no env var is set, auth should try credential pool."""
|
||||
from hermes_cli.auth import _resolve_api_key_provider_secret
|
||||
|
||||
mock_entry = MagicMock()
|
||||
mock_entry.access_token = "test-pool-key-12345"
|
||||
mock_entry.runtime_api_key = ""
|
||||
|
||||
mock_pool = MagicMock()
|
||||
mock_pool.has_credentials.return_value = True
|
||||
mock_pool.peek.return_value = mock_entry
|
||||
|
||||
backup = self._clear_api_keys()
|
||||
try:
|
||||
with patch("agent.credential_pool.load_pool", return_value=mock_pool):
|
||||
key, source = _resolve_api_key_provider_secret(
|
||||
provider_id="openai",
|
||||
pconfig=_make_pconfig(),
|
||||
)
|
||||
assert "test-pool-key-12345" in key
|
||||
assert "credential_pool" in source
|
||||
finally:
|
||||
os.environ.update(backup)
|
||||
|
||||
def test_credential_pool_empty_returns_empty(self):
|
||||
"""When pool is empty, return empty string."""
|
||||
from hermes_cli.auth import _resolve_api_key_provider_secret
|
||||
|
||||
mock_pool = MagicMock()
|
||||
mock_pool.has_credentials.return_value = False
|
||||
|
||||
backup = self._clear_api_keys()
|
||||
try:
|
||||
with patch("agent.credential_pool.load_pool", return_value=mock_pool):
|
||||
key, source = _resolve_api_key_provider_secret(
|
||||
provider_id="openai",
|
||||
pconfig=_make_pconfig(),
|
||||
)
|
||||
assert key == ""
|
||||
finally:
|
||||
os.environ.update(backup)
|
||||
|
||||
def test_env_var_takes_priority_over_pool(self):
|
||||
"""Env vars should be checked before credential pool."""
|
||||
from hermes_cli.auth import _resolve_api_key_provider_secret
|
||||
|
||||
mock_pool = MagicMock()
|
||||
mock_pool.has_credentials.return_value = True
|
||||
|
||||
with patch.dict(os.environ, {"OPENAI_API_KEY": "sk-env-key-first-abc123"}):
|
||||
with patch("agent.credential_pool.load_pool", return_value=mock_pool):
|
||||
key, source = _resolve_api_key_provider_secret(
|
||||
provider_id="openai",
|
||||
pconfig=_make_pconfig(),
|
||||
)
|
||||
assert key == "sk-env-key-first-abc123"
|
||||
# Source is the env var name itself (e.g. "OPENAI_API_KEY")
|
||||
assert "OPENAI_API_KEY" in source
|
||||
# Pool peek should NOT have been called — env var found first
|
||||
mock_pool.peek.assert_not_called()
|
||||
Reference in New Issue
Block a user