124 lines
4.2 KiB
Python
124 lines
4.2 KiB
Python
"""config 模块行为测试 (真实 JSON 文件读写, 非 mock)
|
|
|
|
运行: cd /home/lou/文档/7z-encrypt && .venv/bin/python -m unittest discover -s tests -v
|
|
"""
|
|
import json
|
|
import os
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
|
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
|
|
from config import AppConfig, ConfigError
|
|
|
|
VALID = {
|
|
"server": {"url": "http://127.0.0.1:8000", "timeout": 30, "max_retries": 3},
|
|
"crypto": {"key_id": "default_key", "keyring_path": "config/keyring.json"},
|
|
"splitter": {"chunk_size_mb": 10},
|
|
"state": {"db_path": "config/tasks.db", "cleanup_days": 7},
|
|
}
|
|
|
|
|
|
def write_cfg(td: str, data: dict) -> str:
|
|
path = os.path.join(td, "config.json")
|
|
with open(path, "w", encoding="utf-8") as f:
|
|
json.dump(data, f)
|
|
return path
|
|
|
|
|
|
class TestLoad(unittest.TestCase):
|
|
def setUp(self):
|
|
self._td = tempfile.TemporaryDirectory(prefix='hermes-test-')
|
|
self.addCleanup(self._td.cleanup)
|
|
|
|
def test_valid_config(self):
|
|
cfg = AppConfig(write_cfg(self._td.name, VALID))
|
|
self.assertEqual(cfg.server_url, "http://127.0.0.1:8000")
|
|
self.assertEqual(cfg.key_id, "default_key")
|
|
self.assertEqual(cfg.chunk_size, 10 * 1024 * 1024)
|
|
self.assertEqual(cfg.cleanup_days, 7)
|
|
|
|
def test_defaults_filled(self):
|
|
cfg = AppConfig(write_cfg(self._td.name, {"server": {"url": "http://x:1"}}))
|
|
self.assertEqual(cfg.timeout, 30) # 默认值兜底
|
|
self.assertEqual(cfg.max_retries, 3)
|
|
self.assertEqual(cfg.retry_delay, 1.0)
|
|
self.assertEqual(cfg.data["splitter"]["chunk_size_mb"], 10)
|
|
self.assertEqual(cfg.key_id, "default_key")
|
|
|
|
def test_user_overrides_default(self):
|
|
data = dict(VALID)
|
|
data["server"] = {"url": "http://x:1", "timeout": 5}
|
|
cfg = AppConfig(write_cfg(self._td.name, data))
|
|
self.assertEqual(cfg.timeout, 5) # 用户覆盖
|
|
self.assertEqual(cfg.max_retries, 3) # 未覆盖的保持默认
|
|
|
|
def test_missing_file(self):
|
|
with self.assertRaises(ConfigError):
|
|
AppConfig(os.path.join(self._td.name, "nope.json"))
|
|
|
|
def test_invalid_json(self):
|
|
path = os.path.join(self._td.name, "config.json")
|
|
with open(path, "w", encoding="utf-8") as f:
|
|
f.write("{not json")
|
|
with self.assertRaises(json.JSONDecodeError):
|
|
AppConfig(path)
|
|
|
|
|
|
class TestValidate(unittest.TestCase):
|
|
def setUp(self):
|
|
self._td = tempfile.TemporaryDirectory(prefix='hermes-test-')
|
|
self.addCleanup(self._td.cleanup)
|
|
|
|
def _cfg(self, **mut):
|
|
data = json.loads(json.dumps(VALID))
|
|
for k, v in mut.items():
|
|
data[k] = v
|
|
return AppConfig(write_cfg(self._td.name, data))
|
|
|
|
def test_missing_server_url(self):
|
|
with self.assertRaises(ConfigError):
|
|
self._cfg(server={})
|
|
|
|
def test_bad_url_scheme(self):
|
|
with self.assertRaises(ConfigError):
|
|
self._cfg(server={"url": "ftp://x"})
|
|
|
|
def test_bad_chunk_size(self):
|
|
with self.assertRaises(ConfigError):
|
|
self._cfg(splitter={"chunk_size_mb": 0})
|
|
|
|
def test_bad_max_retries(self):
|
|
with self.assertRaises(ConfigError):
|
|
self._cfg(server={"url": "http://x:1", "max_retries": 0})
|
|
|
|
def test_bad_timeout(self):
|
|
with self.assertRaises(ConfigError):
|
|
self._cfg(server={"url": "http://x:1", "timeout": -1})
|
|
|
|
|
|
class TestFactory(unittest.TestCase):
|
|
"""分发: 构造各模块实例 (真实构造, 非 mock)"""
|
|
|
|
def setUp(self):
|
|
self._td = tempfile.TemporaryDirectory(prefix='hermes-test-')
|
|
self.addCleanup(self._td.cleanup)
|
|
|
|
def test_build_instances(self):
|
|
cfg = AppConfig(write_cfg(self._td.name, VALID))
|
|
from crypto import CryptoEngine
|
|
from transfer import TransferClient
|
|
from state import TaskStore
|
|
|
|
self.assertIsInstance(cfg.build_crypto(), CryptoEngine)
|
|
t = cfg.build_transfer()
|
|
self.assertIsInstance(t, TransferClient)
|
|
self.assertEqual(t.base_url, VALID["server"]["url"])
|
|
self.assertEqual(t.max_retries, 3)
|
|
self.assertIsInstance(cfg.build_store(), TaskStore)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|