397 lines
9.0 KiB
Go
397 lines
9.0 KiB
Go
package iface
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/davecgh/go-spew/spew"
|
|
)
|
|
|
|
func TestAddressConfig_String(t *testing.T) {
|
|
type test struct {
|
|
name string
|
|
ac AddressConfig
|
|
want string
|
|
}
|
|
|
|
tests := []test{{
|
|
name: "static",
|
|
ac: AddressConfigStatic,
|
|
want: "static",
|
|
},
|
|
{
|
|
name: "dhcp",
|
|
ac: AddressConfigDHCP,
|
|
want: "dhcp",
|
|
},
|
|
{
|
|
name: "manual",
|
|
ac: AddressConfigManual,
|
|
want: "manual",
|
|
},
|
|
{
|
|
name: "loopback",
|
|
ac: AddressConfigLoopback,
|
|
want: "loopback",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := tt.ac.String(); got != tt.want {
|
|
t.Errorf("String() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAddressType_String(t *testing.T) {
|
|
type test struct {
|
|
name string
|
|
at AddressVersion
|
|
want string
|
|
}
|
|
|
|
tests := []test{
|
|
{
|
|
name: "ipv4",
|
|
at: AddressVersion4,
|
|
want: "inet",
|
|
},
|
|
{
|
|
name: "ipv6",
|
|
at: AddressVersion6,
|
|
want: "inet6",
|
|
},
|
|
{
|
|
name: "nil",
|
|
at: AddressVersionNil,
|
|
want: "",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := tt.at.String(); got != tt.want {
|
|
t.Errorf("String() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNetworkInterface_String(t *testing.T) {
|
|
type test struct {
|
|
name string
|
|
builder func() *NetworkInterface
|
|
wantErrors []error
|
|
wantString string
|
|
}
|
|
|
|
tests := []test{
|
|
{
|
|
name: "static ipv4 #1",
|
|
builder: func() *NetworkInterface {
|
|
return NewNetworkInterface("eth0").
|
|
WithStatic().
|
|
WithAddressVersion(AddressVersion4).
|
|
WithAddress("10.0.0.5").
|
|
WithNetmask(8, 32).
|
|
WithGateway("10.0.0.1")
|
|
},
|
|
wantString: `auto eth0
|
|
iface eth0 inet static
|
|
address 10.0.0.5
|
|
netmask 255.0.0.0
|
|
gateway 10.0.0.1
|
|
`,
|
|
wantErrors: nil,
|
|
},
|
|
{
|
|
name: "static ipv6 #1",
|
|
builder: func() *NetworkInterface {
|
|
return NewNetworkInterface("eth0").
|
|
WithStatic().
|
|
WithAddressVersion(AddressVersion6).
|
|
WithAddress("2001:db8::1").
|
|
WithNetmask(64, 128).
|
|
WithGateway("2001:db8::2")
|
|
},
|
|
wantString: `auto eth0
|
|
iface eth0 inet6 static
|
|
address 2001:db8::1
|
|
netmask ffff:ffff:ffff:ffff::
|
|
gateway 2001:db8::2
|
|
`,
|
|
wantErrors: nil,
|
|
},
|
|
{
|
|
name: "static ipv6 #2",
|
|
builder: func() *NetworkInterface {
|
|
return NewNetworkInterface("eth0").
|
|
WithStatic().
|
|
WithAddressVersion(AddressVersion6).
|
|
WithAddress("2001:db8::2").
|
|
WithNetmask(48, 128).
|
|
WithGateway("2001:db8::1")
|
|
},
|
|
wantString: `auto eth0
|
|
iface eth0 inet6 static
|
|
address 2001:db8::2
|
|
netmask ffff:ffff:ffff::
|
|
gateway 2001:db8::1
|
|
`,
|
|
wantErrors: nil,
|
|
},
|
|
{
|
|
name: "static ipv6 #3",
|
|
builder: func() *NetworkInterface {
|
|
return NewNetworkInterface("eth0").
|
|
WithStatic().
|
|
WithAddressVersion(AddressVersion6).
|
|
WithAddress("fc00:bbbb:bbbb:bb01::31:1927").
|
|
WithNetmask(128, 128).
|
|
WithGateway("fc00:bbbb:bbbb:bb01::1")
|
|
},
|
|
wantString: `auto eth0
|
|
iface eth0 inet6 static
|
|
address fc00:bbbb:bbbb:bb01::31:1927
|
|
netmask ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
|
|
gateway fc00:bbbb:bbbb:bb01::1
|
|
`,
|
|
wantErrors: nil,
|
|
},
|
|
{
|
|
name: "dhcp ipv4",
|
|
builder: func() *NetworkInterface {
|
|
return NewNetworkInterface("eth0").
|
|
WithDHCP().
|
|
WithAddressVersion(AddressVersion4)
|
|
},
|
|
wantString: `auto eth0
|
|
iface eth0 inet dhcp
|
|
`,
|
|
wantErrors: nil,
|
|
},
|
|
{
|
|
name: "dhcp ipv6",
|
|
builder: func() *NetworkInterface {
|
|
return NewNetworkInterface("eth0").
|
|
WithDHCP().
|
|
WithAddressVersion(AddressVersion6)
|
|
},
|
|
wantString: `auto eth0
|
|
iface eth0 inet6 dhcp
|
|
`,
|
|
wantErrors: nil,
|
|
},
|
|
{
|
|
name: "manual ipv4",
|
|
builder: func() *NetworkInterface {
|
|
return NewNetworkInterface("eth0").
|
|
WithManual().
|
|
WithAddressVersion(AddressVersion4)
|
|
},
|
|
wantString: `auto eth0
|
|
iface eth0 inet manual
|
|
`,
|
|
wantErrors: nil,
|
|
},
|
|
{
|
|
name: "manual ipv6",
|
|
builder: func() *NetworkInterface {
|
|
return NewNetworkInterface("eth0").WithManual().WithAddressVersion(AddressVersion6)
|
|
},
|
|
wantString: `auto eth0
|
|
iface eth0 inet6 manual
|
|
`,
|
|
wantErrors: nil,
|
|
},
|
|
{
|
|
name: "loopback ipv4",
|
|
builder: func() *NetworkInterface {
|
|
return NewNetworkInterface("lo").WithLoopback().WithAddressVersion(AddressVersion4)
|
|
},
|
|
wantString: `auto lo
|
|
iface lo inet loopback
|
|
`,
|
|
wantErrors: nil,
|
|
},
|
|
{
|
|
name: "loopback ipv6",
|
|
builder: func() *NetworkInterface {
|
|
return NewNetworkInterface("lo").
|
|
WithAddressConfig(AddressConfigLoopback).
|
|
WithAddressVersion(AddressVersion6)
|
|
},
|
|
wantString: `auto lo
|
|
iface lo inet6 loopback
|
|
`,
|
|
wantErrors: nil,
|
|
},
|
|
{
|
|
name: "invalid address config",
|
|
builder: func() *NetworkInterface {
|
|
return NewNetworkInterface("eth0").
|
|
WithAddress("yeeterson")
|
|
},
|
|
wantString: ``,
|
|
wantErrors: []error{fmt.Errorf(": %s", "yeeterson")},
|
|
},
|
|
{
|
|
name: "unallocated interface",
|
|
builder: func() *NetworkInterface {
|
|
return &NetworkInterface{}
|
|
},
|
|
wantString: ``,
|
|
wantErrors: []error{ErrUnallocatedInterface},
|
|
},
|
|
{
|
|
name: "invalid address version",
|
|
builder: func() *NetworkInterface {
|
|
return NewNetworkInterface("eth0").
|
|
WithAddressVersion(3)
|
|
},
|
|
wantString: ``,
|
|
wantErrors: []error{ErrInvalidAddressVersion},
|
|
},
|
|
{
|
|
name: "dirty config",
|
|
builder: func() *NetworkInterface {
|
|
ifa := NewNetworkInterface("eth0").
|
|
WithAddressVersion(3)
|
|
if ifa.Validate() == nil {
|
|
t.Errorf("invalid interface passed validation")
|
|
}
|
|
ifa = ifa.WithAddressVersion(AddressVersion4).
|
|
WithStatic().WithAddress("1.1.1.1").
|
|
WithNetmask(32, 32)
|
|
return ifa
|
|
},
|
|
wantString: `auto eth0
|
|
iface eth0 inet static
|
|
address 1.1.1.1
|
|
netmask 255.255.255.255
|
|
`,
|
|
wantErrors: nil,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
iface := tt.builder()
|
|
|
|
if iface == nil {
|
|
t.Fatal("nil interface returned")
|
|
}
|
|
|
|
validationErrs := iface.Validate()
|
|
|
|
switch {
|
|
case len(tt.wantErrors) < 1 && validationErrs != nil:
|
|
t.Errorf("Validate(): %v", validationErrs)
|
|
spew.Dump(iface)
|
|
case len(tt.wantErrors) != 0 && len(iface.errs) == 0:
|
|
t.Errorf("interface error: %v, wanted %+v", iface.errs, tt.wantErrors)
|
|
t.Logf("%s", spew.Sdump(iface))
|
|
case len(tt.wantErrors) != 0 && len(iface.errs) != 0:
|
|
need := len(tt.wantErrors)
|
|
for _, err := range iface.errs {
|
|
if need == 0 {
|
|
t.Errorf("interface has extra error: %v", err)
|
|
continue
|
|
}
|
|
|
|
for _, wantErr := range tt.wantErrors {
|
|
if errors.Is(err, wantErr) {
|
|
need--
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
xeroxWant := bufio.NewScanner(strings.NewReader(tt.wantString))
|
|
xeroxGot := bufio.NewScanner(strings.NewReader(iface.String()))
|
|
for xeroxWant.Scan() {
|
|
if !xeroxGot.Scan() {
|
|
t.Errorf("xerox: got %s, want %s", xeroxGot.Text(), xeroxWant.Text())
|
|
continue
|
|
}
|
|
if strings.TrimSpace(xeroxGot.Text()) == "" {
|
|
xeroxGot.Scan()
|
|
}
|
|
if strings.TrimSpace(xeroxGot.Text()) != strings.TrimSpace(xeroxWant.Text()) {
|
|
t.Errorf("xerox: got %s, want %s", xeroxGot.Text(), xeroxWant.Text())
|
|
}
|
|
}
|
|
|
|
if len(tt.wantErrors) > 0 {
|
|
return
|
|
}
|
|
|
|
b := make([]byte, len(iface.String()))
|
|
n, err := iface.Read(b)
|
|
if err != nil {
|
|
t.Errorf("Read(): = %v", err)
|
|
}
|
|
if n != len(iface.String()) {
|
|
t.Errorf("Read() = %v, want %v", n, len(tt.wantString))
|
|
}
|
|
xeroxWant = bufio.NewScanner(strings.NewReader(tt.wantString))
|
|
xeroxGot = bufio.NewScanner(strings.NewReader(string(b)))
|
|
for xeroxWant.Scan() {
|
|
if !xeroxGot.Scan() {
|
|
t.Errorf("xerox: got %s, want %s", xeroxGot.Text(), xeroxWant.Text())
|
|
continue
|
|
}
|
|
if strings.TrimSpace(xeroxGot.Text()) == "" {
|
|
xeroxGot.Scan()
|
|
}
|
|
if strings.TrimSpace(xeroxGot.Text()) != strings.TrimSpace(xeroxWant.Text()) {
|
|
t.Errorf("xerox: got %s, want %s", xeroxGot.Text(), xeroxWant.Text())
|
|
}
|
|
}
|
|
|
|
newIface := &NetworkInterface{}
|
|
if n, err = newIface.Write(b); err != nil {
|
|
t.Errorf("Write(): = %v", err)
|
|
}
|
|
if n != len(b) {
|
|
t.Errorf("Write() = %v, want %v", n, len(tt.wantString))
|
|
}
|
|
newipstr, err := newIface.Address.MarshalText()
|
|
if err != nil {
|
|
t.Errorf("Write() = %v", err)
|
|
}
|
|
ipstr, err := iface.Address.MarshalText()
|
|
if err != nil {
|
|
t.Errorf("Write() = %v", err)
|
|
}
|
|
if !strings.EqualFold(string(newipstr), string(ipstr)) {
|
|
t.Errorf("Write() = %v, want %v", newipstr, ipstr)
|
|
}
|
|
if newIface.Version != iface.Version {
|
|
t.Errorf("Write() = %v, want %v", newIface.Version, iface.Version)
|
|
}
|
|
if newIface.Config != iface.Config {
|
|
t.Errorf("Write() = %v, want %v", newIface.Config, iface.Config)
|
|
}
|
|
if iface.Version == AddressVersion4 && !bytes.Equal(newIface.Netmask, iface.Netmask) {
|
|
t.Errorf("Write() netmask = %v, want %v", newIface.Netmask, iface.Netmask)
|
|
}
|
|
if newIface.Gateway.String() != iface.Gateway.String() {
|
|
t.Errorf("Write() = %v, want %v", newIface.Gateway, iface.Gateway)
|
|
}
|
|
oldIfaceIsValidated := iface.Validate() == nil
|
|
err = newIface.Validate()
|
|
if oldIfaceIsValidated && err != nil {
|
|
t.Errorf("Write() Validate = %v", err)
|
|
}
|
|
})
|
|
}
|
|
}
|