Add unit tests covering the whole root package

Co-authored-by: Loyalsoldier <10487845+Loyalsoldier@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-08-05 14:27:23 +00:00 committed by GitHub
parent 646bf25ac9
commit 4642ee5d9a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,13 +1,22 @@
package main
import (
"errors"
"os"
"os/exec"
"path/filepath"
"slices"
"strings"
"testing"
"github.com/v2fly/domain-list-community/internal/dlc"
router "github.com/v2fly/v2ray-core/v5/app/router/routercommon"
"google.golang.org/protobuf/proto"
)
// mainExitEnv marks the re-executed test binary that has to run main().
const mainExitEnv = "DLC_TEST_MAIN_EXIT"
func TestParseEntry(t *testing.T) {
testCases := []struct {
name string
@ -29,6 +38,10 @@ func TestParseEntry(t *testing.T) {
{name: "empty rule", typ: "domain", rule: " ", wantErr: true},
{name: "unknown type", typ: "prefix", rule: "example.com", wantErr: true},
{name: "invalid domain", typ: "domain", rule: "exa_mple.com @ads", wantErr: true},
{name: "invalid keyword", typ: "keyword", rule: "ad_s", wantErr: true},
{name: "overlong domain", typ: "domain", rule: strings.Repeat("a.", 127) + "com", wantErr: true},
{name: "invalid attr", typ: "domain", rule: "example.com @a_ds", wantErr: true},
{name: "invalid affiliation", typ: "domain", rule: "example.com &other_list", wantErr: true},
{name: "empty label", typ: "domain", rule: "example..com", wantErr: true},
{name: "trailing dot", typ: "full", rule: "example.com.", wantErr: true},
{name: "leading dot", typ: "domain", rule: ".example.com", wantErr: true},
@ -81,6 +94,7 @@ func TestParseInclusion(t *testing.T) {
{name: "empty ban attr", rule: "other @-", wantErr: true},
{name: "empty rule", rule: " ", wantErr: true},
{name: "invalid name", rule: "other@list", wantErr: true},
{name: "unknown field", rule: "other list", wantErr: true},
{name: "affiliation", rule: "other &another", wantErr: true},
}
for _, tc := range testCases {
@ -193,6 +207,566 @@ func TestResolveCircularInclusion(t *testing.T) {
}
}
func TestValidateChars(t *testing.T) {
testCases := []struct {
name string
validate func(string) bool
input string
want bool
}{
{name: "domain chars", validate: validateDomainChars, input: "my-example.com", want: true},
{name: "empty domain chars", validate: validateDomainChars, input: "", want: false},
{name: "uppercase domain chars", validate: validateDomainChars, input: "Example.com", want: false},
{name: "domain name", validate: validateDomainName, input: "a.example.com", want: true},
{name: "empty domain name", validate: validateDomainName, input: "", want: false},
{name: "attr chars", validate: validateAttrChars, input: "!ads1", want: true},
{name: "empty attr chars", validate: validateAttrChars, input: "", want: false},
{name: "uppercase attr chars", validate: validateAttrChars, input: "Ads", want: false},
{name: "site name", validate: validateSiteName, input: "GEOLOCATION-!CN", want: true},
{name: "empty site name", validate: validateSiteName, input: "", want: false},
{name: "lowercase site name", validate: validateSiteName, input: "cn", want: false},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
if got := tc.validate(tc.input); got != tc.want {
t.Errorf("validate(%q) = %v, want %v", tc.input, got, tc.want)
}
})
}
}
func TestLoadData(t *testing.T) {
dataPath := t.TempDir()
content := strings.Join([]string{
"# A comment line",
"",
" ",
"example.com # Rule without type falls back to domain",
"full:mail.example.com @cn &affiliated",
"include:other @ads",
"keyword:example",
`regexp:^ads\.example\.com$`,
}, "\n")
writeTestData(t, dataPath, map[string]string{"test": content})
processor := &Processor{parsedListByName: make(map[string]*ParsedList)}
if err := processor.loadData("TEST", filepath.Join(dataPath, "test")); err != nil {
t.Fatalf("loadData(\"TEST\") got unexpected error: %v", err)
}
pl := processor.parsedListByName["TEST"]
assertPlains(t, "TEST", pl.Entries, []string{
"domain:example.com",
"full:mail.example.com:@cn",
"keyword:example",
`regexp:^ads\.example\.com$`,
})
if len(pl.Inclusions) != 1 || pl.Inclusions[0].Source != "OTHER" {
t.Errorf("TEST inclusions = %+v, want one inclusion of %q", pl.Inclusions, "OTHER")
}
// Affiliated entries are also added to the affiliated list
apl, exist := processor.parsedListByName["AFFILIATED"]
if !exist {
t.Fatal("list \"AFFILIATED\" does not exist")
}
assertPlains(t, "AFFILIATED", apl.Entries, []string{"full:mail.example.com:@cn"})
}
func TestLoadDataErrors(t *testing.T) {
dataPath := t.TempDir()
files := map[string]string{
"invalid-entry": "domain:exa_mple.com\n",
"invalid-inclusion": "include:other@list\n",
}
writeTestData(t, dataPath, files)
for name := range files {
t.Run(name, func(t *testing.T) {
processor := &Processor{parsedListByName: make(map[string]*ParsedList)}
if err := processor.loadData("TEST", filepath.Join(dataPath, name)); err == nil {
t.Errorf("loadData(%q) = nil, want parsing error", name)
}
})
}
t.Run("missing file", func(t *testing.T) {
processor := &Processor{parsedListByName: make(map[string]*ParsedList)}
if err := processor.loadData("TEST", filepath.Join(dataPath, "missing")); err == nil {
t.Error("loadData(\"missing\") = nil, want file opening error")
}
})
}
func TestResolveMissingList(t *testing.T) {
processor := &Processor{parsedListByName: make(map[string]*ParsedList)}
if _, err := processor.resolveList("MISSING"); err == nil {
t.Error("resolveList(\"MISSING\") = nil, want list not found error")
}
}
func TestResolveEmptyList(t *testing.T) {
dataPath := t.TempDir()
writeTestData(t, dataPath, map[string]string{"empty": "# Only a comment\n"})
processor := &Processor{parsedListByName: make(map[string]*ParsedList)}
if err := processor.loadData("EMPTY", filepath.Join(dataPath, "empty")); err != nil {
t.Fatalf("loadData(\"EMPTY\") got unexpected error: %v", err)
}
pl, err := processor.resolveList("EMPTY")
if err != nil {
t.Fatalf("resolveList(\"EMPTY\") got unexpected error: %v", err)
}
if len(pl.FinalEntries) != 0 {
t.Errorf("EMPTY final entries = %v, want none", pl.FinalEntries)
}
}
func TestMakeProtoList(t *testing.T) {
rules := []struct{ typ, rule string }{
{"domain", "example.com @cn @ads"},
{"full", "www.example.com"},
{"keyword", "example"},
{"regexp", `^example\.com$`},
}
entries := make([]*Entry, 0, len(rules))
for _, r := range rules {
entry, _, err := parseEntry(r.typ, r.rule)
if err != nil {
t.Fatalf("parseEntry(%q, %q) got unexpected error: %v", r.typ, r.rule, err)
}
entries = append(entries, entry)
}
site := makeProtoList("TEST", entries)
if site.CountryCode != "TEST" {
t.Errorf("makeProtoList() country code = %q, want %q", site.CountryCode, "TEST")
}
wantTypes := []router.Domain_Type{
router.Domain_RootDomain,
router.Domain_Full,
router.Domain_Plain,
router.Domain_Regex,
}
if len(site.Domain) != len(wantTypes) {
t.Fatalf("makeProtoList() domains = %v, want %d domains", site.Domain, len(wantTypes))
}
for i, pdomain := range site.Domain {
if pdomain.Type != wantTypes[i] {
t.Errorf("makeProtoList() domain[%d] type = %v, want %v", i, pdomain.Type, wantTypes[i])
}
if pdomain.Value != entries[i].Value {
t.Errorf("makeProtoList() domain[%d] value = %q, want %q", i, pdomain.Value, entries[i].Value)
}
}
attrs := site.Domain[0].Attribute
if len(attrs) != 2 || attrs[0].Key != "ads" || attrs[1].Key != "cn" {
t.Fatalf("makeProtoList() domain[0] attributes = %v, want %v", attrs, []string{"ads", "cn"})
}
for _, attr := range attrs {
if !attr.GetBoolValue() {
t.Errorf("makeProtoList() attribute %q value = %v, want true", attr.Key, attr.GetBoolValue())
}
}
}
func TestLoadTasks(t *testing.T) {
dataPath := t.TempDir()
testCases := []struct {
name string
content string
want []DatTask
wantErr bool
}{
{
name: "valid",
content: `[{"name":"dlc.dat","mode":"all"},{"name":"cn.dat","mode":"allowlist","lists":["cn"]},{"name":"nocn.dat","mode":"denylist","lists":["cn"]}]`,
want: []DatTask{
{Name: "dlc.dat", Mode: ModeAll},
{Name: "cn.dat", Mode: ModeAllowlist, Lists: []string{"cn"}},
{Name: "nocn.dat", Mode: ModeDenylist, Lists: []string{"cn"}},
},
},
{name: "invalid json", content: "{", wantErr: true},
{name: "missing name", content: `[{"mode":"all"}]`, wantErr: true},
{name: "invalid mode", content: `[{"name":"dlc.dat","mode":"unknown"}]`, wantErr: true},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
path := filepath.Join(dataPath, tc.name+".json")
if err := os.WriteFile(path, []byte(tc.content), 0644); err != nil {
t.Fatalf("failed to write test profile %q: %v", path, err)
}
tasks, err := loadTasks(path)
if tc.wantErr {
if err == nil {
t.Fatalf("loadTasks(%q) = %+v, want error", tc.name, tasks)
}
return
}
if err != nil {
t.Fatalf("loadTasks(%q) got unexpected error: %v", tc.name, err)
}
if !slices.EqualFunc(tasks, tc.want, func(a, b DatTask) bool {
return a.Name == b.Name && a.Mode == b.Mode && slices.Equal(a.Lists, b.Lists)
}) {
t.Errorf("loadTasks(%q) = %+v, want %+v", tc.name, tasks, tc.want)
}
})
}
t.Run("missing file", func(t *testing.T) {
if _, err := loadTasks(filepath.Join(dataPath, "missing.json")); err == nil {
t.Error("loadTasks(\"missing.json\") = nil, want file opening error")
}
})
}
func TestAssembleDat(t *testing.T) {
outPath := t.TempDir()
setFlag(t, outputDir, outPath)
gs := newTestGeoSites("APPLE", "CN", "GOOGLE")
testCases := []struct {
name string
task DatTask
want []string
wantErr bool
}{
{name: "all", task: DatTask{Name: "All.dat", Mode: ModeAll}, want: []string{"APPLE", "CN", "GOOGLE"}},
{name: "allowlist", task: DatTask{Name: "allow.dat", Mode: ModeAllowlist, Lists: []string{"google", "cn", "CN"}}, want: []string{"CN", "GOOGLE"}},
{name: "denylist", task: DatTask{Name: "deny.dat", Mode: ModeDenylist, Lists: []string{"cn", "missing"}}, want: []string{"APPLE", "GOOGLE"}},
{name: "denylist without valid list", task: DatTask{Name: "nodeny.dat", Mode: ModeDenylist, Lists: []string{"missing"}}, want: []string{"APPLE", "CN", "GOOGLE"}},
{name: "allowlist with missing list", task: DatTask{Name: "missing.dat", Mode: ModeAllowlist, Lists: []string{"missing"}}, wantErr: true},
{name: "allowlist without list", task: DatTask{Name: "none.dat", Mode: ModeAllowlist}, wantErr: true},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
err := gs.assembleDat(tc.task)
if tc.wantErr {
if err == nil {
t.Fatalf("assembleDat(%+v) = nil, want error", tc.task)
}
return
}
if err != nil {
t.Fatalf("assembleDat(%+v) got unexpected error: %v", tc.task, err)
}
got := readDatSites(t, filepath.Join(outPath, strings.ToLower(tc.task.Name)))
if !slices.Equal(got, tc.want) {
t.Errorf("assembleDat(%+v) = %v, want %v", tc.task, got, tc.want)
}
})
}
}
func TestAssembleDatErrors(t *testing.T) {
outPath := t.TempDir()
setFlag(t, outputDir, outPath)
// A directory occupying the output path makes writing the dat file fail
if err := os.Mkdir(filepath.Join(outPath, "blocked.dat"), 0755); err != nil {
t.Fatalf("failed to create blocking directory: %v", err)
}
gs := newTestGeoSites("CN")
if err := gs.assembleDat(DatTask{Name: "Blocked.dat", Mode: ModeAll}); err == nil {
t.Error("assembleDat() = nil, want file writing error")
}
// Invalid UTF-8 in a proto3 string field makes marshaling fail
invalid := &GeoSites{Sites: []*router.GeoSite{{CountryCode: "\xff"}}}
if err := invalid.assembleDat(DatTask{Name: "invalid.dat", Mode: ModeAll}); err == nil {
t.Error("assembleDat() = nil, want marshaling error")
}
}
func TestWritePlainList(t *testing.T) {
outPath := t.TempDir()
setFlag(t, outputDir, outPath)
entries := []*Entry{{Plain: "domain:example.com"}, {Plain: "full:www.example.com:@ads"}}
if err := writePlainList("CN", entries); err != nil {
t.Fatalf("writePlainList(\"CN\") got unexpected error: %v", err)
}
got, err := os.ReadFile(filepath.Join(outPath, "cn.txt"))
if err != nil {
t.Fatalf("failed to read generated list: %v", err)
}
want := "domain:example.com\nfull:www.example.com:@ads\n"
if string(got) != want {
t.Errorf("writePlainList(\"CN\") wrote %q, want %q", got, want)
}
// A directory occupying the output path makes creating the list file fail
if err := os.Mkdir(filepath.Join(outPath, "blocked.txt"), 0755); err != nil {
t.Fatalf("failed to create blocking directory: %v", err)
}
if err := writePlainList("Blocked", entries); err == nil {
t.Error("writePlainList(\"Blocked\") = nil, want file creating error")
}
}
func TestRun(t *testing.T) {
dataPath := t.TempDir()
outPath := filepath.Join(t.TempDir(), "output") // Not existing yet
writeTestData(t, dataPath, map[string]string{
"cn": "# Chinese sites\ndomain:example.cn\nfull:www.example.cn @ads\nkeyword:examplecn\n",
"apple": "include:cn\ndomain:apple.com &icloud\n",
"icloud": "domain:icloud.com\n",
"empty": "# Nothing here\n",
})
setRunFlags(t, dataPath, outPath, "test.dat", "", "cn, ,missing,")
if err := run(); err != nil {
t.Fatalf("run() got unexpected error: %v", err)
}
got := readDatLists(t, filepath.Join(outPath, "test.dat"))
want := map[string][]string{
"APPLE": {"domain:apple.com", "domain:example.cn", "full:www.example.cn:@ads", "keyword:examplecn"},
"CN": {"domain:example.cn", "full:www.example.cn:@ads", "keyword:examplecn"},
"ICLOUD": {"domain:apple.com", "domain:icloud.com"},
}
if len(got) != len(want) {
t.Fatalf("run() generated lists %v, want %v", got, want)
}
for name, wantRules := range want {
if !slices.Equal(got[name], wantRules) {
t.Errorf("run() list %q = %v, want %v", name, got[name], wantRules)
}
}
plain, err := os.ReadFile(filepath.Join(outPath, "cn.txt"))
if err != nil {
t.Fatalf("failed to read exported list: %v", err)
}
wantPlain := "domain:example.cn\nfull:www.example.cn:@ads\nkeyword:examplecn\n"
if string(plain) != wantPlain {
t.Errorf("run() exported list = %q, want %q", plain, wantPlain)
}
}
func TestRunWithDatProfile(t *testing.T) {
dataPath := t.TempDir()
outPath := t.TempDir()
writeTestData(t, dataPath, map[string]string{
"cn": "domain:example.cn\n",
"google": "domain:google.com\n",
})
profile := filepath.Join(t.TempDir(), "profile.json")
if err := os.WriteFile(profile, []byte(`[{"name":"CN.dat","mode":"allowlist","lists":["cn"]}]`), 0644); err != nil {
t.Fatalf("failed to write test profile: %v", err)
}
setRunFlags(t, dataPath, outPath, "dlc.dat", profile, "")
if err := run(); err != nil {
t.Fatalf("run() got unexpected error: %v", err)
}
if got, want := readDatSites(t, filepath.Join(outPath, "cn.dat")), []string{"CN"}; !slices.Equal(got, want) {
t.Errorf("run() generated dat = %v, want %v", got, want)
}
// Only the dat files defined by the profile are generated
if _, err := os.Stat(filepath.Join(outPath, "dlc.dat")); !os.IsNotExist(err) {
t.Errorf("run() generated %q, want it not to exist", "dlc.dat")
}
}
func TestRunErrors(t *testing.T) {
t.Run("missing data directory", func(t *testing.T) {
setRunFlags(t, filepath.Join(t.TempDir(), "missing"), t.TempDir(), "dlc.dat", "", "")
if err := run(); err == nil {
t.Error("run() = nil, want data directory error")
}
})
t.Run("invalid list name", func(t *testing.T) {
dataPath := t.TempDir()
writeTestData(t, dataPath, map[string]string{"invalid_name": "domain:example.com\n"})
setRunFlags(t, dataPath, t.TempDir(), "dlc.dat", "", "")
if err := run(); err == nil {
t.Error("run() = nil, want invalid list name error")
}
})
t.Run("invalid rule", func(t *testing.T) {
dataPath := t.TempDir()
writeTestData(t, dataPath, map[string]string{"cn": "domain:exa_mple.cn\n"})
setRunFlags(t, dataPath, t.TempDir(), "dlc.dat", "", "")
if err := run(); err == nil {
t.Error("run() = nil, want invalid rule error")
}
})
t.Run("circular inclusion", func(t *testing.T) {
dataPath := t.TempDir()
writeTestData(t, dataPath, map[string]string{
"first": "include:second\n",
"second": "include:first\n",
})
setRunFlags(t, dataPath, t.TempDir(), "dlc.dat", "", "")
if err := run(); err == nil {
t.Error("run() = nil, want circular inclusion error")
}
})
t.Run("invalid output directory", func(t *testing.T) {
dataPath := t.TempDir()
writeTestData(t, dataPath, map[string]string{"cn": "domain:example.cn\n"})
outPath := t.TempDir()
blocking := filepath.Join(outPath, "blocking")
if err := os.WriteFile(blocking, nil, 0644); err != nil {
t.Fatalf("failed to create blocking file: %v", err)
}
setRunFlags(t, dataPath, filepath.Join(blocking, "output"), "dlc.dat", "", "")
if err := run(); err == nil {
t.Error("run() = nil, want output directory error")
}
})
t.Run("missing dat profile", func(t *testing.T) {
dataPath := t.TempDir()
writeTestData(t, dataPath, map[string]string{"cn": "domain:example.cn\n"})
setRunFlags(t, dataPath, t.TempDir(), "dlc.dat", filepath.Join(t.TempDir(), "missing.json"), "")
if err := run(); err == nil {
t.Error("run() = nil, want dat profile error")
}
})
t.Run("failed plaintext export", func(t *testing.T) {
dataPath := t.TempDir()
writeTestData(t, dataPath, map[string]string{"cn": "domain:example.cn\n"})
outPath := t.TempDir()
if err := os.Mkdir(filepath.Join(outPath, "cn.txt"), 0755); err != nil {
t.Fatalf("failed to create blocking directory: %v", err)
}
setRunFlags(t, dataPath, outPath, "dlc.dat", "", "cn")
if err := run(); err == nil {
t.Error("run() = nil, want plaintext export error")
}
})
t.Run("failed dat task", func(t *testing.T) {
dataPath := t.TempDir()
writeTestData(t, dataPath, map[string]string{"cn": "domain:example.cn\n"})
profile := filepath.Join(t.TempDir(), "profile.json")
if err := os.WriteFile(profile, []byte(`[{"name":"none.dat","mode":"allowlist","lists":["missing"]}]`), 0644); err != nil {
t.Fatalf("failed to write test profile: %v", err)
}
setRunFlags(t, dataPath, t.TempDir(), "dlc.dat", profile, "")
if err := run(); err == nil {
t.Error("run() = nil, want dat task error")
}
})
}
func TestMainGeneratesDat(t *testing.T) {
dataPath := t.TempDir()
outPath := t.TempDir()
writeTestData(t, dataPath, map[string]string{"cn": "domain:example.cn\n"})
setRunFlags(t, dataPath, outPath, "dlc.dat", "", "")
oldArgs := os.Args
t.Cleanup(func() { os.Args = oldArgs })
os.Args = []string{"domain-list-community", "--datapath=" + dataPath, "--outputdir=" + outPath, "--outputname=main.dat"}
main()
if got, want := readDatSites(t, filepath.Join(outPath, "main.dat")), []string{"CN"}; !slices.Equal(got, want) {
t.Errorf("main() generated dat = %v, want %v", got, want)
}
}
// TestMainExitsOnError re-executes the test binary, because main() terminates
// the process when the generation fails.
func TestMainExitsOnError(t *testing.T) {
if os.Getenv(mainExitEnv) == "1" {
os.Args = []string{"domain-list-community", "--datapath=" + filepath.Join(t.TempDir(), "missing")}
main()
return
}
cmd := exec.Command(os.Args[0], "-test.run=^TestMainExitsOnError$")
cmd.Env = append(os.Environ(), mainExitEnv+"=1")
out, err := cmd.CombinedOutput()
var exitErr *exec.ExitError
if !errors.As(err, &exitErr) || exitErr.ExitCode() != 1 {
t.Fatalf("main() exited with %v, want exit status 1, output:\n%s", err, out)
}
if !strings.Contains(string(out), "[Fatal]") {
t.Errorf("main() output = %q, want it to report a fatal error", out)
}
}
// setFlag overrides a command line flag for the duration of the test.
func setFlag(t *testing.T, flagValue *string, value string) {
t.Helper()
old := *flagValue
*flagValue = value
t.Cleanup(func() { *flagValue = old })
}
func setRunFlags(t *testing.T, data, output, name, profile, exports string) {
t.Helper()
setFlag(t, dataPath, data)
setFlag(t, outputDir, output)
setFlag(t, outputName, name)
setFlag(t, datProfile, profile)
setFlag(t, exportLists, exports)
}
func writeTestData(t *testing.T, dataPath string, files map[string]string) {
t.Helper()
for name, content := range files {
if err := os.WriteFile(filepath.Join(dataPath, name), []byte(content), 0644); err != nil {
t.Fatalf("failed to write test data %q: %v", name, err)
}
}
}
func newTestGeoSites(names ...string) *GeoSites {
gs := &GeoSites{
Sites: make([]*router.GeoSite, 0, len(names)),
SiteIdx: make(map[string]int, len(names)),
}
for i, name := range names {
gs.Sites = append(gs.Sites, &router.GeoSite{
CountryCode: name,
Domain: []*router.Domain{{Type: router.Domain_RootDomain, Value: strings.ToLower(name) + ".com"}},
})
gs.SiteIdx[name] = i
}
return gs
}
func readDatSites(t *testing.T, path string) []string {
t.Helper()
lists := readDatLists(t, path)
names := make([]string, 0, len(lists))
for name := range lists {
names = append(names, name)
}
slices.Sort(names)
return names
}
func readDatLists(t *testing.T, path string) map[string][]string {
t.Helper()
data, err := os.ReadFile(path)
if err != nil {
t.Fatalf("failed to read generated dat: %v", err)
}
geoSiteList := new(router.GeoSiteList)
if err := proto.Unmarshal(data, geoSiteList); err != nil {
t.Fatalf("failed to unmarshal generated dat: %v", err)
}
lists := make(map[string][]string, len(geoSiteList.Entry))
for _, site := range geoSiteList.Entry {
rules := make([]string, 0, len(site.Domain))
for _, pdomain := range site.Domain {
rule := pdomain.Value
for i, attr := range pdomain.Attribute {
if i == 0 {
rule += ":"
} else {
rule += ","
}
rule += "@" + attr.Key
}
switch pdomain.Type {
case router.Domain_RootDomain:
rule = dlc.RuleTypeDomain + ":" + rule
case router.Domain_Full:
rule = dlc.RuleTypeFullDomain + ":" + rule
case router.Domain_Plain:
rule = dlc.RuleTypeKeyword + ":" + rule
case router.Domain_Regex:
rule = dlc.RuleTypeRegexp + ":" + rule
}
rules = append(rules, rule)
}
lists[site.CountryCode] = rules
}
return lists
}
func assertList(t *testing.T, p *Processor, name string, want []string) {
t.Helper()
pl, exist := p.parsedListByName[name]