|
|
@@ -0,0 +1,54 @@
|
|
|
+package outbound
|
|
|
+
|
|
|
+import (
|
|
|
+ "net/http"
|
|
|
+ "net/http/httptest"
|
|
|
+ "net/url"
|
|
|
+ "testing"
|
|
|
+
|
|
|
+ "github.com/mhsanaei/3x-ui/v3/internal/xray"
|
|
|
+)
|
|
|
+
|
|
|
+// A direct, DNS, loopback or blackhole outbound is not a tunnel, so the probe
|
|
|
+// rejects it whatever the spelling: the core resolves "Freedom" to freedom.
|
|
|
+func TestTestOutboundsRejectsCaseVariantUntestableIDs(t *testing.T) {
|
|
|
+ srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
+ w.WriteHeader(http.StatusNoContent)
|
|
|
+ }))
|
|
|
+ defer srv.Close()
|
|
|
+
|
|
|
+ withStubProcess(t, func(cfg *xray.Config, configPath string) batchProcess {
|
|
|
+ return &stubProcess{cfg: cfg, serveSocks: true}
|
|
|
+ })
|
|
|
+ withEgressTraceProbe(t, func(*url.URL) *TestEgressResult {
|
|
|
+ return &TestEgressResult{IPv4: "198.51.100.2", Country: "ZZ", Warp: "off"}
|
|
|
+ })
|
|
|
+
|
|
|
+ tests := []struct {
|
|
|
+ name string
|
|
|
+ protocol string
|
|
|
+ wantErr string
|
|
|
+ }{
|
|
|
+ {"freedom", "freedom", "Direct/DNS outbound cannot be tested"},
|
|
|
+ {"Freedom", "Freedom", "Direct/DNS outbound cannot be tested"},
|
|
|
+ {"FREEDOM", "FREEDOM", "Direct/DNS outbound cannot be tested"},
|
|
|
+ {"DNS", "DNS", "Direct/DNS outbound cannot be tested"},
|
|
|
+ {"Blackhole", "Blackhole", "Blocked/blackhole outbound cannot be tested"},
|
|
|
+ {"Loopback", "Loopback", "Loopback outbound cannot be tested"},
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, tt := range tests {
|
|
|
+ t.Run(tt.name, func(t *testing.T) {
|
|
|
+ batch := mustJSON(t, []any{map[string]any{"tag": "probe", "protocol": tt.protocol}})
|
|
|
+ results, err := (&OutboundService{}).TestOutbounds(batch, srv.URL, "", "http")
|
|
|
+ if err != nil {
|
|
|
+ t.Fatalf("TestOutbounds: %v", err)
|
|
|
+ }
|
|
|
+ r := results[0]
|
|
|
+ if r.Success || r.Error != tt.wantErr {
|
|
|
+ t.Errorf("%q = success=%v err=%q egress=%+v, want the rejection %q",
|
|
|
+ tt.protocol, r.Success, r.Error, r.Egress, tt.wantErr)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|