OLD | NEW |
1 // Copyright 2015 The LUCI Authors. All rights reserved. | 1 // Copyright 2015 The LUCI Authors. All rights reserved. |
2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
4 | 4 |
5 package memory | 5 package memory |
6 | 6 |
7 import ( | 7 import ( |
8 "sync" | 8 "sync" |
9 "sync/atomic" | 9 "sync/atomic" |
10 "testing" | 10 "testing" |
11 | 11 |
12 » "github.com/luci/gae/service/datastore" | 12 » ds "github.com/luci/gae/service/datastore" |
| 13 |
13 "golang.org/x/net/context" | 14 "golang.org/x/net/context" |
14 ) | 15 ) |
15 | 16 |
16 func TestRaceGetPut(t *testing.T) { | 17 func TestRaceGetPut(t *testing.T) { |
17 t.Parallel() | 18 t.Parallel() |
18 | 19 |
19 value := int32(0) | 20 value := int32(0) |
20 num := int32(0) | 21 num := int32(0) |
21 | 22 |
22 » ds := datastore.Get(Use(context.Background())) | 23 » c := Use(context.Background()) |
23 | 24 |
24 wg := sync.WaitGroup{} | 25 wg := sync.WaitGroup{} |
25 | 26 |
26 for i := 0; i < 100; i++ { | 27 for i := 0; i < 100; i++ { |
27 wg.Add(1) | 28 wg.Add(1) |
28 go func() { | 29 go func() { |
29 defer wg.Done() | 30 defer wg.Done() |
30 | 31 |
31 » » » err := ds.RunInTransaction(func(c context.Context) error
{ | 32 » » » err := ds.RunInTransaction(c, func(c context.Context) er
ror { |
32 atomic.AddInt32(&num, 1) | 33 atomic.AddInt32(&num, 1) |
33 | 34 |
34 » » » » ds := datastore.Get(c) | 35 » » » » obj := pmap("$key", ds.MakeKey(c, "Obj", 1)) |
35 | 36 » » » » if err := ds.Get(c, obj); err != nil && err != d
s.ErrNoSuchEntity { |
36 » » » » obj := pmap("$key", ds.MakeKey("Obj", 1)) | |
37 » » » » if err := ds.Get(obj); err != nil && err != data
store.ErrNoSuchEntity { | |
38 t.Fatal("error get", err) | 37 t.Fatal("error get", err) |
39 } | 38 } |
40 cur := int64(0) | 39 cur := int64(0) |
41 if ps := obj.Slice("Value"); len(ps) > 0 { | 40 if ps := obj.Slice("Value"); len(ps) > 0 { |
42 cur = ps[0].Value().(int64) | 41 cur = ps[0].Value().(int64) |
43 } | 42 } |
44 | 43 |
45 cur++ | 44 cur++ |
46 obj["Value"] = prop(cur) | 45 obj["Value"] = prop(cur) |
47 | 46 |
48 » » » » return ds.Put(obj) | 47 » » » » return ds.Put(c, obj) |
49 » » » }, &datastore.TransactionOptions{Attempts: 200}) | 48 » » » }, &ds.TransactionOptions{Attempts: 200}) |
50 | 49 |
51 if err != nil { | 50 if err != nil { |
52 t.Fatal("error during transaction", err) | 51 t.Fatal("error during transaction", err) |
53 } | 52 } |
54 | 53 |
55 atomic.AddInt32(&value, 1) | 54 atomic.AddInt32(&value, 1) |
56 }() | 55 }() |
57 } | 56 } |
58 wg.Wait() | 57 wg.Wait() |
59 | 58 |
60 » obj := pmap("$key", ds.MakeKey("Obj", 1)) | 59 » obj := pmap("$key", ds.MakeKey(c, "Obj", 1)) |
61 » if ds.Get(obj) != nil { | 60 » if ds.Get(c, obj) != nil { |
62 t.FailNow() | 61 t.FailNow() |
63 } | 62 } |
64 t.Logf("Ran %d inner functions", num) | 63 t.Logf("Ran %d inner functions", num) |
65 if int64(value) != obj.Slice("Value")[0].Value().(int64) { | 64 if int64(value) != obj.Slice("Value")[0].Value().(int64) { |
66 t.Fatalf("value wrong value %d v %d", value, obj.Slice("Value")[
0].Value().(int64)) | 65 t.Fatalf("value wrong value %d v %d", value, obj.Slice("Value")[
0].Value().(int64)) |
67 } | 66 } |
68 } | 67 } |
69 | 68 |
70 func TestRaceNonConflictingPuts(t *testing.T) { | 69 func TestRaceNonConflictingPuts(t *testing.T) { |
71 t.Parallel() | 70 t.Parallel() |
72 | 71 |
73 » ds := datastore.Get(Use(context.Background())) | 72 » c := Use(context.Background()) |
74 | 73 |
75 num := int32(0) | 74 num := int32(0) |
76 | 75 |
77 wg := sync.WaitGroup{} | 76 wg := sync.WaitGroup{} |
78 | 77 |
79 for i := 0; i < 100; i++ { | 78 for i := 0; i < 100; i++ { |
80 wg.Add(1) | 79 wg.Add(1) |
81 go func() { | 80 go func() { |
82 defer wg.Done() | 81 defer wg.Done() |
83 | 82 |
84 » » » err := ds.RunInTransaction(func(c context.Context) error
{ | 83 » » » err := ds.RunInTransaction(c, func(c context.Context) er
ror { |
85 » » » » ds := datastore.Get(c) | 84 » » » » return ds.Put(c, pmap( |
86 » » » » return ds.Put(pmap( | |
87 "$kind", "Thing", Next, | 85 "$kind", "Thing", Next, |
88 "Value", 100)) | 86 "Value", 100)) |
89 }, nil) | 87 }, nil) |
90 if err != nil { | 88 if err != nil { |
91 t.Fatal("error during transaction", err) | 89 t.Fatal("error during transaction", err) |
92 } | 90 } |
93 atomic.AddInt32(&num, 1) | 91 atomic.AddInt32(&num, 1) |
94 }() | 92 }() |
95 } | 93 } |
96 wg.Wait() | 94 wg.Wait() |
97 | 95 |
98 if num != 100 { | 96 if num != 100 { |
99 t.Fatal("expected 100 runs, got", num) | 97 t.Fatal("expected 100 runs, got", num) |
100 } | 98 } |
101 } | 99 } |
OLD | NEW |