Index: filter/txnBuf/race_test.go |
diff --git a/filter/txnBuf/race_test.go b/filter/txnBuf/race_test.go |
new file mode 100644 |
index 0000000000000000000000000000000000000000..8ad0734954a42754ee532b89ce411fd57fcdbdd9 |
--- /dev/null |
+++ b/filter/txnBuf/race_test.go |
@@ -0,0 +1,62 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+package txnBuf |
+ |
+import ( |
+ "sync" |
+ "testing" |
+ |
+ "github.com/luci/gae/impl/memory" |
+ "github.com/luci/gae/service/datastore" |
+ "golang.org/x/net/context" |
+) |
+ |
+type Counter struct { |
+ ID int64 `gae:"$id"` |
+ |
+ Value int64 |
+} |
+ |
+func TestRace(t *testing.T) { |
+ t.Parallel() |
+ |
+ c := FilterRDS(memory.Use(context.Background())) |
+ ds := datastore.Get(c) |
+ |
+ wg := sync.WaitGroup{} |
+ for i := 0; i < 100; i++ { |
+ id := int64(i + 1) |
+ |
+ wg.Add(1) |
+ go func() { |
+ defer wg.Done() |
+ err := ds.RunInTransaction(func(c context.Context) error { |
+ ds := datastore.Get(c) |
+ |
+ for i := 0; i < 100; i++ { |
+ err := ds.RunInTransaction(func(c context.Context) error { |
+ ds := datastore.Get(c) |
+ |
+ ctr := &Counter{ID: id} |
+ if err := ds.Get(ctr); err != nil && err != datastore.ErrNoSuchEntity { |
+ t.Fatal("bad Get", err) |
+ } |
+ ctr.Value++ |
+ return ds.Put(ctr) |
+ }, nil) |
+ if err != nil { |
+ t.Fatal("bad inner RIT", err) |
+ } |
+ } |
+ |
+ return nil |
+ }, nil) |
+ if err != nil { |
+ t.Fatal("bad outer RIT", err) |
+ } |
+ }() |
+ } |
+ wg.Wait() |
+} |