Files
proxy-station/scripts/ffsb/test_overlay.py
YANG JIANKUAN a5d980a5e9 feat: 添加 WireGuard 设备管理并完善客户端分流
实现独立加密设备身份、网关 agent、持久生命周期任务和 Surge/FlClash 专属订阅凭证。

完善 Shadowrocket 规则转换与 Clash AI DNS,增加 Surge FFSB 适配、规则快照、运维工具及验收文档。
2026-11-02 22:44:23 +08:00

54 lines
2.8 KiB
Python

import unittest
from overlay import build, sections
DOMAINS = ['*.anthropic.com','*.clau.de','*.claude.com','*.claudemcpclient.com','*.claudemcpcontent.com','*.claudeusercontent.com','*.ffsb.sg','a.claude.ai','anthropic.com','api.anthropic.com','api.ipify.org','assets.claude.ai','clau.de','claude.ai','claude.com','claudemcpclient.com','claudemcpcontent.com','claudeusercontent.com','ffsb.sg','icanhazip.com','ifconfig.me','ip.net.coffee','join.fufeishangban.com','pivot.claude.ai','www.claude.ai']
BASE = '''[General]
always-real-ip = *.example.ts.net
[Proxy]
Node = http, 127.0.0.1, 9999
[Proxy Group]
Claude = select, Node
AI = select, Node
[Rule]
DOMAIN-SUFFIX,claude.ai,Claude
DOMAIN,anthropic.auth0.com,Claude
DOMAIN-SUFFIX,openai.com,AI
FINAL,DIRECT
[Host]
*.claude.ai = server:https://1.0.0.1/dns-query
'''
class OverlayTests(unittest.TestCase):
def test_on_preserves_exact_ffsb_scope_and_extra_fallback(self):
s = sections(build(BASE, DOMAINS, True))
self.assertEqual(sum(x.endswith(',Claude') for x in s['Rule']), 25)
self.assertIn('DOMAIN,claude.ai,Claude', s['Rule'])
self.assertNotIn('DOMAIN-SUFFIX,claude.ai,Claude', s['Rule'])
self.assertIn('DOMAIN-SUFFIX,claude.ai,"🦀 Claude"', s['Rule'])
self.assertIn('DOMAIN,anthropic.auth0.com,"🦀 Claude"', s['Rule'])
self.assertIn('DOMAIN-SUFFIX,openai.com,AI', s['Rule'])
self.assertTrue(s['Rule'][0].startswith('PROCESS-NAME,'))
self.assertEqual([x for x in s['Rule'] if x.startswith('FINAL,')], ['FINAL,DIRECT'])
self.assertIn('*.example.ts.net', '\n'.join(s['General']))
self.assertEqual(sum('server:100.70.255.254' in x for x in s['Host']), 25)
def test_off_removes_tunnel_dns_and_selection(self):
s = sections(build(BASE, DOMAINS, False))
self.assertNotIn('100.70.255.254', '\n'.join(s['Host']))
self.assertIn('Claude = fallback, "🦀 Claude", interval=5', s['Proxy Group'])
self.assertEqual(s['General'][0], 'always-real-ip = *.example.ts.net')
self.assertIn('*.claude.ai = server:https://1.0.0.1/dns-query',s['Host'])
def test_production_renamed_group(self):
renamed = BASE.replace('Claude = select', '🦀 Claude = select').replace(',Claude', ',"🦀 Claude"')
result = build(renamed, DOMAINS, True)
self.assertEqual(result.count('🦀 Claude = select'), 1)
self.assertIn('DOMAIN,anthropic.auth0.com,"🦀 Claude"', result)
def test_drift_rejected(self):
with self.assertRaises(ValueError): build(BASE, DOMAINS[:-1], True)
with self.assertRaises(ValueError): build(BASE.replace('Claude = select, Node','Other = select, Node'), DOMAINS, True)
with self.assertRaises(ValueError): build(BASE, DOMAINS[:-1]+[DOMAINS[0]], True)
if __name__ == '__main__': unittest.main()