OLD | NEW |
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 datastore | 5 package serialize |
6 | 6 |
7 import ( | 7 import ( |
8 "bytes" | 8 "bytes" |
| 9 "fmt" |
9 "io" | 10 "io" |
10 "testing" | 11 "testing" |
11 "time" | 12 "time" |
12 | 13 |
13 "github.com/luci/gae/service/blobstore" | 14 "github.com/luci/gae/service/blobstore" |
| 15 ds "github.com/luci/gae/service/datastore" |
| 16 "github.com/luci/gae/service/datastore/dskey" |
14 "github.com/luci/luci-go/common/cmpbin" | 17 "github.com/luci/luci-go/common/cmpbin" |
| 18 . "github.com/luci/luci-go/common/testing/assertions" |
15 . "github.com/smartystreets/goconvey/convey" | 19 . "github.com/smartystreets/goconvey/convey" |
16 ) | 20 ) |
17 | 21 |
18 func init() { | 22 func init() { |
19 WritePropertyMapDeterministic = true | 23 WritePropertyMapDeterministic = true |
20 } | 24 } |
21 | 25 |
| 26 var ( |
| 27 mp = ds.MkProperty |
| 28 mpNI = ds.MkPropertyNI |
| 29 ) |
| 30 |
22 type dspmapTC struct { | 31 type dspmapTC struct { |
23 name string | 32 name string |
24 » props PropertyMap | 33 » props ds.PropertyMap |
| 34 } |
| 35 |
| 36 // TODO(riannucci): dedup with datastore/key testing file. |
| 37 func mkKey(aid, ns string, elems ...interface{}) ds.Key { |
| 38 » if len(elems)%2 != 0 { |
| 39 » » panic("odd number of tokens") |
| 40 » } |
| 41 » toks := make([]ds.KeyTok, len(elems)/2) |
| 42 » for i := 0; i < len(elems); i += 2 { |
| 43 » » toks[i/2].Kind = elems[i].(string) |
| 44 » » switch x := elems[i+1].(type) { |
| 45 » » case string: |
| 46 » » » toks[i/2].StringID = x |
| 47 » » case int: |
| 48 » » » toks[i/2].IntID = int64(x) |
| 49 » » default: |
| 50 » » » panic("bad token id") |
| 51 » » } |
| 52 » } |
| 53 » return dskey.NewToks(aid, ns, toks) |
| 54 } |
| 55 |
| 56 func mkBuf(data []byte) Buffer { |
| 57 » return Invertible(bytes.NewBuffer(data)) |
| 58 } |
| 59 |
| 60 // TODO(riannucci): dedup with datastore/key testing file |
| 61 func ShouldEqualKey(actual interface{}, expected ...interface{}) string { |
| 62 » if len(expected) != 1 { |
| 63 » » return fmt.Sprintf("Assertion requires 1 expected value, got %d"
, len(expected)) |
| 64 » } |
| 65 » if dskey.Equal(actual.(ds.Key), expected[0].(ds.Key)) { |
| 66 » » return "" |
| 67 » } |
| 68 » return fmt.Sprintf("Expected: %q\nActual: %q", actual, expected[0]) |
25 } | 69 } |
26 | 70 |
27 func TestPropertyMapSerialization(t *testing.T) { | 71 func TestPropertyMapSerialization(t *testing.T) { |
28 t.Parallel() | 72 t.Parallel() |
29 | 73 |
30 tests := []dspmapTC{ | 74 tests := []dspmapTC{ |
31 { | 75 { |
32 "basic", | 76 "basic", |
33 » » » PropertyMap{ | 77 » » » ds.PropertyMap{ |
34 "R": {mp(false), mp(2.1), mpNI(3)}, | 78 "R": {mp(false), mp(2.1), mpNI(3)}, |
35 "S": {mp("hello"), mp("world")}, | 79 "S": {mp("hello"), mp("world")}, |
36 }, | 80 }, |
37 }, | 81 }, |
38 { | 82 { |
39 "keys", | 83 "keys", |
40 » » » PropertyMap{ | 84 » » » ds.PropertyMap{ |
41 "DS": {mp(mkKey("appy", "ns", "Foo", 7)),
mp(mkKey("other", "", "Yot", "wheeep"))}, | 85 "DS": {mp(mkKey("appy", "ns", "Foo", 7)),
mp(mkKey("other", "", "Yot", "wheeep"))}, |
42 "blobstore": {mp(blobstore.Key("sup")), mp(blobs
tore.Key("nerds"))}, | 86 "blobstore": {mp(blobstore.Key("sup")), mp(blobs
tore.Key("nerds"))}, |
43 }, | 87 }, |
44 }, | 88 }, |
45 { | 89 { |
46 "geo", | 90 "geo", |
47 » » » PropertyMap{ | 91 » » » ds.PropertyMap{ |
48 » » » » "G": {mp(GeoPoint{Lat: 1, Lng: 2})}, | 92 » » » » "G": {mp(ds.GeoPoint{Lat: 1, Lng: 2})}, |
49 }, | 93 }, |
50 }, | 94 }, |
51 { | 95 { |
52 "data", | 96 "data", |
53 » » » PropertyMap{ | 97 » » » ds.PropertyMap{ |
54 "S": {mp("sup"), mp("fool"), mp("nerd")
}, | 98 "S": {mp("sup"), mp("fool"), mp("nerd")
}, |
55 "D.Foo.Nerd": {mp([]byte("sup")), mp([]byte("foo
l"))}, | 99 "D.Foo.Nerd": {mp([]byte("sup")), mp([]byte("foo
l"))}, |
56 » » » » "B": {mp(ByteString("sup")), mp(ByteStr
ing("fool"))}, | 100 » » » » "B": {mp(ds.ByteString("sup")), mp(ds.B
yteString("fool"))}, |
57 }, | 101 }, |
58 }, | 102 }, |
59 { | 103 { |
60 "time", | 104 "time", |
61 » » » PropertyMap{ | 105 » » » ds.PropertyMap{ |
62 "T": { | 106 "T": { |
63 mp(time.Now().UTC()), | 107 mp(time.Now().UTC()), |
64 mp(time.Now().Add(time.Second).UTC())}, | 108 mp(time.Now().Add(time.Second).UTC())}, |
65 }, | 109 }, |
66 }, | 110 }, |
67 { | 111 { |
68 "empty vals", | 112 "empty vals", |
69 » » » PropertyMap{ | 113 » » » ds.PropertyMap{ |
70 "T": {mp(true), mp(true)}, | 114 "T": {mp(true), mp(true)}, |
71 "F": {mp(false), mp(false)}, | 115 "F": {mp(false), mp(false)}, |
72 "N": {mp(nil), mp(nil)}, | 116 "N": {mp(nil), mp(nil)}, |
73 "E": {}, | 117 "E": {}, |
74 }, | 118 }, |
75 }, | 119 }, |
76 } | 120 } |
77 | 121 |
78 Convey("PropertyMap serialization", t, func() { | 122 Convey("PropertyMap serialization", t, func() { |
79 Convey("round trip", func() { | 123 Convey("round trip", func() { |
80 for _, tc := range tests { | 124 for _, tc := range tests { |
81 tc := tc | 125 tc := tc |
82 Convey(tc.name, func() { | 126 Convey(tc.name, func() { |
83 » » » » » buf := &bytes.Buffer{} | 127 » » » » » data := ToBytesWithContext(tc.props) |
84 » » » » » tc.props.Write(buf, WithContext) | 128 » » » » » dec, err := ReadPropertyMap(mkBuf(data),
WithContext, "", "") |
85 » » » » » dec := PropertyMap{} | |
86 » » » » » err := dec.Read(buf, WithContext, "", ""
) | |
87 So(err, ShouldBeNil) | 129 So(err, ShouldBeNil) |
88 So(dec, ShouldResemble, tc.props) | 130 So(dec, ShouldResemble, tc.props) |
89 }) | 131 }) |
90 } | 132 } |
91 }) | 133 }) |
92 }) | 134 }) |
93 } | 135 } |
94 | 136 |
95 func TestSerializationReadMisc(t *testing.T) { | 137 func TestSerializationReadMisc(t *testing.T) { |
96 t.Parallel() | 138 t.Parallel() |
97 | 139 |
98 Convey("Misc Serialization tests", t, func() { | 140 Convey("Misc Serialization tests", t, func() { |
99 » » buf := &bytes.Buffer{} | 141 » » Convey("GeoPoint", func() { |
| 142 » » » buf := mkBuf(nil) |
| 143 » » » cmpbin.WriteFloat64(buf, 10) |
| 144 » » » cmpbin.WriteFloat64(buf, 20) |
| 145 » » » So(string(ToBytes(ds.GeoPoint{Lat: 10, Lng: 20})), Shoul
dEqual, buf.String()) |
| 146 » » }) |
| 147 |
| 148 » » Convey("IndexColumn", func() { |
| 149 » » » buf := mkBuf(nil) |
| 150 » » » buf.WriteByte(1) |
| 151 » » » cmpbin.WriteString(buf, "hi") |
| 152 » » » So(string(ToBytes(ds.IndexColumn{Property: "hi", Directi
on: ds.DESCENDING})), |
| 153 » » » » ShouldEqual, buf.String()) |
| 154 » » }) |
| 155 |
| 156 » » Convey("KeyTok", func() { |
| 157 » » » buf := mkBuf(nil) |
| 158 » » » cmpbin.WriteString(buf, "foo") |
| 159 » » » buf.WriteByte(byte(ds.PTInt)) |
| 160 » » » cmpbin.WriteInt(buf, 20) |
| 161 » » » So(string(ToBytes(ds.KeyTok{Kind: "foo", IntID: 20})), |
| 162 » » » » ShouldEqual, buf.String()) |
| 163 » » }) |
| 164 |
| 165 » » Convey("Property", func() { |
| 166 » » » buf := mkBuf(nil) |
| 167 » » » buf.WriteByte(byte(ds.PTString)) |
| 168 » » » cmpbin.WriteString(buf, "nerp") |
| 169 » » » So(string(ToBytes(mp("nerp"))), |
| 170 » » » » ShouldEqual, buf.String()) |
| 171 » » }) |
| 172 |
| 173 » » Convey("Time", func() { |
| 174 » » » tp := mp(time.Now().UTC()) |
| 175 » » » So(string(ToBytes(tp.Value())), ShouldEqual, string(ToBy
tes(tp)[1:])) |
| 176 » » }) |
| 177 |
| 178 » » Convey("Bad ToBytes", func() { |
| 179 » » » So(func() { ToBytes(100.7) }, ShouldPanic) |
| 180 » » » So(func() { ToBytesWithContext(100.7) }, ShouldPanic) |
| 181 » » }) |
| 182 |
100 Convey("ReadKey", func() { | 183 Convey("ReadKey", func() { |
101 Convey("good cases", func() { | 184 Convey("good cases", func() { |
102 Convey("w/ ctx decodes normally w/ ctx", func()
{ | 185 Convey("w/ ctx decodes normally w/ ctx", func()
{ |
103 k := mkKey("aid", "ns", "knd", "yo", "ot
her", 10) | 186 k := mkKey("aid", "ns", "knd", "yo", "ot
her", 10) |
104 » » » » » WriteKey(buf, WithContext, k) | 187 » » » » » data := ToBytesWithContext(k) |
105 » » » » » dk, err := ReadKey(buf, WithContext, "",
"") | 188 » » » » » dk, err := ReadKey(mkBuf(data), WithCont
ext, "", "") |
106 So(err, ShouldBeNil) | 189 So(err, ShouldBeNil) |
107 So(dk, ShouldEqualKey, k) | 190 So(dk, ShouldEqualKey, k) |
108 }) | 191 }) |
109 Convey("w/ ctx decodes normally w/o ctx", func()
{ | 192 Convey("w/ ctx decodes normally w/o ctx", func()
{ |
110 k := mkKey("aid", "ns", "knd", "yo", "ot
her", 10) | 193 k := mkKey("aid", "ns", "knd", "yo", "ot
her", 10) |
111 » » » » » WriteKey(buf, WithContext, k) | 194 » » » » » data := ToBytesWithContext(k) |
112 » » » » » dk, err := ReadKey(buf, WithoutContext,
"spam", "nerd") | 195 » » » » » dk, err := ReadKey(mkBuf(data), WithoutC
ontext, "spam", "nerd") |
113 So(err, ShouldBeNil) | 196 So(err, ShouldBeNil) |
114 So(dk, ShouldEqualKey, mkKey("spam", "ne
rd", "knd", "yo", "other", 10)) | 197 So(dk, ShouldEqualKey, mkKey("spam", "ne
rd", "knd", "yo", "other", 10)) |
115 }) | 198 }) |
116 Convey("w/o ctx decodes normally w/ ctx", func()
{ | 199 Convey("w/o ctx decodes normally w/ ctx", func()
{ |
117 k := mkKey("aid", "ns", "knd", "yo", "ot
her", 10) | 200 k := mkKey("aid", "ns", "knd", "yo", "ot
her", 10) |
118 » » » » » WriteKey(buf, WithoutContext, k) | 201 » » » » » data := ToBytes(k) |
119 » » » » » dk, err := ReadKey(buf, WithContext, "sp
am", "nerd") | 202 » » » » » dk, err := ReadKey(mkBuf(data), WithCont
ext, "spam", "nerd") |
120 So(err, ShouldBeNil) | 203 So(err, ShouldBeNil) |
121 So(dk, ShouldEqualKey, mkKey("", "", "kn
d", "yo", "other", 10)) | 204 So(dk, ShouldEqualKey, mkKey("", "", "kn
d", "yo", "other", 10)) |
122 }) | 205 }) |
123 Convey("w/o ctx decodes normally w/o ctx", func(
) { | 206 Convey("w/o ctx decodes normally w/o ctx", func(
) { |
124 k := mkKey("aid", "ns", "knd", "yo", "ot
her", 10) | 207 k := mkKey("aid", "ns", "knd", "yo", "ot
her", 10) |
125 » » » » » WriteKey(buf, WithoutContext, k) | 208 » » » » » data := ToBytes(k) |
126 » » » » » dk, err := ReadKey(buf, WithoutContext,
"spam", "nerd") | 209 » » » » » dk, err := ReadKey(mkBuf(data), WithoutC
ontext, "spam", "nerd") |
127 So(err, ShouldBeNil) | 210 So(err, ShouldBeNil) |
128 So(dk, ShouldEqualKey, mkKey("spam", "ne
rd", "knd", "yo", "other", 10)) | 211 So(dk, ShouldEqualKey, mkKey("spam", "ne
rd", "knd", "yo", "other", 10)) |
129 }) | 212 }) |
130 Convey("IntIDs always sort before StringIDs", fu
nc() { | 213 Convey("IntIDs always sort before StringIDs", fu
nc() { |
131 // -1 writes as almost all 1's in the fi
rst byte under cmpbin, even | 214 // -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. | 215 // though it's technically not a valid k
ey. |
133 k := mkKey("aid", "ns", "knd", -1) | 216 k := mkKey("aid", "ns", "knd", -1) |
134 » » » » » WriteKey(buf, WithoutContext, k) | 217 » » » » » data := ToBytes(k) |
135 | 218 |
136 k = mkKey("aid", "ns", "knd", "hat") | 219 k = mkKey("aid", "ns", "knd", "hat") |
137 » » » » » buf2 := &bytes.Buffer{} | 220 » » » » » data2 := ToBytes(k) |
138 » » » » » WriteKey(buf2, WithoutContext, k) | |
139 | 221 |
140 » » » » » So(bytes.Compare(buf.Bytes(), buf2.Bytes
()), ShouldBeLessThan, 0) | 222 » » » » » So(string(data), ShouldBeLessThan, strin
g(data2)) |
141 }) | 223 }) |
142 }) | 224 }) |
143 | 225 |
144 Convey("err cases", func() { | 226 Convey("err cases", func() { |
| 227 buf := mkBuf(nil) |
145 Convey("nil", func() { | 228 Convey("nil", func() { |
146 _, err := ReadKey(buf, WithContext, "",
"") | 229 _, err := ReadKey(buf, WithContext, "",
"") |
147 So(err, ShouldEqual, io.EOF) | 230 So(err, ShouldEqual, io.EOF) |
148 }) | 231 }) |
149 Convey("str", func() { | 232 Convey("str", func() { |
150 buf.WriteString("sup") | 233 buf.WriteString("sup") |
151 _, err := ReadKey(buf, WithContext, "",
"") | 234 _, err := ReadKey(buf, WithContext, "",
"") |
152 So(err, ShouldErrLike, "expected actualC
tx") | 235 So(err, ShouldErrLike, "expected actualC
tx") |
153 }) | 236 }) |
154 Convey("truncated 1", func() { | 237 Convey("truncated 1", func() { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 cmpbin.WriteString(buf, "hi") | 276 cmpbin.WriteString(buf, "hi") |
194 _, err := ReadKey(buf, WithContext, "",
"") | 277 _, err := ReadKey(buf, WithContext, "",
"") |
195 So(err, ShouldEqual, io.EOF) | 278 So(err, ShouldEqual, io.EOF) |
196 }) | 279 }) |
197 Convey("partial token 2", func() { | 280 Convey("partial token 2", func() { |
198 buf.WriteByte(1) // actualCtx == 1 | 281 buf.WriteByte(1) // actualCtx == 1 |
199 cmpbin.WriteString(buf, "aid") | 282 cmpbin.WriteString(buf, "aid") |
200 cmpbin.WriteString(buf, "ns") | 283 cmpbin.WriteString(buf, "ns") |
201 cmpbin.WriteUint(buf, 2) | 284 cmpbin.WriteUint(buf, 2) |
202 cmpbin.WriteString(buf, "hi") | 285 cmpbin.WriteString(buf, "hi") |
203 » » » » » buf.WriteByte(byte(PTString)) | 286 » » » » » buf.WriteByte(byte(ds.PTString)) |
204 _, err := ReadKey(buf, WithContext, "",
"") | 287 _, err := ReadKey(buf, WithContext, "",
"") |
205 So(err, ShouldEqual, io.EOF) | 288 So(err, ShouldEqual, io.EOF) |
206 }) | 289 }) |
207 Convey("bad token (invalid type)", func() { | 290 Convey("bad token (invalid type)", func() { |
208 buf.WriteByte(1) // actualCtx == 1 | 291 buf.WriteByte(1) // actualCtx == 1 |
209 cmpbin.WriteString(buf, "aid") | 292 cmpbin.WriteString(buf, "aid") |
210 cmpbin.WriteString(buf, "ns") | 293 cmpbin.WriteString(buf, "ns") |
211 cmpbin.WriteUint(buf, 2) | 294 cmpbin.WriteUint(buf, 2) |
212 cmpbin.WriteString(buf, "hi") | 295 cmpbin.WriteString(buf, "hi") |
213 » » » » » buf.WriteByte(byte(PTBlobKey)) | 296 » » » » » buf.WriteByte(byte(ds.PTBlobKey)) |
214 _, err := ReadKey(buf, WithContext, "",
"") | 297 _, err := ReadKey(buf, WithContext, "",
"") |
215 So(err, ShouldErrLike, "invalid type PTB
lobKey") | 298 So(err, ShouldErrLike, "invalid type PTB
lobKey") |
216 }) | 299 }) |
217 Convey("bad token (invalid IntID)", func() { | 300 Convey("bad token (invalid IntID)", func() { |
218 buf.WriteByte(1) // actualCtx == 1 | 301 buf.WriteByte(1) // actualCtx == 1 |
219 cmpbin.WriteString(buf, "aid") | 302 cmpbin.WriteString(buf, "aid") |
220 cmpbin.WriteString(buf, "ns") | 303 cmpbin.WriteString(buf, "ns") |
221 cmpbin.WriteUint(buf, 2) | 304 cmpbin.WriteUint(buf, 2) |
222 cmpbin.WriteString(buf, "hi") | 305 cmpbin.WriteString(buf, "hi") |
223 » » » » » buf.WriteByte(byte(PTInt)) | 306 » » » » » buf.WriteByte(byte(ds.PTInt)) |
224 cmpbin.WriteInt(buf, -2) | 307 cmpbin.WriteInt(buf, -2) |
225 _, err := ReadKey(buf, WithContext, "",
"") | 308 _, err := ReadKey(buf, WithContext, "",
"") |
226 So(err, ShouldErrLike, "zero/negative") | 309 So(err, ShouldErrLike, "zero/negative") |
227 }) | 310 }) |
228 }) | 311 }) |
229 }) | 312 }) |
230 | 313 |
231 Convey("ReadGeoPoint", func() { | 314 Convey("ReadGeoPoint", func() { |
232 » » » gp := GeoPoint{} | 315 » » » buf := mkBuf(nil) |
233 Convey("trunc 1", func() { | 316 Convey("trunc 1", func() { |
234 » » » » err := gp.Read(buf) | 317 » » » » _, err := ReadGeoPoint(buf) |
235 So(err, ShouldEqual, io.EOF) | 318 So(err, ShouldEqual, io.EOF) |
236 }) | 319 }) |
237 Convey("trunc 2", func() { | 320 Convey("trunc 2", func() { |
238 cmpbin.WriteFloat64(buf, 100) | 321 cmpbin.WriteFloat64(buf, 100) |
239 » » » » err := gp.Read(buf) | 322 » » » » _, err := ReadGeoPoint(buf) |
240 So(err, ShouldEqual, io.EOF) | 323 So(err, ShouldEqual, io.EOF) |
241 }) | 324 }) |
242 Convey("invalid", func() { | 325 Convey("invalid", func() { |
243 cmpbin.WriteFloat64(buf, 100) | 326 cmpbin.WriteFloat64(buf, 100) |
244 cmpbin.WriteFloat64(buf, 1000) | 327 cmpbin.WriteFloat64(buf, 1000) |
245 » » » » err := gp.Read(buf) | 328 » » » » _, err := ReadGeoPoint(buf) |
246 So(err, ShouldErrLike, "invalid GeoPoint") | 329 So(err, ShouldErrLike, "invalid GeoPoint") |
247 }) | 330 }) |
248 }) | 331 }) |
249 | 332 |
250 Convey("WriteTime", func() { | 333 Convey("WriteTime", func() { |
251 Convey("in non-UTC!", func() { | 334 Convey("in non-UTC!", func() { |
252 pst, err := time.LoadLocation("America/Los_Angel
es") | 335 pst, err := time.LoadLocation("America/Los_Angel
es") |
253 So(err, ShouldBeNil) | 336 So(err, ShouldBeNil) |
254 So(func() { | 337 So(func() { |
255 » » » » » WriteTime(buf, time.Now().In(pst)) | 338 » » » » » WriteTime(mkBuf(nil), time.Now().In(pst)
) |
256 }, ShouldPanic) | 339 }, ShouldPanic) |
257 }) | 340 }) |
258 }) | 341 }) |
259 | 342 |
260 Convey("ReadTime", func() { | 343 Convey("ReadTime", func() { |
261 Convey("trunc 1", func() { | 344 Convey("trunc 1", func() { |
262 » » » » _, err := ReadTime(buf) | 345 » » » » _, err := ReadTime(mkBuf(nil)) |
263 So(err, ShouldEqual, io.EOF) | 346 So(err, ShouldEqual, io.EOF) |
264 }) | 347 }) |
265 }) | 348 }) |
266 | 349 |
267 Convey("ReadProperty", func() { | 350 Convey("ReadProperty", func() { |
268 » » » p := Property{} | 351 » » » buf := mkBuf(nil) |
269 Convey("trunc 1", func() { | 352 Convey("trunc 1", func() { |
270 » » » » err := p.Read(buf, WithContext, "", "") | 353 » » » » p, err := ReadProperty(buf, WithContext, "", "") |
271 So(err, ShouldEqual, io.EOF) | 354 So(err, ShouldEqual, io.EOF) |
272 » » » » So(p.Type(), ShouldEqual, PTNull) | 355 » » » » So(p.Type(), ShouldEqual, ds.PTNull) |
273 So(p.Value(), ShouldBeNil) | 356 So(p.Value(), ShouldBeNil) |
274 }) | 357 }) |
275 Convey("trunc (PTBytes)", func() { | 358 Convey("trunc (PTBytes)", func() { |
276 » » » » buf.WriteByte(byte(PTBytes)) | 359 » » » » buf.WriteByte(byte(ds.PTBytes)) |
277 » » » » err := p.Read(buf, WithContext, "", "") | 360 » » » » _, err := ReadProperty(buf, WithContext, "", "") |
278 So(err, ShouldEqual, io.EOF) | 361 So(err, ShouldEqual, io.EOF) |
279 }) | 362 }) |
280 Convey("trunc (PTBlobKey)", func() { | 363 Convey("trunc (PTBlobKey)", func() { |
281 » » » » buf.WriteByte(byte(PTBlobKey)) | 364 » » » » buf.WriteByte(byte(ds.PTBlobKey)) |
282 » » » » err := p.Read(buf, WithContext, "", "") | 365 » » » » _, err := ReadProperty(buf, WithContext, "", "") |
283 So(err, ShouldEqual, io.EOF) | 366 So(err, ShouldEqual, io.EOF) |
284 }) | 367 }) |
285 Convey("invalid type", func() { | 368 Convey("invalid type", func() { |
286 » » » » buf.WriteByte(byte(PTUnknown + 1)) | 369 » » » » buf.WriteByte(byte(ds.PTUnknown + 1)) |
287 » » » » err := p.Read(buf, WithContext, "", "") | 370 » » » » _, err := ReadProperty(buf, WithContext, "", "") |
288 So(err, ShouldErrLike, "unknown type!") | 371 So(err, ShouldErrLike, "unknown type!") |
289 }) | 372 }) |
290 }) | 373 }) |
291 | 374 |
292 Convey("ReadPropertyMap", func() { | 375 Convey("ReadPropertyMap", func() { |
293 » » » pm := PropertyMap{} | 376 » » » buf := mkBuf(nil) |
294 Convey("trunc 1", func() { | 377 Convey("trunc 1", func() { |
295 » » » » err := pm.Read(buf, WithContext, "", "") | 378 » » » » _, err := ReadPropertyMap(buf, WithContext, "",
"") |
296 So(err, ShouldEqual, io.EOF) | 379 So(err, ShouldEqual, io.EOF) |
297 }) | 380 }) |
298 Convey("too many rows", func() { | 381 Convey("too many rows", func() { |
299 cmpbin.WriteUint(buf, 1000000) | 382 cmpbin.WriteUint(buf, 1000000) |
300 » » » » err := pm.Read(buf, WithContext, "", "") | 383 » » » » _, err := ReadPropertyMap(buf, WithContext, "",
"") |
301 So(err, ShouldErrLike, "huge number of rows") | 384 So(err, ShouldErrLike, "huge number of rows") |
302 }) | 385 }) |
303 Convey("trunc 2", func() { | 386 Convey("trunc 2", func() { |
304 cmpbin.WriteUint(buf, 10) | 387 cmpbin.WriteUint(buf, 10) |
305 » » » » err := pm.Read(buf, WithContext, "", "") | 388 » » » » _, err := ReadPropertyMap(buf, WithContext, "",
"") |
306 So(err, ShouldEqual, io.EOF) | 389 So(err, ShouldEqual, io.EOF) |
307 }) | 390 }) |
308 Convey("trunc 3", func() { | 391 Convey("trunc 3", func() { |
309 cmpbin.WriteUint(buf, 10) | 392 cmpbin.WriteUint(buf, 10) |
310 cmpbin.WriteString(buf, "ohai") | 393 cmpbin.WriteString(buf, "ohai") |
311 » » » » err := pm.Read(buf, WithContext, "", "") | 394 » » » » _, err := ReadPropertyMap(buf, WithContext, "",
"") |
312 So(err, ShouldEqual, io.EOF) | 395 So(err, ShouldEqual, io.EOF) |
313 }) | 396 }) |
314 Convey("too many values", func() { | 397 Convey("too many values", func() { |
315 cmpbin.WriteUint(buf, 10) | 398 cmpbin.WriteUint(buf, 10) |
316 cmpbin.WriteString(buf, "ohai") | 399 cmpbin.WriteString(buf, "ohai") |
317 cmpbin.WriteUint(buf, 100000) | 400 cmpbin.WriteUint(buf, 100000) |
318 » » » » err := pm.Read(buf, WithContext, "", "") | 401 » » » » _, err := ReadPropertyMap(buf, WithContext, "",
"") |
319 So(err, ShouldErrLike, "huge number of propertie
s") | 402 So(err, ShouldErrLike, "huge number of propertie
s") |
320 }) | 403 }) |
321 Convey("trunc 4", func() { | 404 Convey("trunc 4", func() { |
322 cmpbin.WriteUint(buf, 10) | 405 cmpbin.WriteUint(buf, 10) |
323 cmpbin.WriteString(buf, "ohai") | 406 cmpbin.WriteString(buf, "ohai") |
324 cmpbin.WriteUint(buf, 10) | 407 cmpbin.WriteUint(buf, 10) |
325 » » » » err := pm.Read(buf, WithContext, "", "") | 408 » » » » _, err := ReadPropertyMap(buf, WithContext, "",
"") |
326 So(err, ShouldEqual, io.EOF) | 409 So(err, ShouldEqual, io.EOF) |
327 }) | 410 }) |
328 }) | 411 }) |
| 412 |
| 413 Convey("IndexDefinition", func() { |
| 414 id := ds.IndexDefinition{Kind: "kind"} |
| 415 data := ToBytes(id) |
| 416 So(string(data), ShouldStartWith, string(ds.IndexBuiltin
QueryPrefix())) |
| 417 newID, err := ReadIndexDefinition(mkBuf(data)) |
| 418 So(err, ShouldBeNil) |
| 419 So(newID, ShouldResemble, id) |
| 420 |
| 421 id.SortBy = append(id.SortBy, ds.IndexColumn{Property: "
prop"}) |
| 422 data = ToBytes(id) |
| 423 So(string(data), ShouldStartWith, string(ds.IndexBuiltin
QueryPrefix())) |
| 424 newID, err = ReadIndexDefinition(mkBuf(data)) |
| 425 So(err, ShouldBeNil) |
| 426 So(newID, ShouldResemble, id) |
| 427 |
| 428 id.SortBy = append(id.SortBy, ds.IndexColumn{Property: "
other", Direction: ds.DESCENDING}) |
| 429 id.Ancestor = true |
| 430 data = ToBytes(id) |
| 431 So(string(data), ShouldStartWith, string(ds.IndexComplex
QueryPrefix())) |
| 432 newID, err = ReadIndexDefinition(mkBuf(data)) |
| 433 So(err, ShouldBeNil) |
| 434 So(newID, ShouldResemble, id) |
| 435 |
| 436 // invalid |
| 437 id.SortBy = append(id.SortBy, ds.IndexColumn{Property: "
", Direction: ds.DESCENDING}) |
| 438 data = ToBytes(id) |
| 439 So(string(data), ShouldStartWith, string(ds.IndexComplex
QueryPrefix())) |
| 440 newID, err = ReadIndexDefinition(mkBuf(data)) |
| 441 So(err, ShouldBeNil) |
| 442 So(newID, ShouldResemble, id) |
| 443 |
| 444 Convey("too many", func() { |
| 445 id := ds.IndexDefinition{Kind: "wat"} |
| 446 for i := 0; i < MaxIndexColumns+1; i++ { |
| 447 id.SortBy = append(id.SortBy, ds.IndexCo
lumn{Property: "Hi", Direction: ds.ASCENDING}) |
| 448 } |
| 449 data := ToBytes(id) |
| 450 newID, err = ReadIndexDefinition(mkBuf(data)) |
| 451 So(err, ShouldErrLike, "over 64 sort orders") |
| 452 }) |
| 453 }) |
329 }) | 454 }) |
330 } | 455 } |
OLD | NEW |