cleanup: merge legacy errorsx in netxlite and hide classifiers (#655)
This diff implements the first two cleanups defined at https://github.com/ooni/probe/issues/1956: > - [ ] observe that `netxlite` and `netx` differ in error wrapping only in the way in which we set `ErrWrapper.Operation`. Observe that the code using `netxlite` does not care about such a field. Therefore, we can modify `netxlite` to set such a field using the code of `netx` and we can remove `netx` specific code for errors (which currently lives inside of the `./internal/engine/legacy/errorsx` package > > - [ ] after we've done the previous cleanup, we can make all the classifiers code private, since there's no code outside `netxlite` that needs them A subsequent diff will address the remaining cleanup. While there, notice that there are failing, unrelated obfs4 tests, so disable them in short mode. (I am confident these tests are unrelated because they fail for me when running test locally from the `master` branch.)
This commit is contained in:
@@ -16,7 +16,6 @@ import (
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/experiment/urlgetter"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/httpheader"
|
||||
errorsxlegacy "github.com/ooni/probe-cli/v3/internal/engine/legacy/errorsx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/archival"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/dialer"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
@@ -180,8 +179,9 @@ func Transact(txp Transport, req *http.Request,
|
||||
callbacks model.ExperimentCallbacks) (*http.Response, []byte, error) {
|
||||
// make sure that we return a wrapped error here
|
||||
resp, data, err := transact(txp, req, callbacks)
|
||||
err = errorsxlegacy.SafeErrWrapperBuilder{
|
||||
Error: err, Operation: netxlite.TopLevelOperation}.MaybeBuild()
|
||||
if err != nil {
|
||||
err = netxlite.NewTopLevelGenericErrWrapper(err)
|
||||
}
|
||||
return resp, data, err
|
||||
}
|
||||
|
||||
|
||||
@@ -11,12 +11,12 @@ import (
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/legacy/errorsx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/archival"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/dialer"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
"github.com/pion/stun"
|
||||
)
|
||||
|
||||
@@ -60,10 +60,10 @@ func (m *Measurer) ExperimentVersion() string {
|
||||
}
|
||||
|
||||
func wrap(err error) error {
|
||||
return errorsx.SafeErrWrapperBuilder{
|
||||
Error: err,
|
||||
Operation: "stun",
|
||||
}.MaybeBuild()
|
||||
if err != nil {
|
||||
return netxlite.NewTopLevelGenericErrWrapper(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// errStunMissingInput means that the user did not provide any input
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
legacyerrorsx "github.com/ooni/probe-cli/v3/internal/engine/legacy/errorsx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/archival"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
@@ -55,10 +54,9 @@ func (g Getter) Get(ctx context.Context) (TestKeys, error) {
|
||||
tk, err := g.get(ctx, saver)
|
||||
// Make sure we have an operation in cases where we fail before
|
||||
// hitting our httptransport that does error wrapping.
|
||||
err = legacyerrorsx.SafeErrWrapperBuilder{
|
||||
Error: err,
|
||||
Operation: netxlite.TopLevelOperation,
|
||||
}.MaybeBuild()
|
||||
if err != nil {
|
||||
err = netxlite.NewTopLevelGenericErrWrapper(err)
|
||||
}
|
||||
tk.FailedOperation = archival.NewFailedOperation(err)
|
||||
tk.Failure = archival.NewFailure(err)
|
||||
events := saver.Read()
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/geolocate"
|
||||
legacyerrorsx "github.com/ooni/probe-cli/v3/internal/engine/legacy/errorsx"
|
||||
"github.com/ooni/probe-cli/v3/internal/httpx"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
@@ -61,10 +60,10 @@ func Control(
|
||||
}
|
||||
sess.Logger().Infof("control for %s...", creq.HTTPRequest)
|
||||
// make sure error is wrapped
|
||||
err = legacyerrorsx.SafeErrWrapperBuilder{
|
||||
Error: clnt.WithBodyLogging().Build().PostJSON(ctx, "/", creq, &out),
|
||||
Operation: netxlite.TopLevelOperation,
|
||||
}.MaybeBuild()
|
||||
err = clnt.WithBodyLogging().Build().PostJSON(ctx, "/", creq, &out)
|
||||
if err != nil {
|
||||
err = netxlite.NewTopLevelGenericErrWrapper(err)
|
||||
}
|
||||
sess.Logger().Infof("control for %s... %+v", creq.HTTPRequest, err)
|
||||
(&out.DNS).FillASNs(sess)
|
||||
return
|
||||
|
||||
@@ -3,7 +3,6 @@ package websteps
|
||||
import (
|
||||
"context"
|
||||
|
||||
errorsxlegacy "github.com/ooni/probe-cli/v3/internal/engine/legacy/errorsx"
|
||||
"github.com/ooni/probe-cli/v3/internal/httpx"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
@@ -19,9 +18,9 @@ func Control(
|
||||
Logger: sess.Logger(),
|
||||
}
|
||||
// make sure error is wrapped
|
||||
err = errorsxlegacy.SafeErrWrapperBuilder{
|
||||
Error: clnt.WithBodyLogging().Build().PostJSON(ctx, resourcePath, creq, &out),
|
||||
Operation: netxlite.TopLevelOperation,
|
||||
}.MaybeBuild()
|
||||
err = clnt.WithBodyLogging().Build().PostJSON(ctx, resourcePath, creq, &out)
|
||||
if err != nil {
|
||||
err = netxlite.NewTopLevelGenericErrWrapper(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -12,8 +12,6 @@ import (
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
"github.com/lucas-clemente/quic-go/http3"
|
||||
oohttp "github.com/ooni/oohttp"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/legacy/errorsx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/quicdialer"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
"github.com/ooni/probe-cli/v3/internal/runtimex"
|
||||
@@ -34,28 +32,28 @@ func NewRequest(ctx context.Context, URL *url.URL, headers http.Header) *http.Re
|
||||
|
||||
// NewDialerResolver contructs a new dialer for TCP connections,
|
||||
// with default, errorwrapping and resolve functionalities
|
||||
func NewDialerResolver(resolver netxlite.ResolverLegacy) netxlite.DialerLegacy {
|
||||
var d netxlite.DialerLegacy = netxlite.DefaultDialer
|
||||
d = &errorsx.ErrorWrapperDialer{Dialer: d}
|
||||
func NewDialerResolver(resolver netxlite.ResolverLegacy) model.Dialer {
|
||||
var d model.Dialer = netxlite.DefaultDialer
|
||||
d = &netxlite.ErrorWrapperDialer{Dialer: d}
|
||||
d = &netxlite.DialerResolver{
|
||||
Resolver: netxlite.NewResolverLegacyAdapter(resolver),
|
||||
Dialer: netxlite.NewDialerLegacyAdapter(d),
|
||||
Dialer: d,
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// NewQUICDialerResolver creates a new QUICDialerResolver
|
||||
// with default, errorwrapping and resolve functionalities
|
||||
func NewQUICDialerResolver(resolver netxlite.ResolverLegacy) netxlite.QUICContextDialer {
|
||||
var ql quicdialer.QUICListener = &netxlite.QUICListenerStdlib{}
|
||||
ql = &errorsx.ErrorWrapperQUICListener{QUICListener: ql}
|
||||
var dialer netxlite.QUICContextDialer = &netxlite.QUICDialerQUICGo{
|
||||
func NewQUICDialerResolver(resolver netxlite.ResolverLegacy) model.QUICDialer {
|
||||
var ql model.QUICListener = &netxlite.QUICListenerStdlib{}
|
||||
ql = &netxlite.ErrorWrapperQUICListener{QUICListener: ql}
|
||||
var dialer model.QUICDialer = &netxlite.QUICDialerQUICGo{
|
||||
QUICListener: ql,
|
||||
}
|
||||
dialer = &errorsx.ErrorWrapperQUICDialer{Dialer: dialer}
|
||||
dialer = &netxlite.ErrorWrapperQUICDialer{QUICDialer: dialer}
|
||||
dialer = &netxlite.QUICDialerResolver{
|
||||
Resolver: netxlite.NewResolverLegacyAdapter(resolver),
|
||||
Dialer: netxlite.NewQUICDialerFromContextDialerAdapter(dialer),
|
||||
Dialer: dialer,
|
||||
}
|
||||
return dialer
|
||||
}
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
package errorsx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
// Dialer establishes network connections.
|
||||
type Dialer interface {
|
||||
// DialContext behaves like net.Dialer.DialContext.
|
||||
DialContext(ctx context.Context, network, address string) (net.Conn, error)
|
||||
}
|
||||
|
||||
// ErrorWrapperDialer is a dialer that performs error wrapping. The connection
|
||||
// returned by the DialContext function will also perform error wrapping.
|
||||
type ErrorWrapperDialer struct {
|
||||
// Dialer is the underlying dialer.
|
||||
Dialer
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
return nil, SafeErrWrapperBuilder{
|
||||
Classifier: netxlite.ClassifyGenericError,
|
||||
Operation: netxlite.ConnectOperation,
|
||||
Error: err,
|
||||
}.MaybeBuild()
|
||||
}
|
||||
return &errorWrapperConn{Conn: conn}, nil
|
||||
}
|
||||
|
||||
// errorWrapperConn is a net.Conn that performs error wrapping.
|
||||
type errorWrapperConn struct {
|
||||
// Conn is the underlying connection.
|
||||
net.Conn
|
||||
}
|
||||
|
||||
// Read implements net.Conn.Read.
|
||||
func (c *errorWrapperConn) Read(b []byte) (int, error) {
|
||||
count, err := c.Conn.Read(b)
|
||||
if err != nil {
|
||||
return 0, SafeErrWrapperBuilder{
|
||||
Classifier: netxlite.ClassifyGenericError,
|
||||
Operation: netxlite.ReadOperation,
|
||||
Error: err,
|
||||
}.MaybeBuild()
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// Write implements net.Conn.Write.
|
||||
func (c *errorWrapperConn) Write(b []byte) (int, error) {
|
||||
count, err := c.Conn.Write(b)
|
||||
if err != nil {
|
||||
return 0, SafeErrWrapperBuilder{
|
||||
Classifier: netxlite.ClassifyGenericError,
|
||||
Operation: netxlite.WriteOperation,
|
||||
Error: err,
|
||||
}.MaybeBuild()
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// Close implements net.Conn.Close.
|
||||
func (c *errorWrapperConn) Close() error {
|
||||
err := c.Conn.Close()
|
||||
if err != nil {
|
||||
return SafeErrWrapperBuilder{
|
||||
Classifier: netxlite.ClassifyGenericError,
|
||||
Operation: netxlite.CloseOperation,
|
||||
Error: err,
|
||||
}.MaybeBuild()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,189 +0,0 @@
|
||||
package errorsx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/model/mocks"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
func TestErrorWrapperDialerFailure(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
d := &ErrorWrapperDialer{Dialer: &mocks.Dialer{
|
||||
MockDialContext: func(ctx context.Context, network string, address string) (net.Conn, error) {
|
||||
return nil, io.EOF
|
||||
},
|
||||
}}
|
||||
conn, err := d.DialContext(ctx, "tcp", "www.google.com:443")
|
||||
var ew *netxlite.ErrWrapper
|
||||
if !errors.As(err, &ew) {
|
||||
t.Fatal("cannot convert to ErrWrapper")
|
||||
}
|
||||
if ew.Operation != netxlite.ConnectOperation {
|
||||
t.Fatal("unexpected operation", ew.Operation)
|
||||
}
|
||||
if ew.Failure != netxlite.FailureEOFError {
|
||||
t.Fatal("unexpected failure", ew.Failure)
|
||||
}
|
||||
if !errors.Is(ew.WrappedErr, io.EOF) {
|
||||
t.Fatal("unexpected underlying error", ew.WrappedErr)
|
||||
}
|
||||
if conn != nil {
|
||||
t.Fatal("expected a nil conn here")
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorWrapperDialerSuccess(t *testing.T) {
|
||||
origConn := &net.TCPConn{}
|
||||
ctx := context.Background()
|
||||
d := &ErrorWrapperDialer{Dialer: &mocks.Dialer{
|
||||
MockDialContext: func(ctx context.Context, network string, address string) (net.Conn, error) {
|
||||
return origConn, nil
|
||||
},
|
||||
}}
|
||||
conn, err := d.DialContext(ctx, "tcp", "www.google.com:443")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ewConn, ok := conn.(*errorWrapperConn)
|
||||
if !ok {
|
||||
t.Fatal("cannot cast to errorWrapperConn")
|
||||
}
|
||||
if ewConn.Conn != origConn {
|
||||
t.Fatal("not the connection we expected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorWrapperConnReadFailure(t *testing.T) {
|
||||
c := &errorWrapperConn{
|
||||
Conn: &mocks.Conn{
|
||||
MockRead: func(b []byte) (int, error) {
|
||||
return 0, io.EOF
|
||||
},
|
||||
},
|
||||
}
|
||||
buf := make([]byte, 1024)
|
||||
cnt, err := c.Read(buf)
|
||||
var ew *netxlite.ErrWrapper
|
||||
if !errors.As(err, &ew) {
|
||||
t.Fatal("cannot cast error to ErrWrapper")
|
||||
}
|
||||
if ew.Operation != netxlite.ReadOperation {
|
||||
t.Fatal("invalid operation", ew.Operation)
|
||||
}
|
||||
if ew.Failure != netxlite.FailureEOFError {
|
||||
t.Fatal("invalid failure", ew.Failure)
|
||||
}
|
||||
if !errors.Is(ew.WrappedErr, io.EOF) {
|
||||
t.Fatal("invalid wrapped error", ew.WrappedErr)
|
||||
}
|
||||
if cnt != 0 {
|
||||
t.Fatal("expected zero here", cnt)
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorWrapperConnReadSuccess(t *testing.T) {
|
||||
c := &errorWrapperConn{
|
||||
Conn: &mocks.Conn{
|
||||
MockRead: func(b []byte) (int, error) {
|
||||
return len(b), nil
|
||||
},
|
||||
},
|
||||
}
|
||||
buf := make([]byte, 1024)
|
||||
cnt, err := c.Read(buf)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if cnt != len(buf) {
|
||||
t.Fatal("expected len(buf) here", cnt)
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorWrapperConnWriteFailure(t *testing.T) {
|
||||
c := &errorWrapperConn{
|
||||
Conn: &mocks.Conn{
|
||||
MockWrite: func(b []byte) (int, error) {
|
||||
return 0, io.EOF
|
||||
},
|
||||
},
|
||||
}
|
||||
buf := make([]byte, 1024)
|
||||
cnt, err := c.Write(buf)
|
||||
var ew *netxlite.ErrWrapper
|
||||
if !errors.As(err, &ew) {
|
||||
t.Fatal("cannot cast error to ErrWrapper")
|
||||
}
|
||||
if ew.Operation != netxlite.WriteOperation {
|
||||
t.Fatal("invalid operation", ew.Operation)
|
||||
}
|
||||
if ew.Failure != netxlite.FailureEOFError {
|
||||
t.Fatal("invalid failure", ew.Failure)
|
||||
}
|
||||
if !errors.Is(ew.WrappedErr, io.EOF) {
|
||||
t.Fatal("invalid wrapped error", ew.WrappedErr)
|
||||
}
|
||||
if cnt != 0 {
|
||||
t.Fatal("expected zero here", cnt)
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorWrapperConnWriteSuccess(t *testing.T) {
|
||||
c := &errorWrapperConn{
|
||||
Conn: &mocks.Conn{
|
||||
MockWrite: func(b []byte) (int, error) {
|
||||
return len(b), nil
|
||||
},
|
||||
},
|
||||
}
|
||||
buf := make([]byte, 1024)
|
||||
cnt, err := c.Write(buf)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if cnt != len(buf) {
|
||||
t.Fatal("expected len(buf) here", cnt)
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorWrapperConnCloseFailure(t *testing.T) {
|
||||
c := &errorWrapperConn{
|
||||
Conn: &mocks.Conn{
|
||||
MockClose: func() error {
|
||||
return io.EOF
|
||||
},
|
||||
},
|
||||
}
|
||||
err := c.Close()
|
||||
var ew *netxlite.ErrWrapper
|
||||
if !errors.As(err, &ew) {
|
||||
t.Fatal("cannot cast error to ErrWrapper")
|
||||
}
|
||||
if ew.Operation != netxlite.CloseOperation {
|
||||
t.Fatal("invalid operation", ew.Operation)
|
||||
}
|
||||
if ew.Failure != netxlite.FailureEOFError {
|
||||
t.Fatal("invalid failure", ew.Failure)
|
||||
}
|
||||
if !errors.Is(ew.WrappedErr, io.EOF) {
|
||||
t.Fatal("invalid wrapped error", ew.WrappedErr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorWrapperConnCloseSuccess(t *testing.T) {
|
||||
c := &errorWrapperConn{
|
||||
Conn: &mocks.Conn{
|
||||
MockClose: func() error {
|
||||
return nil
|
||||
},
|
||||
},
|
||||
}
|
||||
err := c.Close()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
// Package errorsx contains error extensions.
|
||||
package errorsx
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
// 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 = netxlite.ClassifyGenericError
|
||||
}
|
||||
err = &netxlite.ErrWrapper{
|
||||
Failure: classifier(b.Error),
|
||||
Operation: toOperationString(b.Error, b.Operation),
|
||||
WrappedErr: b.Error,
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func toOperationString(err error, operation string) string {
|
||||
var errwrapper *netxlite.ErrWrapper
|
||||
if errors.As(err, &errwrapper) {
|
||||
// Basically, as explained in ErrWrapper docs, let's
|
||||
// keep the child major operation, if any.
|
||||
if errwrapper.Operation == netxlite.ConnectOperation {
|
||||
return errwrapper.Operation
|
||||
}
|
||||
if errwrapper.Operation == netxlite.HTTPRoundTripOperation {
|
||||
return errwrapper.Operation
|
||||
}
|
||||
if errwrapper.Operation == netxlite.ResolveOperation {
|
||||
return errwrapper.Operation
|
||||
}
|
||||
if errwrapper.Operation == netxlite.TLSHandshakeOperation {
|
||||
return errwrapper.Operation
|
||||
}
|
||||
if errwrapper.Operation == netxlite.QUICHandshakeOperation {
|
||||
return errwrapper.Operation
|
||||
}
|
||||
if errwrapper.Operation == "quic_handshake_start" {
|
||||
return netxlite.QUICHandshakeOperation
|
||||
}
|
||||
if errwrapper.Operation == "quic_handshake_done" {
|
||||
return netxlite.QUICHandshakeOperation
|
||||
}
|
||||
// FALLTHROUGH
|
||||
}
|
||||
return operation
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
package errorsx
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
func TestMaybeBuildFactory(t *testing.T) {
|
||||
err := SafeErrWrapperBuilder{
|
||||
Error: errors.New("mocked error"),
|
||||
}.MaybeBuild()
|
||||
var target *netxlite.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 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 := &netxlite.ErrWrapper{Operation: netxlite.ConnectOperation}
|
||||
if toOperationString(err, netxlite.HTTPRoundTripOperation) != netxlite.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 := &netxlite.ErrWrapper{Operation: netxlite.HTTPRoundTripOperation}
|
||||
if toOperationString(err, netxlite.ResolveOperation) != netxlite.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 := &netxlite.ErrWrapper{Operation: netxlite.ResolveOperation}
|
||||
if toOperationString(err, netxlite.HTTPRoundTripOperation) != netxlite.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 := &netxlite.ErrWrapper{Operation: netxlite.TLSHandshakeOperation}
|
||||
if toOperationString(err, netxlite.HTTPRoundTripOperation) != netxlite.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 := &netxlite.ErrWrapper{Operation: netxlite.ReadOperation}
|
||||
if toOperationString(err, netxlite.TLSHandshakeOperation) != netxlite.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 := &netxlite.ErrWrapper{Operation: netxlite.QUICHandshakeOperation}
|
||||
if toOperationString(err, netxlite.HTTPRoundTripOperation) != netxlite.QUICHandshakeOperation {
|
||||
t.Fatal("unexpected result")
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
package errorsx_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"testing"
|
||||
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
errorsxlegacy "github.com/ooni/probe-cli/v3/internal/engine/legacy/errorsx"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite/quictesting"
|
||||
)
|
||||
|
||||
func TestErrorWrapperQUICDialerFailure(t *testing.T) {
|
||||
nextprotos := []string{"h3"}
|
||||
servername := "example.com"
|
||||
tlsConf := &tls.Config{
|
||||
NextProtos: nextprotos,
|
||||
ServerName: servername,
|
||||
}
|
||||
|
||||
dlr := &errorsxlegacy.ErrorWrapperQUICDialer{Dialer: &netxlite.QUICDialerQUICGo{
|
||||
QUICListener: &netxlite.QUICListenerStdlib{},
|
||||
}}
|
||||
sess, err := dlr.DialContext(context.Background(), "udp",
|
||||
quictesting.Endpoint("443"), tlsConf, &quic.Config{})
|
||||
if err == nil {
|
||||
t.Fatal("expected an error here")
|
||||
}
|
||||
if sess != nil {
|
||||
t.Fatal("expected nil sess here")
|
||||
}
|
||||
if err.Error() != netxlite.FailureSSLFailedHandshake {
|
||||
t.Fatal("unexpected failure", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorWrapperQUICDialerSuccess(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
tlsConf := &tls.Config{
|
||||
NextProtos: []string{"h3"},
|
||||
ServerName: quictesting.Domain,
|
||||
}
|
||||
d := &errorsxlegacy.ErrorWrapperQUICDialer{Dialer: &netxlite.QUICDialerQUICGo{
|
||||
QUICListener: &netxlite.QUICListenerStdlib{},
|
||||
}}
|
||||
sess, err := d.DialContext(ctx, "udp", quictesting.Endpoint("443"), tlsConf, &quic.Config{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if sess == nil {
|
||||
t.Fatal("expected non-nil sess here")
|
||||
}
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
package errorsx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net"
|
||||
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
// QUICContextDialer is a dialer for QUIC using Context.
|
||||
type QUICContextDialer interface {
|
||||
// DialContext establishes a new QUIC session using the given
|
||||
// network and address. The tlsConfig and the quicConfig arguments
|
||||
// MUST NOT be nil. Returns either the session or an error.
|
||||
DialContext(ctx context.Context, network, address string,
|
||||
tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlySession, error)
|
||||
}
|
||||
|
||||
// QUICListener listens for QUIC connections.
|
||||
type QUICListener interface {
|
||||
// Listen creates a new listening UDPConn.
|
||||
Listen(addr *net.UDPAddr) (model.UDPLikeConn, error)
|
||||
}
|
||||
|
||||
// ErrorWrapperQUICListener is a QUICListener that wraps errors.
|
||||
type ErrorWrapperQUICListener struct {
|
||||
// QUICListener is the underlying listener.
|
||||
QUICListener QUICListener
|
||||
}
|
||||
|
||||
var _ QUICListener = &ErrorWrapperQUICListener{}
|
||||
|
||||
// Listen implements QUICListener.Listen.
|
||||
func (qls *ErrorWrapperQUICListener) Listen(addr *net.UDPAddr) (model.UDPLikeConn, error) {
|
||||
pconn, err := qls.QUICListener.Listen(addr)
|
||||
if err != nil {
|
||||
return nil, SafeErrWrapperBuilder{
|
||||
Error: err,
|
||||
Operation: netxlite.QUICListenOperation,
|
||||
}.MaybeBuild()
|
||||
}
|
||||
return &errorWrapperUDPConn{pconn}, nil
|
||||
}
|
||||
|
||||
// errorWrapperUDPConn is a model.UDPLikeConn that wraps errors.
|
||||
type errorWrapperUDPConn struct {
|
||||
// UDPLikeConn is the underlying conn.
|
||||
model.UDPLikeConn
|
||||
}
|
||||
|
||||
var _ model.UDPLikeConn = &errorWrapperUDPConn{}
|
||||
|
||||
// WriteTo implements model.UDPLikeConn.WriteTo.
|
||||
func (c *errorWrapperUDPConn) WriteTo(p []byte, addr net.Addr) (int, error) {
|
||||
count, err := c.UDPLikeConn.WriteTo(p, addr)
|
||||
if err != nil {
|
||||
return 0, SafeErrWrapperBuilder{
|
||||
Error: err,
|
||||
Operation: netxlite.WriteToOperation,
|
||||
}.MaybeBuild()
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// ReadFrom implements model.UDPLikeConn.ReadFrom.
|
||||
func (c *errorWrapperUDPConn) ReadFrom(b []byte) (int, net.Addr, error) {
|
||||
n, addr, err := c.UDPLikeConn.ReadFrom(b)
|
||||
if err != nil {
|
||||
return 0, nil, SafeErrWrapperBuilder{
|
||||
Error: err,
|
||||
Operation: netxlite.ReadFromOperation,
|
||||
}.MaybeBuild()
|
||||
}
|
||||
return n, addr, nil
|
||||
}
|
||||
|
||||
// ErrorWrapperQUICDialer is a dialer that performs quic err wrapping
|
||||
type ErrorWrapperQUICDialer struct {
|
||||
Dialer QUICContextDialer
|
||||
}
|
||||
|
||||
// DialContext implements ContextDialer.DialContext
|
||||
func (d *ErrorWrapperQUICDialer) 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)
|
||||
if err != nil {
|
||||
return nil, SafeErrWrapperBuilder{
|
||||
Classifier: netxlite.ClassifyQUICHandshakeError,
|
||||
Error: err,
|
||||
Operation: netxlite.QUICHandshakeOperation,
|
||||
}.MaybeBuild()
|
||||
}
|
||||
return sess, nil
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
package errorsx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/model/mocks"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
nlmocks "github.com/ooni/probe-cli/v3/internal/netxlite/mocks"
|
||||
)
|
||||
|
||||
func TestErrorWrapperQUICListenerSuccess(t *testing.T) {
|
||||
ql := &ErrorWrapperQUICListener{
|
||||
QUICListener: &mocks.QUICListener{
|
||||
MockListen: func(addr *net.UDPAddr) (model.UDPLikeConn, error) {
|
||||
return &net.UDPConn{}, nil
|
||||
},
|
||||
},
|
||||
}
|
||||
pconn, err := ql.Listen(&net.UDPAddr{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
pconn.Close()
|
||||
}
|
||||
|
||||
func TestErrorWrapperQUICListenerFailure(t *testing.T) {
|
||||
ql := &ErrorWrapperQUICListener{
|
||||
QUICListener: &mocks.QUICListener{
|
||||
MockListen: func(addr *net.UDPAddr) (model.UDPLikeConn, error) {
|
||||
return nil, io.EOF
|
||||
},
|
||||
},
|
||||
}
|
||||
pconn, err := ql.Listen(&net.UDPAddr{})
|
||||
if err.Error() != "eof_error" {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
if pconn != nil {
|
||||
t.Fatal("expected nil pconn here")
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorWrapperUDPConnWriteToSuccess(t *testing.T) {
|
||||
quc := &errorWrapperUDPConn{
|
||||
UDPLikeConn: &mocks.QUICUDPLikeConn{
|
||||
MockWriteTo: func(p []byte, addr net.Addr) (int, error) {
|
||||
return 10, nil
|
||||
},
|
||||
},
|
||||
}
|
||||
pkt := make([]byte, 128)
|
||||
addr := &net.UDPAddr{}
|
||||
cnt, err := quc.WriteTo(pkt, addr)
|
||||
if err != nil {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
if cnt != 10 {
|
||||
t.Fatal("expected 10 here")
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorWrapperUDPConnWriteToFailure(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
quc := &errorWrapperUDPConn{
|
||||
UDPLikeConn: &mocks.QUICUDPLikeConn{
|
||||
MockWriteTo: func(p []byte, addr net.Addr) (int, error) {
|
||||
return 0, expected
|
||||
},
|
||||
},
|
||||
}
|
||||
pkt := make([]byte, 128)
|
||||
addr := &net.UDPAddr{}
|
||||
cnt, err := quc.WriteTo(pkt, addr)
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
if cnt != 0 {
|
||||
t.Fatal("expected 0 here")
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorWrapperUDPConnReadFromSuccess(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
quc := &errorWrapperUDPConn{
|
||||
UDPLikeConn: &mocks.QUICUDPLikeConn{
|
||||
MockReadFrom: func(b []byte) (int, net.Addr, error) {
|
||||
return 0, nil, expected
|
||||
},
|
||||
},
|
||||
}
|
||||
b := make([]byte, 128)
|
||||
n, addr, err := quc.ReadFrom(b)
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
if n != 0 {
|
||||
t.Fatal("expected 0 here")
|
||||
}
|
||||
if addr != nil {
|
||||
t.Fatal("expected nil here")
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorWrapperUDPConnReadFromFailure(t *testing.T) {
|
||||
quc := &errorWrapperUDPConn{
|
||||
UDPLikeConn: &mocks.QUICUDPLikeConn{
|
||||
MockReadFrom: func(b []byte) (int, net.Addr, error) {
|
||||
return 10, nil, nil
|
||||
},
|
||||
},
|
||||
}
|
||||
b := make([]byte, 128)
|
||||
n, addr, err := quc.ReadFrom(b)
|
||||
if err != nil {
|
||||
t.Fatal("not the error we expected", err)
|
||||
}
|
||||
if n != 10 {
|
||||
t.Fatal("expected 10 here")
|
||||
}
|
||||
if addr != nil {
|
||||
t.Fatal("expected nil here")
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorWrapperQUICDialerFailure(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
d := &ErrorWrapperQUICDialer{Dialer: &nlmocks.QUICContextDialer{
|
||||
MockDialContext: func(ctx context.Context, network, address string, tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlySession, error) {
|
||||
return nil, io.EOF
|
||||
},
|
||||
}}
|
||||
sess, err := d.DialContext(
|
||||
ctx, "udp", "www.google.com:443", &tls.Config{}, &quic.Config{})
|
||||
if sess != nil {
|
||||
t.Fatal("expected a nil sess here")
|
||||
}
|
||||
if !errors.Is(err, io.EOF) {
|
||||
t.Fatal("expected another error here")
|
||||
}
|
||||
var errWrapper *netxlite.ErrWrapper
|
||||
if !errors.As(err, &errWrapper) {
|
||||
t.Fatal("cannot cast to ErrWrapper")
|
||||
}
|
||||
if errWrapper.Operation != netxlite.QUICHandshakeOperation {
|
||||
t.Fatal("unexpected Operation")
|
||||
}
|
||||
if errWrapper.Failure != netxlite.FailureEOFError {
|
||||
t.Fatal("unexpected failure")
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package errorsx
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
// Resolver is a DNS resolver. The *net.Resolver used by Go implements
|
||||
// this interface, but other implementations are possible.
|
||||
type Resolver interface {
|
||||
// LookupHost resolves a hostname to a list of IP addresses.
|
||||
LookupHost(ctx context.Context, hostname string) (addrs []string, err error)
|
||||
}
|
||||
|
||||
// ErrorWrapperResolver is a Resolver that knows about wrapping errors.
|
||||
type ErrorWrapperResolver struct {
|
||||
Resolver
|
||||
}
|
||||
|
||||
var _ Resolver = &ErrorWrapperResolver{}
|
||||
|
||||
// LookupHost implements Resolver.LookupHost
|
||||
func (r *ErrorWrapperResolver) LookupHost(ctx context.Context, hostname string) ([]string, error) {
|
||||
addrs, err := r.Resolver.LookupHost(ctx, hostname)
|
||||
err = SafeErrWrapperBuilder{
|
||||
Classifier: netxlite.ClassifyResolverError,
|
||||
Error: err,
|
||||
Operation: netxlite.ResolveOperation,
|
||||
}.MaybeBuild()
|
||||
return addrs, err
|
||||
}
|
||||
|
||||
type resolverNetworker interface {
|
||||
Network() string
|
||||
}
|
||||
|
||||
// Network implements Resolver.Network.
|
||||
func (r *ErrorWrapperResolver) Network() string {
|
||||
if rn, ok := r.Resolver.(resolverNetworker); ok {
|
||||
return rn.Network()
|
||||
}
|
||||
return "errorWrapper"
|
||||
}
|
||||
|
||||
type resolverAddresser interface {
|
||||
Address() string
|
||||
}
|
||||
|
||||
// Address implements Resolver.Address.
|
||||
func (r *ErrorWrapperResolver) Address() string {
|
||||
if ra, ok := r.Resolver.(resolverAddresser); ok {
|
||||
return ra.Address()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package errorsx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/model/mocks"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
func TestErrorWrapperResolverSuccess(t *testing.T) {
|
||||
orig := []string{"8.8.8.8"}
|
||||
r := &ErrorWrapperResolver{
|
||||
Resolver: &mocks.Resolver{
|
||||
MockLookupHost: func(ctx context.Context, domain string) ([]string, error) {
|
||||
return orig, nil
|
||||
},
|
||||
},
|
||||
}
|
||||
addrs, err := r.LookupHost(context.Background(), "dns.google.com")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(addrs) != len(orig) || addrs[0] != orig[0] {
|
||||
t.Fatal("not the result we expected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorWrapperResolverFailure(t *testing.T) {
|
||||
r := &ErrorWrapperResolver{
|
||||
Resolver: &mocks.Resolver{
|
||||
MockLookupHost: func(ctx context.Context, domain string) ([]string, error) {
|
||||
return nil, errors.New("no such host")
|
||||
},
|
||||
},
|
||||
}
|
||||
ctx := context.Background()
|
||||
addrs, err := r.LookupHost(ctx, "dns.google.com")
|
||||
if addrs != nil {
|
||||
t.Fatal("expected nil addr here")
|
||||
}
|
||||
var errWrapper *netxlite.ErrWrapper
|
||||
if !errors.As(err, &errWrapper) {
|
||||
t.Fatal("cannot properly cast the returned error")
|
||||
}
|
||||
if errWrapper.Failure != netxlite.FailureDNSNXDOMAINError {
|
||||
t.Fatal("unexpected failure")
|
||||
}
|
||||
if errWrapper.Operation != netxlite.ResolveOperation {
|
||||
t.Fatal("unexpected Operation")
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorWrapperResolverChildNetworkAddress(t *testing.T) {
|
||||
r := &ErrorWrapperResolver{Resolver: &mocks.Resolver{
|
||||
MockNetwork: func() string {
|
||||
return "udp"
|
||||
},
|
||||
MockAddress: func() string {
|
||||
return "8.8.8.8:53"
|
||||
},
|
||||
}}
|
||||
if r.Network() != "udp" {
|
||||
t.Fatal("invalid Network")
|
||||
}
|
||||
if r.Address() != "8.8.8.8:53" {
|
||||
t.Fatal("invalid Address")
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorWrapperResolverNoChildNetworkAddress(t *testing.T) {
|
||||
r := &ErrorWrapperResolver{Resolver: &net.Resolver{}}
|
||||
if r.Network() != "errorWrapper" {
|
||||
t.Fatal("invalid Network")
|
||||
}
|
||||
if r.Address() != "" {
|
||||
t.Fatal("invalid Address")
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package errorsx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
// TLSHandshaker is the generic TLS handshaker
|
||||
type TLSHandshaker interface {
|
||||
Handshake(ctx context.Context, conn net.Conn, config *tls.Config) (
|
||||
net.Conn, tls.ConnectionState, error)
|
||||
}
|
||||
|
||||
// ErrorWrapperTLSHandshaker wraps the returned error to be an OONI error
|
||||
type ErrorWrapperTLSHandshaker struct {
|
||||
TLSHandshaker
|
||||
}
|
||||
|
||||
// Handshake implements TLSHandshaker.Handshake
|
||||
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 = SafeErrWrapperBuilder{
|
||||
Classifier: netxlite.ClassifyTLSHandshakeError,
|
||||
Error: err,
|
||||
Operation: netxlite.TLSHandshakeOperation,
|
||||
}.MaybeBuild()
|
||||
return tlsconn, state, err
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package errorsx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/model/mocks"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
func TestErrorWrapperTLSHandshakerFailure(t *testing.T) {
|
||||
th := ErrorWrapperTLSHandshaker{TLSHandshaker: &mocks.TLSHandshaker{
|
||||
MockHandshake: func(ctx context.Context, conn net.Conn, config *tls.Config) (net.Conn, tls.ConnectionState, error) {
|
||||
return nil, tls.ConnectionState{}, io.EOF
|
||||
},
|
||||
}}
|
||||
conn, _, err := th.Handshake(
|
||||
context.Background(), &mocks.Conn{
|
||||
MockRead: func(b []byte) (int, error) {
|
||||
return 0, io.EOF
|
||||
},
|
||||
}, new(tls.Config))
|
||||
if !errors.Is(err, io.EOF) {
|
||||
t.Fatal("not the error that we expected")
|
||||
}
|
||||
if conn != nil {
|
||||
t.Fatal("expected nil con here")
|
||||
}
|
||||
var errWrapper *netxlite.ErrWrapper
|
||||
if !errors.As(err, &errWrapper) {
|
||||
t.Fatal("cannot cast to ErrWrapper")
|
||||
}
|
||||
if errWrapper.Failure != netxlite.FailureEOFError {
|
||||
t.Fatal("unexpected Failure")
|
||||
}
|
||||
if errWrapper.Operation != netxlite.TLSHandshakeOperation {
|
||||
t.Fatal("unexpected Operation")
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/geolocate"
|
||||
errorsxlegacy "github.com/ooni/probe-cli/v3/internal/engine/legacy/errorsx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
@@ -111,10 +110,7 @@ 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 = errorsxlegacy.SafeErrWrapperBuilder{
|
||||
Error: err,
|
||||
Operation: netxlite.TopLevelOperation,
|
||||
}.MaybeBuild()
|
||||
err = netxlite.NewTopLevelGenericErrWrapper(err)
|
||||
errWrapper := err.(*netxlite.ErrWrapper)
|
||||
s := errWrapper.Failure
|
||||
if s == "" {
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"net"
|
||||
"net/url"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/legacy/errorsx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
@@ -61,8 +60,7 @@ type Config struct {
|
||||
|
||||
// New creates a new Dialer from the specified config and resolver.
|
||||
func New(config *Config, resolver Resolver) Dialer {
|
||||
var d Dialer = netxlite.DefaultDialer
|
||||
d = &errorsx.ErrorWrapperDialer{Dialer: d}
|
||||
var d Dialer = &netxlite.ErrorWrapperDialer{Dialer: netxlite.DefaultDialer}
|
||||
if config.Logger != nil {
|
||||
d = &netxlite.DialerLogger{
|
||||
Dialer: netxlite.NewDialerLegacyAdapter(d),
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/legacy/errorsx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
@@ -56,7 +55,7 @@ func TestNewCreatesTheExpectedChain(t *testing.T) {
|
||||
if !ok {
|
||||
t.Fatal("invalid type")
|
||||
}
|
||||
ewd, ok := dad.DialerLegacy.(*errorsx.ErrorWrapperDialer)
|
||||
ewd, ok := dad.DialerLegacy.(*netxlite.ErrorWrapperDialer)
|
||||
if !ok {
|
||||
t.Fatal("not an errorWrappingDialer")
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@ import (
|
||||
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
"github.com/ooni/probe-cli/v3/internal/bytecounter"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/legacy/errorsx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/dialer"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/httptransport"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/quicdialer"
|
||||
@@ -129,7 +128,7 @@ func NewResolver(config Config) Resolver {
|
||||
if config.BogonIsError {
|
||||
r = resolver.BogonResolver{Resolver: r}
|
||||
}
|
||||
r = &errorsx.ErrorWrapperResolver{Resolver: r}
|
||||
r = &netxlite.ErrorWrapperResolver{Resolver: netxlite.NewResolverLegacyAdapter(r)}
|
||||
if config.Logger != nil {
|
||||
r = &netxlite.ResolverLogger{
|
||||
Logger: config.Logger,
|
||||
@@ -162,7 +161,7 @@ func NewQUICDialer(config Config) QUICDialer {
|
||||
config.FullResolver = NewResolver(config)
|
||||
}
|
||||
var ql quicdialer.QUICListener = &netxlite.QUICListenerStdlib{}
|
||||
ql = &errorsx.ErrorWrapperQUICListener{QUICListener: ql}
|
||||
ql = &netxlite.ErrorWrapperQUICListener{QUICListener: ql}
|
||||
if config.ReadWriteSaver != nil {
|
||||
ql = &quicdialer.QUICListenerSaver{
|
||||
QUICListener: ql,
|
||||
@@ -172,7 +171,9 @@ func NewQUICDialer(config Config) QUICDialer {
|
||||
var d quicdialer.ContextDialer = &netxlite.QUICDialerQUICGo{
|
||||
QUICListener: ql,
|
||||
}
|
||||
d = &errorsx.ErrorWrapperQUICDialer{Dialer: d}
|
||||
d = &netxlite.ErrorWrapperQUICDialer{
|
||||
QUICDialer: netxlite.NewQUICDialerFromContextDialerAdapter(d),
|
||||
}
|
||||
if config.TLSSaver != nil {
|
||||
d = quicdialer.HandshakeSaver{Saver: config.TLSSaver, Dialer: d}
|
||||
}
|
||||
@@ -189,7 +190,7 @@ func NewTLSDialer(config Config) TLSDialer {
|
||||
config.Dialer = NewDialer(config)
|
||||
}
|
||||
var h tlsHandshaker = &netxlite.TLSHandshakerConfigurable{}
|
||||
h = &errorsx.ErrorWrapperTLSHandshaker{TLSHandshaker: h}
|
||||
h = &netxlite.ErrorWrapperTLSHandshaker{TLSHandshaker: h}
|
||||
if config.Logger != nil {
|
||||
h = &netxlite.TLSHandshakerLogger{DebugLogger: config.Logger, TLSHandshaker: h}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/ooni/probe-cli/v3/internal/bytecounter"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/legacy/errorsx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/httptransport"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/resolver"
|
||||
@@ -31,11 +30,11 @@ func TestNewResolverVanilla(t *testing.T) {
|
||||
if !ok {
|
||||
t.Fatal("not the resolver we expected")
|
||||
}
|
||||
ewr, ok := rla.ResolverLegacy.(*errorsx.ErrorWrapperResolver)
|
||||
ewr, ok := rla.ResolverLegacy.(*netxlite.ErrorWrapperResolver)
|
||||
if !ok {
|
||||
t.Fatal("not the resolver we expected")
|
||||
}
|
||||
ar, ok := ewr.Resolver.(*resolver.AddressResolver)
|
||||
ar, ok := ewr.Resolver.(*netxlite.ResolverLegacyAdapter).ResolverLegacy.(*resolver.AddressResolver)
|
||||
if !ok {
|
||||
t.Fatal("not the resolver we expected")
|
||||
}
|
||||
@@ -63,11 +62,11 @@ func TestNewResolverSpecificResolver(t *testing.T) {
|
||||
if !ok {
|
||||
t.Fatal("not the resolver we expected")
|
||||
}
|
||||
ewr, ok := rla.ResolverLegacy.(*errorsx.ErrorWrapperResolver)
|
||||
ewr, ok := rla.ResolverLegacy.(*netxlite.ErrorWrapperResolver)
|
||||
if !ok {
|
||||
t.Fatal("not the resolver we expected")
|
||||
}
|
||||
ar, ok := ewr.Resolver.(*resolver.AddressResolver)
|
||||
ar, ok := ewr.Resolver.(*netxlite.ResolverLegacyAdapter).ResolverLegacy.(*resolver.AddressResolver)
|
||||
if !ok {
|
||||
t.Fatal("not the resolver we expected")
|
||||
}
|
||||
@@ -93,11 +92,11 @@ func TestNewResolverWithBogonFilter(t *testing.T) {
|
||||
if !ok {
|
||||
t.Fatal("not the resolver we expected")
|
||||
}
|
||||
ewr, ok := rla.ResolverLegacy.(*errorsx.ErrorWrapperResolver)
|
||||
ewr, ok := rla.ResolverLegacy.(*netxlite.ErrorWrapperResolver)
|
||||
if !ok {
|
||||
t.Fatal("not the resolver we expected")
|
||||
}
|
||||
br, ok := ewr.Resolver.(resolver.BogonResolver)
|
||||
br, ok := ewr.Resolver.(*netxlite.ResolverLegacyAdapter).ResolverLegacy.(resolver.BogonResolver)
|
||||
if !ok {
|
||||
t.Fatal("not the resolver we expected")
|
||||
}
|
||||
@@ -146,11 +145,11 @@ func TestNewResolverWithLogging(t *testing.T) {
|
||||
if !ok {
|
||||
t.Fatal("not the resolver we expected")
|
||||
}
|
||||
ewr, ok := rla.ResolverLegacy.(*errorsx.ErrorWrapperResolver)
|
||||
ewr, ok := rla.ResolverLegacy.(*netxlite.ErrorWrapperResolver)
|
||||
if !ok {
|
||||
t.Fatalf("not the resolver we expected %T", rla.ResolverLegacy)
|
||||
}
|
||||
ar, ok := ewr.Resolver.(*resolver.AddressResolver)
|
||||
ar, ok := ewr.Resolver.(*netxlite.ResolverLegacyAdapter).ResolverLegacy.(*resolver.AddressResolver)
|
||||
if !ok {
|
||||
t.Fatal("not the resolver we expected")
|
||||
}
|
||||
@@ -184,11 +183,11 @@ func TestNewResolverWithSaver(t *testing.T) {
|
||||
if sr.Saver != saver {
|
||||
t.Fatal("not the saver we expected")
|
||||
}
|
||||
ewr, ok := sr.Resolver.(*errorsx.ErrorWrapperResolver)
|
||||
ewr, ok := sr.Resolver.(*netxlite.ErrorWrapperResolver)
|
||||
if !ok {
|
||||
t.Fatal("not the resolver we expected")
|
||||
}
|
||||
ar, ok := ewr.Resolver.(*resolver.AddressResolver)
|
||||
ar, ok := ewr.Resolver.(*netxlite.ResolverLegacyAdapter).ResolverLegacy.(*resolver.AddressResolver)
|
||||
if !ok {
|
||||
t.Fatal("not the resolver we expected")
|
||||
}
|
||||
@@ -214,11 +213,11 @@ func TestNewResolverWithReadWriteCache(t *testing.T) {
|
||||
if !ok {
|
||||
t.Fatal("not the resolver we expected")
|
||||
}
|
||||
ewr, ok := rla.ResolverLegacy.(*errorsx.ErrorWrapperResolver)
|
||||
ewr, ok := rla.ResolverLegacy.(*netxlite.ErrorWrapperResolver)
|
||||
if !ok {
|
||||
t.Fatal("not the resolver we expected")
|
||||
}
|
||||
cr, ok := ewr.Resolver.(*resolver.CacheResolver)
|
||||
cr, ok := ewr.Resolver.(*netxlite.ResolverLegacyAdapter).ResolverLegacy.(*resolver.CacheResolver)
|
||||
if !ok {
|
||||
t.Fatal("not the resolver we expected")
|
||||
}
|
||||
@@ -253,11 +252,11 @@ func TestNewResolverWithPrefilledReadonlyCache(t *testing.T) {
|
||||
if !ok {
|
||||
t.Fatal("not the resolver we expected")
|
||||
}
|
||||
ewr, ok := rla.ResolverLegacy.(*errorsx.ErrorWrapperResolver)
|
||||
ewr, ok := rla.ResolverLegacy.(*netxlite.ErrorWrapperResolver)
|
||||
if !ok {
|
||||
t.Fatal("not the resolver we expected")
|
||||
}
|
||||
cr, ok := ewr.Resolver.(*resolver.CacheResolver)
|
||||
cr, ok := ewr.Resolver.(*netxlite.ResolverLegacyAdapter).ResolverLegacy.(*resolver.CacheResolver)
|
||||
if !ok {
|
||||
t.Fatal("not the resolver we expected")
|
||||
}
|
||||
@@ -302,7 +301,7 @@ func TestNewTLSDialerVanilla(t *testing.T) {
|
||||
if rtd.TLSHandshaker == nil {
|
||||
t.Fatal("invalid TLSHandshaker")
|
||||
}
|
||||
ewth, ok := rtd.TLSHandshaker.(*errorsx.ErrorWrapperTLSHandshaker)
|
||||
ewth, ok := rtd.TLSHandshaker.(*netxlite.ErrorWrapperTLSHandshaker)
|
||||
if !ok {
|
||||
t.Fatal("not the TLSHandshaker we expected")
|
||||
}
|
||||
@@ -331,7 +330,7 @@ func TestNewTLSDialerWithConfig(t *testing.T) {
|
||||
if rtd.TLSHandshaker == nil {
|
||||
t.Fatal("invalid TLSHandshaker")
|
||||
}
|
||||
ewth, ok := rtd.TLSHandshaker.(*errorsx.ErrorWrapperTLSHandshaker)
|
||||
ewth, ok := rtd.TLSHandshaker.(*netxlite.ErrorWrapperTLSHandshaker)
|
||||
if !ok {
|
||||
t.Fatal("not the TLSHandshaker we expected")
|
||||
}
|
||||
@@ -370,7 +369,7 @@ func TestNewTLSDialerWithLogging(t *testing.T) {
|
||||
if lth.DebugLogger != log.Log {
|
||||
t.Fatal("not the Logger we expected")
|
||||
}
|
||||
ewth, ok := lth.TLSHandshaker.(*errorsx.ErrorWrapperTLSHandshaker)
|
||||
ewth, ok := lth.TLSHandshaker.(*netxlite.ErrorWrapperTLSHandshaker)
|
||||
if !ok {
|
||||
t.Fatal("not the TLSHandshaker we expected")
|
||||
}
|
||||
@@ -410,7 +409,7 @@ func TestNewTLSDialerWithSaver(t *testing.T) {
|
||||
if sth.Saver != saver {
|
||||
t.Fatal("not the Logger we expected")
|
||||
}
|
||||
ewth, ok := sth.TLSHandshaker.(*errorsx.ErrorWrapperTLSHandshaker)
|
||||
ewth, ok := sth.TLSHandshaker.(*netxlite.ErrorWrapperTLSHandshaker)
|
||||
if !ok {
|
||||
t.Fatal("not the TLSHandshaker we expected")
|
||||
}
|
||||
@@ -443,7 +442,7 @@ func TestNewTLSDialerWithNoTLSVerifyAndConfig(t *testing.T) {
|
||||
if rtd.TLSHandshaker == nil {
|
||||
t.Fatal("invalid TLSHandshaker")
|
||||
}
|
||||
ewth, ok := rtd.TLSHandshaker.(*errorsx.ErrorWrapperTLSHandshaker)
|
||||
ewth, ok := rtd.TLSHandshaker.(*netxlite.ErrorWrapperTLSHandshaker)
|
||||
if !ok {
|
||||
t.Fatal("not the TLSHandshaker we expected")
|
||||
}
|
||||
@@ -478,7 +477,7 @@ func TestNewTLSDialerWithNoTLSVerifyAndNoConfig(t *testing.T) {
|
||||
if rtd.TLSHandshaker == nil {
|
||||
t.Fatal("invalid TLSHandshaker")
|
||||
}
|
||||
ewth, ok := rtd.TLSHandshaker.(*errorsx.ErrorWrapperTLSHandshaker)
|
||||
ewth, ok := rtd.TLSHandshaker.(*netxlite.ErrorWrapperTLSHandshaker)
|
||||
if !ok {
|
||||
t.Fatal("not the TLSHandshaker we expected")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user