SPB Git forge
15commits 1branches 0releases
29.7 MBsize
maindefault branch
10 days agolast push
TypeScript 36.3% Python 31.8% Go 18% JavaScript 9.8% Shell 1.9% SQL 1.4% CSS 0.5%
3.3 KB · 106 lines go
Raw Blame History
1package dns23import (4	"context"5	"errors"6	"net"7	"testing"8	"time"910	mdns "github.com/miekg/dns"1112	"internetpressure.io/probe-agent/internal/protocol"13)1415type timeoutErr struct{}1617func (timeoutErr) Error() string   { return "i/o timeout" }18func (timeoutErr) Timeout() bool   { return true }19func (timeoutErr) Temporary() bool { return true }2021func TestClassify(t *testing.T) {22	cases := []struct {23		err   error24		rcode string25		want  string26	}{27		{nil, "TIMEOUT", protocol.ErrDNSTimeout},28		{nil, "SERVFAIL", protocol.ErrDNSServfail},29		{nil, "NXDOMAIN", protocol.ErrDNSNxdomain},30		{nil, "REFUSED", protocol.ErrDNSFail},31		{timeoutErr{}, "ERROR", protocol.ErrDNSTimeout},32		{context.DeadlineExceeded, "", protocol.ErrDNSTimeout},33		{errors.New("boom"), "ERROR", protocol.ErrDNSFail},34	}35	for _, c := range cases {36		if got := classify(c.err, c.rcode); got != c.want {37			t.Errorf("classify(%v,%q)=%q want %q", c.err, c.rcode, got, c.want)38		}39	}40}4142// A tiny in-process authoritative server answers example.test with two A records and NXDOMAIN otherwise.43func startServer(t *testing.T) string {44	pc, err := net.ListenPacket("udp", "127.0.0.1:0")45	if err != nil {46		t.Fatal(err)47	}48	srv := &mdns.Server{PacketConn: pc, Handler: mdns.HandlerFunc(func(w mdns.ResponseWriter, r *mdns.Msg) {49		m := new(mdns.Msg)50		m.SetReply(r)51		switch r.Question[0].Name {52		case "example.test.":53			m.Answer = append(m.Answer,54				&mdns.A{Hdr: mdns.RR_Header{Name: "example.test.", Rrtype: mdns.TypeA, Class: mdns.ClassINET, Ttl: 60}, A: net.ParseIP("10.0.0.2")},55				&mdns.A{Hdr: mdns.RR_Header{Name: "example.test.", Rrtype: mdns.TypeA, Class: mdns.ClassINET, Ttl: 60}, A: net.ParseIP("10.0.0.1")})56		case "fail.test.":57			m.Rcode = mdns.RcodeServerFailure58		case "slow.test.":59			return // never answers → timeout60		default:61			m.Rcode = mdns.RcodeNameError62		}63		_ = w.WriteMsg(m)64	})}65	go srv.ActivateAndServe()66	t.Cleanup(func() { srv.Shutdown() })67	return pc.LocalAddr().String()68}6970func TestQueryServer(t *testing.T) {71	addr := startServer(t)72	c := &Checker{}73	res := []protocol.Resolver{{ID: "local", Address: addr}}7475	ms := c.Run(context.Background(), protocol.Target{TargetID: "t", Hostname: "example.test"}, res)76	if len(ms) != 1 {77		t.Fatalf("expected 1 measurement, got %d", len(ms))78	}79	m := ms[0]80	if !m.OK || m.Error != "" || m.DNSRcode != "NOERROR" || m.Resolver != "local" || m.Kind != "dns" {81		t.Fatalf("unexpected: %+v", m)82	}83	if len(m.DNSAnswers) != 2 || m.DNSAnswers[0] != "10.0.0.1" || m.DNSAnswers[1] != "10.0.0.2" {84		t.Fatalf("answers not sorted: %v", m.DNSAnswers)85	}86	if m.DNSMs == nil || *m.DNSMs < 0 {87		t.Fatalf("dns_ms missing")88	}8990	m = c.Run(context.Background(), protocol.Target{TargetID: "t", Hostname: "nope.test"}, res)[0]91	if m.OK || m.Error != protocol.ErrDNSNxdomain || m.DNSRcode != "NXDOMAIN" {92		t.Fatalf("nxdomain: %+v", m)93	}94	m = c.Run(context.Background(), protocol.Target{TargetID: "t", Hostname: "fail.test"}, res)[0]95	if m.OK || m.Error != protocol.ErrDNSServfail || m.DNSRcode != "SERVFAIL" {96		t.Fatalf("servfail: %+v", m)97	}9899	ctx, cancel := context.WithTimeout(context.Background(), 700*time.Millisecond)100	defer cancel()101	m = c.Run(ctx, protocol.Target{TargetID: "t", Hostname: "slow.test"}, res)[0]102	if m.OK || m.Error != protocol.ErrDNSTimeout || m.DNSRcode != "TIMEOUT" {103		t.Fatalf("timeout: %+v", m)104	}105}106