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

Side by Side Diff: impl/memory/datastore_index_test.go

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

Powered by Google App Engine
This is Rietveld 408576698