package service import ( "net/url" "strings" "testing" ) func TestBuildHysteria2Url_EncodesUserInfoQueryAndFragment(t *testing.T) { raw := buildHysteria2Url( "u@ser:#&=+ pass", "example.com", 443, "salamander", "obf+s&pass=@x", "exa mple.com", "my remark #1", ) parsed, err := url.Parse(raw) if err != nil { t.Fatalf("expected valid url, got error: %v", err) } if parsed.Scheme != "hysteria2" { t.Fatalf("expected hysteria2 scheme, got %s", parsed.Scheme) } if parsed.User == nil { t.Fatal("expected userinfo to be present") } if parsed.User.Username() != "u@ser:#&=+ pass" { t.Fatalf("expected decoded userinfo to match source, got %q", parsed.User.Username()) } q := parsed.Query() if q.Get("obfs") != "salamander" { t.Fatalf("expected obfs=salamander, got %q", q.Get("obfs")) } if q.Get("obfs-password") != "obf+s&pass=@x" { t.Fatalf("expected decoded obfs-password, got %q", q.Get("obfs-password")) } if q.Get("sni") != "exa mple.com" { t.Fatalf("expected decoded sni, got %q", q.Get("sni")) } if q.Get("insecure") != "0" { t.Fatalf("expected insecure=0, got %q", q.Get("insecure")) } if parsed.Fragment != "my remark #1" { t.Fatalf("expected decoded fragment, got %q", parsed.Fragment) } if strings.Contains(raw, "u@ser:#&=+ pass") { t.Fatalf("raw uri must not contain unescaped userinfo: %s", raw) } } func TestBuildHysteria2Url_MinimalConfig(t *testing.T) { raw := buildHysteria2Url("pass", "example.com", 8443, "", "", "", "") parsed, err := url.Parse(raw) if err != nil { t.Fatalf("expected valid url, got error: %v", err) } if parsed.Host != "example.com:8443" { t.Fatalf("unexpected host: %s", parsed.Host) } q := parsed.Query() if q.Get("insecure") != "0" { t.Fatalf("expected insecure=0, got %q", q.Get("insecure")) } if q.Get("obfs") != "" || q.Get("obfs-password") != "" || q.Get("sni") != "" { t.Fatalf("unexpected optional query params in minimal config: %s", parsed.RawQuery) } }