Skip to content

Commit

Permalink
swarm: fix Unwrap for DialError, implement Unwrap for TransportError
Browse files Browse the repository at this point in the history
  • Loading branch information
sukunrt committed Aug 25, 2023
1 parent cd930fa commit 5d41d7f
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 8 deletions.
25 changes: 18 additions & 7 deletions p2p/net/swarm/dial_error.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,7 @@ func (e *DialError) recordErr(addr ma.Multiaddr, err error) {
e.Skipped++
return
}
e.DialErrors = append(e.DialErrors, TransportError{
Address: addr,
Cause: err,
})
e.DialErrors = append(e.DialErrors, TransportError{Address: addr, Cause: err})
}

func (e *DialError) Error() string {
Expand All @@ -51,9 +48,19 @@ func (e *DialError) Error() string {
return builder.String()
}

// Unwrap implements https://godoc.org/golang.org/x/xerrors#Wrapper.
func (e *DialError) Unwrap() error {
return e.Cause
func (e *DialError) Unwrap() []error {
if e == nil {
return nil
}

errs := make([]error, len(e.DialErrors)+1)
if e.Cause != nil {
errs = append(errs, e.Cause)
}
for i := 0; i < len(e.DialErrors); i++ {
errs = append(errs, &e.DialErrors[i])
}
return errs
}

var _ error = (*DialError)(nil)
Expand All @@ -68,4 +75,8 @@ func (e *TransportError) Error() string {
return fmt.Sprintf("failed to dial %s: %s", e.Address, e.Cause)
}

func (e *TransportError) Unwrap() error {
return e.Cause
}

var _ error = (*TransportError)(nil)
51 changes: 51 additions & 0 deletions p2p/net/swarm/dial_error_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package swarm

import (
"net"
"os"
"testing"

ma "github.com/multiformats/go-multiaddr"
"github.com/stretchr/testify/require"
)

func TestTransportError(t *testing.T) {
aa := ma.StringCast("/ip4/1.2.3.4/tcp/1234")
te := &TransportError{Address: aa, Cause: ErrDialBackoff}
require.ErrorIs(t, te, ErrDialBackoff, "TransportError should implement Unwrap")
}

func TestDialError(t *testing.T) {
de := &DialError{Peer: "pid", Cause: ErrGaterDisallowedConnection}
require.ErrorIs(t, de, ErrGaterDisallowedConnection,
"DialError Unwrap should handle DialError.Cause")
require.ErrorIs(t, de, de, "DialError Unwrap should handle match to self")

aa := ma.StringCast("/ip4/1.2.3.4/tcp/1234")
ab := ma.StringCast("/ip6/1::1/udp/1234/quic-v1")
de = &DialError{
Peer: "pid",
DialErrors: []TransportError{
{Address: aa, Cause: ErrDialBackoff}, {Address: ab, Cause: ErrNoTransport},
},
}
require.ErrorIs(t, de, ErrDialBackoff, "DialError.Unwrap should traverse TransportErrors")
require.ErrorIs(t, de, ErrNoTransport, "DialError.Unwrap should traverse TransportErrors")

de = &DialError{
Peer: "pid",
DialErrors: []TransportError{{Address: ab, Cause: ErrNoTransport},
// wrapped error 2 levels deep
{Address: aa, Cause: &net.OpError{
Op: "write",
Net: "tcp",
Err: &os.SyscallError{
Syscall: "connect",
Err: os.ErrPermission,
},
}},
},
}
require.ErrorIs(t, de, os.ErrPermission, "DialError.Unwrap should traverse TransportErrors")

}
2 changes: 1 addition & 1 deletion p2p/net/swarm/swarm_dial_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -372,5 +372,5 @@ func TestBlackHoledAddrBlocked(t *testing.T) {
if !errors.As(err, &de) {
t.Fatalf("expected to receive an error of type *DialError, got %s of type %T", err, err)
}
require.Contains(t, de.DialErrors, TransportError{Address: addr, Cause: ErrDialRefusedBlackHole})
require.ErrorIs(t, err, ErrDialRefusedBlackHole)
}

0 comments on commit 5d41d7f

Please sign in to comment.