cleanup(netx): remove subpackages and unnecessary code (#788)

This pull request consists of several small and obvious cleanups in the netx directory.

See https://github.com/ooni/probe/issues/2121
This commit is contained in:
Simone Basso 2022-06-02 11:51:21 +02:00 committed by GitHub
parent 9354191b85
commit 1cb820b19d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 201 additions and 815 deletions

View File

@ -1,4 +1,4 @@
package resolver
package netx
import (
"context"

View File

@ -1,17 +1,21 @@
package resolver_test
package netx
import (
"context"
"errors"
"testing"
"github.com/ooni/probe-cli/v3/internal/engine/netx/resolver"
"github.com/ooni/probe-cli/v3/internal/model/mocks"
)
func TestCacheFailure(t *testing.T) {
func TestCacheResolverFailure(t *testing.T) {
expected := errors.New("mocked error")
r := resolver.NewFakeResolverWithExplicitError(expected)
cache := &resolver.CacheResolver{Resolver: r}
r := &mocks.Resolver{
MockLookupHost: func(ctx context.Context, domain string) ([]string, error) {
return nil, expected
},
}
cache := &CacheResolver{Resolver: r}
addrs, err := cache.LookupHost(context.Background(), "www.google.com")
if !errors.Is(err, expected) {
t.Fatal("not the error we expected")
@ -24,10 +28,14 @@ func TestCacheFailure(t *testing.T) {
}
}
func TestCacheHitSuccess(t *testing.T) {
func TestCacheResolverHitSuccess(t *testing.T) {
expected := errors.New("mocked error")
r := resolver.NewFakeResolverWithExplicitError(expected)
cache := &resolver.CacheResolver{Resolver: r}
r := &mocks.Resolver{
MockLookupHost: func(ctx context.Context, domain string) ([]string, error) {
return nil, expected
},
}
cache := &CacheResolver{Resolver: r}
cache.Set("dns.google.com", []string{"8.8.8.8"})
addrs, err := cache.LookupHost(context.Background(), "dns.google.com")
if err != nil {
@ -38,9 +46,13 @@ func TestCacheHitSuccess(t *testing.T) {
}
}
func TestCacheMissSuccess(t *testing.T) {
r := resolver.NewFakeResolverWithResult([]string{"8.8.8.8"})
cache := &resolver.CacheResolver{Resolver: r}
func TestCacheResolverMissSuccess(t *testing.T) {
r := &mocks.Resolver{
MockLookupHost: func(ctx context.Context, domain string) ([]string, error) {
return []string{"8.8.8.8"}, nil
},
}
cache := &CacheResolver{Resolver: r}
addrs, err := cache.LookupHost(context.Background(), "dns.google.com")
if err != nil {
t.Fatal(err)
@ -53,9 +65,13 @@ func TestCacheMissSuccess(t *testing.T) {
}
}
func TestCacheReadonlySuccess(t *testing.T) {
r := resolver.NewFakeResolverWithResult([]string{"8.8.8.8"})
cache := &resolver.CacheResolver{Resolver: r, ReadOnly: true}
func TestCacheResolverReadonlySuccess(t *testing.T) {
r := &mocks.Resolver{
MockLookupHost: func(ctx context.Context, domain string) ([]string, error) {
return []string{"8.8.8.8"}, nil
},
}
cache := &CacheResolver{Resolver: r, ReadOnly: true}
addrs, err := cache.LookupHost(context.Background(), "dns.google.com")
if err != nil {
t.Fatal(err)

View File

@ -1,7 +1,4 @@
// Package dialer allows you to create a net.Dialer-compatible
// DialContext-enabled dialer with error wrapping, optional logging,
// optional network-events saving, and optional proxying.
package dialer
package netx
import (
"net/url"
@ -12,8 +9,8 @@ import (
"github.com/ooni/probe-cli/v3/internal/tracex"
)
// Config contains the settings for New.
type Config struct {
// dialerConfig contains the settings for New.
type dialerConfig struct {
// ContextByteCounting optionally configures context-based
// byte counting. By default we don't do that.
//
@ -48,8 +45,8 @@ type Config struct {
ReadWriteSaver *tracex.Saver
}
// New creates a new Dialer from the specified config and resolver.
func New(config *Config, resolver model.Resolver) model.Dialer {
// newDialer creates a new Dialer from the specified config and resolver.
func newDialer(config *dialerConfig, resolver model.Resolver) model.Dialer {
var logger model.DebugLogger = model.DiscardLogger
if config.Logger != nil {
logger = config.Logger

View File

@ -1,4 +1,4 @@
package dialer
package netx
import (
"net/http"
@ -13,7 +13,7 @@ import (
func TestNewCreatesTheExpectedChain(t *testing.T) {
saver := &tracex.Saver{}
dlr := New(&Config{
dlr := newDialer(&dialerConfig{
ContextByteCounting: true,
DialSaver: saver,
Logger: log.Log,
@ -37,7 +37,7 @@ func TestDialerNewSuccess(t *testing.T) {
t.Skip("skip test in short mode")
}
log.SetLevel(log.DebugLevel)
d := New(&Config{Logger: log.Log}, netxlite.DefaultResolver)
d := newDialer(&dialerConfig{Logger: log.Log}, netxlite.DefaultResolver)
txp := &http.Transport{DialContext: d.DialContext}
client := &http.Client{Transport: txp}
resp, err := client.Get("http://www.google.com")

View File

@ -1,59 +0,0 @@
package netx
import (
"context"
"net"
"net/http"
"time"
"github.com/ooni/probe-cli/v3/internal/netxlite"
)
type FakeDialer struct {
Conn net.Conn
Err error
}
func (d FakeDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
time.Sleep(10 * time.Microsecond)
return d.Conn, d.Err
}
func (d FakeDialer) CloseIdleConnections() {}
type FakeTransport struct {
Err error
Func func(*http.Request) (*http.Response, error)
Resp *http.Response
}
func (txp FakeTransport) RoundTrip(req *http.Request) (*http.Response, error) {
time.Sleep(10 * time.Microsecond)
if txp.Func != nil {
return txp.Func(req)
}
if req.Body != nil {
netxlite.ReadAllContext(req.Context(), req.Body)
req.Body.Close()
}
if txp.Err != nil {
return nil, txp.Err
}
txp.Resp.Request = req // non thread safe but it doesn't matter
return txp.Resp, nil
}
func (txp FakeTransport) CloseIdleConnections() {}
type FakeBody struct {
Err error
}
func (fb FakeBody) Read(p []byte) (int, error) {
time.Sleep(10 * time.Microsecond)
return 0, fb.Err
}
func (fb FakeBody) Close() error {
return nil
}

View File

@ -1,5 +1,4 @@
// Package httptransport contains HTTP transport extensions.
package httptransport
package netx
import (
"crypto/tls"
@ -8,32 +7,32 @@ import (
"github.com/ooni/probe-cli/v3/internal/netxlite"
)
// Config contains the configuration required for constructing an HTTP transport
type Config struct {
// httpTransportConfig contains the configuration required for constructing an HTTP transport
type httpTransportConfig struct {
Dialer model.Dialer
QUICDialer model.QUICDialer
TLSDialer model.TLSDialer
TLSConfig *tls.Config
}
// NewHTTP3Transport creates a new HTTP3Transport instance.
// newHTTP3Transport creates a new HTTP3Transport instance.
//
// Deprecation warning
//
// New code should use netxlite.NewHTTP3Transport instead.
func NewHTTP3Transport(config Config) model.HTTPTransport {
func newHTTP3Transport(config httpTransportConfig) model.HTTPTransport {
// Rationale for using NoLogger here: previously this code did
// not use a logger as well, so it's fine to keep it as is.
return netxlite.NewHTTP3Transport(model.DiscardLogger,
config.QUICDialer, config.TLSConfig)
}
// NewSystemTransport creates a new "system" HTTP transport. That is a transport
// newSystemTransport creates a new "system" HTTP transport. That is a transport
// using the Go standard library with custom dialer and TLS dialer.
//
// Deprecation warning
//
// New code should use netxlite.NewHTTPTransport instead.
func NewSystemTransport(config Config) model.HTTPTransport {
func newSystemTransport(config httpTransportConfig) model.HTTPTransport {
return netxlite.NewOOHTTPBaseTransport(config.Dialer, config.TLSDialer)
}

View File

@ -1,89 +0,0 @@
package netx_test
import (
"context"
"errors"
"net/http"
"testing"
"github.com/apex/log"
"github.com/ooni/probe-cli/v3/internal/bytecounter"
"github.com/ooni/probe-cli/v3/internal/engine/netx"
"github.com/ooni/probe-cli/v3/internal/netxlite"
"github.com/ooni/probe-cli/v3/internal/tracex"
)
func TestSuccess(t *testing.T) {
if testing.Short() {
t.Skip("skip test in short mode")
}
log.SetLevel(log.DebugLevel)
counter := bytecounter.New()
config := netx.Config{
BogonIsError: true,
ByteCounter: counter,
CacheResolutions: true,
ContextByteCounting: true,
DialSaver: &tracex.Saver{},
HTTPSaver: &tracex.Saver{},
Logger: log.Log,
ReadWriteSaver: &tracex.Saver{},
ResolveSaver: &tracex.Saver{},
TLSSaver: &tracex.Saver{},
}
txp := netx.NewHTTPTransport(config)
client := &http.Client{Transport: txp}
resp, err := client.Get("https://www.google.com")
if err != nil {
t.Fatal(err)
}
if _, err = netxlite.ReadAllContext(context.Background(), resp.Body); err != nil {
t.Fatal(err)
}
if err = resp.Body.Close(); err != nil {
t.Fatal(err)
}
if counter.Sent.Load() <= 0 {
t.Fatal("no bytes sent?!")
}
if counter.Received.Load() <= 0 {
t.Fatal("no bytes received?!")
}
if ev := config.DialSaver.Read(); len(ev) <= 0 {
t.Fatal("no dial events?!")
}
if ev := config.HTTPSaver.Read(); len(ev) <= 0 {
t.Fatal("no HTTP events?!")
}
if ev := config.ReadWriteSaver.Read(); len(ev) <= 0 {
t.Fatal("no R/W events?!")
}
if ev := config.ResolveSaver.Read(); len(ev) <= 0 {
t.Fatal("no resolver events?!")
}
if ev := config.TLSSaver.Read(); len(ev) <= 0 {
t.Fatal("no TLS events?!")
}
}
func TestBogonResolutionNotBroken(t *testing.T) {
saver := new(tracex.Saver)
r := netx.NewResolver(netx.Config{
BogonIsError: true,
DNSCache: map[string][]string{
"www.google.com": {"127.0.0.1"},
},
ResolveSaver: saver,
Logger: log.Log,
})
addrs, err := r.LookupHost(context.Background(), "www.google.com")
if !errors.Is(err, netxlite.ErrDNSBogon) {
t.Fatal("not the error we expected")
}
if err.Error() != netxlite.FailureDNSBogonError {
t.Fatal("error not correctly wrapped")
}
if len(addrs) > 0 {
t.Fatal("expected no addresses here")
}
}

View File

@ -31,9 +31,6 @@ import (
"net/url"
"github.com/ooni/probe-cli/v3/internal/bytecounter"
"github.com/ooni/probe-cli/v3/internal/engine/netx/dialer"
"github.com/ooni/probe-cli/v3/internal/engine/netx/httptransport"
"github.com/ooni/probe-cli/v3/internal/engine/netx/resolver"
"github.com/ooni/probe-cli/v3/internal/model"
"github.com/ooni/probe-cli/v3/internal/netxlite"
"github.com/ooni/probe-cli/v3/internal/tracex"
@ -85,10 +82,10 @@ func NewResolver(config Config) model.Resolver {
Resolver: r,
}
if config.CacheResolutions {
r = &resolver.CacheResolver{Resolver: r}
r = &CacheResolver{Resolver: r}
}
if config.DNSCache != nil {
cache := &resolver.CacheResolver{Resolver: r, ReadOnly: true}
cache := &CacheResolver{Resolver: r, ReadOnly: true}
for key, values := range config.DNSCache {
cache.Set(key, values)
}
@ -113,7 +110,7 @@ func NewDialer(config Config) model.Dialer {
if config.FullResolver == nil {
config.FullResolver = NewResolver(config)
}
return dialer.New(&dialer.Config{
return newDialer(&dialerConfig{
ContextByteCounting: config.ContextByteCounting,
DialSaver: config.DialSaver,
Logger: config.Logger,
@ -175,7 +172,7 @@ func NewHTTPTransport(config Config) model.HTTPTransport {
}
tInfo := allTransportsInfo[config.HTTP3Enabled]
txp := tInfo.Factory(httptransport.Config{
txp := tInfo.Factory(httpTransportConfig{
Dialer: config.Dialer, QUICDialer: config.QUICDialer, TLSDialer: config.TLSDialer,
TLSConfig: config.TLSConfig})
@ -195,17 +192,17 @@ func NewHTTPTransport(config Config) model.HTTPTransport {
// httpTransportInfo contains the constructing function as well as the transport name
type httpTransportInfo struct {
Factory func(httptransport.Config) model.HTTPTransport
Factory func(httpTransportConfig) model.HTTPTransport
TransportName string
}
var allTransportsInfo = map[bool]httpTransportInfo{
false: {
Factory: httptransport.NewSystemTransport,
Factory: newSystemTransport,
TransportName: "tcp",
},
true: {
Factory: httptransport.NewHTTP3Transport,
Factory: newHTTP3Transport,
TransportName: "quic",
},
}

View File

@ -1,8 +0,0 @@
package netx
import "crypto/x509"
// DefaultCertPool allows tests to access the default cert pool.
func DefaultCertPool() *x509.CertPool {
return defaultCertPool
}

View File

@ -1,4 +1,4 @@
package netx_test
package netx
import (
"context"
@ -11,15 +11,13 @@ import (
"github.com/apex/log"
"github.com/ooni/probe-cli/v3/internal/bytecounter"
"github.com/ooni/probe-cli/v3/internal/engine/netx"
"github.com/ooni/probe-cli/v3/internal/engine/netx/resolver"
"github.com/ooni/probe-cli/v3/internal/model/mocks"
"github.com/ooni/probe-cli/v3/internal/netxlite"
"github.com/ooni/probe-cli/v3/internal/tracex"
)
func TestNewResolverVanilla(t *testing.T) {
r := netx.NewResolver(netx.Config{})
r := NewResolver(Config{})
ir, ok := r.(*netxlite.ResolverIDNA)
if !ok {
t.Fatal("not the resolver we expected")
@ -39,7 +37,7 @@ func TestNewResolverVanilla(t *testing.T) {
}
func TestNewResolverSpecificResolver(t *testing.T) {
r := netx.NewResolver(netx.Config{
r := NewResolver(Config{
BaseResolver: &netxlite.BogonResolver{
// not initialized because it doesn't matter in this context
},
@ -63,7 +61,7 @@ func TestNewResolverSpecificResolver(t *testing.T) {
}
func TestNewResolverWithBogonFilter(t *testing.T) {
r := netx.NewResolver(netx.Config{
r := NewResolver(Config{
BogonIsError: true,
})
ir, ok := r.(*netxlite.ResolverIDNA)
@ -89,7 +87,7 @@ func TestNewResolverWithBogonFilter(t *testing.T) {
}
func TestNewResolverWithLogging(t *testing.T) {
r := netx.NewResolver(netx.Config{
r := NewResolver(Config{
Logger: log.Log,
})
ir, ok := r.(*netxlite.ResolverIDNA)
@ -119,7 +117,7 @@ func TestNewResolverWithLogging(t *testing.T) {
func TestNewResolverWithSaver(t *testing.T) {
saver := new(tracex.Saver)
r := netx.NewResolver(netx.Config{
r := NewResolver(Config{
ResolveSaver: saver,
})
ir, ok := r.(*netxlite.ResolverIDNA)
@ -148,7 +146,7 @@ func TestNewResolverWithSaver(t *testing.T) {
}
func TestNewResolverWithReadWriteCache(t *testing.T) {
r := netx.NewResolver(netx.Config{
r := NewResolver(Config{
CacheResolutions: true,
})
ir, ok := r.(*netxlite.ResolverIDNA)
@ -159,7 +157,7 @@ func TestNewResolverWithReadWriteCache(t *testing.T) {
if !ok {
t.Fatal("not the resolver we expected")
}
cr, ok := ewr.Resolver.(*resolver.CacheResolver)
cr, ok := ewr.Resolver.(*CacheResolver)
if !ok {
t.Fatal("not the resolver we expected")
}
@ -177,7 +175,7 @@ func TestNewResolverWithReadWriteCache(t *testing.T) {
}
func TestNewResolverWithPrefilledReadonlyCache(t *testing.T) {
r := netx.NewResolver(netx.Config{
r := NewResolver(Config{
DNSCache: map[string][]string{
"dns.google.com": {"8.8.8.8"},
},
@ -190,7 +188,7 @@ func TestNewResolverWithPrefilledReadonlyCache(t *testing.T) {
if !ok {
t.Fatal("not the resolver we expected")
}
cr, ok := ewr.Resolver.(*resolver.CacheResolver)
cr, ok := ewr.Resolver.(*CacheResolver)
if !ok {
t.Fatal("not the resolver we expected")
}
@ -211,7 +209,7 @@ func TestNewResolverWithPrefilledReadonlyCache(t *testing.T) {
}
func TestNewTLSDialerVanilla(t *testing.T) {
td := netx.NewTLSDialer(netx.Config{})
td := NewTLSDialer(Config{})
rtd, ok := td.(*netxlite.TLSDialerLegacy)
if !ok {
t.Fatal("not the TLSDialer we expected")
@ -222,7 +220,7 @@ func TestNewTLSDialerVanilla(t *testing.T) {
if rtd.Config.NextProtos[0] != "h2" || rtd.Config.NextProtos[1] != "http/1.1" {
t.Fatal("invalid Config.NextProtos")
}
if rtd.Config.RootCAs != netx.DefaultCertPool() {
if rtd.Config.RootCAs != defaultCertPool {
t.Fatal("invalid Config.RootCAs")
}
if rtd.Dialer == nil {
@ -241,7 +239,7 @@ func TestNewTLSDialerVanilla(t *testing.T) {
}
func TestNewTLSDialerWithConfig(t *testing.T) {
td := netx.NewTLSDialer(netx.Config{
td := NewTLSDialer(Config{
TLSConfig: new(tls.Config),
})
rtd, ok := td.(*netxlite.TLSDialerLegacy)
@ -251,7 +249,7 @@ func TestNewTLSDialerWithConfig(t *testing.T) {
if len(rtd.Config.NextProtos) != 0 {
t.Fatal("invalid len(config.NextProtos)")
}
if rtd.Config.RootCAs != netx.DefaultCertPool() {
if rtd.Config.RootCAs != defaultCertPool {
t.Fatal("invalid Config.RootCAs")
}
if rtd.Dialer == nil {
@ -270,7 +268,7 @@ func TestNewTLSDialerWithConfig(t *testing.T) {
}
func TestNewTLSDialerWithLogging(t *testing.T) {
td := netx.NewTLSDialer(netx.Config{
td := NewTLSDialer(Config{
Logger: log.Log,
})
rtd, ok := td.(*netxlite.TLSDialerLegacy)
@ -283,7 +281,7 @@ func TestNewTLSDialerWithLogging(t *testing.T) {
if rtd.Config.NextProtos[0] != "h2" || rtd.Config.NextProtos[1] != "http/1.1" {
t.Fatal("invalid Config.NextProtos")
}
if rtd.Config.RootCAs != netx.DefaultCertPool() {
if rtd.Config.RootCAs != defaultCertPool {
t.Fatal("invalid Config.RootCAs")
}
if rtd.Dialer == nil {
@ -310,7 +308,7 @@ func TestNewTLSDialerWithLogging(t *testing.T) {
func TestNewTLSDialerWithSaver(t *testing.T) {
saver := new(tracex.Saver)
td := netx.NewTLSDialer(netx.Config{
td := NewTLSDialer(Config{
TLSSaver: saver,
})
rtd, ok := td.(*netxlite.TLSDialerLegacy)
@ -323,7 +321,7 @@ func TestNewTLSDialerWithSaver(t *testing.T) {
if rtd.Config.NextProtos[0] != "h2" || rtd.Config.NextProtos[1] != "http/1.1" {
t.Fatal("invalid Config.NextProtos")
}
if rtd.Config.RootCAs != netx.DefaultCertPool() {
if rtd.Config.RootCAs != defaultCertPool {
t.Fatal("invalid Config.RootCAs")
}
if rtd.Dialer == nil {
@ -349,7 +347,7 @@ func TestNewTLSDialerWithSaver(t *testing.T) {
}
func TestNewTLSDialerWithNoTLSVerifyAndConfig(t *testing.T) {
td := netx.NewTLSDialer(netx.Config{
td := NewTLSDialer(Config{
TLSConfig: new(tls.Config),
NoTLSVerify: true,
})
@ -363,7 +361,7 @@ func TestNewTLSDialerWithNoTLSVerifyAndConfig(t *testing.T) {
if rtd.Config.InsecureSkipVerify != true {
t.Fatal("expected true InsecureSkipVerify")
}
if rtd.Config.RootCAs != netx.DefaultCertPool() {
if rtd.Config.RootCAs != defaultCertPool {
t.Fatal("invalid Config.RootCAs")
}
if rtd.Dialer == nil {
@ -382,7 +380,7 @@ func TestNewTLSDialerWithNoTLSVerifyAndConfig(t *testing.T) {
}
func TestNewTLSDialerWithNoTLSVerifyAndNoConfig(t *testing.T) {
td := netx.NewTLSDialer(netx.Config{
td := NewTLSDialer(Config{
NoTLSVerify: true,
})
rtd, ok := td.(*netxlite.TLSDialerLegacy)
@ -398,7 +396,7 @@ func TestNewTLSDialerWithNoTLSVerifyAndNoConfig(t *testing.T) {
if rtd.Config.InsecureSkipVerify != true {
t.Fatal("expected true InsecureSkipVerify")
}
if rtd.Config.RootCAs != netx.DefaultCertPool() {
if rtd.Config.RootCAs != defaultCertPool {
t.Fatal("invalid Config.RootCAs")
}
if rtd.Dialer == nil {
@ -417,7 +415,7 @@ func TestNewTLSDialerWithNoTLSVerifyAndNoConfig(t *testing.T) {
}
func TestNewVanilla(t *testing.T) {
txp := netx.NewHTTPTransport(netx.Config{})
txp := NewHTTPTransport(Config{})
if _, ok := txp.(*netxlite.HTTPTransportWrapper); !ok {
t.Fatal("not the transport we expected")
}
@ -425,8 +423,12 @@ func TestNewVanilla(t *testing.T) {
func TestNewWithDialer(t *testing.T) {
expected := errors.New("mocked error")
dialer := netx.FakeDialer{Err: expected}
txp := netx.NewHTTPTransport(netx.Config{
dialer := &mocks.Dialer{
MockDialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
return nil, expected
},
}
txp := NewHTTPTransport(Config{
Dialer: dialer,
})
client := &http.Client{Transport: txp}
@ -453,7 +455,7 @@ func TestNewWithTLSDialer(t *testing.T) {
},
TLSHandshaker: &netxlite.TLSHandshakerConfigurable{},
}
txp := netx.NewHTTPTransport(netx.Config{
txp := NewHTTPTransport(Config{
TLSDialer: tlsDialer,
})
client := &http.Client{Transport: txp}
@ -468,7 +470,7 @@ func TestNewWithTLSDialer(t *testing.T) {
func TestNewWithByteCounter(t *testing.T) {
counter := bytecounter.New()
txp := netx.NewHTTPTransport(netx.Config{
txp := NewHTTPTransport(Config{
ByteCounter: counter,
})
bctxp, ok := txp.(*bytecounter.HTTPTransport)
@ -484,7 +486,7 @@ func TestNewWithByteCounter(t *testing.T) {
}
func TestNewWithLogger(t *testing.T) {
txp := netx.NewHTTPTransport(netx.Config{
txp := NewHTTPTransport(Config{
Logger: log.Log,
})
ltxp, ok := txp.(*netxlite.HTTPTransportLogger)
@ -501,7 +503,7 @@ func TestNewWithLogger(t *testing.T) {
func TestNewWithSaver(t *testing.T) {
saver := new(tracex.Saver)
txp := netx.NewHTTPTransport(netx.Config{
txp := NewHTTPTransport(Config{
HTTPSaver: saver,
})
stxptxp, ok := txp.(*tracex.HTTPTransportSaver)
@ -520,7 +522,7 @@ func TestNewWithSaver(t *testing.T) {
}
func TestNewDNSClientInvalidURL(t *testing.T) {
dnsclient, err := netx.NewDNSClient(netx.Config{}, "\t\t\t")
dnsclient, err := NewDNSClient(Config{}, "\t\t\t")
if err == nil || !strings.HasSuffix(err.Error(), "invalid control character in URL") {
t.Fatal("not the error we expected")
}
@ -530,7 +532,7 @@ func TestNewDNSClientInvalidURL(t *testing.T) {
}
func TestNewDNSClientUnsupportedScheme(t *testing.T) {
dnsclient, err := netx.NewDNSClient(netx.Config{}, "antani:///")
dnsclient, err := NewDNSClient(Config{}, "antani:///")
if err == nil || err.Error() != "unsupported resolver scheme" {
t.Fatal("not the error we expected")
}
@ -540,8 +542,8 @@ func TestNewDNSClientUnsupportedScheme(t *testing.T) {
}
func TestNewDNSClientSystemResolver(t *testing.T) {
dnsclient, err := netx.NewDNSClient(
netx.Config{}, "system:///")
dnsclient, err := NewDNSClient(
Config{}, "system:///")
if err != nil {
t.Fatal(err)
}
@ -552,8 +554,8 @@ func TestNewDNSClientSystemResolver(t *testing.T) {
}
func TestNewDNSClientEmpty(t *testing.T) {
dnsclient, err := netx.NewDNSClient(
netx.Config{}, "")
dnsclient, err := NewDNSClient(
Config{}, "")
if err != nil {
t.Fatal(err)
}
@ -564,8 +566,8 @@ func TestNewDNSClientEmpty(t *testing.T) {
}
func TestNewDNSClientPowerdnsDoH(t *testing.T) {
dnsclient, err := netx.NewDNSClient(
netx.Config{}, "doh://powerdns")
dnsclient, err := NewDNSClient(
Config{}, "doh://powerdns")
if err != nil {
t.Fatal(err)
}
@ -580,8 +582,8 @@ func TestNewDNSClientPowerdnsDoH(t *testing.T) {
}
func TestNewDNSClientGoogleDoH(t *testing.T) {
dnsclient, err := netx.NewDNSClient(
netx.Config{}, "doh://google")
dnsclient, err := NewDNSClient(
Config{}, "doh://google")
if err != nil {
t.Fatal(err)
}
@ -596,8 +598,8 @@ func TestNewDNSClientGoogleDoH(t *testing.T) {
}
func TestNewDNSClientCloudflareDoH(t *testing.T) {
dnsclient, err := netx.NewDNSClient(
netx.Config{}, "doh://cloudflare")
dnsclient, err := NewDNSClient(
Config{}, "doh://cloudflare")
if err != nil {
t.Fatal(err)
}
@ -613,8 +615,8 @@ func TestNewDNSClientCloudflareDoH(t *testing.T) {
func TestNewDNSClientCloudflareDoHSaver(t *testing.T) {
saver := new(tracex.Saver)
dnsclient, err := netx.NewDNSClient(
netx.Config{ResolveSaver: saver}, "doh://cloudflare")
dnsclient, err := NewDNSClient(
Config{ResolveSaver: saver}, "doh://cloudflare")
if err != nil {
t.Fatal(err)
}
@ -633,8 +635,8 @@ func TestNewDNSClientCloudflareDoHSaver(t *testing.T) {
}
func TestNewDNSClientUDP(t *testing.T) {
dnsclient, err := netx.NewDNSClient(
netx.Config{}, "udp://8.8.8.8:53")
dnsclient, err := NewDNSClient(
Config{}, "udp://8.8.8.8:53")
if err != nil {
t.Fatal(err)
}
@ -650,8 +652,8 @@ func TestNewDNSClientUDP(t *testing.T) {
func TestNewDNSClientUDPDNSSaver(t *testing.T) {
saver := new(tracex.Saver)
dnsclient, err := netx.NewDNSClient(
netx.Config{ResolveSaver: saver}, "udp://8.8.8.8:53")
dnsclient, err := NewDNSClient(
Config{ResolveSaver: saver}, "udp://8.8.8.8:53")
if err != nil {
t.Fatal(err)
}
@ -670,8 +672,8 @@ func TestNewDNSClientUDPDNSSaver(t *testing.T) {
}
func TestNewDNSClientTCP(t *testing.T) {
dnsclient, err := netx.NewDNSClient(
netx.Config{}, "tcp://8.8.8.8:53")
dnsclient, err := NewDNSClient(
Config{}, "tcp://8.8.8.8:53")
if err != nil {
t.Fatal(err)
}
@ -691,8 +693,8 @@ func TestNewDNSClientTCP(t *testing.T) {
func TestNewDNSClientTCPDNSSaver(t *testing.T) {
saver := new(tracex.Saver)
dnsclient, err := netx.NewDNSClient(
netx.Config{ResolveSaver: saver}, "tcp://8.8.8.8:53")
dnsclient, err := NewDNSClient(
Config{ResolveSaver: saver}, "tcp://8.8.8.8:53")
if err != nil {
t.Fatal(err)
}
@ -715,8 +717,8 @@ func TestNewDNSClientTCPDNSSaver(t *testing.T) {
}
func TestNewDNSClientDoT(t *testing.T) {
dnsclient, err := netx.NewDNSClient(
netx.Config{}, "dot://8.8.8.8:53")
dnsclient, err := NewDNSClient(
Config{}, "dot://8.8.8.8:53")
if err != nil {
t.Fatal(err)
}
@ -736,8 +738,8 @@ func TestNewDNSClientDoT(t *testing.T) {
func TestNewDNSClientDoTDNSSaver(t *testing.T) {
saver := new(tracex.Saver)
dnsclient, err := netx.NewDNSClient(
netx.Config{ResolveSaver: saver}, "dot://8.8.8.8:53")
dnsclient, err := NewDNSClient(
Config{ResolveSaver: saver}, "dot://8.8.8.8:53")
if err != nil {
t.Fatal(err)
}
@ -760,8 +762,8 @@ func TestNewDNSClientDoTDNSSaver(t *testing.T) {
}
func TestNewDNSCLientDoTWithoutPort(t *testing.T) {
c, err := netx.NewDNSClientWithOverrides(
netx.Config{}, "dot://8.8.8.8", "", "8.8.8.8", "")
c, err := NewDNSClientWithOverrides(
Config{}, "dot://8.8.8.8", "", "8.8.8.8", "")
if err != nil {
t.Fatal(err)
}
@ -771,8 +773,8 @@ func TestNewDNSCLientDoTWithoutPort(t *testing.T) {
}
func TestNewDNSCLientTCPWithoutPort(t *testing.T) {
c, err := netx.NewDNSClientWithOverrides(
netx.Config{}, "tcp://8.8.8.8", "", "8.8.8.8", "")
c, err := NewDNSClientWithOverrides(
Config{}, "tcp://8.8.8.8", "", "8.8.8.8", "")
if err != nil {
t.Fatal(err)
}
@ -782,8 +784,8 @@ func TestNewDNSCLientTCPWithoutPort(t *testing.T) {
}
func TestNewDNSCLientUDPWithoutPort(t *testing.T) {
c, err := netx.NewDNSClientWithOverrides(
netx.Config{}, "udp://8.8.8.8", "", "8.8.8.8", "")
c, err := NewDNSClientWithOverrides(
Config{}, "udp://8.8.8.8", "", "8.8.8.8", "")
if err != nil {
t.Fatal(err)
}
@ -793,33 +795,108 @@ func TestNewDNSCLientUDPWithoutPort(t *testing.T) {
}
func TestNewDNSClientBadDoTEndpoint(t *testing.T) {
_, err := netx.NewDNSClient(
netx.Config{}, "dot://bad:endpoint:53")
_, err := NewDNSClient(
Config{}, "dot://bad:endpoint:53")
if err == nil || !strings.Contains(err.Error(), "too many colons in address") {
t.Fatal("expected error with bad endpoint")
}
}
func TestNewDNSClientBadTCPEndpoint(t *testing.T) {
_, err := netx.NewDNSClient(
netx.Config{}, "tcp://bad:endpoint:853")
_, err := NewDNSClient(
Config{}, "tcp://bad:endpoint:853")
if err == nil || !strings.Contains(err.Error(), "too many colons in address") {
t.Fatal("expected error with bad endpoint")
}
}
func TestNewDNSClientBadUDPEndpoint(t *testing.T) {
_, err := netx.NewDNSClient(
netx.Config{}, "udp://bad:endpoint:853")
_, err := NewDNSClient(
Config{}, "udp://bad:endpoint:853")
if err == nil || !strings.Contains(err.Error(), "too many colons in address") {
t.Fatal("expected error with bad endpoint")
}
}
func TestNewDNSCLientWithInvalidTLSVersion(t *testing.T) {
_, err := netx.NewDNSClientWithOverrides(
netx.Config{}, "dot://8.8.8.8", "", "", "TLSv999")
_, err := NewDNSClientWithOverrides(
Config{}, "dot://8.8.8.8", "", "", "TLSv999")
if !errors.Is(err, netxlite.ErrInvalidTLSVersion) {
t.Fatalf("not the error we expected: %+v", err)
}
}
func TestSuccess(t *testing.T) {
if testing.Short() {
t.Skip("skip test in short mode")
}
log.SetLevel(log.DebugLevel)
counter := bytecounter.New()
config := Config{
BogonIsError: true,
ByteCounter: counter,
CacheResolutions: true,
ContextByteCounting: true,
DialSaver: &tracex.Saver{},
HTTPSaver: &tracex.Saver{},
Logger: log.Log,
ReadWriteSaver: &tracex.Saver{},
ResolveSaver: &tracex.Saver{},
TLSSaver: &tracex.Saver{},
}
txp := NewHTTPTransport(config)
client := &http.Client{Transport: txp}
resp, err := client.Get("https://www.google.com")
if err != nil {
t.Fatal(err)
}
if _, err = netxlite.ReadAllContext(context.Background(), resp.Body); err != nil {
t.Fatal(err)
}
if err = resp.Body.Close(); err != nil {
t.Fatal(err)
}
if counter.Sent.Load() <= 0 {
t.Fatal("no bytes sent?!")
}
if counter.Received.Load() <= 0 {
t.Fatal("no bytes received?!")
}
if ev := config.DialSaver.Read(); len(ev) <= 0 {
t.Fatal("no dial events?!")
}
if ev := config.HTTPSaver.Read(); len(ev) <= 0 {
t.Fatal("no HTTP events?!")
}
if ev := config.ReadWriteSaver.Read(); len(ev) <= 0 {
t.Fatal("no R/W events?!")
}
if ev := config.ResolveSaver.Read(); len(ev) <= 0 {
t.Fatal("no resolver events?!")
}
if ev := config.TLSSaver.Read(); len(ev) <= 0 {
t.Fatal("no TLS events?!")
}
}
func TestBogonResolutionNotBroken(t *testing.T) {
saver := new(tracex.Saver)
r := NewResolver(Config{
BogonIsError: true,
DNSCache: map[string][]string{
"www.google.com": {"127.0.0.1"},
},
ResolveSaver: saver,
Logger: log.Log,
})
addrs, err := r.LookupHost(context.Background(), "www.google.com")
if !errors.Is(err, netxlite.ErrDNSBogon) {
t.Fatal("not the error we expected")
}
if err.Error() != netxlite.FailureDNSBogonError {
t.Fatal("error not correctly wrapped")
}
if len(addrs) > 0 {
t.Fatal("expected no addresses here")
}
}

View File

@ -1,128 +0,0 @@
package resolver
import (
"context"
"errors"
"io"
"net"
"time"
"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 {
Conn net.Conn
Err error
}
func (d FakeDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
time.Sleep(10 * time.Microsecond)
return d.Conn, d.Err
}
type FakeConn struct {
ReadError error
ReadData []byte
SetDeadlineError error
SetReadDeadlineError error
SetWriteDeadlineError error
WriteError error
}
func (c *FakeConn) Read(b []byte) (int, error) {
if len(c.ReadData) > 0 {
n := copy(b, c.ReadData)
c.ReadData = c.ReadData[n:]
return n, nil
}
if c.ReadError != nil {
return 0, c.ReadError
}
return 0, io.EOF
}
func (c *FakeConn) Write(b []byte) (n int, err error) {
if c.WriteError != nil {
return 0, c.WriteError
}
n = len(b)
return
}
func (*FakeConn) Close() (err error) {
return
}
func (*FakeConn) LocalAddr() net.Addr {
return &net.TCPAddr{}
}
func (*FakeConn) RemoteAddr() net.Addr {
return &net.TCPAddr{}
}
func (c *FakeConn) SetDeadline(t time.Time) (err error) {
return c.SetDeadlineError
}
func (c *FakeConn) SetReadDeadline(t time.Time) (err error) {
return c.SetReadDeadlineError
}
func (c *FakeConn) SetWriteDeadline(t time.Time) (err error) {
return c.SetWriteDeadlineError
}
func NewFakeResolverThatFails() model.Resolver {
return NewFakeResolverWithExplicitError(netxlite.ErrOODNSNoSuchHost)
}
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")
},
}
}
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")
},
}
}

View File

@ -1,76 +0,0 @@
package resolver
import (
"net"
"testing"
"github.com/miekg/dns"
)
func GenReplyError(t *testing.T, code int) []byte {
question := dns.Question{
Name: dns.Fqdn("x.org"),
Qtype: dns.TypeA,
Qclass: dns.ClassINET,
}
query := new(dns.Msg)
query.Id = dns.Id()
query.RecursionDesired = true
query.Question = make([]dns.Question, 1)
query.Question[0] = question
reply := new(dns.Msg)
reply.Compress = true
reply.MsgHdr.RecursionAvailable = true
reply.SetRcode(query, code)
data, err := reply.Pack()
if err != nil {
t.Fatal(err)
}
return data
}
func GenReplySuccess(t *testing.T, qtype uint16, ips ...string) []byte {
question := dns.Question{
Name: dns.Fqdn("x.org"),
Qtype: qtype,
Qclass: dns.ClassINET,
}
query := new(dns.Msg)
query.Id = dns.Id()
query.RecursionDesired = true
query.Question = make([]dns.Question, 1)
query.Question[0] = question
reply := new(dns.Msg)
reply.Compress = true
reply.MsgHdr.RecursionAvailable = true
reply.SetReply(query)
for _, ip := range ips {
switch qtype {
case dns.TypeA:
reply.Answer = append(reply.Answer, &dns.A{
Hdr: dns.RR_Header{
Name: dns.Fqdn("x.org"),
Rrtype: qtype,
Class: dns.ClassINET,
Ttl: 0,
},
A: net.ParseIP(ip),
})
case dns.TypeAAAA:
reply.Answer = append(reply.Answer, &dns.AAAA{
Hdr: dns.RR_Header{
Name: dns.Fqdn("x.org"),
Rrtype: qtype,
Class: dns.ClassINET,
Ttl: 0,
},
AAAA: net.ParseIP(ip),
})
}
}
data, err := reply.Pack()
if err != nil {
t.Fatal(err)
}
return data
}

View File

@ -1,119 +0,0 @@
package resolver_test
import (
"context"
"crypto/tls"
"net"
"net/http"
"testing"
"github.com/apex/log"
"github.com/ooni/probe-cli/v3/internal/model"
"github.com/ooni/probe-cli/v3/internal/netxlite"
)
func init() {
log.SetLevel(log.DebugLevel)
}
func testresolverquick(t *testing.T, reso model.Resolver) {
if testing.Short() {
t.Skip("skip test in short mode")
}
reso = &netxlite.ResolverLogger{
Logger: log.Log,
Resolver: reso,
}
addrs, err := reso.LookupHost(context.Background(), "dns.google.com")
if err != nil {
t.Fatal(err)
}
if addrs == nil {
t.Fatal("expected non-nil addrs here")
}
var foundquad8 bool
for _, addr := range addrs {
// See https://github.com/ooni/probe-engine/pull/954/checks?check_run_id=1182269025
if addr == "8.8.8.8" || addr == "2001:4860:4860::8888" {
foundquad8 = true
}
}
if !foundquad8 {
t.Fatalf("did not find 8.8.8.8 in output; output=%+v", addrs)
}
}
// Ensuring we can handle Internationalized Domain Names (IDNs) without issues
func testresolverquickidna(t *testing.T, reso model.Resolver) {
if testing.Short() {
t.Skip("skip test in short mode")
}
reso = &netxlite.ResolverIDNA{
Resolver: &netxlite.ResolverLogger{
Logger: log.Log,
Resolver: reso,
},
}
addrs, err := reso.LookupHost(context.Background(), "яндекс.рф")
if err != nil {
t.Fatal(err)
}
if addrs == nil {
t.Fatal("expected non-nil addrs here")
}
}
func TestNewResolverSystem(t *testing.T) {
reso := netxlite.NewResolverSystem()
testresolverquick(t, reso)
testresolverquickidna(t, reso)
}
func TestNewResolverUDPAddress(t *testing.T) {
reso := netxlite.NewUnwrappedSerialResolver(
netxlite.NewUnwrappedDNSOverUDPTransport(netxlite.DefaultDialer, "8.8.8.8:53"))
testresolverquick(t, reso)
testresolverquickidna(t, reso)
}
func TestNewResolverUDPDomain(t *testing.T) {
reso := netxlite.NewUnwrappedSerialResolver(
netxlite.NewUnwrappedDNSOverUDPTransport(netxlite.DefaultDialer, "dns.google.com:53"))
testresolverquick(t, reso)
testresolverquickidna(t, reso)
}
func TestNewResolverTCPAddress(t *testing.T) {
reso := netxlite.NewUnwrappedSerialResolver(
netxlite.NewUnwrappedDNSOverTCPTransport(new(net.Dialer).DialContext, "8.8.8.8:53"))
testresolverquick(t, reso)
testresolverquickidna(t, reso)
}
func TestNewResolverTCPDomain(t *testing.T) {
reso := netxlite.NewUnwrappedSerialResolver(
netxlite.NewUnwrappedDNSOverTCPTransport(new(net.Dialer).DialContext, "dns.google.com:53"))
testresolverquick(t, reso)
testresolverquickidna(t, reso)
}
func TestNewResolverDoTAddress(t *testing.T) {
reso := netxlite.NewUnwrappedSerialResolver(
netxlite.NewUnwrappedDNSOverTLSTransport(new(tls.Dialer).DialContext, "8.8.8.8:853"))
testresolverquick(t, reso)
testresolverquickidna(t, reso)
}
func TestNewResolverDoTDomain(t *testing.T) {
reso := netxlite.NewUnwrappedSerialResolver(
netxlite.NewUnwrappedDNSOverTLSTransport(new(tls.Dialer).DialContext, "dns.google.com:853"))
testresolverquick(t, reso)
testresolverquickidna(t, reso)
}
func TestNewResolverDoH(t *testing.T) {
reso := netxlite.NewUnwrappedSerialResolver(
netxlite.NewUnwrappedDNSOverHTTPSTransport(http.DefaultClient, "https://cloudflare-dns.com/dns-query"))
testresolverquick(t, reso)
testresolverquickidna(t, reso)
}

View File

@ -1,80 +0,0 @@
package tlsdialer
import (
"context"
"crypto/tls"
"io"
"net"
"time"
)
type EOFDialer struct{}
func (EOFDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
time.Sleep(10 * time.Microsecond)
return nil, io.EOF
}
type EOFConnDialer struct{}
func (EOFConnDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
return EOFConn{}, nil
}
type EOFConn struct {
net.Conn
}
func (EOFConn) Read(p []byte) (int, error) {
time.Sleep(10 * time.Microsecond)
return 0, io.EOF
}
func (EOFConn) Write(p []byte) (int, error) {
time.Sleep(10 * time.Microsecond)
return 0, io.EOF
}
func (EOFConn) Close() error {
time.Sleep(10 * time.Microsecond)
return io.EOF
}
func (EOFConn) LocalAddr() net.Addr {
return EOFAddr{}
}
func (EOFConn) RemoteAddr() net.Addr {
return EOFAddr{}
}
func (EOFConn) SetDeadline(t time.Time) error {
return nil
}
func (EOFConn) SetReadDeadline(t time.Time) error {
return nil
}
func (EOFConn) SetWriteDeadline(t time.Time) error {
return nil
}
type EOFAddr struct{}
func (EOFAddr) Network() string {
return "tcp"
}
func (EOFAddr) String() string {
return "127.0.0.1:1234"
}
type EOFTLSHandshaker struct{}
func (EOFTLSHandshaker) Handshake(
ctx context.Context, conn net.Conn, config *tls.Config,
) (net.Conn, tls.ConnectionState, error) {
time.Sleep(10 * time.Microsecond)
return nil, tls.ConnectionState{}, io.EOF
}

View File

@ -1,71 +0,0 @@
package tlsdialer
import (
"context"
"io"
"net"
"time"
)
type FakeDialer struct {
Conn net.Conn
Err error
}
func (d FakeDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
time.Sleep(10 * time.Microsecond)
return d.Conn, d.Err
}
type FakeConn struct {
ReadError error
ReadData []byte
SetDeadlineError error
SetReadDeadlineError error
SetWriteDeadlineError error
WriteError error
}
func (c *FakeConn) Read(b []byte) (int, error) {
if len(c.ReadData) > 0 {
n := copy(b, c.ReadData)
c.ReadData = c.ReadData[n:]
return n, nil
}
if c.ReadError != nil {
return 0, c.ReadError
}
return 0, io.EOF
}
func (c *FakeConn) Write(b []byte) (n int, err error) {
if c.WriteError != nil {
return 0, c.WriteError
}
n = len(b)
return
}
func (*FakeConn) Close() (err error) {
return
}
func (*FakeConn) LocalAddr() net.Addr {
return &net.TCPAddr{}
}
func (*FakeConn) RemoteAddr() net.Addr {
return &net.TCPAddr{}
}
func (c *FakeConn) SetDeadline(t time.Time) (err error) {
return c.SetDeadlineError
}
func (c *FakeConn) SetReadDeadline(t time.Time) (err error) {
return c.SetReadDeadlineError
}
func (c *FakeConn) SetWriteDeadline(t time.Time) (err error) {
return c.SetWriteDeadlineError
}

View File

@ -1,35 +0,0 @@
package tlsdialer_test
import (
"net/http"
"testing"
"github.com/apex/log"
oohttp "github.com/ooni/oohttp"
"github.com/ooni/probe-cli/v3/internal/netxlite"
)
func TestTLSDialerSuccess(t *testing.T) {
if testing.Short() {
t.Skip("skip test in short mode")
}
log.SetLevel(log.DebugLevel)
dialer := &netxlite.TLSDialerLegacy{Dialer: netxlite.DefaultDialer,
TLSHandshaker: &netxlite.TLSHandshakerLogger{
TLSHandshaker: &netxlite.TLSHandshakerConfigurable{},
DebugLogger: log.Log,
},
}
txp := &oohttp.StdlibTransport{
Transport: &oohttp.Transport{
DialTLSContext: dialer.DialTLSContext,
ForceAttemptHTTP2: true,
},
}
client := &http.Client{Transport: txp}
resp, err := client.Get("https://www.google.com")
if err != nil {
t.Fatal(err)
}
resp.Body.Close()
}

View File

@ -1,35 +0,0 @@
package tlsdialer_test
import (
"context"
"crypto/tls"
"io"
"testing"
"time"
"github.com/ooni/probe-cli/v3/internal/engine/netx/tlsdialer"
"github.com/ooni/probe-cli/v3/internal/netxlite"
)
func TestSystemTLSHandshakerEOFError(t *testing.T) {
h := &netxlite.TLSHandshakerConfigurable{}
conn, _, err := h.Handshake(context.Background(), tlsdialer.EOFConn{}, &tls.Config{
ServerName: "x.org",
})
if err != io.EOF {
t.Fatal("not the error that we expected")
}
if conn != nil {
t.Fatal("expected nil con here")
}
}
type SetDeadlineConn struct {
tlsdialer.EOFConn
deadlines []time.Time
}
func (c *SetDeadlineConn) SetDeadline(t time.Time) error {
c.deadlines = append(c.deadlines, t)
return nil
}