dhcpsvc: imp tests

This commit is contained in:
Eugene Burkov 2024-07-08 19:31:43 +03:00
parent 83ec7c54ef
commit 22e37e587e
6 changed files with 155 additions and 104 deletions

View file

@ -102,13 +102,12 @@ func New(ctx context.Context, conf *Config) (srv *DHCPServer, err error) {
dbFilePath: conf.DBFilePath, dbFilePath: conf.DBFilePath,
} }
// TODO(e.burkov): !! migrate?
err = srv.dbLoad(ctx) err = srv.dbLoad(ctx)
if err != nil { if err != nil {
// Don't wrap the error since it's informative enough as is. // Don't wrap the error since it's informative enough as is.
return nil, err return nil, err
} }
// TODO(e.burkov): Migrate.
return srv, nil return srv, nil
} }

View file

@ -1,8 +1,10 @@
package dhcpsvc_test package dhcpsvc_test
import ( import (
"io/fs"
"net" "net"
"net/netip" "net/netip"
"os"
"path/filepath" "path/filepath"
"strings" "strings"
"testing" "testing"
@ -15,8 +17,6 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
// TODO(e.burkov): !! Adjust tests and check the leases db.
// testLocalTLD is a common local TLD for tests. // testLocalTLD is a common local TLD for tests.
const testLocalTLD = "local" const testLocalTLD = "local"
@ -26,6 +26,23 @@ const testTimeout time.Duration = 10 * time.Second
// discardLog is a logger to discard test output. // discardLog is a logger to discard test output.
var discardLog = slogutil.NewDiscardLogger() var discardLog = slogutil.NewDiscardLogger()
// copyDB copies the leases database file located in the testdata directory,
// under tb.Name() directory, to a temporary directory and returns the path to
// the copied file.
func copyDB(tb testing.TB) (dst string) {
testdata := os.DirFS("testdata")
data, err := fs.ReadFile(testdata, filepath.Join(tb.Name(), "leases.json"))
require.NoError(tb, err)
dst = filepath.Join(tb.TempDir(), "leases.json")
err = os.WriteFile(dst, data, 0o644)
require.NoError(tb, err)
return dst
}
// testInterfaceConf is a common set of interface configurations for tests. // testInterfaceConf is a common set of interface configurations for tests.
var testInterfaceConf = map[string]*dhcpsvc.InterfaceConfig{ var testInterfaceConf = map[string]*dhcpsvc.InterfaceConfig{
"eth0": { "eth0": {
@ -189,12 +206,13 @@ func TestNew(t *testing.T) {
func TestDHCPServer_AddLease(t *testing.T) { func TestDHCPServer_AddLease(t *testing.T) {
ctx := testutil.ContextWithTimeout(t, testTimeout) ctx := testutil.ContextWithTimeout(t, testTimeout)
leasesPath := filepath.Join(t.TempDir(), "leases.json")
srv, err := dhcpsvc.New(ctx, &dhcpsvc.Config{ srv, err := dhcpsvc.New(ctx, &dhcpsvc.Config{
Enabled: true, Enabled: true,
Logger: discardLog, Logger: discardLog,
LocalDomainName: testLocalTLD, LocalDomainName: testLocalTLD,
Interfaces: testInterfaceConf, Interfaces: testInterfaceConf,
DBFilePath: filepath.Join(t.TempDir(), "leases.json"), DBFilePath: leasesPath,
}) })
require.NoError(t, err) require.NoError(t, err)
@ -290,17 +308,21 @@ func TestDHCPServer_AddLease(t *testing.T) {
testutil.AssertErrorMsg(t, tc.wantErrMsg, srv.AddLease(ctx, tc.lease)) testutil.AssertErrorMsg(t, tc.wantErrMsg, srv.AddLease(ctx, tc.lease))
}) })
} }
assert.NotEmpty(t, srv.Leases())
assert.FileExists(t, leasesPath)
} }
func TestDHCPServer_index(t *testing.T) { func TestDHCPServer_index(t *testing.T) {
ctx := testutil.ContextWithTimeout(t, testTimeout) ctx := testutil.ContextWithTimeout(t, testTimeout)
leasesPath := copyDB(t)
srv, err := dhcpsvc.New(ctx, &dhcpsvc.Config{ srv, err := dhcpsvc.New(ctx, &dhcpsvc.Config{
Enabled: true, Enabled: true,
Logger: discardLog, Logger: discardLog,
LocalDomainName: testLocalTLD, LocalDomainName: testLocalTLD,
Interfaces: testInterfaceConf, Interfaces: testInterfaceConf,
DBFilePath: filepath.Join(t.TempDir(), "leases.json"), DBFilePath: leasesPath,
}) })
require.NoError(t, err) require.NoError(t, err)
@ -321,31 +343,6 @@ func TestDHCPServer_index(t *testing.T) {
mac2 := mustParseMAC(t, "06:05:04:03:02:01") mac2 := mustParseMAC(t, "06:05:04:03:02:01")
mac3 := mustParseMAC(t, "02:03:04:05:06:07") mac3 := mustParseMAC(t, "02:03:04:05:06:07")
leases := []*dhcpsvc.Lease{{
Hostname: host1,
IP: ip1,
HWAddr: mac1,
IsStatic: true,
}, {
Hostname: host2,
IP: ip2,
HWAddr: mac2,
IsStatic: true,
}, {
Hostname: host3,
IP: ip3,
HWAddr: mac3,
IsStatic: true,
}, {
Hostname: host4,
IP: ip4,
HWAddr: mac1,
IsStatic: true,
}}
for _, l := range leases {
require.NoError(t, srv.AddLease(ctx, l))
}
t.Run("ip_idx", func(t *testing.T) { t.Run("ip_idx", func(t *testing.T) {
assert.Equal(t, ip1, srv.IPByHost(host1)) assert.Equal(t, ip1, srv.IPByHost(host1))
assert.Equal(t, ip2, srv.IPByHost(host2)) assert.Equal(t, ip2, srv.IPByHost(host2))
@ -374,12 +371,13 @@ func TestDHCPServer_index(t *testing.T) {
func TestDHCPServer_UpdateStaticLease(t *testing.T) { func TestDHCPServer_UpdateStaticLease(t *testing.T) {
ctx := testutil.ContextWithTimeout(t, testTimeout) ctx := testutil.ContextWithTimeout(t, testTimeout)
leasesPath := copyDB(t)
srv, err := dhcpsvc.New(ctx, &dhcpsvc.Config{ srv, err := dhcpsvc.New(ctx, &dhcpsvc.Config{
Enabled: true, Enabled: true,
Logger: discardLog, Logger: discardLog,
LocalDomainName: testLocalTLD, LocalDomainName: testLocalTLD,
Interfaces: testInterfaceConf, Interfaces: testInterfaceConf,
DBFilePath: filepath.Join(t.TempDir(), "leases.json"), DBFilePath: leasesPath,
}) })
require.NoError(t, err) require.NoError(t, err)
@ -395,33 +393,11 @@ func TestDHCPServer_UpdateStaticLease(t *testing.T) {
ip1 := netip.MustParseAddr("192.168.0.2") ip1 := netip.MustParseAddr("192.168.0.2")
ip2 := netip.MustParseAddr("192.168.0.3") ip2 := netip.MustParseAddr("192.168.0.3")
ip3 := netip.MustParseAddr("192.168.0.4") ip3 := netip.MustParseAddr("192.168.0.4")
ip4 := netip.MustParseAddr("2001:db8::2") ip4 := netip.MustParseAddr("2001:db8::3")
ip5 := netip.MustParseAddr("2001:db8::3")
mac1 := mustParseMAC(t, "01:02:03:04:05:06") mac1 := mustParseMAC(t, "01:02:03:04:05:06")
mac2 := mustParseMAC(t, "01:02:03:04:05:07") mac2 := mustParseMAC(t, "06:05:04:03:02:01")
mac3 := mustParseMAC(t, "06:05:04:03:02:01") mac3 := mustParseMAC(t, "06:05:04:03:02:02")
mac4 := mustParseMAC(t, "06:05:04:03:02:02")
leases := []*dhcpsvc.Lease{{
Hostname: host1,
IP: ip1,
HWAddr: mac1,
IsStatic: true,
}, {
Hostname: host2,
IP: ip2,
HWAddr: mac2,
IsStatic: true,
}, {
Hostname: host4,
IP: ip4,
HWAddr: mac4,
IsStatic: true,
}}
for _, l := range leases {
require.NoError(t, srv.AddLease(ctx, l))
}
testCases := []struct { testCases := []struct {
name string name string
@ -440,9 +416,9 @@ func TestDHCPServer_UpdateStaticLease(t *testing.T) {
lease: &dhcpsvc.Lease{ lease: &dhcpsvc.Lease{
Hostname: host3, Hostname: host3,
IP: ip3, IP: ip3,
HWAddr: mac3, HWAddr: mac2,
}, },
wantErrMsg: "updating static lease: no lease for mac " + mac3.String(), wantErrMsg: "updating static lease: no lease for mac " + mac2.String(),
}, { }, {
name: "duplicate_ip", name: "duplicate_ip",
lease: &dhcpsvc.Lease{ lease: &dhcpsvc.Lease{
@ -482,8 +458,8 @@ func TestDHCPServer_UpdateStaticLease(t *testing.T) {
name: "valid_v6", name: "valid_v6",
lease: &dhcpsvc.Lease{ lease: &dhcpsvc.Lease{
Hostname: host6, Hostname: host6,
IP: ip5, IP: ip4,
HWAddr: mac4, HWAddr: mac3,
}, },
wantErrMsg: "", wantErrMsg: "",
}} }}
@ -493,17 +469,20 @@ func TestDHCPServer_UpdateStaticLease(t *testing.T) {
testutil.AssertErrorMsg(t, tc.wantErrMsg, srv.UpdateStaticLease(ctx, tc.lease)) testutil.AssertErrorMsg(t, tc.wantErrMsg, srv.UpdateStaticLease(ctx, tc.lease))
}) })
} }
assert.FileExists(t, leasesPath)
} }
func TestDHCPServer_RemoveLease(t *testing.T) { func TestDHCPServer_RemoveLease(t *testing.T) {
ctx := testutil.ContextWithTimeout(t, testTimeout) ctx := testutil.ContextWithTimeout(t, testTimeout)
leasesPath := copyDB(t)
srv, err := dhcpsvc.New(ctx, &dhcpsvc.Config{ srv, err := dhcpsvc.New(ctx, &dhcpsvc.Config{
Enabled: true, Enabled: true,
Logger: discardLog, Logger: discardLog,
LocalDomainName: testLocalTLD, LocalDomainName: testLocalTLD,
Interfaces: testInterfaceConf, Interfaces: testInterfaceConf,
DBFilePath: filepath.Join(t.TempDir(), "leases.json"), DBFilePath: leasesPath,
}) })
require.NoError(t, err) require.NoError(t, err)
@ -521,21 +500,6 @@ func TestDHCPServer_RemoveLease(t *testing.T) {
mac2 := mustParseMAC(t, "02:03:04:05:06:07") mac2 := mustParseMAC(t, "02:03:04:05:06:07")
mac3 := mustParseMAC(t, "06:05:04:03:02:01") mac3 := mustParseMAC(t, "06:05:04:03:02:01")
leases := []*dhcpsvc.Lease{{
Hostname: host1,
IP: ip1,
HWAddr: mac1,
IsStatic: true,
}, {
Hostname: host3,
IP: ip3,
HWAddr: mac3,
IsStatic: true,
}}
for _, l := range leases {
require.NoError(t, srv.AddLease(ctx, l))
}
testCases := []struct { testCases := []struct {
name string name string
lease *dhcpsvc.Lease lease *dhcpsvc.Lease
@ -588,11 +552,12 @@ func TestDHCPServer_RemoveLease(t *testing.T) {
}) })
} }
assert.FileExists(t, leasesPath)
assert.Empty(t, srv.Leases()) assert.Empty(t, srv.Leases())
} }
func TestDHCPServer_Reset(t *testing.T) { func TestDHCPServer_Reset(t *testing.T) {
leasesPath := filepath.Join(t.TempDir(), "leases.json") leasesPath := copyDB(t)
conf := &dhcpsvc.Config{ conf := &dhcpsvc.Config{
Enabled: true, Enabled: true,
Logger: discardLog, Logger: discardLog,
@ -605,33 +570,9 @@ func TestDHCPServer_Reset(t *testing.T) {
srv, err := dhcpsvc.New(ctx, conf) srv, err := dhcpsvc.New(ctx, conf)
require.NoError(t, err) require.NoError(t, err)
leases := []*dhcpsvc.Lease{{ const leasesNum = 4
Hostname: "host1",
IP: netip.MustParseAddr("192.168.0.2"),
HWAddr: mustParseMAC(t, "01:02:03:04:05:06"),
IsStatic: true,
}, {
Hostname: "host2",
IP: netip.MustParseAddr("192.168.0.3"),
HWAddr: mustParseMAC(t, "06:05:04:03:02:01"),
IsStatic: true,
}, {
Hostname: "host3",
IP: netip.MustParseAddr("2001:db8::2"),
HWAddr: mustParseMAC(t, "02:03:04:05:06:07"),
IsStatic: true,
}, {
Hostname: "host4",
IP: netip.MustParseAddr("2001:db8::3"),
HWAddr: mustParseMAC(t, "06:05:04:03:02:02"),
IsStatic: true,
}}
for _, l := range leases { require.Len(t, srv.Leases(), leasesNum)
require.NoError(t, srv.AddLease(ctx, l))
}
require.Len(t, srv.Leases(), len(leases))
require.NoError(t, srv.Reset(ctx)) require.NoError(t, srv.Reset(ctx))

View file

@ -0,0 +1,19 @@
{
"leases": [
{
"expires": "",
"ip": "192.168.0.2",
"hostname": "host1",
"mac": "01:02:03:04:05:06",
"static": true
},
{
"expires": "",
"ip": "2001:db8::2",
"hostname": "host3",
"mac": "06:05:04:03:02:01",
"static": true
}
],
"version": 1
}

View file

@ -0,0 +1,33 @@
{
"leases": [
{
"expires": "",
"ip": "192.168.0.2",
"hostname": "host1",
"mac": "01:02:03:04:05:06",
"static": true
},
{
"expires": "",
"ip": "192.168.0.3",
"hostname": "host2",
"mac": "06:05:04:03:02:01",
"static": true
},
{
"expires": "",
"ip": "2001:db8::2",
"hostname": "host3",
"mac": "02:03:04:05:06:07",
"static": true
},
{
"expires": "",
"ip": "2001:db8::3",
"hostname": "host4",
"mac": "06:05:04:03:02:02",
"static": true
}
],
"version": 1
}

View file

@ -0,0 +1,26 @@
{
"leases": [
{
"expires": "",
"ip": "192.168.0.2",
"hostname": "host1",
"mac": "01:02:03:04:05:06",
"static": true
},
{
"expires": "",
"ip": "192.168.0.3",
"hostname": "host2",
"mac": "01:02:03:04:05:07",
"static": true
},
{
"expires": "",
"ip": "2001:db8::2",
"hostname": "host4",
"mac": "06:05:04:03:02:02",
"static": true
}
],
"version": 1
}

View file

@ -0,0 +1,33 @@
{
"leases": [
{
"expires": "",
"ip": "192.168.0.2",
"hostname": "host1",
"mac": "01:02:03:04:05:06",
"static": true
},
{
"expires": "",
"ip": "192.168.0.3",
"hostname": "host2",
"mac": "06:05:04:03:02:01",
"static": true
},
{
"expires": "",
"ip": "172.16.0.3",
"hostname": "host3",
"mac": "02:03:04:05:06:07",
"static": true
},
{
"expires": "",
"ip": "172.16.0.4",
"hostname": "host4",
"mac": "01:02:03:04:05:06",
"static": true
}
],
"version": 1
}