| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- import os
- import json
- import time
- import tempfile
- import threading
- import unittest
- from http.server import HTTPServer, BaseHTTPRequestHandler
- from utils.cloud_config import (
- compute_config_hash,
- fetch_remote_config,
- save_local_cache,
- load_local_config,
- load_remote_or_cache,
- )
- class MockConfigHTTPHandler(BaseHTTPRequestHandler):
- config_payload = [{"identifier": "test_group", "enable": True}]
- status_code = 200
- def do_GET(self):
- self.send_response(self.status_code)
- self.send_header("Content-Type", "application/json")
- self.end_headers()
- response_data = json.dumps(self.config_payload).encode("utf-8")
- self.wfile.write(response_data)
- def log_message(self, format, *args):
- pass # 禁用标准输出日志,保持测试输出简洁
- class TestCloudConfig(unittest.TestCase):
- @classmethod
- def setUpClass(cls):
- # 启动本地 Mock HTTP 服务器
- cls.server = HTTPServer(("127.0.0.1", 0), MockConfigHTTPHandler)
- cls.port = cls.server.server_address[1]
- cls.server_thread = threading.Thread(target=cls.server.serve_forever)
- cls.server_thread.daemon = True
- cls.server_thread.start()
- cls.url = f"http://127.0.0.1:{cls.port}/config.json"
- @classmethod
- def tearDownClass(cls):
- cls.server.shutdown()
- cls.server.server_close()
- def test_compute_config_hash(self):
- data1 = {"b": 2, "a": 1}
- data2 = {"a": 1, "b": 2}
- data3 = {"a": 1, "b": 3}
- self.assertEqual(compute_config_hash(data1), compute_config_hash(data2))
- self.assertNotEqual(compute_config_hash(data1), compute_config_hash(data3))
- def test_fetch_remote_config_success(self):
- MockConfigHTTPHandler.config_payload = [{"identifier": "group_a", "enable": True}]
- MockConfigHTTPHandler.status_code = 200
- data = fetch_remote_config(self.url)
- self.assertEqual(data, [{"identifier": "group_a", "enable": True}])
- def test_fetch_remote_config_http_error(self):
- MockConfigHTTPHandler.status_code = 500
- with self.assertRaises(RuntimeError):
- fetch_remote_config(self.url)
- def test_load_remote_or_cache_success_and_save(self):
- MockConfigHTTPHandler.config_payload = [{"identifier": "group_remote", "enable": True}]
- MockConfigHTTPHandler.status_code = 200
- with tempfile.TemporaryDirectory() as tmp_dir:
- cache_path = os.path.join(tmp_dir, "cache.json")
- data, hash_val, loaded_remote = load_remote_or_cache(
- remote_url=self.url,
- local_cache_path=cache_path
- )
- self.assertTrue(loaded_remote)
- self.assertEqual(data, [{"identifier": "group_remote", "enable": True}])
- self.assertTrue(os.path.exists(cache_path))
- # 验证本地缓存是否被写入
- cached_data = load_local_config(cache_path)
- self.assertEqual(cached_data, [{"identifier": "group_remote", "enable": True}])
- def test_load_remote_or_cache_fallback_to_local(self):
- MockConfigHTTPHandler.status_code = 500 # 模拟云端 API 失败
- with tempfile.TemporaryDirectory() as tmp_dir:
- cache_path = os.path.join(tmp_dir, "cache.json")
- # 预先存入本地缓存
- save_local_cache(cache_path, [{"identifier": "group_cached", "enable": True}])
- data, hash_val, loaded_remote = load_remote_or_cache(
- remote_url=self.url,
- local_cache_path=cache_path
- )
- self.assertFalse(loaded_remote)
- self.assertEqual(data, [{"identifier": "group_cached", "enable": True}])
- if __name__ == "__main__":
- unittest.main()
|