OLD | NEW |
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 Loading... |
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 } |
OLD | NEW |