test_router_scripts.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import pathlib
  2. import unittest
  3. PROJECT_ROOT = pathlib.Path(__file__).resolve().parent.parent
  4. class TestRouterScriptsBugsAndContracts(unittest.TestCase):
  5. """测试并锁定路由器 BusyBox 脚本中的文件原子性与选优漏洞,并纠正旧报告虚假报警"""
  6. def test_p1_router_local_update_atomic_file_write(self):
  7. """[P1/P2 修复验证] 验证 router_local_update.sh 采用 .tmp.$$ + mv -f 原子替换写入文件"""
  8. script_path = PROJECT_ROOT / "scripts" / "router" / "router_local_update.sh"
  9. content = script_path.read_text()
  10. self.assertIn("atomic_write_file()", content)
  11. self.assertIn(".tmp.$$", content)
  12. self.assertIn('atomic_write_file "$CURRENT_JSON_PATH"', content)
  13. def test_p2_router_local_update_filters_zero_speed(self):
  14. """[P2 修复验证] 验证 router_local_update.sh 在开启测速时优先挑选 download_speed > 0 的候选行"""
  15. script_path = PROJECT_ROOT / "scripts" / "router" / "router_local_update.sh"
  16. content = script_path.read_text()
  17. self.assertIn("speed = trim($6) + 0", content)
  18. self.assertIn("speed > 0", content)
  19. def test_recheck_correction_router_cfst_params_already_supported(self):
  20. """[复核纠偏] 验证初审报告关于 'router_local_update.sh 缺少 -dt/-dn/-dd 参数' 系虚假误报"""
  21. script_path = PROJECT_ROOT / "scripts" / "router" / "router_local_update.sh"
  22. content = script_path.read_text()
  23. # 验证源码中实际已存在这些参数映射
  24. self.assertIn('CFST_DOWNLOAD_COUNT', content)
  25. self.assertIn('-dn "$CFST_DOWNLOAD_COUNT"', content)
  26. self.assertIn('CFST_DOWNLOAD_TIME', content)
  27. self.assertIn('-dt "$CFST_DOWNLOAD_TIME"', content)
  28. self.assertIn('CFST_DISABLE_DOWNLOAD', content)
  29. self.assertIn('-dd', content)
  30. def test_build_router_package_ssot_sync(self):
  31. """[方案B SSOT驱动验证] 验证 build_router_package.sh --sync-from-config 自动将 JSON 测速与输出参数投影至路由器配置"""
  32. import json
  33. import os
  34. import subprocess
  35. import tarfile
  36. import tempfile
  37. with tempfile.TemporaryDirectory() as tmpdir:
  38. tmppath = pathlib.Path(tmpdir)
  39. base_conf = tmppath / "base_router.conf"
  40. base_conf.write_text("""CFST_DISPLAY_COUNT="10"
  41. CFST_PORT="443"
  42. CFST_DISABLE_DOWNLOAD="0"
  43. TOP_N="3"
  44. VALUE_TEXT_FILE="current_ip.txt"
  45. """)
  46. json_conf = tmppath / "config.local.json"
  47. json_conf.write_text(json.dumps({
  48. "selection": {"top_n": 5},
  49. "output": {"selected_value_file": "ssot_custom_ip.txt"},
  50. "cfst_local": {
  51. "run_args": ["-p", "25", "-f", "my_ips.txt", "-tp", "8443", "-dd"]
  52. }
  53. }))
  54. out_tar = tmppath / "test_pkg.tar.gz"
  55. script_path = PROJECT_ROOT / "build_router_package.sh"
  56. env = os.environ.copy()
  57. env["ROUTER_CONF"] = str(base_conf)
  58. env["OUT_TAR"] = str(out_tar)
  59. env["TMP_DIR"] = str(tmppath / "build_tmp")
  60. proc = subprocess.run(
  61. [
  62. "sh",
  63. str(script_path),
  64. "--sync-from-config",
  65. str(json_conf),
  66. ],
  67. env=env,
  68. capture_output=True,
  69. text=True,
  70. cwd=str(PROJECT_ROOT),
  71. )
  72. self.assertEqual(proc.returncode, 0, f"打包失败: {proc.stderr}\nSTDOUT: {proc.stdout}")
  73. self.assertTrue(out_tar.exists(), "生成的 tar.gz 必须存在")
  74. # 解压并校验打包中的 config_router.conf
  75. with tarfile.open(out_tar, "r:gz") as tar:
  76. conf_member = tar.extractfile("vmess/config_router.conf")
  77. self.assertIsNotNone(conf_member)
  78. conf_content = conf_member.read().decode("utf-8")
  79. # 验证 SSOT 同步生效
  80. self.assertIn('TOP_N="5"', conf_content)
  81. self.assertIn('VALUE_TEXT_FILE="ssot_custom_ip.txt"', conf_content)
  82. self.assertIn('CFST_DISPLAY_COUNT="25"', conf_content)
  83. self.assertIn('CFST_IP_FILE="my_ips.txt"', conf_content)
  84. self.assertIn('CFST_PORT="8443"', conf_content)
  85. self.assertIn('CFST_DISABLE_DOWNLOAD="1"', conf_content)
  86. if __name__ == "__main__":
  87. unittest.main()