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

Side by Side Diff: memory/plist_test.go

Issue 1243323002: Refactor a bit. (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: fix golint 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
« no previous file with comments | « memory/plist.go ('k') | memory/raw_datastore.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 "testing"
9 "time"
10
11 "github.com/luci/gae"
12 "github.com/luci/gkvlite"
13 . "github.com/smartystreets/goconvey/convey"
14 )
15
16 func init() {
17 indexCreationDeterministic = true
18 }
19
20 var fakeKey = key("knd", 10, key("parentKind", "sid"))
21
22 func TestCollated(t *testing.T) {
23 t.Parallel()
24
25 Convey("TestCollated", t, func() {
26 Convey("nil list", func() {
27 pm := (gae.DSPropertyMap)(nil)
28 sip := partiallySerialize(pm)
29 So(sip, ShouldBeNil)
30
31 Convey("nil collated", func() {
32 Convey("defaultIndicies", func() {
33 idxs := defaultIndicies("knd", pm)
34 So(len(idxs), ShouldEqual, 1)
35 So(idxs[0].String(), ShouldEqual, "B:knd ")
36 })
37 Convey("indexEntries", func() {
38 s := sip.indexEntries(fakeKey, defaultIn dicies("knd", pm))
39 numItems, _ := s.GetCollection("idx").Ge tTotals()
40 So(numItems, ShouldEqual, 1)
41 itm := s.GetCollection("idx").MinItem(fa lse)
42 So(itm.Key, ShouldResemble, cat(indx("kn d")))
43 numItems, _ = s.GetCollection("idx:ns:" + string(itm.Key)).GetTotals()
44 So(numItems, ShouldEqual, 1)
45 })
46 })
47 })
48
49 Convey("list", func() {
50 pm := gae.DSPropertyMap{
51 "wat": {propNI("thing"), prop("hat"), prop(100) },
52 "nerd": {prop(103.7)},
53 "spaz": {propNI(false)},
54 }
55 sip := partiallySerialize(pm)
56 So(len(sip), ShouldEqual, 2)
57
58 Convey("single collated", func() {
59 Convey("indexableMap", func() {
60 So(sip, ShouldResemble, serializedIndexa blePmap{
61 "wat": {
62 cat(gae.DSPTInt, 100),
63 cat(gae.DSPTString, "hat "),
64 // 'thing' is skipped, b ecause it's not NoIndex
65 },
66 "nerd": {
67 cat(gae.DSPTFloat, 103.7 ),
68 },
69 })
70 })
71 Convey("defaultIndicies", func() {
72 idxs := defaultIndicies("knd", pm)
73 So(len(idxs), ShouldEqual, 5)
74 So(idxs[0].String(), ShouldEqual, "B:knd ")
75 So(idxs[1].String(), ShouldEqual, "B:knd /-nerd")
76 So(idxs[2].String(), ShouldEqual, "B:knd /-wat")
77 So(idxs[3].String(), ShouldEqual, "B:knd /nerd")
78 So(idxs[4].String(), ShouldEqual, "B:knd /wat")
79 })
80 })
81 })
82 })
83 }
84
85 var rgenComplexTime = time.Date(
86 1986, time.October, 26, 1, 20, 00, 00, time.UTC)
87 var rgenComplexKey = key("kind", "id")
88
89 var rowGenTestCases = []struct {
90 name string
91 pmap gae.DSPropertyMap
92 withBuiltin bool
93 idxs []*qIndex
94
95 // These are checked in TestIndexRowGen. nil to skip test case.
96 expected []serializedPvals
97
98 // just the collections you want to assert. These are checked in
99 // TestIndexEntries. nil to skip test case.
100 collections map[string][]kv
101 }{
102 {
103 name: "simple including builtins",
104 pmap: gae.DSPropertyMap{
105 "wat": {propNI("thing"), prop("hat"), prop(100)},
106 "nerd": {prop(103.7)},
107 "spaz": {propNI(false)},
108 },
109 withBuiltin: true,
110 idxs: []*qIndex{
111 indx("knd", "-wat", "nerd"),
112 },
113 expected: []serializedPvals{
114 {{}}, // B:knd
115 {icat(gae.DSPTFloat, 103.7)}, / / B:knd/-nerd
116 {icat(gae.DSPTString, "hat"), icat(gae.DSPTInt, 100)}, / / B:knd/-wat
117 {cat(gae.DSPTFloat, 103.7)}, / / B:knd/nerd
118 {cat(gae.DSPTInt, 100), cat(gae.DSPTString, "hat")}, / / B:knd/wat
119 { // B:knd/-wat/nerd
120 cat(icat(gae.DSPTString, "hat"), cat(gae.DSPTFlo at, 103.7)),
121 cat(icat(gae.DSPTInt, 100), cat(gae.DSPTFloat, 1 03.7)),
122 },
123 },
124 collections: map[string][]kv{
125 "idx": {
126 // 0 == builtin, 1 == complex
127 {cat(byte(0), "knd", byte(1), 0), []byte{}},
128 {cat(byte(0), "knd", byte(1), 1, byte(0), "nerd" ), []byte{}},
129 {cat(byte(0), "knd", byte(1), 1, byte(0), "wat") , []byte{}},
130 {cat(byte(0), "knd", byte(1), 1, byte(1), "nerd" ), []byte{}},
131 {cat(byte(0), "knd", byte(1), 1, byte(1), "wat") , []byte{}},
132 {cat(byte(1), "knd", byte(1), 2, byte(1), "wat", byte(0), "nerd"), []byte{}},
133 },
134 "idx:ns:" + sat(indx("knd")): {
135 {cat(fakeKey), []byte{}},
136 },
137 "idx:ns:" + sat(indx("knd", "wat")): {
138 {cat(gae.DSPTInt, 100, fakeKey), []byte{}},
139 {cat(gae.DSPTString, "hat", fakeKey), cat(gae.DS PTInt, 100)},
140 },
141 "idx:ns:" + sat(indx("knd", "-wat")): {
142 {cat(icat(gae.DSPTString, "hat"), fakeKey), []by te{}},
143 {cat(icat(gae.DSPTInt, 100), fakeKey), icat(gae. DSPTString, "hat")},
144 },
145 },
146 },
147 {
148 name: "complex",
149 pmap: gae.DSPropertyMap{
150 "yerp": {prop("hat"), prop(73.9)},
151 "wat": {
152 prop(rgenComplexTime),
153 prop(gae.DSByteString("value")),
154 prop(rgenComplexKey)},
155 "spaz": {prop(nil), prop(false), prop(true)},
156 },
157 idxs: []*qIndex{
158 indx("knd", "-wat", "nerd", "spaz"), // doesn't match, s o empty
159 indx("knd", "yerp", "-wat", "spaz"),
160 },
161 expected: []serializedPvals{
162 {}, // C:knd/-wat/nerd/spaz, no match
163 { // C:knd/yerp/-wat/spaz
164 // thank goodness the binary serialization only happens 1/val in the
165 // real code :).
166 cat(cat(gae.DSPTString, "hat"), icat(gae.DSPTKey , rgenComplexKey), cat(gae.DSPTNull)),
167 cat(cat(gae.DSPTString, "hat"), icat(gae.DSPTKey , rgenComplexKey), cat(gae.DSPTBoolFalse)),
168 cat(cat(gae.DSPTString, "hat"), icat(gae.DSPTKey , rgenComplexKey), cat(gae.DSPTBoolTrue)),
169 cat(cat(gae.DSPTString, "hat"), icat(gae.DSPTByt es, "value"), cat(gae.DSPTNull)),
170 cat(cat(gae.DSPTString, "hat"), icat(gae.DSPTByt es, "value"), cat(gae.DSPTBoolFalse)),
171 cat(cat(gae.DSPTString, "hat"), icat(gae.DSPTByt es, "value"), cat(gae.DSPTBoolTrue)),
172 cat(cat(gae.DSPTString, "hat"), icat(gae.DSPTTim e, rgenComplexTime), cat(gae.DSPTNull)),
173 cat(cat(gae.DSPTString, "hat"), icat(gae.DSPTTim e, rgenComplexTime), cat(gae.DSPTBoolFalse)),
174 cat(cat(gae.DSPTString, "hat"), icat(gae.DSPTTim e, rgenComplexTime), cat(gae.DSPTBoolTrue)),
175
176 cat(cat(gae.DSPTFloat, 73.9), icat(gae.DSPTKey, rgenComplexKey), cat(gae.DSPTNull)),
177 cat(cat(gae.DSPTFloat, 73.9), icat(gae.DSPTKey, rgenComplexKey), cat(gae.DSPTBoolFalse)),
178 cat(cat(gae.DSPTFloat, 73.9), icat(gae.DSPTKey, rgenComplexKey), cat(gae.DSPTBoolTrue)),
179 cat(cat(gae.DSPTFloat, 73.9), icat(gae.DSPTBytes , "value"), cat(gae.DSPTNull)),
180 cat(cat(gae.DSPTFloat, 73.9), icat(gae.DSPTBytes , "value"), cat(gae.DSPTBoolFalse)),
181 cat(cat(gae.DSPTFloat, 73.9), icat(gae.DSPTBytes , "value"), cat(gae.DSPTBoolTrue)),
182 cat(cat(gae.DSPTFloat, 73.9), icat(gae.DSPTTime, rgenComplexTime), cat(gae.DSPTNull)),
183 cat(cat(gae.DSPTFloat, 73.9), icat(gae.DSPTTime, rgenComplexTime), cat(gae.DSPTBoolFalse)),
184 cat(cat(gae.DSPTFloat, 73.9), icat(gae.DSPTTime, rgenComplexTime), cat(gae.DSPTBoolTrue)),
185 },
186 },
187 },
188 {
189 name: "ancestor",
190 pmap: gae.DSPropertyMap{
191 "wat": {prop("sup")},
192 },
193 idxs: []*qIndex{
194 indx("knd!", "wat"),
195 },
196 collections: map[string][]kv{
197 "idx:ns:" + sat(indx("knd!", "wat")): {
198 {cat(fakeKey.Parent(), gae.DSPTString, "sup", fa keKey), []byte{}},
199 {cat(fakeKey, gae.DSPTString, "sup", fakeKey), [ ]byte{}},
200 },
201 },
202 },
203 }
204
205 func TestIndexRowGen(t *testing.T) {
206 t.Parallel()
207
208 Convey("Test Index Row Generation", t, func() {
209 for _, tc := range rowGenTestCases {
210 if tc.expected == nil {
211 Convey(tc.name, nil) // shows up as 'skipped'
212 continue
213 }
214
215 Convey(tc.name, func() {
216 mvals := partiallySerialize(tc.pmap)
217 idxs := []*qIndex(nil)
218 if tc.withBuiltin {
219 idxs = append(defaultIndicies("coolKind" , tc.pmap), tc.idxs...)
220 } else {
221 idxs = tc.idxs
222 }
223
224 m := matcher{}
225 for i, idx := range idxs {
226 Convey(idx.String(), func() {
227 iGen, ok := m.match(idx, mvals)
228 if len(tc.expected[i]) > 0 {
229 So(ok, ShouldBeTrue)
230 j := 0
231 iGen.permute(func(row [] byte) {
232 So([]byte(row), ShouldResemble, tc.expected[i][j])
233 j++
234 })
235 So(j, ShouldEqual, len(t c.expected[i]))
236 } else {
237 So(ok, ShouldBeFalse)
238 }
239 })
240 }
241 })
242 }
243 })
244 }
245
246 func TestIndexEntries(t *testing.T) {
247 t.Parallel()
248
249 Convey("Test indexEntriesWithBuiltins", t, func() {
250 for _, tc := range rowGenTestCases {
251 if tc.collections == nil {
252 Convey(tc.name, nil) // shows up as 'skipped'
253 continue
254 }
255
256 Convey(tc.name, func() {
257 store := (*memStore)(nil)
258 if tc.withBuiltin {
259 store = indexEntriesWithBuiltins(fakeKey , tc.pmap, tc.idxs)
260 } else {
261 store = partiallySerialize(tc.pmap).inde xEntries(fakeKey, tc.idxs)
262 }
263 for colName, vals := range tc.collections {
264 i := 0
265 store.GetCollection(colName).VisitItemsA scend(nil, true, func(itm *gkvlite.Item) bool {
266 So(itm.Key, ShouldResemble, vals [i].k)
267 So(itm.Val, ShouldResemble, vals [i].v)
268 i++
269 return true
270 })
271 So(i, ShouldEqual, len(vals))
272 }
273 })
274 }
275 })
276 }
277
278 type dumbItem struct {
279 key gae.DSKey
280 props gae.DSPropertyMap
281 }
282
283 var updateIndiciesTests = []struct {
284 name string
285 idxs []*qIndex
286 data []dumbItem
287 expected map[string][][]byte
288 }{
289 {
290 name: "basic",
291 data: []dumbItem{
292 {key("knd", 1), gae.DSPropertyMap{
293 "wat": {prop(10)},
294 "yerp": {prop(10)}},
295 },
296 {key("knd", 10), gae.DSPropertyMap{
297 "wat": {prop(1)},
298 "yerp": {prop(200)}},
299 },
300 {key("knd", 1), gae.DSPropertyMap{
301 "wat": {prop(10)},
302 "yerp": {prop(202)}},
303 },
304 },
305 expected: map[string][][]byte{
306 "idx:ns:" + sat(indx("knd", "wat")): {
307 cat(gae.DSPTInt, 1, key("knd", 10)),
308 cat(gae.DSPTInt, 10, key("knd", 1)),
309 },
310 "idx:ns:" + sat(indx("knd", "-wat")): {
311 cat(icat(gae.DSPTInt, 10), key("knd", 1)),
312 cat(icat(gae.DSPTInt, 1), key("knd", 10)),
313 },
314 "idx:ns:" + sat(indx("knd", "yerp")): {
315 cat(gae.DSPTInt, 200, key("knd", 10)),
316 cat(gae.DSPTInt, 202, key("knd", 1)),
317 },
318 },
319 },
320 {
321 name: "compound",
322 idxs: []*qIndex{indx("knd", "yerp", "-wat")},
323 data: []dumbItem{
324 {key("knd", 1), gae.DSPropertyMap{
325 "wat": {prop(10)},
326 "yerp": {prop(100)}},
327 },
328 {key("knd", 10), gae.DSPropertyMap{
329 "wat": {prop(1)},
330 "yerp": {prop(200)}},
331 },
332 {key("knd", 11), gae.DSPropertyMap{
333 "wat": {prop(20)},
334 "yerp": {prop(200)}},
335 },
336 {key("knd", 14), gae.DSPropertyMap{
337 "wat": {prop(20)},
338 "yerp": {prop(200)}},
339 },
340 {key("knd", 1), gae.DSPropertyMap{
341 "wat": {prop(10)},
342 "yerp": {prop(202)}},
343 },
344 },
345 expected: map[string][][]byte{
346 "idx:ns:" + sat(indx("knd", "yerp", "-wat")): {
347 cat(gae.DSPTInt, 200, icat(gae.DSPTInt, 20), key ("knd", 11)),
348 cat(gae.DSPTInt, 200, icat(gae.DSPTInt, 20), key ("knd", 14)),
349 cat(gae.DSPTInt, 200, icat(gae.DSPTInt, 1), key( "knd", 10)),
350 cat(gae.DSPTInt, 202, icat(gae.DSPTInt, 10), key ("knd", 1)),
351 },
352 },
353 },
354 }
355
356 func TestUpdateIndicies(t *testing.T) {
357 t.Parallel()
358
359 Convey("Test updateIndicies", t, func() {
360 for _, tc := range updateIndiciesTests {
361 Convey(tc.name, func() {
362 store := newMemStore()
363 idxColl := store.SetCollection("idx", nil)
364 for _, i := range tc.idxs {
365 idxColl.Set(cat(i), []byte{})
366 }
367
368 tmpLoader := map[string]gae.DSPropertyMap{}
369 for _, itm := range tc.data {
370 ks := itm.key.String()
371 prev := tmpLoader[ks]
372 updateIndicies(store, itm.key, prev, itm .props)
373 tmpLoader[ks] = itm.props
374 }
375 tmpLoader = nil
376
377 for colName, data := range tc.expected {
378 coll := store.GetCollection(colName)
379 So(coll, ShouldNotBeNil)
380 i := 0
381 coll.VisitItemsAscend(nil, false, func(i tm *gkvlite.Item) bool {
382 So(data[i], ShouldResemble, itm. Key)
383 i++
384 return true
385 })
386 So(i, ShouldEqual, len(data))
387 }
388 })
389 }
390 })
391 }
OLDNEW
« no previous file with comments | « memory/plist.go ('k') | memory/raw_datastore.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698