From f0d721a2a69a635010b35af2bfba77e5e11556de Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Fri, 29 Nov 2024 18:57:52 +0300 Subject: [PATCH 1/8] Refactor and fix 'NewPeerInfoFromString' Add check for IP address parsing failure. Improved 'TestNewPeerInfoFromString'. --- pkg/proto/proto.go | 20 +++++++++++------ pkg/proto/proto_test.go | 48 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 57 insertions(+), 11 deletions(-) diff --git a/pkg/proto/proto.go b/pkg/proto/proto.go index 8a917301f..476e55ce1 100644 --- a/pkg/proto/proto.go +++ b/pkg/proto/proto.go @@ -744,19 +744,25 @@ type PeerInfo struct { } func NewPeerInfoFromString(addr string) (PeerInfo, error) { - parts := strings.Split(addr, ":") - if len(parts) != 2 { - return PeerInfo{}, errors.Errorf("invalid addr %s", addr) + host, port, err := net.SplitHostPort(addr) + if err != nil { + return PeerInfo{}, errors.Wrap(err, "failed to split host and port") } - ip := net.ParseIP(parts[0]) - port, err := strconv.ParseUint(parts[1], 10, 16) + ip := net.ParseIP(host) + if ip == nil { + return PeerInfo{}, errors.Errorf("invalid ip %q", host) + } + portNum, err := strconv.ParseUint(port, 10, 16) if err != nil { - return PeerInfo{}, errors.Errorf("invalid port %s", parts[1]) + return PeerInfo{}, errors.Errorf("invalid port %q", port) + } + if portNum == 0 { + return PeerInfo{}, errors.Errorf("invalid port %q", port) } return PeerInfo{ Addr: ip, - Port: uint16(port), + Port: uint16(portNum), }, nil } diff --git a/pkg/proto/proto_test.go b/pkg/proto/proto_test.go index bdad8a522..545e421c5 100644 --- a/pkg/proto/proto_test.go +++ b/pkg/proto/proto_test.go @@ -7,6 +7,7 @@ import ( "encoding/json" "fmt" "io" + "math" "net" "sort" "strings" @@ -14,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/wavesplatform/gowaves/pkg/crypto" ) @@ -277,10 +279,48 @@ func TestPeerInfoMarshalJSON(t *testing.T) { } func TestNewPeerInfoFromString(t *testing.T) { - rs, err := NewPeerInfoFromString("34.253.153.4:6868") - require.NoError(t, err) - assert.Equal(t, "34.253.153.4", rs.Addr.String()) - assert.EqualValues(t, 6868, rs.Port) + tests := []struct { + in string + out PeerInfo + err string + }{ + {"34.253.153.4:6868", PeerInfo{net.IPv4(34, 253, 153, 4), 6868}, ""}, + {"34.444.153.4:6868", PeerInfo{}, "invalid ip \"34.444.153.4\""}, + { + fmt.Sprintf("34.44.153.4:%d", math.MaxUint16+1), + PeerInfo{}, + fmt.Sprintf("invalid port \"%d\"", math.MaxUint16+1), + }, + { + fmt.Sprintf("34.44.153.4:%d", -42), + PeerInfo{}, + fmt.Sprintf("invalid port \"%d\"", -42), + }, + {"34.44.153.4:bugaga", PeerInfo{}, "invalid port \"bugaga\""}, + {"34.44.153.4:0", PeerInfo{}, "invalid port \"0\""}, + {"34.44.153.4:", PeerInfo{}, "invalid port \"\""}, + { + "34.44.153.4", + PeerInfo{}, + "failed to split host and port: address 34.44.153.4: missing port in address", + }, + { + "34.44.153.4:42:", + PeerInfo{}, + "failed to split host and port: address 34.44.153.4:42:: too many colons in address", + }, + } + for i, tc := range tests { + t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) { + rs, err := NewPeerInfoFromString(tc.in) + if tc.err != "" { + assert.EqualError(t, err, tc.err) + } else { + require.NoError(t, err) + assert.Equal(t, tc.out, rs) + } + }) + } } func TestPeerInfoUnmarshalJSON(t *testing.T) { From 48d4a187da2e74dd4c8d3aef4d0d14c8449fadae Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Fri, 29 Nov 2024 20:28:38 +0300 Subject: [PATCH 2/8] Improve 'NewPeerInfoFromString' Add hostname IP resolving. --- pkg/proto/proto.go | 48 +++++++++++++++++++++++++++++++++++++---- pkg/proto/proto_test.go | 21 +++++++++++++++++- 2 files changed, 64 insertions(+), 5 deletions(-) diff --git a/pkg/proto/proto.go b/pkg/proto/proto.go index 476e55ce1..f157a38f9 100644 --- a/pkg/proto/proto.go +++ b/pkg/proto/proto.go @@ -6,6 +6,7 @@ import ( "encoding/binary" "fmt" "io" + "math/rand/v2" "net" "strconv" "strings" @@ -737,6 +738,46 @@ func (a *IpPort) String() string { return NewTCPAddr(a.Addr(), a.Port()).String() } +func ipV4Loopback() net.IP { + const a, b, c, d = 127, 0, 0, 1 + return net.IPv4(a, b, c, d) +} + +func filterToIPV4(ips []net.IP) []net.IP { + for i := 0; i < len(ips); i++ { + ip := ips[i] + if ip.IsLoopback() { + // after resolving localhost, ip can be in both format, unify it to IPv4 + ips[i] = ipV4Loopback() + continue + } + if ip.To4() == nil { // for now we support only IPv4 + ips = append(ips[:i], ips[i+1:]...) // remove non-IPv4 address, assume that count of addresses is small + } + } + return ips +} + +func resolveHostToIPv4(host string) (net.IP, error) { + if ip := net.ParseIP(host); ip != nil { // try to parse host as IP address + if ip.To4() == nil { + return nil, errors.Errorf("non-IPv4 address %q", host) + } + return ip, nil // host is already an IP address + } + ips, err := net.LookupIP(host) // try to resolve host + if err != nil { + return nil, errors.Wrapf(err, "failed to resolve host %q", host) + } + ips = filterToIPV4(ips) + if len(ips) == 0 { + return nil, errors.Errorf("no IPv4 addresses found for host %q", host) + } + // Select random IPv4 from the list + n := rand.IntN(len(ips)) // #nosec: it's ok to use math/rand/v2 here + return ips[n], nil +} + // PeerInfo represents the address of a single peer type PeerInfo struct { Addr net.IP @@ -748,10 +789,9 @@ func NewPeerInfoFromString(addr string) (PeerInfo, error) { if err != nil { return PeerInfo{}, errors.Wrap(err, "failed to split host and port") } - - ip := net.ParseIP(host) - if ip == nil { - return PeerInfo{}, errors.Errorf("invalid ip %q", host) + ip, err := resolveHostToIPv4(host) + if err != nil { + return PeerInfo{}, errors.Wrap(err, "failed to resolve host") } portNum, err := strconv.ParseUint(port, 10, 16) if err != nil { diff --git a/pkg/proto/proto_test.go b/pkg/proto/proto_test.go index 545e421c5..4efe1cd4e 100644 --- a/pkg/proto/proto_test.go +++ b/pkg/proto/proto_test.go @@ -285,7 +285,26 @@ func TestNewPeerInfoFromString(t *testing.T) { err string }{ {"34.253.153.4:6868", PeerInfo{net.IPv4(34, 253, 153, 4), 6868}, ""}, - {"34.444.153.4:6868", PeerInfo{}, "invalid ip \"34.444.153.4\""}, + { + "34.444.153.4:6868", + PeerInfo{}, + "failed to resolve host: failed to resolve host \"34.444.153.4\": lookup 34.444.153.4: no such host", + }, + { + "jfhasjdhfkmnn:6868", + PeerInfo{}, + "failed to resolve host: failed to resolve host \"jfhasjdhfkmnn\": lookup jfhasjdhfkmnn: no such host", + }, + { + "localhost:6868", + PeerInfo{net.IPv4(127, 0, 0, 1), 6868}, + "", + }, + { + "127.0.0.1:6868", + PeerInfo{net.IPv4(127, 0, 0, 1), 6868}, + "", + }, { fmt.Sprintf("34.44.153.4:%d", math.MaxUint16+1), PeerInfo{}, From f211e0f1f0e64d116f014a020ab2b181594f69f5 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Fri, 29 Nov 2024 20:46:00 +0300 Subject: [PATCH 3/8] Simplified 'NewTCPAddrFromString' --- pkg/proto/proto.go | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/pkg/proto/proto.go b/pkg/proto/proto.go index f157a38f9..d89633e35 100644 --- a/pkg/proto/proto.go +++ b/pkg/proto/proto.go @@ -376,23 +376,14 @@ func (a TCPAddr) Equal(other TCPAddr) bool { return a.IP.Equal(other.IP) && a.Port == other.Port } +// NewTCPAddrFromString creates TCPAddr from string. +// Returns empty TCPAddr if string can't be parsed. func NewTCPAddrFromString(s string) TCPAddr { - host, port, err := net.SplitHostPort(s) + pi, err := NewPeerInfoFromString(s) if err != nil { - return TCPAddr{} + return TCPAddr{} // return empty TCPAddr in case of error } - ip := net.ParseIP(host) - if ip == nil { - ips, err := net.LookupIP(host) - if err == nil { - ip = ips[0] - } - } - p, err := strconv.ParseUint(port, 10, 16) - if err != nil { - return TCPAddr{} - } - return NewTCPAddr(ip, int(p)) + return NewTCPAddr(pi.Addr, int(pi.Port)) } func NewTcpAddrFromUint64(value uint64) TCPAddr { From 90fd325d0ee60f62c7b627ab20564f5acb440f69 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Mon, 2 Dec 2024 23:36:56 +0300 Subject: [PATCH 4/8] Refactoring and bugfix of 'resolveHostToIPv4' - Now it returns ipV4 address exactly in ipV4 form. - Fixed bug with skipping address for chesk after ipV6 removal. - Fixed bug with duplication of ipV4 address when resolving 'localhost'. --- pkg/proto/proto.go | 22 ++++++++-------------- pkg/proto/proto_test.go | 6 +++--- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/pkg/proto/proto.go b/pkg/proto/proto.go index d89633e35..c4bebc7f1 100644 --- a/pkg/proto/proto.go +++ b/pkg/proto/proto.go @@ -729,21 +729,14 @@ func (a *IpPort) String() string { return NewTCPAddr(a.Addr(), a.Port()).String() } -func ipV4Loopback() net.IP { - const a, b, c, d = 127, 0, 0, 1 - return net.IPv4(a, b, c, d) -} - func filterToIPV4(ips []net.IP) []net.IP { for i := 0; i < len(ips); i++ { - ip := ips[i] - if ip.IsLoopback() { - // after resolving localhost, ip can be in both format, unify it to IPv4 - ips[i] = ipV4Loopback() - continue - } - if ip.To4() == nil { // for now we support only IPv4 + ipV4 := ips[i].To4() + if ipV4 == nil { // for now we support only IPv4 ips = append(ips[:i], ips[i+1:]...) // remove non-IPv4 address, assume that count of addresses is small + i-- // move back to check next address + } else { + ips[i] = ipV4 // replace with exact IPv4 form (ipV4 can be in both forms: ipv4 and ipV4 in ipv6) } } return ips @@ -751,10 +744,11 @@ func filterToIPV4(ips []net.IP) []net.IP { func resolveHostToIPv4(host string) (net.IP, error) { if ip := net.ParseIP(host); ip != nil { // try to parse host as IP address - if ip.To4() == nil { + ipV4 := ip.To4() // try to convert to IPv4 + if ipV4 == nil { return nil, errors.Errorf("non-IPv4 address %q", host) } - return ip, nil // host is already an IP address + return ipV4, nil // host is already an IP address, return it } ips, err := net.LookupIP(host) // try to resolve host if err != nil { diff --git a/pkg/proto/proto_test.go b/pkg/proto/proto_test.go index 4efe1cd4e..72f93d5e6 100644 --- a/pkg/proto/proto_test.go +++ b/pkg/proto/proto_test.go @@ -284,7 +284,7 @@ func TestNewPeerInfoFromString(t *testing.T) { out PeerInfo err string }{ - {"34.253.153.4:6868", PeerInfo{net.IPv4(34, 253, 153, 4), 6868}, ""}, + {"34.253.153.4:6868", PeerInfo{net.IPv4(34, 253, 153, 4).To4(), 6868}, ""}, { "34.444.153.4:6868", PeerInfo{}, @@ -297,12 +297,12 @@ func TestNewPeerInfoFromString(t *testing.T) { }, { "localhost:6868", - PeerInfo{net.IPv4(127, 0, 0, 1), 6868}, + PeerInfo{net.IPv4(127, 0, 0, 1).To4(), 6868}, "", }, { "127.0.0.1:6868", - PeerInfo{net.IPv4(127, 0, 0, 1), 6868}, + PeerInfo{net.IPv4(127, 0, 0, 1).To4(), 6868}, "", }, { From 9cba6cbeb35fefdf234fb390b4c06110234ccc31 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Tue, 3 Dec 2024 00:12:48 +0300 Subject: [PATCH 5/8] Optimized a bit 'filterToIPV4'. --- pkg/proto/proto.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/proto/proto.go b/pkg/proto/proto.go index c4bebc7f1..e1312e930 100644 --- a/pkg/proto/proto.go +++ b/pkg/proto/proto.go @@ -733,8 +733,10 @@ func filterToIPV4(ips []net.IP) []net.IP { for i := 0; i < len(ips); i++ { ipV4 := ips[i].To4() if ipV4 == nil { // for now we support only IPv4 - ips = append(ips[:i], ips[i+1:]...) // remove non-IPv4 address, assume that count of addresses is small - i-- // move back to check next address + iLast := len(ips) - 1 + ips[i], ips[iLast] = ips[iLast], nil // move last address to the current position, order is not important + ips = ips[:iLast] // remove last address + i-- // move back to check the previously last address } else { ips[i] = ipV4 // replace with exact IPv4 form (ipV4 can be in both forms: ipv4 and ipV4 in ipv6) } From a2eaf3d170aa8826f234fffc7f0676000e61755e Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Tue, 3 Dec 2024 00:38:53 +0300 Subject: [PATCH 6/8] Create 'NewPeerInfosFromString' function. --- pkg/proto/proto.go | 55 ++++++++++++++++++++++++++++++----------- pkg/proto/proto_test.go | 29 ++++++++++++++++------ 2 files changed, 62 insertions(+), 22 deletions(-) diff --git a/pkg/proto/proto.go b/pkg/proto/proto.go index e1312e930..8f039d9b0 100644 --- a/pkg/proto/proto.go +++ b/pkg/proto/proto.go @@ -744,13 +744,13 @@ func filterToIPV4(ips []net.IP) []net.IP { return ips } -func resolveHostToIPv4(host string) (net.IP, error) { +func resolveHostToIPsv4(host string) ([]net.IP, error) { if ip := net.ParseIP(host); ip != nil { // try to parse host as IP address ipV4 := ip.To4() // try to convert to IPv4 if ipV4 == nil { return nil, errors.Errorf("non-IPv4 address %q", host) } - return ipV4, nil // host is already an IP address, return it + return []net.IP{ipV4}, nil // host is already an IP address } ips, err := net.LookupIP(host) // try to resolve host if err != nil { @@ -760,9 +760,7 @@ func resolveHostToIPv4(host string) (net.IP, error) { if len(ips) == 0 { return nil, errors.Errorf("no IPv4 addresses found for host %q", host) } - // Select random IPv4 from the list - n := rand.IntN(len(ips)) // #nosec: it's ok to use math/rand/v2 here - return ips[n], nil + return ips, nil } // PeerInfo represents the address of a single peer @@ -771,25 +769,54 @@ type PeerInfo struct { Port uint16 } -func NewPeerInfoFromString(addr string) (PeerInfo, error) { +func ipsV4PortFromString(addr string) ([]net.IP, uint16, error) { host, port, err := net.SplitHostPort(addr) if err != nil { - return PeerInfo{}, errors.Wrap(err, "failed to split host and port") - } - ip, err := resolveHostToIPv4(host) - if err != nil { - return PeerInfo{}, errors.Wrap(err, "failed to resolve host") + return nil, 0, errors.Wrap(err, "failed to split host and port") } portNum, err := strconv.ParseUint(port, 10, 16) if err != nil { - return PeerInfo{}, errors.Errorf("invalid port %q", port) + return nil, 0, errors.Errorf("invalid port %q", port) } if portNum == 0 { - return PeerInfo{}, errors.Errorf("invalid port %q", port) + return nil, 0, errors.Errorf("invalid port %q", port) + } + ips, err := resolveHostToIPsv4(host) + if err != nil { + return nil, 0, errors.Wrap(err, "failed to resolve host") } + return ips, uint16(portNum), nil +} + +// NewPeerInfosFromString creates PeerInfo slice from string 'host:port'. +// It resolves host to IPv4 addresses and creates PeerInfo for each of them. +func NewPeerInfosFromString(addr string) ([]PeerInfo, error) { + ips, portNum, err := ipsV4PortFromString(addr) + if err != nil { + return nil, err + } + res := make([]PeerInfo, 0, len(ips)) + for _, ip := range ips { + res = append(res, PeerInfo{ + Addr: ip, + Port: portNum, + }) + } + return res, nil +} + +// NewPeerInfoFromString creates PeerInfo from string 'host:port'. +// It resolves host to IPv4 addresses and selects the random one using math/rand/v2. +func NewPeerInfoFromString(addr string) (PeerInfo, error) { + ips, portNum, err := ipsV4PortFromString(addr) + if err != nil { + return PeerInfo{}, err + } + n := rand.IntN(len(ips)) // #nosec: it's ok to use math/rand/v2 here + ip := ips[n] // Select random IPv4 from the list return PeerInfo{ Addr: ip, - Port: uint16(portNum), + Port: portNum, }, nil } diff --git a/pkg/proto/proto_test.go b/pkg/proto/proto_test.go index 72f93d5e6..e953e6646 100644 --- a/pkg/proto/proto_test.go +++ b/pkg/proto/proto_test.go @@ -330,14 +330,27 @@ func TestNewPeerInfoFromString(t *testing.T) { }, } for i, tc := range tests { - t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) { - rs, err := NewPeerInfoFromString(tc.in) - if tc.err != "" { - assert.EqualError(t, err, tc.err) - } else { - require.NoError(t, err) - assert.Equal(t, tc.out, rs) - } + t.Run(fmt.Sprintf("case_%d", i), func(t *testing.T) { + t.Run("NewPeerInfoFromString", func(t *testing.T) { + rs, err := NewPeerInfoFromString(tc.in) + if tc.err != "" { + assert.EqualError(t, err, tc.err) + } else { + require.NoError(t, err) + assert.Equal(t, tc.out, rs) + } + }) + t.Run("NewPeerInfosFromString", func(t *testing.T) { + rs, err := NewPeerInfosFromString(tc.in) + if tc.err != "" { + assert.EqualError(t, err, tc.err) + } else { + require.NoError(t, err) + assert.Len(t, rs, 1) + res := rs[0] + assert.Equal(t, tc.out, res) + } + }) }) } } From f03d7020a4a7c4fb7867ac23aba872951f9422ee Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Tue, 3 Dec 2024 00:48:37 +0300 Subject: [PATCH 7/8] Use 'NewPeerInfosFromString' for resolving 'host:port' records by '-peers' CLI parameter. --- cmd/node/node.go | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/cmd/node/node.go b/cmd/node/node.go index 6c8c96fa0..fdbeb8bf1 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -640,14 +640,21 @@ func spawnPeersByAddresses(ctx context.Context, addressesByComma string, pm *pee } addresses := strings.Split(addressesByComma, ",") for _, addr := range addresses { - tcpAddr := proto.NewTCPAddrFromString(addr) - if tcpAddr.Empty() { - // That means that configuration parameter is invalid - return errors.Errorf("Failed to parse TCPAddr from string %q", tcpAddr.String()) + peerInfos, err := proto.NewPeerInfosFromString(addr) + if err != nil { + return errors.Wrapf(err, "failed to resolve TCP addresses from string %q", addr) } - if pErr := pm.AddAddress(ctx, tcpAddr); pErr != nil { - // That means that we have problems with peers storage - return errors.Wrapf(pErr, "failed to add address %q into known peers storage", tcpAddr.String()) + for _, pi := range peerInfos { + tcpAddr := proto.NewTCPAddr(pi.Addr, int(pi.Port)) + if tcpAddr.Empty() { + return errors.Errorf("failed to create TCP address from IP %q and port %d", + fmt.Stringer(pi.Addr), pi.Port, + ) + } + if pErr := pm.AddAddress(ctx, tcpAddr); pErr != nil { + // That means that we have problems with peers storage + return errors.Wrapf(pErr, "failed to add address %q into known peers storage", tcpAddr.String()) + } } } return nil From b3a188c8888f81f06ff2e5473693f5aa3badd9f8 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Tue, 3 Dec 2024 01:03:00 +0300 Subject: [PATCH 8/8] Fix 'TestNewPeerInfoFromString' test. --- pkg/proto/proto_test.go | 76 +++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/pkg/proto/proto_test.go b/pkg/proto/proto_test.go index e953e6646..b63d469aa 100644 --- a/pkg/proto/proto_test.go +++ b/pkg/proto/proto_test.go @@ -280,53 +280,55 @@ func TestPeerInfoMarshalJSON(t *testing.T) { func TestNewPeerInfoFromString(t *testing.T) { tests := []struct { - in string - out PeerInfo - err string + in string + out PeerInfo + err string + platformDependentErrMsg bool }{ - {"34.253.153.4:6868", PeerInfo{net.IPv4(34, 253, 153, 4).To4(), 6868}, ""}, + {in: "34.253.153.4:6868", out: PeerInfo{net.IPv4(34, 253, 153, 4).To4(), 6868}, err: ""}, { - "34.444.153.4:6868", - PeerInfo{}, - "failed to resolve host: failed to resolve host \"34.444.153.4\": lookup 34.444.153.4: no such host", + in: "34.444.153.4:6868", + out: PeerInfo{}, + err: "failed to resolve host: failed to resolve host \"34.444.153.4\": lookup 34.444.153.4: no such host", }, { - "jfhasjdhfkmnn:6868", - PeerInfo{}, - "failed to resolve host: failed to resolve host \"jfhasjdhfkmnn\": lookup jfhasjdhfkmnn: no such host", + in: "jfhasjdhfkmnn:6868", + out: PeerInfo{}, + err: "failed to resolve host: failed to resolve host \"jfhasjdhfkmnn\": ", + platformDependentErrMsg: true, }, { - "localhost:6868", - PeerInfo{net.IPv4(127, 0, 0, 1).To4(), 6868}, - "", + in: "localhost:6868", + out: PeerInfo{net.IPv4(127, 0, 0, 1).To4(), 6868}, + err: "", }, { - "127.0.0.1:6868", - PeerInfo{net.IPv4(127, 0, 0, 1).To4(), 6868}, - "", + in: "127.0.0.1:6868", + out: PeerInfo{net.IPv4(127, 0, 0, 1).To4(), 6868}, + err: "", }, { - fmt.Sprintf("34.44.153.4:%d", math.MaxUint16+1), - PeerInfo{}, - fmt.Sprintf("invalid port \"%d\"", math.MaxUint16+1), + in: fmt.Sprintf("34.44.153.4:%d", math.MaxUint16+1), + out: PeerInfo{}, + err: fmt.Sprintf("invalid port \"%d\"", math.MaxUint16+1), }, { - fmt.Sprintf("34.44.153.4:%d", -42), - PeerInfo{}, - fmt.Sprintf("invalid port \"%d\"", -42), + in: fmt.Sprintf("34.44.153.4:%d", -42), + out: PeerInfo{}, + err: fmt.Sprintf("invalid port \"%d\"", -42), }, - {"34.44.153.4:bugaga", PeerInfo{}, "invalid port \"bugaga\""}, - {"34.44.153.4:0", PeerInfo{}, "invalid port \"0\""}, - {"34.44.153.4:", PeerInfo{}, "invalid port \"\""}, + {in: "34.44.153.4:bugaga", out: PeerInfo{}, err: "invalid port \"bugaga\""}, + {in: "34.44.153.4:0", out: PeerInfo{}, err: "invalid port \"0\""}, + {in: "34.44.153.4:", out: PeerInfo{}, err: "invalid port \"\""}, { - "34.44.153.4", - PeerInfo{}, - "failed to split host and port: address 34.44.153.4: missing port in address", + in: "34.44.153.4", + out: PeerInfo{}, + err: "failed to split host and port: address 34.44.153.4: missing port in address", }, { - "34.44.153.4:42:", - PeerInfo{}, - "failed to split host and port: address 34.44.153.4:42:: too many colons in address", + in: "34.44.153.4:42:", + out: PeerInfo{}, + err: "failed to split host and port: address 34.44.153.4:42:: too many colons in address", }, } for i, tc := range tests { @@ -334,7 +336,11 @@ func TestNewPeerInfoFromString(t *testing.T) { t.Run("NewPeerInfoFromString", func(t *testing.T) { rs, err := NewPeerInfoFromString(tc.in) if tc.err != "" { - assert.EqualError(t, err, tc.err) + if tc.platformDependentErrMsg { + assert.ErrorContains(t, err, tc.err) + } else { + assert.EqualError(t, err, tc.err) + } } else { require.NoError(t, err) assert.Equal(t, tc.out, rs) @@ -343,7 +349,11 @@ func TestNewPeerInfoFromString(t *testing.T) { t.Run("NewPeerInfosFromString", func(t *testing.T) { rs, err := NewPeerInfosFromString(tc.in) if tc.err != "" { - assert.EqualError(t, err, tc.err) + if tc.platformDependentErrMsg { + assert.ErrorContains(t, err, tc.err) + } else { + assert.EqualError(t, err, tc.err) + } } else { require.NoError(t, err) assert.Len(t, rs, 1)