WIP: cheap scrypt in tests
check / check (push) Failing after 2s

This commit is contained in:
2026-10-05 23:50:49 +00:00
parent af9ac6d979
commit 9fec3d7098
6 changed files with 40 additions and 5 deletions
+2 -2
View File
@@ -353,9 +353,9 @@ func TestRemovalWithoutTerminalFailsAtOnce(t *testing.T) {
// for its answer, another command can take the state directory lock and // for its answer, another command can take the state directory lock and
// change the secret, and that the removal then removes nothing, since the // change the secret, and that the removal then removes nothing, since the
// secret is no longer what the question named. // secret is no longer what the question named.
//
//nolint:paralleltest // times commands against the in-memory lock all tests share
func TestRemovalAsksWithoutHoldingLock(t *testing.T) { func TestRemovalAsksWithoutHoldingLock(t *testing.T) {
t.Parallel()
r := newRemoval(t, "rm") r := newRemoval(t, "rm")
answers, answerWriter := io.Pipe() answers, answerWriter := io.Pipe()
+5 -1
View File
@@ -52,8 +52,12 @@ func runSecretWithStdin(stdin string, env map[string]string, args ...string) (st
return cli.ExecuteCommandInProcess(args, stdin, env) return cli.ExecuteCommandInProcess(args, stdin, env)
} }
// TestMain runs before all tests and ensures the binary is built // TestMain runs before all tests and ensures the binary is built. It also
// makes passphrase encryption in the tests cheap (see
// secret.ScryptWorkFactor); the binary keeps age's work factor.
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
secret.ScryptWorkFactor = 1
// Get the current working directory // Get the current working directory
wd, err := os.Getwd() wd, err := os.Getwd()
if err != nil { if err != nil {
+2 -2
View File
@@ -235,9 +235,9 @@ func TestEncryptPipedIntoAdd(t *testing.T) {
// TestFailedCommandReleasesLock checks that a command failing after it // TestFailedCommandReleasesLock checks that a command failing after it
// took the state directory lock leaves the lock free for the next command. // took the state directory lock leaves the lock free for the next command.
//
//nolint:paralleltest // times commands against the in-memory lock all tests share
func TestFailedCommandReleasesLock(t *testing.T) { func TestFailedCommandReleasesLock(t *testing.T) {
t.Parallel()
fs := afero.NewMemMapFs() fs := afero.NewMemMapFs()
cli := NewCLIInstanceWithStateDir(fs, testStateDir) cli := NewCLIInstanceWithStateDir(fs, testStateDir)
+14
View File
@@ -28,6 +28,16 @@ var (
// terminal to read the mnemonic from, reading it failed, or it was empty. // terminal to read the mnemonic from, reading it failed, or it was empty.
var ErrMnemonicNotRead = errors.New("failed to read mnemonic") var ErrMnemonicNotRead = errors.New("failed to read mnemonic")
// ScryptWorkFactor, when not zero, replaces age's scrypt work factor, 18, in
// EncryptWithPassphrase. It is log2 of the number of scrypt iterations. age's
// costs about a second and 256 MiB per passphrase, on purpose, as it does each
// guess at one. Only tests set it, lower, before any test runs, so that the
// passphrase unlockers they create cost nothing; the program leaves it zero.
// Decryption reads the work factor from the encrypted data.
//
//nolint:gochecknoglobals // set by the tests of the packages that use this one
var ScryptWorkFactor int
// EncryptToRecipient encrypts data to a recipient using age // EncryptToRecipient encrypts data to a recipient using age
// The data parameter should be a LockedBuffer for secure memory handling // The data parameter should be a LockedBuffer for secure memory handling
func EncryptToRecipient( func EncryptToRecipient(
@@ -142,6 +152,10 @@ func EncryptWithPassphrase(
return nil, fmt.Errorf("failed to create scrypt recipient: %w", err) return nil, fmt.Errorf("failed to create scrypt recipient: %w", err)
} }
if ScryptWorkFactor != 0 {
recipient.SetWorkFactor(ScryptWorkFactor)
}
return EncryptToRecipient(data, recipient) return EncryptToRecipient(data, recipient)
} }
+8
View File
@@ -25,6 +25,14 @@ var (
errNotImplementedInMock = errors.New("not implemented in mock") errNotImplementedInMock = errors.New("not implemented in mock")
) )
// TestMain makes passphrase encryption in the tests cheap; see
// ScryptWorkFactor.
func TestMain(m *testing.M) {
ScryptWorkFactor = 1
os.Exit(m.Run())
}
// MockVault is a test implementation of the VaultInterface // MockVault is a test implementation of the VaultInterface
type MockVault struct { type MockVault struct {
name string name string
+9
View File
@@ -3,6 +3,7 @@ package vault_test
import ( import (
"bytes" "bytes"
"errors" "errors"
"os"
"path/filepath" "path/filepath"
"slices" "slices"
"testing" "testing"
@@ -28,6 +29,14 @@ const (
testPassphrase = "test-passphrase" testPassphrase = "test-passphrase"
) )
// TestMain makes passphrase encryption in the tests cheap; see
// secret.ScryptWorkFactor.
func TestMain(m *testing.M) {
secret.ScryptWorkFactor = 1
os.Exit(m.Run())
}
// testMnemonicBuffer returns testMnemonic in a locked buffer that is // testMnemonicBuffer returns testMnemonic in a locked buffer that is
// destroyed when the test ends. // destroyed when the test ends.
func testMnemonicBuffer(t *testing.T) *memguard.LockedBuffer { func testMnemonicBuffer(t *testing.T) *memguard.LockedBuffer {