feat(netxlite): implements NS queries (#734)

This diff has been extracted from https://github.com/bassosimone/websteps-illustrated/commit/eb0bf38957e79fbad198fcdc9f9c7b36f61a8e2c.

See https://github.com/ooni/probe/issues/2096.

While there, skip the broken tests caused by issue
https://github.com/ooni/probe/issues/2098.
This commit is contained in:
Simone Basso
2022-05-16 10:46:53 +02:00
committed by GitHub
parent c1b06a2d09
commit ce052b665e
26 changed files with 857 additions and 73 deletions
+1 -1
View File
@@ -25,7 +25,7 @@ func (r *CacheResolver) LookupHost(
if err != nil {
return nil, err
}
if r.ReadOnly == false {
if !r.ReadOnly {
r.Set(hostname, entry)
}
return entry, nil
+5 -13
View File
@@ -6,14 +6,11 @@ import (
"testing"
"github.com/ooni/probe-cli/v3/internal/engine/netx/resolver"
"github.com/ooni/probe-cli/v3/internal/model"
)
func TestCacheFailure(t *testing.T) {
expected := errors.New("mocked error")
var r model.Resolver = resolver.FakeResolver{
Err: expected,
}
r := resolver.NewFakeResolverWithExplicitError(expected)
cache := &resolver.CacheResolver{Resolver: r}
addrs, err := cache.LookupHost(context.Background(), "www.google.com")
if !errors.Is(err, expected) {
@@ -28,9 +25,8 @@ func TestCacheFailure(t *testing.T) {
}
func TestCacheHitSuccess(t *testing.T) {
var r model.Resolver = resolver.FakeResolver{
Err: errors.New("mocked error"),
}
expected := errors.New("mocked error")
r := resolver.NewFakeResolverWithExplicitError(expected)
cache := &resolver.CacheResolver{Resolver: r}
cache.Set("dns.google.com", []string{"8.8.8.8"})
addrs, err := cache.LookupHost(context.Background(), "dns.google.com")
@@ -43,9 +39,7 @@ func TestCacheHitSuccess(t *testing.T) {
}
func TestCacheMissSuccess(t *testing.T) {
var r model.Resolver = resolver.FakeResolver{
Result: []string{"8.8.8.8"},
}
r := resolver.NewFakeResolverWithResult([]string{"8.8.8.8"})
cache := &resolver.CacheResolver{Resolver: r}
addrs, err := cache.LookupHost(context.Background(), "dns.google.com")
if err != nil {
@@ -60,9 +54,7 @@ func TestCacheMissSuccess(t *testing.T) {
}
func TestCacheReadonlySuccess(t *testing.T) {
var r model.Resolver = resolver.FakeResolver{
Result: []string{"8.8.8.8"},
}
r := resolver.NewFakeResolverWithResult([]string{"8.8.8.8"})
cache := &resolver.CacheResolver{Resolver: r, ReadOnly: true}
addrs, err := cache.LookupHost(context.Background(), "dns.google.com")
if err != nil {
+47 -40
View File
@@ -7,8 +7,10 @@ import (
"net"
"time"
"github.com/ooni/probe-cli/v3/internal/atomicx"
"github.com/ooni/probe-cli/v3/internal/model"
"github.com/ooni/probe-cli/v3/internal/model/mocks"
"github.com/ooni/probe-cli/v3/internal/netxlite"
"github.com/ooni/probe-cli/v3/internal/runtimex"
)
type FakeDialer struct {
@@ -108,48 +110,53 @@ func (fe FakeEncoder) Encode(domain string, qtype uint16, padding bool) ([]byte,
return fe.Data, fe.Err
}
type FakeResolver struct {
NumFailures *atomicx.Int64
Err error
Result []string
func NewFakeResolverThatFails() model.Resolver {
return NewFakeResolverWithExplicitError(netxlite.ErrOODNSNoSuchHost)
}
func NewFakeResolverThatFails() FakeResolver {
return FakeResolver{NumFailures: &atomicx.Int64{}, Err: errNotFound}
}
func NewFakeResolverWithResult(r []string) FakeResolver {
return FakeResolver{NumFailures: &atomicx.Int64{}, Result: r}
}
var errNotFound = &net.DNSError{
Err: "no such host",
}
func (c FakeResolver) LookupHost(ctx context.Context, hostname string) ([]string, error) {
time.Sleep(10 * time.Microsecond)
if c.Err != nil {
if c.NumFailures != nil {
c.NumFailures.Add(1)
}
return nil, c.Err
func NewFakeResolverWithExplicitError(err error) model.Resolver {
runtimex.PanicIfNil(err, "passed nil error")
return &mocks.Resolver{
MockLookupHost: func(ctx context.Context, domain string) ([]string, error) {
return nil, err
},
MockNetwork: func() string {
return "fake"
},
MockAddress: func() string {
return ""
},
MockCloseIdleConnections: func() {
// nothing
},
MockLookupHTTPS: func(ctx context.Context, domain string) (*model.HTTPSSvc, error) {
return nil, errors.New("not implemented")
},
MockLookupNS: func(ctx context.Context, domain string) ([]*net.NS, error) {
return nil, errors.New("not implemented")
},
}
return c.Result, nil
}
func (c FakeResolver) Network() string {
return "fake"
func NewFakeResolverWithResult(r []string) model.Resolver {
return &mocks.Resolver{
MockLookupHost: func(ctx context.Context, domain string) ([]string, error) {
return r, nil
},
MockNetwork: func() string {
return "fake"
},
MockAddress: func() string {
return ""
},
MockCloseIdleConnections: func() {
// nothing
},
MockLookupHTTPS: func(ctx context.Context, domain string) (*model.HTTPSSvc, error) {
return nil, errors.New("not implemented")
},
MockLookupNS: func(ctx context.Context, domain string) ([]*net.NS, error) {
return nil, errors.New("not implemented")
},
}
}
func (c FakeResolver) Address() string {
return ""
}
func (c FakeResolver) CloseIdleConnections() {}
func (c FakeResolver) LookupHTTPS(
ctx context.Context, domain string) (*model.HTTPSSvc, error) {
return nil, errors.New("not implemented")
}
var _ model.Resolver = FakeResolver{}
+4 -8
View File
@@ -16,10 +16,8 @@ func TestSaverResolverFailure(t *testing.T) {
expected := errors.New("no such host")
saver := &trace.Saver{}
reso := resolver.SaverResolver{
Resolver: resolver.FakeResolver{
Err: expected,
},
Saver: saver,
Resolver: resolver.NewFakeResolverWithExplicitError(expected),
Saver: saver,
}
addrs, err := reso.LookupHost(context.Background(), "www.google.com")
if !errors.Is(err, expected) {
@@ -65,10 +63,8 @@ func TestSaverResolverSuccess(t *testing.T) {
expected := []string{"8.8.8.8", "8.8.4.4"}
saver := &trace.Saver{}
reso := resolver.SaverResolver{
Resolver: resolver.FakeResolver{
Result: expected,
},
Saver: saver,
Resolver: resolver.NewFakeResolverWithResult(expected),
Saver: saver,
}
addrs, err := reso.LookupHost(context.Background(), "www.google.com")
if err != nil {