Files
netbird/client/internal/profilemanager/migration_test.go
T

122 lines
4.3 KiB
Go

package profilemanager
import (
"os"
"os/user"
"path/filepath"
"runtime"
"strconv"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// currentUserPrincipal returns the running account's name and the owner
// principal migration should record for it. Migration resolves a real account
// through the host's user database, so there is nothing to stub.
func currentUserPrincipal(t *testing.T) (string, string) {
t.Helper()
if runtime.GOOS == "windows" {
t.Skip("the windows path records a SID rather than a numeric uid")
}
u, err := user.Current()
require.NoError(t, err)
uid, err := strconv.ParseUint(u.Uid, 10, 32)
require.NoError(t, err)
return u.Username, "uid:" + strconv.FormatUint(uid, 10)
}
func TestMigrate_StampsTheActiveAccountsDirectory(t *testing.T) {
username, principal := currentUserPrincipal(t)
withLegacyLayout(t, func(sm *ServiceManager, configDir string) {
dir := sanitizeProfileName(username)
mine := writeLegacyProfile(t, configDir, dir, "work", nil)
theirs := writeLegacyProfile(t, configDir, "someone-else", "theirs", nil)
require.NoError(t, sm.SetActiveProfileState(&ActiveProfileState{ID: "work", Username: username}))
require.NoError(t, sm.MigrateLegacyProfiles())
assert.Equal(t, []string{principal}, readOwners(t, mine))
assert.Empty(t, readOwners(t, theirs),
"only the account the active state names has a directory we can attribute")
assert.DirExists(t, filepath.Join(configDir, DefaultProfilePathDir),
"the marker is written once both halves are done")
})
}
func TestMigrate_IsIdempotentAndSkipsOnceMarked(t *testing.T) {
username, principal := currentUserPrincipal(t)
withLegacyLayout(t, func(sm *ServiceManager, configDir string) {
path := writeLegacyProfile(t, configDir, sanitizeProfileName(username), "work", nil)
require.NoError(t, sm.SetActiveProfileState(&ActiveProfileState{ID: "work", Username: username}))
require.NoError(t, sm.MigrateLegacyProfiles())
require.NoError(t, sm.MigrateLegacyProfiles())
assert.Equal(t, []string{principal}, readOwners(t, path))
// A profile appearing after the marker is left to the per-caller claim.
late := writeLegacyProfile(t, configDir, sanitizeProfileName(username), "late", nil)
require.NoError(t, sm.MigrateLegacyProfiles())
assert.Empty(t, readOwners(t, late))
})
}
func TestMigrate_RekeysDuplicateIDsAndKeepsTheActiveOne(t *testing.T) {
username, principal := currentUserPrincipal(t)
withLegacyLayout(t, func(sm *ServiceManager, configDir string) {
dir := sanitizeProfileName(username)
writeLegacyProfile(t, configDir, dir, "work", nil)
writeLegacyProfile(t, configDir, "someone-else", "work", nil)
require.NoError(t, os.WriteFile(filepath.Join(configDir, dir, "work"+stateFileSuffix), []byte("{}"), 0600))
require.NoError(t, sm.SetActiveProfileState(&ActiveProfileState{ID: "work", Username: username}))
require.NoError(t, sm.MigrateLegacyProfiles())
profiles, err := sm.loadAllProfiles()
require.NoError(t, err)
ids := map[ID]int{}
for _, p := range profiles {
ids[p.ID]++
if p.ID != defaultProfileName {
assert.Equal(t, "work", p.Name, "the display name outlives the filename it came from")
}
}
for id, n := range ids {
assert.Equal(t, 1, n, "%s is still shared after migration", id)
}
state, err := sm.GetActiveProfileState()
require.NoError(t, err)
assert.NotEqual(t, ID("work"), state.ID, "the active profile follows its new ID")
active, err := sm.ActiveProfilePath(state)
require.NoError(t, err)
assert.Equal(t, dir, filepath.Base(filepath.Dir(active)),
"and still resolves inside the account that was running it")
assert.Equal(t, []string{principal}, readOwners(t, active))
assert.FileExists(t, filepath.Join(configDir, dir, state.ID.String()+stateFileSuffix),
"the state file follows the profile it belongs to")
})
}
func TestMigrate_UnresolvableAccountLeavesNoMarker(t *testing.T) {
withLegacyLayout(t, func(sm *ServiceManager, configDir string) {
path := writeLegacyProfile(t, configDir, "ghost", "work", nil)
require.NoError(t, sm.SetActiveProfileState(&ActiveProfileState{
ID: "work", Username: "no-such-account-here",
}))
require.Error(t, sm.MigrateLegacyProfiles())
assert.Empty(t, readOwners(t, path))
assert.NoDirExists(t, filepath.Join(configDir, DefaultProfilePathDir),
"an unfinished run leaves no marker, so the next start tries again")
})
}