ceremonyclient/go-multiaddr/net/convert_test.go
2024-10-12 11:55:17 -07:00

267 lines
7.0 KiB
Go

package manet
import (
"net"
"runtime"
"testing"
ma "github.com/multiformats/go-multiaddr"
)
type GenFunc func() (ma.Multiaddr, error)
func testConvert(t *testing.T, s string, gen GenFunc) {
m, err := gen()
if err != nil {
t.Fatal("failed to generate.")
}
if s2 := m.String(); err != nil || s2 != s {
t.Fatal("failed to convert: " + s + " != " + s2)
}
}
func testToNetAddr(t *testing.T, maddr, ntwk, addr string) {
m, err := ma.NewMultiaddr(maddr)
if err != nil {
t.Fatal("failed to generate.")
}
naddr, err := ToNetAddr(m)
if addr == "" { // should fail
if err == nil {
t.Fatalf("failed to error: %s", m)
}
return
}
// shouldn't fail
if err != nil {
t.Fatalf("failed to convert to net addr: %s", m)
}
if naddr.String() != addr {
t.Fatalf("naddr.Address() == %s != %s", naddr, addr)
}
if naddr.Network() != ntwk {
t.Fatalf("naddr.Network() == %s != %s", naddr.Network(), ntwk)
}
// should convert properly
switch ntwk {
case "tcp":
taddr := naddr.(*net.TCPAddr)
if ip, err := ToIP(m); err != nil || !taddr.IP.Equal(ip) {
t.Fatalf("ToIP() and ToNetAddr diverged: %s != %s", taddr, ip)
}
case "udp":
uaddr := naddr.(*net.UDPAddr)
if ip, err := ToIP(m); err != nil || !uaddr.IP.Equal(ip) {
t.Fatalf("ToIP() and ToNetAddr diverged: %s != %s", uaddr, ip)
}
case "ip":
ipaddr := naddr.(*net.IPAddr)
if ip, err := ToIP(m); err != nil || !ipaddr.IP.Equal(ip) {
t.Fatalf("ToIP() and ToNetAddr diverged: %s != %s", ipaddr, ip)
}
}
}
func TestFromIP4(t *testing.T) {
testConvert(t, "/ip4/10.20.30.40", func() (ma.Multiaddr, error) {
return FromNetAddr(&net.IPAddr{IP: net.ParseIP("10.20.30.40")})
})
}
func TestFromUnix(t *testing.T) {
path := "/C:/foo/bar"
if runtime.GOOS == "windows" {
path = `C:\foo\bar`
}
testConvert(t, "/unix/C:/foo/bar", func() (ma.Multiaddr, error) {
return FromNetAddr(&net.UnixAddr{Name: path, Net: "unix"})
})
}
func TestToUnix(t *testing.T) {
path := "/C:/foo/bar"
if runtime.GOOS == "windows" {
path = `C:\foo\bar`
}
testToNetAddr(t, "/unix/C:/foo/bar", "unix", path)
}
func TestFromIP6(t *testing.T) {
testConvert(t, "/ip6/2001:4860:0:2001::68", func() (ma.Multiaddr, error) {
return FromNetAddr(&net.IPAddr{IP: net.ParseIP("2001:4860:0:2001::68")})
})
}
func TestFromTCP(t *testing.T) {
testConvert(t, "/ip4/10.20.30.40/tcp/1234", func() (ma.Multiaddr, error) {
return FromNetAddr(&net.TCPAddr{
IP: net.ParseIP("10.20.30.40"),
Port: 1234,
})
})
}
func TestFromUDP(t *testing.T) {
testConvert(t, "/ip4/10.20.30.40/udp/1234", func() (ma.Multiaddr, error) {
return FromNetAddr(&net.UDPAddr{
IP: net.ParseIP("10.20.30.40"),
Port: 1234,
})
})
}
func TestThinWaist(t *testing.T) {
addrs := map[string]bool{
"/ip4/127.0.0.1/udp/1234": true,
"/ip4/127.0.0.1/tcp/1234": true,
"/ip4/127.0.0.1/udp/1234/tcp/1234": true,
"/ip4/127.0.0.1/tcp/12345/ip4/1.2.3.4": true,
"/ip6/::1/tcp/80": true,
"/ip6/::1/udp/80": true,
"/ip6/::1": true,
"/ip6zone/hello/ip6/fe80::1/tcp/80": true,
"/ip6zone/hello/ip6/fe80::1": true,
"/tcp/1234/ip4/1.2.3.4": false,
"/tcp/1234": false,
"/tcp/1234/udp/1234": false,
"/ip4/1.2.3.4/ip4/2.3.4.5": true,
"/ip6/fe80::1/ip4/2.3.4.5": true,
"/ip6zone/hello/ip6/fe80::1/ip4/2.3.4.5": true,
// Invalid ip6zone usage:
"/ip6zone/hello": false,
"/ip6zone/hello/ip4/1.1.1.1": false,
}
for a, res := range addrs {
m, err := ma.NewMultiaddr(a)
if err != nil {
t.Fatalf("failed to construct Multiaddr: %s", a)
}
if IsThinWaist(m) != res {
t.Fatalf("IsThinWaist(%s) != %v", a, res)
}
}
}
func TestDialArgs(t *testing.T) {
test := func(e_maddr, e_nw, e_host string) {
m, err := ma.NewMultiaddr(e_maddr)
if err != nil {
t.Fatal("failed to construct", e_maddr)
}
nw, host, err := DialArgs(m)
if err != nil {
t.Fatal("failed to get dial args", e_maddr, m, err)
}
if nw != e_nw {
t.Error("failed to get udp network Dial Arg", e_nw, nw)
}
if host != e_host {
t.Error("failed to get host:port Dial Arg", e_host, host)
}
}
test_error := func(e_maddr string) {
m, err := ma.NewMultiaddr(e_maddr)
if err != nil {
t.Fatal("failed to construct", e_maddr)
}
_, _, err = DialArgs(m)
if err == nil {
t.Fatal("expected DialArgs to fail on", e_maddr)
}
}
test("/ip4/127.0.0.1/udp/1234", "udp4", "127.0.0.1:1234")
test("/ip4/127.0.0.1/tcp/4321", "tcp4", "127.0.0.1:4321")
test("/ip6/::1/udp/1234", "udp6", "[::1]:1234")
test("/ip6/::1/tcp/4321", "tcp6", "[::1]:4321")
test("/ip6/::1", "ip6", "::1") // Just an IP
test("/ip4/1.2.3.4", "ip4", "1.2.3.4") // Just an IP
test("/ip6zone/foo/ip6/::1/tcp/4321", "tcp6", "[::1%foo]:4321") // zone
test("/ip6zone/foo/ip6/::1/udp/4321", "udp6", "[::1%foo]:4321") // zone
test("/ip6zone/foo/ip6/::1", "ip6", "::1%foo") // no TCP
test_error("/ip6zone/foo/ip4/127.0.0.1") // IP4 doesn't take zone
test("/ip6zone/foo/ip6/::1/ip6zone/bar", "ip6", "::1%foo") // IP over IP
test_error("/ip6zone/foo/ip6zone/bar/ip6/::1") // Only one zone per IP6
test("/dns/abc.com/tcp/1234", "tcp", "abc.com:1234") // DNS4:port
test("/dns4/abc.com/tcp/1234", "tcp4", "abc.com:1234") // DNS4:port
test("/dns4/abc.com", "ip4", "abc.com") // Just DNS4
test("/dns6/abc.com/udp/1234", "udp6", "abc.com:1234") // DNS6:port
test("/dns6/abc.com", "ip6", "abc.com") // Just DNS6
}
func TestMultiaddrToIPNet(t *testing.T) {
type testCase struct {
name string
ma string
ips []string
contained []bool
}
testCases := []testCase{
{
name: "basic",
ma: "/ip4/1.2.3.0/ipcidr/24",
ips: []string{"1.2.3.4", "1.2.3.9", "2.1.1.1"},
contained: []bool{true, true, false},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
ma, _ := ma.StringCast(tc.ma)
ipnet, err := MultiaddrToIPNet(ma)
if err != nil {
t.Fatalf("failed to parse multiaddr %v into ipnet", ma)
}
for i, ipString := range tc.ips {
ip := net.ParseIP(ipString)
if ip == nil {
t.Fatalf("failed to parse IP %s", ipString)
}
if ipnet.Contains(ip) != tc.contained[i] {
t.Fatalf("Contains check failed. Expected %v got %v", tc.contained[i], ipnet.Contains(ip))
}
}
})
}
}
func TestFailMultiaddrToIPNet(t *testing.T) {
type testCase struct {
name string
ma string
}
testCases := []testCase{
{name: "missing ip addr", ma: "/ipcidr/24"},
{name: "wrong mask", ma: "/ip4/1.2.3.0/ipcidr/128"},
{name: "wrong mask", ma: "/ip6/::/ipcidr/255"},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
ma, _ := ma.StringCast(tc.ma)
_, err := MultiaddrToIPNet(ma)
if err == nil {
t.Fatalf("Expected error when parsing: %s", tc.ma)
}
})
}
}