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:
DecFox 2022-08-11 19:30:37 +05:30 committed by GitHub
commit fc51590a67
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 172 additions and 220 deletions

View file

@ -46,9 +46,15 @@ func TestNewTrace(t *testing.T) {
}
})
t.Run("NewParallelResolverFn is nil", func(t *testing.T) {
if trace.NewParallelResolverFn != nil {
t.Fatal("expected nil NewUnwrappedParallelResolverFn")
t.Run("NewParallelUDPResolverFn is nil", func(t *testing.T) {
if trace.NewParallelUDPResolverFn != nil {
t.Fatal("expected nil NewParallelUDPResolverFn")
}
})
t.Run("NewParallelDNSOverHTTPSResolverFn is nil", func(t *testing.T) {
if trace.NewParallelDNSOverHTTPSResolverFn != nil {
t.Fatal("expected nil NewParallelDNSOverHTTPSResolverFn")
}
})
@ -66,23 +72,21 @@ func TestNewTrace(t *testing.T) {
t.Run("DNSLookup has the expected buffer size", func(t *testing.T) {
ff := &testingx.FakeFiller{}
for _, qtype := range DNSQueryTypes {
var count int
Loop:
for {
ev := &model.ArchivalDNSLookupResult{}
ff.Fill(ev)
select {
case trace.DNSLookup[qtype] <- ev:
count++
default:
break Loop
}
}
if count != DNSLookupBufferSize {
t.Fatal("invalid DNSLookup A channel buffer size")
var idx int
Loop:
for {
ev := &model.ArchivalDNSLookupResult{}
ff.Fill(ev)
select {
case trace.DNSLookup <- ev:
idx++
default:
break Loop
}
}
if idx != DNSLookupBufferSize {
t.Fatal("invalid DNSLookup channel buffer size")
}
})
t.Run("TCPConnect has the expected buffer size", func(t *testing.T) {
@ -138,11 +142,11 @@ func TestNewTrace(t *testing.T) {
}
func TestTrace(t *testing.T) {
t.Run("NewParallelResolverFn works as intended", func(t *testing.T) {
t.Run("NewParallelUDPResolverFn works as intended", func(t *testing.T) {
t.Run("when not nil", func(t *testing.T) {
mockedErr := errors.New("mocked")
tx := &Trace{
NewParallelResolverFn: func() model.Resolver {
NewParallelUDPResolverFn: func(logger model.Logger, dialer model.Dialer, address string) model.Resolver {
return &mocks.Resolver{
MockLookupHost: func(ctx context.Context, domain string) ([]string, error) {
return []string{}, mockedErr
@ -150,9 +154,8 @@ func TestTrace(t *testing.T) {
}
},
}
resolver := tx.newParallelResolver(func() model.Resolver {
return nil
})
dialer := &mocks.Dialer{}
resolver := tx.newParallelUDPResolver(model.DiscardLogger, dialer, "1.1.1.1:53")
ctx := context.Background()
addrs, err := resolver.LookupHost(ctx, "example.com")
if !errors.Is(err, mockedErr) {
@ -165,26 +168,58 @@ func TestTrace(t *testing.T) {
t.Run("when nil", func(t *testing.T) {
tx := &Trace{
NewParallelResolverFn: nil,
NewParallelUDPResolverFn: nil,
}
newResolver := func() model.Resolver {
return &mocks.Resolver{
MockLookupHost: func(ctx context.Context, domain string) ([]string, error) {
return []string{"1.1.1.1"}, nil
},
}
}
resolver := tx.newParallelResolver(newResolver)
ctx := context.Background()
dialer := netxlite.NewDialerWithoutResolver(model.DiscardLogger)
resolver := tx.newParallelUDPResolver(model.DiscardLogger, dialer, "1.1.1.1:53")
ctx, cancel := context.WithCancel(context.Background())
cancel()
addrs, err := resolver.LookupHost(ctx, "example.com")
if err != nil {
if err == nil || err.Error() != netxlite.FailureInterrupted {
t.Fatal("unexpected err", err)
}
if len(addrs) != 1 {
t.Fatal("expected array of size 1")
if len(addrs) != 0 {
t.Fatal("expected array of size 0")
}
if addrs[0] != "1.1.1.1" {
t.Fatal("unexpected array output", addrs)
})
})
t.Run("NewParallelDNSOverHTTPSResolverFn works as intended", func(t *testing.T) {
t.Run("when not nil", func(t *testing.T) {
mockedErr := errors.New("mocked")
tx := &Trace{
NewParallelDNSOverHTTPSResolverFn: func(logger model.Logger, URL string) model.Resolver {
return &mocks.Resolver{
MockLookupHost: func(ctx context.Context, domain string) ([]string, error) {
return []string{}, mockedErr
},
}
},
}
resolver := tx.newParallelDNSOverHTTPSResolver(model.DiscardLogger, "dns.google.com")
ctx := context.Background()
addrs, err := resolver.LookupHost(ctx, "example.com")
if !errors.Is(err, mockedErr) {
t.Fatal("unexpected err", err)
}
if len(addrs) != 0 {
t.Fatal("expected array of size 0")
}
})
t.Run("when nil", func(t *testing.T) {
tx := &Trace{
NewParallelDNSOverHTTPSResolverFn: nil,
}
resolver := tx.newParallelDNSOverHTTPSResolver(model.DiscardLogger, "https://dns.google.com")
ctx, cancel := context.WithCancel(context.Background())
cancel()
addrs, err := resolver.LookupHost(ctx, "example.com")
if err == nil || err.Error() != netxlite.FailureInterrupted {
t.Fatal("unexpected err", err)
}
if len(addrs) != 0 {
t.Fatal("expected array of size 0")
}
})
})