test(secrets): cover compileAll and ScanBytes compile-error paths #3053
@@ -2,6 +2,7 @@ package secrets
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -187,3 +188,101 @@ func TestMatch_NoRoundtrip(t *testing.T) {
|
||||
// The two-field shape is part of the public contract; new fields
|
||||
// require deliberation about whether they leak the secret value.
|
||||
}
|
||||
|
||||
// resetPatternState snapshots the package-level pattern state and returns a
|
||||
// cleanup function that restores it. Tests that intentionally corrupt
|
||||
// Patterns to exercise compile-failure paths must restore the canonical state
|
||||
// so later tests don't see the corrupted slice / stuck compileErr.
|
||||
func resetPatternState(t *testing.T) (cleanup func()) {
|
||||
t.Helper()
|
||||
origPatterns := make([]Pattern, len(Patterns))
|
||||
copy(origPatterns, Patterns)
|
||||
origCompiledPatterns := compiledPatterns
|
||||
origCompileErr := compileErr
|
||||
return func() {
|
||||
Patterns = origPatterns
|
||||
compiledPatterns = origCompiledPatterns
|
||||
compileErr = origCompileErr
|
||||
compiledOnce = sync.Once{}
|
||||
}
|
||||
}
|
||||
|
||||
// TestCompileError exercises the compileAll error path when a pattern regex
|
||||
// is invalid. This is intentionally unreachable in production (a build bug),
|
||||
// but the error path must be covered.
|
||||
func TestCompileError(t *testing.T) {
|
||||
cleanup := resetPatternState(t)
|
||||
defer cleanup()
|
||||
|
||||
Patterns = []Pattern{{
|
||||
Name: "bad-pattern",
|
||||
Description: "invalid regex for testing",
|
||||
regexSource: `(`, // unbalanced paren
|
||||
}}
|
||||
compiledOnce = sync.Once{}
|
||||
compiledPatterns = nil
|
||||
compileErr = nil
|
||||
|
||||
compileAll()
|
||||
if compileErr == nil {
|
||||
t.Fatal("compileAll expected compile error for invalid regex, got nil")
|
||||
}
|
||||
if !strings.Contains(compileErr.Error(), "bad-pattern") {
|
||||
t.Errorf("compileErr should mention pattern name, got: %v", compileErr)
|
||||
}
|
||||
}
|
||||
|
||||
// TestScanBytes_CompileErr exercises ScanBytes returning the compile error
|
||||
// when Patterns contains an invalid regex.
|
||||
func TestScanBytes_CompileErr(t *testing.T) {
|
||||
cleanup := resetPatternState(t)
|
||||
defer cleanup()
|
||||
|
||||
Patterns = []Pattern{{
|
||||
Name: "another-bad-pattern",
|
||||
Description: "invalid regex for testing",
|
||||
regexSource: `[`, // unclosed character class
|
||||
}}
|
||||
compiledOnce = sync.Once{}
|
||||
compiledPatterns = nil
|
||||
compileErr = nil
|
||||
|
||||
m, err := ScanBytes([]byte("anything"))
|
||||
if err == nil {
|
||||
t.Fatal("ScanBytes expected compile error, got nil")
|
||||
}
|
||||
if m != nil {
|
||||
t.Errorf("ScanBytes should return nil Match on compile error, got %+v", m)
|
||||
}
|
||||
if !strings.Contains(err.Error(), "another-bad-pattern") {
|
||||
t.Errorf("error should mention pattern name, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestScanString_CompileErr exercises ScanString returning the compile error
|
||||
// when Patterns contains an invalid regex. ScanString is the zero-copy wrapper
|
||||
// around ScanBytes, so this confirms the error path propagates through it.
|
||||
func TestScanString_CompileErr(t *testing.T) {
|
||||
cleanup := resetPatternState(t)
|
||||
defer cleanup()
|
||||
|
||||
Patterns = []Pattern{{
|
||||
Name: "string-bad-pattern",
|
||||
Description: "invalid regex for testing",
|
||||
regexSource: `(?`, // invalid regex syntax
|
||||
}}
|
||||
compiledOnce = sync.Once{}
|
||||
compiledPatterns = nil
|
||||
compileErr = nil
|
||||
|
||||
m, err := ScanString("anything")
|
||||
if err == nil {
|
||||
t.Fatal("ScanString expected compile error, got nil")
|
||||
}
|
||||
if m != nil {
|
||||
t.Errorf("ScanString should return nil Match on compile error, got %+v", m)
|
||||
}
|
||||
if !strings.Contains(err.Error(), "string-bad-pattern") {
|
||||
t.Errorf("error should mention pattern name, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user