Files
orm/serialization_failure_test.go
zeekayandHanzo Dev 4be00f32ab Go 1.27.1, and the code it can say more simply
Modules declare go 1.27.1 and the build images follow. go fix applied the
modernizers: any, reflect.TypeFor, the atomic types, WaitGroup.Go, the
reflect field iterators, CutPrefix, SplitSeq, strings.Builder and range over
int. omitzero is not applied, since it changes what the JSON says.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-16 19:46:12 -07:00

60 lines
2.0 KiB
Go

package orm
import (
"errors"
"fmt"
"testing"
)
// isSerializationFailure must recognize SQLite busy/locked errors as
// retryable. A missing substring match turns contention into a spurious 500.
func TestIsSerializationFailure_RetryableSQLiteErrors(t *testing.T) {
cases := []struct {
name string
err error
want bool
}{
{"sqlite_busy", errors.New("SQLITE_BUSY: database is locked"), true},
{"sqlite_locked", errors.New("SQLITE_LOCKED: database table is locked"), true},
{"database is locked", errors.New("database is locked"), true},
{"database table is locked", errors.New("database table is locked"), true},
// Non-retryable — must NOT be treated as transient.
{"constraint_violation", errors.New("UNIQUE constraint failed: _entities.id"), false},
{"syntax_error", errors.New("syntax error near \"SELECTT\""), false},
{"no_such_table", errors.New("no such table: missing"), false},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
if got := isSerializationFailure(c.err); got != c.want {
t.Errorf("isSerializationFailure(%q)=%v, want %v", c.err, got, c.want)
}
})
}
}
// Wrapped errors still unwrap correctly and match the sentinel / substrings.
func TestIsSerializationFailure_Wrapped(t *testing.T) {
base := errors.New("SQLITE_BUSY: database is locked")
wrapped := fmt.Errorf("exec: %w", base)
if !isSerializationFailure(wrapped) {
t.Errorf("wrapped BUSY should be retryable")
}
}
// Sanity: nil is not a failure.
func TestIsSerializationFailure_Nil(t *testing.T) {
if isSerializationFailure(nil) {
t.Errorf("nil error must not be treated as retryable")
}
}
// Sanity: the sentinel ErrSerializationFailure still triggers.
func TestIsSerializationFailure_Sentinel(t *testing.T) {
if !isSerializationFailure(ErrSerializationFailure) {
t.Errorf("ErrSerializationFailure sentinel must be retryable")
}
if !isSerializationFailure(fmt.Errorf("wrap: %w", ErrSerializationFailure)) {
t.Errorf("wrapped sentinel must be retryable")
}
}