package hostparse import ( "reflect" "testing" ) func TestParse(t *testing.T) { tests := []struct { name string rule string hosts []string wildcards []string invalid int regexp int }{ {"single", "Host(`app.example.com`)", []string{"app.example.com"}, nil, 0, 0}, {"multi args v3", "Host(`a.example.com`, `b.example.com`)", []string{"a.example.com", "b.example.com"}, nil, 0, 0}, {"or", "Host(`a.example.com`) || Host(`b.example.com`)", []string{"a.example.com", "b.example.com"}, nil, 0, 0}, {"with path and", "Host(`a.example.com`) && PathPrefix(`/api`)", []string{"a.example.com"}, nil, 0, 0}, {"double quotes", `Host("a.example.com")`, []string{"a.example.com"}, nil, 0, 0}, {"spaces", " Host ( `A.Example.COM.` ) ", []string{"a.example.com"}, nil, 0, 0}, {"dedupe", "Host(`a.example.com`) || Host(`a.example.com`)", []string{"a.example.com"}, nil, 0, 0}, {"regexp ignored", "HostRegexp(`^.+\\.example\\.com$`)", nil, nil, 0, 1}, {"regexp and host", "Host(`a.example.com`) || HostRegexp(`{sub:.+}.example.com`)", []string{"a.example.com"}, nil, 0, 1}, {"wildcard", "Host(`*.example.com`)", nil, []string{"*.example.com"}, 0, 0}, {"negated host", "!Host(`a.example.com`) && Host(`b.example.com`)", []string{"b.example.com"}, nil, 0, 0}, {"negated group", "!(Host(`a.example.com`) || Host(`c.example.com`)) && Host(`b.example.com`)", []string{"b.example.com"}, nil, 0, 0}, {"group positive", "(Host(`a.example.com`) || Host(`b.example.com`)) && Path(`/x`)", []string{"a.example.com", "b.example.com"}, nil, 0, 0}, {"host inside other string", "PathPrefix(`/Host(`)", nil, nil, 0, 0}, {"hostsni not host", "HostSNI(`a.example.com`)", nil, nil, 0, 0}, {"invalid", "Host(`bad host`, `-x.example.com`, `ünï.example.com`)", nil, nil, 3, 0}, {"empty", "", nil, nil, 0, 0}, {"api internal", "PathPrefix(`/api`) || PathPrefix(`/dashboard`)", nil, nil, 0, 0}, {"unterminated", "Host(`a.example.com", []string{"a.example.com"}, nil, 0, 0}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { got := Parse(tc.rule) if !reflect.DeepEqual(got.Hosts, tc.hosts) { t.Errorf("hosts = %v, want %v", got.Hosts, tc.hosts) } if !reflect.DeepEqual(got.Wildcards, tc.wildcards) { t.Errorf("wildcards = %v, want %v", got.Wildcards, tc.wildcards) } if len(got.Invalid) != tc.invalid { t.Errorf("invalid = %v, want %d", got.Invalid, tc.invalid) } if got.RegexpCount != tc.regexp { t.Errorf("regexp = %d, want %d", got.RegexpCount, tc.regexp) } }) } } func TestMatchZone(t *testing.T) { zones := []string{"example.com", "dev.example.com", "other.org"} tests := []struct { host, zone string ok bool }{ {"example.com", "example.com", true}, {"app.example.com", "example.com", true}, {"a.b.example.com", "example.com", true}, {"app.dev.example.com", "dev.example.com", true}, {"dev.example.com", "dev.example.com", true}, {"badexample.com", "", false}, {"example.com.evil.net", "", false}, {"x.other.org", "other.org", true}, {"unknown.net", "", false}, } for _, tc := range tests { z, ok := MatchZone(tc.host, zones) if z != tc.zone || ok != tc.ok { t.Errorf("MatchZone(%q) = %q,%v want %q,%v", tc.host, z, ok, tc.zone, tc.ok) } } }