import unittest from sbp.clash import cert_fingerprint, proxies_yaml from sbp.errors import SbpError from sbp.share import clash_proxies, clash_yaml from tests.test_state import CERT_SHA256, SERVER_SS_KEY, USER_SS_KEY, sample_state class FingerprintTest(unittest.TestCase): def test_colon_uppercase(self) -> None: self.assertEqual(cert_fingerprint("ab" * 32), ":".join(["AB"] * 32)) def test_rejects_short_value(self) -> None: with self.assertRaises(ValueError): cert_fingerprint("abc") class YamlTest(unittest.TestCase): def test_nested_mapping_and_list(self) -> None: text = proxies_yaml([{ "name": "a", "port": 1, "udp": True, "alpn": ["h3"], "reality-opts": {"public-key": "P", "short-id": "s"}, }]) self.assertEqual( text, "proxies:\n" " - name: a\n" " port: 1\n" " udp: true\n" " alpn:\n" " - h3\n" " reality-opts:\n" " public-key: P\n" " short-id: s\n", ) def test_quotes_values_that_need_it(self) -> None: text = proxies_yaml([{"name": "a", "password": "abc:def", "server": "2602::1"}]) self.assertIn('password: "abc:def"', text) self.assertIn('server: "2602::1"', text) def test_quotes_reserved_words(self) -> None: self.assertIn('name: "no"', proxies_yaml([{"name": "no"}])) class ProxyTest(unittest.TestCase): def setUp(self) -> None: self.state = sample_state() self.user = self.state.users[0] self.proxies = {proxy["type"]: proxy for proxy in clash_proxies(self.state, self.user)} def test_all_protocols_present(self) -> None: self.assertEqual( set(self.proxies), {"hysteria2", "vless", "trojan", "ss", "tuic", "anytls"} ) def test_hysteria2_pins_certificate(self) -> None: proxy = self.proxies["hysteria2"] self.assertEqual(proxy["fingerprint"], cert_fingerprint(CERT_SHA256)) self.assertEqual(proxy["obfs"], "salamander") self.assertNotIn("skip-cert-verify", proxy) def test_vless_reality_options(self) -> None: proxy = self.proxies["vless"] self.assertEqual(proxy["reality-opts"]["public-key"], "PUBLIC") self.assertEqual(proxy["servername"], "www.bing.com") self.assertTrue(proxy["tls"]) def test_shadowsocks_sends_identity_and_user_key(self) -> None: self.assertEqual( self.proxies["ss"]["password"], f"{SERVER_SS_KEY}:{USER_SS_KEY}" ) def test_self_signed_protocols_skip_verification(self) -> None: for key in ("trojan", "tuic", "anytls"): self.assertTrue(self.proxies[key]["skip-cert-verify"], key) def test_disabled_protocol_is_rejected(self) -> None: self.state.protocols["tuic"].enabled = False with self.assertRaises(SbpError): clash_proxies(self.state, self.user, "tuic") def test_single_protocol(self) -> None: proxies = clash_proxies(self.state, self.user, "trojan") self.assertEqual([proxy["type"] for proxy in proxies], ["trojan"]) def test_yaml_covers_every_enabled_protocol(self) -> None: text = clash_yaml(self.state, self.user) self.assertTrue(text.startswith("proxies:\n")) self.assertEqual(text.count("\n - name: "), 6) if __name__ == "__main__": unittest.main()