The utility of SafeErrWrapperBuilder is low. Let us instead change the code to always create ErrWrapper when we're in this package. While there, also note some TODO-next items. Part of https://github.com/ooni/probe/issues/1505.
		
			
				
	
	
		
			189 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			189 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package errorsx
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"errors"
 | |
| 	"io"
 | |
| 	"net"
 | |
| 	"testing"
 | |
| 
 | |
| 	"github.com/ooni/probe-cli/v3/internal/netxmocks"
 | |
| )
 | |
| 
 | |
| func TestErrorWrapperDialerFailure(t *testing.T) {
 | |
| 	ctx := context.Background()
 | |
| 	d := &ErrorWrapperDialer{Dialer: &netxmocks.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 *ErrWrapper
 | |
| 	if !errors.As(err, &ew) {
 | |
| 		t.Fatal("cannot convert to ErrWrapper")
 | |
| 	}
 | |
| 	if ew.Operation != ConnectOperation {
 | |
| 		t.Fatal("unexpected operation", ew.Operation)
 | |
| 	}
 | |
| 	if ew.Failure != 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: &netxmocks.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: &netxmocks.Conn{
 | |
| 			MockRead: func(b []byte) (int, error) {
 | |
| 				return 0, io.EOF
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 	buf := make([]byte, 1024)
 | |
| 	cnt, err := c.Read(buf)
 | |
| 	var ew *ErrWrapper
 | |
| 	if !errors.As(err, &ew) {
 | |
| 		t.Fatal("cannot cast error to ErrWrapper")
 | |
| 	}
 | |
| 	if ew.Operation != ReadOperation {
 | |
| 		t.Fatal("invalid operation", ew.Operation)
 | |
| 	}
 | |
| 	if ew.Failure != 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: &netxmocks.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: &netxmocks.Conn{
 | |
| 			MockWrite: func(b []byte) (int, error) {
 | |
| 				return 0, io.EOF
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 	buf := make([]byte, 1024)
 | |
| 	cnt, err := c.Write(buf)
 | |
| 	var ew *ErrWrapper
 | |
| 	if !errors.As(err, &ew) {
 | |
| 		t.Fatal("cannot cast error to ErrWrapper")
 | |
| 	}
 | |
| 	if ew.Operation != WriteOperation {
 | |
| 		t.Fatal("invalid operation", ew.Operation)
 | |
| 	}
 | |
| 	if ew.Failure != 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: &netxmocks.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: &netxmocks.Conn{
 | |
| 			MockClose: func() error {
 | |
| 				return io.EOF
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 	err := c.Close()
 | |
| 	var ew *ErrWrapper
 | |
| 	if !errors.As(err, &ew) {
 | |
| 		t.Fatal("cannot cast error to ErrWrapper")
 | |
| 	}
 | |
| 	if ew.Operation != CloseOperation {
 | |
| 		t.Fatal("invalid operation", ew.Operation)
 | |
| 	}
 | |
| 	if ew.Failure != 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: &netxmocks.Conn{
 | |
| 			MockClose: func() error {
 | |
| 				return nil
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 	err := c.Close()
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| }
 |