85 lines
2.1 KiB
Go
85 lines
2.1 KiB
Go
package user
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"os"
|
|
"testing"
|
|
|
|
"example.com/userService/internal/model"
|
|
"git.yuntuo.hk/k2safe/go-omni/database"
|
|
)
|
|
|
|
// This suite runs only against the disposable database created by verifyAPIWorkflow.
|
|
func TestTransactions(t *testing.T) {
|
|
if os.Getenv("USER_SERVICE_TEST_DATABASE") != "1" {
|
|
t.Skip("isolated MySQL required")
|
|
}
|
|
cfg, err := database.ConfigFromEnv("")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
db, err := database.Open(context.Background(), cfg)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer db.Close()
|
|
store := NewStore(db)
|
|
for _, kind := range []string{"error", "panic", "cancel", "commit"} {
|
|
t.Run(kind, func(t *testing.T) {
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
email := kind + "@transaction.example"
|
|
var recovered any
|
|
func() {
|
|
defer func() { recovered = recover() }()
|
|
err = store.WithTx(ctx, func(r UserRepository, audit func(string, int64, string) error) error {
|
|
u, e := r.Create(ctx, model.UserInput{Name: "Transaction", Email: email})
|
|
if e != nil {
|
|
return e
|
|
}
|
|
if e = audit("created", u.ID, "transactionCheck"); e != nil {
|
|
return e
|
|
}
|
|
switch kind {
|
|
case "error":
|
|
return errors.New("rollback sentinel")
|
|
case "panic":
|
|
panic("rollback sentinel")
|
|
case "cancel":
|
|
cancel()
|
|
}
|
|
return nil
|
|
})
|
|
}()
|
|
if kind == "panic" && recovered == nil {
|
|
t.Fatal("panic lost")
|
|
}
|
|
if kind == "commit" && err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if kind != "commit" && kind != "panic" && err == nil {
|
|
t.Fatal("failed transaction committed")
|
|
}
|
|
var count int
|
|
if e := db.QueryRow("SELECT COUNT(*) FROM users WHERE email=?", email).Scan(&count); e != nil {
|
|
t.Fatal(e)
|
|
}
|
|
want := 0
|
|
if kind == "commit" {
|
|
want = 1
|
|
}
|
|
if count != want {
|
|
t.Fatalf("rows=%d want=%d", count, want)
|
|
}
|
|
})
|
|
}
|
|
var audits int
|
|
if err = db.QueryRow("SELECT COUNT(*) FROM user_audit WHERE request_id='transactionCheck'").Scan(&audits); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if audits != 1 {
|
|
t.Fatalf("audit transaction mismatch: %d", audits)
|
|
}
|
|
}
|