Chromium Code Reviews| Index: impl/memory/race_test.go |
| diff --git a/impl/memory/race_test.go b/impl/memory/race_test.go |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..713e6cab04e6b9b5719175f5c7ecab1b67435a8b |
| --- /dev/null |
| +++ b/impl/memory/race_test.go |
| @@ -0,0 +1,101 @@ |
| +// 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 memory |
| + |
| +import ( |
| + "sync" |
| + "sync/atomic" |
| + "testing" |
| + |
| + "github.com/luci/gae/service/datastore" |
| + "golang.org/x/net/context" |
| +) |
| + |
| +func TestRaceGetPut(t *testing.T) { |
| + t.Parallel() |
| + |
| + value := new(int64) |
|
dnj
2015/11/10 00:20:20
nit: int64(0), use &value elsewhere.
iannucci
2015/11/11 18:13:58
*shrug*
|
| + num := new(int64) |
| + |
| + ds := datastore.Get(Use(context.Background())) |
| + |
| + wg := sync.WaitGroup{} |
| + |
| + for i := 0; i < 100; i++ { |
| + wg.Add(1) |
| + go func() { |
| + defer wg.Done() |
| + |
| + err := ds.RunInTransaction(func(c context.Context) error { |
| + atomic.AddInt64(num, 1) |
| + |
| + ds := datastore.Get(c) |
| + |
| + obj := pmap("$key", ds.MakeKey("Obj", 1)) |
| + if err := ds.Get(obj); err != nil && err != datastore.ErrNoSuchEntity { |
| + t.Fatal("error get", err) |
| + } |
| + cur := int64(0) |
| + if ps, ok := obj["Value"]; ok { |
| + cur = ps[0].Value().(int64) |
| + } |
| + |
| + cur++ |
| + obj["Value"] = []datastore.Property{prop(cur)} |
| + |
| + return ds.Put(obj) |
| + }, &datastore.TransactionOptions{Attempts: 200}) |
| + |
| + if err != nil { |
| + t.Fatal("error during transaction", err) |
| + } |
| + |
| + atomic.AddInt64(value, 1) |
|
dnj
2015/11/10 00:20:20
This may break on 32-bit systems b/c not allocated
iannucci
2015/11/11 18:13:58
it's allocated so it's fine
|
| + }() |
| + } |
| + wg.Wait() |
| + |
| + obj := pmap("$key", ds.MakeKey("Obj", 1)) |
| + if ds.Get(obj) != nil { |
| + t.FailNow() |
| + } |
| + t.Logf("Ran %d inner functions", *num) |
| + if *value != obj["Value"][0].Value().(int64) { |
| + t.Fatalf("value wrong value %d v %d", *value, obj["Value"][0].Value().(int64)) |
| + } |
| +} |
| + |
| +func TestRaceNonConflictingPuts(t *testing.T) { |
| + t.Parallel() |
| + |
| + ds := datastore.Get(Use(context.Background())) |
| + |
| + num := new(int64) |
|
dnj
2015/11/10 00:20:20
int64(0)
|
| + |
| + wg := sync.WaitGroup{} |
| + |
| + for i := 0; i < 100; i++ { |
| + wg.Add(1) |
| + go func() { |
| + defer wg.Done() |
| + |
| + err := ds.RunInTransaction(func(c context.Context) error { |
| + ds := datastore.Get(c) |
| + return ds.Put(pmap( |
| + "$kind", "Thing", Next, |
| + "Value", 100)) |
| + }, nil) |
| + if err != nil { |
| + t.Fatal("error during transaction", err) |
| + } |
| + atomic.AddInt64(num, 1) |
| + }() |
| + } |
| + wg.Wait() |
| + |
| + if *num != 100 { |
| + t.Fatal("expected 100 runs, got", *num) |
| + } |
| +} |