refactor(netxlite): finish grouping tests (#488)
They are now more readable. I'll do another pass and start separating integration testing from unit testing. I think we need to have some always on integration testing for netxlite that runs on macOS, linux, and windows. See https://github.com/ooni/probe/issues/1591
This commit is contained in:
parent
493b72b170
commit
f2e3e5cc08
|
@ -1,12 +1,15 @@
|
|||
package netxlite_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
utls "gitlab.com/yawning/utls.git"
|
||||
)
|
||||
|
||||
func TestHTTPTransport(t *testing.T) {
|
||||
|
@ -49,3 +52,21 @@ func TestHTTP3Transport(t *testing.T) {
|
|||
txp.CloseIdleConnections()
|
||||
})
|
||||
}
|
||||
|
||||
func TestUTLSHandshaker(t *testing.T) {
|
||||
t.Run("with chrome fingerprint", func(t *testing.T) {
|
||||
h := netxlite.NewTLSHandshakerUTLS(log.Log, &utls.HelloChrome_Auto)
|
||||
cfg := &tls.Config{ServerName: "google.com"}
|
||||
conn, err := net.Dial("tcp", "google.com:443")
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error", err)
|
||||
}
|
||||
conn, _, err = h.Handshake(context.Background(), conn, cfg)
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error", err)
|
||||
}
|
||||
if conn == nil {
|
||||
t.Fatal("nil connection")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -7,7 +7,8 @@ import (
|
|||
"github.com/ooni/probe-cli/v3/internal/netxlite/mocks"
|
||||
)
|
||||
|
||||
func TestResolverLegacyAdapterWithCompatibleType(t *testing.T) {
|
||||
func TestResolverLegacyAdapter(t *testing.T) {
|
||||
t.Run("with compatible type", func(t *testing.T) {
|
||||
var called bool
|
||||
r := NewResolverLegacyAdapter(&mocks.Resolver{
|
||||
MockNetwork: func() string {
|
||||
|
@ -30,9 +31,9 @@ func TestResolverLegacyAdapterWithCompatibleType(t *testing.T) {
|
|||
if !called {
|
||||
t.Fatal("not called")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestResolverLegacyAdapterDefaults(t *testing.T) {
|
||||
t.Run("with incompatible type", func(t *testing.T) {
|
||||
r := NewResolverLegacyAdapter(&net.Resolver{})
|
||||
if r.Network() != "adapter" {
|
||||
t.Fatal("invalid Network")
|
||||
|
@ -41,9 +42,11 @@ func TestResolverLegacyAdapterDefaults(t *testing.T) {
|
|||
t.Fatal("invalid Address")
|
||||
}
|
||||
r.CloseIdleConnections() // does not crash
|
||||
})
|
||||
}
|
||||
|
||||
func TestDialerLegacyAdapterWithCompatibleType(t *testing.T) {
|
||||
func TestDialerLegacyAdapter(t *testing.T) {
|
||||
t.Run("with compatible type", func(t *testing.T) {
|
||||
var called bool
|
||||
r := NewDialerLegacyAdapter(&mocks.Dialer{
|
||||
MockCloseIdleConnections: func() {
|
||||
|
@ -54,14 +57,16 @@ func TestDialerLegacyAdapterWithCompatibleType(t *testing.T) {
|
|||
if !called {
|
||||
t.Fatal("not called")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestDialerLegacyAdapterDefaults(t *testing.T) {
|
||||
t.Run("with incompatible type", func(t *testing.T) {
|
||||
r := NewDialerLegacyAdapter(&net.Dialer{})
|
||||
r.CloseIdleConnections() // does not crash
|
||||
})
|
||||
}
|
||||
|
||||
func TestQUICContextDialerAdapterWithCompatibleType(t *testing.T) {
|
||||
func TestQUICContextDialerAdapter(t *testing.T) {
|
||||
t.Run("with compatible type", func(t *testing.T) {
|
||||
var called bool
|
||||
d := NewQUICDialerFromContextDialerAdapter(&mocks.QUICDialer{
|
||||
MockCloseIdleConnections: func() {
|
||||
|
@ -72,9 +77,10 @@ func TestQUICContextDialerAdapterWithCompatibleType(t *testing.T) {
|
|||
if !called {
|
||||
t.Fatal("not called")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestQUICContextDialerAdapterDefaults(t *testing.T) {
|
||||
t.Run("with incompatible type", func(t *testing.T) {
|
||||
d := NewQUICDialerFromContextDialerAdapter(&mocks.QUICContextDialer{})
|
||||
d.CloseIdleConnections() // does not crash
|
||||
})
|
||||
}
|
||||
|
|
|
@ -17,7 +17,9 @@ import (
|
|||
"github.com/ooni/probe-cli/v3/internal/netxlite/quicx"
|
||||
)
|
||||
|
||||
func TestQUICDialerQUICGoCannotSplitHostPort(t *testing.T) {
|
||||
func TestQUICDialerQUICGo(t *testing.T) {
|
||||
t.Run("DialContext", func(t *testing.T) {
|
||||
t.Run("cannot split host port", func(t *testing.T) {
|
||||
tlsConfig := &tls.Config{
|
||||
ServerName: "www.google.com",
|
||||
}
|
||||
|
@ -34,9 +36,9 @@ func TestQUICDialerQUICGoCannotSplitHostPort(t *testing.T) {
|
|||
if sess != nil {
|
||||
t.Fatal("expected nil sess here")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestQUICDialerQUICGoInvalidPort(t *testing.T) {
|
||||
t.Run("with invalid port", func(t *testing.T) {
|
||||
tlsConfig := &tls.Config{
|
||||
ServerName: "www.google.com",
|
||||
}
|
||||
|
@ -52,9 +54,9 @@ func TestQUICDialerQUICGoInvalidPort(t *testing.T) {
|
|||
if sess != nil {
|
||||
t.Fatal("expected nil sess here")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestQUICDialerQUICGoInvalidIP(t *testing.T) {
|
||||
t.Run("with invalid IP", func(t *testing.T) {
|
||||
tlsConfig := &tls.Config{
|
||||
ServerName: "www.google.com",
|
||||
}
|
||||
|
@ -70,9 +72,9 @@ func TestQUICDialerQUICGoInvalidIP(t *testing.T) {
|
|||
if sess != nil {
|
||||
t.Fatal("expected nil sess here")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestQUICDialerQUICGoCannotListen(t *testing.T) {
|
||||
t.Run("with listen error", func(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
tlsConfig := &tls.Config{
|
||||
ServerName: "www.google.com",
|
||||
|
@ -93,9 +95,9 @@ func TestQUICDialerQUICGoCannotListen(t *testing.T) {
|
|||
if sess != nil {
|
||||
t.Fatal("expected nil sess here")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestQUICDialerQUICGoCannotPerformHandshake(t *testing.T) {
|
||||
t.Run("with handshake failure", func(t *testing.T) {
|
||||
tlsConfig := &tls.Config{
|
||||
ServerName: "dns.google",
|
||||
}
|
||||
|
@ -112,9 +114,12 @@ func TestQUICDialerQUICGoCannotPerformHandshake(t *testing.T) {
|
|||
if sess != nil {
|
||||
log.Fatal("expected nil session here")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestQUICDialerQUICGoWorksAsIntended(t *testing.T) {
|
||||
t.Run("works as intended", func(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skip test in short mode")
|
||||
}
|
||||
tlsConfig := &tls.Config{
|
||||
ServerName: "dns.google",
|
||||
}
|
||||
|
@ -131,9 +136,9 @@ func TestQUICDialerQUICGoWorksAsIntended(t *testing.T) {
|
|||
if err := sess.CloseWithError(0, ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestQUICDialerQUICGoTLSDefaultsForWeb(t *testing.T) {
|
||||
t.Run("TLS defaults for web", func(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
var gotTLSConfig *tls.Config
|
||||
tlsConfig := &tls.Config{
|
||||
|
@ -172,9 +177,9 @@ func TestQUICDialerQUICGoTLSDefaultsForWeb(t *testing.T) {
|
|||
if tlsConfig.ServerName != gotTLSConfig.ServerName {
|
||||
t.Fatal("the ServerName field must match")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestQUICDialerQUICGoTLSDefaultsForDoQ(t *testing.T) {
|
||||
t.Run("TLS defaults for DoQ", func(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
var gotTLSConfig *tls.Config
|
||||
tlsConfig := &tls.Config{
|
||||
|
@ -213,9 +218,13 @@ func TestQUICDialerQUICGoTLSDefaultsForDoQ(t *testing.T) {
|
|||
if tlsConfig.ServerName != gotTLSConfig.ServerName {
|
||||
t.Fatal("the ServerName field must match")
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestQUICDialerResolverCloseIdleConnections(t *testing.T) {
|
||||
func TestQUICDialerResolver(t *testing.T) {
|
||||
|
||||
t.Run("CloseIdleConnections", func(t *testing.T) {
|
||||
var (
|
||||
forDialer bool
|
||||
forResolver bool
|
||||
|
@ -236,9 +245,10 @@ func TestQUICDialerResolverCloseIdleConnections(t *testing.T) {
|
|||
if !forDialer || !forResolver {
|
||||
t.Fatal("not called")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestQUICDialerResolverSuccess(t *testing.T) {
|
||||
t.Run("DialContext", func(t *testing.T) {
|
||||
t.Run("on success", func(t *testing.T) {
|
||||
tlsConfig := &tls.Config{}
|
||||
dialer := &quicDialerResolver{
|
||||
Resolver: NewResolverSystem(log.Log),
|
||||
|
@ -255,9 +265,9 @@ func TestQUICDialerResolverSuccess(t *testing.T) {
|
|||
if err := sess.CloseWithError(0, ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestQUICDialerResolverNoPort(t *testing.T) {
|
||||
t.Run("with missing port", func(t *testing.T) {
|
||||
tlsConfig := &tls.Config{}
|
||||
dialer := &quicDialerResolver{
|
||||
Resolver: NewResolverSystem(log.Log),
|
||||
|
@ -271,26 +281,9 @@ func TestQUICDialerResolverNoPort(t *testing.T) {
|
|||
if sess != nil {
|
||||
t.Fatal("expected a nil sess here")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestQUICDialerResolverLookupHostAddress(t *testing.T) {
|
||||
dialer := &quicDialerResolver{Resolver: &mocks.Resolver{
|
||||
MockLookupHost: func(ctx context.Context, domain string) ([]string, error) {
|
||||
// We should not arrive here and call this function but if we do then
|
||||
// there is going to be an error that fails this test.
|
||||
return nil, errors.New("mocked error")
|
||||
},
|
||||
}}
|
||||
addrs, err := dialer.lookupHost(context.Background(), "1.1.1.1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(addrs) != 1 || addrs[0] != "1.1.1.1" {
|
||||
t.Fatal("not the result we expected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICDialerResolverLookupHostFailure(t *testing.T) {
|
||||
t.Run("with lookup host failure", func(t *testing.T) {
|
||||
tlsConfig := &tls.Config{}
|
||||
expected := errors.New("mocked error")
|
||||
dialer := &quicDialerResolver{Resolver: &mocks.Resolver{
|
||||
|
@ -307,9 +300,9 @@ func TestQUICDialerResolverLookupHostFailure(t *testing.T) {
|
|||
if sess != nil {
|
||||
t.Fatal("expected nil sess")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestQUICDialerResolverInvalidPort(t *testing.T) {
|
||||
t.Run("with invalid port", func(t *testing.T) {
|
||||
// This test allows us to check for the case where every attempt
|
||||
// to establish a connection leads to a failure
|
||||
tlsConf := &tls.Config{}
|
||||
|
@ -331,9 +324,9 @@ func TestQUICDialerResolverInvalidPort(t *testing.T) {
|
|||
if sess != nil {
|
||||
t.Fatal("expected nil sess")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestQUICDialerResolverApplyTLSDefaults(t *testing.T) {
|
||||
t.Run("we apply TLS defaults", func(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
var gotTLSConfig *tls.Config
|
||||
tlsConfig := &tls.Config{}
|
||||
|
@ -361,9 +354,30 @@ func TestQUICDialerResolverApplyTLSDefaults(t *testing.T) {
|
|||
if gotTLSConfig.ServerName != "www.google.com" {
|
||||
t.Fatal("gotTLSConfig.ServerName has not been set")
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("lookup host with address", func(t *testing.T) {
|
||||
dialer := &quicDialerResolver{Resolver: &mocks.Resolver{
|
||||
MockLookupHost: func(ctx context.Context, domain string) ([]string, error) {
|
||||
// We should not arrive here and call this function but if we do then
|
||||
// there is going to be an error that fails this test.
|
||||
return nil, errors.New("mocked error")
|
||||
},
|
||||
}}
|
||||
addrs, err := dialer.lookupHost(context.Background(), "1.1.1.1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(addrs) != 1 || addrs[0] != "1.1.1.1" {
|
||||
t.Fatal("not the result we expected")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestQUICDialerLoggerCloseIdleConnections(t *testing.T) {
|
||||
func TestQUICLoggerDialer(t *testing.T) {
|
||||
|
||||
t.Run("CloseIdleConnections", func(t *testing.T) {
|
||||
var forDialer bool
|
||||
d := &quicDialerLogger{
|
||||
Dialer: &mocks.QUICDialer{
|
||||
|
@ -376,9 +390,10 @@ func TestQUICDialerLoggerCloseIdleConnections(t *testing.T) {
|
|||
if !forDialer {
|
||||
t.Fatal("not called")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestQUICDialerLoggerSuccess(t *testing.T) {
|
||||
t.Run("DialContext", func(t *testing.T) {
|
||||
t.Run("on success", func(t *testing.T) {
|
||||
d := &quicDialerLogger{
|
||||
Dialer: &mocks.QUICDialer{
|
||||
MockDialContext: func(ctx context.Context, network string,
|
||||
|
@ -404,9 +419,9 @@ func TestQUICDialerLoggerSuccess(t *testing.T) {
|
|||
if err := sess.CloseWithError(0, ""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestQUICDialerLoggerFailure(t *testing.T) {
|
||||
t.Run("on failure", func(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
d := &quicDialerLogger{
|
||||
Dialer: &mocks.QUICDialer{
|
||||
|
@ -428,46 +443,33 @@ func TestQUICDialerLoggerFailure(t *testing.T) {
|
|||
if sess != nil {
|
||||
t.Fatal("expected nil session")
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestNewQUICDialerWithoutResolverChain(t *testing.T) {
|
||||
func TestNewQUICDialer(t *testing.T) {
|
||||
ql := NewQUICListener()
|
||||
dlr := NewQUICDialerWithoutResolver(ql, log.Log)
|
||||
dlog, okay := dlr.(*quicDialerLogger)
|
||||
if !okay {
|
||||
t.Fatal("invalid type")
|
||||
}
|
||||
if dlog.Logger != log.Log {
|
||||
logger := dlr.(*quicDialerLogger)
|
||||
if logger.Logger != log.Log {
|
||||
t.Fatal("invalid logger")
|
||||
}
|
||||
dr, okay := dlog.Dialer.(*quicDialerResolver)
|
||||
if !okay {
|
||||
t.Fatal("invalid type")
|
||||
}
|
||||
if _, okay := dr.Resolver.(*nullResolver); !okay {
|
||||
resolver := logger.Dialer.(*quicDialerResolver)
|
||||
if _, okay := resolver.Resolver.(*nullResolver); !okay {
|
||||
t.Fatal("invalid resolver type")
|
||||
}
|
||||
dlog, okay = dr.Dialer.(*quicDialerLogger)
|
||||
if !okay {
|
||||
t.Fatal("invalid type")
|
||||
}
|
||||
if dlog.Logger != log.Log {
|
||||
logger = resolver.Dialer.(*quicDialerLogger)
|
||||
if logger.Logger != log.Log {
|
||||
t.Fatal("invalid logger")
|
||||
}
|
||||
ew, okay := dlog.Dialer.(*quicDialerErrWrapper)
|
||||
if !okay {
|
||||
t.Fatal("invalid type")
|
||||
}
|
||||
dgo, okay := ew.QUICDialer.(*quicDialerQUICGo)
|
||||
if !okay {
|
||||
t.Fatal("invalid type")
|
||||
}
|
||||
if dgo.QUICListener != ql {
|
||||
errWrapper := logger.Dialer.(*quicDialerErrWrapper)
|
||||
base := errWrapper.QUICDialer.(*quicDialerQUICGo)
|
||||
if base.QUICListener != ql {
|
||||
t.Fatal("invalid quic listener")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewSingleUseQUICDialerWorksAsIntended(t *testing.T) {
|
||||
func TestNewSingleUseQUICDialer(t *testing.T) {
|
||||
sess := &mocks.QUICEarlySession{}
|
||||
qd := NewSingleUseQUICDialer(sess)
|
||||
outsess, err := qd.DialContext(
|
||||
|
|
|
@ -15,6 +15,7 @@ func TestQuirkReduceErrors(t *testing.T) {
|
|||
t.Fatal("wrong result")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("single error", func(t *testing.T) {
|
||||
err := errors.New("mocked error")
|
||||
result := quirkReduceErrors([]error{err})
|
||||
|
@ -22,6 +23,7 @@ func TestQuirkReduceErrors(t *testing.T) {
|
|||
t.Fatal("wrong result")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("multiple errors", func(t *testing.T) {
|
||||
err1 := errors.New("mocked error #1")
|
||||
err2 := errors.New("mocked error #2")
|
||||
|
@ -30,6 +32,7 @@ func TestQuirkReduceErrors(t *testing.T) {
|
|||
t.Fatal("wrong result")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("multiple errors with meaningful ones", func(t *testing.T) {
|
||||
err1 := errors.New("mocked error #1")
|
||||
err2 := &errorsx.ErrWrapper{
|
||||
|
|
|
@ -15,7 +15,8 @@ import (
|
|||
"github.com/ooni/probe-cli/v3/internal/netxlite/mocks"
|
||||
)
|
||||
|
||||
func TestResolverSystemNetworkAddress(t *testing.T) {
|
||||
func TestResolverSystem(t *testing.T) {
|
||||
t.Run("Network and Address", func(t *testing.T) {
|
||||
r := &resolverSystem{}
|
||||
if r.Network() != "system" {
|
||||
t.Fatal("invalid Network")
|
||||
|
@ -23,9 +24,9 @@ func TestResolverSystemNetworkAddress(t *testing.T) {
|
|||
if r.Address() != "" {
|
||||
t.Fatal("invalid Address")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestResolverSystemWorksAsIntended(t *testing.T) {
|
||||
t.Run("works as intended", func(t *testing.T) {
|
||||
r := &resolverSystem{}
|
||||
defer r.CloseIdleConnections()
|
||||
addrs, err := r.LookupHost(context.Background(), "dns.google.com")
|
||||
|
@ -35,16 +36,17 @@ func TestResolverSystemWorksAsIntended(t *testing.T) {
|
|||
if addrs == nil {
|
||||
t.Fatal("expected non-nil result here")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestResolverSystemDefaultTimeout(t *testing.T) {
|
||||
t.Run("check default timeout", func(t *testing.T) {
|
||||
r := &resolverSystem{}
|
||||
if r.timeout() != 15*time.Second {
|
||||
t.Fatal("unexpected default timeout")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestResolverSystemWithTimeoutAndSuccess(t *testing.T) {
|
||||
t.Run("LookupHost", func(t *testing.T) {
|
||||
t.Run("with timeout and success", func(t *testing.T) {
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
r := &resolverSystem{
|
||||
|
@ -64,9 +66,9 @@ func TestResolverSystemWithTimeoutAndSuccess(t *testing.T) {
|
|||
t.Fatal("invalid addrs")
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
})
|
||||
|
||||
func TestResolverSystemWithTimeoutAndFailure(t *testing.T) {
|
||||
t.Run("with timeout and failure", func(t *testing.T) {
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
r := &resolverSystem{
|
||||
|
@ -86,9 +88,9 @@ func TestResolverSystemWithTimeoutAndFailure(t *testing.T) {
|
|||
t.Fatal("invalid addrs")
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
})
|
||||
|
||||
func TestResolverSystemWithNXDOMAIN(t *testing.T) {
|
||||
t.Run("with NXDOMAIN", func(t *testing.T) {
|
||||
r := &resolverSystem{
|
||||
testableLookupHost: func(ctx context.Context, domain string) ([]string, error) {
|
||||
return nil, errors.New("no such host")
|
||||
|
@ -102,9 +104,13 @@ func TestResolverSystemWithNXDOMAIN(t *testing.T) {
|
|||
if addrs != nil {
|
||||
t.Fatal("invalid addrs")
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestResolverLoggerWithSuccess(t *testing.T) {
|
||||
func TestResolverLogger(t *testing.T) {
|
||||
t.Run("LookupHost", func(t *testing.T) {
|
||||
t.Run("with success", func(t *testing.T) {
|
||||
expected := []string{"1.1.1.1"}
|
||||
r := resolverLogger{
|
||||
Logger: log.Log,
|
||||
|
@ -121,9 +127,9 @@ func TestResolverLoggerWithSuccess(t *testing.T) {
|
|||
if diff := cmp.Diff(expected, addrs); diff != "" {
|
||||
t.Fatal(diff)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestResolverLoggerWithFailure(t *testing.T) {
|
||||
t.Run("with failure", func(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
r := resolverLogger{
|
||||
Logger: log.Log,
|
||||
|
@ -140,9 +146,13 @@ func TestResolverLoggerWithFailure(t *testing.T) {
|
|||
if addrs != nil {
|
||||
t.Fatal("expected nil addr here")
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestResolverIDNAWorksAsIntended(t *testing.T) {
|
||||
func TestResolverIDNA(t *testing.T) {
|
||||
t.Run("LookupHost", func(t *testing.T) {
|
||||
t.Run("with valid IDNA in input", func(t *testing.T) {
|
||||
expectedIPs := []string{"77.88.55.66"}
|
||||
r := &resolverIDNA{
|
||||
Resolver: &mocks.Resolver{
|
||||
|
@ -162,9 +172,9 @@ func TestResolverIDNAWorksAsIntended(t *testing.T) {
|
|||
if diff := cmp.Diff(expectedIPs, addrs); diff != "" {
|
||||
t.Fatal(diff)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestResolverIDNAWithInvalidPunycode(t *testing.T) {
|
||||
t.Run("with invalid punycode", func(t *testing.T) {
|
||||
r := &resolverIDNA{Resolver: &mocks.Resolver{
|
||||
MockLookupHost: func(ctx context.Context, domain string) ([]string, error) {
|
||||
return nil, errors.New("should not happen")
|
||||
|
@ -179,35 +189,25 @@ func TestResolverIDNAWithInvalidPunycode(t *testing.T) {
|
|||
if addrs != nil {
|
||||
t.Fatal("expected no response here")
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestNewResolverTypeChain(t *testing.T) {
|
||||
r := NewResolverSystem(log.Log)
|
||||
ridna, ok := r.(*resolverIDNA)
|
||||
if !ok {
|
||||
t.Fatal("invalid resolver")
|
||||
}
|
||||
rl, ok := ridna.Resolver.(*resolverLogger)
|
||||
if !ok {
|
||||
t.Fatal("invalid resolver")
|
||||
}
|
||||
if rl.Logger != log.Log {
|
||||
func TestNewResolverSystem(t *testing.T) {
|
||||
resolver := NewResolverSystem(log.Log)
|
||||
idna := resolver.(*resolverIDNA)
|
||||
logger := idna.Resolver.(*resolverLogger)
|
||||
if logger.Logger != log.Log {
|
||||
t.Fatal("invalid logger")
|
||||
}
|
||||
scia, ok := rl.Resolver.(*resolverShortCircuitIPAddr)
|
||||
if !ok {
|
||||
t.Fatal("invalid resolver")
|
||||
}
|
||||
ew, ok := scia.Resolver.(*resolverErrWrapper)
|
||||
if !ok {
|
||||
t.Fatal("invalid resolver")
|
||||
}
|
||||
if _, ok := ew.Resolver.(*resolverSystem); !ok {
|
||||
t.Fatal("invalid resolver")
|
||||
}
|
||||
shortCircuit := logger.Resolver.(*resolverShortCircuitIPAddr)
|
||||
errWrapper := shortCircuit.Resolver.(*resolverErrWrapper)
|
||||
_ = errWrapper.Resolver.(*resolverSystem)
|
||||
}
|
||||
|
||||
func TestResolverShortCircuitIPAddrWithIPAddr(t *testing.T) {
|
||||
func TestResolverShortCircuitIPAddr(t *testing.T) {
|
||||
t.Run("LookupHost", func(t *testing.T) {
|
||||
t.Run("with IP addr", func(t *testing.T) {
|
||||
r := &resolverShortCircuitIPAddr{
|
||||
Resolver: &mocks.Resolver{
|
||||
MockLookupHost: func(ctx context.Context, domain string) ([]string, error) {
|
||||
|
@ -223,9 +223,9 @@ func TestResolverShortCircuitIPAddrWithIPAddr(t *testing.T) {
|
|||
if len(addrs) != 1 || addrs[0] != "8.8.8.8" {
|
||||
t.Fatal("invalid result")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestResolverShortCircuitIPAddrWithDomain(t *testing.T) {
|
||||
t.Run("with domain", func(t *testing.T) {
|
||||
r := &resolverShortCircuitIPAddr{
|
||||
Resolver: &mocks.Resolver{
|
||||
MockLookupHost: func(ctx context.Context, domain string) ([]string, error) {
|
||||
|
@ -241,9 +241,11 @@ func TestResolverShortCircuitIPAddrWithDomain(t *testing.T) {
|
|||
if addrs != nil {
|
||||
t.Fatal("invalid result")
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestNullResolverWorksAsIntended(t *testing.T) {
|
||||
func TestNullResolver(t *testing.T) {
|
||||
r := &nullResolver{}
|
||||
ctx := context.Background()
|
||||
addrs, err := r.LookupHost(ctx, "dns.google")
|
||||
|
|
|
@ -118,7 +118,10 @@ func TestConfigureTLSVersion(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestTLSHandshakerConfigurableWithError(t *testing.T) {
|
||||
func TestTLSHandshakerConfigurable(t *testing.T) {
|
||||
t.Run("Handshake", func(t *testing.T) {
|
||||
t.Run("with error", func(t *testing.T) {
|
||||
|
||||
var times []time.Time
|
||||
h := &tlsHandshakerConfigurable{}
|
||||
tcpConn := &mocks.Conn{
|
||||
|
@ -149,9 +152,9 @@ func TestTLSHandshakerConfigurableWithError(t *testing.T) {
|
|||
if !times[1].IsZero() {
|
||||
t.Fatal("did not clear timeout on exit")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestTLSHandshakerConfigurableSuccess(t *testing.T) {
|
||||
t.Run("with success", func(t *testing.T) {
|
||||
handler := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
rw.WriteHeader(200)
|
||||
})
|
||||
|
@ -182,9 +185,9 @@ func TestTLSHandshakerConfigurableSuccess(t *testing.T) {
|
|||
if connState.Version != tls.VersionTLS13 {
|
||||
t.Fatal("unexpected TLS version")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestTLSHandshakerConfigurableSetsDefaultRootCAs(t *testing.T) {
|
||||
t.Run("sets default root CA", func(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
var gotTLSConfig *tls.Config
|
||||
handshaker := &tlsHandshakerConfigurable{
|
||||
|
@ -220,9 +223,13 @@ func TestTLSHandshakerConfigurableSetsDefaultRootCAs(t *testing.T) {
|
|||
if gotTLSConfig.RootCAs != defaultCertPool {
|
||||
t.Fatal("gotTLSConfig.RootCAs has not been correctly set")
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestTLSHandshakerLoggerSuccess(t *testing.T) {
|
||||
func TestTLSHandshakerLogger(t *testing.T) {
|
||||
t.Run("Handshake", func(t *testing.T) {
|
||||
t.Run("on success", func(t *testing.T) {
|
||||
th := &tlsHandshakerLogger{
|
||||
TLSHandshaker: &mocks.TLSHandshaker{
|
||||
MockHandshake: func(ctx context.Context, conn net.Conn, config *tls.Config) (net.Conn, tls.ConnectionState, error) {
|
||||
|
@ -248,9 +255,9 @@ func TestTLSHandshakerLoggerSuccess(t *testing.T) {
|
|||
if !reflect.ValueOf(connState).IsZero() {
|
||||
t.Fatal("expected zero ConnectionState here")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestTLSHandshakerLoggerFailure(t *testing.T) {
|
||||
t.Run("on failure", func(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
th := &tlsHandshakerLogger{
|
||||
TLSHandshaker: &mocks.TLSHandshaker{
|
||||
|
@ -277,9 +284,12 @@ func TestTLSHandshakerLoggerFailure(t *testing.T) {
|
|||
if !reflect.ValueOf(connState).IsZero() {
|
||||
t.Fatal("expected zero ConnectionState here")
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestTLSDialerCloseIdleConnections(t *testing.T) {
|
||||
func TestTLSDialer(t *testing.T) {
|
||||
t.Run("CloseIdleConnections", func(t *testing.T) {
|
||||
var called bool
|
||||
dialer := &tlsDialer{
|
||||
Dialer: &mocks.Dialer{
|
||||
|
@ -292,9 +302,10 @@ func TestTLSDialerCloseIdleConnections(t *testing.T) {
|
|||
if !called {
|
||||
t.Fatal("not called")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestTLSDialerDialTLSContextFailureSplitHostPort(t *testing.T) {
|
||||
t.Run("DialTLSContext", func(t *testing.T) {
|
||||
t.Run("failure to split host and port", func(t *testing.T) {
|
||||
dialer := &tlsDialer{}
|
||||
ctx := context.Background()
|
||||
const address = "www.google.com" // missing port
|
||||
|
@ -305,9 +316,9 @@ func TestTLSDialerDialTLSContextFailureSplitHostPort(t *testing.T) {
|
|||
if conn != nil {
|
||||
t.Fatal("connection is not nil")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestTLSDialerDialTLSContextFailureDialing(t *testing.T) {
|
||||
t.Run("failure dialing", func(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cancel() // immediately fail
|
||||
dialer := tlsDialer{Dialer: &dialerSystem{}}
|
||||
|
@ -318,9 +329,9 @@ func TestTLSDialerDialTLSContextFailureDialing(t *testing.T) {
|
|||
if conn != nil {
|
||||
t.Fatal("connection is not nil")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestTLSDialerDialTLSContextFailureHandshaking(t *testing.T) {
|
||||
t.Run("failure handshaking", func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
dialer := tlsDialer{
|
||||
Config: &tls.Config{},
|
||||
|
@ -342,9 +353,9 @@ func TestTLSDialerDialTLSContextFailureHandshaking(t *testing.T) {
|
|||
if conn != nil {
|
||||
t.Fatal("connection is not nil")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestTLSDialerDialTLSContextSuccessHandshaking(t *testing.T) {
|
||||
t.Run("success handshaking", func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
dialer := tlsDialer{
|
||||
Dialer: &mocks.Dialer{MockDialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
|
@ -370,9 +381,11 @@ func TestTLSDialerDialTLSContextSuccessHandshaking(t *testing.T) {
|
|||
t.Fatal("connection is nil")
|
||||
}
|
||||
conn.Close()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
func TestTLSDialerConfigFromEmptyConfigForWeb(t *testing.T) {
|
||||
t.Run("config", func(t *testing.T) {
|
||||
t.Run("from empty config for web", func(t *testing.T) {
|
||||
d := &tlsDialer{}
|
||||
config := d.config("www.google.com", "443")
|
||||
if config.ServerName != "www.google.com" {
|
||||
|
@ -381,9 +394,9 @@ func TestTLSDialerConfigFromEmptyConfigForWeb(t *testing.T) {
|
|||
if diff := cmp.Diff(config.NextProtos, []string{"h2", "http/1.1"}); diff != "" {
|
||||
t.Fatal(diff)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestTLSDialerConfigFromEmptyConfigForDoT(t *testing.T) {
|
||||
t.Run("from empty config for dot", func(t *testing.T) {
|
||||
d := &tlsDialer{}
|
||||
config := d.config("dns.google", "853")
|
||||
if config.ServerName != "dns.google" {
|
||||
|
@ -392,9 +405,9 @@ func TestTLSDialerConfigFromEmptyConfigForDoT(t *testing.T) {
|
|||
if diff := cmp.Diff(config.NextProtos, []string{"dot"}); diff != "" {
|
||||
t.Fatal(diff)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestTLSDialerConfigWithServerName(t *testing.T) {
|
||||
t.Run("with server name", func(t *testing.T) {
|
||||
d := &tlsDialer{
|
||||
Config: &tls.Config{
|
||||
ServerName: "example.com",
|
||||
|
@ -407,9 +420,9 @@ func TestTLSDialerConfigWithServerName(t *testing.T) {
|
|||
if diff := cmp.Diff(config.NextProtos, []string{"dot"}); diff != "" {
|
||||
t.Fatal(diff)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestTLSDialerConfigWithALPN(t *testing.T) {
|
||||
t.Run("with alpn", func(t *testing.T) {
|
||||
d := &tlsDialer{
|
||||
Config: &tls.Config{
|
||||
NextProtos: []string{"h2"},
|
||||
|
@ -422,50 +435,40 @@ func TestTLSDialerConfigWithALPN(t *testing.T) {
|
|||
if diff := cmp.Diff(config.NextProtos, []string{"h2"}); diff != "" {
|
||||
t.Fatal(diff)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestNewTLSHandshakerStdlibTypes(t *testing.T) {
|
||||
func TestNewTLSHandshakerStdlib(t *testing.T) {
|
||||
th := NewTLSHandshakerStdlib(log.Log)
|
||||
thl, okay := th.(*tlsHandshakerLogger)
|
||||
if !okay {
|
||||
t.Fatal("invalid type")
|
||||
}
|
||||
if thl.Logger != log.Log {
|
||||
logger := th.(*tlsHandshakerLogger)
|
||||
if logger.Logger != log.Log {
|
||||
t.Fatal("invalid logger")
|
||||
}
|
||||
ew, okay := thl.TLSHandshaker.(*tlsHandshakerErrWrapper)
|
||||
if !okay {
|
||||
t.Fatal("invalid type")
|
||||
}
|
||||
thc, okay := ew.TLSHandshaker.(*tlsHandshakerConfigurable)
|
||||
if !okay {
|
||||
t.Fatal("invalid type")
|
||||
}
|
||||
if thc.NewConn != nil {
|
||||
errWrapper := logger.TLSHandshaker.(*tlsHandshakerErrWrapper)
|
||||
configurable := errWrapper.TLSHandshaker.(*tlsHandshakerConfigurable)
|
||||
if configurable.NewConn != nil {
|
||||
t.Fatal("expected nil NewConn")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewTLSDialerWorksAsIntended(t *testing.T) {
|
||||
func TestNewTLSDialer(t *testing.T) {
|
||||
d := &mocks.Dialer{}
|
||||
tlsh := &mocks.TLSHandshaker{}
|
||||
td := NewTLSDialer(d, tlsh)
|
||||
tdut, okay := td.(*tlsDialer)
|
||||
if !okay {
|
||||
t.Fatal("invalid type")
|
||||
}
|
||||
if tdut.Config == nil {
|
||||
th := &mocks.TLSHandshaker{}
|
||||
dialer := NewTLSDialer(d, th)
|
||||
tlsd := dialer.(*tlsDialer)
|
||||
if tlsd.Config == nil {
|
||||
t.Fatal("unexpected config")
|
||||
}
|
||||
if tdut.Dialer != d {
|
||||
if tlsd.Dialer != d {
|
||||
t.Fatal("unexpected dialer")
|
||||
}
|
||||
if tdut.TLSHandshaker != tlsh {
|
||||
if tlsd.TLSHandshaker != th {
|
||||
t.Fatal("invalid handshaker")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewSingleUseTLSDialerWorksAsIntended(t *testing.T) {
|
||||
func TestNewSingleUseTLSDialer(t *testing.T) {
|
||||
conn := &mocks.TLSConn{}
|
||||
d := NewSingleUseTLSDialer(conn)
|
||||
outconn, err := d.DialTLSContext(context.Background(), "", "")
|
||||
|
|
|
@ -2,9 +2,7 @@ package netxlite
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"net"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -13,47 +11,22 @@ import (
|
|||
utls "gitlab.com/yawning/utls.git"
|
||||
)
|
||||
|
||||
func TestUTLSHandshakerChrome(t *testing.T) {
|
||||
h := &tlsHandshakerConfigurable{
|
||||
NewConn: newConnUTLS(&utls.HelloChrome_Auto),
|
||||
}
|
||||
cfg := &tls.Config{ServerName: "google.com"}
|
||||
conn, err := net.Dial("tcp", "google.com:443")
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error", err)
|
||||
}
|
||||
conn, _, err = h.Handshake(context.Background(), conn, cfg)
|
||||
if err != nil {
|
||||
t.Fatal("unexpected error", err)
|
||||
}
|
||||
if conn == nil {
|
||||
t.Fatal("nil connection")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewTLSHandshakerUTLSTypes(t *testing.T) {
|
||||
func TestNewTLSHandshakerUTLS(t *testing.T) {
|
||||
th := NewTLSHandshakerUTLS(log.Log, &utls.HelloChrome_83)
|
||||
thl, okay := th.(*tlsHandshakerLogger)
|
||||
if !okay {
|
||||
t.Fatal("invalid type")
|
||||
}
|
||||
if thl.Logger != log.Log {
|
||||
logger := th.(*tlsHandshakerLogger)
|
||||
if logger.Logger != log.Log {
|
||||
t.Fatal("invalid logger")
|
||||
}
|
||||
ew, okay := thl.TLSHandshaker.(*tlsHandshakerErrWrapper)
|
||||
if !okay {
|
||||
t.Fatal("invalid type")
|
||||
}
|
||||
thc, okay := ew.TLSHandshaker.(*tlsHandshakerConfigurable)
|
||||
if !okay {
|
||||
t.Fatal("invalid type")
|
||||
}
|
||||
if thc.NewConn == nil {
|
||||
errWrapper := logger.TLSHandshaker.(*tlsHandshakerErrWrapper)
|
||||
configurable := errWrapper.TLSHandshaker.(*tlsHandshakerConfigurable)
|
||||
if configurable.NewConn == nil {
|
||||
t.Fatal("expected non-nil NewConn")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUTLSConnHandshakeNotInterruptedSuccess(t *testing.T) {
|
||||
func TestUTLSConn(t *testing.T) {
|
||||
t.Run("Handshake", func(t *testing.T) {
|
||||
t.Run("not interrupted with success", func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
conn := &utlsConn{
|
||||
testableHandshake: func() error {
|
||||
|
@ -64,9 +37,9 @@ func TestUTLSConnHandshakeNotInterruptedSuccess(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestUTLSConnHandshakeNotInterruptedFailure(t *testing.T) {
|
||||
t.Run("not interrupted with failure", func(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
ctx := context.Background()
|
||||
conn := &utlsConn{
|
||||
|
@ -78,9 +51,9 @@ func TestUTLSConnHandshakeNotInterruptedFailure(t *testing.T) {
|
|||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
func TestUTLSConnHandshakeInterrupted(t *testing.T) {
|
||||
t.Run("interrupted", func(t *testing.T) {
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
sigch := make(chan interface{})
|
||||
|
@ -99,9 +72,9 @@ func TestUTLSConnHandshakeInterrupted(t *testing.T) {
|
|||
}
|
||||
close(sigch)
|
||||
wg.Wait()
|
||||
}
|
||||
})
|
||||
|
||||
func TestUTLSConnHandshakePanic(t *testing.T) {
|
||||
t.Run("with panic", func(t *testing.T) {
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
ctx := context.Background()
|
||||
|
@ -116,4 +89,6 @@ func TestUTLSConnHandshakePanic(t *testing.T) {
|
|||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
wg.Wait()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user