package daemon import ( "context" "isle/bootstrap" "isle/daemon/daecommon" "isle/daemon/network" "isle/toolkit" "testing" "dev.mediocregopher.com/mediocre-go-lib.git/mlog" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) type expectNetworkLoad struct { creationParams bootstrap.CreationParams networkConfig *daecommon.NetworkConfig network *network.MockNetwork } type harnessOpts struct { config daecommon.Config expectNetworksLoaded []expectNetworkLoad } func (o *harnessOpts) withDefaults() *harnessOpts { if o == nil { o = new(harnessOpts) } return o } type harness struct { ctx context.Context networkLoader *network.MockLoader daemon *Daemon } func newHarness(t *testing.T, opts *harnessOpts) *harness { t.Parallel() opts = opts.withDefaults() var ( ctx = context.Background() logger = toolkit.NewTestLogger(t) networkLoader = network.NewMockLoader(t) ) expectLoadable := make( []bootstrap.CreationParams, len(opts.expectNetworksLoaded), ) for i, expectNetworkLoaded := range opts.expectNetworksLoaded { expectLoadable[i] = expectNetworkLoaded.creationParams networkLoader. On( "Load", toolkit.MockArg[context.Context](), toolkit.MockArg[*mlog.Logger](), expectNetworkLoaded.creationParams, &network.Opts{ Config: expectNetworkLoaded.networkConfig, }, ). Return(expectNetworkLoaded.network, nil). Once() expectNetworkLoaded.network.On("Shutdown").Return(nil).Once() } networkLoader. On("Loadable", toolkit.MockArg[context.Context]()). Return(expectLoadable, nil). Once() daemon, err := New(ctx, logger, networkLoader, opts.config) require.NoError(t, err) t.Cleanup(func() { t.Log("Shutting down Daemon") assert.NoError(t, daemon.Shutdown()) }) return &harness{ctx, networkLoader, daemon} } func TestNew(t *testing.T) { t.Run("no networks loaded", func(t *testing.T) { _ = newHarness(t, nil) }) t.Run("DEPRECATED network config matching", func(t *testing.T) { var ( creationParams = bootstrap.NewCreationParams("AAA", "a.com") networkConfig = daecommon.NewNetworkConfig(func(c *daecommon.NetworkConfig) { c.DNS.Resolvers = []string{"foo"} }) config = daecommon.Config{ Networks: map[string]daecommon.NetworkConfig{ daecommon.DeprecatedNetworkID: networkConfig, }, } ) _ = newHarness(t, &harnessOpts{ config: config, expectNetworksLoaded: []expectNetworkLoad{ { creationParams, &networkConfig, network.NewMockNetwork(t), }, }, }) }) t.Run("network config matching", func(t *testing.T) { var ( creationParamsA = bootstrap.NewCreationParams("AAA", "a.com") creationParamsB = bootstrap.NewCreationParams("BBB", "b.com") creationParamsC = bootstrap.NewCreationParams("CCC", "c.com") creationParamsD = bootstrap.NewCreationParams("DDD", "d.com") networkConfigA = daecommon.NewNetworkConfig(func(c *daecommon.NetworkConfig) { c.DNS.Resolvers = []string{"foo"} }) networkConfigB = daecommon.NewNetworkConfig(func(c *daecommon.NetworkConfig) { c.VPN.Tun.Device = "bar" }) networkConfigC = daecommon.NewNetworkConfig(func(c *daecommon.NetworkConfig) { c.Storage.Allocations = []daecommon.ConfigStorageAllocation{ { DataPath: "/path/data", MetaPath: "/path/meta", Capacity: 1, }, } }) config = daecommon.Config{ Networks: map[string]daecommon.NetworkConfig{ creationParamsA.ID: networkConfigA, creationParamsB.Name: networkConfigB, creationParamsC.Domain: networkConfigC, "unknown": {}, }, } ) _ = newHarness(t, &harnessOpts{ config: config, expectNetworksLoaded: []expectNetworkLoad{ { creationParamsA, &networkConfigA, network.NewMockNetwork(t), }, { creationParamsB, &networkConfigB, network.NewMockNetwork(t), }, { creationParamsC, &networkConfigC, network.NewMockNetwork(t), }, { creationParamsD, nil, network.NewMockNetwork(t), }, }, }) }) } func TestDaemon_SetConfig(t *testing.T) { t.Run("success", func(t *testing.T) { var ( networkA = network.NewMockNetwork(t) h = newHarness(t, &harnessOpts{ expectNetworksLoaded: []expectNetworkLoad{{ bootstrap.NewCreationParams("AAA", "a.com"), nil, networkA, }}, }) networkConfig = daecommon.NewNetworkConfig(func(c *daecommon.NetworkConfig) { c.VPN.Tun.Device = "foo" }) ) networkA. On("SetConfig", toolkit.MockArg[context.Context](), networkConfig). Return(nil). Once() err := h.daemon.SetConfig(h.ctx, networkConfig) assert.NoError(t, err) }) t.Run("ErrUserManagedNetworkConfig", func(t *testing.T) { var ( creationParams = bootstrap.NewCreationParams("AAA", "a.com") networkA = network.NewMockNetwork(t) networkConfig = daecommon.NewNetworkConfig(nil) h = newHarness(t, &harnessOpts{ config: daecommon.Config{ Networks: map[string]daecommon.NetworkConfig{ creationParams.Name: networkConfig, }, }, expectNetworksLoaded: []expectNetworkLoad{ {creationParams, &networkConfig, networkA}, }, }) ) networkConfig.VPN.Tun.Device = "foo" err := h.daemon.SetConfig(h.ctx, networkConfig) assert.ErrorIs(t, err, ErrUserManagedNetworkConfig) }) }