refactor: move i/e/n/errorx to i/errorsx (#416)
Still working towards https://github.com/ooni/probe/issues/1505
This commit is contained in:
@@ -18,8 +18,8 @@ import (
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/geolocate"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/errorx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/errorsx"
|
||||
)
|
||||
|
||||
// ExtSpec describes a data format extension
|
||||
@@ -80,7 +80,7 @@ type TCPConnectEntry struct {
|
||||
func NewTCPConnectList(begin time.Time, events []trace.Event) []TCPConnectEntry {
|
||||
var out []TCPConnectEntry
|
||||
for _, event := range events {
|
||||
if event.Name != errorx.ConnectOperation {
|
||||
if event.Name != errorsx.ConnectOperation {
|
||||
continue
|
||||
}
|
||||
if event.Proto != "tcp" {
|
||||
@@ -110,11 +110,11 @@ func NewFailure(err error) *string {
|
||||
// The following code guarantees that the error is always wrapped even
|
||||
// when we could not actually hit our code that does the wrapping. A case
|
||||
// in which this happen is with context deadline for HTTP.
|
||||
err = errorx.SafeErrWrapperBuilder{
|
||||
err = errorsx.SafeErrWrapperBuilder{
|
||||
Error: err,
|
||||
Operation: errorx.TopLevelOperation,
|
||||
Operation: errorsx.TopLevelOperation,
|
||||
}.MaybeBuild()
|
||||
errWrapper := err.(*errorx.ErrWrapper)
|
||||
errWrapper := err.(*errorsx.ErrWrapper)
|
||||
s := errWrapper.Failure
|
||||
if s == "" {
|
||||
s = "unknown_failure: errWrapper.Failure is empty"
|
||||
@@ -128,8 +128,8 @@ func NewFailedOperation(err error) *string {
|
||||
return nil
|
||||
}
|
||||
var (
|
||||
errWrapper *errorx.ErrWrapper
|
||||
s = errorx.UnknownOperation
|
||||
errWrapper *errorsx.ErrWrapper
|
||||
s = errorsx.UnknownOperation
|
||||
)
|
||||
if errors.As(err, &errWrapper) && errWrapper.Operation != "" {
|
||||
s = errWrapper.Operation
|
||||
@@ -474,7 +474,7 @@ type NetworkEvent struct {
|
||||
func NewNetworkEventsList(begin time.Time, events []trace.Event) []NetworkEvent {
|
||||
var out []NetworkEvent
|
||||
for _, ev := range events {
|
||||
if ev.Name == errorx.ConnectOperation {
|
||||
if ev.Name == errorsx.ConnectOperation {
|
||||
out = append(out, NetworkEvent{
|
||||
Address: ev.Address,
|
||||
Failure: NewFailure(ev.Err),
|
||||
@@ -484,7 +484,7 @@ func NewNetworkEventsList(begin time.Time, events []trace.Event) []NetworkEvent
|
||||
})
|
||||
continue
|
||||
}
|
||||
if ev.Name == errorx.ReadOperation {
|
||||
if ev.Name == errorsx.ReadOperation {
|
||||
out = append(out, NetworkEvent{
|
||||
Failure: NewFailure(ev.Err),
|
||||
Operation: ev.Name,
|
||||
@@ -493,7 +493,7 @@ func NewNetworkEventsList(begin time.Time, events []trace.Event) []NetworkEvent
|
||||
})
|
||||
continue
|
||||
}
|
||||
if ev.Name == errorx.WriteOperation {
|
||||
if ev.Name == errorsx.WriteOperation {
|
||||
out = append(out, NetworkEvent{
|
||||
Failure: NewFailure(ev.Err),
|
||||
Operation: ev.Name,
|
||||
@@ -502,7 +502,7 @@ func NewNetworkEventsList(begin time.Time, events []trace.Event) []NetworkEvent
|
||||
})
|
||||
continue
|
||||
}
|
||||
if ev.Name == errorx.ReadFromOperation {
|
||||
if ev.Name == errorsx.ReadFromOperation {
|
||||
out = append(out, NetworkEvent{
|
||||
Address: ev.Address,
|
||||
Failure: NewFailure(ev.Err),
|
||||
@@ -512,7 +512,7 @@ func NewNetworkEventsList(begin time.Time, events []trace.Event) []NetworkEvent
|
||||
})
|
||||
continue
|
||||
}
|
||||
if ev.Name == errorx.WriteToOperation {
|
||||
if ev.Name == errorsx.WriteToOperation {
|
||||
out = append(out, NetworkEvent{
|
||||
Address: ev.Address,
|
||||
Failure: NewFailure(ev.Err),
|
||||
|
||||
@@ -14,8 +14,8 @@ import (
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/archival"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/errorx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/errorsx"
|
||||
)
|
||||
|
||||
func TestNewTCPConnectList(t *testing.T) {
|
||||
@@ -47,20 +47,20 @@ func TestNewTCPConnectList(t *testing.T) {
|
||||
}, {
|
||||
Address: "8.8.8.8:853",
|
||||
Duration: 30 * time.Millisecond,
|
||||
Name: errorx.ConnectOperation,
|
||||
Name: errorsx.ConnectOperation,
|
||||
Proto: "tcp",
|
||||
Time: begin.Add(130 * time.Millisecond),
|
||||
}, {
|
||||
Address: "8.8.8.8:853",
|
||||
Duration: 55 * time.Millisecond,
|
||||
Name: errorx.ConnectOperation,
|
||||
Name: errorsx.ConnectOperation,
|
||||
Proto: "udp",
|
||||
Time: begin.Add(130 * time.Millisecond),
|
||||
}, {
|
||||
Address: "8.8.4.4:53",
|
||||
Duration: 50 * time.Millisecond,
|
||||
Err: io.EOF,
|
||||
Name: errorx.ConnectOperation,
|
||||
Name: errorsx.ConnectOperation,
|
||||
Proto: "tcp",
|
||||
Time: begin.Add(180 * time.Millisecond),
|
||||
}},
|
||||
@@ -314,14 +314,14 @@ func TestNewDNSQueriesList(t *testing.T) {
|
||||
}, {
|
||||
Address: "8.8.8.8:853",
|
||||
Duration: 30 * time.Millisecond,
|
||||
Name: errorx.ConnectOperation,
|
||||
Name: errorsx.ConnectOperation,
|
||||
Proto: "tcp",
|
||||
Time: begin.Add(130 * time.Millisecond),
|
||||
}, {
|
||||
Address: "8.8.4.4:53",
|
||||
Duration: 50 * time.Millisecond,
|
||||
Err: io.EOF,
|
||||
Name: errorx.ConnectOperation,
|
||||
Name: errorsx.ConnectOperation,
|
||||
Proto: "tcp",
|
||||
Time: begin.Add(180 * time.Millisecond),
|
||||
}},
|
||||
@@ -371,7 +371,7 @@ func TestNewDNSQueriesList(t *testing.T) {
|
||||
args: args{
|
||||
begin: begin,
|
||||
events: []trace.Event{{
|
||||
Err: &errorx.ErrWrapper{Failure: errorx.FailureDNSNXDOMAINError},
|
||||
Err: &errorsx.ErrWrapper{Failure: errorsx.FailureDNSNXDOMAINError},
|
||||
Hostname: "dns.google.com",
|
||||
Name: "resolve_done",
|
||||
Time: begin.Add(200 * time.Millisecond),
|
||||
@@ -380,14 +380,14 @@ func TestNewDNSQueriesList(t *testing.T) {
|
||||
want: []archival.DNSQueryEntry{{
|
||||
Answers: nil,
|
||||
Failure: archival.NewFailure(
|
||||
&errorx.ErrWrapper{Failure: errorx.FailureDNSNXDOMAINError}),
|
||||
&errorsx.ErrWrapper{Failure: errorsx.FailureDNSNXDOMAINError}),
|
||||
Hostname: "dns.google.com",
|
||||
QueryType: "A",
|
||||
T: 0.2,
|
||||
}, {
|
||||
Answers: nil,
|
||||
Failure: archival.NewFailure(
|
||||
&errorx.ErrWrapper{Failure: errorx.FailureDNSNXDOMAINError}),
|
||||
&errorsx.ErrWrapper{Failure: errorsx.FailureDNSNXDOMAINError}),
|
||||
Hostname: "dns.google.com",
|
||||
QueryType: "AAAA",
|
||||
T: 0.2,
|
||||
@@ -425,35 +425,35 @@ func TestNewNetworkEventsList(t *testing.T) {
|
||||
args: args{
|
||||
begin: begin,
|
||||
events: []trace.Event{{
|
||||
Name: errorx.ConnectOperation,
|
||||
Name: errorsx.ConnectOperation,
|
||||
Address: "8.8.8.8:853",
|
||||
Err: io.EOF,
|
||||
Proto: "tcp",
|
||||
Time: begin.Add(7 * time.Millisecond),
|
||||
}, {
|
||||
Name: errorx.ReadOperation,
|
||||
Name: errorsx.ReadOperation,
|
||||
Err: context.Canceled,
|
||||
NumBytes: 7117,
|
||||
Time: begin.Add(11 * time.Millisecond),
|
||||
}, {
|
||||
Address: "8.8.8.8:853",
|
||||
Name: errorx.ReadFromOperation,
|
||||
Name: errorsx.ReadFromOperation,
|
||||
Err: context.Canceled,
|
||||
NumBytes: 7117,
|
||||
Time: begin.Add(11 * time.Millisecond),
|
||||
}, {
|
||||
Name: errorx.WriteOperation,
|
||||
Name: errorsx.WriteOperation,
|
||||
Err: websocket.ErrBadHandshake,
|
||||
NumBytes: 4114,
|
||||
Time: begin.Add(14 * time.Millisecond),
|
||||
}, {
|
||||
Address: "8.8.8.8:853",
|
||||
Name: errorx.WriteToOperation,
|
||||
Name: errorsx.WriteToOperation,
|
||||
Err: websocket.ErrBadHandshake,
|
||||
NumBytes: 4114,
|
||||
Time: begin.Add(14 * time.Millisecond),
|
||||
}, {
|
||||
Name: errorx.CloseOperation,
|
||||
Name: errorsx.CloseOperation,
|
||||
Err: websocket.ErrReadLimit,
|
||||
Time: begin.Add(17 * time.Millisecond),
|
||||
}},
|
||||
@@ -461,34 +461,34 @@ func TestNewNetworkEventsList(t *testing.T) {
|
||||
want: []archival.NetworkEvent{{
|
||||
Address: "8.8.8.8:853",
|
||||
Failure: archival.NewFailure(io.EOF),
|
||||
Operation: errorx.ConnectOperation,
|
||||
Operation: errorsx.ConnectOperation,
|
||||
Proto: "tcp",
|
||||
T: 0.007,
|
||||
}, {
|
||||
Failure: archival.NewFailure(context.Canceled),
|
||||
NumBytes: 7117,
|
||||
Operation: errorx.ReadOperation,
|
||||
Operation: errorsx.ReadOperation,
|
||||
T: 0.011,
|
||||
}, {
|
||||
Address: "8.8.8.8:853",
|
||||
Failure: archival.NewFailure(context.Canceled),
|
||||
NumBytes: 7117,
|
||||
Operation: errorx.ReadFromOperation,
|
||||
Operation: errorsx.ReadFromOperation,
|
||||
T: 0.011,
|
||||
}, {
|
||||
Failure: archival.NewFailure(websocket.ErrBadHandshake),
|
||||
NumBytes: 4114,
|
||||
Operation: errorx.WriteOperation,
|
||||
Operation: errorsx.WriteOperation,
|
||||
T: 0.014,
|
||||
}, {
|
||||
Address: "8.8.8.8:853",
|
||||
Failure: archival.NewFailure(websocket.ErrBadHandshake),
|
||||
NumBytes: 4114,
|
||||
Operation: errorx.WriteToOperation,
|
||||
Operation: errorsx.WriteToOperation,
|
||||
T: 0.014,
|
||||
}, {
|
||||
Failure: archival.NewFailure(websocket.ErrReadLimit),
|
||||
Operation: errorx.CloseOperation,
|
||||
Operation: errorsx.CloseOperation,
|
||||
T: 0.017,
|
||||
}},
|
||||
}}
|
||||
@@ -523,7 +523,7 @@ func TestNewTLSHandshakesList(t *testing.T) {
|
||||
args: args{
|
||||
begin: begin,
|
||||
events: []trace.Event{{
|
||||
Name: errorx.CloseOperation,
|
||||
Name: errorsx.CloseOperation,
|
||||
Err: websocket.ErrReadLimit,
|
||||
Time: begin.Add(17 * time.Millisecond),
|
||||
}, {
|
||||
@@ -929,18 +929,18 @@ func TestNewFailure(t *testing.T) {
|
||||
}, {
|
||||
name: "when error is wrapped and failure meaningful",
|
||||
args: args{
|
||||
err: &errorx.ErrWrapper{
|
||||
Failure: errorx.FailureConnectionRefused,
|
||||
err: &errorsx.ErrWrapper{
|
||||
Failure: errorsx.FailureConnectionRefused,
|
||||
},
|
||||
},
|
||||
want: func() *string {
|
||||
s := errorx.FailureConnectionRefused
|
||||
s := errorsx.FailureConnectionRefused
|
||||
return &s
|
||||
}(),
|
||||
}, {
|
||||
name: "when error is wrapped and failure is not meaningful",
|
||||
args: args{
|
||||
err: &errorx.ErrWrapper{},
|
||||
err: &errorsx.ErrWrapper{},
|
||||
},
|
||||
want: func() *string {
|
||||
s := "unknown_failure: errWrapper.Failure is empty"
|
||||
@@ -1002,24 +1002,24 @@ func TestNewFailedOperation(t *testing.T) {
|
||||
}, {
|
||||
name: "With wrapped error and non-empty operation",
|
||||
args: args{
|
||||
err: &errorx.ErrWrapper{
|
||||
Failure: errorx.FailureConnectionRefused,
|
||||
Operation: errorx.ConnectOperation,
|
||||
err: &errorsx.ErrWrapper{
|
||||
Failure: errorsx.FailureConnectionRefused,
|
||||
Operation: errorsx.ConnectOperation,
|
||||
},
|
||||
},
|
||||
want: (func() *string {
|
||||
s := errorx.ConnectOperation
|
||||
s := errorsx.ConnectOperation
|
||||
return &s
|
||||
})(),
|
||||
}, {
|
||||
name: "With wrapped error and empty operation",
|
||||
args: args{
|
||||
err: &errorx.ErrWrapper{
|
||||
Failure: errorx.FailureConnectionRefused,
|
||||
err: &errorsx.ErrWrapper{
|
||||
Failure: errorsx.FailureConnectionRefused,
|
||||
},
|
||||
},
|
||||
want: (func() *string {
|
||||
s := errorx.UnknownOperation
|
||||
s := errorsx.UnknownOperation
|
||||
return &s
|
||||
})(),
|
||||
}, {
|
||||
@@ -1028,7 +1028,7 @@ func TestNewFailedOperation(t *testing.T) {
|
||||
err: io.EOF,
|
||||
},
|
||||
want: (func() *string {
|
||||
s := errorx.UnknownOperation
|
||||
s := errorsx.UnknownOperation
|
||||
return &s
|
||||
})(),
|
||||
}}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/errorx"
|
||||
"github.com/ooni/probe-cli/v3/internal/errorsx"
|
||||
)
|
||||
|
||||
// errorWrapperDialer is a dialer that performs err wrapping
|
||||
@@ -15,9 +15,9 @@ type errorWrapperDialer struct {
|
||||
// DialContext implements Dialer.DialContext
|
||||
func (d *errorWrapperDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
conn, err := d.Dialer.DialContext(ctx, network, address)
|
||||
err = errorx.SafeErrWrapperBuilder{
|
||||
err = errorsx.SafeErrWrapperBuilder{
|
||||
Error: err,
|
||||
Operation: errorx.ConnectOperation,
|
||||
Operation: errorsx.ConnectOperation,
|
||||
}.MaybeBuild()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -33,9 +33,9 @@ type errorWrapperConn struct {
|
||||
// Read implements net.Conn.Read
|
||||
func (c *errorWrapperConn) Read(b []byte) (n int, err error) {
|
||||
n, err = c.Conn.Read(b)
|
||||
err = errorx.SafeErrWrapperBuilder{
|
||||
err = errorsx.SafeErrWrapperBuilder{
|
||||
Error: err,
|
||||
Operation: errorx.ReadOperation,
|
||||
Operation: errorsx.ReadOperation,
|
||||
}.MaybeBuild()
|
||||
return
|
||||
}
|
||||
@@ -43,9 +43,9 @@ func (c *errorWrapperConn) Read(b []byte) (n int, err error) {
|
||||
// Write implements net.Conn.Write
|
||||
func (c *errorWrapperConn) Write(b []byte) (n int, err error) {
|
||||
n, err = c.Conn.Write(b)
|
||||
err = errorx.SafeErrWrapperBuilder{
|
||||
err = errorsx.SafeErrWrapperBuilder{
|
||||
Error: err,
|
||||
Operation: errorx.WriteOperation,
|
||||
Operation: errorsx.WriteOperation,
|
||||
}.MaybeBuild()
|
||||
return
|
||||
}
|
||||
@@ -53,9 +53,9 @@ func (c *errorWrapperConn) Write(b []byte) (n int, err error) {
|
||||
// Close implements net.Conn.Close
|
||||
func (c *errorWrapperConn) Close() (err error) {
|
||||
err = c.Conn.Close()
|
||||
err = errorx.SafeErrWrapperBuilder{
|
||||
err = errorsx.SafeErrWrapperBuilder{
|
||||
Error: err,
|
||||
Operation: errorx.CloseOperation,
|
||||
Operation: errorsx.CloseOperation,
|
||||
}.MaybeBuild()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/errorx"
|
||||
"github.com/ooni/probe-cli/v3/internal/errorsx"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxmocks"
|
||||
)
|
||||
|
||||
@@ -22,21 +22,21 @@ func TestErrorWrapperFailure(t *testing.T) {
|
||||
if conn != nil {
|
||||
t.Fatal("expected a nil conn here")
|
||||
}
|
||||
errorWrapperCheckErr(t, err, errorx.ConnectOperation)
|
||||
errorWrapperCheckErr(t, err, errorsx.ConnectOperation)
|
||||
}
|
||||
|
||||
func errorWrapperCheckErr(t *testing.T, err error, op string) {
|
||||
if !errors.Is(err, io.EOF) {
|
||||
t.Fatal("expected another error here")
|
||||
}
|
||||
var errWrapper *errorx.ErrWrapper
|
||||
var errWrapper *errorsx.ErrWrapper
|
||||
if !errors.As(err, &errWrapper) {
|
||||
t.Fatal("cannot cast to ErrWrapper")
|
||||
}
|
||||
if errWrapper.Operation != op {
|
||||
t.Fatal("unexpected Operation")
|
||||
}
|
||||
if errWrapper.Failure != errorx.FailureEOFError {
|
||||
if errWrapper.Failure != errorsx.FailureEOFError {
|
||||
t.Fatal("unexpected failure")
|
||||
}
|
||||
}
|
||||
@@ -69,11 +69,11 @@ func TestErrorWrapperSuccess(t *testing.T) {
|
||||
t.Fatal("expected non-nil conn here")
|
||||
}
|
||||
count, err := conn.Read(nil)
|
||||
errorWrapperCheckIOResult(t, count, err, errorx.ReadOperation)
|
||||
errorWrapperCheckIOResult(t, count, err, errorsx.ReadOperation)
|
||||
count, err = conn.Write(nil)
|
||||
errorWrapperCheckIOResult(t, count, err, errorx.WriteOperation)
|
||||
errorWrapperCheckIOResult(t, count, err, errorsx.WriteOperation)
|
||||
err = conn.Close()
|
||||
errorWrapperCheckErr(t, err, errorx.CloseOperation)
|
||||
errorWrapperCheckErr(t, err, errorsx.CloseOperation)
|
||||
}
|
||||
|
||||
func errorWrapperCheckIOResult(t *testing.T, count int, err error, op string) {
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/errorx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/errorsx"
|
||||
)
|
||||
|
||||
// saverDialer saves events occurring during the dial
|
||||
@@ -24,7 +24,7 @@ func (d *saverDialer) DialContext(ctx context.Context, network, address string)
|
||||
Address: address,
|
||||
Duration: stop.Sub(start),
|
||||
Err: err,
|
||||
Name: errorx.ConnectOperation,
|
||||
Name: errorsx.ConnectOperation,
|
||||
Proto: network,
|
||||
Time: stop,
|
||||
})
|
||||
@@ -61,7 +61,7 @@ func (c *saverConn) Read(p []byte) (int, error) {
|
||||
Duration: stop.Sub(start),
|
||||
Err: err,
|
||||
NumBytes: count,
|
||||
Name: errorx.ReadOperation,
|
||||
Name: errorsx.ReadOperation,
|
||||
Time: stop,
|
||||
})
|
||||
return count, err
|
||||
@@ -76,7 +76,7 @@ func (c *saverConn) Write(p []byte) (int, error) {
|
||||
Duration: stop.Sub(start),
|
||||
Err: err,
|
||||
NumBytes: count,
|
||||
Name: errorx.WriteOperation,
|
||||
Name: errorsx.WriteOperation,
|
||||
Time: stop,
|
||||
})
|
||||
return count, err
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/errorx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/errorsx"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxmocks"
|
||||
)
|
||||
|
||||
@@ -44,7 +44,7 @@ func TestSaverDialerFailure(t *testing.T) {
|
||||
if !errors.Is(ev[0].Err, expected) {
|
||||
t.Fatal("unexpected Err")
|
||||
}
|
||||
if ev[0].Name != errorx.ConnectOperation {
|
||||
if ev[0].Name != errorsx.ConnectOperation {
|
||||
t.Fatal("unexpected Name")
|
||||
}
|
||||
if ev[0].Proto != "tcp" {
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
package errorx
|
||||
|
||||
import "golang.org/x/sys/unix"
|
||||
|
||||
const (
|
||||
ECANCELED = unix.ECANCELED
|
||||
ECONNREFUSED = unix.ECONNREFUSED
|
||||
ECONNRESET = unix.ECONNRESET
|
||||
EHOSTUNREACH = unix.EHOSTUNREACH
|
||||
ETIMEDOUT = unix.ETIMEDOUT
|
||||
EAFNOSUPPORT = unix.EAFNOSUPPORT
|
||||
EADDRINUSE = unix.EADDRINUSE
|
||||
EADDRNOTAVAIL = unix.EADDRNOTAVAIL
|
||||
EISCONN = unix.EISCONN
|
||||
EFAULT = unix.EFAULT
|
||||
EBADF = unix.EBADF
|
||||
ECONNABORTED = unix.ECONNABORTED
|
||||
EALREADY = unix.EALREADY
|
||||
EDESTADDRREQ = unix.EDESTADDRREQ
|
||||
EINTR = unix.EINTR
|
||||
EINVAL = unix.EINVAL
|
||||
EMSGSIZE = unix.EMSGSIZE
|
||||
ENETDOWN = unix.ENETDOWN
|
||||
ENETRESET = unix.ENETRESET
|
||||
ENETUNREACH = unix.ENETUNREACH
|
||||
ENOBUFS = unix.ENOBUFS
|
||||
ENOPROTOOPT = unix.ENOPROTOOPT
|
||||
ENOTSOCK = unix.ENOTSOCK
|
||||
ENOTCONN = unix.ENOTCONN
|
||||
EWOULDBLOCK = unix.EWOULDBLOCK
|
||||
EACCES = unix.EACCES
|
||||
EPROTONOSUPPORT = unix.EPROTONOSUPPORT
|
||||
EPROTOTYPE = unix.EPROTOTYPE
|
||||
)
|
||||
@@ -1,34 +0,0 @@
|
||||
package errorx
|
||||
|
||||
import "golang.org/x/sys/windows"
|
||||
|
||||
const (
|
||||
ECANCELED = windows.ECANCELED
|
||||
ECONNREFUSED = windows.ECONNREFUSED
|
||||
ECONNRESET = windows.ECONNRESET
|
||||
EHOSTUNREACH = windows.EHOSTUNREACH
|
||||
ETIMEDOUT = windows.ETIMEDOUT
|
||||
EAFNOSUPPORT = windows.EAFNOSUPPORT
|
||||
EADDRINUSE = windows.EADDRINUSE
|
||||
EADDRNOTAVAIL = windows.EADDRNOTAVAIL
|
||||
EISCONN = windows.EISCONN
|
||||
EFAULT = windows.EFAULT
|
||||
EBADF = windows.EBADF
|
||||
ECONNABORTED = windows.ECONNABORTED
|
||||
EALREADY = windows.EALREADY
|
||||
EDESTADDRREQ = windows.EDESTADDRREQ
|
||||
EINTR = windows.EINTR
|
||||
EINVAL = windows.EINVAL
|
||||
EMSGSIZE = windows.EMSGSIZE
|
||||
ENETDOWN = windows.ENETDOWN
|
||||
ENETRESET = windows.ENETRESET
|
||||
ENETUNREACH = windows.ENETUNREACH
|
||||
ENOBUFS = windows.ENOBUFS
|
||||
ENOPROTOOPT = windows.ENOPROTOOPT
|
||||
ENOTSOCK = windows.ENOTSOCK
|
||||
ENOTCONN = windows.ENOTCONN
|
||||
EWOULDBLOCK = windows.EWOULDBLOCK
|
||||
EACCES = windows.EACCES
|
||||
EPROTONOSUPPORT = windows.EPROTONOSUPPORT
|
||||
EPROTOTYPE = windows.EPROTOTYPE
|
||||
)
|
||||
@@ -1,400 +0,0 @@
|
||||
// Package errorx contains error extensions
|
||||
package errorx
|
||||
|
||||
// TODO: eventually we want to re-structure the error classification code by clearly separating the layers where the error occur:
|
||||
//
|
||||
// - errno.go and errno_test.go: contain only the errno classifier (for system errors)
|
||||
// - qtls.go and qtls_test.go: contain qtls dialers, handshaker, classifier
|
||||
// - tls.go and tls_test.go: contain tls dialers, handshaker, classifier
|
||||
// - resolver.go and resolver_test.go: contain dialers and classifier for resolving
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
"github.com/ooni/probe-cli/v3/internal/scrubber"
|
||||
)
|
||||
|
||||
const (
|
||||
// FailureConnectionRefused means ECONNREFUSED.
|
||||
FailureConnectionRefused = "connection_refused"
|
||||
|
||||
// FailureConnectionReset means ECONNRESET.
|
||||
FailureConnectionReset = "connection_reset"
|
||||
|
||||
// FailureDNSBogonError means we detected bogon in DNS reply.
|
||||
FailureDNSBogonError = "dns_bogon_error"
|
||||
|
||||
// FailureDNSNXDOMAINError means we got NXDOMAIN in DNS reply.
|
||||
FailureDNSNXDOMAINError = "dns_nxdomain_error"
|
||||
|
||||
// FailureEOFError means we got unexpected EOF on connection.
|
||||
FailureEOFError = "eof_error"
|
||||
|
||||
// FailureGenericTimeoutError means we got some timer has expired.
|
||||
FailureGenericTimeoutError = "generic_timeout_error"
|
||||
|
||||
// FailureHostUnreachable means that there is "no route to host".
|
||||
FailureHostUnreachable = "host_unreachable"
|
||||
|
||||
// FailureInterrupted means that the user interrupted us.
|
||||
FailureInterrupted = "interrupted"
|
||||
|
||||
// FailureNoCompatibleQUICVersion means that the server does not support the proposed QUIC version
|
||||
FailureNoCompatibleQUICVersion = "quic_incompatible_version"
|
||||
|
||||
// FailureSSLHandshake means that the negotiation of cryptographic parameters failed
|
||||
FailureSSLHandshake = "ssl_failed_handshake"
|
||||
|
||||
// FailureSSLInvalidHostname means we got certificate is not valid for SNI.
|
||||
FailureSSLInvalidHostname = "ssl_invalid_hostname"
|
||||
|
||||
// FailureSSLUnknownAuthority means we cannot find CA validating certificate.
|
||||
FailureSSLUnknownAuthority = "ssl_unknown_authority"
|
||||
|
||||
// FailureSSLInvalidCertificate means certificate experired or other
|
||||
// sort of errors causing it to be invalid.
|
||||
FailureSSLInvalidCertificate = "ssl_invalid_certificate"
|
||||
|
||||
// FailureJSONParseError indicates that we couldn't parse a JSON
|
||||
FailureJSONParseError = "json_parse_error"
|
||||
)
|
||||
|
||||
// TLS alert protocol as defined in RFC8446
|
||||
const (
|
||||
// Sender was unable to negotiate an acceptable set of security parameters given the options available.
|
||||
TLSAlertHandshakeFailure = 40
|
||||
|
||||
// Certificate was corrupt, contained signatures that did not verify correctly, etc.
|
||||
TLSAlertBadCertificate = 42
|
||||
|
||||
// Certificate was of an unsupported type.
|
||||
TLSAlertUnsupportedCertificate = 43
|
||||
|
||||
// Certificate was revoked by its signer.
|
||||
TLSAlertCertificateRevoked = 44
|
||||
|
||||
// Certificate has expired or is not currently valid.
|
||||
TLSAlertCertificateExpired = 45
|
||||
|
||||
// Some unspecified issue arose in processing the certificate, rendering it unacceptable.
|
||||
TLSAlertCertificateUnknown = 46
|
||||
|
||||
// Certificate was not accepted because the CA certificate could not be located or could not be matched with a known trust anchor.
|
||||
TLSAlertUnknownCA = 48
|
||||
|
||||
// Handshake (not record layer) cryptographic operation failed.
|
||||
TLSAlertDecryptError = 51
|
||||
|
||||
// Sent by servers when no server exists identified by the name provided by the client via the "server_name" extension.
|
||||
TLSUnrecognizedName = 112
|
||||
)
|
||||
|
||||
const (
|
||||
// ResolveOperation is the operation where we resolve a domain name
|
||||
ResolveOperation = "resolve"
|
||||
|
||||
// ConnectOperation is the operation where we do a TCP connect
|
||||
ConnectOperation = "connect"
|
||||
|
||||
// TLSHandshakeOperation is the TLS handshake
|
||||
TLSHandshakeOperation = "tls_handshake"
|
||||
|
||||
// QUICHandshakeOperation is the handshake to setup a QUIC connection
|
||||
QUICHandshakeOperation = "quic_handshake"
|
||||
|
||||
// HTTPRoundTripOperation is the HTTP round trip
|
||||
HTTPRoundTripOperation = "http_round_trip"
|
||||
|
||||
// CloseOperation is when we close a socket
|
||||
CloseOperation = "close"
|
||||
|
||||
// ReadOperation is when we read from a socket
|
||||
ReadOperation = "read"
|
||||
|
||||
// WriteOperation is when we write to a socket
|
||||
WriteOperation = "write"
|
||||
|
||||
// ReadFromOperation is when we read from an UDP socket
|
||||
ReadFromOperation = "read_from"
|
||||
|
||||
// WriteToOperation is when we write to an UDP socket
|
||||
WriteToOperation = "write_to"
|
||||
|
||||
// UnknownOperation is when we cannot determine the operation
|
||||
UnknownOperation = "unknown"
|
||||
|
||||
// TopLevelOperation is used when the failure happens at top level. This
|
||||
// happens for example with urlgetter with a cancelled context.
|
||||
TopLevelOperation = "top_level"
|
||||
)
|
||||
|
||||
// ErrDNSBogon indicates that we found a bogon address. This is the
|
||||
// correct value with which to initialize MeasurementRoot.ErrDNSBogon
|
||||
// to tell this library to return an error when a bogon is found.
|
||||
var ErrDNSBogon = errors.New("dns: detected bogon address")
|
||||
|
||||
// ErrWrapper is our error wrapper for Go errors. The key objective of
|
||||
// this structure is to properly set Failure, which is also returned by
|
||||
// the Error() method, so be one of the OONI defined strings.
|
||||
type ErrWrapper struct {
|
||||
// Failure is the OONI failure string. The failure strings are
|
||||
// loosely backward compatible with Measurement Kit.
|
||||
//
|
||||
// This is either one of the FailureXXX strings or any other
|
||||
// string like `unknown_failure ...`. The latter represents an
|
||||
// error that we have not yet mapped to a failure.
|
||||
Failure string
|
||||
|
||||
// Operation is the operation that failed. If possible, it
|
||||
// SHOULD be a _major_ operation. Major operations are:
|
||||
//
|
||||
// - ResolveOperation: resolving a domain name failed
|
||||
// - ConnectOperation: connecting to an IP failed
|
||||
// - TLSHandshakeOperation: TLS handshaking failed
|
||||
// - HTTPRoundTripOperation: other errors during round trip
|
||||
//
|
||||
// Because a network connection doesn't necessarily know
|
||||
// what is the current major operation we also have the
|
||||
// following _minor_ operations:
|
||||
//
|
||||
// - CloseOperation: CLOSE failed
|
||||
// - ReadOperation: READ failed
|
||||
// - WriteOperation: WRITE failed
|
||||
//
|
||||
// If an ErrWrapper referring to a major operation is wrapping
|
||||
// another ErrWrapper and such ErrWrapper already refers to
|
||||
// a major operation, then the new ErrWrapper should use the
|
||||
// child ErrWrapper major operation. Otherwise, it should use
|
||||
// its own major operation. This way, the topmost wrapper is
|
||||
// supposed to refer to the major operation that failed.
|
||||
Operation string
|
||||
|
||||
// WrappedErr is the error that we're wrapping.
|
||||
WrappedErr error
|
||||
}
|
||||
|
||||
// Error returns a description of the error that occurred.
|
||||
func (e *ErrWrapper) Error() string {
|
||||
return e.Failure
|
||||
}
|
||||
|
||||
// Unwrap allows to access the underlying error
|
||||
func (e *ErrWrapper) Unwrap() error {
|
||||
return e.WrappedErr
|
||||
}
|
||||
|
||||
// SafeErrWrapperBuilder contains a builder for ErrWrapper that
|
||||
// is safe, i.e., behaves correctly when the error is nil.
|
||||
type SafeErrWrapperBuilder struct {
|
||||
// Error is the error, if any
|
||||
Error error
|
||||
|
||||
// Classifier is the local error to string classifier. When there is no
|
||||
// configured classifier we will use the generic classifier.
|
||||
Classifier func(err error) string
|
||||
|
||||
// Operation is the operation that failed
|
||||
Operation string
|
||||
}
|
||||
|
||||
// MaybeBuild builds a new ErrWrapper, if b.Error is not nil, and returns
|
||||
// a nil error value, instead, if b.Error is nil.
|
||||
func (b SafeErrWrapperBuilder) MaybeBuild() (err error) {
|
||||
if b.Error != nil {
|
||||
classifier := b.Classifier
|
||||
if classifier == nil {
|
||||
classifier = toFailureString
|
||||
}
|
||||
err = &ErrWrapper{
|
||||
Failure: classifier(b.Error),
|
||||
Operation: toOperationString(b.Error, b.Operation),
|
||||
WrappedErr: b.Error,
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// TODO (kelmenhorst, bassosimone):
|
||||
// Use errors.Is / errors.As more often, when possible, in this classifier.
|
||||
// These methods are more robust to library changes than strings.
|
||||
// errors.Is / errors.As can only be used when the error is exported.
|
||||
func toFailureString(err error) string {
|
||||
// The list returned here matches the values used by MK unless
|
||||
// explicitly noted otherwise with a comment.
|
||||
|
||||
var errwrapper *ErrWrapper
|
||||
if errors.As(err, &errwrapper) {
|
||||
return errwrapper.Error() // we've already wrapped it
|
||||
}
|
||||
|
||||
// filter out system errors: necessary to detect all windows errors
|
||||
// https://github.com/ooni/probe/issues/1526 describes the problem of mapping localized windows errors
|
||||
var errno syscall.Errno
|
||||
if errors.As(err, &errno) {
|
||||
switch errno {
|
||||
case ECANCELED:
|
||||
return FailureInterrupted
|
||||
case ECONNRESET:
|
||||
return FailureConnectionReset
|
||||
case ECONNREFUSED:
|
||||
return FailureConnectionRefused
|
||||
case EHOSTUNREACH:
|
||||
return FailureHostUnreachable
|
||||
case ETIMEDOUT:
|
||||
return FailureGenericTimeoutError
|
||||
// TODO(kelmenhorst): find out if we need more system errors here
|
||||
}
|
||||
}
|
||||
if errors.Is(err, context.Canceled) {
|
||||
return FailureInterrupted
|
||||
}
|
||||
s := err.Error()
|
||||
if strings.HasSuffix(s, "operation was canceled") {
|
||||
return FailureInterrupted
|
||||
}
|
||||
if strings.HasSuffix(s, "EOF") {
|
||||
return FailureEOFError
|
||||
}
|
||||
if strings.HasSuffix(s, "context deadline exceeded") {
|
||||
return FailureGenericTimeoutError
|
||||
}
|
||||
if strings.HasSuffix(s, "transaction is timed out") {
|
||||
return FailureGenericTimeoutError
|
||||
}
|
||||
if strings.HasSuffix(s, "i/o timeout") {
|
||||
return FailureGenericTimeoutError
|
||||
}
|
||||
// TODO(kelmenhorst,bassosimone): this can probably be moved since it's TLS specific
|
||||
if strings.HasSuffix(s, "TLS handshake timeout") {
|
||||
return FailureGenericTimeoutError
|
||||
}
|
||||
if strings.HasSuffix(s, "no such host") {
|
||||
// This is dns_lookup_error in MK but such error is used as a
|
||||
// generic "hey, the lookup failed" error. Instead, this error
|
||||
// that we return here is significantly more specific.
|
||||
return FailureDNSNXDOMAINError
|
||||
}
|
||||
formatted := fmt.Sprintf("unknown_failure: %s", s)
|
||||
return scrubber.Scrub(formatted) // scrub IP addresses in the error
|
||||
}
|
||||
|
||||
// ClassifyQUICFailure is a classifier to translate QUIC errors to OONI error strings.
|
||||
// TODO(kelmenhorst,bassosimone): Consider moving this into quicdialer.
|
||||
func ClassifyQUICFailure(err error) string {
|
||||
var versionNegotiation *quic.VersionNegotiationError
|
||||
var statelessReset *quic.StatelessResetError
|
||||
var handshakeTimeout *quic.HandshakeTimeoutError
|
||||
var idleTimeout *quic.IdleTimeoutError
|
||||
var transportError *quic.TransportError
|
||||
|
||||
if errors.As(err, &versionNegotiation) {
|
||||
return FailureNoCompatibleQUICVersion
|
||||
}
|
||||
if errors.As(err, &statelessReset) {
|
||||
return FailureConnectionReset
|
||||
}
|
||||
if errors.As(err, &handshakeTimeout) {
|
||||
return FailureGenericTimeoutError
|
||||
}
|
||||
if errors.As(err, &idleTimeout) {
|
||||
return FailureGenericTimeoutError
|
||||
}
|
||||
if errors.As(err, &transportError) {
|
||||
if transportError.ErrorCode == quic.ConnectionRefused {
|
||||
return FailureConnectionRefused
|
||||
}
|
||||
// the TLS Alert constants are taken from RFC8446
|
||||
errCode := uint8(transportError.ErrorCode)
|
||||
if isCertificateError(errCode) {
|
||||
return FailureSSLInvalidCertificate
|
||||
}
|
||||
// TLSAlertDecryptError and TLSAlertHandshakeFailure are summarized to a FailureSSLHandshake error because both
|
||||
// alerts are caused by a failed or corrupted parameter negotiation during the TLS handshake.
|
||||
if errCode == TLSAlertDecryptError || errCode == TLSAlertHandshakeFailure {
|
||||
return FailureSSLHandshake
|
||||
}
|
||||
if errCode == TLSAlertUnknownCA {
|
||||
return FailureSSLUnknownAuthority
|
||||
}
|
||||
if errCode == TLSUnrecognizedName {
|
||||
return FailureSSLInvalidHostname
|
||||
}
|
||||
}
|
||||
return toFailureString(err)
|
||||
}
|
||||
|
||||
// ClassifyResolveFailure is a classifier to translate DNS resolving errors to OONI error strings.
|
||||
// TODO(kelmenhorst,bassosimone): Consider moving this into resolve.
|
||||
func ClassifyResolveFailure(err error) string {
|
||||
if errors.Is(err, ErrDNSBogon) {
|
||||
return FailureDNSBogonError // not in MK
|
||||
}
|
||||
return toFailureString(err)
|
||||
}
|
||||
|
||||
// ClassifyTLSFailure is a classifier to translate TLS errors to OONI error strings.
|
||||
// TODO(kelmenhorst,bassosimone): Consider moving this into tlsdialer.
|
||||
func ClassifyTLSFailure(err error) string {
|
||||
var x509HostnameError x509.HostnameError
|
||||
if errors.As(err, &x509HostnameError) {
|
||||
// Test case: https://wrong.host.badssl.com/
|
||||
return FailureSSLInvalidHostname
|
||||
}
|
||||
var x509UnknownAuthorityError x509.UnknownAuthorityError
|
||||
if errors.As(err, &x509UnknownAuthorityError) {
|
||||
// Test case: https://self-signed.badssl.com/. This error has
|
||||
// never been among the ones returned by MK.
|
||||
return FailureSSLUnknownAuthority
|
||||
}
|
||||
var x509CertificateInvalidError x509.CertificateInvalidError
|
||||
if errors.As(err, &x509CertificateInvalidError) {
|
||||
// Test case: https://expired.badssl.com/
|
||||
return FailureSSLInvalidCertificate
|
||||
}
|
||||
return toFailureString(err)
|
||||
}
|
||||
|
||||
func toOperationString(err error, operation string) string {
|
||||
var errwrapper *ErrWrapper
|
||||
if errors.As(err, &errwrapper) {
|
||||
// Basically, as explained in ErrWrapper docs, let's
|
||||
// keep the child major operation, if any.
|
||||
if errwrapper.Operation == ConnectOperation {
|
||||
return errwrapper.Operation
|
||||
}
|
||||
if errwrapper.Operation == HTTPRoundTripOperation {
|
||||
return errwrapper.Operation
|
||||
}
|
||||
if errwrapper.Operation == ResolveOperation {
|
||||
return errwrapper.Operation
|
||||
}
|
||||
if errwrapper.Operation == TLSHandshakeOperation {
|
||||
return errwrapper.Operation
|
||||
}
|
||||
if errwrapper.Operation == QUICHandshakeOperation {
|
||||
return errwrapper.Operation
|
||||
}
|
||||
if errwrapper.Operation == "quic_handshake_start" {
|
||||
return QUICHandshakeOperation
|
||||
}
|
||||
if errwrapper.Operation == "quic_handshake_done" {
|
||||
return QUICHandshakeOperation
|
||||
}
|
||||
// FALLTHROUGH
|
||||
}
|
||||
return operation
|
||||
}
|
||||
|
||||
func isCertificateError(alert uint8) bool {
|
||||
return (alert == TLSAlertBadCertificate ||
|
||||
alert == TLSAlertUnsupportedCertificate ||
|
||||
alert == TLSAlertCertificateExpired ||
|
||||
alert == TLSAlertCertificateRevoked ||
|
||||
alert == TLSAlertCertificateUnknown)
|
||||
}
|
||||
@@ -1,290 +0,0 @@
|
||||
package errorx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"syscall"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
"github.com/pion/stun"
|
||||
)
|
||||
|
||||
func TestMaybeBuildFactory(t *testing.T) {
|
||||
err := SafeErrWrapperBuilder{
|
||||
Error: errors.New("mocked error"),
|
||||
}.MaybeBuild()
|
||||
var target *ErrWrapper
|
||||
if errors.As(err, &target) == false {
|
||||
t.Fatal("not the expected error type")
|
||||
}
|
||||
if target.Failure != "unknown_failure: mocked error" {
|
||||
t.Fatal("the failure string is wrong")
|
||||
}
|
||||
if target.WrappedErr.Error() != "mocked error" {
|
||||
t.Fatal("the wrapped error is wrong")
|
||||
}
|
||||
}
|
||||
|
||||
func TestToFailureString(t *testing.T) {
|
||||
t.Run("for already wrapped error", func(t *testing.T) {
|
||||
err := SafeErrWrapperBuilder{Error: io.EOF}.MaybeBuild()
|
||||
if toFailureString(err) != FailureEOFError {
|
||||
t.Fatal("unexpected result")
|
||||
}
|
||||
})
|
||||
t.Run("for context.Canceled", func(t *testing.T) {
|
||||
if toFailureString(context.Canceled) != FailureInterrupted {
|
||||
t.Fatal("unexpected result")
|
||||
}
|
||||
})
|
||||
t.Run("for operation was canceled error", func(t *testing.T) {
|
||||
if toFailureString(errors.New("operation was canceled")) != FailureInterrupted {
|
||||
t.Fatal("unexpected result")
|
||||
}
|
||||
})
|
||||
t.Run("for EOF", func(t *testing.T) {
|
||||
if toFailureString(io.EOF) != FailureEOFError {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
})
|
||||
t.Run("for canceled", func(t *testing.T) {
|
||||
if toFailureString(syscall.ECANCELED) != FailureInterrupted {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
})
|
||||
t.Run("for connection_refused", func(t *testing.T) {
|
||||
if toFailureString(syscall.ECONNREFUSED) != FailureConnectionRefused {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
})
|
||||
t.Run("for connection_reset", func(t *testing.T) {
|
||||
if toFailureString(syscall.ECONNRESET) != FailureConnectionReset {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
})
|
||||
t.Run("for host_unreachable", func(t *testing.T) {
|
||||
if toFailureString(syscall.EHOSTUNREACH) != FailureHostUnreachable {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
})
|
||||
t.Run("for system timeout", func(t *testing.T) {
|
||||
if toFailureString(syscall.ETIMEDOUT) != FailureGenericTimeoutError {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
})
|
||||
t.Run("for context deadline exceeded", func(t *testing.T) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 1)
|
||||
defer cancel()
|
||||
<-ctx.Done()
|
||||
if toFailureString(ctx.Err()) != FailureGenericTimeoutError {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
})
|
||||
t.Run("for stun's transaction is timed out", func(t *testing.T) {
|
||||
if toFailureString(stun.ErrTransactionTimeOut) != FailureGenericTimeoutError {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
})
|
||||
t.Run("for i/o error", func(t *testing.T) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 1)
|
||||
defer cancel() // fail immediately
|
||||
conn, err := (&net.Dialer{}).DialContext(ctx, "tcp", "www.google.com:80")
|
||||
if err == nil {
|
||||
t.Fatal("expected an error here")
|
||||
}
|
||||
if conn != nil {
|
||||
t.Fatal("expected nil connection here")
|
||||
}
|
||||
if toFailureString(err) != FailureGenericTimeoutError {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
})
|
||||
t.Run("for TLS handshake timeout error", func(t *testing.T) {
|
||||
err := errors.New("net/http: TLS handshake timeout")
|
||||
if toFailureString(err) != FailureGenericTimeoutError {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
})
|
||||
t.Run("for no such host", func(t *testing.T) {
|
||||
if toFailureString(&net.DNSError{
|
||||
Err: "no such host",
|
||||
}) != FailureDNSNXDOMAINError {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
})
|
||||
t.Run("for errors including IPv4 address", func(t *testing.T) {
|
||||
input := errors.New("read tcp 10.0.2.15:56948->93.184.216.34:443: use of closed network connection")
|
||||
expected := "unknown_failure: read tcp [scrubbed]->[scrubbed]: use of closed network connection"
|
||||
out := toFailureString(input)
|
||||
if out != expected {
|
||||
t.Fatal(cmp.Diff(expected, out))
|
||||
}
|
||||
})
|
||||
t.Run("for errors including IPv6 address", func(t *testing.T) {
|
||||
input := errors.New("read tcp [::1]:56948->[::1]:443: use of closed network connection")
|
||||
expected := "unknown_failure: read tcp [scrubbed]->[scrubbed]: use of closed network connection"
|
||||
out := toFailureString(input)
|
||||
if out != expected {
|
||||
t.Fatal(cmp.Diff(expected, out))
|
||||
}
|
||||
})
|
||||
t.Run("for i/o error", func(t *testing.T) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 1)
|
||||
defer cancel() // fail immediately
|
||||
udpAddr := &net.UDPAddr{IP: net.ParseIP("216.58.212.164"), Port: 80, Zone: ""}
|
||||
udpConn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4zero, Port: 0})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sess, err := quic.DialEarlyContext(ctx, udpConn, udpAddr, "google.com:80", &tls.Config{}, &quic.Config{})
|
||||
if err == nil {
|
||||
t.Fatal("expected an error here")
|
||||
}
|
||||
if sess != nil {
|
||||
t.Fatal("expected nil session here")
|
||||
}
|
||||
if toFailureString(err) != FailureGenericTimeoutError {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestClassifyQUICFailure(t *testing.T) {
|
||||
t.Run("for connection_reset", func(t *testing.T) {
|
||||
if ClassifyQUICFailure(&quic.StatelessResetError{}) != FailureConnectionReset {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
})
|
||||
t.Run("for incompatible quic version", func(t *testing.T) {
|
||||
if ClassifyQUICFailure(&quic.VersionNegotiationError{}) != FailureNoCompatibleQUICVersion {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
})
|
||||
t.Run("for quic connection refused", func(t *testing.T) {
|
||||
if ClassifyQUICFailure(&quic.TransportError{ErrorCode: quic.ConnectionRefused}) != FailureConnectionRefused {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
})
|
||||
t.Run("for quic handshake timeout", func(t *testing.T) {
|
||||
if ClassifyQUICFailure(&quic.HandshakeTimeoutError{}) != FailureGenericTimeoutError {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
})
|
||||
t.Run("for QUIC idle connection timeout", func(t *testing.T) {
|
||||
if ClassifyQUICFailure(&quic.IdleTimeoutError{}) != FailureGenericTimeoutError {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
})
|
||||
t.Run("for QUIC CRYPTO Handshake", func(t *testing.T) {
|
||||
var err quic.TransportErrorCode = TLSAlertHandshakeFailure
|
||||
if ClassifyQUICFailure(&quic.TransportError{ErrorCode: err}) != FailureSSLHandshake {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
})
|
||||
t.Run("for QUIC CRYPTO Invalid Certificate", func(t *testing.T) {
|
||||
var err quic.TransportErrorCode = TLSAlertBadCertificate
|
||||
if ClassifyQUICFailure(&quic.TransportError{ErrorCode: err}) != FailureSSLInvalidCertificate {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
})
|
||||
t.Run("for QUIC CRYPTO Unknown CA", func(t *testing.T) {
|
||||
var err quic.TransportErrorCode = TLSAlertUnknownCA
|
||||
if ClassifyQUICFailure(&quic.TransportError{ErrorCode: err}) != FailureSSLUnknownAuthority {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
})
|
||||
t.Run("for QUIC CRYPTO Bad Hostname", func(t *testing.T) {
|
||||
var err quic.TransportErrorCode = TLSUnrecognizedName
|
||||
if ClassifyQUICFailure(&quic.TransportError{ErrorCode: err}) != FailureSSLInvalidHostname {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestClassifyResolveFailure(t *testing.T) {
|
||||
t.Run("for ErrDNSBogon", func(t *testing.T) {
|
||||
if ClassifyResolveFailure(ErrDNSBogon) != FailureDNSBogonError {
|
||||
t.Fatal("unexpected result")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestClassifyTLSFailure(t *testing.T) {
|
||||
t.Run("for x509.HostnameError", func(t *testing.T) {
|
||||
var err x509.HostnameError
|
||||
if ClassifyTLSFailure(err) != FailureSSLInvalidHostname {
|
||||
t.Fatal("unexpected result")
|
||||
}
|
||||
})
|
||||
t.Run("for x509.UnknownAuthorityError", func(t *testing.T) {
|
||||
var err x509.UnknownAuthorityError
|
||||
if ClassifyTLSFailure(err) != FailureSSLUnknownAuthority {
|
||||
t.Fatal("unexpected result")
|
||||
}
|
||||
})
|
||||
t.Run("for x509.CertificateInvalidError", func(t *testing.T) {
|
||||
var err x509.CertificateInvalidError
|
||||
if ClassifyTLSFailure(err) != FailureSSLInvalidCertificate {
|
||||
t.Fatal("unexpected result")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestToOperationString(t *testing.T) {
|
||||
t.Run("for connect", func(t *testing.T) {
|
||||
// You're doing HTTP and connect fails. You want to know
|
||||
// that connect failed not that HTTP failed.
|
||||
err := &ErrWrapper{Operation: ConnectOperation}
|
||||
if toOperationString(err, HTTPRoundTripOperation) != ConnectOperation {
|
||||
t.Fatal("unexpected result")
|
||||
}
|
||||
})
|
||||
t.Run("for http_round_trip", func(t *testing.T) {
|
||||
// You're doing DoH and something fails inside HTTP. You want
|
||||
// to know about the internal HTTP error, not resolve.
|
||||
err := &ErrWrapper{Operation: HTTPRoundTripOperation}
|
||||
if toOperationString(err, ResolveOperation) != HTTPRoundTripOperation {
|
||||
t.Fatal("unexpected result")
|
||||
}
|
||||
})
|
||||
t.Run("for resolve", func(t *testing.T) {
|
||||
// You're doing HTTP and the DNS fails. You want to
|
||||
// know that resolve failed.
|
||||
err := &ErrWrapper{Operation: ResolveOperation}
|
||||
if toOperationString(err, HTTPRoundTripOperation) != ResolveOperation {
|
||||
t.Fatal("unexpected result")
|
||||
}
|
||||
})
|
||||
t.Run("for tls_handshake", func(t *testing.T) {
|
||||
// You're doing HTTP and the TLS handshake fails. You want
|
||||
// to know about a TLS handshake error.
|
||||
err := &ErrWrapper{Operation: TLSHandshakeOperation}
|
||||
if toOperationString(err, HTTPRoundTripOperation) != TLSHandshakeOperation {
|
||||
t.Fatal("unexpected result")
|
||||
}
|
||||
})
|
||||
t.Run("for minor operation", func(t *testing.T) {
|
||||
// You just noticed that TLS handshake failed and you
|
||||
// have a child error telling you that read failed. Here
|
||||
// you want to know about a TLS handshake error.
|
||||
err := &ErrWrapper{Operation: ReadOperation}
|
||||
if toOperationString(err, TLSHandshakeOperation) != TLSHandshakeOperation {
|
||||
t.Fatal("unexpected result")
|
||||
}
|
||||
})
|
||||
t.Run("for quic_handshake", func(t *testing.T) {
|
||||
// You're doing HTTP and the TLS handshake fails. You want
|
||||
// to know about a TLS handshake error.
|
||||
err := &ErrWrapper{Operation: QUICHandshakeOperation}
|
||||
if toOperationString(err, HTTPRoundTripOperation) != QUICHandshakeOperation {
|
||||
t.Fatal("unexpected result")
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -9,8 +9,8 @@ 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/errorx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/errorsx"
|
||||
"github.com/ooni/probe-cli/v3/internal/iox"
|
||||
)
|
||||
|
||||
@@ -78,10 +78,10 @@ func TestBogonResolutionNotBroken(t *testing.T) {
|
||||
Logger: log.Log,
|
||||
})
|
||||
addrs, err := r.LookupHost(context.Background(), "www.google.com")
|
||||
if !errors.Is(err, errorx.ErrDNSBogon) {
|
||||
if !errors.Is(err, errorsx.ErrDNSBogon) {
|
||||
t.Fatal("not the error we expected")
|
||||
}
|
||||
if err.Error() != errorx.FailureDNSBogonError {
|
||||
if err.Error() != errorsx.FailureDNSBogonError {
|
||||
t.Fatal("error not correctly wrapped")
|
||||
}
|
||||
if len(addrs) > 0 {
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"crypto/tls"
|
||||
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/errorx"
|
||||
"github.com/ooni/probe-cli/v3/internal/errorsx"
|
||||
)
|
||||
|
||||
// ErrorWrapperDialer is a dialer that performs quic err wrapping
|
||||
@@ -18,10 +18,10 @@ func (d ErrorWrapperDialer) DialContext(
|
||||
ctx context.Context, network string, host string,
|
||||
tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlySession, error) {
|
||||
sess, err := d.Dialer.DialContext(ctx, network, host, tlsCfg, cfg)
|
||||
err = errorx.SafeErrWrapperBuilder{
|
||||
Classifier: errorx.ClassifyQUICFailure,
|
||||
err = errorsx.SafeErrWrapperBuilder{
|
||||
Classifier: errorsx.ClassifyQUICFailure,
|
||||
Error: err,
|
||||
Operation: errorx.QUICHandshakeOperation,
|
||||
Operation: errorsx.QUICHandshakeOperation,
|
||||
}.MaybeBuild()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/errorx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/quicdialer"
|
||||
"github.com/ooni/probe-cli/v3/internal/errorsx"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
@@ -22,21 +22,21 @@ func TestErrorWrapperFailure(t *testing.T) {
|
||||
if sess != nil {
|
||||
t.Fatal("expected a nil sess here")
|
||||
}
|
||||
errorWrapperCheckErr(t, err, errorx.QUICHandshakeOperation)
|
||||
errorWrapperCheckErr(t, err, errorsx.QUICHandshakeOperation)
|
||||
}
|
||||
|
||||
func errorWrapperCheckErr(t *testing.T, err error, op string) {
|
||||
if !errors.Is(err, io.EOF) {
|
||||
t.Fatal("expected another error here")
|
||||
}
|
||||
var errWrapper *errorx.ErrWrapper
|
||||
var errWrapper *errorsx.ErrWrapper
|
||||
if !errors.As(err, &errWrapper) {
|
||||
t.Fatal("cannot cast to ErrWrapper")
|
||||
}
|
||||
if errWrapper.Operation != op {
|
||||
t.Fatal("unexpected Operation")
|
||||
}
|
||||
if errWrapper.Failure != errorx.FailureEOFError {
|
||||
if errWrapper.Failure != errorsx.FailureEOFError {
|
||||
t.Fatal("unexpected failure")
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,7 @@ func TestErrorWrapperInvalidCertificate(t *testing.T) {
|
||||
if sess != nil {
|
||||
t.Fatal("expected nil sess here")
|
||||
}
|
||||
if err.Error() != errorx.FailureSSLInvalidCertificate {
|
||||
if err.Error() != errorsx.FailureSSLInvalidCertificate {
|
||||
t.Fatal("unexpected failure")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/errorx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/errorsx"
|
||||
)
|
||||
|
||||
// QUICListener listens for QUIC connections.
|
||||
@@ -53,7 +53,7 @@ func (c saverUDPConn) WriteTo(p []byte, addr net.Addr) (int, error) {
|
||||
Duration: stop.Sub(start),
|
||||
Err: err,
|
||||
NumBytes: count,
|
||||
Name: errorx.WriteToOperation,
|
||||
Name: errorsx.WriteToOperation,
|
||||
Time: stop,
|
||||
})
|
||||
return count, err
|
||||
@@ -73,7 +73,7 @@ func (c saverUDPConn) ReadMsgUDP(b, oob []byte) (int, int, int, *net.UDPAddr, er
|
||||
Duration: stop.Sub(start),
|
||||
Err: err,
|
||||
NumBytes: n,
|
||||
Name: errorx.ReadFromOperation,
|
||||
Name: errorsx.ReadFromOperation,
|
||||
Time: stop,
|
||||
})
|
||||
return n, oobn, flags, addr, err
|
||||
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/errorx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/quicdialer"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/errorsx"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
@@ -49,7 +49,7 @@ func TestSystemDialerSuccessWithReadWrite(t *testing.T) {
|
||||
t.Fatal("unexpected NumBytes")
|
||||
}
|
||||
switch ev[idx].Name {
|
||||
case errorx.ReadFromOperation, errorx.WriteToOperation:
|
||||
case errorsx.ReadFromOperation, errorsx.WriteToOperation:
|
||||
default:
|
||||
t.Fatal("unexpected Name")
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/errorx"
|
||||
"github.com/ooni/probe-cli/v3/internal/errorsx"
|
||||
"github.com/ooni/probe-cli/v3/internal/runtimex"
|
||||
)
|
||||
|
||||
@@ -65,7 +65,7 @@ func (r BogonResolver) LookupHost(ctx context.Context, hostname string) ([]strin
|
||||
addrs, err := r.Resolver.LookupHost(ctx, hostname)
|
||||
for _, addr := range addrs {
|
||||
if IsBogon(addr) {
|
||||
return nil, errorx.ErrDNSBogon
|
||||
return nil, errorsx.ErrDNSBogon
|
||||
}
|
||||
}
|
||||
return addrs, err
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/errorx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/resolver"
|
||||
"github.com/ooni/probe-cli/v3/internal/errorsx"
|
||||
)
|
||||
|
||||
func TestResolverIsBogon(t *testing.T) {
|
||||
@@ -29,7 +29,7 @@ func TestBogonAwareResolverWithBogon(t *testing.T) {
|
||||
Resolver: resolver.NewFakeResolverWithResult([]string{"127.0.0.1"}),
|
||||
}
|
||||
addrs, err := r.LookupHost(context.Background(), "dns.google.com")
|
||||
if !errors.Is(err, errorx.ErrDNSBogon) {
|
||||
if !errors.Is(err, errorsx.ErrDNSBogon) {
|
||||
t.Fatal("not the error we expected")
|
||||
}
|
||||
if len(addrs) > 0 {
|
||||
|
||||
@@ -3,7 +3,7 @@ package resolver
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/errorx"
|
||||
"github.com/ooni/probe-cli/v3/internal/errorsx"
|
||||
)
|
||||
|
||||
// ErrorWrapperResolver is a Resolver that knows about wrapping errors.
|
||||
@@ -14,10 +14,10 @@ type ErrorWrapperResolver struct {
|
||||
// LookupHost implements Resolver.LookupHost
|
||||
func (r ErrorWrapperResolver) LookupHost(ctx context.Context, hostname string) ([]string, error) {
|
||||
addrs, err := r.Resolver.LookupHost(ctx, hostname)
|
||||
err = errorx.SafeErrWrapperBuilder{
|
||||
Classifier: errorx.ClassifyResolveFailure,
|
||||
err = errorsx.SafeErrWrapperBuilder{
|
||||
Classifier: errorsx.ClassifyResolveFailure,
|
||||
Error: err,
|
||||
Operation: errorx.ResolveOperation,
|
||||
Operation: errorsx.ResolveOperation,
|
||||
}.MaybeBuild()
|
||||
return addrs, err
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/errorx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/resolver"
|
||||
"github.com/ooni/probe-cli/v3/internal/errorsx"
|
||||
)
|
||||
|
||||
func TestErrorWrapperSuccess(t *testing.T) {
|
||||
@@ -32,14 +32,14 @@ func TestErrorWrapperFailure(t *testing.T) {
|
||||
if addrs != nil {
|
||||
t.Fatal("expected nil addr here")
|
||||
}
|
||||
var errWrapper *errorx.ErrWrapper
|
||||
var errWrapper *errorsx.ErrWrapper
|
||||
if !errors.As(err, &errWrapper) {
|
||||
t.Fatal("cannot properly cast the returned error")
|
||||
}
|
||||
if errWrapper.Failure != errorx.FailureDNSNXDOMAINError {
|
||||
if errWrapper.Failure != errorsx.FailureDNSNXDOMAINError {
|
||||
t.Fatal("unexpected failure")
|
||||
}
|
||||
if errWrapper.Operation != errorx.ResolveOperation {
|
||||
if errWrapper.Operation != errorsx.ResolveOperation {
|
||||
t.Fatal("unexpected Operation")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/dialer"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/errorx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/tlsdialer"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/errorsx"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
@@ -69,7 +69,7 @@ func TestSaverTLSHandshakerSuccessWithReadWrite(t *testing.T) {
|
||||
t.Fatal("unexpected NumBytes")
|
||||
}
|
||||
switch ev[idx].Name {
|
||||
case errorx.ReadOperation, errorx.WriteOperation:
|
||||
case errorsx.ReadOperation, errorsx.WriteOperation:
|
||||
default:
|
||||
t.Fatal("unexpected Name")
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/legacy/netx/modelx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/errorx"
|
||||
"github.com/ooni/probe-cli/v3/internal/errorsx"
|
||||
)
|
||||
|
||||
// UnderlyingDialer is the underlying dialer type.
|
||||
@@ -32,10 +32,10 @@ func (h ErrorWrapperTLSHandshaker) Handshake(
|
||||
ctx context.Context, conn net.Conn, config *tls.Config,
|
||||
) (net.Conn, tls.ConnectionState, error) {
|
||||
tlsconn, state, err := h.TLSHandshaker.Handshake(ctx, conn, config)
|
||||
err = errorx.SafeErrWrapperBuilder{
|
||||
Classifier: errorx.ClassifyTLSFailure,
|
||||
err = errorsx.SafeErrWrapperBuilder{
|
||||
Classifier: errorsx.ClassifyTLSFailure,
|
||||
Error: err,
|
||||
Operation: errorx.TLSHandshakeOperation,
|
||||
Operation: errorsx.TLSHandshakeOperation,
|
||||
}.MaybeBuild()
|
||||
return tlsconn, state, err
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/legacy/netx/handlers"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/legacy/netx/modelx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/errorx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/tlsdialer"
|
||||
"github.com/ooni/probe-cli/v3/internal/errorsx"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
@@ -48,14 +48,14 @@ func TestErrorWrapperTLSHandshakerFailure(t *testing.T) {
|
||||
if conn != nil {
|
||||
t.Fatal("expected nil con here")
|
||||
}
|
||||
var errWrapper *errorx.ErrWrapper
|
||||
var errWrapper *errorsx.ErrWrapper
|
||||
if !errors.As(err, &errWrapper) {
|
||||
t.Fatal("cannot cast to ErrWrapper")
|
||||
}
|
||||
if errWrapper.Failure != errorx.FailureEOFError {
|
||||
if errWrapper.Failure != errorsx.FailureEOFError {
|
||||
t.Fatal("unexpected Failure")
|
||||
}
|
||||
if errWrapper.Operation != errorx.TLSHandshakeOperation {
|
||||
if errWrapper.Operation != errorsx.TLSHandshakeOperation {
|
||||
t.Fatal("unexpected Operation")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user