Skip to content

Commit

Permalink
pkg/addr: add tests for address parsing functions
Browse files Browse the repository at this point in the history
  • Loading branch information
matzf committed Jun 1, 2023
1 parent fbc3722 commit b5b945b
Show file tree
Hide file tree
Showing 6 changed files with 388 additions and 10 deletions.
12 changes: 10 additions & 2 deletions pkg/addr/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,15 @@ go_library(

go_test(
name = "go_default_test",
srcs = ["isdas_test.go"],
srcs = [
"addr_test.go",
"host_test.go",
"isdas_test.go",
"svc_test.go",
],
embed = [":go_default_library"],
deps = ["@com_github_stretchr_testify//assert:go_default_library"],
deps = [
"@com_github_stretchr_testify//assert:go_default_library",
"@com_github_stretchr_testify//require:go_default_library",
],
)
161 changes: 160 additions & 1 deletion pkg/addr/addr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,170 @@ package addr_test

import (
"fmt"
"net/netip"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/scionproto/scion/pkg/addr"
)

func ExampleParseAddr() {
a, err := addr.ParseAddr("6-ffaa:0:123,198.51.100.1")
fmt.Printf("a: %+v, err: %v\n", a, err)
fmt.Printf("ia: %v, host: %v, err: %v\n", a.IA, a.Host, err)
// Output: ia: 6-ffaa:0:123, host: 198.51.100.1, err: <nil>
}

func ExampleParseAddr_svc() {
a, err := addr.ParseAddr("6-ffaa:0:123,CS")
fmt.Printf("host type: %v, err: %v\n", a.Host.Type(), err)
// Output: host type: SVC, err: <nil>
}

func TestParseAddr(t *testing.T) {
invalid := []string{
"",
",",
"a",
"0-0::",
"0-0,::,",
"1,ffaa:0:1101::",
"65536-1,ff00::1",
"[1-ffaa:0:1101,127.0.0.1]",
}
for _, s := range invalid {
t.Run(s, func(t *testing.T) {
_, err := addr.ParseAddr(s)
assert.Error(t, err)
})
}

valid := map[string]addr.Addr{
"0-0,::": {
IA: addr.MustIAFrom(0, 0),
Host: addr.HostIP(netip.AddrFrom16([16]byte{})),
},
"0-0,0.0.0.0": {
IA: addr.MustIAFrom(0, 0),
Host: addr.HostIP(netip.AddrFrom4([4]byte{})),
},
"1-ffaa:0:1101,::1": {
IA: addr.MustIAFrom(1, 0xffaa_0000_1101),
Host: addr.HostIP(netip.AddrFrom16(
[16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
)),
},
"1-ffaa:0:1101,127.0.0.1": {
IA: addr.MustIAFrom(1, 0xffaa_0000_1101),
Host: addr.HostIP(netip.AddrFrom4([4]byte{127, 0, 0, 1})),
},
"1-ffaa:0:1101,CS": {
IA: addr.MustIAFrom(1, 0xffaa_0000_1101),
Host: addr.HostSVC(addr.SvcCS),
},
"65535-1,ff00::1": {
IA: addr.MustIAFrom(65535, 1),
Host: addr.HostIP(netip.AddrFrom16(
[16]byte{0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
)),
},
"1-1:fcd1:1,::ffff:192.0.2.128": {
IA: addr.MustIAFrom(1, 0x0001_fcd1_0001),
Host: addr.HostIP(netip.AddrFrom16(
[16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 0, 2, 128},
)),
},
}
for s, expected := range valid {
t.Run(s, func(t *testing.T) {
a, err := addr.ParseAddr(s)
require.NoError(t, err)
assert.Equal(t, expected, a)
})
}
}

func TestParseAddrPort(t *testing.T) {
invalid := []string{
"",
"[]",
"[]:",
"[0-0,::]:65536",
"[0-0,::]:http",
"[0-0,::]:a",
"[1-ffaa:0:1101,127.0.0.1]",
"[1-ffaa:0:1101,127.0.0.1]:0xff",
"[1-ffaa:0:1101,127.0.0.1]:ff",
"[1-ffaa:0:1101,127.0.0.1]:-1",
"[1-ffaa:0:1101,127.0.0.1]:666666",
}
for _, s := range invalid {
t.Run(s, func(t *testing.T) {
_, _, err := addr.ParseAddrPort(s)
assert.Error(t, err)
})
}

valid := map[string]struct {
IA addr.IA
Host addr.Host
Port uint16
}{
"[0-0,::]:0": {
IA: addr.MustIAFrom(0, 0),
Host: addr.HostIP(netip.AddrFrom16([16]byte{})),
Port: 0,
},
"[0-0,::]:65535": {
IA: addr.MustIAFrom(0, 0),
Host: addr.HostIP(netip.AddrFrom16([16]byte{})),
Port: 65535,
},
"[0-0,0.0.0.0]:1234": {
IA: addr.MustIAFrom(0, 0),
Host: addr.HostIP(netip.AddrFrom4([4]byte{})),
Port: 1234,
},
"[1-ffaa:0:1101,::1]:54321": {
IA: addr.MustIAFrom(1, 0xffaa_0000_1101),
Host: addr.HostIP(netip.AddrFrom16(
[16]byte{15: 1},
)),
Port: 54321,
},
"[1-ffaa:0:1101,127.0.0.1]:010": {
IA: addr.MustIAFrom(1, 0xffaa_0000_1101),
Host: addr.HostIP(netip.AddrFrom4([4]byte{127, 0, 0, 1})),
Port: 10,
},
"[1-ffaa:0:1101,CS]:42": {
IA: addr.MustIAFrom(1, 0xffaa_0000_1101),
Host: addr.HostSVC(addr.SvcCS),
Port: 42,
},
"[65535-1,ff00::1]:8888": {
IA: addr.MustIAFrom(65535, 1),
Host: addr.HostIP(netip.AddrFrom16(
[16]byte{0: 0xff, 15: 1},
)),
Port: 8888,
},
"[1-1:fcd1:1,::ffff:192.0.2.128]:0000000000000000000080": {
IA: addr.MustIAFrom(1, 0x0001_fcd1_0001),
Host: addr.HostIP(netip.AddrFrom16(
[16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 0, 2, 128},
)),
Port: 80,
},
}

for s, expected := range valid {
t.Run(s, func(t *testing.T) {
a, port, err := addr.ParseAddrPort(s)
require.NoError(t, err)
assert.Equal(t, addr.Addr{IA: expected.IA, Host: expected.Host}, a)
assert.Equal(t, expected.Port, port)
})
}
}
4 changes: 2 additions & 2 deletions pkg/addr/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ type Host struct {
// s can either be a SVC address, in the format supported by ParseSVC(s),
// or an IP address in dotted decimal or IPv6 format.
func ParseHost(s string) (Host, error) {
svc := ParseSVC(s)
if svc != SvcNone {
svc, err := ParseSVC(s)
if err == nil {
return HostSVC(svc), nil
}
ip, err := netip.ParseAddr(s)
Expand Down
143 changes: 143 additions & 0 deletions pkg/addr/host_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// Copyright 2023 SCION Association
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package addr_test

import (
"fmt"
"net/netip"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/scionproto/scion/pkg/addr"
)

func ExampleHost() {
hs := []addr.Host{
{},
addr.HostIP(netip.MustParseAddr("::1")),
addr.HostIP(netip.AddrFrom4([4]byte{198, 51, 100, 1})),
addr.HostSVC(addr.SvcCS),
}
for _, h := range hs {
fmt.Printf("h: %q, h.Type(): %q", h, h.Type())
switch h.Type() {
case addr.HostTypeIP:
fmt.Printf(", h.IP().Is4(): %v", h.IP().Is4())
case addr.HostTypeSVC:
fmt.Printf(", h.SVC().IsMulticast(): %v", h.SVC().IsMulticast())
default:
fmt.Printf(", h == addr.Host{}: %v", h == addr.Host{})
}
fmt.Println()
}

// Use Host as map key:
stuff := make(map[addr.Host]struct{})
for _, h := range hs {
stuff[h] = struct{}{}
}
_, hasSvcCS := stuff[addr.HostSVC(addr.SvcCS)]
_, hasSvcDS := stuff[addr.HostSVC(addr.SvcDS)]
fmt.Printf("has SvcCS: %v, has SvcDS: %v", hasSvcCS, hasSvcDS)

// Output:
// h: "<None>", h.Type(): "None", h == addr.Host{}: true
// h: "::1", h.Type(): "IP", h.IP().Is4(): false
// h: "198.51.100.1", h.Type(): "IP", h.IP().Is4(): true
// h: "CS A (0x0002)", h.Type(): "SVC", h.SVC().IsMulticast(): false
// has SvcCS: true, has SvcDS: false
}

func TestParseHost(t *testing.T) {
invalid := []string{
"",
"x",
"512.0.0.1",
"10.1234567",
"::ffff1",
"2001:0db8:85a3:0000:0000:8a2e:0370:7334:1", // too long
" ::1",
"::1 ",
"localhost",
"CS_X", // almost a service addr
}
for _, s := range invalid {
t.Run(s, func(t *testing.T) {
_, err := addr.ParseHost(s)
assert.Error(t, err)
})
}

ipv6 := []string{
"::",
"::1",
"::ff02:1",
"2001:0db8:85a3:0000:0000:8a2e:0370:7334",
"fe80::1ff:fe23:4567:890a%eth2",
"::ffff:192.0.2.128",
"ff00::",
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
}
for _, s := range ipv6 {
t.Run(s, func(t *testing.T) {
h, err := addr.ParseHost(s)
require.NoError(t, err)
require.Equal(t, addr.HostTypeIP, h.Type())
assert.True(t, h.IP().Is6())
assert.Equal(t, netip.MustParseAddr(s), h.IP())
})
}

ipv4 := []string{
"0.0.0.0",
"127.0.0.1",
"198.51.100.0",
"198.51.100.1",
"198.51.100.254",
"198.51.100.255",
"255.255.255.255",
}
for _, s := range ipv4 {
t.Run(s, func(t *testing.T) {
h, err := addr.ParseHost(s)
require.NoError(t, err)
require.Equal(t, addr.HostTypeIP, h.Type())
assert.True(t, h.IP().Is4())
assert.Equal(t, netip.MustParseAddr(s), h.IP())
})
}

svcs := map[string]addr.SVC{
"CS": addr.SvcCS,
"DS": addr.SvcDS,
"Wildcard": addr.SvcWildcard,
"CS_A": addr.SvcCS,
"DS_A": addr.SvcDS,
"Wildcard_A": addr.SvcWildcard,
"CS_M": addr.SvcCS.Multicast(),
"DS_M": addr.SvcDS.Multicast(),
"Wildcard_M": addr.SvcWildcard.Multicast(),
}
for src, svc := range svcs {
t.Run(src, func(t *testing.T) {
h, err := addr.ParseHost(src)
require.NoError(t, err)
require.Equal(t, addr.HostTypeSVC, h.Type())
assert.Equal(t, svc, h.SVC())
})
}
}
Loading

0 comments on commit b5b945b

Please sign in to comment.