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

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

Issue 2604943002: impl/memory: Replace gkvlite with "treapstore". (Closed)
Patch Set: Comments. Created 3 years, 11 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/gkvlite_iter.go ('k') | impl/memory/gkvlite_tracing_utils.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 LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file.
4
5 package memory
6
7 import (
8 "bytes"
9 "testing"
10
11 "github.com/luci/gae/service/datastore"
12 "github.com/luci/gae/service/datastore/serialize"
13 "github.com/luci/gkvlite"
14 "github.com/luci/luci-go/common/data/cmpbin"
15 . "github.com/smartystreets/goconvey/convey"
16 )
17
18 func mkNum(n int64) []byte {
19 buf := &bytes.Buffer{}
20 _, err := cmpbin.WriteInt(buf, n)
21 memoryCorruption(err)
22
23 return buf.Bytes()
24 }
25
26 func readNum(data []byte) int64 {
27 ret, _, err := cmpbin.ReadInt(bytes.NewBuffer(data))
28 memoryCorruption(err)
29
30 return ret
31 }
32
33 func TestIterator(t *testing.T) {
34 t.Parallel()
35
36 s := newMemStore()
37 c := s.GetOrCreateCollection("zup")
38 prev := []byte{}
39 for i := 5; i < 100; i++ {
40 data := mkNum(int64(i))
41 c.Set(data, prev)
42 prev = data
43 }
44 c = s.Snapshot().GetCollection("zup")
45
46 get := func(c C, t *iterator) interface{} {
47 ret := interface{}(nil)
48 t.next(nil, func(i *gkvlite.Item) {
49 if i != nil {
50 ret = readNum(i.Key)
51 }
52 })
53 return ret
54 }
55
56 skipGet := func(c C, t *iterator, skipTo int64) interface{} {
57 ret := interface{}(nil)
58 t.next(mkNum(skipTo), func(i *gkvlite.Item) {
59 if i != nil {
60 ret = readNum(i.Key)
61 }
62 })
63 return ret
64 }
65
66 Convey("Test iterator", t, func() {
67 Convey("start at nil", func(ctx C) {
68 t := (&iterDefinition{c: c}).mkIter()
69 defer t.stop()
70 So(get(ctx, t), ShouldEqual, 5)
71 So(get(ctx, t), ShouldEqual, 6)
72 So(get(ctx, t), ShouldEqual, 7)
73
74 Convey("And can skip", func(ctx C) {
75 So(skipGet(ctx, t, 10), ShouldEqual, 10)
76 So(get(ctx, t), ShouldEqual, 11)
77
78 Convey("But not forever", func(ctx C) {
79 t.next(mkNum(200), func(i *gkvlite.Item) {
80 ctx.So(i, ShouldBeNil)
81 })
82 t.next(nil, func(i *gkvlite.Item) {
83 ctx.So(i, ShouldBeNil)
84 })
85 })
86 })
87
88 Convey("Can iterate explicitly", func(ctx C) {
89 So(skipGet(ctx, t, 7), ShouldEqual, 8)
90 So(skipGet(ctx, t, 8), ShouldEqual, 9)
91
92 // Giving the immediately next key doesn't cause an internal reset.
93 So(skipGet(ctx, t, 10), ShouldEqual, 10)
94 })
95
96 Convey("Can stop", func(ctx C) {
97 t.stop()
98 t.next(mkNum(200), func(i *gkvlite.Item) {
99 ctx.So(i, ShouldBeNil)
100 })
101 t.next(nil, func(i *gkvlite.Item) {
102 ctx.So(i, ShouldBeNil)
103 })
104 So(t.stop, ShouldNotPanic)
105 })
106
107 Convey("Going backwards is ignored", func(ctx C) {
108 So(skipGet(ctx, t, 3), ShouldEqual, 8)
109 So(get(ctx, t), ShouldEqual, 9)
110 So(skipGet(ctx, t, 20), ShouldEqual, 20)
111 So(get(ctx, t), ShouldEqual, 21)
112 })
113
114 Convey("will stop at the end of the list", func(ctx C) {
115 So(skipGet(ctx, t, 95), ShouldEqual, 95)
116 So(get(ctx, t), ShouldEqual, 96)
117 So(get(ctx, t), ShouldEqual, 97)
118 So(get(ctx, t), ShouldEqual, 98)
119 So(get(ctx, t), ShouldEqual, 99)
120 So(get(ctx, t), ShouldBeNil)
121 So(get(ctx, t), ShouldBeNil)
122 })
123 })
124
125 Convey("can have caps on both sides", func(ctx C) {
126 t := (&iterDefinition{c: c, start: mkNum(20), end: mkNum (25)}).mkIter()
127 So(get(ctx, t), ShouldEqual, 20)
128 So(get(ctx, t), ShouldEqual, 21)
129 So(get(ctx, t), ShouldEqual, 22)
130 So(get(ctx, t), ShouldEqual, 23)
131 So(get(ctx, t), ShouldEqual, 24)
132 t.next(nil, func(i *gkvlite.Item) {
133 ctx.So(i, ShouldBeNil)
134 })
135 })
136
137 Convey("can skip over starting cap", func(ctx C) {
138 t := (&iterDefinition{c: c, start: mkNum(20), end: mkNum (25)}).mkIter()
139 So(skipGet(ctx, t, 22), ShouldEqual, 22)
140 So(get(ctx, t), ShouldEqual, 23)
141 So(get(ctx, t), ShouldEqual, 24)
142 t.next(nil, func(i *gkvlite.Item) {
143 ctx.So(i, ShouldBeNil)
144 })
145 })
146
147 })
148 }
149
150 func TestMultiIteratorSimple(t *testing.T) {
151 t.Parallel()
152
153 // Simulate an index with 2 columns (int and int).
154 vals := [][]int64{
155 {1, 0},
156 {1, 2},
157 {1, 4},
158 {1, 7},
159 {1, 9},
160 {3, 10},
161 {3, 11},
162 }
163
164 valBytes := make([][]byte, len(vals))
165 for i, nms := range vals {
166 numbs := make([][]byte, len(nms))
167 for j, n := range nms {
168 numbs[j] = mkNum(n)
169 }
170 valBytes[i] = serialize.Join(numbs...)
171 }
172
173 otherVals := [][]int64{
174 {3, 0},
175 {4, 10},
176 {19, 7},
177 {20, 2},
178 {20, 3},
179 {20, 4},
180 {20, 8},
181 {20, 11},
182 }
183
184 otherValBytes := make([][]byte, len(otherVals))
185 for i, nms := range otherVals {
186 numbs := make([][]byte, len(nms))
187 for i, n := range nms {
188 numbs[i] = mkNum(n)
189 }
190 otherValBytes[i] = serialize.Join(numbs...)
191 }
192
193 Convey("Test MultiIterator", t, func() {
194 s := newMemStore()
195 c := s.GetOrCreateCollection("zup1")
196 for _, row := range valBytes {
197 c.Set(row, []byte{})
198 }
199 c2 := s.GetOrCreateCollection("zup2")
200 for _, row := range otherValBytes {
201 c2.Set(row, []byte{})
202 }
203 c = s.Snapshot().GetCollection("zup1")
204 c2 = s.Snapshot().GetCollection("zup2")
205
206 Convey("can join the same collection twice", func() {
207 // get just the (1, *)
208 // starting at (1, 2) (i.e. >= 2)
209 // ending at (1, 4) (i.e. < 7)
210 defs := []*iterDefinition{
211 {c: c, prefix: mkNum(1), prefixLen: len(mkNum(1) ), start: mkNum(2), end: mkNum(7)},
212 {c: c, prefix: mkNum(1), prefixLen: len(mkNum(1) ), start: mkNum(2), end: mkNum(7)},
213 }
214
215 i := 1
216 So(multiIterate(defs, func(suffix []byte) error {
217 So(readNum(suffix), ShouldEqual, vals[i][1])
218 i++
219 return nil
220 }), shouldBeSuccessful)
221
222 So(i, ShouldEqual, 3)
223 })
224
225 Convey("can make empty iteration", func() {
226 // get just the (20, *) (doesn't exist)
227 defs := []*iterDefinition{
228 {c: c, prefix: mkNum(20)},
229 {c: c, prefix: mkNum(20)},
230 }
231
232 i := 0
233 So(multiIterate(defs, func(suffix []byte) error {
234 panic("never")
235 }), shouldBeSuccessful)
236
237 So(i, ShouldEqual, 0)
238 })
239
240 Convey("can join (other, val, val)", func() {
241 // 'other' must start with 20, 'vals' must start with 1
242 // no range constraints
243 defs := []*iterDefinition{
244 {c: c2, prefix: mkNum(20)},
245 {c: c, prefix: mkNum(1)},
246 {c: c, prefix: mkNum(1)},
247 }
248
249 expect := []int64{2, 4}
250 i := 0
251 So(multiIterate(defs, func(suffix []byte) error {
252 So(readNum(suffix), ShouldEqual, expect[i])
253 i++
254 return nil
255 }), shouldBeSuccessful)
256 })
257
258 Convey("Can stop early", func() {
259 defs := []*iterDefinition{
260 {c: c, prefix: mkNum(1), prefixLen: len(mkNum(1) )},
261 {c: c, prefix: mkNum(1), prefixLen: len(mkNum(1) )},
262 }
263
264 i := 0
265 So(multiIterate(defs, func(suffix []byte) error {
266 So(readNum(suffix), ShouldEqual, vals[i][1])
267 i++
268 return nil
269 }), shouldBeSuccessful)
270 So(i, ShouldEqual, 5)
271
272 i = 0
273 So(multiIterate(defs, func(suffix []byte) error {
274 So(readNum(suffix), ShouldEqual, vals[i][1])
275 i++
276 return datastore.Stop
277 }), shouldBeSuccessful)
278 So(i, ShouldEqual, 1)
279 })
280
281 })
282
283 }
OLDNEW
« no previous file with comments | « impl/memory/gkvlite_iter.go ('k') | impl/memory/gkvlite_tracing_utils.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698