package routing import ( "sync" "testing" ) func TestRuleSetUsesFirstMatchingRule(t *testing.T) { rules, err := Compile([]Rule{ {Name: "specific", Match: Match{HostRegex: `(^|\.)jd\.com$`}, Upstreams: []string{"jd"}}, {Name: "default", Match: Match{HostRegex: `.*`}, Action: ActionReject}, }) if err != nil { t.Fatalf("Compile(): %v", err) } got, ok := rules.Match(Request{Host: "api.jd.com", Method: "GET", Path: "/"}) if !ok || got.Name != "specific" { t.Fatalf("Match() = %q, %v; want specific, true", got.Name, ok) } } func TestSequentialSwitchesOnceAtThreshold(t *testing.T) { sequence, err := NewSequential([]string{"a", "b", "c"}, 5) if err != nil { t.Fatalf("NewSequential(): %v", err) } for range 4 { sequence.ObserveEmpty("a") } if got := sequence.Current(); got != "a" { t.Fatalf("Current() = %q before threshold, want a", got) } var wg sync.WaitGroup for range 100 { wg.Add(1) go func() { defer wg.Done() sequence.ObserveEmpty("a") }() } wg.Wait() if got := sequence.Current(); got != "b" { t.Fatalf("Current() = %q after concurrent threshold, want b", got) } } func TestSequentialValidFetchResetsEmptyCount(t *testing.T) { sequence, _ := NewSequential([]string{"a", "b"}, 5) for range 4 { sequence.ObserveEmpty("a") } sequence.ObserveValid("a") for range 4 { sequence.ObserveEmpty("a") } if got := sequence.Current(); got != "a" { t.Fatalf("Current() = %q, want a after reset", got) } }