feat: refactor dns implementation in measurexlite (#857)
* refactor: remove query-based mapping and introducing resolver wrapper * refactor dnsping to adapt to measurexlite * dnsping: extra comments * Apply suggestions from code review * Update internal/measurexlite/dns_test.go See https://github.com/ooni/probe/issues/2208 Co-authored-by: decfox <decfox@github.com> Co-authored-by: Simone Basso <bassosimone@gmail.com>
This commit is contained in:
parent
576b52b1e3
commit
fc51590a67
5 changed files with 172 additions and 220 deletions
|
|
@ -13,17 +13,11 @@ import (
|
|||
)
|
||||
|
||||
func TestNewUnwrappedParallelResolver(t *testing.T) {
|
||||
t.Run("NewUnwrappedParallelResolver creates an UnwrappedParallelResolver with Trace", func(t *testing.T) {
|
||||
t.Run("WrapResolver creates a wrapped resolver with Trace", func(t *testing.T) {
|
||||
underlying := &mocks.Resolver{}
|
||||
zeroTime := time.Now()
|
||||
trace := NewTrace(0, zeroTime)
|
||||
trace.NewParallelResolverFn = func() model.Resolver {
|
||||
return underlying
|
||||
}
|
||||
resolver := trace.newParallelResolverTrace(func() model.Resolver {
|
||||
return nil
|
||||
})
|
||||
resolvert := resolver.(*resolverTrace)
|
||||
resolvert := trace.wrapResolver(underlying).(*resolverTrace)
|
||||
if resolvert.r != underlying {
|
||||
t.Fatal("invalid parallel resolver")
|
||||
}
|
||||
|
|
@ -36,20 +30,18 @@ func TestNewUnwrappedParallelResolver(t *testing.T) {
|
|||
var called bool
|
||||
zeroTime := time.Now()
|
||||
trace := NewTrace(0, zeroTime)
|
||||
newMockResolver := func() model.Resolver {
|
||||
return &mocks.Resolver{
|
||||
MockAddress: func() string {
|
||||
return "dns.google"
|
||||
},
|
||||
MockNetwork: func() string {
|
||||
return "udp"
|
||||
},
|
||||
MockCloseIdleConnections: func() {
|
||||
called = true
|
||||
},
|
||||
}
|
||||
mockResolver := &mocks.Resolver{
|
||||
MockAddress: func() string {
|
||||
return "dns.google"
|
||||
},
|
||||
MockNetwork: func() string {
|
||||
return "udp"
|
||||
},
|
||||
MockCloseIdleConnections: func() {
|
||||
called = true
|
||||
},
|
||||
}
|
||||
resolver := trace.newParallelResolver(newMockResolver)
|
||||
resolver := trace.wrapResolver(mockResolver)
|
||||
|
||||
t.Run("Address is correctly forwarded", func(t *testing.T) {
|
||||
got := resolver.Address()
|
||||
|
|
@ -94,16 +86,14 @@ func TestNewUnwrappedParallelResolver(t *testing.T) {
|
|||
return true
|
||||
},
|
||||
MockNetwork: func() string {
|
||||
return ""
|
||||
return "mocked"
|
||||
},
|
||||
MockAddress: func() string {
|
||||
return "dns.google"
|
||||
},
|
||||
}
|
||||
newResolver := func() model.Resolver {
|
||||
return netxlite.NewUnwrappedParallelResolver(txp)
|
||||
}
|
||||
resolver := trace.newParallelResolverTrace(newResolver)
|
||||
r := netxlite.NewUnwrappedParallelResolver(txp)
|
||||
resolver := trace.wrapResolver(r)
|
||||
ctx := context.Background()
|
||||
addrs, err := resolver.LookupHost(ctx, "example.com")
|
||||
if err != nil {
|
||||
|
|
@ -119,45 +109,27 @@ func TestNewUnwrappedParallelResolver(t *testing.T) {
|
|||
t.Fatal("unexpected array output", addrs)
|
||||
}
|
||||
|
||||
t.Run("DNSLookups QueryType A", func(t *testing.T) {
|
||||
events := trace.DNSLookupsFromRoundTrip(dns.TypeA)
|
||||
if len(events) != 1 {
|
||||
t.Fatal("expected to see single DNSLookup event")
|
||||
t.Run("DNSLookup events", func(t *testing.T) {
|
||||
events := trace.DNSLookupsFromRoundTrip()
|
||||
if len(events) != 2 {
|
||||
t.Fatal("unexpected DNS events")
|
||||
}
|
||||
lookup := events[0]
|
||||
answers := lookup.Answers
|
||||
if lookup.Failure != nil {
|
||||
t.Fatal("unexpected err", *(lookup.Failure))
|
||||
}
|
||||
if lookup.ResolverAddress != "dns.google" {
|
||||
t.Fatal("unexpected address field")
|
||||
}
|
||||
if len(answers) != 1 {
|
||||
t.Fatal("expected 1 DNS answer, got", len(answers))
|
||||
}
|
||||
if answers[0].AnswerType != "A" || answers[0].IPv4 != "1.1.1.1" {
|
||||
t.Fatal("unexpected DNS answer", answers)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("DNSLookups QueryType AAAA", func(t *testing.T) {
|
||||
events := trace.DNSLookupsFromRoundTrip(dns.TypeAAAA)
|
||||
if len(events) != 1 {
|
||||
t.Fatal("expected to see single DNSLookup event")
|
||||
}
|
||||
lookup := events[0]
|
||||
answers := lookup.Answers
|
||||
if lookup.Failure != nil {
|
||||
t.Fatal("unexpected err", *(lookup.Failure))
|
||||
}
|
||||
if lookup.ResolverAddress != "dns.google" {
|
||||
t.Fatal("unexpected address field")
|
||||
}
|
||||
if len(answers) != 1 {
|
||||
t.Fatal("expected 1 DNS answer, got", len(answers))
|
||||
}
|
||||
if answers[0].AnswerType != "AAAA" || answers[0].IPv6 != "fe80::a00:20ff:feb9:4c54" {
|
||||
t.Fatal("unexpected DNS answer", answers)
|
||||
for _, ev := range events {
|
||||
if ev.ResolverAddress != "dns.google" {
|
||||
t.Fatal("unexpected resolver address")
|
||||
}
|
||||
if ev.Engine != "mocked" {
|
||||
t.Fatal("unexpected engine")
|
||||
}
|
||||
if len(ev.Answers) != 1 {
|
||||
t.Fatal("expected single answer in DNSLookup event")
|
||||
}
|
||||
if ev.QueryType == "A" && ev.Answers[0].IPv4 != "1.1.1.1" {
|
||||
t.Fatal("unexpected A query result")
|
||||
}
|
||||
if ev.QueryType == "AAAA" && ev.Answers[0].IPv6 != "fe80::a00:20ff:feb9:4c54" {
|
||||
t.Fatal("unexpected AAAA query result")
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
@ -166,10 +138,7 @@ func TestNewUnwrappedParallelResolver(t *testing.T) {
|
|||
zeroTime := time.Now()
|
||||
td := testingx.NewTimeDeterministic(zeroTime)
|
||||
trace := NewTrace(0, zeroTime)
|
||||
trace.DNSLookup = map[uint16]chan *model.ArchivalDNSLookupResult{
|
||||
dns.TypeA: make(chan *model.ArchivalDNSLookupResult), // no buffer
|
||||
dns.TypeAAAA: make(chan *model.ArchivalDNSLookupResult), // no buffer
|
||||
}
|
||||
trace.DNSLookup = make(chan *model.ArchivalDNSLookupResult) // no buffer
|
||||
trace.TimeNowFn = td.Now
|
||||
txp := &mocks.DNSTransport{
|
||||
MockRoundTrip: func(ctx context.Context, query model.DNSQuery) (model.DNSResponse, error) {
|
||||
|
|
@ -193,10 +162,8 @@ func TestNewUnwrappedParallelResolver(t *testing.T) {
|
|||
return "dns.google"
|
||||
},
|
||||
}
|
||||
newResolver := func() model.Resolver {
|
||||
return netxlite.NewUnwrappedParallelResolver(txp)
|
||||
}
|
||||
resolver := trace.newParallelResolverTrace(newResolver)
|
||||
r := netxlite.NewUnwrappedParallelResolver(txp)
|
||||
resolver := trace.wrapResolver(r)
|
||||
ctx := context.Background()
|
||||
addrs, err := resolver.LookupHost(ctx, "example.com")
|
||||
if err != nil {
|
||||
|
|
@ -205,17 +172,17 @@ func TestNewUnwrappedParallelResolver(t *testing.T) {
|
|||
if len(addrs) != 2 {
|
||||
t.Fatal("unexpected array output", addrs)
|
||||
}
|
||||
if addrs[0] != "1.1.1.1" && addrs[1] != "1.1.1.1" {
|
||||
t.Fatal("unexpected array output", addrs)
|
||||
}
|
||||
if addrs[0] != "fe80::a00:20ff:feb9:4c54" && addrs[1] != "fe80::a00:20ff:feb9:4c54" {
|
||||
t.Fatal("unexpected array output", addrs)
|
||||
}
|
||||
|
||||
t.Run("DNSLookups QueryType A", func(t *testing.T) {
|
||||
events := trace.DNSLookupsFromRoundTrip(dns.TypeA)
|
||||
t.Run("DNSLookup Events", func(t *testing.T) {
|
||||
events := trace.DNSLookupsFromRoundTrip()
|
||||
if len(events) != 0 {
|
||||
t.Fatal("expected to see no DNSLookup")
|
||||
}
|
||||
})
|
||||
t.Run("DNSLookups QueryType AAAA", func(t *testing.T) {
|
||||
events := trace.DNSLookupsFromRoundTrip(dns.TypeAAAA)
|
||||
if len(events) != 0 {
|
||||
t.Fatal("expected to see no DNSLookup")
|
||||
t.Fatal("expected to see no DNSLookup events")
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
@ -271,26 +238,3 @@ func TestAnswersFromAddrs(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDNSLookupsFromRoundTrips(t *testing.T) {
|
||||
zeroTime := time.Now()
|
||||
trace := NewTrace(0, zeroTime)
|
||||
checkPanic := func(query uint16, f func(uint16) []*model.ArchivalDNSLookupResult) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
t.Fatal("unexpected panic encoutered")
|
||||
}
|
||||
}()
|
||||
f(query)
|
||||
}
|
||||
t.Run("DNSLookup is nil", func(t *testing.T) {
|
||||
trace.DNSLookup = nil
|
||||
checkPanic(dns.TypeA, trace.DNSLookupsFromRoundTrip)
|
||||
})
|
||||
t.Run("Query has nil channel", func(t *testing.T) {
|
||||
trace.DNSLookup = map[uint16]chan *model.ArchivalDNSLookupResult{
|
||||
dns.TypeA: nil,
|
||||
}
|
||||
checkPanic(dns.TypeA, trace.DNSLookupsFromRoundTrip)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue