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()