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

Side by Side Diff: service/rawdatastore/serialize_test.go

Issue 1259593005: Add 'user friendly' datastore API. (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: 100% coverage of new code Created 5 years, 4 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
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 rawdatastore
6
7 import (
8 "bytes"
9 "io"
10 "testing"
11 "time"
12
13 "github.com/luci/gae/service/blobstore"
14 "github.com/luci/luci-go/common/cmpbin"
15 . "github.com/smartystreets/goconvey/convey"
16 )
17
18 func init() {
19 WritePropertyMapDeterministic = true
20 }
21
22 type dspmapTC struct {
23 name string
24 props PropertyMap
25 }
26
27 func TestPropertyMapSerialization(t *testing.T) {
28 t.Parallel()
29
30 tests := []dspmapTC{
31 {
32 "basic",
33 PropertyMap{
34 "R": {mp(false), mp(2.1), mpNI(3)},
35 "S": {mp("hello"), mp("world")},
36 },
37 },
38 {
39 "keys",
40 PropertyMap{
41 "DS": {mp(mkKey("appy", "ns", "Foo", 7)), mp(mkKey("other", "", "Yot", "wheeep"))},
42 "blobstore": {mp(blobstore.Key("sup")), mp(blobs tore.Key("nerds"))},
43 },
44 },
45 {
46 "geo",
47 PropertyMap{
48 "G": {mp(GeoPoint{Lat: 1, Lng: 2})},
49 },
50 },
51 {
52 "data",
53 PropertyMap{
54 "S": {mp("sup"), mp("fool"), mp("nerd") },
55 "D.Foo.Nerd": {mp([]byte("sup")), mp([]byte("foo l"))},
56 "B": {mp(ByteString("sup")), mp(ByteStr ing("fool"))},
57 },
58 },
59 {
60 "time",
61 PropertyMap{
62 "T": {
63 mp(time.Now().UTC()),
64 mp(time.Now().Add(time.Second).UTC())},
65 },
66 },
67 {
68 "empty vals",
69 PropertyMap{
70 "T": {mp(true), mp(true)},
71 "F": {mp(false), mp(false)},
72 "N": {mp(nil), mp(nil)},
73 "E": {},
74 },
75 },
76 }
77
78 Convey("PropertyMap serialization", t, func() {
79 Convey("round trip", func() {
80 for _, tc := range tests {
81 tc := tc
82 Convey(tc.name, func() {
83 buf := &bytes.Buffer{}
84 tc.props.Write(buf, WithContext)
85 dec := PropertyMap{}
86 err := dec.Read(buf, WithContext, "", "" )
87 So(err, ShouldBeNil)
88 So(dec, ShouldResemble, tc.props)
89 })
90 }
91 })
92 })
93 }
94
95 func TestSerializationReadMisc(t *testing.T) {
96 t.Parallel()
97
98 Convey("Misc Serialization tests", t, func() {
99 buf := &bytes.Buffer{}
100 Convey("ReadKey", func() {
101 Convey("good cases", func() {
102 Convey("w/ ctx decodes normally w/ ctx", func() {
103 k := mkKey("aid", "ns", "knd", "yo", "ot her", 10)
104 WriteKey(buf, WithContext, k)
105 dk, err := ReadKey(buf, WithContext, "", "")
106 So(err, ShouldBeNil)
107 So(dk, ShouldEqualKey, k)
108 })
109 Convey("w/ ctx decodes normally w/o ctx", func() {
110 k := mkKey("aid", "ns", "knd", "yo", "ot her", 10)
111 WriteKey(buf, WithContext, k)
112 dk, err := ReadKey(buf, WithoutContext, "spam", "nerd")
113 So(err, ShouldBeNil)
114 So(dk, ShouldEqualKey, mkKey("spam", "ne rd", "knd", "yo", "other", 10))
115 })
116 Convey("w/o ctx decodes normally w/ ctx", func() {
117 k := mkKey("aid", "ns", "knd", "yo", "ot her", 10)
118 WriteKey(buf, WithoutContext, k)
119 dk, err := ReadKey(buf, WithContext, "sp am", "nerd")
120 So(err, ShouldBeNil)
121 So(dk, ShouldEqualKey, mkKey("", "", "kn d", "yo", "other", 10))
122 })
123 Convey("w/o ctx decodes normally w/o ctx", func( ) {
124 k := mkKey("aid", "ns", "knd", "yo", "ot her", 10)
125 WriteKey(buf, WithoutContext, k)
126 dk, err := ReadKey(buf, WithoutContext, "spam", "nerd")
127 So(err, ShouldBeNil)
128 So(dk, ShouldEqualKey, mkKey("spam", "ne rd", "knd", "yo", "other", 10))
129 })
130 Convey("IntIDs always sort before StringIDs", fu nc() {
131 // -1 writes as almost all 1's in the fi rst byte under cmpbin, even
132 // though it's technically not a valid k ey.
133 k := mkKey("aid", "ns", "knd", -1)
134 WriteKey(buf, WithoutContext, k)
135
136 k = mkKey("aid", "ns", "knd", "hat")
137 buf2 := &bytes.Buffer{}
138 WriteKey(buf2, WithoutContext, k)
139
140 So(bytes.Compare(buf.Bytes(), buf2.Bytes ()), ShouldBeLessThan, 0)
141 })
142 })
143
144 Convey("err cases", func() {
145 Convey("nil", func() {
146 _, err := ReadKey(buf, WithContext, "", "")
147 So(err, ShouldEqual, io.EOF)
148 })
149 Convey("str", func() {
150 buf.WriteString("sup")
151 _, err := ReadKey(buf, WithContext, "", "")
152 So(err, ShouldErrLike, "expected actualC tx")
153 })
154 Convey("truncated 1", func() {
155 buf.WriteByte(1) // actualCtx == 1
156 _, err := ReadKey(buf, WithContext, "", "")
157 So(err, ShouldEqual, io.EOF)
158 })
159 Convey("truncated 2", func() {
160 buf.WriteByte(1) // actualCtx == 1
161 cmpbin.WriteString(buf, "aid")
162 _, err := ReadKey(buf, WithContext, "", "")
163 So(err, ShouldEqual, io.EOF)
164 })
165 Convey("truncated 3", func() {
166 buf.WriteByte(1) // actualCtx == 1
167 cmpbin.WriteString(buf, "aid")
168 cmpbin.WriteString(buf, "ns")
169 _, err := ReadKey(buf, WithContext, "", "")
170 So(err, ShouldEqual, io.EOF)
171 })
172 Convey("huge key", func() {
173 buf.WriteByte(1) // actualCtx == 1
174 cmpbin.WriteString(buf, "aid")
175 cmpbin.WriteString(buf, "ns")
176 cmpbin.WriteUint(buf, 1000)
177 _, err := ReadKey(buf, WithContext, "", "")
178 So(err, ShouldErrLike, "huge key")
179 })
180 Convey("insufficient tokens", func() {
181 buf.WriteByte(1) // actualCtx == 1
182 cmpbin.WriteString(buf, "aid")
183 cmpbin.WriteString(buf, "ns")
184 cmpbin.WriteUint(buf, 2)
185 _, err := ReadKey(buf, WithContext, "", "")
186 So(err, ShouldEqual, io.EOF)
187 })
188 Convey("partial token 1", func() {
189 buf.WriteByte(1) // actualCtx == 1
190 cmpbin.WriteString(buf, "aid")
191 cmpbin.WriteString(buf, "ns")
192 cmpbin.WriteUint(buf, 2)
193 cmpbin.WriteString(buf, "hi")
194 _, err := ReadKey(buf, WithContext, "", "")
195 So(err, ShouldEqual, io.EOF)
196 })
197 Convey("partial token 2", func() {
198 buf.WriteByte(1) // actualCtx == 1
199 cmpbin.WriteString(buf, "aid")
200 cmpbin.WriteString(buf, "ns")
201 cmpbin.WriteUint(buf, 2)
202 cmpbin.WriteString(buf, "hi")
203 buf.WriteByte(byte(PTString))
204 _, err := ReadKey(buf, WithContext, "", "")
205 So(err, ShouldEqual, io.EOF)
206 })
207 Convey("bad token (invalid type)", func() {
208 buf.WriteByte(1) // actualCtx == 1
209 cmpbin.WriteString(buf, "aid")
210 cmpbin.WriteString(buf, "ns")
211 cmpbin.WriteUint(buf, 2)
212 cmpbin.WriteString(buf, "hi")
213 buf.WriteByte(byte(PTBlobKey))
214 _, err := ReadKey(buf, WithContext, "", "")
215 So(err, ShouldErrLike, "invalid type PTB lobKey")
216 })
217 Convey("bad token (invalid IntID)", func() {
218 buf.WriteByte(1) // actualCtx == 1
219 cmpbin.WriteString(buf, "aid")
220 cmpbin.WriteString(buf, "ns")
221 cmpbin.WriteUint(buf, 2)
222 cmpbin.WriteString(buf, "hi")
223 buf.WriteByte(byte(PTInt))
224 cmpbin.WriteInt(buf, -2)
225 _, err := ReadKey(buf, WithContext, "", "")
226 So(err, ShouldErrLike, "zero/negative")
227 })
228 })
229 })
230
231 Convey("ReadGeoPoint", func() {
232 gp := GeoPoint{}
233 Convey("trunc 1", func() {
234 err := gp.Read(buf)
235 So(err, ShouldEqual, io.EOF)
236 })
237 Convey("trunc 2", func() {
238 cmpbin.WriteFloat64(buf, 100)
239 err := gp.Read(buf)
240 So(err, ShouldEqual, io.EOF)
241 })
242 Convey("invalid", func() {
243 cmpbin.WriteFloat64(buf, 100)
244 cmpbin.WriteFloat64(buf, 1000)
245 err := gp.Read(buf)
246 So(err, ShouldErrLike, "invalid GeoPoint")
247 })
248 })
249
250 Convey("WriteTime", func() {
251 Convey("in non-UTC!", func() {
252 pst, err := time.LoadLocation("America/Los_Angel es")
253 So(err, ShouldBeNil)
254 So(func() {
255 WriteTime(buf, time.Now().In(pst))
256 }, ShouldPanic)
257 })
258 })
259
260 Convey("ReadTime", func() {
261 Convey("trunc 1", func() {
262 _, err := ReadTime(buf)
263 So(err, ShouldEqual, io.EOF)
264 })
265 })
266
267 Convey("ReadProperty", func() {
268 p := Property{}
269 Convey("trunc 1", func() {
270 err := p.Read(buf, WithContext, "", "")
271 So(err, ShouldEqual, io.EOF)
272 So(p.Type(), ShouldEqual, PTNull)
273 So(p.Value(), ShouldBeNil)
274 })
275 Convey("trunc (PTBytes)", func() {
276 buf.WriteByte(byte(PTBytes))
277 err := p.Read(buf, WithContext, "", "")
278 So(err, ShouldEqual, io.EOF)
279 })
280 Convey("trunc (PTBlobKey)", func() {
281 buf.WriteByte(byte(PTBlobKey))
282 err := p.Read(buf, WithContext, "", "")
283 So(err, ShouldEqual, io.EOF)
284 })
285 Convey("invalid type", func() {
286 buf.WriteByte(byte(PTUnknown + 1))
287 err := p.Read(buf, WithContext, "", "")
288 So(err, ShouldErrLike, "unknown type!")
289 })
290 })
291
292 Convey("ReadPropertyMap", func() {
293 pm := PropertyMap{}
294 Convey("trunc 1", func() {
295 err := pm.Read(buf, WithContext, "", "")
296 So(err, ShouldEqual, io.EOF)
297 })
298 Convey("too many rows", func() {
299 cmpbin.WriteUint(buf, 1000000)
300 err := pm.Read(buf, WithContext, "", "")
301 So(err, ShouldErrLike, "huge number of rows")
302 })
303 Convey("trunc 2", func() {
304 cmpbin.WriteUint(buf, 10)
305 err := pm.Read(buf, WithContext, "", "")
306 So(err, ShouldEqual, io.EOF)
307 })
308 Convey("trunc 3", func() {
309 cmpbin.WriteUint(buf, 10)
310 cmpbin.WriteString(buf, "ohai")
311 err := pm.Read(buf, WithContext, "", "")
312 So(err, ShouldEqual, io.EOF)
313 })
314 Convey("too many values", func() {
315 cmpbin.WriteUint(buf, 10)
316 cmpbin.WriteString(buf, "ohai")
317 cmpbin.WriteUint(buf, 100000)
318 err := pm.Read(buf, WithContext, "", "")
319 So(err, ShouldErrLike, "huge number of propertie s")
320 })
321 Convey("trunc 4", func() {
322 cmpbin.WriteUint(buf, 10)
323 cmpbin.WriteString(buf, "ohai")
324 cmpbin.WriteUint(buf, 10)
325 err := pm.Read(buf, WithContext, "", "")
326 So(err, ShouldEqual, io.EOF)
327 })
328 })
329 })
330 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698