精简P2: geodata 测试夹具改 protowire 手工编码(geodat.proto 字段号+proto3 零值省略语义原样复刻), 不再依赖 xray-core 生成类型写 .dat 夹具
This commit is contained in:
@@ -12,24 +12,97 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
xraygeodata "github.com/xtls/xray-core/common/geodata"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/encoding/protowire"
|
||||
)
|
||||
|
||||
func writeSiteDB(t *testing.T, dir, name string, sites ...*xraygeodata.GeoSite) string {
|
||||
// The fixtures are encoded with protowire directly: the databases' wire
|
||||
// layout is the contract this package parses, and spelling it out keeps the
|
||||
// tests independent of xray-core's generated types. Field numbers follow
|
||||
// geodat.proto — list entry 1; entry code 1, payload 2; domain type 1,
|
||||
// value 2, attribute 3; attribute key 1, bool value 2; cidr ip 1, prefix 2.
|
||||
// proto3 zero-value omission is reproduced exactly (a domain of type 0 and
|
||||
// a /0 prefix emit no field), because the reader's behavior depends on it.
|
||||
|
||||
// Domain match types, mirroring xray's Domain_Type enum.
|
||||
const (
|
||||
DomainSubstr = 0
|
||||
DomainRegex = 1
|
||||
DomainDomain = 2
|
||||
DomainFull = 3
|
||||
)
|
||||
|
||||
type fixtureDomain struct {
|
||||
typ uint64
|
||||
value string
|
||||
attrs []string
|
||||
}
|
||||
|
||||
type fixtureSite struct {
|
||||
code string
|
||||
domains []fixtureDomain
|
||||
}
|
||||
|
||||
type fixtureIP struct {
|
||||
code string
|
||||
prefixes []string
|
||||
}
|
||||
|
||||
func wireBytes(num protowire.Number, payload []byte) []byte {
|
||||
out := protowire.AppendTag(nil, num, protowire.BytesType)
|
||||
return protowire.AppendBytes(out, payload)
|
||||
}
|
||||
|
||||
func wireString(num protowire.Number, value string) []byte {
|
||||
out := protowire.AppendTag(nil, num, protowire.BytesType)
|
||||
return protowire.AppendString(out, value)
|
||||
}
|
||||
|
||||
func wireVarint(num protowire.Number, value uint64) []byte {
|
||||
out := protowire.AppendTag(nil, num, protowire.VarintType)
|
||||
return protowire.AppendVarint(out, value)
|
||||
}
|
||||
|
||||
func encodeFixtureDomain(d fixtureDomain) []byte {
|
||||
var msg []byte
|
||||
if d.typ != 0 {
|
||||
msg = append(msg, wireVarint(1, d.typ)...)
|
||||
}
|
||||
msg = append(msg, wireString(2, d.value)...)
|
||||
for _, attr := range d.attrs {
|
||||
attrMsg := wireString(1, attr)
|
||||
attrMsg = append(attrMsg, wireVarint(2, 1)...) // bool_value = true
|
||||
msg = append(msg, wireBytes(3, attrMsg)...)
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
func writeSiteDB(t *testing.T, dir, name string, sites ...fixtureSite) string {
|
||||
t.Helper()
|
||||
data, err := proto.Marshal(&xraygeodata.GeoSiteList{Entry: sites})
|
||||
if err != nil {
|
||||
t.Fatalf("marshal geosite list: %v", err)
|
||||
var data []byte
|
||||
for _, s := range sites {
|
||||
entry := wireString(1, s.code)
|
||||
for _, d := range s.domains {
|
||||
entry = append(entry, wireBytes(2, encodeFixtureDomain(d))...)
|
||||
}
|
||||
data = append(data, wireBytes(1, entry)...)
|
||||
}
|
||||
return writeFile(t, dir, name, data)
|
||||
}
|
||||
|
||||
func writeIPDB(t *testing.T, dir, name string, geoips ...*xraygeodata.GeoIP) string {
|
||||
func writeIPDB(t *testing.T, dir, name string, geoips ...fixtureIP) string {
|
||||
t.Helper()
|
||||
data, err := proto.Marshal(&xraygeodata.GeoIPList{Entry: geoips})
|
||||
if err != nil {
|
||||
t.Fatalf("marshal geoip list: %v", err)
|
||||
var data []byte
|
||||
for _, g := range geoips {
|
||||
entry := wireString(1, g.code)
|
||||
for _, raw := range g.prefixes {
|
||||
prefix := netip.MustParsePrefix(raw)
|
||||
cidr := wireBytes(1, prefix.Addr().AsSlice())
|
||||
if prefix.Bits() != 0 {
|
||||
cidr = append(cidr, wireVarint(2, uint64(prefix.Bits()))...)
|
||||
}
|
||||
entry = append(entry, wireBytes(2, cidr)...)
|
||||
}
|
||||
data = append(data, wireBytes(1, entry)...)
|
||||
}
|
||||
return writeFile(t, dir, name, data)
|
||||
}
|
||||
@@ -43,45 +116,30 @@ func writeFile(t *testing.T, dir, name string, data []byte) string {
|
||||
return path
|
||||
}
|
||||
|
||||
func site(code string, domains ...*xraygeodata.Domain) *xraygeodata.GeoSite {
|
||||
return &xraygeodata.GeoSite{Code: code, Domain: domains}
|
||||
func site(code string, domains ...fixtureDomain) fixtureSite {
|
||||
return fixtureSite{code: code, domains: domains}
|
||||
}
|
||||
|
||||
func domain(domainType xraygeodata.Domain_Type, value string, attributes ...string) *xraygeodata.Domain {
|
||||
d := &xraygeodata.Domain{Type: domainType, Value: value}
|
||||
for _, attribute := range attributes {
|
||||
d.Attribute = append(d.Attribute, &xraygeodata.Domain_Attribute{
|
||||
Key: attribute,
|
||||
TypedValue: &xraygeodata.Domain_Attribute_BoolValue{BoolValue: true},
|
||||
})
|
||||
}
|
||||
return d
|
||||
func domain(domainType uint64, value string, attributes ...string) fixtureDomain {
|
||||
return fixtureDomain{typ: domainType, value: value, attrs: attributes}
|
||||
}
|
||||
|
||||
func geoip(code string, prefixes ...string) *xraygeodata.GeoIP {
|
||||
entry := &xraygeodata.GeoIP{Code: code}
|
||||
for _, raw := range prefixes {
|
||||
prefix := netip.MustParsePrefix(raw)
|
||||
entry.Cidr = append(entry.Cidr, &xraygeodata.CIDR{
|
||||
Ip: prefix.Addr().AsSlice(),
|
||||
Prefix: uint32(prefix.Bits()),
|
||||
})
|
||||
}
|
||||
return entry
|
||||
func geoip(code string, prefixes ...string) fixtureIP {
|
||||
return fixtureIP{code: code, prefixes: prefixes}
|
||||
}
|
||||
|
||||
func sampleSiteDB(t *testing.T, dir string) {
|
||||
t.Helper()
|
||||
writeSiteDB(t, dir, "geosite.dat",
|
||||
site("google",
|
||||
domain(xraygeodata.Domain_Domain, "google.com"),
|
||||
domain(xraygeodata.Domain_Full, "ads.google.com", "ads"),
|
||||
domain(xraygeodata.Domain_Substr, "googlevideo", "cn"),
|
||||
domain(xraygeodata.Domain_Regex, `^g.*\.cn$`),
|
||||
domain(DomainDomain, "google.com"),
|
||||
domain(DomainFull, "ads.google.com", "ads"),
|
||||
domain(DomainSubstr, "googlevideo", "cn"),
|
||||
domain(DomainRegex, `^g.*\.cn$`),
|
||||
),
|
||||
site("CN",
|
||||
domain(xraygeodata.Domain_Domain, "baidu.com"),
|
||||
domain(xraygeodata.Domain_Domain, "qq.com"),
|
||||
domain(DomainDomain, "baidu.com"),
|
||||
domain(DomainDomain, "qq.com"),
|
||||
),
|
||||
)
|
||||
}
|
||||
@@ -126,7 +184,7 @@ func TestListFilesReportsKindAndCategories(t *testing.T) {
|
||||
|
||||
func TestKindDetectedFromContentsNotName(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
writeSiteDB(t, dir, "my_ip_rules.dat", site("corp", domain(xraygeodata.Domain_Domain, "intranet.corp.local")))
|
||||
writeSiteDB(t, dir, "my_ip_rules.dat", site("corp", domain(DomainDomain, "intranet.corp.local")))
|
||||
writeIPDB(t, dir, "custom_sites.dat", geoip("office", "192.168.7.0/24"))
|
||||
|
||||
store := NewStore(dir)
|
||||
@@ -241,9 +299,9 @@ func TestSearchFilters(t *testing.T) {
|
||||
|
||||
func TestPagination(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
domains := make([]*xraygeodata.Domain, 0, 250)
|
||||
domains := make([]fixtureDomain, 0, 250)
|
||||
for i := range 250 {
|
||||
domains = append(domains, domain(xraygeodata.Domain_Domain, "host"+strconv.Itoa(i)+".example.com"))
|
||||
domains = append(domains, domain(DomainDomain, "host"+strconv.Itoa(i)+".example.com"))
|
||||
}
|
||||
writeSiteDB(t, dir, "geosite.dat", site("bulk", domains...))
|
||||
store := NewStore(dir)
|
||||
@@ -284,9 +342,9 @@ func TestPagination(t *testing.T) {
|
||||
|
||||
func TestCategoriesReturnEverythingWithoutLimit(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
sites := make([]*xraygeodata.GeoSite, 0, MaxPageSize+20)
|
||||
sites := make([]fixtureSite, 0, MaxPageSize+20)
|
||||
for i := range MaxPageSize + 20 {
|
||||
sites = append(sites, site("cat"+strconv.Itoa(i), domain(xraygeodata.Domain_Domain, "example.com")))
|
||||
sites = append(sites, site("cat"+strconv.Itoa(i), domain(DomainDomain, "example.com")))
|
||||
}
|
||||
writeSiteDB(t, dir, "geosite.dat", sites...)
|
||||
store := NewStore(dir)
|
||||
@@ -421,9 +479,9 @@ func TestIndexCacheInvalidatedWhenFileChanges(t *testing.T) {
|
||||
}
|
||||
|
||||
path := writeSiteDB(t, dir, "geosite.dat",
|
||||
site("google", domain(xraygeodata.Domain_Domain, "google.com")),
|
||||
site("cn", domain(xraygeodata.Domain_Domain, "baidu.com")),
|
||||
site("telegram", domain(xraygeodata.Domain_Domain, "t.me")),
|
||||
site("google", domain(DomainDomain, "google.com")),
|
||||
site("cn", domain(DomainDomain, "baidu.com")),
|
||||
site("telegram", domain(DomainDomain, "t.me")),
|
||||
)
|
||||
touch(t, path, time.Now().Add(time.Second))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user