CI / go-test (push) Canceled after 0s
CI / postgres-durable-first (push) Canceled after 0s
CI / codegen (push) Canceled after 0s
CI / govulncheck (push) Canceled after 0s
CI / race (push) Canceled after 0s
CI / fuzz-smoke (push) Canceled after 0s
CI / golangci (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CodeQL Advanced / Analyze (go) (push) Canceled after 0s
CodeQL Advanced / Analyze (actions) (push) Canceled after 0s
CodeQL Advanced / Analyze (javascript-typescript) (push) Canceled after 0s
Docs CI / build (push) Canceled after 0s
Docs Deploy (GitHub Pages) / build (push) Canceled after 0s
Release 3X-UI / build (386) (push) Canceled after 0s
Release 3X-UI / build (amd64) (push) Canceled after 0s
Release 3X-UI / build (arm64) (push) Canceled after 0s
Release 3X-UI / build (armv5) (push) Canceled after 0s
Release 3X-UI / build (armv6) (push) Canceled after 0s
Release 3X-UI / build (armv7) (push) Canceled after 0s
Release 3X-UI / build (s390x) (push) Canceled after 0s
Release 3X-UI / Build for Windows (amd64) (push) Canceled after 0s
Deploy Smoke Tests / noninteractive-install (ubuntu-24.04-arm) (push) Canceled after 0s
Deploy Smoke Tests / noninteractive-install (ubuntu-latest) (push) Canceled after 0s
Deploy Smoke Tests / release-tag-install (ubuntu-24.04-arm) (push) Canceled after 0s
Deploy Smoke Tests / release-tag-install (ubuntu-latest) (push) Canceled after 0s
Docs Deploy (GitHub Pages) / deploy (push) Canceled after 0s
Release 3X-UI / Publish rolling dev release (push) Canceled after 0s
101 lines
4.2 KiB
Go
101 lines
4.2 KiB
Go
package pia
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func TestServerListAdapters(t *testing.T) {
|
|
tests := []struct {
|
|
file, hint, schema, id, hostname string
|
|
}{
|
|
{"v6_valid.json", "6", "v6", "us-east", "useast401"},
|
|
{"v7_valid.json", "7", "v7", "de-berlin", "berlin501"},
|
|
}
|
|
for _, test := range tests {
|
|
raw, err := os.ReadFile(filepath.Join("testdata", "serverlist", test.file))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
regions, schema, err := ParseServerList(raw, test.hint)
|
|
if err != nil {
|
|
t.Fatalf("%s: %v", test.file, err)
|
|
}
|
|
if schema != test.schema || len(regions) != 1 || regions[0].ID != test.id || regions[0].WireGuard[0].Hostname != test.hostname {
|
|
t.Fatalf("unexpected parsed result for %s: schema=%s regions=%+v", test.file, schema, regions)
|
|
}
|
|
}
|
|
|
|
raw, err := os.ReadFile(filepath.Join("testdata", "serverlist", "v7_valid.json"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
regions, schema, err := ParseServerList(raw, "6")
|
|
if err != nil || schema != "v7" || regions[0].ID != "de-berlin" {
|
|
t.Fatalf("detected schema did not override a stale endpoint hint: schema=%q regions=%v err=%v", schema, regions, err)
|
|
}
|
|
|
|
legacy := []byte(`{"groups":{"wg":[]},"regions":[{"id":"legacy","name":"Legacy","country":"US","geo":false,"offline":false,"servers":{"wg":[{"ip":"198.51.100.9","cn":"legacy.example"}]}}]}`)
|
|
regions, schema, err = ParseServerList(legacy, "")
|
|
if err != nil || schema != "v6" || regions[0].ID != "legacy" {
|
|
t.Fatalf("versionless v6 fallback failed: schema=%q regions=%v err=%v", schema, regions, err)
|
|
}
|
|
}
|
|
|
|
func TestServerListRejectsMalformedFields(t *testing.T) {
|
|
raw, err := os.ReadFile(filepath.Join("testdata", "serverlist", "malformed.json"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, _, err := ParseServerList(raw, "6"); err == nil || CodeOf(err) != CodeCatalogSchemaUnsupported {
|
|
t.Fatalf("expected %s for malformed server list, got %s: %v", CodeCatalogSchemaUnsupported, CodeOf(err), err)
|
|
}
|
|
}
|
|
|
|
func TestServerListRejectsUnsupportedDuplicateAndTrailingData(t *testing.T) {
|
|
tests := []struct {
|
|
name, raw, hint string
|
|
}{
|
|
{"unsupported schema", `{"version":99,"groups":{},"regions":[]}`, ""},
|
|
{"invalid version value", `{"version":"v7beta","groups":{"wg":[]},"regions":[]}`, ""},
|
|
{"trailing JSON", `{"version":6,"groups":{},"regions":[]} {}`, "6"},
|
|
{"wrong groups type", `{"version":6,"groups":[],"regions":[]}`, "6"},
|
|
{"wrong field type", `{"version":6,"groups":{"wg":[]},"regions":[{"id":7,"name":"One","country":"US","geo":false,"offline":false,"servers":{"wg":[]}}]}`, "6"},
|
|
}
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
if _, _, err := ParseServerList([]byte(test.raw), test.hint); err == nil || CodeOf(err) != CodeCatalogSchemaUnsupported {
|
|
t.Fatalf("expected %s, got %s: %v", CodeCatalogSchemaUnsupported, CodeOf(err), err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestServerListSkipsBadRows(t *testing.T) {
|
|
duplicate := []byte(`{"version":6,"groups":{"wg":[]},"regions":[{"id":"same","name":"One","country":"US","geo":false,"offline":false,"servers":{"wg":[{"ip":"198.51.100.1","cn":"one.example"}]}},{"id":"SAME","name":"Two","country":"US","geo":false,"offline":false,"servers":{"wg":[{"ip":"198.51.100.2","cn":"two.example"}]}}]}`)
|
|
regions, _, err := ParseServerList(duplicate, "6")
|
|
if err != nil || len(regions) != 1 || regions[0].ID != "same" || regions[0].WireGuard[0].Hostname != "one.example" {
|
|
t.Fatalf("duplicate region id should keep the first: regions=%+v err=%v", regions, err)
|
|
}
|
|
|
|
mixed := []byte(`{"version":6,"groups":{"wg":[]},"regions":[{"id":"us-east","name":"US East","country":"US","geo":false,"offline":false,"servers":{"wg":[{"ip":"2001:db8::1","cn":"bad6"},{"ip":"198.51.100.10","cn":"useast1"}]}}]}`)
|
|
regions, _, err = ParseServerList(mixed, "6")
|
|
if err != nil || len(regions) != 1 || len(regions[0].WireGuard) != 1 || regions[0].WireGuard[0].Hostname != "useast1" {
|
|
t.Fatalf("invalid WireGuard server should be skipped: regions=%+v err=%v", regions, err)
|
|
}
|
|
}
|
|
|
|
func FuzzParseServerList(f *testing.F) {
|
|
for _, name := range []string{"v6_valid.json", "v7_valid.json", "malformed.json"} {
|
|
raw, err := os.ReadFile(filepath.Join("testdata", "serverlist", name))
|
|
if err != nil {
|
|
f.Fatal(err)
|
|
}
|
|
f.Add(raw)
|
|
}
|
|
f.Fuzz(func(t *testing.T, raw []byte) {
|
|
_, _, _ = ParseServerList(raw, "6")
|
|
})
|
|
}
|