Check errors by identity, not by message text, in tests (closes #49)
check / check (push) Failing after 4s

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
This commit is contained in:
2026-10-04 20:44:24 +00:00
parent 2adc588ace
commit 79bc021412
19 changed files with 401 additions and 256 deletions
+5 -18
View File
@@ -38,7 +38,6 @@ const (
testMessageLargePattern = "A"
// Error messages for validation
errorMsgNeed32Bytes = "need 32-byte scalar, got"
errorMsgInvalidXPRV = "invalid-xprv"
// Test constants for various scenarios
@@ -330,24 +329,17 @@ func TestClampFunction(t *testing.T) {
}
}
// requireIdentityError asserts that identity derivation failed with an
// error containing errorMsg and returned no identity.
// requireIdentityError asserts that identity derivation failed with
// errInvalidScalarSize and returned no identity.
func requireIdentityError(
t *testing.T,
identity *age.X25519Identity,
err error,
errorMsg string,
) {
t.Helper()
if err == nil {
t.Errorf("expected error but got none")
} else if !strings.Contains(err.Error(), errorMsg) {
t.Errorf(
"expected error containing %q, got %q",
errorMsg,
err.Error(),
)
if !errors.Is(err, errInvalidScalarSize) {
t.Errorf("expected errInvalidScalarSize, got %v", err)
}
if identity != nil {
@@ -363,31 +355,26 @@ func TestIdentityFromEntropyEdgeCases(t *testing.T) {
name string
entropy []byte
expectError bool
errorMsg string
}{
{
name: "nil entropy",
entropy: nil,
expectError: true,
errorMsg: errorMsgNeed32Bytes + " 0",
},
{
name: "empty entropy",
entropy: []byte{},
expectError: true,
errorMsg: errorMsgNeed32Bytes + " 0",
},
{
name: "too short entropy",
entropy: make([]byte, 31),
expectError: true,
errorMsg: errorMsgNeed32Bytes + " 31",
},
{
name: "too long entropy",
entropy: make([]byte, 33),
expectError: true,
errorMsg: errorMsgNeed32Bytes + " 33",
},
{
name: "valid 32-byte entropy",
@@ -419,7 +406,7 @@ func TestIdentityFromEntropyEdgeCases(t *testing.T) {
identity, err := IdentityFromEntropy(tt.entropy)
if tt.expectError {
requireIdentityError(t, identity, err, tt.errorMsg)
requireIdentityError(t, identity, err)
return
}
+35 -9
View File
@@ -4,6 +4,7 @@ package bip85_test
import (
"bytes"
"encoding/hex"
"errors"
"fmt"
"strings"
"testing"
@@ -1013,14 +1014,13 @@ func TestHexDerivation(t *testing.T) {
func TestInvalidParameters(t *testing.T) {
t.Parallel()
logTestVector(t, "Invalid Parameters")
masterKey := mustParseTestMasterKey(t)
// Test cases for parameter validation
testCases := []struct {
name string
testFunc func() error
want error
}{
{
name: "BIP39 invalid word count",
@@ -1030,6 +1030,7 @@ func TestInvalidParameters(t *testing.T) {
return err
},
want: bip85.ErrInvalidWordCount,
},
{
name: "Base64 password too short",
@@ -1039,6 +1040,7 @@ func TestInvalidParameters(t *testing.T) {
return err
},
want: bip85.ErrInvalidBase64PwdLen,
},
{
name: "Base64 password too long",
@@ -1048,6 +1050,7 @@ func TestInvalidParameters(t *testing.T) {
return err
},
want: bip85.ErrInvalidBase64PwdLen,
},
{
name: "Base85 password too short",
@@ -1057,6 +1060,7 @@ func TestInvalidParameters(t *testing.T) {
return err
},
want: bip85.ErrInvalidBase85PwdLen,
},
{
name: "Base85 password too long",
@@ -1066,6 +1070,7 @@ func TestInvalidParameters(t *testing.T) {
return err
},
want: bip85.ErrInvalidBase85PwdLen,
},
{
name: "Hex data too small",
@@ -1075,6 +1080,7 @@ func TestInvalidParameters(t *testing.T) {
return err
},
want: bip85.ErrInvalidNumBytes,
},
{
name: "Hex data too large",
@@ -1084,23 +1090,43 @@ func TestInvalidParameters(t *testing.T) {
return err
},
want: bip85.ErrInvalidNumBytes,
},
}
// Run all validation test cases
for _, tc := range testCases {
t.Logf("Testing: %s", tc.name)
err := tc.testFunc()
if err == nil {
t.Errorf("Expected error for %s, but got nil", tc.name)
} else {
t.Logf("Got expected error: %v", err)
t.Logf("RESULT: PASS")
if !errors.Is(err, tc.want) {
t.Errorf("Expected %v for %s, got %v", tc.want, tc.name, err)
}
}
}
// TestDeriveBIP85EntropyErrors checks that DeriveBIP85Entropy returns
// ErrNotPrivateKey for a public master key, and ErrInvalidPathComponent,
// wrapped, for a path component that is not a number.
func TestDeriveBIP85EntropyErrors(t *testing.T) {
t.Parallel()
masterKey := mustParseTestMasterKey(t)
publicKey, err := masterKey.Neuter()
if err != nil {
t.Fatalf("Failed to get the public key of the master key: %v", err)
}
_, err = bip85.DeriveBIP85Entropy(publicKey, testCase1Path)
if !errors.Is(err, bip85.ErrNotPrivateKey) {
t.Errorf("Expected ErrNotPrivateKey, got %v", err)
}
_, err = bip85.DeriveBIP85Entropy(masterKey, bip85.BIP85_MASTER_PATH+"/x'")
if !errors.Is(err, bip85.ErrInvalidPathComponent) {
t.Errorf("Expected ErrInvalidPathComponent, got %v", err)
}
}
// TestAdditionalDeriveHex tests additional hex derivation scenarios
func TestAdditionalDeriveHex(t *testing.T) {
t.Parallel()