From b769d71f6ec4fac83e0ccc02e324d8c9a3ab7d2e Mon Sep 17 00:00:00 2001 From: Tim Van Baak Date: Fri, 31 Jan 2025 09:32:23 -0800 Subject: [PATCH] Add DB implementation with fault injection --- core/db_test.go | 77 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/core/db_test.go b/core/db_test.go index 93823fc..de50635 100644 --- a/core/db_test.go +++ b/core/db_test.go @@ -1,11 +1,88 @@ package core import ( + "database/sql" + "errors" + "strings" "testing" _ "github.com/mattn/go-sqlite3" ) +type FailureDb struct { + db DB + queryError func(string, ...any) error + execError func(string, ...any) error +} + +func (f *FailureDb) Query(query string, args ...any) (*sql.Rows, error) { + if f.queryError != nil { + if err := f.queryError(query, args...); err != nil { + return nil, err + } + } + return f.db.Query(query, args...) +} + +func (f *FailureDb) QueryRow(query string, args ...any) *sql.Row { + return f.db.QueryRow(query, args...) +} + +func (f *FailureDb) Exec(query string, args ...any) (sql.Result, error) { + if f.execError != nil { + if err := f.execError(query, args...); err != nil { + return nil, err + } + } + return f.db.Exec(query, args...) +} + +func (f *FailureDb) Prepare(query string) (*sql.Stmt, error) { + return f.db.Prepare(query) +} + +func (f *FailureDb) Transact(txFunc func(DB) error) error { + return f.db.Transact(func(tx DB) error { + ftx := FailureDb{ + db: tx, + queryError: f.queryError, + execError: f.execError, + } + return txFunc(&ftx) + }) +} + +func TestFailureDb(t *testing.T) { + db := EphemeralDb(t) + fdb := FailureDb{ + db: db, + queryError: func(q string, a ...any) error { + if strings.Contains(q, "2") { + return errors.New("oopsie") + } + return nil + }, + } + + if _, err := fdb.Query("select 1"); err != nil { + t.Fatal(err) + } + + if _, err := fdb.Query("select 2"); err == nil { + t.Fatal("expected error") + } + + if err := fdb.Transact(func(tx DB) error { + if _, err := tx.Query("select 1"); err != nil { + t.Fatal(err) + } + _, err := tx.Query("select 2") + return err + }); err == nil { + t.Fatal("expected error from inside transaction") + } +} + func TestDeleteSourceCascade(t *testing.T) { db := EphemeralDb(t)