From fbe3c6657099db66e15d46eb947a4a00f65ee7ab Mon Sep 17 00:00:00 2001 From: Filipe Utzig Date: Thu, 10 Oct 2024 19:26:57 -0300 Subject: [PATCH] Unit tests for the StaticDhcpHost model (#8) While writing the unit tests was verified the need for better error handling during host conversion to the config format. The code was improved to not produce inconsistent configurations. Signed-off-by: Filipe Utzig --- pkg/host/repository.go | 6 +- pkg/host/repository_test.go | 92 +++++++----- pkg/host/service_test.go | 2 +- pkg/model/static_dhcp_host.go | 38 ++++- pkg/model/static_dhcp_host_test.go | 225 +++++++++++++++++++++++++++++ 5 files changed, 316 insertions(+), 47 deletions(-) create mode 100644 pkg/model/static_dhcp_host_test.go diff --git a/pkg/host/repository.go b/pkg/host/repository.go index 395437b..1c2cc54 100644 --- a/pkg/host/repository.go +++ b/pkg/host/repository.go @@ -115,7 +115,11 @@ func (r *repository) parse(file *os.File) (*[]model.StaticDhcpHost, error) { func (r *repository) save(hosts *[]model.StaticDhcpHost) error { config := make([]string, 0, len(*hosts)) for _, host := range *hosts { - config = append(config, host.ToConfig()) + hostConfig, err := host.ToConfig() + if err != nil { + return err + } + config = append(config, hostConfig) } err := os.WriteFile(r.staticHostsFilePath, []byte(strings.Join(config, "\n")), os.FileMode(0644)) diff --git a/pkg/host/repository_test.go b/pkg/host/repository_test.go index e4883fb..ba40f9a 100644 --- a/pkg/host/repository_test.go +++ b/pkg/host/repository_test.go @@ -102,8 +102,8 @@ func TestHostRepositoryFindAll(t *testing.T) { os.Remove(tc.fileName) }, assert: func(t *testing.T, hosts *[]model.StaticDhcpHost, err error, tc *testcase) { - assert.Error(t, err, "FindAll() did NOT returned an expected error") - assert.ErrorIs(t, err, os.ErrNotExist, "FindAll() returned an unexpected error type") + assert.Error(t, err, "FindAll() did NOT returned an error") + assert.ErrorIs(t, err, os.ErrNotExist, "FindAll() returned an unexpected error") }, }, { @@ -111,9 +111,9 @@ func TestHostRepositoryFindAll(t *testing.T) { setupFileContent: InvalidHostsFileContent, setup: voidSetup, assert: func(t *testing.T, hosts *[]model.StaticDhcpHost, err error, tc *testcase) { - assert.Error(t, err, "FindAll() did NOT returned an expected error") + assert.Error(t, err, "FindAll() did NOT returned an error") // Just to ensure that we are not getting false negatives - assert.NotErrorIs(t, err, os.ErrNotExist, "FindAll() returned an unexpected error type") + assert.NotErrorIs(t, err, os.ErrNotExist, "FindAll() returned an unexpected error") // Verify that the file content hasn't changed assertFileContent(t, tc.setupFileContent, tc.fileName) }, @@ -180,8 +180,8 @@ func TestHostRepositoryFind(t *testing.T) { os.Remove(tc.fileName) }, assert: func(t *testing.T, host *model.StaticDhcpHost, err error, tc *testcase) { - assert.Error(t, err, "Find() did NOT returned an expected error") - assert.ErrorIs(t, err, os.ErrNotExist, "Find() returned an unexpected error type") + assert.Error(t, err, "Find() did NOT returned an error") + assert.ErrorIs(t, err, os.ErrNotExist, "Find() returned an unexpected error") }, }, { @@ -190,9 +190,9 @@ func TestHostRepositoryFind(t *testing.T) { argument: &ValidHost, setup: voidSetup, assert: func(t *testing.T, host *model.StaticDhcpHost, err error, tc *testcase) { - assert.Error(t, err, "Find() did NOT returned an expected error") + assert.Error(t, err, "Find() did NOT returned an error") // Just to ensure that we are not getting false negatives - assert.NotErrorIs(t, err, os.ErrNotExist, "Find() returned an unexpected error type") + assert.NotErrorIs(t, err, os.ErrNotExist, "Find() returned an unexpected error") // Verify that the file content hasn't changed assertFileContent(t, tc.setupFileContent, tc.fileName) }, @@ -259,8 +259,8 @@ func TestHostRepositoryFindByIP(t *testing.T) { os.Remove(tc.fileName) }, assert: func(t *testing.T, host *model.StaticDhcpHost, err error, tc *testcase) { - assert.Error(t, err, "FindByIP() did NOT returned an expected error") - assert.ErrorIs(t, err, os.ErrNotExist, "FindByIP() returned an unexpected error type") + assert.Error(t, err, "FindByIP() did NOT returned an error") + assert.ErrorIs(t, err, os.ErrNotExist, "FindByIP() returned an unexpected error") }, }, { @@ -269,9 +269,9 @@ func TestHostRepositoryFindByIP(t *testing.T) { argument: ValidHost.IPAddress, setup: voidSetup, assert: func(t *testing.T, host *model.StaticDhcpHost, err error, tc *testcase) { - assert.Error(t, err, "FindByIP() did NOT returned an expected error") + assert.Error(t, err, "FindByIP() did NOT returned an error") // Just to ensure that we are not getting false negatives - assert.NotErrorIs(t, err, os.ErrNotExist, "FindByIP() returned an unexpected error type") + assert.NotErrorIs(t, err, os.ErrNotExist, "FindByIP() returned an unexpected error") // Verify that the file content hasn't changed assertFileContent(t, tc.setupFileContent, tc.fileName) }, @@ -338,8 +338,8 @@ func TestHostRepositoryFindByMac(t *testing.T) { os.Remove(tc.fileName) }, assert: func(t *testing.T, host *model.StaticDhcpHost, err error, tc *testcase) { - assert.Error(t, err, "FindByMac() did NOT returned an expected error") - assert.ErrorIs(t, err, os.ErrNotExist, "FindByMac() returned an unexpected error type") + assert.Error(t, err, "FindByMac() did NOT returned an error") + assert.ErrorIs(t, err, os.ErrNotExist, "FindByMac() returned an unexpected error") }, }, { @@ -348,9 +348,9 @@ func TestHostRepositoryFindByMac(t *testing.T) { argument: tests.ParseMAC(ValidMACAddress), setup: voidSetup, assert: func(t *testing.T, host *model.StaticDhcpHost, err error, tc *testcase) { - assert.Error(t, err, "FindByMac() did NOT returned an expected error") + assert.Error(t, err, "FindByMac() did NOT returned an error") // Just to ensure that we are not getting false negatives - assert.NotErrorIs(t, err, os.ErrNotExist, "FindByMac() returned an unexpected error type") + assert.NotErrorIs(t, err, os.ErrNotExist, "FindByMac() returned an unexpected error") // Verify that the file content hasn't changed assertFileContent(t, tc.setupFileContent, tc.fileName) }, @@ -430,8 +430,8 @@ func TestHostRepositoryDelete(t *testing.T) { os.Remove(tc.fileName) }, assert: func(t *testing.T, host *model.StaticDhcpHost, err error, tc *testcase) { - assert.Error(t, err, "Delete() did NOT returned an expected error") - assert.ErrorIs(t, err, os.ErrNotExist, "Delete() returned an unexpected error type") + assert.Error(t, err, "Delete() did NOT returned an error") + assert.ErrorIs(t, err, os.ErrNotExist, "Delete() returned an unexpected error") }, }, { @@ -444,8 +444,8 @@ func TestHostRepositoryDelete(t *testing.T) { f.Chmod(os.FileMode(0444)) }, assert: func(t *testing.T, host *model.StaticDhcpHost, err error, tc *testcase) { - assert.Error(t, err, "Delete() did NOT returned an expected error") - assert.ErrorIs(t, err, os.ErrPermission, "Delete() returned an unexpected error type") + assert.Error(t, err, "Delete() did NOT returned an error") + assert.ErrorIs(t, err, os.ErrPermission, "Delete() returned an unexpected error") }, }, { @@ -454,9 +454,9 @@ func TestHostRepositoryDelete(t *testing.T) { argument: &ValidHost, setup: voidSetup, assert: func(t *testing.T, host *model.StaticDhcpHost, err error, tc *testcase) { - assert.Error(t, err, "Delete() did NOT returned an expected error") + assert.Error(t, err, "Delete() did NOT returned an error") // Just to ensure that we are not getting false negatives - assert.NotErrorIs(t, err, os.ErrNotExist, "Delete() returned an unexpected error type") + assert.NotErrorIs(t, err, os.ErrNotExist, "Delete() returned an unexpected error") // Verify that the file content hasn't changed assertFileContent(t, tc.setupFileContent, tc.fileName) }, @@ -536,8 +536,8 @@ func TestHostRepositoryDeleteByIP(t *testing.T) { os.Remove(tc.fileName) }, assert: func(t *testing.T, host *model.StaticDhcpHost, err error, tc *testcase) { - assert.Error(t, err, "DeleteByIP() did NOT returned an expected error") - assert.ErrorIs(t, err, os.ErrNotExist, "DeleteByIP() returned an unexpected error type") + assert.Error(t, err, "DeleteByIP() did NOT returned an error") + assert.ErrorIs(t, err, os.ErrNotExist, "DeleteByIP() returned an unexpected error") }, }, { @@ -550,8 +550,8 @@ func TestHostRepositoryDeleteByIP(t *testing.T) { f.Chmod(os.FileMode(0444)) }, assert: func(t *testing.T, host *model.StaticDhcpHost, err error, tc *testcase) { - assert.Error(t, err, "DeleteByIP() did NOT returned an expected error") - assert.ErrorIs(t, err, os.ErrPermission, "DeleteByIP() returned an unexpected error type") + assert.Error(t, err, "DeleteByIP() did NOT returned an error") + assert.ErrorIs(t, err, os.ErrPermission, "DeleteByIP() returned an unexpected error") }, }, { @@ -560,9 +560,9 @@ func TestHostRepositoryDeleteByIP(t *testing.T) { argument: net.ParseIP(ValidIPAddress), setup: voidSetup, assert: func(t *testing.T, host *model.StaticDhcpHost, err error, tc *testcase) { - assert.Error(t, err, "DeleteByIP() did NOT returned an expected error") + assert.Error(t, err, "DeleteByIP() did NOT returned an error") // Just to ensure that we are not getting false negatives - assert.NotErrorIs(t, err, os.ErrNotExist, "DeleteByIP() returned an unexpected error type") + assert.NotErrorIs(t, err, os.ErrNotExist, "DeleteByIP() returned an unexpected error") // Verify that the file content hasn't changed assertFileContent(t, tc.setupFileContent, tc.fileName) }, @@ -642,8 +642,8 @@ func TestHostRepositoryDeleteByMac(t *testing.T) { os.Remove(tc.fileName) }, assert: func(t *testing.T, host *model.StaticDhcpHost, err error, tc *testcase) { - assert.Error(t, err, "DeleteByMac() did NOT returned an expected error") - assert.ErrorIs(t, err, os.ErrNotExist, "DeleteByMac() returned an unexpected error type") + assert.Error(t, err, "DeleteByMac() did NOT returned an error") + assert.ErrorIs(t, err, os.ErrNotExist, "DeleteByMac() returned an unexpected error") }, }, { @@ -656,8 +656,8 @@ func TestHostRepositoryDeleteByMac(t *testing.T) { f.Chmod(os.FileMode(0444)) }, assert: func(t *testing.T, host *model.StaticDhcpHost, err error, tc *testcase) { - assert.Error(t, err, "DeleteByMac() did NOT returned an expected error") - assert.ErrorIs(t, err, os.ErrPermission, "DeleteByMac() returned an unexpected error type") + assert.Error(t, err, "DeleteByMac() did NOT returned an error") + assert.ErrorIs(t, err, os.ErrPermission, "DeleteByMac() returned an unexpected error") }, }, { @@ -666,9 +666,9 @@ func TestHostRepositoryDeleteByMac(t *testing.T) { argument: tests.ParseMAC(ValidMACAddress), setup: voidSetup, assert: func(t *testing.T, host *model.StaticDhcpHost, err error, tc *testcase) { - assert.Error(t, err, "DeleteByMac() did NOT returned an expected error") + assert.Error(t, err, "DeleteByMac() did NOT returned an error") // Just to ensure that we are not getting false negatives - assert.NotErrorIs(t, err, os.ErrNotExist, "DeleteByMac() returned an unexpected error type") + assert.NotErrorIs(t, err, os.ErrNotExist, "DeleteByMac() returned an unexpected error") // Verify that the file content hasn't changed assertFileContent(t, tc.setupFileContent, tc.fileName) }, @@ -730,8 +730,8 @@ func TestHostRepositorySave(t *testing.T) { os.Remove(tc.fileName) }, assert: func(t *testing.T, err error, tc *testcase) { - assert.Error(t, err, "Save() did NOT returned an expected error") - assert.ErrorIs(t, err, os.ErrNotExist, "Save() returned an unexpected error type") + assert.Error(t, err, "Save() did NOT returned an error") + assert.ErrorIs(t, err, os.ErrNotExist, "Save() returned an unexpected error") }, }, { @@ -744,8 +744,8 @@ func TestHostRepositorySave(t *testing.T) { f.Chmod(os.FileMode(0444)) }, assert: func(t *testing.T, err error, tc *testcase) { - assert.Error(t, err, "Save() did NOT returned an expected error") - assert.ErrorIs(t, err, os.ErrPermission, "Save() returned an unexpected error type") + assert.Error(t, err, "Save() did NOT returned an error") + assert.ErrorIs(t, err, os.ErrPermission, "Save() returned an unexpected error") }, }, { @@ -754,9 +754,21 @@ func TestHostRepositorySave(t *testing.T) { host: &ValidHost, setup: voidSetup, assert: func(t *testing.T, err error, tc *testcase) { - assert.Error(t, err, "Save() did NOT returned an expected error") + assert.Error(t, err, "Save() did NOT returned an error") // Just to ensure that we are not getting false negatives - assert.NotErrorIs(t, err, os.ErrNotExist, "Save() returned an unexpected error type") + assert.NotErrorIs(t, err, os.ErrNotExist, "Save() returned an unexpected error") + // Verify that the file content hasn't changed + assertFileContent(t, tc.setupFileContent, tc.fileName) + }, + }, + { + name: "InvalidHost", + setupFileContent: ValidHostFileContent, + host: &model.StaticDhcpHost{}, + setup: voidSetup, + assert: func(t *testing.T, err error, tc *testcase) { + assert.Error(t, err, "Save() did NOT returned an error") + assert.ErrorIs(t, err, model.ErrDHCPHostMissingMACAddress, "Save() returned an unexpected error") // Verify that the file content hasn't changed assertFileContent(t, tc.setupFileContent, tc.fileName) }, diff --git a/pkg/host/service_test.go b/pkg/host/service_test.go index 42612fb..47e7614 100644 --- a/pkg/host/service_test.go +++ b/pkg/host/service_test.go @@ -458,7 +458,7 @@ func TestHostServiceErrors(t *testing.T) { t.Run(test.name, func(t *testing.T) { err := &DuplicatedEntryError{Field: test.field, Value: test.value} expectedMessage := fmt.Sprintf(duplicatedEntryErrorMessage, test.field, test.value) - assert.ErrorContains(t, err, expectedMessage) + assert.EqualError(t, err, expectedMessage) }) } } diff --git a/pkg/model/static_dhcp_host.go b/pkg/model/static_dhcp_host.go index fe0e1d5..40b4f4d 100644 --- a/pkg/model/static_dhcp_host.go +++ b/pkg/model/static_dhcp_host.go @@ -14,29 +14,57 @@ type StaticDhcpHost struct { HostName string } -var ErrInvalidDHCPHost = errors.New("invalid DHCP host entry") +const errInvalidDHCPHostConfig = "invalid DHCP host config: %s" + +var ErrDHCPHostMissingMACAddress = errors.New("invalid DHCP host: missing MAC address") +var ErrDHCPHostMissingIPAddress = errors.New("invalid DHCP host: missing IP address") +var ErrDHCPHostMissingHostName = errors.New("invalid DHCP host: missing hostname") func (h *StaticDhcpHost) FromConfig(config string) error { tokens := strings.Split(config, ",") if len(tokens) != 3 { - return ErrInvalidDHCPHost + return fmt.Errorf(errInvalidDHCPHostConfig, config) } var mac string _, err := fmt.Sscanf(tokens[0], "dhcp-host=%s", &mac) if err != nil { - return err + return errors.Join(fmt.Errorf(errInvalidDHCPHostConfig, config), err) } h.MacAddress, err = net.ParseMAC(mac) h.IPAddress = net.ParseIP(tokens[1]) + if h.IPAddress == nil { + err = errors.Join(err, &net.AddrError{Err: "invalid IP address", Addr: tokens[1]}) + } + h.HostName = tokens[2] return err } -func (h *StaticDhcpHost) ToConfig() string { - return fmt.Sprintf("dhcp-host=%s,%s,%s", h.MacAddress.String(), h.IPAddress.String(), h.HostName) +func (h *StaticDhcpHost) check() error { + var err error = nil + if h.MacAddress.String() == "" { + err = errors.Join(err, ErrDHCPHostMissingMACAddress) + } + if h.IPAddress.String() == "" { + err = errors.Join(err, ErrDHCPHostMissingIPAddress) + } + if h.HostName == "" { + err = errors.Join(err, ErrDHCPHostMissingHostName) + } + return err +} + +func (h *StaticDhcpHost) ToConfig() (string, error) { + err := h.check() + if err != nil { + return "", err + } + + config := fmt.Sprintf("dhcp-host=%s,%s,%s", h.MacAddress.String(), h.IPAddress.String(), h.HostName) + return config, nil } func (h *StaticDhcpHost) Equal(other StaticDhcpHost) bool { diff --git a/pkg/model/static_dhcp_host_test.go b/pkg/model/static_dhcp_host_test.go new file mode 100644 index 0000000..02c3c3a --- /dev/null +++ b/pkg/model/static_dhcp_host_test.go @@ -0,0 +1,225 @@ +package model + +import ( + "fmt" + "net" + "testing" + + "github.com/gringolito/dnsmasq-manager/tests" + "github.com/stretchr/testify/assert" +) + +const ( + ValidHostConfig = `dhcp-host=02:04:06:aa:bb:cc,1.1.1.1,Foo` + InvalidMacAddressConfig = `dhcp-host=ab:cd:ef:gh:ij:kl,1.1.1.1,Jung` + InvalidIPAddressConfig = `dhcp-host=02:04:06:aa:bb:cc,11.1.1,Jung` + InvalidBothAddressesConfig = `dhcp-host=ab:cd:ef:gh:ij:kl,11.1.1,Jung` + InvalidConfig = `not-dhcp-config` + InvalidConfig2 = `02:04:06:aa:bb:cc,1.1.1.1,Jung` + MissingMacAddressConfig = `dhcp-host=1.1.1.1,Foo` + MissingIPAddressConfig = `dhcp-host=02:04:06:aa:bb:cc,Foo` + MissingHostNameConfig = `dhcp-host=02:04:06:aa:bb:cc,1.1.1.1` + InvalidIPAddress = `11.1.1` + InvalidMacAddress = `ab:cd:ef:gh:ij:kl` +) + +var ValidHost = StaticDhcpHost{MacAddress: tests.ParseMAC("02:04:06:aa:bb:cc"), IPAddress: net.ParseIP("1.1.1.1"), HostName: "Foo"} + +func TestStaticDhcpHostFromConfig(t *testing.T) { + testCases := []struct { + name string + config string + assert func(t *testing.T, host *StaticDhcpHost, err error) + }{ + { + name: "Success", + config: ValidHostConfig, + assert: func(t *testing.T, host *StaticDhcpHost, err error) { + assert.NoError(t, err, "StaticDhcpHost.FromConfig() returned an unexpected error") + assert.Equal(t, host, &ValidHost, "StaticDhcpHost.FromConfig() has generated an unexpected host") + }, + }, + { + name: "InvalidIPAddress", + config: InvalidIPAddressConfig, + assert: func(t *testing.T, host *StaticDhcpHost, err error) { + assert.Error(t, err, "StaticDhcpHost.FromConfig() did NOT returned error") + assert.EqualError(t, err, fmt.Sprintf("address %s: invalid IP address", InvalidIPAddress), "StaticDhcpHost.FromConfig() returned an unexpected error") + }, + }, + { + name: "InvalidMacAddress", + config: InvalidMacAddressConfig, + assert: func(t *testing.T, host *StaticDhcpHost, err error) { + assert.Error(t, err, "StaticDhcpHost.FromConfig() did NOT returned error") + assert.EqualError(t, err, fmt.Sprintf("address %s: invalid MAC address", InvalidMacAddress), "StaticDhcpHost.FromConfig() returned an unexpected error") + }, + }, + { + name: "InvalidBothAddresses", + config: InvalidBothAddressesConfig, + assert: func(t *testing.T, host *StaticDhcpHost, err error) { + assert.Error(t, err, "StaticDhcpHost.FromConfig() did NOT returned error") + assert.ErrorContains(t, err, fmt.Sprintf("address %s: invalid MAC address", InvalidMacAddress), "StaticDhcpHost.FromConfig() returned an unexpected error") + assert.ErrorContains(t, err, fmt.Sprintf("address %s: invalid IP address", InvalidIPAddress), "StaticDhcpHost.FromConfig() returned an unexpected error") + }, + }, + { + name: "NotADhcpHost", + config: InvalidConfig, + assert: func(t *testing.T, host *StaticDhcpHost, err error) { + assert.Error(t, err, "StaticDhcpHost.FromConfig() did NOT returned error") + assert.EqualError(t, err, fmt.Sprintf(errInvalidDHCPHostConfig, InvalidConfig), "StaticDhcpHost.FromConfig() returned an unexpected error") + }, + }, + { + name: "NotADhcpHost2", + config: InvalidConfig2, + assert: func(t *testing.T, host *StaticDhcpHost, err error) { + assert.Error(t, err, "StaticDhcpHost.FromConfig() did NOT returned error") + assert.ErrorContains(t, err, fmt.Sprintf(errInvalidDHCPHostConfig, InvalidConfig2), "StaticDhcpHost.FromConfig() returned an unexpected error") + }, + }, + { + name: "MissingMacAddress", + config: MissingMacAddressConfig, + assert: func(t *testing.T, host *StaticDhcpHost, err error) { + assert.Error(t, err, "StaticDhcpHost.FromConfig() did NOT returned error") + assert.EqualError(t, err, fmt.Sprintf(errInvalidDHCPHostConfig, MissingMacAddressConfig), "StaticDhcpHost.FromConfig() returned an unexpected error") + }, + }, + { + name: "MissingIPAddress", + config: MissingIPAddressConfig, + assert: func(t *testing.T, host *StaticDhcpHost, err error) { + assert.Error(t, err, "StaticDhcpHost.FromConfig() did NOT returned error") + assert.EqualError(t, err, fmt.Sprintf(errInvalidDHCPHostConfig, MissingIPAddressConfig), "StaticDhcpHost.FromConfig() returned an unexpected error") + }, + }, + { + name: "MissingHostName", + config: MissingHostNameConfig, + assert: func(t *testing.T, host *StaticDhcpHost, err error) { + assert.Error(t, err, "StaticDhcpHost.FromConfig() did NOT returned error") + assert.EqualError(t, err, fmt.Sprintf(errInvalidDHCPHostConfig, MissingHostNameConfig), "StaticDhcpHost.FromConfig() returned an unexpected error") + }, + }, + } + + for _, test := range testCases { + t.Run(test.name, func(t *testing.T) { + host := StaticDhcpHost{} + err := host.FromConfig(test.config) + test.assert(t, &host, err) + }) + } +} + +func TestStaticDhcpHostToConfig(t *testing.T) { + testCases := []struct { + name string + host StaticDhcpHost + assert func(t *testing.T, config string, err error) + }{ + { + name: "Success", + host: ValidHost, + assert: func(t *testing.T, config string, err error) { + assert.NoError(t, err, "StaticDhcpHost.ToConfig() returned an unexpected error") + assert.Equal(t, ValidHostConfig, config, "StaticDhcpHost.ToConfig() returned an unexpected config string") + }, + }, + { + name: "MissingMacAddress", + host: StaticDhcpHost{IPAddress: net.ParseIP("1.1.1.1"), HostName: "FooBar"}, + assert: func(t *testing.T, config string, err error) { + assert.Error(t, err, "StaticDhcpHost.ToConfig() did NOT returned an error") + assert.ErrorIs(t, err, ErrDHCPHostMissingMACAddress, "StaticDhcpHost.ToConfig returned an unexpected error") + }, + }, + { + name: "MissingIPAddress", + host: StaticDhcpHost{MacAddress: tests.ParseMAC("02:04:06:ab:cd:ef"), HostName: "FooBar"}, + assert: func(t *testing.T, config string, err error) { + assert.Error(t, err, "StaticDhcpHost.ToConfig() did NOT returned an error") + assert.ErrorIs(t, err, ErrDHCPHostMissingIPAddress, "StaticDhcpHost.ToConfig returned an unexpected error") + }, + }, + { + name: "MissingHostName", + host: StaticDhcpHost{MacAddress: tests.ParseMAC("02:04:06:ab:cd:ef"), IPAddress: net.ParseIP("1.1.1.1")}, + assert: func(t *testing.T, config string, err error) { + assert.Error(t, err, "StaticDhcpHost.ToConfig() did NOT returned an error") + assert.ErrorIs(t, err, ErrDHCPHostMissingHostName, "StaticDhcpHost.ToConfig returned an unexpected error") + }, + }, + { + name: "EmptyHost", + assert: func(t *testing.T, config string, err error) { + assert.Error(t, err, "StaticDhcpHost.ToConfig() did NOT returned an error") + assert.ErrorIs(t, err, ErrDHCPHostMissingMACAddress, "StaticDhcpHost.ToConfig returned an unexpected error") + assert.ErrorIs(t, err, ErrDHCPHostMissingIPAddress, "StaticDhcpHost.ToConfig returned an unexpected error") + assert.ErrorIs(t, err, ErrDHCPHostMissingHostName, "StaticDhcpHost.ToConfig returned an unexpected error") + }, + }, + } + + for _, test := range testCases { + t.Run(test.name, func(t *testing.T) { + config, err := test.host.ToConfig() + test.assert(t, config, err) + }) + } +} + +func TestStaticDhcpHostEqual(t *testing.T) { + testCases := []struct { + name string + a StaticDhcpHost + b StaticDhcpHost + result bool + }{ + { + name: "EmptyHosts", + a: StaticDhcpHost{}, + b: StaticDhcpHost{}, + result: true, + }, + { + name: "SameHosts", + a: ValidHost, + b: ValidHost, + result: true, + }, + { + name: "DifferentIpAddresses", + a: StaticDhcpHost{MacAddress: tests.ParseMAC("02:04:06:aa:bb:cc"), IPAddress: net.ParseIP("1.1.1.1"), HostName: "Foo"}, + b: StaticDhcpHost{MacAddress: tests.ParseMAC("02:04:06:aa:bb:cc"), IPAddress: net.ParseIP("1.1.1.2"), HostName: "Foo"}, + result: false, + }, + { + name: "DifferentMacAddresses", + a: StaticDhcpHost{MacAddress: tests.ParseMAC("02:04:06:aa:bb:cc"), IPAddress: net.ParseIP("1.1.1.1"), HostName: "Foo"}, + b: StaticDhcpHost{MacAddress: tests.ParseMAC("12:04:06:aa:bb:cc"), IPAddress: net.ParseIP("1.1.1.1"), HostName: "Foo"}, + result: false, + }, + { + name: "DifferentHostnames", + a: StaticDhcpHost{MacAddress: tests.ParseMAC("02:04:06:aa:bb:cc"), IPAddress: net.ParseIP("1.1.1.1"), HostName: "Foo"}, + b: StaticDhcpHost{MacAddress: tests.ParseMAC("02:04:06:aa:bb:cc"), IPAddress: net.ParseIP("1.1.1.1"), HostName: "Bar"}, + result: false, + }, + { + name: "AllDifferent", + a: StaticDhcpHost{MacAddress: tests.ParseMAC("02:04:06:aa:bb:cc"), IPAddress: net.ParseIP("1.1.1.1"), HostName: "Foo"}, + b: StaticDhcpHost{MacAddress: tests.ParseMAC("12:04:06:aa:bb:cc"), IPAddress: net.ParseIP("1.1.1.2"), HostName: "Bar"}, + result: false, + }, + } + + for _, test := range testCases { + t.Run(test.name, func(t *testing.T) { + assert.Equal(t, test.result, test.a.Equal(test.b)) + }) + } +}