blob: 413ab144c110681d76a79bf1069e7b3a54dbea9b [file] [log] [blame]
// Copyright 2016 The Netstack Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package tcpip
import (
"strings"
"testing"
)
func TestSubnetContains(t *testing.T) {
tests := []struct {
s Address
m AddressMask
a Address
want bool
}{
{"\xa0", "\xf0", "\x90", false},
{"\xa0", "\xf0", "\xa0", true},
{"\xa0", "\xf0", "\xa5", true},
{"\xa0", "\xf0", "\xaf", true},
{"\xa0", "\xf0", "\xb0", false},
{"\xa0", "\xf0", "", false},
{"\xa0", "\xf0", "\xa0\x00", false},
{"\xc2\x80", "\xff\xf0", "\xc2\x80", true},
{"\xc2\x80", "\xff\xf0", "\xc2\x00", false},
{"\xc2\x00", "\xff\xf0", "\xc2\x00", true},
{"\xc2\x00", "\xff\xf0", "\xc2\x80", false},
}
for _, tt := range tests {
s, err := NewSubnet(tt.s, tt.m)
if err != nil {
t.Errorf("NewSubnet(%v, %v) = %v", tt.s, tt.m, err)
continue
}
if got := s.Contains(tt.a); got != tt.want {
t.Errorf("Subnet(%v).Contains(%v) = %v, want %v", s, tt.a, got, tt.want)
}
}
}
func TestSubnetBits(t *testing.T) {
tests := []struct {
a AddressMask
want1 int
want0 int
}{
{"\x00", 0, 8},
{"\x00\x00", 0, 16},
{"\x36", 4, 4},
{"\x5c", 4, 4},
{"\x5c\x5c", 8, 8},
{"\x5c\x36", 8, 8},
{"\x36\x5c", 8, 8},
{"\x36\x36", 8, 8},
{"\xff", 8, 0},
{"\xff\xff", 16, 0},
}
for _, tt := range tests {
s := &Subnet{mask: tt.a}
got1, got0 := s.Bits()
if got1 != tt.want1 || got0 != tt.want0 {
t.Errorf("Subnet{mask: %x}.Bits() = %d, %d, want %d, %d", tt.a, got1, got0, tt.want1, tt.want0)
}
}
}
func TestSubnetPrefix(t *testing.T) {
tests := []struct {
a AddressMask
want int
}{
{"\x00", 0},
{"\x00\x00", 0},
{"\x36", 0},
{"\x86", 1},
{"\xc5", 2},
{"\xff\x00", 8},
{"\xff\x36", 8},
{"\xff\x8c", 9},
{"\xff\xc8", 10},
{"\xff", 8},
{"\xff\xff", 16},
}
for _, tt := range tests {
s := &Subnet{mask: tt.a}
got := s.Prefix()
if got != tt.want {
t.Errorf("Subnet{mask: %x}.Bits() = %d want %d", tt.a, got, tt.want)
}
}
}
func TestSubnetCreation(t *testing.T) {
tests := []struct {
a Address
m AddressMask
want error
}{
{"\xa0", "\xf0", nil},
{"\xa0\xa0", "\xf0", errSubnetLengthMismatch},
{"\xaa", "\xf0", errSubnetAddressMasked},
{"", "", nil},
}
for _, tt := range tests {
if _, err := NewSubnet(tt.a, tt.m); err != tt.want {
t.Errorf("NewSubnet(%v, %v) = %v, want %v", tt.a, tt.m, err, tt.want)
}
}
}
func TestRouteMatch(t *testing.T) {
tests := []struct {
d Address
m Address
a Address
want bool
}{
{"\xc2\x80", "\xff\xf0", "\xc2\x80", true},
{"\xc2\x80", "\xff\xf0", "\xc2\x00", false},
{"\xc2\x00", "\xff\xf0", "\xc2\x00", true},
{"\xc2\x00", "\xff\xf0", "\xc2\x80", false},
}
for _, tt := range tests {
r := Route{Destination: tt.d, Mask: tt.m}
if got := r.Match(tt.a); got != tt.want {
t.Errorf("Route(%v).Match(%v) = %v, want %v", r, tt.a, got, tt.want)
}
}
}
func TestParse(t *testing.T) {
tests := []struct {
txt string
addr Address
}{
{"::", Address(strings.Repeat("\x00", 16))},
{"8::", Address("\x00\x08" + strings.Repeat("\x00", 14))},
{"::8a", Address(strings.Repeat("\x00", 14) + "\x00\x8a")},
{"fe80::1234:5678", "\xfe\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x34\x56\x78"},
{"fe80::b097:c9ff:fe02:477", "\xfe\x80\x00\x00\x00\x00\x00\x00\xb0\x97\xc9\xff\xfe\x02\x04\x77"},
{"a:b:c:d:1:2:3:4", "\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x01\x00\x02\x00\x03\x00\x04"},
{"a:b:c::2:3:4", "\x00\x0a\x00\x0b\x00\x0c\x00\x00\x00\x00\x00\x02\x00\x03\x00\x04"},
{"000a:000b:000c::", "\x00\x0a\x00\x0b\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"},
{"0000:0000:0000::0001", Address(strings.Repeat("\x00", 15) + "\x01")},
{"0:0::1", Address(strings.Repeat("\x00", 15) + "\x01")},
}
for _, test := range tests {
got := Parse(test.txt)
if got != test.addr {
t.Errorf("Parse(%v)=%v, want %v", test.txt, got, test.addr)
}
}
}
func TestAddressString(t *testing.T) {
tests := []string{
"a:b:c::2:3:4",
"8::",
"fe80::5054:ff:fe12:3456",
"::1",
}
for _, want := range tests {
addr := Parse(want)
if got := addr.String(); got != want {
t.Errorf("Address(%x).String()=%q, want %q", addr, got, want)
}
}
}