File: //proc/self/root/opt/go/pkg/mod/github.com/hashicorp/
[email protected]/sockaddrs_test.go
package sockaddr_test
import (
crand "crypto/rand"
"fmt"
"math"
"math/big"
"math/rand"
"testing"
"time"
sockaddr "github.com/hashicorp/go-sockaddr"
)
func init() {
seedMathRand()
}
// seedMathRand provides weak, but guaranteed seeding, which is better than
// running with Go's default seed of 1.
func seedMathRand() {
n, err := crand.Int(crand.Reader, big.NewInt(math.MaxInt64))
if err != nil {
rand.Seed(time.Now().UTC().UnixNano())
return
}
rand.Seed(n.Int64())
}
// NOTE: A number of these code paths are exercised in template/ and
// cmd/sockaddr/
// sockAddrStringInputs allows for easy test creation by developers.
// Parallel arrays of string inputs are converted to their SockAddr
// equivalents for use by unit tests.
type sockAddrStringInputs []struct {
inputAddrs []string
sortedAddrs []string
sortedTypes []sockaddr.SockAddrType
sortFuncs []sockaddr.CmpAddrFunc
numIPv4Inputs int
numIPv6Inputs int
numUnixInputs int
}
func convertToSockAddrs(t *testing.T, inputs []string) sockaddr.SockAddrs {
sockAddrs := make(sockaddr.SockAddrs, 0, len(inputs))
for i, input := range inputs {
sa, err := sockaddr.NewSockAddr(input)
if err != nil {
t.Fatalf("[%d] Invalid SockAddr input for %+q: %v", i, input, err)
}
sockAddrs = append(sockAddrs, sa)
}
return sockAddrs
}
// shuffleStrings randomly shuffles the list of strings
func shuffleStrings(list []string) {
for i := range list {
j := rand.Intn(i + 1)
list[i], list[j] = list[j], list[i]
}
}
func TestSockAddr_SockAddrs_AscAddress(t *testing.T) {
testInputs := sockAddrStringInputs{
{ // testNum: 0
sortFuncs: []sockaddr.CmpAddrFunc{
sockaddr.AscAddress,
},
numIPv4Inputs: 9,
numIPv6Inputs: 1,
numUnixInputs: 0,
inputAddrs: []string{
"10.0.0.0/8",
"172.16.1.3/12",
"128.95.120.2:53",
"128.95.120.2/32",
"192.168.0.0/16",
"128.95.120.1/32",
"192.168.1.10/24",
"128.95.120.2:8600",
"240.0.0.1/4",
"::",
},
sortedAddrs: []string{
"10.0.0.0/8",
"128.95.120.1/32",
"128.95.120.2:53",
"128.95.120.2/32",
"128.95.120.2:8600",
"172.16.1.3/12",
"192.168.0.0/16",
"192.168.1.10/24",
"240.0.0.1/4",
"::",
},
},
}
for idx, test := range testInputs {
t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) {
shuffleStrings(test.inputAddrs)
inputSockAddrs := convertToSockAddrs(t, test.inputAddrs)
sas := convertToSockAddrs(t, test.sortedAddrs)
sortedIPv4Addrs, nonIPv4Addrs := sas.FilterByType(sockaddr.TypeIPv4)
if l := len(sortedIPv4Addrs); l != test.numIPv4Inputs {
t.Fatalf("[%d] Missing IPv4Addrs: expected %d, received %d", idx, test.numIPv4Inputs, l)
}
if len(nonIPv4Addrs) != test.numIPv6Inputs+test.numUnixInputs {
t.Fatalf("[%d] Non-IPv4 Address in input", idx)
}
// Copy inputAddrs so we can manipulate it. wtb const.
sockAddrs := append(sockaddr.SockAddrs(nil), inputSockAddrs...)
filteredAddrs, _ := sockAddrs.FilterByType(sockaddr.TypeIPv4)
sockaddr.OrderedAddrBy(test.sortFuncs...).Sort(filteredAddrs)
ipv4SockAddrs, nonIPv4s := filteredAddrs.FilterByType(sockaddr.TypeIPv4)
if len(nonIPv4s) != 0 {
t.Fatalf("[%d] bad", idx)
}
for i, ipv4SockAddr := range ipv4SockAddrs {
ipv4Addr := sockaddr.ToIPv4Addr(ipv4SockAddr)
sortedIPv4Addr := sockaddr.ToIPv4Addr(sortedIPv4Addrs[i])
if ipv4Addr.Address != sortedIPv4Addr.Address {
t.Errorf("[%d/%d] Sort equality failed: expected %s, received %s", idx, i, sortedIPv4Addrs[i], ipv4Addr)
}
}
})
}
}
func TestSockAddr_SockAddrs_AscPrivate(t *testing.T) {
testInputs := []struct {
sortFuncs []sockaddr.CmpAddrFunc
inputAddrs []string
sortedAddrs []string
}{
{ // testNum: 0
sortFuncs: []sockaddr.CmpAddrFunc{
sockaddr.AscType,
sockaddr.AscPrivate,
sockaddr.AscAddress,
sockaddr.AscType,
sockaddr.AscAddress,
sockaddr.AscPort,
},
inputAddrs: []string{
"10.0.0.0/8",
"172.16.1.3/12",
"192.168.0.0/16",
"192.168.0.0/16",
"192.168.1.10/24",
"128.95.120.1/32",
"128.95.120.2/32",
"128.95.120.2:53",
"128.95.120.2:8600",
"240.0.0.1/4",
"::",
},
sortedAddrs: []string{
"10.0.0.0/8",
"172.16.1.3/12",
"192.168.0.0/16",
"192.168.0.0/16",
"192.168.1.10/24",
"240.0.0.1/4",
"128.95.120.1/32",
"128.95.120.2/32",
// "128.95.120.2:53",
// "128.95.120.2:8600",
// "::",
},
},
{
sortFuncs: []sockaddr.CmpAddrFunc{
sockaddr.AscType,
sockaddr.AscPrivate,
sockaddr.AscAddress,
},
inputAddrs: []string{
"1.2.3.4:53",
"192.168.1.2",
"/tmp/foo",
"[cc::1]:8600",
"[::1]:53",
},
sortedAddrs: []string{
"/tmp/foo",
"192.168.1.2",
"1.2.3.4:53",
"[::1]:53",
"[cc::1]:8600",
},
},
{
sortFuncs: []sockaddr.CmpAddrFunc{
sockaddr.AscType,
sockaddr.AscPrivate,
sockaddr.AscAddress,
},
inputAddrs: []string{
"/tmp/foo",
"/tmp/bar",
"1.2.3.4",
},
sortedAddrs: []string{
"/tmp/bar",
"/tmp/foo",
"1.2.3.4",
},
},
}
for idx, test := range testInputs {
t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) {
sortedAddrs := convertToSockAddrs(t, test.sortedAddrs)
inputAddrs := append([]string(nil), test.inputAddrs...)
shuffleStrings(inputAddrs)
inputSockAddrs := convertToSockAddrs(t, inputAddrs)
sockaddr.OrderedAddrBy(test.sortFuncs...).Sort(inputSockAddrs)
for i, sockAddr := range sortedAddrs {
if !sockAddr.Equal(inputSockAddrs[i]) {
t.Logf("Input Addrs:\t%+v", inputAddrs)
t.Logf("Sorted Addrs:\t%+v", inputSockAddrs)
t.Logf("Expected Addrs:\t%+v", test.sortedAddrs)
t.Fatalf("[%d/%d] Sort AscType/AscAddress failed: expected %+q, received %+q", idx, i, sockAddr, inputSockAddrs[i])
}
}
})
}
}
func TestSockAddr_SockAddrs_AscPort(t *testing.T) {
testInputs := []struct {
name string
sortFuncs []sockaddr.CmpAddrFunc
inputAddrs []string
sortedAddrs []string
}{
{
name: "simple port test",
sortFuncs: []sockaddr.CmpAddrFunc{
sockaddr.AscPort,
sockaddr.AscType,
},
inputAddrs: []string{
"1.2.3.4:53",
"/tmp/foo",
"[::1]:53",
},
sortedAddrs: []string{
"/tmp/foo",
"1.2.3.4:53",
"[::1]:53",
},
},
{
name: "simple port test",
sortFuncs: []sockaddr.CmpAddrFunc{
sockaddr.AscPort,
sockaddr.AscType,
},
inputAddrs: []string{
"1.2.3.4:53",
"/tmp/foo",
},
sortedAddrs: []string{
"/tmp/foo",
"1.2.3.4:53",
},
},
}
for idx, test := range testInputs {
t.Run(test.name, func(t *testing.T) {
sortedAddrs := convertToSockAddrs(t, test.sortedAddrs)
inputAddrs := append([]string(nil), test.inputAddrs...)
shuffleStrings(inputAddrs)
inputSockAddrs := convertToSockAddrs(t, inputAddrs)
sockaddr.OrderedAddrBy(test.sortFuncs...).Sort(inputSockAddrs)
for i, sockAddr := range sortedAddrs {
if !sockAddr.Equal(inputSockAddrs[i]) {
t.Logf("Input Addrs:\t%+v", inputAddrs)
t.Logf("Sorted Addrs:\t%+v", inputSockAddrs)
t.Logf("Expected Addrs:\t%+v", test.sortedAddrs)
t.Fatalf("[%d/%d] Sort AscType/AscAddress failed: expected %+q, received %+q", idx, i, sockAddr, inputSockAddrs[i])
}
}
})
}
}
func TestSockAddr_SockAddrs_AscType(t *testing.T) {
testInputs := sockAddrStringInputs{
{ // testNum: 0
sortFuncs: []sockaddr.CmpAddrFunc{
sockaddr.AscType,
},
inputAddrs: []string{
"10.0.0.0/8",
"172.16.1.3/12",
"128.95.120.2:53",
"::",
"128.95.120.2/32",
"192.168.0.0/16",
"128.95.120.1/32",
"192.168.1.10/24",
"128.95.120.2:8600",
"240.0.0.1/4",
},
sortedTypes: []sockaddr.SockAddrType{
sockaddr.TypeIPv4,
sockaddr.TypeIPv4,
sockaddr.TypeIPv4,
sockaddr.TypeIPv4,
sockaddr.TypeIPv4,
sockaddr.TypeIPv4,
sockaddr.TypeIPv4,
sockaddr.TypeIPv4,
sockaddr.TypeIPv4,
sockaddr.TypeIPv6,
},
},
}
for idx, test := range testInputs {
t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) {
shuffleStrings(test.inputAddrs)
inputSockAddrs := convertToSockAddrs(t, test.inputAddrs)
sortedAddrs := convertToSockAddrs(t, test.sortedAddrs)
sockaddr.OrderedAddrBy(test.sortFuncs...).Sort(inputSockAddrs)
for i, sockAddr := range sortedAddrs {
if sockAddr.Type() != sortedAddrs[i].Type() {
t.Errorf("[%d/%d] Sort AscType failed: expected %+q, received %+q", idx, i, sortedAddrs[i], sockAddr)
}
}
})
}
}