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 helper | |
6 | |
7 import ( | |
8 "bytes" | |
9 "io" | |
10 "testing" | |
11 "time" | |
12 | |
13 "github.com/luci/gae" | |
14 "github.com/luci/luci-go/common/cmpbin" | |
15 . "github.com/smartystreets/goconvey/convey" | |
16 ) | |
17 | |
18 func init() { | |
19 WriteDSPropertyMapDeterministic = true | |
20 } | |
21 | |
22 type dspmapTC struct { | |
23 name string | |
24 props gae.DSPropertyMap | |
25 } | |
26 | |
27 func TestDSPropertyMapSerialization(t *testing.T) { | |
28 t.Parallel() | |
29 | |
30 tests := []dspmapTC{ | |
31 { | |
32 "basic", | |
33 gae.DSPropertyMap{ | |
34 "R": {mp(false), mp(2.1), mpNI(3)}, | |
35 "S": {mp("hello"), mp("world")}, | |
36 }, | |
37 }, | |
38 { | |
39 "keys", | |
40 gae.DSPropertyMap{ | |
41 "DS": {mp(mkKey("appy", "ns", "Foo", 7)), mp(mkK
ey("other", "", "Yot", "wheeep"))}, | |
42 "BS": {mp(gae.BSKey("sup")), mp(gae.BSKey("nerds
"))}, | |
43 }, | |
44 }, | |
45 { | |
46 "geo", | |
47 gae.DSPropertyMap{ | |
48 "G": {mp(gae.DSGeoPoint{Lat: 1, Lng: 2})}, | |
49 }, | |
50 }, | |
51 { | |
52 "data", | |
53 gae.DSPropertyMap{ | |
54 "S": {mp("sup"), mp("fool"), mp("nerd")
}, | |
55 "D.Foo.Nerd": {mp([]byte("sup")), mp([]byte("foo
l"))}, | |
56 "B": {mp(gae.DSByteString("sup")), mp(g
ae.DSByteString("fool"))}, | |
57 }, | |
58 }, | |
59 { | |
60 "time", | |
61 gae.DSPropertyMap{ | |
62 "T": { | |
63 mp(time.Now().UTC()), | |
64 mp(time.Now().Add(time.Second).UTC())}, | |
65 }, | |
66 }, | |
67 { | |
68 "empty vals", | |
69 gae.DSPropertyMap{ | |
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("DSPropertyMap 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 WriteDSPropertyMap(buf, tc.props, WithCo
ntext) | |
85 dec, err := ReadDSPropertyMap(buf, WithC
ontext, "", "") | |
86 So(err, ShouldBeNil) | |
87 So(dec, ShouldResemble, tc.props) | |
88 }) | |
89 } | |
90 }) | |
91 }) | |
92 } | |
93 | |
94 func TestSerializationReadMisc(t *testing.T) { | |
95 t.Parallel() | |
96 | |
97 Convey("Misc Serialization tests", t, func() { | |
98 Convey("ReadDSKey", func() { | |
99 Convey("good cases", func() { | |
100 Convey("w/ ctx decodes normally w/ ctx", func()
{ | |
101 k := mkKey("aid", "ns", "knd", "yo", "ot
her", 10) | |
102 buf := &bytes.Buffer{} | |
103 WriteDSKey(buf, WithContext, k) | |
104 dk, err := ReadDSKey(buf, WithContext, "
", "") | |
105 So(err, ShouldBeNil) | |
106 So(dk, ShouldEqualKey, k) | |
107 }) | |
108 Convey("w/ ctx decodes normally w/o ctx", func()
{ | |
109 k := mkKey("aid", "ns", "knd", "yo", "ot
her", 10) | |
110 buf := &bytes.Buffer{} | |
111 WriteDSKey(buf, WithContext, k) | |
112 dk, err := ReadDSKey(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 buf := &bytes.Buffer{} | |
119 WriteDSKey(buf, WithoutContext, k) | |
120 dk, err := ReadDSKey(buf, WithContext, "
spam", "nerd") | |
121 So(err, ShouldBeNil) | |
122 So(dk, ShouldEqualKey, mkKey("", "", "kn
d", "yo", "other", 10)) | |
123 }) | |
124 Convey("w/o ctx decodes normally w/o ctx", func(
) { | |
125 k := mkKey("aid", "ns", "knd", "yo", "ot
her", 10) | |
126 buf := &bytes.Buffer{} | |
127 WriteDSKey(buf, WithoutContext, k) | |
128 dk, err := ReadDSKey(buf, WithoutContext
, "spam", "nerd") | |
129 So(err, ShouldBeNil) | |
130 So(dk, ShouldEqualKey, mkKey("spam", "ne
rd", "knd", "yo", "other", 10)) | |
131 }) | |
132 Convey("IntIDs always sort before StringIDs", fu
nc() { | |
133 // -1 writes as almost all 1's in the fi
rst byte under cmpbin, even | |
134 // though it's technically not a valid k
ey. | |
135 k := mkKey("aid", "ns", "knd", -1) | |
136 buf := &bytes.Buffer{} | |
137 WriteDSKey(buf, WithoutContext, k) | |
138 | |
139 k = mkKey("aid", "ns", "knd", "hat") | |
140 buf2 := &bytes.Buffer{} | |
141 WriteDSKey(buf2, WithoutContext, k) | |
142 | |
143 So(bytes.Compare(buf.Bytes(), buf2.Bytes
()), ShouldBeLessThan, 0) | |
144 }) | |
145 }) | |
146 | |
147 Convey("err cases", func() { | |
148 Convey("nil", func() { | |
149 buf := &bytes.Buffer{} | |
150 _, err := ReadDSKey(buf, WithContext, ""
, "") | |
151 So(err, ShouldEqual, io.EOF) | |
152 }) | |
153 Convey("str", func() { | |
154 buf := &bytes.Buffer{} | |
155 buf.WriteString("sup") | |
156 _, err := ReadDSKey(buf, WithContext, ""
, "") | |
157 So(err, ShouldErrLike, "expected actualC
tx") | |
158 }) | |
159 Convey("truncated 1", func() { | |
160 buf := &bytes.Buffer{} | |
161 buf.WriteByte(1) // actualCtx == 1 | |
162 _, err := ReadDSKey(buf, WithContext, ""
, "") | |
163 So(err, ShouldEqual, io.EOF) | |
164 }) | |
165 Convey("truncated 2", func() { | |
166 buf := &bytes.Buffer{} | |
167 buf.WriteByte(1) // actualCtx == 1 | |
168 cmpbin.WriteString(buf, "aid") | |
169 _, err := ReadDSKey(buf, WithContext, ""
, "") | |
170 So(err, ShouldEqual, io.EOF) | |
171 }) | |
172 Convey("truncated 3", func() { | |
173 buf := &bytes.Buffer{} | |
174 buf.WriteByte(1) // actualCtx == 1 | |
175 cmpbin.WriteString(buf, "aid") | |
176 cmpbin.WriteString(buf, "ns") | |
177 _, err := ReadDSKey(buf, WithContext, ""
, "") | |
178 So(err, ShouldEqual, io.EOF) | |
179 }) | |
180 Convey("huge key", func() { | |
181 buf := &bytes.Buffer{} | |
182 buf.WriteByte(1) // actualCtx == 1 | |
183 cmpbin.WriteString(buf, "aid") | |
184 cmpbin.WriteString(buf, "ns") | |
185 cmpbin.WriteUint(buf, 1000) | |
186 _, err := ReadDSKey(buf, WithContext, ""
, "") | |
187 So(err, ShouldErrLike, "huge key") | |
188 }) | |
189 Convey("insufficient tokens", func() { | |
190 buf := &bytes.Buffer{} | |
191 buf.WriteByte(1) // actualCtx == 1 | |
192 cmpbin.WriteString(buf, "aid") | |
193 cmpbin.WriteString(buf, "ns") | |
194 cmpbin.WriteUint(buf, 2) | |
195 _, err := ReadDSKey(buf, WithContext, ""
, "") | |
196 So(err, ShouldEqual, io.EOF) | |
197 }) | |
198 Convey("partial token 1", func() { | |
199 buf := &bytes.Buffer{} | |
200 buf.WriteByte(1) // actualCtx == 1 | |
201 cmpbin.WriteString(buf, "aid") | |
202 cmpbin.WriteString(buf, "ns") | |
203 cmpbin.WriteUint(buf, 2) | |
204 cmpbin.WriteString(buf, "hi") | |
205 _, err := ReadDSKey(buf, WithContext, ""
, "") | |
206 So(err, ShouldEqual, io.EOF) | |
207 }) | |
208 Convey("partial token 2", func() { | |
209 buf := &bytes.Buffer{} | |
210 buf.WriteByte(1) // actualCtx == 1 | |
211 cmpbin.WriteString(buf, "aid") | |
212 cmpbin.WriteString(buf, "ns") | |
213 cmpbin.WriteUint(buf, 2) | |
214 cmpbin.WriteString(buf, "hi") | |
215 buf.WriteByte(byte(gae.DSPTString)) | |
216 _, err := ReadDSKey(buf, WithContext, ""
, "") | |
217 So(err, ShouldEqual, io.EOF) | |
218 }) | |
219 Convey("bad token (invalid type)", func() { | |
220 buf := &bytes.Buffer{} | |
221 buf.WriteByte(1) // actualCtx == 1 | |
222 cmpbin.WriteString(buf, "aid") | |
223 cmpbin.WriteString(buf, "ns") | |
224 cmpbin.WriteUint(buf, 2) | |
225 cmpbin.WriteString(buf, "hi") | |
226 buf.WriteByte(byte(gae.DSPTBlobKey)) | |
227 _, err := ReadDSKey(buf, WithContext, ""
, "") | |
228 So(err, ShouldErrLike, "invalid type DSP
TBlobKey") | |
229 }) | |
230 Convey("bad token (invalid IntID)", func() { | |
231 buf := &bytes.Buffer{} | |
232 buf.WriteByte(1) // actualCtx == 1 | |
233 cmpbin.WriteString(buf, "aid") | |
234 cmpbin.WriteString(buf, "ns") | |
235 cmpbin.WriteUint(buf, 2) | |
236 cmpbin.WriteString(buf, "hi") | |
237 buf.WriteByte(byte(gae.DSPTInt)) | |
238 cmpbin.WriteInt(buf, -2) | |
239 _, err := ReadDSKey(buf, WithContext, ""
, "") | |
240 So(err, ShouldErrLike, "zero/negative") | |
241 }) | |
242 }) | |
243 }) | |
244 | |
245 Convey("ReadDSGeoPoint", func() { | |
246 Convey("trunc 1", func() { | |
247 buf := &bytes.Buffer{} | |
248 _, err := ReadDSGeoPoint(buf) | |
249 So(err, ShouldEqual, io.EOF) | |
250 }) | |
251 Convey("trunc 2", func() { | |
252 buf := &bytes.Buffer{} | |
253 cmpbin.WriteFloat64(buf, 100) | |
254 _, err := ReadDSGeoPoint(buf) | |
255 So(err, ShouldEqual, io.EOF) | |
256 }) | |
257 Convey("invalid", func() { | |
258 buf := &bytes.Buffer{} | |
259 cmpbin.WriteFloat64(buf, 100) | |
260 cmpbin.WriteFloat64(buf, 1000) | |
261 _, err := ReadDSGeoPoint(buf) | |
262 So(err, ShouldErrLike, "invalid DSGeoPoint") | |
263 }) | |
264 }) | |
265 | |
266 Convey("WriteTime", func() { | |
267 Convey("in non-UTC!", func() { | |
268 buf := &bytes.Buffer{} | |
269 pst, err := time.LoadLocation("America/Los_Angel
es") | |
270 So(err, ShouldBeNil) | |
271 So(func() { | |
272 WriteTime(buf, time.Now().In(pst)) | |
273 }, ShouldPanic) | |
274 }) | |
275 }) | |
276 | |
277 Convey("ReadTime", func() { | |
278 Convey("trunc 1", func() { | |
279 buf := &bytes.Buffer{} | |
280 _, err := ReadTime(buf) | |
281 So(err, ShouldEqual, io.EOF) | |
282 }) | |
283 }) | |
284 | |
285 Convey("ReadDSProperty", func() { | |
286 Convey("trunc 1", func() { | |
287 buf := &bytes.Buffer{} | |
288 _, err := ReadDSProperty(buf, WithContext, "", "
") | |
289 So(err, ShouldEqual, io.EOF) | |
290 }) | |
291 Convey("trunc (DSPTBytes)", func() { | |
292 buf := &bytes.Buffer{} | |
293 buf.WriteByte(byte(gae.DSPTBytes)) | |
294 _, err := ReadDSProperty(buf, WithContext, "", "
") | |
295 So(err, ShouldEqual, io.EOF) | |
296 }) | |
297 Convey("trunc (DSPTBlobKey)", func() { | |
298 buf := &bytes.Buffer{} | |
299 buf.WriteByte(byte(gae.DSPTBlobKey)) | |
300 _, err := ReadDSProperty(buf, WithContext, "", "
") | |
301 So(err, ShouldEqual, io.EOF) | |
302 }) | |
303 Convey("invalid type", func() { | |
304 buf := &bytes.Buffer{} | |
305 buf.WriteByte(byte(gae.DSPTUnknown + 1)) | |
306 _, err := ReadDSProperty(buf, WithContext, "", "
") | |
307 So(err, ShouldErrLike, "unknown type!") | |
308 }) | |
309 }) | |
310 | |
311 Convey("ReadDSPropertyMap", func() { | |
312 Convey("trunc 1", func() { | |
313 buf := &bytes.Buffer{} | |
314 _, err := ReadDSPropertyMap(buf, WithContext, ""
, "") | |
315 So(err, ShouldEqual, io.EOF) | |
316 }) | |
317 Convey("too many rows", func() { | |
318 buf := &bytes.Buffer{} | |
319 cmpbin.WriteUint(buf, 1000000) | |
320 _, err := ReadDSPropertyMap(buf, WithContext, ""
, "") | |
321 So(err, ShouldErrLike, "huge number of rows") | |
322 }) | |
323 Convey("trunc 2", func() { | |
324 buf := &bytes.Buffer{} | |
325 cmpbin.WriteUint(buf, 10) | |
326 _, err := ReadDSPropertyMap(buf, WithContext, ""
, "") | |
327 So(err, ShouldEqual, io.EOF) | |
328 }) | |
329 Convey("trunc 3", func() { | |
330 buf := &bytes.Buffer{} | |
331 cmpbin.WriteUint(buf, 10) | |
332 cmpbin.WriteString(buf, "ohai") | |
333 _, err := ReadDSPropertyMap(buf, WithContext, ""
, "") | |
334 So(err, ShouldEqual, io.EOF) | |
335 }) | |
336 Convey("too many values", func() { | |
337 buf := &bytes.Buffer{} | |
338 cmpbin.WriteUint(buf, 10) | |
339 cmpbin.WriteString(buf, "ohai") | |
340 cmpbin.WriteUint(buf, 100000) | |
341 _, err := ReadDSPropertyMap(buf, WithContext, ""
, "") | |
342 So(err, ShouldErrLike, "huge number of propertie
s") | |
343 }) | |
344 Convey("trunc 4", func() { | |
345 buf := &bytes.Buffer{} | |
346 cmpbin.WriteUint(buf, 10) | |
347 cmpbin.WriteString(buf, "ohai") | |
348 cmpbin.WriteUint(buf, 10) | |
349 _, err := ReadDSPropertyMap(buf, WithContext, ""
, "") | |
350 So(err, ShouldEqual, io.EOF) | |
351 }) | |
352 }) | |
353 }) | |
354 } | |
OLD | NEW |