package btcwire import ( "bytes" "errors" "testing" ) func TestNewNetAddress(t *testing.T) { tests := []struct { host string port uint16 wantString string }{ {"127.0.0.1", 8333, "127.0.0.1:8333"}, {"0.0.0.0", 0, "0.0.0.0:0"}, {"255.255.255.255", 65535, "255.255.255.255:65535"}, {"192.168.1.20", 18333, "192.168.1.20:18333"}, {"::1", 8333, "[::1]:8333"}, {"::", 0, "[::]:0"}, {"2001:db8::1", 18333, "[2001:db8::1]:18333"}, {"2001:0db8:0000:0000:0000:0000:0000:0001", 1, "[2001:db8::1]:1"}, {"::ffff:1.2.3.4", 8333, "1.2.3.4:8333"}, {"[::1]", 8333, "[::1]:8333"}, {"[2001:db8::1]", 2, "[2001:db8::1]:2"}, {"2001:DB8::1", 3, "[2001:db8::1]:3"}, {"1:2:3:4:5:6:7:8", 4, "[1:2:3:4:5:6:7:8]:4"}, {"1:2:3:4:5:6:1.2.3.4", 5, "[1:2:3:4:5:6:102:304]:5"}, {"2001:db8:0:0:1:0:0:1", 6, "[2001:db8::1:0:0:1]:6"}, {"fe80::", 7, "[fe80::]:7"}, } for _, tc := range tests { t.Run(tc.host, func(t *testing.T) { addr, err := NewNetAddress(tc.host, tc.port) if err != nil { t.Fatalf("NewNetAddress(%q): %v", tc.host, err) } if got := addr.String(); got != tc.wantString { t.Fatalf("String() = %q, want %q", got, tc.wantString) } }) } } func TestNewNetAddressIPv4Mapped(t *testing.T) { addr, err := NewNetAddress("127.0.0.1", 8333) if err != nil { t.Fatalf("NewNetAddress: %v", err) } want := [16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 127, 0, 0, 1} if addr.IP != want { t.Fatalf("IP = %x, want %x", addr.IP, want) } if got := addr.IPString(); got != "127.0.0.1" { t.Fatalf("IPString() = %q, want %q", got, "127.0.0.1") } } func TestNewNetAddressErrors(t *testing.T) { hosts := []string{ "", "1.2.3", "1.2.3.4.5", "1.2.3.256", "1.2.3.-1", "1.2.3.04", "example.com", ":::", "1::2::3", "1:2:3:4:5:6:7:8:9", "12345::1", "::g", "[::1", } for _, host := range hosts { t.Run(host, func(t *testing.T) { if _, err := NewNetAddress(host, 1); !errors.Is(err, ErrInvalidAddress) { t.Fatalf("NewNetAddress(%q) error = %v, want ErrInvalidAddress", host, err) } }) } } func TestNetAddressWire(t *testing.T) { addr, err := NewNetAddress("127.0.0.1", 8080) if err != nil { t.Fatalf("NewNetAddress: %v", err) } addr.Services = ServiceNodeNetwork | ServiceNodeCompactFilters var e Encoder addr.encode(&e) want := []byte{ // Services, little endian: 1 | 1<<6 = 0x41. 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // IPv4-mapped 127.0.0.1. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x01, // Port 8080 big endian. 0x1f, 0x90, } if !bytes.Equal(e.Bytes(), want) { t.Fatalf("encoded = %x, want %x", e.Bytes(), want) } var got NetAddress d := NewDecoder(want) if err := got.decode(d); err != nil { t.Fatalf("decode: %v", err) } if got != *addr { t.Fatalf("decoded %+v, want %+v", got, *addr) } } func TestNetAddressWireRoundTrip(t *testing.T) { hosts := []string{ "127.0.0.1", "10.0.0.255", "::1", "::", "2001:db8::dead:beef", "::ffff:192.168.1.1", "fe80::1:2:3:4", } for _, host := range hosts { addr, err := NewNetAddress(host, 8333) if err != nil { t.Fatalf("NewNetAddress(%q): %v", host, err) } addr.Services = ServiceNodeWitness var e Encoder addr.encode(&e) var got NetAddress d := NewDecoder(e.Bytes()) if err := got.decode(d); err != nil { t.Fatalf("%s: decode: %v", host, err) } if got != *addr { t.Fatalf("%s: decoded %+v, want %+v", host, got, *addr) } if d.Remaining() != 0 { t.Fatalf("%s: %d bytes left", host, d.Remaining()) } } } func TestNetAddressDecodeTruncated(t *testing.T) { addr, err := NewNetAddress("127.0.0.1", 8333) if err != nil { t.Fatalf("NewNetAddress: %v", err) } var e Encoder addr.encode(&e) full := e.Bytes() for n := 0; n < len(full); n++ { var got NetAddress if err := got.decode(NewDecoder(full[:n])); err == nil { t.Fatalf("decoding %d of %d bytes succeeded", n, len(full)) } } } func TestNetAddressIsZero(t *testing.T) { var zero NetAddress if !zero.IsZero() { t.Fatal("zero NetAddress is not IsZero") } zero.Services = ServiceNodeNetwork if !zero.IsZero() { t.Fatal("services alone should not make an address non-zero") } addr := mustAddress(t, "127.0.0.1", 0) if addr.IsZero() { t.Fatal("address with non-zero IP reported IsZero") } addr = mustAddress(t, "0.0.0.0", 1) if addr.IsZero() { t.Fatal("address with non-zero port reported IsZero") } }