check / check (push) Failing after 3s
Tests that asserted a failure by a fragment of its message now use errors.Is: a refactor returning the wrong error, or wrapping with %v instead of %w, now fails them. New tests return each exported error of internal/vault and pkg/bip85 that no test returned, and check wrapped causes (os.ErrNotExist, ErrMnemonicMismatch through GetSecret, ErrInvalidPathComponent through DeriveBIP85Entropy). The 999-versions test moves into package secret to name its unexported error. Checks of errors no test can name keep their text; they are listed on the issue. Model: opus-5-5
112 lines
2.9 KiB
Go
112 lines
2.9 KiB
Go
//go:build darwin
|
|
|
|
//nolint:testpackage // white-box test of unexported Secure Enclave helpers
|
|
package secret
|
|
|
|
import (
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/spf13/afero"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestNewSecureEnclaveUnlocker(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
fs := afero.NewMemMapFs()
|
|
dir := "/tmp/test-se-unlocker"
|
|
metadata := UnlockerMetadata{
|
|
Type: seUnlockerType,
|
|
CreatedAt: time.Date(2026, 1, 15, 10, 30, 0, 0, time.UTC),
|
|
Flags: []string{seUnlockerType, "macos"},
|
|
}
|
|
|
|
unlocker := NewSecureEnclaveUnlocker(fs, dir, metadata)
|
|
require.NotNil(t, unlocker, "NewSecureEnclaveUnlocker should return a valid instance")
|
|
|
|
// Test GetType returns correct type
|
|
assert.Equal(t, seUnlockerType, unlocker.GetType())
|
|
|
|
// Test GetMetadata returns the metadata we passed in
|
|
assert.Equal(t, metadata, unlocker.GetMetadata())
|
|
|
|
// Test GetDirectory returns the directory we passed in
|
|
assert.Equal(t, dir, unlocker.GetDirectory())
|
|
}
|
|
|
|
func TestSecureEnclaveUnlockerImplementsInterface(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
fs := afero.NewMemMapFs()
|
|
metadata := UnlockerMetadata{
|
|
Type: seUnlockerType,
|
|
CreatedAt: time.Now().UTC(),
|
|
}
|
|
|
|
unlocker := NewSecureEnclaveUnlocker(fs, "/tmp/test", metadata)
|
|
|
|
// Verify the darwin implementation implements the Unlocker interface
|
|
var _ Unlocker = unlocker
|
|
}
|
|
|
|
func TestSecureEnclaveUnlockerGetIDFormat(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
fs := afero.NewMemMapFs()
|
|
metadata := UnlockerMetadata{
|
|
Type: seUnlockerType,
|
|
CreatedAt: time.Date(2026, 3, 10, 14, 30, 0, 0, time.UTC),
|
|
}
|
|
|
|
unlocker := NewSecureEnclaveUnlocker(fs, "/tmp/test", metadata)
|
|
|
|
// The ID is the name of the unlocker's directory
|
|
assert.Equal(t, "test", unlocker.GetID())
|
|
}
|
|
|
|
func TestGenerateSEKeyLabel(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
label, err := generateSEKeyLabel("test-vault")
|
|
require.NoError(t, err)
|
|
|
|
// Label should contain the prefix and vault name
|
|
assert.Contains(t, label, seKeyLabelPrefix)
|
|
assert.Contains(t, label, "test-vault")
|
|
}
|
|
|
|
func TestSecureEnclaveUnlockerGetIdentityMissingFile(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
fs := afero.NewMemMapFs()
|
|
dir := "/tmp/test-se-unlocker-missing"
|
|
|
|
// Create unlocker directory with metadata but no encrypted key file
|
|
require.NoError(t, fs.MkdirAll(dir, DirPerms))
|
|
|
|
metadataJSON := `{
|
|
"type": "secure-enclave",
|
|
"createdAt": "2026-01-15T10:30:00Z",
|
|
"seKeyLabel": "berlin.sneak.app.secret.se.test",
|
|
"seKeyHash": "abc123"
|
|
}`
|
|
require.NoError(t, afero.WriteFile(
|
|
fs, dir+"/unlocker-metadata.json", []byte(metadataJSON), FilePerms,
|
|
))
|
|
|
|
metadata := UnlockerMetadata{
|
|
Type: seUnlockerType,
|
|
CreatedAt: time.Date(2026, 1, 15, 10, 30, 0, 0, time.UTC),
|
|
}
|
|
|
|
unlocker := NewSecureEnclaveUnlocker(fs, dir, metadata)
|
|
|
|
// GetIdentity should fail because the encrypted longterm key file is missing
|
|
identity, err := unlocker.GetIdentity()
|
|
assert.Nil(t, identity)
|
|
require.ErrorIs(t, err, os.ErrNotExist)
|
|
}
|