Files
hermes-agent/tests/tools/test_credential_files.py

159 lines
5.3 KiB
Python
Raw Normal View History

"""Tests for credential file passthrough registry (tools/credential_files.py)."""
import os
from pathlib import Path
import pytest
from tools.credential_files import (
clear_credential_files,
get_credential_file_mounts,
register_credential_file,
register_credential_files,
reset_config_cache,
)
@pytest.fixture(autouse=True)
def _clean_registry():
"""Reset registry between tests."""
clear_credential_files()
reset_config_cache()
yield
clear_credential_files()
reset_config_cache()
class TestRegisterCredentialFile:
def test_registers_existing_file(self, tmp_path, monkeypatch):
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
(tmp_path / "token.json").write_text('{"token": "abc"}')
result = register_credential_file("token.json")
assert result is True
mounts = get_credential_file_mounts()
assert len(mounts) == 1
assert mounts[0]["host_path"] == str(tmp_path / "token.json")
assert mounts[0]["container_path"] == "/root/.hermes/token.json"
def test_skips_missing_file(self, tmp_path, monkeypatch):
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
result = register_credential_file("nonexistent.json")
assert result is False
assert get_credential_file_mounts() == []
def test_custom_container_base(self, tmp_path, monkeypatch):
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
(tmp_path / "cred.json").write_text("{}")
register_credential_file("cred.json", container_base="/home/user/.hermes")
mounts = get_credential_file_mounts()
assert mounts[0]["container_path"] == "/home/user/.hermes/cred.json"
def test_deduplicates_by_container_path(self, tmp_path, monkeypatch):
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
(tmp_path / "token.json").write_text("{}")
register_credential_file("token.json")
register_credential_file("token.json")
mounts = get_credential_file_mounts()
assert len(mounts) == 1
class TestRegisterCredentialFiles:
def test_string_entries(self, tmp_path, monkeypatch):
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
(tmp_path / "a.json").write_text("{}")
(tmp_path / "b.json").write_text("{}")
missing = register_credential_files(["a.json", "b.json"])
assert missing == []
assert len(get_credential_file_mounts()) == 2
def test_dict_entries(self, tmp_path, monkeypatch):
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
(tmp_path / "token.json").write_text("{}")
missing = register_credential_files([
{"path": "token.json", "description": "OAuth token"},
])
assert missing == []
assert len(get_credential_file_mounts()) == 1
def test_returns_missing_files(self, tmp_path, monkeypatch):
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
(tmp_path / "exists.json").write_text("{}")
missing = register_credential_files([
"exists.json",
"missing.json",
{"path": "also_missing.json"},
])
assert missing == ["missing.json", "also_missing.json"]
assert len(get_credential_file_mounts()) == 1
def test_empty_list(self, tmp_path, monkeypatch):
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
assert register_credential_files([]) == []
class TestConfigCredentialFiles:
def test_loads_from_config(self, tmp_path, monkeypatch):
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
(tmp_path / "oauth.json").write_text("{}")
(tmp_path / "config.yaml").write_text(
"terminal:\n credential_files:\n - oauth.json\n"
)
mounts = get_credential_file_mounts()
assert len(mounts) == 1
assert mounts[0]["host_path"] == str(tmp_path / "oauth.json")
def test_config_skips_missing_files(self, tmp_path, monkeypatch):
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
(tmp_path / "config.yaml").write_text(
"terminal:\n credential_files:\n - nonexistent.json\n"
)
mounts = get_credential_file_mounts()
assert mounts == []
def test_combines_skill_and_config(self, tmp_path, monkeypatch):
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
(tmp_path / "skill_token.json").write_text("{}")
(tmp_path / "config_token.json").write_text("{}")
(tmp_path / "config.yaml").write_text(
"terminal:\n credential_files:\n - config_token.json\n"
)
register_credential_file("skill_token.json")
mounts = get_credential_file_mounts()
assert len(mounts) == 2
paths = {m["container_path"] for m in mounts}
assert "/root/.hermes/skill_token.json" in paths
assert "/root/.hermes/config_token.json" in paths
class TestGetMountsRechecksExistence:
def test_removed_file_excluded_from_mounts(self, tmp_path, monkeypatch):
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
token = tmp_path / "token.json"
token.write_text("{}")
register_credential_file("token.json")
assert len(get_credential_file_mounts()) == 1
# Delete the file after registration
token.unlink()
assert get_credential_file_mounts() == []