package engine import ( "context" "net" "testing" "time" "git.k8s-git-k6n.net/mats/fancy-dns/internal/config" "github.com/miekg/dns" ) func TestQueryDeadlineAcrossFailoverAndReload(t *testing.T) { var servers []config.UpstreamServer for i := 0; i < 3; i++ { pc, err := net.ListenPacket("udp", "127.0.0.1:0") if err != nil { t.Fatal(err) } t.Cleanup(func() { _ = pc.Close() }) servers = append(servers, config.UpstreamServer{Addr: pc.LocalAddr().String(), Proto: "udp"}) } h := newHarness(t, hopt{upstreams: servers, timeout: 100 * time.Millisecond, server: func(s *config.Server) { s.Timeouts.Query = config.Duration(150 * time.Millisecond) }}) cfg := h.pool.Config() cfg.Policy = "failover" cfg.MaxAttempts = 3 h.pool.Rebind(cfg) for _, tc := range []struct { name string query, caller, limit time.Duration }{ {"configured", 150 * time.Millisecond, time.Second, 250 * time.Millisecond}, {"reload", 40 * time.Millisecond, time.Second, 90 * time.Millisecond}, {"earlier-caller", time.Second, 30 * time.Millisecond, 90 * time.Millisecond}, } { t.Run(tc.name, func(t *testing.T) { next := *h.cfg next.Server.Timeouts.Query = config.Duration(tc.query) if err := h.store.Swap(&next); err != nil { t.Fatal(err) } ctx, cancel := context.WithTimeout(context.Background(), tc.caller) defer cancel() start := time.Now() res := h.eng.Handle(ctx, h.request(tc.name+".test.", dns.TypeA)) requireRcode(t, res, dns.RcodeServerFailure) if elapsed := time.Since(start); elapsed > tc.limit { t.Fatalf("query took %v, limit %v", elapsed, tc.limit) } }) } }