"""hub_system_logs_lib 单元测试.""" from __future__ import annotations import tempfile import unittest from pathlib import Path from unittest.mock import patch from lib.hub import hub_system_logs_lib as logs_lib from lib.hub.hub_system_logs_lib import ( load_system_logs, resolve_log_paths, system_logs_meta, tail_lines, ) class HubSystemLogsLibTest(unittest.TestCase): def setUp(self): logs_lib._path_cache.clear() logs_lib._path_cache_at = 0.0 def test_system_logs_meta(self): meta = system_logs_meta() self.assertTrue(meta["ok"]) keys = [t["key"] for t in meta["targets"]] self.assertEqual(keys, ["binance", "gate", "okx", "hub"]) def test_tail_lines_reads_last_lines(self): with tempfile.TemporaryDirectory() as tmp: path = Path(tmp) / "demo-out.log" path.write_text("\n".join(f"line-{i}" for i in range(1, 11)), encoding="utf-8") out = tail_lines(path, lines=3) self.assertEqual(out.splitlines(), ["line-8", "line-9", "line-10"]) def test_resolve_log_paths_from_pm2_jlist(self): with tempfile.TemporaryDirectory() as tmp: logs_dir = Path(tmp) out_file = logs_dir / "crypto-binance-out-0.log" err_file = logs_dir / "crypto-binance-error-0.log" out_file.write_text("stdout line", encoding="utf-8") err_file.write_text("stderr line", encoding="utf-8") payload = [ { "name": "crypto_binance", "pm2_env": { "pm_out_log_path": str(out_file), "pm_err_log_path": str(err_file), }, } ] with patch.object(logs_lib, "_pm2_jlist", return_value=payload): out_path, err_path = resolve_log_paths("crypto_binance") self.assertEqual(out_path, out_file) self.assertEqual(err_path, err_file) def test_resolve_log_paths_glob_fallback(self): with tempfile.TemporaryDirectory() as tmp: logs_dir = Path(tmp) out_file = logs_dir / "crypto-gate-out-1.log" err_file = logs_dir / "crypto-gate-error-1.log" out_file.write_text("gate out", encoding="utf-8") err_file.write_text("gate err", encoding="utf-8") with patch.object(logs_lib, "pm2_logs_dir", return_value=logs_dir): with patch.object(logs_lib, "_pm2_jlist", return_value=[]): out_path, err_path = resolve_log_paths("crypto_gate") self.assertEqual(out_path, out_file) self.assertEqual(err_path, err_file) def test_load_system_logs_unknown(self): with self.assertRaises(KeyError): load_system_logs("unknown") def test_load_system_logs_with_resolved_paths(self): with tempfile.TemporaryDirectory() as tmp: logs_dir = Path(tmp) out_file = logs_dir / "manual-trading-hub-out-6.log" err_file = logs_dir / "manual-trading-hub-error-6.log" out_file.write_text("hub stdout", encoding="utf-8") err_file.write_text("hub stderr", encoding="utf-8") payload = [ { "name": "manual-trading-hub", "pm2_env": { "pm_out_log_path": str(out_file), "pm_err_log_path": str(err_file), }, } ] with patch.object(logs_lib, "_pm2_jlist", return_value=payload): data = load_system_logs("hub", lines=50) self.assertTrue(data["ok"]) self.assertIn("hub stdout", data["out"]) self.assertIn("hub stderr", data["err"]) self.assertTrue(data["out_exists"]) self.assertTrue(data["err_exists"])