OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 package memory | |
6 | |
7 import ( | |
8 "infra/gae/libs/wrapper" | |
9 "infra/gae/libs/wrapper/unsafe" | |
10 "infra/libs/clock/testclock" | |
11 "testing" | |
12 "time" | |
13 | |
14 . "github.com/smartystreets/goconvey/convey" | |
15 "golang.org/x/net/context" | |
16 | |
17 "appengine/memcache" | |
18 ) | |
19 | |
20 func TestMemcache(t *testing.T) { | |
21 t.Parallel() | |
22 | |
23 Convey("memcache", t, func() { | |
24 now := time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC) | |
25 c, tc := testclock.UseTime(context.Background(), now) | |
26 c = Use(c) | |
27 mc := wrapper.GetMC(c) | |
28 mci := wrapper.GetMC(c).(*memcacheImpl) | |
29 So(mc, ShouldNotEqual, mci) // two impls with the same memcacheD
ata | |
30 | |
31 Convey("implements MCSingleReadWriter", func() { | |
32 Convey("Add", func() { | |
33 itm := &memcache.Item{ | |
34 Key: "sup", | |
35 Value: []byte("cool"), | |
36 Expiration: time.Second, | |
37 } | |
38 err := mc.Add(itm) | |
39 So(err, ShouldBeNil) | |
40 Convey("which rejects objects already there", fu
nc() { | |
41 err := mc.Add(itm) | |
42 So(err, ShouldEqual, memcache.ErrNotStor
ed) | |
43 }) | |
44 | |
45 Convey("which can be broken intentionally", func
() { | |
46 mci.BreakFeatures(nil, "Add") | |
47 err := mc.Add(itm) | |
48 So(err, ShouldEqual, memcache.ErrServerE
rror) | |
49 }) | |
50 }) | |
51 | |
52 Convey("Get", func() { | |
53 itm := &memcache.Item{ | |
54 Key: "sup", | |
55 Value: []byte("cool"), | |
56 Expiration: time.Second, | |
57 } | |
58 err := mc.Add(itm) | |
59 So(err, ShouldBeNil) | |
60 | |
61 testItem := &memcache.Item{ | |
62 Key: "sup", | |
63 Value: []byte("cool"), | |
64 } | |
65 unsafe.MCSetCasID(testItem, 1) | |
66 i, err := mc.Get("sup") | |
67 So(err, ShouldBeNil) | |
68 So(i, ShouldResemble, testItem) | |
69 | |
70 Convey("which can expire", func() { | |
71 tc.Add(time.Second * 4) | |
72 i, err := mc.Get("sup") | |
73 So(err, ShouldEqual, memcache.ErrCacheMi
ss) | |
74 So(i, ShouldBeNil) | |
75 }) | |
76 | |
77 Convey("which can be broken intentionally", func
() { | |
78 mci.BreakFeatures(nil, "Get") | |
79 _, err := mc.Get("sup") | |
80 So(err, ShouldEqual, memcache.ErrServerE
rror) | |
81 }) | |
82 }) | |
83 | |
84 Convey("Delete", func() { | |
85 Convey("works if it's there", func() { | |
86 itm := &memcache.Item{ | |
87 Key: "sup", | |
88 Value: []byte("cool"), | |
89 Expiration: time.Second, | |
90 } | |
91 err := mc.Add(itm) | |
92 So(err, ShouldBeNil) | |
93 | |
94 err = mc.Delete("sup") | |
95 So(err, ShouldBeNil) | |
96 | |
97 i, err := mc.Get("sup") | |
98 So(err, ShouldEqual, memcache.ErrCacheMi
ss) | |
99 So(i, ShouldBeNil) | |
100 }) | |
101 | |
102 Convey("but not if it's not there", func() { | |
103 err := mc.Delete("sup") | |
104 So(err, ShouldEqual, memcache.ErrCacheMi
ss) | |
105 }) | |
106 | |
107 Convey("and can be broken", func() { | |
108 mci.BreakFeatures(nil, "Delete") | |
109 err := mc.Delete("sup") | |
110 So(err, ShouldEqual, memcache.ErrServerE
rror) | |
111 }) | |
112 }) | |
113 | |
114 Convey("Set", func() { | |
115 itm := &memcache.Item{ | |
116 Key: "sup", | |
117 Value: []byte("cool"), | |
118 Expiration: time.Second, | |
119 } | |
120 err := mc.Add(itm) | |
121 So(err, ShouldBeNil) | |
122 | |
123 itm.Value = []byte("newp") | |
124 err = mc.Set(itm) | |
125 So(err, ShouldBeNil) | |
126 | |
127 testItem := &memcache.Item{ | |
128 Key: "sup", | |
129 Value: []byte("newp"), | |
130 } | |
131 unsafe.MCSetCasID(testItem, 2) | |
132 i, err := mc.Get("sup") | |
133 So(err, ShouldBeNil) | |
134 So(i, ShouldResemble, testItem) | |
135 | |
136 Convey("and can be broken", func() { | |
137 mci.BreakFeatures(nil, "Set") | |
138 err := mc.Set(itm) | |
139 So(err, ShouldEqual, memcache.ErrServerE
rror) | |
140 }) | |
141 }) | |
142 | |
143 Convey("CompareAndSwap", func() { | |
144 itm := &memcache.Item{ | |
145 Key: "sup", | |
146 Value: []byte("cool"), | |
147 Expiration: time.Second * 2, | |
148 } | |
149 err := mc.Add(itm) | |
150 So(err, ShouldBeNil) | |
151 | |
152 Convey("works after a Get", func() { | |
153 itm, err = mc.Get("sup") | |
154 So(err, ShouldBeNil) | |
155 So(unsafe.MCGetCasID(itm), ShouldEqual,
1) | |
156 | |
157 itm.Value = []byte("newp") | |
158 err = mc.CompareAndSwap(itm) | |
159 So(err, ShouldBeNil) | |
160 }) | |
161 | |
162 Convey("but fails if you don't", func() { | |
163 itm.Value = []byte("newp") | |
164 err = mc.CompareAndSwap(itm) | |
165 So(err, ShouldEqual, memcache.ErrCASConf
lict) | |
166 }) | |
167 | |
168 Convey("and fails if the item is expired/gone",
func() { | |
169 tc.Add(3 * time.Second) | |
170 itm.Value = []byte("newp") | |
171 err = mc.CompareAndSwap(itm) | |
172 So(err, ShouldEqual, memcache.ErrNotStor
ed) | |
173 }) | |
174 | |
175 Convey("and can be broken", func() { | |
176 mci.BreakFeatures(nil, "CompareAndSwap") | |
177 err = mc.CompareAndSwap(itm) | |
178 So(err, ShouldEqual, memcache.ErrServerE
rror) | |
179 }) | |
180 }) | |
181 }) | |
182 | |
183 Convey("check that the internal implementation is sane", func()
{ | |
184 curTime := now | |
185 err := mc.Add(&memcache.Item{ | |
186 Key: "sup", | |
187 Value: []byte("cool"), | |
188 Expiration: time.Second * 2, | |
189 }) | |
190 | |
191 So(err, ShouldBeNil) | |
192 So(len(mci.data.items), ShouldEqual, 1) | |
193 So(mci.data.casID, ShouldEqual, 1) | |
194 So(mci.data.items["sup"], ShouldResemble, &unsafe.Item{ | |
195 Key: "sup", | |
196 Value: []byte("cool"), | |
197 CasID: 1, | |
198 Expiration: time.Duration(curTime.Add(time.Secon
d * 2).UnixNano()), | |
199 }) | |
200 | |
201 el, err := mc.Get("sup") | |
202 So(err, ShouldBeNil) | |
203 So(len(mci.data.items), ShouldEqual, 1) | |
204 So(mci.data.casID, ShouldEqual, 1) | |
205 | |
206 testItem := &memcache.Item{ | |
207 Key: "sup", | |
208 Value: []byte("cool"), | |
209 } | |
210 unsafe.MCSetCasID(testItem, 1) | |
211 So(el, ShouldResemble, testItem) | |
212 }) | |
213 | |
214 }) | |
215 } | |
OLD | NEW |