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
176 lines
5.2 KiB
Go
176 lines
5.2 KiB
Go
package geodata
|
|
|
|
import (
|
|
"errors"
|
|
"testing"
|
|
)
|
|
|
|
func TestParseReference(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
token string
|
|
kind GeoKind
|
|
want Reference
|
|
wantErr error
|
|
}{
|
|
{
|
|
name: "geosite shorthand",
|
|
token: "geosite:google",
|
|
kind: KindSite,
|
|
want: Reference{File: "geosite.dat", Code: "google"},
|
|
},
|
|
{
|
|
name: "geosite code is case insensitive",
|
|
token: "geosite:GOOGLE",
|
|
kind: KindSite,
|
|
want: Reference{File: "geosite.dat", Code: "google"},
|
|
},
|
|
{
|
|
name: "geosite with attribute",
|
|
token: "geosite:google@ads",
|
|
kind: KindSite,
|
|
want: Reference{File: "geosite.dat", Code: "google", Attributes: []string{"ads"}},
|
|
},
|
|
{
|
|
name: "geosite with several attributes",
|
|
token: "geosite:google@ads@cn",
|
|
kind: KindSite,
|
|
want: Reference{File: "geosite.dat", Code: "google", Attributes: []string{"ads", "cn"}},
|
|
},
|
|
{
|
|
name: "ext form",
|
|
token: "ext:my_rules.dat:corp",
|
|
kind: KindSite,
|
|
want: Reference{File: "my_rules.dat", Code: "corp"},
|
|
},
|
|
{
|
|
name: "ext-site form",
|
|
token: "ext-site:my_rules.dat:corp",
|
|
kind: KindSite,
|
|
want: Reference{File: "my_rules.dat", Code: "corp"},
|
|
},
|
|
{
|
|
name: "ext-domain form",
|
|
token: "ext-domain:my_rules.dat:corp",
|
|
kind: KindSite,
|
|
want: Reference{File: "my_rules.dat", Code: "corp"},
|
|
},
|
|
{
|
|
name: "surrounding spaces",
|
|
token: " geosite:google ",
|
|
kind: KindSite,
|
|
want: Reference{File: "geosite.dat", Code: "google"},
|
|
},
|
|
{
|
|
name: "plain domain needs no database",
|
|
token: "google.com",
|
|
kind: KindSite,
|
|
want: Reference{},
|
|
},
|
|
{
|
|
name: "domain keyword rule needs no database",
|
|
token: "keyword:google",
|
|
kind: KindSite,
|
|
want: Reference{},
|
|
},
|
|
{
|
|
name: "geoip shorthand",
|
|
token: "geoip:private",
|
|
kind: KindIP,
|
|
want: Reference{File: "geoip.dat", Code: "private"},
|
|
},
|
|
{
|
|
name: "geoip reverse before the prefix",
|
|
token: "!geoip:cn",
|
|
kind: KindIP,
|
|
want: Reference{File: "geoip.dat", Code: "cn", Reverse: true},
|
|
},
|
|
{
|
|
name: "geoip reverse before the code",
|
|
token: "geoip:!cn",
|
|
kind: KindIP,
|
|
want: Reference{File: "geoip.dat", Code: "cn", Reverse: true},
|
|
},
|
|
{
|
|
name: "ext-ip form",
|
|
token: "ext-ip:my_ips.dat:office",
|
|
kind: KindIP,
|
|
want: Reference{File: "my_ips.dat", Code: "office"},
|
|
},
|
|
{
|
|
name: "plain cidr needs no database",
|
|
token: "10.0.0.0/8",
|
|
kind: KindIP,
|
|
want: Reference{},
|
|
},
|
|
{name: "empty token", token: " ", kind: KindSite, wantErr: ErrInvalidToken},
|
|
{name: "ext without code", token: "ext:geosite.dat", kind: KindSite, wantErr: ErrInvalidToken},
|
|
{name: "ext with empty code", token: "ext:geosite.dat:", kind: KindSite, wantErr: ErrInvalidToken},
|
|
{name: "ext with empty file", token: "ext::google", kind: KindSite, wantErr: ErrInvalidToken},
|
|
{name: "geosite without code", token: "geosite:", kind: KindSite, wantErr: ErrInvalidToken},
|
|
{name: "bare ext prefix", token: "ext:", kind: KindSite, wantErr: ErrInvalidToken},
|
|
{name: "geoip token in a domain field", token: "geoip:cn", kind: KindSite, wantErr: ErrWrongKind},
|
|
{name: "geosite token in an ip field", token: "geosite:cn", kind: KindIP, wantErr: ErrWrongKind},
|
|
{name: "empty attribute", token: "geosite:cn@", kind: KindSite, wantErr: ErrInvalidToken},
|
|
{
|
|
name: "a space inside the code stays part of the code",
|
|
token: "geosite: cn",
|
|
kind: KindSite,
|
|
want: Reference{File: "geosite.dat", Code: " cn"},
|
|
},
|
|
{
|
|
name: "a space inside an attribute stays part of the attribute",
|
|
token: "geosite:cn@ ads",
|
|
kind: KindSite,
|
|
want: Reference{File: "geosite.dat", Code: "cn", Attributes: []string{" ads"}},
|
|
},
|
|
{name: "empty attribute between two others", token: "geosite:cn@@ads", kind: KindSite, wantErr: ErrInvalidToken},
|
|
{
|
|
name: "double negation folds back to a plain match",
|
|
token: "!!geoip:cn",
|
|
kind: KindIP,
|
|
want: Reference{File: "geoip.dat", Code: "cn"},
|
|
},
|
|
{
|
|
name: "negation on both sides of the prefix cancels out",
|
|
token: "!geoip:!cn",
|
|
kind: KindIP,
|
|
want: Reference{File: "geoip.dat", Code: "cn"},
|
|
},
|
|
{name: "bare ext-ip prefix", token: "ext-ip:", kind: KindIP, wantErr: ErrInvalidToken},
|
|
{
|
|
name: "an attribute suffix is part of the code for ip rules",
|
|
token: "geoip:cn@x",
|
|
kind: KindIP,
|
|
want: Reference{File: "geoip.dat", Code: "cn@x"},
|
|
},
|
|
{name: "attribute only", token: "geosite:@ads", kind: KindSite, wantErr: ErrInvalidToken},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := ParseReference(tt.token, tt.kind)
|
|
if tt.wantErr != nil {
|
|
if !errors.Is(err, tt.wantErr) {
|
|
t.Fatalf("error = %v, want %v", err, tt.wantErr)
|
|
}
|
|
return
|
|
}
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if got.File != tt.want.File || got.Code != tt.want.Code || got.Reverse != tt.want.Reverse {
|
|
t.Errorf("reference = %+v, want %+v", got, tt.want)
|
|
}
|
|
if len(got.Attributes) != len(tt.want.Attributes) {
|
|
t.Fatalf("attributes = %v, want %v", got.Attributes, tt.want.Attributes)
|
|
}
|
|
for i, attribute := range tt.want.Attributes {
|
|
if got.Attributes[i] != attribute {
|
|
t.Errorf("attribute %d = %q, want %q", i, got.Attributes[i], attribute)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|