Index: impl/memory/datastore_test.go |
diff --git a/impl/memory/datastore_test.go b/impl/memory/datastore_test.go |
index 4cfffbd47b97c04341501b6d7980fe02cb86fb2f..2f969989e39fbb27c02665623e540f3dedea70e0 100644 |
--- a/impl/memory/datastore_test.go |
+++ b/impl/memory/datastore_test.go |
@@ -301,7 +301,7 @@ func TestDatastoreSingleReadWriter(t *testing.T) { |
So(f.Val, ShouldEqual, 10) // still gets 10 |
return nil |
- }, nil) |
+ }, &dsS.TransactionOptions{Attempts: 1}) |
So(err.Error(), ShouldContainSubstring, "concurrent") |
f := &Foo{Id: 1} |
@@ -333,7 +333,7 @@ func TestDatastoreSingleReadWriter(t *testing.T) { |
Convey("Concurrent transactions only accept one set of changes", func() { |
// Note: I think this implementation is actually /slightly/ wrong. |
- // Accorting to my read of the docs for appengine, when you open a |
+ // According to my read of the docs for appengine, when you open a |
// transaction it actually (essentially) holds a reference to the |
// entire datastore. Our implementation takes a snapshot of the |
// entity group as soon as something observes/affects it. |
@@ -417,9 +417,63 @@ func TestDatastoreSingleReadWriter(t *testing.T) { |
So(f.Val, ShouldEqual, 10) |
}) |
}) |
+ |
+ Convey("Transaction retries", func() { |
+ tst := ds.Raw().Testable() |
+ Reset(func() { tst.SetTransactionRetryCount(0) }) |
+ |
+ Convey("SetTransactionRetryCount set to zere", func() { |
+ tst.SetTransactionRetryCount(0) |
+ calls := 0 |
+ So(ds.RunInTransaction(func(c context.Context) error { |
+ calls++ |
+ return nil |
+ }, nil), ShouldBeNil) |
+ So(calls, ShouldEqual, 1) |
+ }) |
+ |
+ Convey("default TransactionOptions is 3 attempts", func() { |
+ tst.SetTransactionRetryCount(100) // more than 3 |
+ calls := 0 |
+ So(ds.RunInTransaction(func(c context.Context) error { |
+ calls++ |
+ return nil |
+ }, nil), ShouldEqual, dsS.ErrConcurrentTransaction) |
+ So(calls, ShouldEqual, 3) |
+ }) |
+ |
+ Convey("non-default TransactionOptions ", func() { |
+ tst.SetTransactionRetryCount(100) // more than 20 |
+ calls := 0 |
+ So(ds.RunInTransaction(func(c context.Context) error { |
+ calls++ |
+ return nil |
+ }, &dsS.TransactionOptions{Attempts: 20}), ShouldEqual, dsS.ErrConcurrentTransaction) |
+ So(calls, ShouldEqual, 20) |
+ }) |
+ |
+ Convey("SetTransactionRetryCount is respected", func() { |
+ tst.SetTransactionRetryCount(1) // less than 3 |
+ calls := 0 |
+ So(ds.RunInTransaction(func(c context.Context) error { |
+ calls++ |
+ return nil |
+ }, nil), ShouldBeNil) |
+ So(calls, ShouldEqual, 2) |
+ }) |
+ |
+ Convey("fatal errors are not retried", func() { |
+ tst.SetTransactionRetryCount(1) |
+ calls := 0 |
+ So(ds.RunInTransaction(func(c context.Context) error { |
+ calls++ |
+ return fmt.Errorf("omg") |
+ }, nil).Error(), ShouldEqual, "omg") |
+ So(calls, ShouldEqual, 1) |
+ }) |
+ }) |
}) |
}) |
- |
}) |
} |