From 954c218c8c0045ff8e6ed024f394b895bb16f896 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edu=20G=C3=B3mez=20Escandell?= Date: Thu, 26 Oct 2023 10:42:44 +0200 Subject: [PATCH] WIP: tests --- windows-agent/internal/config/config_test.go | 316 +++++++++++------- .../internal/proservices/ui/ui_test.go | 12 +- 2 files changed, 202 insertions(+), 126 deletions(-) diff --git a/windows-agent/internal/config/config_test.go b/windows-agent/internal/config/config_test.go index 2e195e067..15572df26 100644 --- a/windows-agent/internal/config/config_test.go +++ b/windows-agent/internal/config/config_test.go @@ -19,26 +19,34 @@ import ( "github.com/stretchr/testify/require" wsl "github.com/ubuntu/gowsl" wslmock "github.com/ubuntu/gowsl/mock" + "gopkg.in/yaml.v3" ) -// registryState represents how much data is in the registry. -type registryState uint64 +// settingsState represents how much data is in the registry. +type settingsState uint64 const ( - untouched registryState = 0x00 // Nothing UbuntuPro-related exists, as though the program had never ran before - keyExists registryState = 0x01 // Key exists but is empty - - orgTokenExists = keyExists | 1<<(iota+2) // Key exists, organization token field exists - userTokenExists // Key exists, user token field exists - storeTokenExists // Key exists, microsoft store token field exists - landscapeClientConfigExists // Key exists, landscape client config field exists - landscapeAgentUIDExists // Key exists, landscape agent UID field exists - - orgTokenHasValue = orgTokenExists | 1<<16 // Key exists, organization token field exists and is not empty - userTokenHasValue = userTokenExists | 1<<17 // Key exists, user token field exists and is not empty - storeTokenHasValue = storeTokenExists | 1<<18 // Key exists, microsoft store token field exists and is not empty - landscapeClientConfigHasValue = landscapeClientConfigExists | 1<<19 // Key exists, landscape client config field exists and is not empty - landscapeAgentUIDHasValue = landscapeAgentUIDExists | 1<<20 // Key exists, landscape agent UID field exists and is not empty + untouched settingsState = 0 // Nothing UbuntuPro-related exists, as though the program had never ran before + keyExists settingsState = 1 // Key exists but is empty + fileExists settingsState = 2 // File exists but is empty + + // Registry settings + orgTokenExists = keyExists | 1<<3 // Key exists, organization token exists + orgLandscapeConfigExists = keyExists | 1<<4 // Key exists, organization landscape config exists + + orgTokenHasValue = orgTokenExists | 1<<5 // Key exists, organization token exists, and is not empty + orgLandscapeConfigHasValue = orgTokenExists | 1<<6 // Key exists, organization landscape config , and is not empty + + // File settings + userTokenExists = fileExists | 1<<(7+iota) // File exists, user token exists + storeTokenExists // File exists, microsoft store token exists + userLandscapeConfigExists // File exists, landscape client config exists + landscapeUIDExists // File exists, landscape agent UID exists + + userTokenHasValue = userTokenExists | 1<<20 // File exists, user token exists, and is not empty + storeTokenHasValue = storeTokenExists | 1<<21 // File exists, microsoft store token exists, and is not empty + userLandscapeConfigHasValue = userLandscapeConfigExists | 1<<22 // File exists, landscape client config exists, and is not empty + landscapeUIDHasValue = landscapeUIDExists | 1<<23 // File exists, landscape agent UID exists, and is not empty ) func TestSubscription(t *testing.T) { @@ -46,27 +54,29 @@ func TestSubscription(t *testing.T) { testCases := map[string]struct { mockErrors uint32 - registryState registryState + breakFile bool + settingsState settingsState wantToken string wantSource config.ConfigSource wantError bool }{ - "Success": {registryState: userTokenHasValue, wantToken: "user_token", wantSource: config.SourceGUI}, - "Success when the key does not exist": {registryState: untouched}, - "Success when the key exists but is empty": {registryState: keyExists}, - "Success when the key exists but contains empty fields": {registryState: orgTokenExists | userTokenExists | storeTokenExists}, - - "Success when there is an organization token": {registryState: orgTokenHasValue, wantToken: "org_token", wantSource: config.SourceRegistry}, - "Success when there is a user token": {registryState: userTokenHasValue, wantToken: "user_token", wantSource: config.SourceGUI}, - "Success when there is a store token": {registryState: storeTokenHasValue, wantToken: "store_token", wantSource: config.SourceMicrosoftStore}, - - "Success when there are organization and user tokens": {registryState: orgTokenHasValue | userTokenHasValue, wantToken: "user_token", wantSource: config.SourceGUI}, - "Success when there are organization and store tokens": {registryState: orgTokenHasValue | storeTokenHasValue, wantToken: "store_token", wantSource: config.SourceMicrosoftStore}, - "Success when there are organization and user tokens, and an empty store token": {registryState: orgTokenHasValue | userTokenHasValue | storeTokenExists, wantToken: "user_token", wantSource: config.SourceGUI}, - - "Error when the registry key cannot be opened": {registryState: userTokenHasValue, mockErrors: registry.MockErrOnOpenKey, wantError: true}, - "Error when the registry key cannot be read from": {registryState: userTokenHasValue, mockErrors: registry.MockErrReadValue, wantError: true}, + "Success": {settingsState: userTokenHasValue, wantToken: "user_token", wantSource: config.SourceGUI}, + "Success when neither registry key nor conf file exist": {settingsState: untouched}, + "Success when the key exists but is empty": {settingsState: keyExists}, + "Success when the key exists but contains empty fields": {settingsState: orgTokenExists}, + + "Success when there is an organization token": {settingsState: orgTokenHasValue, wantToken: "org_token", wantSource: config.SourceRegistry}, + "Success when there is a user token": {settingsState: userTokenHasValue, wantToken: "user_token", wantSource: config.SourceGUI}, + "Success when there is a store token": {settingsState: storeTokenHasValue, wantToken: "store_token", wantSource: config.SourceMicrosoftStore}, + + "Success when there are organization and user tokens": {settingsState: orgTokenHasValue | userTokenHasValue, wantToken: "user_token", wantSource: config.SourceGUI}, + "Success when there are organization and store tokens": {settingsState: orgTokenHasValue | storeTokenHasValue, wantToken: "store_token", wantSource: config.SourceMicrosoftStore}, + "Success when there are organization and user tokens, and an empty store token": {settingsState: orgTokenHasValue | userTokenHasValue | storeTokenExists, wantToken: "user_token", wantSource: config.SourceGUI}, + + "Error when the registry key cannot be opened": {settingsState: userTokenHasValue, mockErrors: registry.MockErrOnOpenKey, wantError: true}, + "Error when the registry key cannot be read from": {settingsState: userTokenHasValue, mockErrors: registry.MockErrReadValue, wantError: true}, + "Error when the file cannot be read from": {settingsState: untouched, breakFile: true, wantError: true}, } for name, tc := range testCases { @@ -75,8 +85,8 @@ func TestSubscription(t *testing.T) { t.Parallel() ctx := context.Background() - r := setUpMockRegistry(tc.mockErrors, tc.registryState, false) - conf := config.New(ctx, config.WithRegistry(r)) + r, dir := setUpMockSettings(t, tc.mockErrors, tc.settingsState, false, tc.breakFile) + conf := config.New(ctx, dir, config.WithRegistry(r)) token, source, err := conf.Subscription(ctx) if tc.wantError { @@ -93,49 +103,74 @@ func TestSubscription(t *testing.T) { } } -func TestLandscapeClientConfig(t *testing.T) { +func TestLandscapeConfig(t *testing.T) { t.Parallel() - testConfigGetter(t, testConfigGetterSettings{ - getter: (*config.Config).LandscapeClientConfig, - getterName: "LandscapeClientConfig", - registryHasValue: landscapeClientConfigHasValue, - want: "[client]\nuser=JohnDoe", - }) -} + testCases := map[string]struct { + mockErrors uint32 + breakFile bool + settingsState settingsState -func TestLandscapeAgentUID(t *testing.T) { - t.Parallel() + wantLandscapeConfig string + wantSource config.ConfigSource + wantError bool + }{ + "Success": {settingsState: userLandscapeConfigHasValue, wantLandscapeConfig: "[client]\nuser=JohnDoe", wantSource: config.SourceGUI}, - testConfigGetter(t, testConfigGetterSettings{ - getter: (*config.Config).LandscapeAgentUID, - getterName: "LandscapeAgentUID", - registryHasValue: landscapeAgentUIDHasValue, - want: "landscapeUID1234", - }) -} + "Success when neither registry key nor conf file exist": {settingsState: untouched}, + "Success when the registry key exists but is empty": {settingsState: keyExists}, + "Success when the registry key exists but contains empty fields": {settingsState: orgLandscapeConfigExists}, + + "Success when there is an organization conf": {settingsState: orgLandscapeConfigHasValue, wantLandscapeConfig: "[client]\nuser=BigOrg", wantSource: config.SourceRegistry}, + "Success when there is a user conf": {settingsState: userLandscapeConfigHasValue, wantLandscapeConfig: "[client]\nuser=JohnDoe", wantSource: config.SourceGUI}, + + "Success when there are organization and user confs": {settingsState: orgLandscapeConfigHasValue | userLandscapeConfigHasValue, wantLandscapeConfig: "[client]\nuser=JohnDoe", wantSource: config.SourceGUI}, + + "Error when the registry key cannot be opened": {settingsState: userTokenHasValue, mockErrors: registry.MockErrOnOpenKey, wantError: true}, + "Error when the registry key cannot be read from": {settingsState: userTokenHasValue, mockErrors: registry.MockErrReadValue, wantError: true}, + "Error when the file cannot be read from": {settingsState: untouched, breakFile: true, wantError: true}, + } -type testConfigGetterSettings struct { - getter func(*config.Config, context.Context) (string, error) - getterName string - registryHasValue registryState - want string + for name, tc := range testCases { + tc := tc + t.Run(name, func(t *testing.T) { + t.Parallel() + ctx := context.Background() + + r, dir := setUpMockSettings(t, tc.mockErrors, tc.settingsState, false, tc.breakFile) + conf := config.New(ctx, dir, config.WithRegistry(r)) + + token, source, err := conf.LandscapeClientConfig(ctx) + if tc.wantError { + require.Error(t, err, "ProToken should return an error") + return + } + require.NoError(t, err, "ProToken should return no error") + + // Test values + require.Equal(t, tc.wantLandscapeConfig, token, "Unexpected token value") + require.Equal(t, tc.wantSource, source, "Unexpected token source") + assert.Zero(t, r.OpenKeyCount.Load(), "Leaking keys after ProToken") + }) + } } -//nolint:thelper // This is the test itself, not a helper. Besides, a t.Helper() here would not affect the subtests. -func testConfigGetter(t *testing.T, s testConfigGetterSettings) { +func TestLandscapeAgentUID(t *testing.T) { + t.Parallel() + testCases := map[string]struct { - mockErrors uint32 - registryState registryState + registryState settingsState + breakFile bool + breakFileContents bool wantError bool }{ - "Success": {registryState: s.registryHasValue}, - "Success when the key does not exist": {registryState: untouched}, - "Success when the value does not exist": {registryState: keyExists}, + "Success": {registryState: landscapeUIDHasValue}, + "Success when the file does not exist": {registryState: untouched}, + "Success when the value does not exist": {registryState: fileExists}, - "Error when the registry key cannot be opened": {registryState: s.registryHasValue, mockErrors: registry.MockErrOnOpenKey, wantError: true}, - "Error when the registry key cannot be read from": {registryState: s.registryHasValue, mockErrors: registry.MockErrReadValue, wantError: true}, + "Error when the file cannot be opened": {registryState: fileExists, breakFile: true, wantError: true}, + "Error when the file cannot be parsed": {registryState: fileExists, breakFileContents: true, wantError: true}, } for name, tc := range testCases { @@ -144,25 +179,29 @@ func testConfigGetter(t *testing.T, s testConfigGetterSettings) { t.Parallel() ctx := context.Background() - r := setUpMockRegistry(tc.mockErrors, tc.registryState, false) - conf := config.New(ctx, config.WithRegistry(r)) + r, dir := setUpMockSettings(t, 0, tc.registryState, false, tc.breakFile) + if tc.breakFileContents { + err := os.WriteFile(filepath.Join(dir, "config"), []byte("\tmessage:\n\t\tthis is not YAML!["), 0600) + require.NoError(t, err, "Setup: could not re-write config file") + } + conf := config.New(ctx, dir, config.WithRegistry(r)) - v, err := s.getter(conf, ctx) + v, err := conf.LandscapeAgentUID(ctx) if tc.wantError { - require.Error(t, err, "%s should return an error", s.getterName) + require.Error(t, err, "LandscapeAgentUID should return an error") return } - require.NoError(t, err, "%s should return no error", s.getterName) + require.NoError(t, err, "LandscapeAgentUID should return no error") // Test default values - if !tc.registryState.is(s.registryHasValue) { - require.Emptyf(t, v, "Unexpected value when %s is not set in registry", s.getterName) + if !tc.registryState.is(landscapeUIDHasValue) { + require.Emptyf(t, v, "Unexpected value when LandscapeAgentUID is not set in registry") return } // Test non-default values - assert.Equalf(t, s.want, v, "%s returned an unexpected value", s.getterName) - assert.Zerof(t, r.OpenKeyCount.Load(), "Call to %s leaks registry keys", s.getterName) + assert.Equal(t, "landscapeUID1234", v, "LandscapeAgentUID returned an unexpected value") + assert.Zero(t, r.OpenKeyCount.Load(), "Call to LandscapeAgentUID leaks registry keys") }) } } @@ -172,7 +211,7 @@ func TestProvisioningTasks(t *testing.T) { testCases := map[string]struct { mockErrors uint32 - registryState registryState + registryState settingsState want string wantNoLandscape bool @@ -182,8 +221,8 @@ func TestProvisioningTasks(t *testing.T) { "Success when the pro token field does not exist": {registryState: keyExists}, "Success when the pro token exists but is empty": {registryState: userTokenExists}, "Success with a user token": {registryState: userTokenHasValue, want: "user_token"}, - "Success when there is Landscape config, but no UID": {registryState: landscapeClientConfigHasValue, wantNoLandscape: true}, - "Success when there is Landscape config and UID": {registryState: landscapeClientConfigHasValue | landscapeAgentUIDHasValue}, + "Success when there is Landscape config, but no UID": {registryState: userLandscapeConfigHasValue, wantNoLandscape: true}, + "Success when there is Landscape config and UID": {registryState: userLandscapeConfigHasValue | landscapeUIDHasValue}, "Error when the registry key cannot be opened": {registryState: userTokenExists, mockErrors: registry.MockErrOnOpenKey, wantError: true}, "Error when the registry key cannot be read from": {registryState: userTokenExists, mockErrors: registry.MockErrReadValue, wantError: true}, @@ -195,8 +234,8 @@ func TestProvisioningTasks(t *testing.T) { t.Parallel() ctx := context.Background() - r := setUpMockRegistry(tc.mockErrors, tc.registryState, false) - conf := config.New(ctx, config.WithRegistry(r)) + r, dir := setUpMockSettings(t, tc.mockErrors, tc.registryState, false, false) + conf := config.New(ctx, dir, config.WithRegistry(r)) gotTasks, err := conf.ProvisioningTasks(ctx, "UBUNTU") if tc.wantError { @@ -226,7 +265,7 @@ func TestSetSubscription(t *testing.T) { testCases := map[string]struct { mockErrors uint32 - registryState registryState + registryState settingsState accessIsReadOnly bool emptyToken bool @@ -252,8 +291,8 @@ func TestSetSubscription(t *testing.T) { t.Parallel() ctx := context.Background() - r := setUpMockRegistry(tc.mockErrors, tc.registryState, tc.accessIsReadOnly) - conf := config.New(ctx, config.WithRegistry(r)) + r, dir := setUpMockSettings(t, tc.mockErrors, tc.registryState, tc.accessIsReadOnly, false) + conf := config.New(ctx, dir, config.WithRegistry(r)) token := "new_token" if tc.emptyToken { @@ -284,24 +323,20 @@ func TestSetLandscapeAgentUID(t *testing.T) { t.Parallel() testCases := map[string]struct { - mockErrors uint32 - registryState registryState - accessIsReadOnly bool - emptyUID bool + registryState settingsState + emptyUID bool + breakFile bool want string wantError bool wantErrorType error }{ - "Success": {registryState: landscapeAgentUIDHasValue, want: "new_uid"}, - "Success unsetting the UID": {registryState: landscapeAgentUIDHasValue, emptyUID: true, want: ""}, - "Success when the key does not exist": {registryState: untouched, want: "new_uid"}, - "Success when the pro token field does not exist": {registryState: keyExists, want: "new_uid"}, + "Success overriding the UID": {registryState: landscapeUIDHasValue, want: "new_uid"}, + "Success unsetting the UID": {registryState: landscapeUIDHasValue, emptyUID: true, want: ""}, + "Success when the file does not exist": {registryState: untouched, want: "new_uid"}, + "Success when the pro token field does not exist": {registryState: fileExists, want: "new_uid"}, - "Error when the registry key cannot be written on due to lack of permission": {registryState: landscapeAgentUIDHasValue, accessIsReadOnly: true, want: "landscapeUID1234", wantError: true, wantErrorType: registry.ErrAccessDenied}, - "Error when the registry key cannot be opened": {registryState: landscapeAgentUIDHasValue, mockErrors: registry.MockErrOnCreateKey, want: "landscapeUID1234", wantError: true, wantErrorType: registry.ErrMock}, - "Error when the registry key cannot be written on": {registryState: landscapeAgentUIDHasValue, mockErrors: registry.MockErrOnWriteValue, want: "landscapeUID1234", wantError: true, wantErrorType: registry.ErrMock}, - "Error when the registry key cannot be read": {registryState: landscapeAgentUIDHasValue, mockErrors: registry.MockErrOnOpenKey, want: "landscapeUID1234", wantError: true, wantErrorType: registry.ErrMock}, + "Error when the file cannot be opened": {registryState: landscapeUIDHasValue, breakFile: true, want: "landscapeUID1234", wantError: true, wantErrorType: registry.ErrMock}, } for name, tc := range testCases { @@ -310,8 +345,8 @@ func TestSetLandscapeAgentUID(t *testing.T) { t.Parallel() ctx := context.Background() - r := setUpMockRegistry(tc.mockErrors, tc.registryState, tc.accessIsReadOnly) - conf := config.New(ctx, config.WithRegistry(r)) + r, dir := setUpMockSettings(t, 0, tc.registryState, false, tc.breakFile) + conf := config.New(ctx, dir, config.WithRegistry(r)) uid := "new_uid" if tc.emptyUID { @@ -342,7 +377,7 @@ func TestIsReadOnly(t *testing.T) { t.Parallel() testCases := map[string]struct { - registryState registryState + registryState settingsState readOnly bool registryErr bool @@ -364,12 +399,12 @@ func TestIsReadOnly(t *testing.T) { t.Parallel() ctx := context.Background() - r := setUpMockRegistry(0, tc.registryState, tc.readOnly) + r, dir := setUpMockSettings(t, 0, tc.registryState, tc.readOnly, false) if tc.registryErr { r.Errors = registry.MockErrOnCreateKey } - conf := config.New(ctx, config.WithRegistry(r)) + conf := config.New(ctx, dir, config.WithRegistry(r)) got, err := conf.IsReadOnly() if tc.wantErr { @@ -387,7 +422,7 @@ func TestFetchMicrosoftStoreSubscription(t *testing.T) { t.Parallel() testCases := map[string]struct { - registryState registryState + registryState settingsState registryErr uint32 registryIsReadOnly bool @@ -410,8 +445,8 @@ func TestFetchMicrosoftStoreSubscription(t *testing.T) { ctx := context.Background() - r := setUpMockRegistry(tc.registryErr, tc.registryState, tc.registryIsReadOnly) - c := config.New(ctx, config.WithRegistry(r)) + r, dir := setUpMockSettings(t, tc.registryErr, tc.registryState, tc.registryIsReadOnly, false) + c := config.New(ctx, dir, config.WithRegistry(r)) err := c.FetchMicrosoftStoreSubscription(ctx) if tc.wantErr { @@ -513,54 +548,89 @@ func readFileOrEmpty(path string) (string, error) { } // is defines equality between flags. It is convenience function to check if a registryState matches a certain state. -func (state registryState) is(flag registryState) bool { +func (state settingsState) is(flag settingsState) bool { return state&flag == flag } -func setUpMockRegistry(mockErrors uint32, state registryState, readOnly bool) *registry.Mock { - r := registry.NewMock() +func setUpMockSettings(t *testing.T, mockErrors uint32, state settingsState, readOnly bool, fileBroken bool) (*registry.Mock, string) { + t.Helper() - r.Errors = mockErrors - r.KeyIsReadOnly = readOnly + // Mock registry + reg := registry.NewMock() + reg.Errors = mockErrors + reg.KeyIsReadOnly = readOnly if state.is(keyExists) { - r.KeyExists = true + reg.KeyExists = true } if state.is(orgTokenExists) { - r.UbuntuProData["ProTokenOrg"] = "" + reg.UbuntuProData["UbuntuProToken"] = "" } if state.is(orgTokenHasValue) { - r.UbuntuProData["ProTokenOrg"] = "org_token" + reg.UbuntuProData["UbuntuProToken"] = "org_token" + } + + if state.is(orgLandscapeConfigExists) { + reg.UbuntuProData["LandscapeConfig"] = "" + } + if state.is(orgLandscapeConfigHasValue) { + reg.UbuntuProData["LandscapeConfig"] = "[client]\nuser=BigOrg" + } + + // Mock file config + cacheDir := t.TempDir() + if fileBroken { + err := os.MkdirAll(filepath.Join(cacheDir, "config"), 0600) + require.NoError(t, err, "Setup: could not create directory to interfere with config") + return reg, cacheDir + } + + if !state.is(fileExists) { + return reg, cacheDir + } + + fileData := struct { + Landscape map[string]string + Subscription map[string]string + }{ + Subscription: make(map[string]string), + Landscape: make(map[string]string), } if state.is(userTokenExists) { - r.UbuntuProData["ProTokenUser"] = "" + fileData.Subscription["GUI"] = "" } if state.is(userTokenHasValue) { - r.UbuntuProData["ProTokenUser"] = "user_token" + fileData.Subscription["GUI"] = "user_token" } if state.is(storeTokenExists) { - r.UbuntuProData["ProTokenStore"] = "" + fileData.Subscription["store"] = "" } if state.is(storeTokenHasValue) { - r.UbuntuProData["ProTokenStore"] = "store_token" + fileData.Subscription["store"] = "store_token" } - if state.is(landscapeClientConfigExists) { - r.UbuntuProData["LandscapeClientConfig"] = "" + if state.is(userLandscapeConfigExists) { + fileData.Landscape["config"] = "" } - if state.is(landscapeClientConfigHasValue) { - r.UbuntuProData["LandscapeClientConfig"] = "[client]\nuser=JohnDoe" + if state.is(userLandscapeConfigHasValue) { + fileData.Landscape["config"] = "[client]\nuser=JohnDoe" } - if state.is(landscapeAgentUIDExists) { - r.UbuntuProData["LandscapeAgentUID"] = "" + if state.is(landscapeUIDExists) { + fileData.Landscape["uid"] = "" } - if state.is(landscapeAgentUIDHasValue) { - r.UbuntuProData["LandscapeAgentUID"] = "landscapeUID1234" + if state.is(landscapeUIDHasValue) { + fileData.Landscape["uid"] = "landscapeUID1234" } - return r + out, err := yaml.Marshal(fileData) + require.NoError(t, err, "Setup: could not marshal fake config") + + err = os.WriteFile(filepath.Join(cacheDir, "config"), out, 0600) + require.NoError(t, err, "Setup: could not write config file") + + return reg, cacheDir } diff --git a/windows-agent/internal/proservices/ui/ui_test.go b/windows-agent/internal/proservices/ui/ui_test.go index efb529895..49d76f919 100644 --- a/windows-agent/internal/proservices/ui/ui_test.go +++ b/windows-agent/internal/proservices/ui/ui_test.go @@ -3,6 +3,9 @@ package ui_test import ( "context" "errors" + "fmt" + "os" + "path/filepath" "testing" agentapi "github.com/canonical/ubuntu-pro-for-windows/agentapi/go" @@ -26,7 +29,7 @@ func TestNew(t *testing.T) { require.NoError(t, err, "Setup: empty database New() should return no error") defer db.Close(ctx) - conf := config.New(ctx, config.WithRegistry(registry.NewMock())) + conf := config.New(ctx, dir, config.WithRegistry(registry.NewMock())) _ = ui.New(context.Background(), conf, db) } @@ -80,9 +83,12 @@ func TestAttachPro(t *testing.T) { m := registry.NewMock() m.KeyIsReadOnly = tc.registryReadOnly m.KeyExists = true - m.UbuntuProData["ProTokenUser"] = originalToken - conf := config.New(ctx, config.WithRegistry(m)) + contents := fmt.Sprintf("subscription:\n gui: %s", originalToken) + err = os.WriteFile(filepath.Join(dir, "config"), []byte(contents), 0600) + require.NoError(t, err, "Setup: could not write config file") + + conf := config.New(ctx, dir, config.WithRegistry(m)) serv := ui.New(context.Background(), conf, db) info := agentapi.ProAttachInfo{Token: tc.token}