diff options
Diffstat (limited to 'web/service/xray_setting_test.go')
| -rw-r--r-- | web/service/xray_setting_test.go | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/web/service/xray_setting_test.go b/web/service/xray_setting_test.go new file mode 100644 index 00000000..2c165576 --- /dev/null +++ b/web/service/xray_setting_test.go @@ -0,0 +1,90 @@ +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) +} |
