package service import ( "encoding/json" "strings" "testing" ) func TestUnwrapXrayTemplateConfig(t *testing.T) { real := `{"log":{},"inbounds":[],"outbounds":[],"routing":{}}` t.Run("passes through a clean config", func(t *testing.T) { if got := UnwrapXrayTemplateConfig(real); got != real { t.Fatalf("clean config was modified: %s", got) } }) t.Run("passes through invalid JSON unchanged", func(t *testing.T) { in := "not json at all" if got := UnwrapXrayTemplateConfig(in); got != in { t.Fatalf("invalid input was modified: %s", got) } }) t.Run("unwraps one layer of response-shaped wrapper", func(t *testing.T) { wrapper := `{"inboundTags":["tag"],"outboundTestUrl":"x","xraySetting":` + real + `}` got := UnwrapXrayTemplateConfig(wrapper) if !equalJSON(t, got, real) { t.Fatalf("want %s, got %s", real, got) } }) t.Run("unwraps multiple stacked layers", func(t *testing.T) { lvl1 := `{"xraySetting":` + real + `}` lvl2 := `{"xraySetting":` + lvl1 + `}` lvl3 := `{"xraySetting":` + lvl2 + `}` got := UnwrapXrayTemplateConfig(lvl3) if !equalJSON(t, got, real) { t.Fatalf("want %s, got %s", real, got) } }) t.Run("handles an xraySetting stored as a JSON-encoded string", func(t *testing.T) { encoded, _ := json.Marshal(real) // becomes a quoted string wrapper := `{"xraySetting":` + string(encoded) + `}` got := UnwrapXrayTemplateConfig(wrapper) if !equalJSON(t, got, real) { t.Fatalf("want %s, got %s", real, got) } }) t.Run("does not unwrap when top level already has real xray keys", func(t *testing.T) { // Pathological but defensible: if a user's actual config somehow // has both the real keys and an unrelated `xraySetting` key, we // must not strip it. in := `{"inbounds":[],"xraySetting":{"some":"thing"}}` got := UnwrapXrayTemplateConfig(in) if got != in { t.Fatalf("should have left real config alone, got %s", got) } }) t.Run("stops at a reasonable depth", func(t *testing.T) { // Build a deeper-than-maxDepth chain that ends at something // non-wrapped, and confirm we end up at some valid JSON (we // don't loop forever and we don't blow the stack). s := real for i := 0; i < 16; i++ { s = `{"xraySetting":` + s + `}` } got := UnwrapXrayTemplateConfig(s) if !strings.Contains(got, `"inbounds"`) && !strings.Contains(got, `"xraySetting"`) { t.Fatalf("unexpected tail: %s", got) } }) } func equalJSON(t *testing.T, a, b string) bool { t.Helper() var va, vb any if err := json.Unmarshal([]byte(a), &va); err != nil { return false } if err := json.Unmarshal([]byte(b), &vb); err != nil { return false } ja, _ := json.Marshal(va) jb, _ := json.Marshal(vb) return string(ja) == string(jb) }