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 "testing" | 8 "testing" |
9 "time" | 9 "time" |
10 | 10 |
11 » infoS "github.com/luci/gae/service/info" | 11 » "github.com/luci/gae/service/info" |
12 » mcS "github.com/luci/gae/service/memcache" | 12 » mc "github.com/luci/gae/service/memcache" |
| 13 |
13 "github.com/luci/luci-go/common/clock/testclock" | 14 "github.com/luci/luci-go/common/clock/testclock" |
14 . "github.com/luci/luci-go/common/testing/assertions" | 15 . "github.com/luci/luci-go/common/testing/assertions" |
| 16 |
| 17 "golang.org/x/net/context" |
| 18 |
15 . "github.com/smartystreets/goconvey/convey" | 19 . "github.com/smartystreets/goconvey/convey" |
16 "golang.org/x/net/context" | |
17 ) | 20 ) |
18 | 21 |
19 func TestMemcache(t *testing.T) { | 22 func TestMemcache(t *testing.T) { |
20 t.Parallel() | 23 t.Parallel() |
21 | 24 |
22 Convey("memcache", t, func() { | 25 Convey("memcache", t, func() { |
23 now := time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC) | 26 now := time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC) |
24 c, tc := testclock.UseTime(context.Background(), now) | 27 c, tc := testclock.UseTime(context.Background(), now) |
25 c = Use(c) | 28 c = Use(c) |
26 mc := mcS.Get(c) | |
27 | 29 |
28 Convey("implements MCSingleReadWriter", func() { | 30 Convey("implements MCSingleReadWriter", func() { |
29 Convey("Add", func() { | 31 Convey("Add", func() { |
30 » » » » itm := (mc.NewItem("sup"). | 32 » » » » itm := (mc.NewItem(c, "sup"). |
31 SetValue([]byte("cool")). | 33 SetValue([]byte("cool")). |
32 SetExpiration(time.Second)) | 34 SetExpiration(time.Second)) |
33 » » » » So(mc.Add(itm), ShouldBeNil) | 35 » » » » So(mc.Add(c, itm), ShouldBeNil) |
34 Convey("which rejects objects already there", fu
nc() { | 36 Convey("which rejects objects already there", fu
nc() { |
35 » » » » » So(mc.Add(itm), ShouldEqual, mcS.ErrNotS
tored) | 37 » » » » » So(mc.Add(c, itm), ShouldEqual, mc.ErrNo
tStored) |
36 }) | 38 }) |
37 }) | 39 }) |
38 | 40 |
39 Convey("Get", func() { | 41 Convey("Get", func() { |
40 itm := &mcItem{ | 42 itm := &mcItem{ |
41 key: "sup", | 43 key: "sup", |
42 value: []byte("cool"), | 44 value: []byte("cool"), |
43 expiration: time.Second, | 45 expiration: time.Second, |
44 } | 46 } |
45 » » » » So(mc.Add(itm), ShouldBeNil) | 47 » » » » So(mc.Add(c, itm), ShouldBeNil) |
46 | 48 |
47 testItem := &mcItem{ | 49 testItem := &mcItem{ |
48 key: "sup", | 50 key: "sup", |
49 value: []byte("cool"), | 51 value: []byte("cool"), |
50 CasID: 1, | 52 CasID: 1, |
51 } | 53 } |
52 » » » » getItm, err := mc.Get("sup") | 54 » » » » getItm, err := mc.GetKey(c, "sup") |
53 So(err, ShouldBeNil) | 55 So(err, ShouldBeNil) |
54 So(getItm, ShouldResemble, testItem) | 56 So(getItm, ShouldResemble, testItem) |
55 | 57 |
56 Convey("which can expire", func() { | 58 Convey("which can expire", func() { |
57 tc.Add(time.Second * 4) | 59 tc.Add(time.Second * 4) |
58 » » » » » getItm, err := mc.Get("sup") | 60 » » » » » getItm, err := mc.GetKey(c, "sup") |
59 » » » » » So(err, ShouldEqual, mcS.ErrCacheMiss) | 61 » » » » » So(err, ShouldEqual, mc.ErrCacheMiss) |
60 So(getItm, ShouldResemble, &mcItem{key:
"sup"}) | 62 So(getItm, ShouldResemble, &mcItem{key:
"sup"}) |
61 }) | 63 }) |
62 }) | 64 }) |
63 | 65 |
64 Convey("Delete", func() { | 66 Convey("Delete", func() { |
65 Convey("works if it's there", func() { | 67 Convey("works if it's there", func() { |
66 itm := &mcItem{ | 68 itm := &mcItem{ |
67 key: "sup", | 69 key: "sup", |
68 value: []byte("cool"), | 70 value: []byte("cool"), |
69 expiration: time.Second, | 71 expiration: time.Second, |
70 } | 72 } |
71 » » » » » So(mc.Add(itm), ShouldBeNil) | 73 » » » » » So(mc.Add(c, itm), ShouldBeNil) |
72 | 74 |
73 » » » » » So(mc.Delete("sup"), ShouldBeNil) | 75 » » » » » So(mc.Delete(c, "sup"), ShouldBeNil) |
74 | 76 |
75 » » » » » _, err := mc.Get("sup") | 77 » » » » » _, err := mc.GetKey(c, "sup") |
76 » » » » » So(err, ShouldEqual, mcS.ErrCacheMiss) | 78 » » » » » So(err, ShouldEqual, mc.ErrCacheMiss) |
77 }) | 79 }) |
78 | 80 |
79 Convey("but not if it's not there", func() { | 81 Convey("but not if it's not there", func() { |
80 » » » » » So(mc.Delete("sup"), ShouldEqual, mcS.Er
rCacheMiss) | 82 » » » » » So(mc.Delete(c, "sup"), ShouldEqual, mc.
ErrCacheMiss) |
81 }) | 83 }) |
82 }) | 84 }) |
83 | 85 |
84 Convey("Set", func() { | 86 Convey("Set", func() { |
85 itm := &mcItem{ | 87 itm := &mcItem{ |
86 key: "sup", | 88 key: "sup", |
87 value: []byte("cool"), | 89 value: []byte("cool"), |
88 expiration: time.Second, | 90 expiration: time.Second, |
89 } | 91 } |
90 » » » » So(mc.Add(itm), ShouldBeNil) | 92 » » » » So(mc.Add(c, itm), ShouldBeNil) |
91 | 93 |
92 itm.SetValue([]byte("newp")) | 94 itm.SetValue([]byte("newp")) |
93 » » » » So(mc.Set(itm), ShouldBeNil) | 95 » » » » So(mc.Set(c, itm), ShouldBeNil) |
94 | 96 |
95 testItem := &mcItem{ | 97 testItem := &mcItem{ |
96 key: "sup", | 98 key: "sup", |
97 value: []byte("newp"), | 99 value: []byte("newp"), |
98 CasID: 2, | 100 CasID: 2, |
99 } | 101 } |
100 » » » » getItm, err := mc.Get("sup") | 102 » » » » getItm, err := mc.GetKey(c, "sup") |
101 So(err, ShouldBeNil) | 103 So(err, ShouldBeNil) |
102 So(getItm, ShouldResemble, testItem) | 104 So(getItm, ShouldResemble, testItem) |
103 | 105 |
104 Convey("Flush works too", func() { | 106 Convey("Flush works too", func() { |
105 » » » » » So(mc.Flush(), ShouldBeNil) | 107 » » » » » So(mc.Flush(c), ShouldBeNil) |
106 » » » » » _, err := mc.Get("sup") | 108 » » » » » _, err := mc.GetKey(c, "sup") |
107 » » » » » So(err, ShouldEqual, mcS.ErrCacheMiss) | 109 » » » » » So(err, ShouldEqual, mc.ErrCacheMiss) |
108 }) | 110 }) |
109 }) | 111 }) |
110 | 112 |
111 Convey("Set (nil) is equivalent to Set([]byte{})", func(
) { | 113 Convey("Set (nil) is equivalent to Set([]byte{})", func(
) { |
112 » » » » So(mc.Set(mc.NewItem("bob")), ShouldBeNil) | 114 » » » » So(mc.Set(c, mc.NewItem(c, "bob")), ShouldBeNil) |
113 | 115 |
114 » » » » bob, err := mc.Get("bob") | 116 » » » » bob, err := mc.GetKey(c, "bob") |
115 So(err, ShouldBeNil) | 117 So(err, ShouldBeNil) |
116 So(bob.Value(), ShouldResemble, []byte{}) | 118 So(bob.Value(), ShouldResemble, []byte{}) |
117 }) | 119 }) |
118 | 120 |
119 Convey("Increment", func() { | 121 Convey("Increment", func() { |
120 » » » » val, err := mc.Increment("num", 7, 2) | 122 » » » » val, err := mc.Increment(c, "num", 7, 2) |
121 So(err, ShouldBeNil) | 123 So(err, ShouldBeNil) |
122 So(val, ShouldEqual, 9) | 124 So(val, ShouldEqual, 9) |
123 | 125 |
124 Convey("IncrementExisting", func() { | 126 Convey("IncrementExisting", func() { |
125 » » » » » val, err := mc.IncrementExisting("num",
-2) | 127 » » » » » val, err := mc.IncrementExisting(c, "num
", -2) |
126 So(err, ShouldBeNil) | 128 So(err, ShouldBeNil) |
127 So(val, ShouldEqual, 7) | 129 So(val, ShouldEqual, 7) |
128 | 130 |
129 » » » » » val, err = mc.IncrementExisting("num", -
100) | 131 » » » » » val, err = mc.IncrementExisting(c, "num"
, -100) |
130 So(err, ShouldBeNil) | 132 So(err, ShouldBeNil) |
131 So(val, ShouldEqual, 0) | 133 So(val, ShouldEqual, 0) |
132 | 134 |
133 » » » » » _, err = mc.IncrementExisting("noexist",
2) | 135 » » » » » _, err = mc.IncrementExisting(c, "noexis
t", 2) |
134 » » » » » So(err, ShouldEqual, mcS.ErrCacheMiss) | 136 » » » » » So(err, ShouldEqual, mc.ErrCacheMiss) |
135 | 137 |
136 » » » » » So(mc.Set(mc.NewItem("text").SetValue([]
byte("hello world, hooman!"))), ShouldBeNil) | 138 » » » » » So(mc.Set(c, mc.NewItem(c, "text").SetVa
lue([]byte("hello world, hooman!"))), ShouldBeNil) |
137 | 139 |
138 » » » » » _, err = mc.IncrementExisting("text", 2) | 140 » » » » » _, err = mc.IncrementExisting(c, "text",
2) |
139 So(err.Error(), ShouldContainSubstring,
"got invalid current value") | 141 So(err.Error(), ShouldContainSubstring,
"got invalid current value") |
140 }) | 142 }) |
141 }) | 143 }) |
142 | 144 |
143 Convey("CompareAndSwap", func() { | 145 Convey("CompareAndSwap", func() { |
144 » » » » itm := mcS.Item(&mcItem{ | 146 » » » » itm := mc.Item(&mcItem{ |
145 key: "sup", | 147 key: "sup", |
146 value: []byte("cool"), | 148 value: []byte("cool"), |
147 expiration: time.Second * 2, | 149 expiration: time.Second * 2, |
148 }) | 150 }) |
149 » » » » So(mc.Add(itm), ShouldBeNil) | 151 » » » » So(mc.Add(c, itm), ShouldBeNil) |
150 | 152 |
151 Convey("works after a Get", func() { | 153 Convey("works after a Get", func() { |
152 » » » » » itm, err := mc.Get("sup") | 154 » » » » » itm, err := mc.GetKey(c, "sup") |
153 So(err, ShouldBeNil) | 155 So(err, ShouldBeNil) |
154 So(itm.(*mcItem).CasID, ShouldEqual, 1) | 156 So(itm.(*mcItem).CasID, ShouldEqual, 1) |
155 | 157 |
156 itm.SetValue([]byte("newp")) | 158 itm.SetValue([]byte("newp")) |
157 » » » » » So(mc.CompareAndSwap(itm), ShouldBeNil) | 159 » » » » » So(mc.CompareAndSwap(c, itm), ShouldBeNi
l) |
158 }) | 160 }) |
159 | 161 |
160 Convey("but fails if you don't", func() { | 162 Convey("but fails if you don't", func() { |
161 itm.SetValue([]byte("newp")) | 163 itm.SetValue([]byte("newp")) |
162 » » » » » So(mc.CompareAndSwap(itm), ShouldEqual,
mcS.ErrCASConflict) | 164 » » » » » So(mc.CompareAndSwap(c, itm), ShouldEqua
l, mc.ErrCASConflict) |
163 }) | 165 }) |
164 | 166 |
165 Convey("and fails if the item is expired/gone",
func() { | 167 Convey("and fails if the item is expired/gone",
func() { |
166 tc.Add(3 * time.Second) | 168 tc.Add(3 * time.Second) |
167 itm.SetValue([]byte("newp")) | 169 itm.SetValue([]byte("newp")) |
168 » » » » » So(mc.CompareAndSwap(itm), ShouldEqual,
mcS.ErrNotStored) | 170 » » » » » So(mc.CompareAndSwap(c, itm), ShouldEqua
l, mc.ErrNotStored) |
169 }) | 171 }) |
170 }) | 172 }) |
171 }) | 173 }) |
172 | 174 |
173 Convey("check that the internal implementation is sane", func()
{ | 175 Convey("check that the internal implementation is sane", func()
{ |
174 curTime := now | 176 curTime := now |
175 » » » err := mc.Add(&mcItem{ | 177 » » » err := mc.Add(c, &mcItem{ |
176 key: "sup", | 178 key: "sup", |
177 value: []byte("cool"), | 179 value: []byte("cool"), |
178 expiration: time.Second * 2, | 180 expiration: time.Second * 2, |
179 }) | 181 }) |
180 | 182 |
181 for i := 0; i < 4; i++ { | 183 for i := 0; i < 4; i++ { |
182 » » » » _, err := mc.Get("sup") | 184 » » » » _, err := mc.GetKey(c, "sup") |
183 So(err, ShouldBeNil) | 185 So(err, ShouldBeNil) |
184 } | 186 } |
185 » » » _, err = mc.Get("wot") | 187 » » » _, err = mc.GetKey(c, "wot") |
186 » » » So(err, ShouldErrLike, mcS.ErrCacheMiss) | 188 » » » So(err, ShouldErrLike, mc.ErrCacheMiss) |
187 | 189 |
188 » » » mci := mc.Raw().(*memcacheImpl) | 190 » » » mci := mc.Raw(c).(*memcacheImpl) |
189 | 191 |
190 » » » stats, err := mc.Stats() | 192 » » » stats, err := mc.Stats(c) |
191 So(err, ShouldBeNil) | 193 So(err, ShouldBeNil) |
192 So(stats.Items, ShouldEqual, 1) | 194 So(stats.Items, ShouldEqual, 1) |
193 So(stats.Bytes, ShouldEqual, 4) | 195 So(stats.Bytes, ShouldEqual, 4) |
194 So(stats.Hits, ShouldEqual, 4) | 196 So(stats.Hits, ShouldEqual, 4) |
195 So(stats.Misses, ShouldEqual, 1) | 197 So(stats.Misses, ShouldEqual, 1) |
196 So(stats.ByteHits, ShouldEqual, 4*4) | 198 So(stats.ByteHits, ShouldEqual, 4*4) |
197 So(mci.data.casID, ShouldEqual, 1) | 199 So(mci.data.casID, ShouldEqual, 1) |
198 So(mci.data.items["sup"], ShouldResemble, &mcDataItem{ | 200 So(mci.data.items["sup"], ShouldResemble, &mcDataItem{ |
199 value: []byte("cool"), | 201 value: []byte("cool"), |
200 expiration: curTime.Add(time.Second * 2).Truncat
e(time.Second), | 202 expiration: curTime.Add(time.Second * 2).Truncat
e(time.Second), |
201 casID: 1, | 203 casID: 1, |
202 }) | 204 }) |
203 | 205 |
204 » » » getItm, err := mc.Get("sup") | 206 » » » getItm, err := mc.GetKey(c, "sup") |
205 So(err, ShouldBeNil) | 207 So(err, ShouldBeNil) |
206 So(len(mci.data.items), ShouldEqual, 1) | 208 So(len(mci.data.items), ShouldEqual, 1) |
207 So(mci.data.casID, ShouldEqual, 1) | 209 So(mci.data.casID, ShouldEqual, 1) |
208 | 210 |
209 testItem := &mcItem{ | 211 testItem := &mcItem{ |
210 key: "sup", | 212 key: "sup", |
211 value: []byte("cool"), | 213 value: []byte("cool"), |
212 CasID: 1, | 214 CasID: 1, |
213 } | 215 } |
214 So(getItm, ShouldResemble, testItem) | 216 So(getItm, ShouldResemble, testItem) |
215 }) | 217 }) |
216 | 218 |
217 Convey("When adding an item to an unset namespace", func() { | 219 Convey("When adding an item to an unset namespace", func() { |
218 » » » _, has := infoS.Get(c).GetNamespace() | 220 » » » So(info.GetNamespace(c), ShouldEqual, "") |
219 » » » So(has, ShouldBeFalse) | |
220 | 221 |
221 » » » item := mc.NewItem("foo").SetValue([]byte("heya")) | 222 » » » item := mc.NewItem(c, "foo").SetValue([]byte("heya")) |
222 » » » So(mc.Set(item), ShouldBeNil) | 223 » » » So(mc.Set(c, item), ShouldBeNil) |
223 | 224 |
224 Convey("The item can be retrieved from the unset namespa
ce.", func() { | 225 Convey("The item can be retrieved from the unset namespa
ce.", func() { |
225 » » » » got, err := mc.Get("foo") | 226 » » » » got, err := mc.GetKey(c, "foo") |
226 So(err, ShouldBeNil) | 227 So(err, ShouldBeNil) |
227 So(got.Value(), ShouldResemble, []byte("heya")) | 228 So(got.Value(), ShouldResemble, []byte("heya")) |
228 }) | 229 }) |
229 | 230 |
230 Convey("The item can be retrieved from a set, empty name
space.", func() { | 231 Convey("The item can be retrieved from a set, empty name
space.", func() { |
231 // Now test with empty namespace. | 232 // Now test with empty namespace. |
232 » » » » c = infoS.Get(c).MustNamespace("") | 233 » » » » c = info.MustNamespace(c, "") |
233 | 234 |
234 » » » » got, err := mc.Get("foo") | 235 » » » » got, err := mc.GetKey(c, "foo") |
235 So(err, ShouldBeNil) | 236 So(err, ShouldBeNil) |
236 So(got.Value(), ShouldResemble, []byte("heya")) | 237 So(got.Value(), ShouldResemble, []byte("heya")) |
237 }) | 238 }) |
238 }) | 239 }) |
239 }) | 240 }) |
240 } | 241 } |
OLD | NEW |