feat: clearly indicate which resolver we're using (#885)

See what we documented at https://github.com/ooni/spec/pull/257

Reference issue: https://github.com/ooni/probe/issues/2238

See also the related ooni/spec PR: https://github.com/ooni/spec/pull/257

See also https://github.com/ooni/probe/issues/2237

While there, bump webconnectivity@v0.5 version because this change
has an impact onto the generated data format.

The drop in coverage is unavoidable because we've written some
tests for `measurex` to ensure we deal with DNS resolvers and transport
names correctly depending on the splitting policy we use.

(However, `measurex` is only used for the `tor` experiment and, per
the step-by-step design document, new experiments should use
`measurexlite` instead, so this is hopefully fine(TM).)

While there, fix a broken integration test that does not run in `-short` mode.
This commit is contained in:
Simone Basso 2022-08-27 15:47:48 +02:00 committed by GitHub
parent c3964e43b3
commit 8a0c062844
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 362 additions and 59 deletions

View File

@ -29,7 +29,18 @@ func TestCreateAll(t *testing.T) {
exp := builder.NewExperiment() exp := builder.NewExperiment()
good := (exp.Name() == name) good := (exp.Name() == name)
if !good { if !good {
t.Fatal("unexpected experiment name") // We have introduced the concept of versioned experiments in
// https://github.com/ooni/probe-cli/pull/882. This works like
// in brew: we append @vX.Y to the experiment name. So, here
// we're stripping the version specification and retry.
index := strings.Index(name, "@")
if index >= 0 {
name = name[:index]
if good := (exp.Name() == name); good {
continue
}
}
t.Fatal("unexpected experiment name", exp.Name(), name)
} }
} }
} }

View File

@ -36,7 +36,7 @@ func (m *Measurer) ExperimentName() string {
// ExperimentVersion implements model.ExperimentMeasurer. // ExperimentVersion implements model.ExperimentMeasurer.
func (m *Measurer) ExperimentVersion() string { func (m *Measurer) ExperimentVersion() string {
return "0.5.1" return "0.5.2"
} }
// Run implements model.ExperimentMeasurer. // Run implements model.ExperimentMeasurer.

View File

@ -11,6 +11,7 @@ import (
"time" "time"
"github.com/ooni/probe-cli/v3/internal/model" "github.com/ooni/probe-cli/v3/internal/model"
"github.com/ooni/probe-cli/v3/internal/tracex"
) )
// WrapDNSXRoundTripper creates a new DNSXRoundTripper that // WrapDNSXRoundTripper creates a new DNSXRoundTripper that
@ -42,7 +43,7 @@ func (txp *dnsxRoundTripperDB) RoundTrip(
response, err := txp.DNSTransport.RoundTrip(ctx, query) response, err := txp.DNSTransport.RoundTrip(ctx, query)
finished := time.Since(txp.begin).Seconds() finished := time.Since(txp.begin).Seconds()
txp.db.InsertIntoDNSRoundTrip(&DNSRoundTripEvent{ txp.db.InsertIntoDNSRoundTrip(&DNSRoundTripEvent{
Network: txp.DNSTransport.Network(), Network: tracex.ResolverNetworkAdaptNames(txp.DNSTransport.Network()),
Address: txp.DNSTransport.Address(), Address: txp.DNSTransport.Address(),
Query: txp.maybeQueryBytes(query), Query: txp.maybeQueryBytes(query),
Started: started, Started: started,

View File

@ -0,0 +1,47 @@
package measurex
import (
"context"
"testing"
"github.com/miekg/dns"
"github.com/ooni/probe-cli/v3/internal/model/mocks"
"github.com/ooni/probe-cli/v3/internal/netxlite"
)
func TestDNSXModifiesStdlibTransportName(t *testing.T) {
// See https://github.com/ooni/spec/pull/257 for more information.
child := netxlite.NewDNSOverGetaddrinfoTransport()
mx := NewMeasurerWithDefaultSettings()
dbout := &MeasurementDB{}
txp := mx.WrapDNSXRoundTripper(dbout, child)
ctx, cancel := context.WithCancel(context.Background())
cancel() // we want to fail immediately
query := &mocks.DNSQuery{
MockDomain: func() string {
return "dns.google"
},
MockType: func() uint16 {
return dns.TypeANY
},
MockBytes: func() ([]byte, error) {
return []byte{}, nil
},
MockID: func() uint16 {
return 1453
},
}
_, _ = txp.RoundTrip(ctx, query)
measurement := dbout.AsMeasurement()
var good int
for _, rtinfo := range measurement.DNSRoundTrip {
network := rtinfo.Network
if network != netxlite.StdlibResolverSystem {
t.Fatal("unexpected network", network)
}
good++
}
if good < 1 {
t.Fatal("no good entry seen")
}
}

View File

@ -13,6 +13,7 @@ import (
"github.com/ooni/probe-cli/v3/internal/model" "github.com/ooni/probe-cli/v3/internal/model"
"github.com/ooni/probe-cli/v3/internal/netxlite" "github.com/ooni/probe-cli/v3/internal/netxlite"
"github.com/ooni/probe-cli/v3/internal/tracex"
) )
// WrapResolver creates a new Resolver that saves events into the WritableDB. // WrapResolver creates a new Resolver that saves events into the WritableDB.
@ -105,7 +106,7 @@ func (r *resolverDB) LookupHost(ctx context.Context, domain string) ([]string, e
func (r *resolverDB) saveLookupResults(domain string, started, finished float64, func (r *resolverDB) saveLookupResults(domain string, started, finished float64,
err error, addrs []string, qtype string) { err error, addrs []string, qtype string) {
ev := &DNSLookupEvent{ ev := &DNSLookupEvent{
Network: r.Resolver.Network(), Network: tracex.ResolverNetworkAdaptNames(r.Resolver.Network()),
Address: r.Resolver.Address(), Address: r.Resolver.Address(),
Failure: NewFailure(err), Failure: NewFailure(err),
Domain: domain, Domain: domain,
@ -158,7 +159,7 @@ func (r *resolverDB) LookupHTTPS(ctx context.Context, domain string) (*model.HTT
https, err := r.Resolver.LookupHTTPS(ctx, domain) https, err := r.Resolver.LookupHTTPS(ctx, domain)
finished := time.Since(r.begin).Seconds() finished := time.Since(r.begin).Seconds()
ev := &DNSLookupEvent{ ev := &DNSLookupEvent{
Network: r.Resolver.Network(), Network: tracex.ResolverNetworkAdaptNames(r.Resolver.Network()),
Address: r.Resolver.Address(), Address: r.Resolver.Address(),
Domain: domain, Domain: domain,
QueryType: "HTTPS", QueryType: "HTTPS",

View File

@ -0,0 +1,58 @@
package measurex
import (
"context"
"testing"
"github.com/ooni/probe-cli/v3/internal/model"
"github.com/ooni/probe-cli/v3/internal/netxlite"
)
func TestResolverModifiesStdlibResolverName(t *testing.T) {
// See https://github.com/ooni/spec/pull/257 for more information.
t.Run("for LookupHost", func(t *testing.T) {
child := netxlite.NewStdlibResolver(model.DiscardLogger)
mx := NewMeasurerWithDefaultSettings()
dbout := &MeasurementDB{}
txp := mx.WrapResolver(dbout, child)
ctx, cancel := context.WithCancel(context.Background())
cancel() // we want to fail immediately
_, _ = txp.LookupHost(ctx, "dns.google")
measurement := dbout.AsMeasurement()
var good int
for _, rtinfo := range measurement.LookupHost {
network := rtinfo.Network
if network != netxlite.StdlibResolverSystem {
t.Fatal("unexpected network", network)
}
good++
}
if good < 1 {
t.Fatal("no good entry seen")
}
})
t.Run("for LookupHTTPS", func(t *testing.T) {
child := netxlite.NewStdlibResolver(model.DiscardLogger)
mx := NewMeasurerWithDefaultSettings()
dbout := &MeasurementDB{}
txp := mx.WrapResolver(dbout, child)
ctx, cancel := context.WithCancel(context.Background())
cancel() // we want to fail immediately
_, _ = txp.LookupHTTPS(ctx, "dns.google")
measurement := dbout.AsMeasurement()
var good int
for _, rtinfo := range measurement.LookupHTTPSSvc {
network := rtinfo.Network
if network != netxlite.StdlibResolverSystem {
t.Fatal("unexpected network", network)
}
good++
}
if good < 1 {
t.Fatal("no good entry seen")
}
})
}

View File

@ -301,8 +301,12 @@ func TestNewWrappedResolvers(t *testing.T) {
if resolvert.tx != trace { if resolvert.tx != trace {
t.Fatal("invalid trace") t.Fatal("invalid trace")
} }
if resolver.Network() != "system" { switch network := resolver.Network(); network {
t.Fatal("unexpected resolver network") case netxlite.StdlibResolverGetaddrinfo,
netxlite.StdlibResolverGolangNetResolver:
// ok
default:
t.Fatal("unexpected resolver network", network)
} }
}) })
} }

View File

@ -24,6 +24,11 @@ type dnsOverGetaddrinfoTransport struct {
testableLookupANY func(ctx context.Context, domain string) ([]string, string, error) testableLookupANY func(ctx context.Context, domain string) ([]string, string, error)
} }
// NewDNSOverGetaddrinfoTransport creates a new dns-over-getaddrinfo transport.
func NewDNSOverGetaddrinfoTransport() model.DNSTransport {
return &dnsOverGetaddrinfoTransport{}
}
var _ model.DNSTransport = &dnsOverGetaddrinfoTransport{} var _ model.DNSTransport = &dnsOverGetaddrinfoTransport{}
func (txp *dnsOverGetaddrinfoTransport) RoundTrip( func (txp *dnsOverGetaddrinfoTransport) RoundTrip(

View File

@ -47,7 +47,7 @@
// //
// 1. establishing a TCP connection; // 1. establishing a TCP connection;
// //
// 2. performing a domain name resolution with the "system" resolver // 2. performing a domain name resolution with the "stdlib" resolver
// (i.e., getaddrinfo on Unix) or custom DNS transports (e.g., DoT, DoH); // (i.e., getaddrinfo on Unix) or custom DNS transports (e.g., DoT, DoH);
// //
// 3. performing the TLS handshake; // 3. performing the TLS handshake;

View File

@ -2,6 +2,23 @@ package netxlite
import "errors" import "errors"
// Name of the resolver we use when we link with libc and use getaddrinfo directly.
//
// See https://github.com/ooni/spec/pull/257 for more info.
const StdlibResolverGetaddrinfo = "getaddrinfo"
// Name of the resolver we use when we don't link with libc and use net.Resolver.
//
// See https://github.com/ooni/spec/pull/257 for more info.
const StdlibResolverGolangNetResolver = "golang_net_resolver"
// Legacy name of the resolver we use when we're don't know whether we're using
// getaddrinfo, but we're using net.Resolver, and we're splitting the answer
// in two A and AAAA queries. Eventually will become deprecated.
//
// See https://github.com/ooni/spec/pull/257 for more info.
const StdlibResolverSystem = "system"
// ErrGetaddrinfo represents a getaddrinfo failure. // ErrGetaddrinfo represents a getaddrinfo failure.
type ErrGetaddrinfo struct { type ErrGetaddrinfo struct {
// Err is the error proper. // Err is the error proper.

View File

@ -28,10 +28,13 @@ import (
// been used to implement the getaddrinfo resolver. // been used to implement the getaddrinfo resolver.
// //
// This is the CGO_ENABLED=1 implementation of this function, which // This is the CGO_ENABLED=1 implementation of this function, which
// always returns the string "system", because in this scenario // always returns the string [StdlibResolverGetaddrinfo], because in this scenario
// we are actually calling the getaddrinfo libc function. // we are actually calling the getaddrinfo libc function.
//
// See https://github.com/ooni/spec/pull/257 for more information on how
// we evolved our naming of the "stdlib" resolver over time.
func getaddrinfoResolverNetwork() string { func getaddrinfoResolverNetwork() string {
return "system" return StdlibResolverGetaddrinfo
} }
// getaddrinfoLookupANY attempts to perform an ANY lookup using getaddrinfo. // getaddrinfoLookupANY attempts to perform an ANY lookup using getaddrinfo.

View File

@ -11,13 +11,16 @@ import (
// been used to implement the getaddrinfo resolver. // been used to implement the getaddrinfo resolver.
// //
// This is the CGO_ENABLED=0 implementation of this function, which // This is the CGO_ENABLED=0 implementation of this function, which
// always returns the string "go", because in this scenario we are actually // always returns the string [StdlibResolverGolangNetResolver], because in this scenario
// using whatever resolver is used under the hood by the stdlib. // we are actually using whatever resolver is used under the hood by the stdlib.
// //
// See https://github.com/ooni/probe/issues/2029#issuecomment-1140805266 // See https://github.com/ooni/probe/issues/2029#issuecomment-1140805266
// for an explanation of why calling this resolver "netgo" is wrong. // for an explanation of why calling this resolver "netgo" was wrong.
//
// See https://github.com/ooni/spec/pull/257 for additional documentation
// regarding using "golang_net_resolver" instead of "go".
func getaddrinfoResolverNetwork() string { func getaddrinfoResolverNetwork() string {
return "go" return StdlibResolverGolangNetResolver
} }
// getaddrinfoLookupANY attempts to perform an ANY lookup using getaddrinfo. // getaddrinfoLookupANY attempts to perform an ANY lookup using getaddrinfo.

View File

@ -20,11 +20,11 @@ import (
// ErrNoDNSTransport is the error returned when you attempt to perform // ErrNoDNSTransport is the error returned when you attempt to perform
// a DNS operation that requires a custom DNSTransport (e.g., DNSOverHTTPSTransport) // a DNS operation that requires a custom DNSTransport (e.g., DNSOverHTTPSTransport)
// but you are using the "system" resolver instead. // but you are using the "stdlib" resolver instead.
var ErrNoDNSTransport = errors.New("operation requires a DNS transport") var ErrNoDNSTransport = errors.New("operation requires a DNS transport")
// NewStdlibResolver creates a new Resolver by combining WrapResolver // NewStdlibResolver creates a new Resolver by combining WrapResolver
// with an internal "system" resolver type. The list of optional wrappers // with an internal "stdlib" resolver type. The list of optional wrappers
// allow to wrap the underlying getaddrinfo transport. Any nil wrapper // allow to wrap the underlying getaddrinfo transport. Any nil wrapper
// will be silently ignored by the code that performs the wrapping. // will be silently ignored by the code that performs the wrapping.
func NewStdlibResolver(logger model.DebugLogger, wrappers ...model.DNSTransportWrapper) model.Resolver { func NewStdlibResolver(logger model.DebugLogger, wrappers ...model.DNSTransportWrapper) model.Resolver {
@ -45,7 +45,7 @@ func NewParallelDNSOverHTTPSResolver(logger model.DebugLogger, URL string) model
// implies, this function returns an unwrapped resolver. // implies, this function returns an unwrapped resolver.
func NewUnwrappedStdlibResolver(wrappers ...model.DNSTransportWrapper) model.Resolver { func NewUnwrappedStdlibResolver(wrappers ...model.DNSTransportWrapper) model.Resolver {
return &resolverSystem{ return &resolverSystem{
t: WrapDNSTransport(&dnsOverGetaddrinfoTransport{}, wrappers...), t: WrapDNSTransport(NewDNSOverGetaddrinfoTransport(), wrappers...),
} }
} }

View File

@ -347,7 +347,7 @@ func TestResolverLogger(t *testing.T) {
return expected, nil return expected, nil
}, },
MockNetwork: func() string { MockNetwork: func() string {
return "system" return StdlibResolverGetaddrinfo
}, },
MockAddress: func() string { MockAddress: func() string {
return "" return ""
@ -381,7 +381,7 @@ func TestResolverLogger(t *testing.T) {
return nil, expected return nil, expected
}, },
MockNetwork: func() string { MockNetwork: func() string {
return "system" return StdlibResolverGetaddrinfo
}, },
MockAddress: func() string { MockAddress: func() string {
return "" return ""
@ -420,7 +420,7 @@ func TestResolverLogger(t *testing.T) {
return expected, nil return expected, nil
}, },
MockNetwork: func() string { MockNetwork: func() string {
return "system" return StdlibResolverGetaddrinfo
}, },
MockAddress: func() string { MockAddress: func() string {
return "" return ""
@ -454,7 +454,7 @@ func TestResolverLogger(t *testing.T) {
return nil, expected return nil, expected
}, },
MockNetwork: func() string { MockNetwork: func() string {
return "system" return StdlibResolverGetaddrinfo
}, },
MockAddress: func() string { MockAddress: func() string {
return "" return ""
@ -509,7 +509,7 @@ func TestResolverLogger(t *testing.T) {
return expected, nil return expected, nil
}, },
MockNetwork: func() string { MockNetwork: func() string {
return "system" return StdlibResolverGetaddrinfo
}, },
MockAddress: func() string { MockAddress: func() string {
return "" return ""
@ -543,7 +543,7 @@ func TestResolverLogger(t *testing.T) {
return nil, expected return nil, expected
}, },
MockNetwork: func() string { MockNetwork: func() string {
return "system" return StdlibResolverGetaddrinfo
}, },
MockAddress: func() string { MockAddress: func() string {
return "" return ""

View File

@ -10,6 +10,7 @@ import (
"time" "time"
"github.com/ooni/probe-cli/v3/internal/model" "github.com/ooni/probe-cli/v3/internal/model"
"github.com/ooni/probe-cli/v3/internal/netxlite"
) )
// ResolverSaver is a resolver that saves events. // ResolverSaver is a resolver that saves events.
@ -42,7 +43,7 @@ func (r *ResolverSaver) LookupHost(ctx context.Context, hostname string) ([]stri
r.Saver.Write(&EventResolveStart{&EventValue{ r.Saver.Write(&EventResolveStart{&EventValue{
Address: r.Resolver.Address(), Address: r.Resolver.Address(),
Hostname: hostname, Hostname: hostname,
Proto: r.Resolver.Network(), Proto: r.Network(),
Time: start, Time: start,
}}) }})
addrs, err := r.Resolver.LookupHost(ctx, hostname) addrs, err := r.Resolver.LookupHost(ctx, hostname)
@ -53,14 +54,29 @@ func (r *ResolverSaver) LookupHost(ctx context.Context, hostname string) ([]stri
Duration: stop.Sub(start), Duration: stop.Sub(start),
Err: NewFailureStr(err), Err: NewFailureStr(err),
Hostname: hostname, Hostname: hostname,
Proto: r.Resolver.Network(), Proto: r.Network(),
Time: stop, Time: stop,
}}) }})
return addrs, err return addrs, err
} }
// ResolverNetworkAdaptNames makes sure we map the [netxlite.StdlibResolverGolangNetResolver] and
// [netxlite.StdlibResolverGetaddrinfo] resolver names to [netxlite.StdlibResolverSystem]. You MUST
// call this function when your resolver splits the "stdlib" resolver results into two fake AAAA
// and A queries rather than faking a single ANY query.
//
// See https://github.com/ooni/spec/pull/257 for more information.
func ResolverNetworkAdaptNames(input string) string {
switch input {
case netxlite.StdlibResolverGetaddrinfo, netxlite.StdlibResolverGolangNetResolver:
return netxlite.StdlibResolverSystem
default:
return input
}
}
func (r *ResolverSaver) Network() string { func (r *ResolverSaver) Network() string {
return r.Resolver.Network() return ResolverNetworkAdaptNames(r.Resolver.Network())
} }
func (r *ResolverSaver) Address() string { func (r *ResolverSaver) Address() string {
@ -112,7 +128,7 @@ func (txp *DNSTransportSaver) RoundTrip(
txp.Saver.Write(&EventDNSRoundTripStart{&EventValue{ txp.Saver.Write(&EventDNSRoundTripStart{&EventValue{
Address: txp.DNSTransport.Address(), Address: txp.DNSTransport.Address(),
DNSQuery: dnsMaybeQueryBytes(query), DNSQuery: dnsMaybeQueryBytes(query),
Proto: txp.DNSTransport.Network(), Proto: txp.Network(),
Time: start, Time: start,
}}) }})
response, err := txp.DNSTransport.RoundTrip(ctx, query) response, err := txp.DNSTransport.RoundTrip(ctx, query)
@ -123,14 +139,14 @@ func (txp *DNSTransportSaver) RoundTrip(
DNSResponse: dnsMaybeResponseBytes(response), DNSResponse: dnsMaybeResponseBytes(response),
Duration: stop.Sub(start), Duration: stop.Sub(start),
Err: NewFailureStr(err), Err: NewFailureStr(err),
Proto: txp.DNSTransport.Network(), Proto: txp.Network(),
Time: stop, Time: stop,
}}) }})
return response, err return response, err
} }
func (txp *DNSTransportSaver) Network() string { func (txp *DNSTransportSaver) Network() string {
return txp.DNSTransport.Network() return ResolverNetworkAdaptNames(txp.DNSTransport.Network())
} }
func (txp *DNSTransportSaver) Address() string { func (txp *DNSTransportSaver) Address() string {

View File

@ -9,6 +9,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/miekg/dns"
"github.com/ooni/probe-cli/v3/internal/model" "github.com/ooni/probe-cli/v3/internal/model"
"github.com/ooni/probe-cli/v3/internal/model/mocks" "github.com/ooni/probe-cli/v3/internal/model/mocks"
"github.com/ooni/probe-cli/v3/internal/netxlite" "github.com/ooni/probe-cli/v3/internal/netxlite"
@ -75,7 +76,7 @@ func TestResolverSaver(t *testing.T) {
reso := saver.WrapResolver(newFakeResolverWithResult(expected)) reso := saver.WrapResolver(newFakeResolverWithResult(expected))
addrs, err := reso.LookupHost(context.Background(), "www.google.com") addrs, err := reso.LookupHost(context.Background(), "www.google.com")
if err != nil { if err != nil {
t.Fatal("expected nil error here") t.Fatal(err)
} }
if !reflect.DeepEqual(addrs, expected) { if !reflect.DeepEqual(addrs, expected) {
t.Fatal("not the result we expected") t.Fatal("not the result we expected")
@ -112,19 +113,56 @@ func TestResolverSaver(t *testing.T) {
t.Fatal("the saved time is wrong") t.Fatal("the saved time is wrong")
} }
}) })
t.Run("with stdlib resolver there's correct .Network remapping", func(t *testing.T) {
saver := &Saver{}
reso := saver.WrapResolver(netxlite.NewStdlibResolver(model.DiscardLogger))
ctx, cancel := context.WithCancel(context.Background())
cancel() // immediately fail the operation
_, _ = reso.LookupHost(ctx, "www.google.com")
// basically, we just want to ensure that the engine name is converted
ev := saver.Read()
if len(ev) != 2 {
t.Fatal("expected number of events")
}
if ev[0].Value().Proto != netxlite.StdlibResolverSystem {
t.Fatal("unexpected Proto")
}
if ev[1].Value().Proto != netxlite.StdlibResolverSystem {
t.Fatal("unexpected Proto")
}
})
}) })
t.Run("Network", func(t *testing.T) { t.Run("Network", func(t *testing.T) {
saver := &Saver{} t.Run("when using a custom resolver", func(t *testing.T) {
child := &mocks.Resolver{ saver := &Saver{}
MockNetwork: func() string { child := &mocks.Resolver{
return "x" MockNetwork: func() string {
}, return "x"
} },
reso := saver.WrapResolver(child) }
if reso.Network() != "x" { reso := saver.WrapResolver(child)
t.Fatal("unexpected result") if reso.Network() != "x" {
} t.Fatal("unexpected result")
}
})
t.Run("when using the stdlib resolver", func(t *testing.T) {
child := netxlite.NewStdlibResolver(model.DiscardLogger)
switch network := child.Network(); network {
case netxlite.StdlibResolverGetaddrinfo,
netxlite.StdlibResolverGolangNetResolver:
// ok
default:
t.Fatal("unexpected child resolver network", network)
}
saver := &Saver{}
reso := saver.WrapResolver(child)
if network := reso.Network(); network != netxlite.StdlibResolverSystem {
t.Fatal("unexpected wrapped resolver network", network)
}
})
}) })
t.Run("Address", func(t *testing.T) { t.Run("Address", func(t *testing.T) {
@ -326,19 +364,70 @@ func TestDNSTransportSaver(t *testing.T) {
t.Fatal("the saved time is wrong") t.Fatal("the saved time is wrong")
} }
}) })
t.Run("with getaddrinfo transport there's correct .Network remapping", func(t *testing.T) {
saver := &Saver{}
reso := saver.WrapDNSTransport(netxlite.NewDNSOverGetaddrinfoTransport())
ctx, cancel := context.WithCancel(context.Background())
cancel() // immediately fail the operation
query := &mocks.DNSQuery{
MockBytes: func() ([]byte, error) {
return []byte{}, nil
},
MockType: func() uint16 {
return dns.TypeANY
},
MockID: func() uint16 {
return 1453
},
MockDomain: func() string {
return "dns.google"
},
}
_, _ = reso.RoundTrip(ctx, query)
// basically, we just want to ensure that the engine name is converted
ev := saver.Read()
if len(ev) != 2 {
t.Fatal("expected number of events")
}
if ev[0].Value().Proto != netxlite.StdlibResolverSystem {
t.Fatal("unexpected Proto")
}
if ev[1].Value().Proto != netxlite.StdlibResolverSystem {
t.Fatal("unexpected Proto")
}
})
}) })
t.Run("Network", func(t *testing.T) { t.Run("Network", func(t *testing.T) {
saver := &Saver{} t.Run("with custom child transport", func(t *testing.T) {
child := &mocks.DNSTransport{ saver := &Saver{}
MockNetwork: func() string { child := &mocks.DNSTransport{
return "x" MockNetwork: func() string {
}, return "x"
} },
txp := saver.WrapDNSTransport(child) }
if txp.Network() != "x" { txp := saver.WrapDNSTransport(child)
t.Fatal("unexpected result") if txp.Network() != "x" {
} t.Fatal("unexpected result")
}
})
t.Run("when using the stdlib resolver", func(t *testing.T) {
child := netxlite.NewDNSOverGetaddrinfoTransport()
switch network := child.Network(); network {
case netxlite.StdlibResolverGetaddrinfo,
netxlite.StdlibResolverGolangNetResolver:
// ok
default:
t.Fatal("unexpected child resolver network", network)
}
saver := &Saver{}
reso := saver.WrapDNSTransport(child)
if network := reso.Network(); network != netxlite.StdlibResolverSystem {
t.Fatal("unexpected wrapped resolver network", network)
}
})
}) })
t.Run("Address", func(t *testing.T) { t.Run("Address", func(t *testing.T) {
@ -429,3 +518,45 @@ func newFakeResolverWithResult(r []string) model.Resolver {
}, },
} }
} }
func TestResolverNetworkAdaptNames(t *testing.T) {
type args struct {
input string
}
tests := []struct {
name string
args args
want string
}{{
name: "with StdlibResolverGetaddrinfo",
args: args{
input: netxlite.StdlibResolverGetaddrinfo,
},
want: netxlite.StdlibResolverSystem,
}, {
name: "with StdlibResolverGolangNetResolver",
args: args{
input: netxlite.StdlibResolverGolangNetResolver,
},
want: netxlite.StdlibResolverSystem,
}, {
name: "with StdlibResolverSystem",
args: args{
input: netxlite.StdlibResolverSystem,
},
want: netxlite.StdlibResolverSystem,
}, {
name: "with any other name",
args: args{
input: "doh",
},
want: "doh",
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := ResolverNetworkAdaptNames(tt.args.input); got != tt.want {
t.Errorf("ResolverNetworkAdaptNames() = %v, want %v", got, tt.want)
}
})
}
}

View File

@ -25,7 +25,7 @@ Index:
- [chapter04](chapter04) shows how to establish QUIC sessions; - [chapter04](chapter04) shows how to establish QUIC sessions;
- [chapter05](chapter05) is about the "system" DNS resolver; - [chapter05](chapter05) is about the "stdlib" DNS resolver;
- [chapter06](chapter06) discusses custom DNS-over-UDP resolvers; - [chapter06](chapter06) discusses custom DNS-over-UDP resolvers;

View File

@ -1,10 +1,13 @@
# Chapter I: Using the "system" DNS resolver # Chapter I: Using the "stdlib" DNS resolver
In this chapter we will write together a `main.go` file that In this chapter we will write together a `main.go` file that
uses the "system" DNS resolver to lookup domain names. uses the "stdlib" DNS resolver to lookup domain names.
The "system" resolver is the one used by `getaddrinfo` on Unix. The "stdlib" resolver is `getaddrinfo` on Unix. If we're compiled with
`CGO_ENABLED=1`, we use the `getaddrinfo` stdlib call directly. Otherwise,
we use the `net.Resolver` resolver, which may or may not use
`getaddrinfo` (or equivalent stdlib calls) under the hood.
(This file is auto-generated from the corresponding source file, (This file is auto-generated from the corresponding source file,
so make sure you don't edit it manually.) so make sure you don't edit it manually.)
@ -114,4 +117,4 @@ should cause a timeout error, because the timeout is ridicolously small.
## Conclusions ## Conclusions
We have seen how to use the "system" DNS resolver. We have seen how to use the "stdlib" DNS resolver.

View File

@ -1,11 +1,14 @@
// -=-=- StartHere -=-=- // -=-=- StartHere -=-=-
// //
// # Chapter I: Using the "system" DNS resolver // # Chapter I: Using the "stdlib" DNS resolver
// //
// In this chapter we will write together a `main.go` file that // In this chapter we will write together a `main.go` file that
// uses the "system" DNS resolver to lookup domain names. // uses the "stdlib" DNS resolver to lookup domain names.
// //
// The "system" resolver is the one used by `getaddrinfo` on Unix. // The "stdlib" resolver is `getaddrinfo` on Unix. If we're compiled with
// `CGO_ENABLED=1`, we use the `getaddrinfo` stdlib call directly. Otherwise,
// we use the `net.Resolver` resolver, which may or may not use
// `getaddrinfo` (or equivalent stdlib calls) under the hood.
// //
// (This file is auto-generated from the corresponding source file, // (This file is auto-generated from the corresponding source file,
// so make sure you don't edit it manually.) // so make sure you don't edit it manually.)
@ -115,4 +118,4 @@ func fatal(err error) {
// //
// ## Conclusions // ## Conclusions
// //
// We have seen how to use the "system" DNS resolver. // We have seen how to use the "stdlib" DNS resolver.