package subscription import ( "encoding/base64" "reflect" "testing" "gopkg.in/yaml.v3" ) func TestParseSS_PlainUserinfo(t *testing.T) { uri := "ss://aes-256-gcm:password123@example.com:8388#My%20Node" got := parseSS(uri) want := map[string]interface{}{ "name": "My Node", "type": "ss", "server": "example.com", "port": 8388, "cipher": "aes-256-gcm", "password": "password123", } if !reflect.DeepEqual(got, want) { t.Fatalf("parseSS() = %#v, want %#v", got, want) } } func TestParseSS_Base64Userinfo(t *testing.T) { userinfo := base64.URLEncoding.WithPadding(base64.NoPadding).EncodeToString([]byte("aes-256-gcm:password123")) uri := "ss://" + userinfo + "@example.com:8388#node" got := parseSS(uri) want := map[string]interface{}{ "name": "node", "type": "ss", "server": "example.com", "port": 8388, "cipher": "aes-256-gcm", "password": "password123", } if !reflect.DeepEqual(got, want) { t.Fatalf("parseSS() = %#v, want %#v", got, want) } } func TestParseSS_WholeBodyBase64(t *testing.T) { body := base64.URLEncoding.WithPadding(base64.NoPadding).EncodeToString([]byte("aes-256-gcm:password123@example.com:8388")) uri := "ss://" + body + "#node" got := parseSS(uri) want := map[string]interface{}{ "name": "node", "type": "ss", "server": "example.com", "port": 8388, "cipher": "aes-256-gcm", "password": "password123", } if !reflect.DeepEqual(got, want) { t.Fatalf("parseSS() = %#v, want %#v", got, want) } } func TestParseSS_NotSS(t *testing.T) { if got := parseSS("trojan://foo@bar:443"); got != nil { t.Fatalf("parseSS() = %#v, want nil", got) } } func TestParseTrojan_Basic(t *testing.T) { uri := "trojan://mypassword@example.com:443?sni=sni.example.com&allowInsecure=1#My%20Trojan" got := parseTrojan(uri) want := map[string]interface{}{ "name": "My Trojan", "type": "trojan", "server": "example.com", "port": 443, "password": "mypassword", "udp": true, "sni": "sni.example.com", "skip-cert-verify": true, } if !reflect.DeepEqual(got, want) { t.Fatalf("parseTrojan() = %#v, want %#v", got, want) } } func TestParseTrojan_PeerFallback(t *testing.T) { uri := "trojan://mypassword@example.com:443?peer=peer.example.com" got := parseTrojan(uri) if got["sni"] != "peer.example.com" { t.Fatalf("expected sni from peer fallback, got %#v", got) } } func TestParseVless_TLS(t *testing.T) { uri := "vless://uuid-1234@example.com:443?security=tls&sni=sni.example.com&fp=chrome&type=ws#node" got := parseVless(uri) want := map[string]interface{}{ "name": "node", "type": "vless", "server": "example.com", "port": 443, "uuid": "uuid-1234", "udp": true, "tls": true, "network": "ws", "servername": "sni.example.com", "client-fingerprint": "chrome", } if !reflect.DeepEqual(got, want) { t.Fatalf("parseVless() = %#v, want %#v", got, want) } } func TestParseVless_Reality(t *testing.T) { uri := "vless://uuid-1234@example.com:443?security=reality&pbk=publickey&sid=shortid&sni=sni.example.com" got := parseVless(uri) realityOpts, ok := got["reality-opts"].(map[string]interface{}) if !ok { t.Fatalf("expected reality-opts map, got %#v", got["reality-opts"]) } if realityOpts["public-key"] != "publickey" || realityOpts["short-id"] != "shortid" { t.Fatalf("unexpected reality-opts: %#v", realityOpts) } if got["servername"] != "sni.example.com" { t.Fatalf("expected servername set, got %#v", got["servername"]) } if got["tls"] != true { t.Fatalf("expected tls=true for reality, got %#v", got["tls"]) } } func TestParseVless_DefaultsWithoutQuery(t *testing.T) { uri := "vless://uuid-1234@example.com:443" got := parseVless(uri) if got["tls"] != false || got["network"] != "tcp" || got["udp"] != true { t.Fatalf("unexpected defaults: %#v", got) } } func TestConvertContent_PassthroughExistingClashYAML(t *testing.T) { content := "proxies:\n - name: foo\n type: ss\n" if got := convertContent(content); got != content { t.Fatalf("expected passthrough, got %q", got) } } func TestConvertContent_PlainURIList(t *testing.T) { content := "ss://aes-256-gcm:pw@example.com:8388#node1\ntrojan://pw2@example.com:443#node2\n" out := convertContent(content) var parsed map[string]interface{} if err := yaml.Unmarshal([]byte(out), &parsed); err != nil { t.Fatalf("output is not valid YAML: %v", err) } proxies, ok := parsed["proxies"].([]interface{}) if !ok || len(proxies) != 2 { t.Fatalf("expected 2 proxies, got %#v", parsed["proxies"]) } } func TestConvertContent_WholeBodyBase64List(t *testing.T) { raw := "ss://aes-256-gcm:pw@example.com:8388#node1\ntrojan://pw2@example.com:443#node2\n" encoded := base64.StdEncoding.EncodeToString([]byte(raw)) out := convertContent(encoded) var parsed map[string]interface{} if err := yaml.Unmarshal([]byte(out), &parsed); err != nil { t.Fatalf("output is not valid YAML: %v", err) } proxies, ok := parsed["proxies"].([]interface{}) if !ok || len(proxies) != 2 { t.Fatalf("expected 2 proxies, got %#v", parsed["proxies"]) } } func TestConvertContent_UnrecognizedPassthrough(t *testing.T) { content := "not a uri list and not yaml: [unterminated" if got := convertContent(content); got != content { t.Fatalf("expected passthrough of unrecognized content, got %q", got) } }