Skip to content
Snippets Groups Projects
Commit 76bf6b4c authored by Lukas Braun's avatar Lukas Braun
Browse files

Test nested read-update transactions

parent 2d90769c
No related branches found
No related tags found
No related merge requests found
...@@ -70,20 +70,20 @@ func create_user_t(t *testing.T) { ...@@ -70,20 +70,20 @@ func create_user_t(t *testing.T) {
t.Run("stdin", create_and_check("-", "-")) t.Run("stdin", create_and_check("-", "-"))
} }
// runs two updating transactions concurrently, fails if none of them aborts func interleaved_transactions_t(t *testing.T) {
func transaction_conflict_t(t *testing.T) {
var err error var err error
var txs [2]*sql.Tx var txs [2]*sql.Tx
for i, _ := range txs { for i, _ := range txs {
txs[i], err = db.Begin() txs[i], err = db.Begin()
t_err_fatal(t, err) t_err_fatal(t, err)
defer func(i int) { t.Log("rollback", i); txs[i].Rollback() }(i) defer func(i int) { txs[i].Rollback() }(i)
} }
var c uint64 var c uint64
for _, tx := range txs { for i, tx := range txs {
err = tx.QueryRow("SELECT count FROM users WHERE name = $1", username).Scan(&c) err = tx.QueryRow("SELECT count FROM users WHERE name = $1", username).Scan(&c)
if transaction_failed(err) { if transaction_failed(err) {
t.Log("rollback after select", i)
return return
} else { t_err_fatal(t, err) } } else { t_err_fatal(t, err) }
} }
...@@ -92,19 +92,71 @@ func transaction_conflict_t(t *testing.T) { ...@@ -92,19 +92,71 @@ func transaction_conflict_t(t *testing.T) {
t.Log("update", i) t.Log("update", i)
_, err := tx.Exec("UPDATE users SET count = $1 WHERE name = $2", c + uint64(i), username) _, err := tx.Exec("UPDATE users SET count = $1 WHERE name = $2", c + uint64(i), username)
if transaction_failed(err) { if transaction_failed(err) {
t.Log("rollback after update", i)
return return
} else { t_err_fatal(t, err) } } else { t_err_fatal(t, err) }
t.Log("commit", i) t.Log("commit", i)
err = tx.Commit() err = tx.Commit()
if transaction_failed(err) { if transaction_failed(err) {
t.Log("rollback after commit", i)
return return
} else { t_err_fatal(t, err) } } else { t_err_fatal(t, err) }
} }
t.Error("No transaction failure despite concurrent updates!") t.Error("No transaction failure despite interleaved transactions!")
} }
func nested_transactions_t(t *testing.T) {
outer, err := db.Begin()
t_err_fatal(t, err)
defer outer.Rollback()
inner, err := db.Begin()
t_err_fatal(t, err)
defer inner.Rollback()
var c uint64
t_err_fatal(t, outer.QueryRow("SELECT count FROM users WHERE name = $1", username).Scan(&c))
err = inner.QueryRow("SELECT count FROM users WHERE name = $1", username).Scan(&c)
if transaction_failed(err) {
t.Log("rollback after inner.Query")
return
} else { t_err_fatal(t, err) }
t.Log("update inner")
_, err = inner.Exec("UPDATE users SET count = $1 WHERE name = $2", c + 1, username)
if transaction_failed(err) {
t.Log("rollback after inner.Exec")
return
} else { t_err_fatal(t, err) }
err = inner.Commit()
if transaction_failed(err) {
t.Log("rollback after inner.Commit")
return
} else { t_err_fatal(t, err) }
t.Log("update outer")
_, err = outer.Exec("UPDATE users SET count = $1 WHERE name = $2", c + 1, username)
if transaction_failed(err) {
t.Log("rollback after outer.Exec")
return
} else { t_err_fatal(t, err) }
err = outer.Commit()
if transaction_failed(err) {
t.Log("rollback after outer.Commit")
return
} else { t_err_fatal(t, err) }
t.Error("No transaction failure despite nested transactions")
}
func transaction_conflict_t(t *testing.T) {
t.Run("interleaved_transactions_t", interleaved_transactions_t)
t.Run("nested_transactions_t", nested_transactions_t)
}
func check_offer_t(t *testing.T) { func check_offer_t(t *testing.T) {
t.Run("no_such_user", func(t *testing.T) { t.Run("no_such_user", func(t *testing.T) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment