Add tests for network.Loader
This commit is contained in:
parent
ab8dac0789
commit
53a1dc0cc2
63
go/daemon/network/constructors.go
Normal file
63
go/daemon/network/constructors.go
Normal file
@ -0,0 +1,63 @@
|
||||
//go:generate mockery --name constructors --inpackage --filename constructors_mock.go
|
||||
|
||||
package network
|
||||
|
||||
import (
|
||||
"context"
|
||||
"isle/bootstrap"
|
||||
"isle/daemon/children"
|
||||
"isle/nebula"
|
||||
"isle/toolkit"
|
||||
|
||||
"dev.mediocregopher.com/mediocre-go-lib.git/mlog"
|
||||
)
|
||||
|
||||
// constructors wraps the various Network constructor functions in an interface,
|
||||
// so that they can be mocked.
|
||||
//
|
||||
// This is needed primarily for testing the Loader. We can't test the Loader
|
||||
// during Network integration tests because the Loader doesn't allow multiple
|
||||
// Networks with the same ID to be loaded, but we need to do so in integration
|
||||
// tests. Working around that requirement in the integration tests would add
|
||||
// extra complexity there, and it's better to do unit testing anyway.
|
||||
type constructors interface {
|
||||
load(
|
||||
ctx context.Context,
|
||||
logger *mlog.Logger,
|
||||
envBinDirPath string,
|
||||
nebulaDeviceNamer *children.NebulaDeviceNamer,
|
||||
stateDir toolkit.Dir,
|
||||
runtimeDir toolkit.Dir,
|
||||
opts *Opts,
|
||||
) (
|
||||
Network, error,
|
||||
)
|
||||
|
||||
join(
|
||||
ctx context.Context,
|
||||
logger *mlog.Logger,
|
||||
envBinDirPath string,
|
||||
nebulaDeviceNamer *children.NebulaDeviceNamer,
|
||||
joiningBootstrap JoiningBootstrap,
|
||||
stateDir toolkit.Dir,
|
||||
runtimeDir toolkit.Dir,
|
||||
opts *Opts,
|
||||
) (
|
||||
Network, error,
|
||||
)
|
||||
|
||||
create(
|
||||
ctx context.Context,
|
||||
logger *mlog.Logger,
|
||||
envBinDirPath string,
|
||||
nebulaDeviceNamer *children.NebulaDeviceNamer,
|
||||
stateDir toolkit.Dir,
|
||||
runtimeDir toolkit.Dir,
|
||||
creationParams bootstrap.CreationParams,
|
||||
ipNet nebula.IPNet,
|
||||
hostName nebula.HostName,
|
||||
opts *Opts,
|
||||
) (
|
||||
Network, error,
|
||||
)
|
||||
}
|
127
go/daemon/network/constructors_mock.go
Normal file
127
go/daemon/network/constructors_mock.go
Normal file
@ -0,0 +1,127 @@
|
||||
// Code generated by mockery v2.43.1. DO NOT EDIT.
|
||||
|
||||
package network
|
||||
|
||||
import (
|
||||
bootstrap "isle/bootstrap"
|
||||
children "isle/daemon/children"
|
||||
|
||||
context "context"
|
||||
|
||||
mlog "dev.mediocregopher.com/mediocre-go-lib.git/mlog"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
nebula "isle/nebula"
|
||||
|
||||
toolkit "isle/toolkit"
|
||||
)
|
||||
|
||||
// mockConstructors is an autogenerated mock type for the constructors type
|
||||
type mockConstructors struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// create provides a mock function with given fields: ctx, logger, envBinDirPath, nebulaDeviceNamer, stateDir, runtimeDir, creationParams, ipNet, hostName, opts
|
||||
func (_m *mockConstructors) create(ctx context.Context, logger *mlog.Logger, envBinDirPath string, nebulaDeviceNamer *children.NebulaDeviceNamer, stateDir toolkit.Dir, runtimeDir toolkit.Dir, creationParams bootstrap.CreationParams, ipNet nebula.IPNet, hostName nebula.HostName, opts *Opts) (Network, error) {
|
||||
ret := _m.Called(ctx, logger, envBinDirPath, nebulaDeviceNamer, stateDir, runtimeDir, creationParams, ipNet, hostName, opts)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for create")
|
||||
}
|
||||
|
||||
var r0 Network
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *mlog.Logger, string, *children.NebulaDeviceNamer, toolkit.Dir, toolkit.Dir, bootstrap.CreationParams, nebula.IPNet, nebula.HostName, *Opts) (Network, error)); ok {
|
||||
return rf(ctx, logger, envBinDirPath, nebulaDeviceNamer, stateDir, runtimeDir, creationParams, ipNet, hostName, opts)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *mlog.Logger, string, *children.NebulaDeviceNamer, toolkit.Dir, toolkit.Dir, bootstrap.CreationParams, nebula.IPNet, nebula.HostName, *Opts) Network); ok {
|
||||
r0 = rf(ctx, logger, envBinDirPath, nebulaDeviceNamer, stateDir, runtimeDir, creationParams, ipNet, hostName, opts)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(Network)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *mlog.Logger, string, *children.NebulaDeviceNamer, toolkit.Dir, toolkit.Dir, bootstrap.CreationParams, nebula.IPNet, nebula.HostName, *Opts) error); ok {
|
||||
r1 = rf(ctx, logger, envBinDirPath, nebulaDeviceNamer, stateDir, runtimeDir, creationParams, ipNet, hostName, opts)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// join provides a mock function with given fields: ctx, logger, envBinDirPath, nebulaDeviceNamer, joiningBootstrap, stateDir, runtimeDir, opts
|
||||
func (_m *mockConstructors) join(ctx context.Context, logger *mlog.Logger, envBinDirPath string, nebulaDeviceNamer *children.NebulaDeviceNamer, joiningBootstrap JoiningBootstrap, stateDir toolkit.Dir, runtimeDir toolkit.Dir, opts *Opts) (Network, error) {
|
||||
ret := _m.Called(ctx, logger, envBinDirPath, nebulaDeviceNamer, joiningBootstrap, stateDir, runtimeDir, opts)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for join")
|
||||
}
|
||||
|
||||
var r0 Network
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *mlog.Logger, string, *children.NebulaDeviceNamer, JoiningBootstrap, toolkit.Dir, toolkit.Dir, *Opts) (Network, error)); ok {
|
||||
return rf(ctx, logger, envBinDirPath, nebulaDeviceNamer, joiningBootstrap, stateDir, runtimeDir, opts)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *mlog.Logger, string, *children.NebulaDeviceNamer, JoiningBootstrap, toolkit.Dir, toolkit.Dir, *Opts) Network); ok {
|
||||
r0 = rf(ctx, logger, envBinDirPath, nebulaDeviceNamer, joiningBootstrap, stateDir, runtimeDir, opts)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(Network)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *mlog.Logger, string, *children.NebulaDeviceNamer, JoiningBootstrap, toolkit.Dir, toolkit.Dir, *Opts) error); ok {
|
||||
r1 = rf(ctx, logger, envBinDirPath, nebulaDeviceNamer, joiningBootstrap, stateDir, runtimeDir, opts)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// load provides a mock function with given fields: ctx, logger, envBinDirPath, nebulaDeviceNamer, stateDir, runtimeDir, opts
|
||||
func (_m *mockConstructors) load(ctx context.Context, logger *mlog.Logger, envBinDirPath string, nebulaDeviceNamer *children.NebulaDeviceNamer, stateDir toolkit.Dir, runtimeDir toolkit.Dir, opts *Opts) (Network, error) {
|
||||
ret := _m.Called(ctx, logger, envBinDirPath, nebulaDeviceNamer, stateDir, runtimeDir, opts)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for load")
|
||||
}
|
||||
|
||||
var r0 Network
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *mlog.Logger, string, *children.NebulaDeviceNamer, toolkit.Dir, toolkit.Dir, *Opts) (Network, error)); ok {
|
||||
return rf(ctx, logger, envBinDirPath, nebulaDeviceNamer, stateDir, runtimeDir, opts)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *mlog.Logger, string, *children.NebulaDeviceNamer, toolkit.Dir, toolkit.Dir, *Opts) Network); ok {
|
||||
r0 = rf(ctx, logger, envBinDirPath, nebulaDeviceNamer, stateDir, runtimeDir, opts)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(Network)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *mlog.Logger, string, *children.NebulaDeviceNamer, toolkit.Dir, toolkit.Dir, *Opts) error); ok {
|
||||
r1 = rf(ctx, logger, envBinDirPath, nebulaDeviceNamer, stateDir, runtimeDir, opts)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// newMockConstructors creates a new instance of mockConstructors. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
// The first argument is typically a *testing.T value.
|
||||
func newMockConstructors(t interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}) *mockConstructors {
|
||||
mock := &mockConstructors{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
@ -139,6 +139,8 @@ type Loader interface {
|
||||
type LoaderOpts struct {
|
||||
// Defaults to that returned by daecommon.GetEnvVars.
|
||||
EnvVars daecommon.EnvVars
|
||||
|
||||
constructors constructors // defaults to newConstructors()
|
||||
}
|
||||
|
||||
func (o *LoaderOpts) withDefaults() *LoaderOpts {
|
||||
@ -150,10 +152,15 @@ func (o *LoaderOpts) withDefaults() *LoaderOpts {
|
||||
o.EnvVars = daecommon.GetEnvVars()
|
||||
}
|
||||
|
||||
if o.constructors == nil {
|
||||
o.constructors = newConstructors()
|
||||
}
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
type loader struct {
|
||||
opts *LoaderOpts
|
||||
envBinDirPath string
|
||||
networksStateDir toolkit.Dir
|
||||
networksRuntimeDir toolkit.Dir
|
||||
@ -196,6 +203,7 @@ func NewLoader(
|
||||
}
|
||||
|
||||
return &loader{
|
||||
opts,
|
||||
envBinDirPath,
|
||||
networksStateDir,
|
||||
networksRuntimeDir,
|
||||
@ -247,6 +255,21 @@ func (l *loader) StoredConfig(
|
||||
return loadConfig(networkStateDir)
|
||||
}
|
||||
|
||||
func (l *loader) isJoined(ctx context.Context, networkID string) (bool, error) {
|
||||
allJoinedCreationParams, err := l.Loadable(ctx)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("getting already joined networks: %w", err)
|
||||
}
|
||||
|
||||
for _, joinedCreationParams := range allJoinedCreationParams {
|
||||
if joinedCreationParams.ID == networkID {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (l *loader) Load(
|
||||
ctx context.Context,
|
||||
logger *mlog.Logger,
|
||||
@ -257,6 +280,12 @@ func (l *loader) Load(
|
||||
) {
|
||||
networkID := creationParams.ID
|
||||
|
||||
if isJoined, err := l.isJoined(ctx, networkID); err != nil {
|
||||
return nil, fmt.Errorf("checking if network is already joined: %w", err)
|
||||
} else if !isJoined {
|
||||
return nil, errors.New("network is not yet joined")
|
||||
}
|
||||
|
||||
networkStateDir, networkRuntimeDir, err := networkDirs(
|
||||
l.networksStateDir, l.networksRuntimeDir, networkID, true,
|
||||
)
|
||||
@ -266,7 +295,7 @@ func (l *loader) Load(
|
||||
)
|
||||
}
|
||||
|
||||
return load(
|
||||
return l.opts.constructors.load(
|
||||
ctx,
|
||||
logger,
|
||||
l.envBinDirPath,
|
||||
@ -290,22 +319,6 @@ func (l *loader) Join(
|
||||
networkID = creationParams.ID
|
||||
)
|
||||
|
||||
// Start by checking that the new network isn't already joined. This
|
||||
// shouldn't _technically_ be necessary, as the caller of Join should
|
||||
// already be handling this, but it's worth doing to make sure we don't
|
||||
// accidentally delete the state directory of an already joined network.
|
||||
|
||||
allJoinedCreationParams, err := l.Loadable(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("getting already joined networks: %w", err)
|
||||
}
|
||||
|
||||
for _, joinedCreationParams := range allJoinedCreationParams {
|
||||
if joinedCreationParams.ID == networkID {
|
||||
return nil, fmt.Errorf("network %q already joined", networkID)
|
||||
}
|
||||
}
|
||||
|
||||
networkStateDir, networkRuntimeDir, err := networkDirs(
|
||||
l.networksStateDir, l.networksRuntimeDir, networkID, false,
|
||||
)
|
||||
@ -315,7 +328,7 @@ func (l *loader) Join(
|
||||
)
|
||||
}
|
||||
|
||||
n, err := join(
|
||||
n, err := l.opts.constructors.join(
|
||||
ctx,
|
||||
logger,
|
||||
l.envBinDirPath,
|
||||
@ -356,7 +369,7 @@ func (l *loader) Create(
|
||||
)
|
||||
}
|
||||
|
||||
n, err := create(
|
||||
n, err := l.opts.constructors.create(
|
||||
ctx,
|
||||
logger,
|
||||
l.envBinDirPath,
|
||||
|
389
go/daemon/network/loader_test.go
Normal file
389
go/daemon/network/loader_test.go
Normal file
@ -0,0 +1,389 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io/fs"
|
||||
"isle/bootstrap"
|
||||
"isle/daemon/children"
|
||||
"isle/daemon/daecommon"
|
||||
"isle/nebula"
|
||||
"isle/toolkit"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"dev.mediocregopher.com/mediocre-go-lib.git/mlog"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type loaderHarness struct {
|
||||
ctx context.Context
|
||||
logger *mlog.Logger
|
||||
envBinDirPath string
|
||||
stateDirPath string
|
||||
runtimeDirPath string
|
||||
constructors *mockConstructors
|
||||
|
||||
loader Loader
|
||||
}
|
||||
|
||||
func newLoaderHarness(t *testing.T) *loaderHarness {
|
||||
t.Parallel()
|
||||
|
||||
var (
|
||||
ctx = context.Background()
|
||||
logger = toolkit.NewTestLogger(t)
|
||||
rootDir = toolkit.TempDir(t)
|
||||
envBinDir, _ = rootDir.MkChildDir("bin", false)
|
||||
stateDir, _ = rootDir.MkChildDir("state", false)
|
||||
runtimeDir, _ = rootDir.MkChildDir("runtime", false)
|
||||
constructors = newMockConstructors(t)
|
||||
)
|
||||
|
||||
loader, err := NewLoader(
|
||||
ctx, logger, envBinDir.Path, &LoaderOpts{
|
||||
EnvVars: daecommon.EnvVars{
|
||||
StateDir: stateDir,
|
||||
RuntimeDir: runtimeDir,
|
||||
},
|
||||
constructors: constructors,
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
return &loaderHarness{
|
||||
ctx,
|
||||
logger,
|
||||
envBinDir.Path,
|
||||
stateDir.Path,
|
||||
runtimeDir.Path,
|
||||
constructors,
|
||||
loader,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *loaderHarness) networkStateDirPath(networkID string) string {
|
||||
return filepath.Join(h.stateDirPath, "networks", networkID)
|
||||
}
|
||||
|
||||
func (h *loaderHarness) networkRuntimeDirPath(networkID string) string {
|
||||
return filepath.Join(h.runtimeDirPath, "networks", networkID)
|
||||
}
|
||||
|
||||
func (h *loaderHarness) join(
|
||||
t *testing.T, creationParams bootstrap.CreationParams,
|
||||
) *MockNetwork {
|
||||
var (
|
||||
joiningBootstrap = JoiningBootstrap{
|
||||
Bootstrap: bootstrap.Bootstrap{
|
||||
NetworkCreationParams: creationParams,
|
||||
},
|
||||
}
|
||||
networkStateDirPath = h.networkStateDirPath(creationParams.ID)
|
||||
networkRuntimeDirPath = h.networkRuntimeDirPath(creationParams.ID)
|
||||
network = NewMockNetwork(t)
|
||||
)
|
||||
|
||||
h.constructors.
|
||||
On(
|
||||
"join",
|
||||
toolkit.MockArg[context.Context](),
|
||||
toolkit.MockArg[*mlog.Logger](),
|
||||
h.envBinDirPath,
|
||||
toolkit.MockArg[*children.NebulaDeviceNamer](),
|
||||
joiningBootstrap,
|
||||
toolkit.Dir{Path: networkStateDirPath},
|
||||
toolkit.Dir{Path: networkRuntimeDirPath},
|
||||
(*Opts)(nil),
|
||||
).
|
||||
Return(network, nil).
|
||||
Once()
|
||||
|
||||
got, err := h.loader.Join(
|
||||
h.ctx,
|
||||
h.logger,
|
||||
joiningBootstrap,
|
||||
nil,
|
||||
)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, got, network)
|
||||
|
||||
require.NoError(t, writeBootstrapToStateDir(
|
||||
networkStateDirPath, joiningBootstrap.Bootstrap,
|
||||
))
|
||||
|
||||
return network
|
||||
}
|
||||
|
||||
func (h *loaderHarness) assertDirExists(
|
||||
t *testing.T, exists bool, path string,
|
||||
) {
|
||||
stat, err := os.Stat(path)
|
||||
if exists {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, os.ModeDir, stat.Mode().Type())
|
||||
} else {
|
||||
assert.ErrorIs(t, err, fs.ErrNotExist)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoader_Loadable(t *testing.T) {
|
||||
allCreationParams := []bootstrap.CreationParams{
|
||||
bootstrap.NewCreationParams("AAA", "a.com"),
|
||||
bootstrap.NewCreationParams("BBB", "b.com"),
|
||||
}
|
||||
|
||||
t.Run("empty", func(t *testing.T) {
|
||||
h := newLoaderHarness(t)
|
||||
got, err := h.loader.Loadable(h.ctx)
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, got)
|
||||
})
|
||||
|
||||
t.Run("single", func(t *testing.T) {
|
||||
h := newLoaderHarness(t)
|
||||
h.join(t, allCreationParams[0])
|
||||
got, err := h.loader.Loadable(h.ctx)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, allCreationParams[:1], got)
|
||||
})
|
||||
|
||||
t.Run("multiple", func(t *testing.T) {
|
||||
h := newLoaderHarness(t)
|
||||
h.join(t, allCreationParams[0])
|
||||
h.join(t, allCreationParams[1])
|
||||
got, err := h.loader.Loadable(h.ctx)
|
||||
assert.NoError(t, err)
|
||||
assert.ElementsMatch(t, allCreationParams, got)
|
||||
})
|
||||
}
|
||||
|
||||
func TestLoader_Load(t *testing.T) {
|
||||
var (
|
||||
creationParams = bootstrap.NewCreationParams("AAA", "a.com")
|
||||
)
|
||||
|
||||
t.Run("success", func(t *testing.T) {
|
||||
var (
|
||||
h = newLoaderHarness(t)
|
||||
networkStateDirPath = h.networkStateDirPath(creationParams.ID)
|
||||
networkRuntimeDirPath = h.networkRuntimeDirPath(creationParams.ID)
|
||||
network = h.join(t, creationParams)
|
||||
)
|
||||
|
||||
h.constructors.
|
||||
On(
|
||||
"load",
|
||||
toolkit.MockArg[context.Context](),
|
||||
toolkit.MockArg[*mlog.Logger](),
|
||||
h.envBinDirPath,
|
||||
toolkit.MockArg[*children.NebulaDeviceNamer](),
|
||||
toolkit.Dir{Path: networkStateDirPath},
|
||||
toolkit.Dir{Path: networkRuntimeDirPath},
|
||||
(*Opts)(nil),
|
||||
).
|
||||
Return(network, nil).
|
||||
Once()
|
||||
|
||||
got, err := h.loader.Load(
|
||||
h.ctx,
|
||||
h.logger,
|
||||
creationParams,
|
||||
nil,
|
||||
)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, network, got)
|
||||
})
|
||||
|
||||
t.Run("error/not yet joined", func(t *testing.T) {
|
||||
var (
|
||||
h = newLoaderHarness(t)
|
||||
networkStateDirPath = h.networkStateDirPath(creationParams.ID)
|
||||
networkRuntimeDirPath = h.networkRuntimeDirPath(creationParams.ID)
|
||||
)
|
||||
|
||||
_, err := h.loader.Load(
|
||||
h.ctx,
|
||||
h.logger,
|
||||
creationParams,
|
||||
nil,
|
||||
)
|
||||
|
||||
assert.ErrorContains(t, err, "not yet joined")
|
||||
h.assertDirExists(t, false, networkStateDirPath)
|
||||
h.assertDirExists(t, false, networkRuntimeDirPath)
|
||||
})
|
||||
}
|
||||
|
||||
func TestLoader_Join(t *testing.T) {
|
||||
var (
|
||||
creationParams = bootstrap.NewCreationParams("AAA", "a.com")
|
||||
joiningBootstrap = JoiningBootstrap{
|
||||
Bootstrap: bootstrap.Bootstrap{
|
||||
NetworkCreationParams: creationParams,
|
||||
},
|
||||
}
|
||||
network = NewMockNetwork(t)
|
||||
)
|
||||
|
||||
t.Run("success", func(t *testing.T) {
|
||||
var (
|
||||
h = newLoaderHarness(t)
|
||||
networkStateDirPath = h.networkStateDirPath(creationParams.ID)
|
||||
networkRuntimeDirPath = h.networkRuntimeDirPath(creationParams.ID)
|
||||
)
|
||||
|
||||
h.constructors.
|
||||
On(
|
||||
"join",
|
||||
toolkit.MockArg[context.Context](),
|
||||
toolkit.MockArg[*mlog.Logger](),
|
||||
h.envBinDirPath,
|
||||
toolkit.MockArg[*children.NebulaDeviceNamer](),
|
||||
joiningBootstrap,
|
||||
toolkit.Dir{Path: networkStateDirPath},
|
||||
toolkit.Dir{Path: networkRuntimeDirPath},
|
||||
(*Opts)(nil),
|
||||
).
|
||||
Return(network, nil).
|
||||
Once()
|
||||
|
||||
got, err := h.loader.Join(
|
||||
h.ctx,
|
||||
h.logger,
|
||||
joiningBootstrap,
|
||||
nil,
|
||||
)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, network, got)
|
||||
h.assertDirExists(t, true, networkStateDirPath)
|
||||
h.assertDirExists(t, true, networkRuntimeDirPath)
|
||||
})
|
||||
|
||||
t.Run("error/constructor", func(t *testing.T) {
|
||||
var (
|
||||
h = newLoaderHarness(t)
|
||||
networkStateDirPath = h.networkStateDirPath(creationParams.ID)
|
||||
networkRuntimeDirPath = h.networkRuntimeDirPath(creationParams.ID)
|
||||
wantErr = errors.New("some error")
|
||||
)
|
||||
|
||||
h.constructors.
|
||||
On(
|
||||
"join",
|
||||
toolkit.MockArg[context.Context](),
|
||||
toolkit.MockArg[*mlog.Logger](),
|
||||
h.envBinDirPath,
|
||||
toolkit.MockArg[*children.NebulaDeviceNamer](),
|
||||
joiningBootstrap,
|
||||
toolkit.Dir{Path: networkStateDirPath},
|
||||
toolkit.Dir{Path: networkRuntimeDirPath},
|
||||
(*Opts)(nil),
|
||||
).
|
||||
Return(nil, wantErr).
|
||||
Once()
|
||||
|
||||
_, err := h.loader.Join(
|
||||
h.ctx,
|
||||
h.logger,
|
||||
joiningBootstrap,
|
||||
nil,
|
||||
)
|
||||
|
||||
assert.ErrorIs(t, err, wantErr)
|
||||
h.assertDirExists(t, false, networkStateDirPath)
|
||||
h.assertDirExists(t, false, networkRuntimeDirPath)
|
||||
})
|
||||
}
|
||||
|
||||
func TestLoader_Create(t *testing.T) {
|
||||
var (
|
||||
creationParams = bootstrap.NewCreationParams("AAA", "a.com")
|
||||
ipNet = nebula.MustParseIPNet(t, "172.16.0.0/24")
|
||||
hostName = nebula.HostName("foo")
|
||||
network = NewMockNetwork(t)
|
||||
)
|
||||
|
||||
t.Run("success", func(t *testing.T) {
|
||||
var (
|
||||
h = newLoaderHarness(t)
|
||||
networkStateDirPath = h.networkStateDirPath(creationParams.ID)
|
||||
networkRuntimeDirPath = h.networkRuntimeDirPath(creationParams.ID)
|
||||
)
|
||||
|
||||
h.constructors.
|
||||
On(
|
||||
"create",
|
||||
toolkit.MockArg[context.Context](),
|
||||
toolkit.MockArg[*mlog.Logger](),
|
||||
h.envBinDirPath,
|
||||
toolkit.MockArg[*children.NebulaDeviceNamer](),
|
||||
toolkit.Dir{Path: networkStateDirPath},
|
||||
toolkit.Dir{Path: networkRuntimeDirPath},
|
||||
creationParams,
|
||||
ipNet,
|
||||
hostName,
|
||||
(*Opts)(nil),
|
||||
).
|
||||
Return(network, nil).
|
||||
Once()
|
||||
|
||||
got, err := h.loader.Create(
|
||||
h.ctx,
|
||||
h.logger,
|
||||
creationParams,
|
||||
ipNet,
|
||||
hostName,
|
||||
nil,
|
||||
)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, network, got)
|
||||
h.assertDirExists(t, true, networkStateDirPath)
|
||||
h.assertDirExists(t, true, networkRuntimeDirPath)
|
||||
})
|
||||
|
||||
t.Run("error", func(t *testing.T) {
|
||||
var (
|
||||
h = newLoaderHarness(t)
|
||||
networkStateDirPath = h.networkStateDirPath(creationParams.ID)
|
||||
networkRuntimeDirPath = h.networkRuntimeDirPath(creationParams.ID)
|
||||
wantErr = errors.New("some error")
|
||||
)
|
||||
|
||||
h.constructors.
|
||||
On(
|
||||
"create",
|
||||
toolkit.MockArg[context.Context](),
|
||||
toolkit.MockArg[*mlog.Logger](),
|
||||
h.envBinDirPath,
|
||||
toolkit.MockArg[*children.NebulaDeviceNamer](),
|
||||
toolkit.Dir{Path: networkStateDirPath},
|
||||
toolkit.Dir{Path: networkRuntimeDirPath},
|
||||
creationParams,
|
||||
ipNet,
|
||||
hostName,
|
||||
(*Opts)(nil),
|
||||
).
|
||||
Return(nil, wantErr).
|
||||
Once()
|
||||
|
||||
_, err := h.loader.Create(
|
||||
h.ctx,
|
||||
h.logger,
|
||||
creationParams,
|
||||
ipNet,
|
||||
hostName,
|
||||
nil,
|
||||
)
|
||||
|
||||
assert.ErrorIs(t, err, wantErr)
|
||||
h.assertDirExists(t, false, networkStateDirPath)
|
||||
h.assertDirExists(t, false, networkRuntimeDirPath)
|
||||
})
|
||||
}
|
@ -139,6 +139,12 @@ type Network interface {
|
||||
Shutdown() error
|
||||
}
|
||||
|
||||
// Implements constructors interface, methods defined alongside the rest of the
|
||||
// Network implementation.
|
||||
type constructorsImpl struct{}
|
||||
|
||||
func newConstructors() constructors { return constructorsImpl{} }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Network implementation
|
||||
|
||||
@ -257,7 +263,7 @@ func loadCreationParams(
|
||||
return bs.NetworkCreationParams, nil
|
||||
}
|
||||
|
||||
func load(
|
||||
func (constructorsImpl) load(
|
||||
ctx context.Context,
|
||||
logger *mlog.Logger,
|
||||
envBinDirPath string,
|
||||
@ -298,7 +304,7 @@ func load(
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func join(
|
||||
func (constructorsImpl) join(
|
||||
ctx context.Context,
|
||||
logger *mlog.Logger,
|
||||
envBinDirPath string,
|
||||
@ -337,7 +343,7 @@ func join(
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func create(
|
||||
func (constructorsImpl) create(
|
||||
ctx context.Context,
|
||||
logger *mlog.Logger,
|
||||
envBinDirPath string,
|
||||
|
@ -63,6 +63,7 @@ func newPublicAddr() string {
|
||||
type integrationHarness struct {
|
||||
ctx context.Context
|
||||
logger *mlog.Logger
|
||||
constructors constructors
|
||||
rootDir toolkit.Dir
|
||||
dirCounter atomic.Uint64
|
||||
nebulaDeviceNamer *children.NebulaDeviceNamer
|
||||
@ -90,6 +91,7 @@ func newIntegrationHarness(t *testing.T) *integrationHarness {
|
||||
return &integrationHarness{
|
||||
ctx: context.Background(),
|
||||
logger: toolkit.NewTestLogger(t),
|
||||
constructors: newConstructors(),
|
||||
rootDir: toolkit.Dir{Path: rootDir},
|
||||
nebulaDeviceNamer: children.NewNebulaDeviceNamer(),
|
||||
}
|
||||
@ -171,6 +173,7 @@ type integrationHarnessNetwork struct {
|
||||
|
||||
ctx context.Context
|
||||
logger *mlog.Logger
|
||||
constructors constructors
|
||||
hostName nebula.HostName
|
||||
stateDir, runtimeDir toolkit.Dir
|
||||
nebulaDeviceNamer *children.NebulaDeviceNamer
|
||||
@ -204,7 +207,7 @@ func (h *integrationHarness) createNetwork(
|
||||
}
|
||||
)
|
||||
|
||||
network, err := create(
|
||||
network, err := h.constructors.create(
|
||||
h.ctx,
|
||||
logger,
|
||||
getEnvBinDirPath(),
|
||||
@ -224,6 +227,7 @@ func (h *integrationHarness) createNetwork(
|
||||
network,
|
||||
h.ctx,
|
||||
logger,
|
||||
h.constructors,
|
||||
hostName,
|
||||
stateDir,
|
||||
runtimeDir,
|
||||
@ -288,7 +292,7 @@ func (h *integrationHarness) joinNetwork(
|
||||
)
|
||||
|
||||
t.Logf("Joining as %q", hostNameStr)
|
||||
joinedNetwork, err := join(
|
||||
joinedNetwork, err := h.constructors.join(
|
||||
h.ctx,
|
||||
logger,
|
||||
getEnvBinDirPath(),
|
||||
@ -306,6 +310,7 @@ func (h *integrationHarness) joinNetwork(
|
||||
joinedNetwork,
|
||||
h.ctx,
|
||||
logger,
|
||||
h.constructors,
|
||||
hostName,
|
||||
stateDir,
|
||||
runtimeDir,
|
||||
@ -331,7 +336,7 @@ func (nh *integrationHarnessNetwork) restart(t *testing.T) {
|
||||
|
||||
t.Log("Loading network (restart)")
|
||||
var err error
|
||||
nh.Network, err = load(
|
||||
nh.Network, err = nh.constructors.load(
|
||||
nh.ctx,
|
||||
nh.logger,
|
||||
getEnvBinDirPath(),
|
||||
|
Loading…
Reference in New Issue
Block a user