//nolint:testpackage // white-box test of unexported internals package cli import ( "encoding/json" "path/filepath" "testing" "time" "git.eeqj.de/sneak/secret/internal/secret" "git.eeqj.de/sneak/secret/internal/vault" "github.com/spf13/afero" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) // TestSameMinuteUnlockersHaveTheirOwnIDs writes two passphrase unlockers // created in the same minute side by side, as an `unlocker add passphrase` // that fails before removing the old one leaves them, and asserts that // `unlocker list` gives each its own ID, and that each is selected and // removed by its ID alone. Keychain and Secure Enclave unlockers, which // only macOS can add, get their IDs the same way. func TestSameMinuteUnlockersHaveTheirOwnIDs(t *testing.T) { t.Parallel() fs := afero.NewMemMapFs() _, err := vault.CreateVault(fs, listTestStateDir, listTestVaultName, testMnemonicBuffer(t)) require.NoError(t, err) vaultDir := testVaultDir(listTestVaultName) unlockersDir := filepath.Join(vaultDir, listTestUnlockersDirName) dirNames := []string{ "passphrase-2026-10-04.12.30.00.000000000", "passphrase-2026-10-04.12.30.30.000000000", } for i, dirName := range dirNames { metadata, err := json.Marshal(secret.UnlockerMetadata{ Type: unlockerTypePassphrase, CreatedAt: time.Date(2026, time.October, 4, 12, 30, 30*i, 0, time.UTC), }) require.NoError(t, err) dir := filepath.Join(unlockersDir, dirName) require.NoError(t, fs.MkdirAll(dir, listTestDirPerm)) require.NoError(t, afero.WriteFile(fs, filepath.Join(dir, listTestMetadataFileName), metadata, listTestFilePerm)) } listed := listUnlockersJSON(t, fs) require.Len(t, listed, len(dirNames)) instance, cmd := newTestInstance(fs) for i, unlocker := range listed { assert.Equal(t, dirNames[i], unlocker.ID) require.NoError(t, instance.UnlockerSelect(unlocker.ID)) current, err := afero.ReadFile(fs, filepath.Join(vaultDir, "current-unlocker")) require.NoError(t, err) assert.Equal(t, dirNames[i], string(current)) } // The newer one first: an ID both shared would remove the older one require.NoError(t, instance.UnlockersRemove(listed[1].ID, true, cmd)) assertDirEntries(t, fs, unlockersDir, dirNames[0]) require.NoError(t, instance.UnlockersRemove(listed[0].ID, true, cmd)) assertDirEntries(t, fs, unlockersDir) }