Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(94)

Side by Side Diff: go/src/infra/gae/libs/memlock/memlock_test.go

Issue 1233413002: Simplify memlock and make it less racy. (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package memlock 5 package memlock
6 6
7 import ( 7 import (
8 "fmt" 8 "fmt"
9 "runtime"
10 "testing" 9 "testing"
11 "time" 10 "time"
12 11
13 "infra/gae/libs/gae" 12 "infra/gae/libs/gae"
14 "infra/gae/libs/gae/filters/featureBreaker" 13 "infra/gae/libs/gae/filters/featureBreaker"
15 "infra/gae/libs/gae/memory" 14 "infra/gae/libs/gae/memory"
16 15
17 "github.com/luci/luci-go/common/clock" 16 "github.com/luci/luci-go/common/clock"
18 "github.com/luci/luci-go/common/clock/testclock" 17 "github.com/luci/luci-go/common/clock/testclock"
19 . "github.com/smartystreets/goconvey/convey" 18 . "github.com/smartystreets/goconvey/convey"
(...skipping 19 matching lines...) Expand all
39 select { 38 select {
40 case blocker <- struct{}{}: 39 case blocker <- struct{}{}:
41 default: 40 default:
42 } 41 }
43 }) 42 })
44 ctx, fb := featureBreaker.FilterMC(memory.Use(ctx), nil) 43 ctx, fb := featureBreaker.FilterMC(memory.Use(ctx), nil)
45 mc := gae.GetMC(ctx) 44 mc := gae.GetMC(ctx)
46 45
47 Convey("fails to acquire when memcache is down", func() { 46 Convey("fails to acquire when memcache is down", func() {
48 fb.BreakFeatures(nil, "Add") 47 fb.BreakFeatures(nil, "Add")
49 » » » err := TryWithLock(ctx, "testkey", "id", func(check func () bool) error { 48 » » » err := TryWithLock(ctx, "testkey", "id", func(context.Co ntext) error {
50 // should never reach here 49 // should never reach here
51 So(false, ShouldBeTrue) 50 So(false, ShouldBeTrue)
52 return nil 51 return nil
53 }) 52 })
54 So(err, ShouldEqual, ErrFailedToLock) 53 So(err, ShouldEqual, ErrFailedToLock)
55 }) 54 })
56 55
57 Convey("returns the inner error", func() { 56 Convey("returns the inner error", func() {
58 toRet := fmt.Errorf("sup") 57 toRet := fmt.Errorf("sup")
59 » » » err := TryWithLock(ctx, "testkey", "id", func(check func () bool) error { 58 » » » err := TryWithLock(ctx, "testkey", "id", func(context.Co ntext) error {
60 return toRet 59 return toRet
61 }) 60 })
62 So(err, ShouldEqual, toRet) 61 So(err, ShouldEqual, toRet)
63 }) 62 })
64 63
65 Convey("returns the error", func() { 64 Convey("returns the error", func() {
66 toRet := fmt.Errorf("sup") 65 toRet := fmt.Errorf("sup")
67 » » » err := TryWithLock(ctx, "testkey", "id", func(check func () bool) error { 66 » » » err := TryWithLock(ctx, "testkey", "id", func(context.Co ntext) error {
68 return toRet 67 return toRet
69 }) 68 })
70 So(err, ShouldEqual, toRet) 69 So(err, ShouldEqual, toRet)
71 }) 70 })
72 71
73 Convey("can acquire when empty", func() { 72 Convey("can acquire when empty", func() {
74 » » » err := TryWithLock(ctx, "testkey", "id", func(check func () bool) error { 73 » » » err := TryWithLock(ctx, "testkey", "id", func(ctx contex t.Context) error {
75 » » » » So(check(), ShouldBeTrue) 74 » » » » isDone := func() bool {
75 » » » » » select {
76 » » » » » case <-ctx.Done():
77 » » » » » » return true
78 » » » » » default:
79 » » » » » » return false
80 » » » » » }
81 » » » » }
82
83 » » » » So(isDone(), ShouldBeFalse)
76 84
77 waitFalse := func() { 85 waitFalse := func() {
78 » » » » » <-blocker 86 » » » » loop:
79 » » » » » for i := 0; i < 3; i++ { 87 » » » » » for {
80 » » » » » » if check() { 88 » » » » » » select {
81 » » » » » » » runtime.Gosched() 89 » » » » » » case <-blocker:
90 » » » » » » » continue
91 » » » » » » case <-ctx.Done():
92 » » » » » » » break loop
82 } 93 }
83 } 94 }
84 » » » » » So(check(), ShouldBeFalse) 95 » » » » » So(isDone(), ShouldBeTrue)
85 } 96 }
86 97
87 Convey("waiting for a while keeps refreshing the lock", func() { 98 Convey("waiting for a while keeps refreshing the lock", func() {
88 // simulate waiting for 64*delay time, a nd ensuring that checkLoop 99 // simulate waiting for 64*delay time, a nd ensuring that checkLoop
89 // runs that many times. 100 // runs that many times.
90 for i := 0; i < 64; i++ { 101 for i := 0; i < 64; i++ {
91 <-blocker 102 <-blocker
92 clk.Add(delay) 103 clk.Add(delay)
93 } 104 }
94 » » » » » So(check(), ShouldBeTrue) 105 » » » » » So(isDone(), ShouldBeFalse)
95 }) 106 })
96 107
97 Convey("but sometimes we might lose it", func() { 108 Convey("but sometimes we might lose it", func() {
98 Convey("because it was evicted", func() { 109 Convey("because it was evicted", func() {
99 mc.Delete(key) 110 mc.Delete(key)
100 clk.Add(memcacheLockTime) 111 clk.Add(memcacheLockTime)
101 waitFalse() 112 waitFalse()
102 }) 113 })
103 114
104 Convey("or because it was stolen", func( ) { 115 Convey("or because it was stolen", func( ) {
105 mc.Set(mc.NewItem(key).SetValue( []byte("wat"))) 116 mc.Set(mc.NewItem(key).SetValue( []byte("wat")))
106 waitFalse() 117 waitFalse()
107 }) 118 })
108 119
109 Convey("or because of service issues", f unc() { 120 Convey("or because of service issues", f unc() {
110 fb.BreakFeatures(nil, "CompareAn dSwap") 121 fb.BreakFeatures(nil, "CompareAn dSwap")
111 waitFalse() 122 waitFalse()
112 }) 123 })
113 }) 124 })
114 return nil 125 return nil
115 }) 126 })
116 So(err, ShouldBeNil) 127 So(err, ShouldBeNil)
117 }) 128 })
118 129
119 Convey("an empty context id is an error", func() { 130 Convey("an empty context id is an error", func() {
120 So(TryWithLock(ctx, "testkey", "", nil), ShouldEqual, Er rEmptyClientID) 131 So(TryWithLock(ctx, "testkey", "", nil), ShouldEqual, Er rEmptyClientID)
121 }) 132 })
122 }) 133 })
123 } 134 }
OLDNEW
« go/src/infra/gae/libs/memlock/memlock.go ('K') | « go/src/infra/gae/libs/memlock/memlock.go ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698