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

Side by Side Diff: service/datastore/datastore_test.go

Issue 1259593005: Add 'user friendly' datastore API. (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: more docs 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
« no previous file with comments | « service/datastore/datastore.go ('k') | service/datastore/interface.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 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 // adapted from github.com/golang/appengine/datastore
6
7 package datastore
8
9 import (
10 "fmt"
11 "testing"
12
13 "github.com/luci/gae/service/info"
14 "github.com/luci/luci-go/common/errors"
15 . "github.com/smartystreets/goconvey/convey"
16 "golang.org/x/net/context"
17 )
18
19 func fakeDatastoreFactory(c context.Context) RawInterface {
20 i := info.Get(c)
21 return &fakeDatastore{
22 aid: i.AppID(),
23 ns: i.GetNamespace(),
24 }
25 }
26
27 type fakeQuery struct {
28 Query
29
30 limit int
31
32 err error
33 errSingle error
34 errSingleIdx int
35 }
36
37 func (q *fakeQuery) KeysOnly() Query {
38 return q
39 }
40
41 func (q *fakeQuery) Limit(i int) Query {
42 q.limit = i
43 return q
44 }
45
46 func (q *fakeQuery) FailAll() Query {
47 q.err = errors.New("Query fail all")
48 return q
49 }
50
51 func (q *fakeQuery) Fail(i int) Query {
52 q.errSingleIdx = i
53 q.errSingle = errors.New("Query fail")
54 return q
55 }
56
57 type fakeDatastore struct {
58 RawInterface
59 aid string
60 ns string
61 }
62
63 func (f *fakeDatastore) NewKey(kind, stringID string, intID int64, parent Key) K ey {
64 return NewKey(f.aid, f.ns, kind, stringID, intID, parent)
65 }
66
67 func (f *fakeDatastore) NewQuery(string) Query {
68 return &fakeQuery{}
69 }
70
71 func (f *fakeDatastore) Run(q Query, cb RawRunCB) error {
72 rq := q.(*fakeQuery)
73 if rq.err != nil {
74 return rq.err
75 }
76 for i := 0; i < rq.limit; i++ {
77 if rq.errSingle != nil && i == rq.errSingleIdx {
78 return rq.errSingle
79 } else {
80 k := f.NewKey("Kind", "", int64(i+1), nil)
81 if i == 10 {
82 k = f.NewKey("Kind", "eleven", 0, nil)
83 }
84 pm := PropertyMap{"Value": {MkProperty(i)}}
85 if !cb(k, pm, nil) {
86 break
87 }
88 }
89 }
90 return nil
91 }
92
93 func (f *fakeDatastore) PutMulti(keys []Key, vals []PropertyMap, cb PutMultiCB) error {
94 if keys[0].Kind() == "FailAll" {
95 return errors.New("PutMulti fail all")
96 }
97 assertExtra := false
98 if _, err := vals[0].GetMeta("assertExtra"); err == nil {
99 assertExtra = true
100 }
101 for i, k := range keys {
102 err := error(nil)
103 if k.Kind() == "Fail" {
104 err = errors.New("PutMulti fail")
105 } else {
106 So(vals[i]["Value"], ShouldResemble, []Property{MkProper ty(i)})
107 if assertExtra {
108 So(vals[i]["Extra"], ShouldResemble, []Property{ MkProperty("whoa")})
109 }
110 if KeyIncomplete(k) {
111 k = NewKey(k.AppID(), k.Namespace(), k.Kind(), " ", int64(i+1), k.Parent())
112 }
113 }
114 cb(k, err)
115 }
116 return nil
117 }
118
119 func (f *fakeDatastore) GetMulti(keys []Key, cb GetMultiCB) error {
120 if keys[0].Kind() == "FailAll" {
121 return errors.New("GetMulti fail all")
122 }
123 for i, k := range keys {
124 if k.Kind() == "Fail" {
125 cb(nil, errors.New("GetMulti fail"))
126 } else {
127 cb(PropertyMap{"Value": {MkProperty(i + 1)}}, nil)
128 }
129 }
130 return nil
131 }
132
133 func (f *fakeDatastore) DeleteMulti(keys []Key, cb DeleteMultiCB) error {
134 if keys[0].Kind() == "FailAll" {
135 return errors.New("DeleteMulti fail all")
136 }
137 for _, k := range keys {
138 if k.Kind() == "Fail" {
139 cb(errors.New("DeleteMulti fail"))
140 } else {
141 cb(nil)
142 }
143 }
144 return nil
145 }
146
147 type badStruct struct {
148 ID int64 `gae:"$id"`
149 Compy complex64 // bad type
150 }
151
152 type CommonStruct struct {
153 ID int64 `gae:"$id"`
154 Parent Key `gae:"$parent"`
155
156 Value int64
157 }
158
159 type permaBad struct {
160 PropertyLoadSaver
161 }
162
163 func (f *permaBad) Load(pm PropertyMap) error {
164 return errors.New("permaBad")
165 }
166
167 type FakePLS struct {
168 IntID int64
169 StringID string
170 Kind string
171
172 Value int64
173 gotLoaded bool
174
175 failGetMeta bool
176 failLoad bool
177 failProblem bool
178 failSave bool
179 failSaveMeta bool
180 }
181
182 func (f *FakePLS) Load(pm PropertyMap) error {
183 if f.failLoad {
184 return errors.New("FakePLS.Load")
185 }
186 f.gotLoaded = true
187 f.Value = pm["Value"][0].Value().(int64)
188 return nil
189 }
190
191 func (f *FakePLS) Save(withMeta bool) (PropertyMap, error) {
192 if f.failSave {
193 return nil, errors.New("FakePLS.Save")
194 }
195 ret := PropertyMap{
196 "Value": {MkProperty(f.Value)},
197 "Extra": {MkProperty("whoa")},
198 }
199 if withMeta {
200 id, _ := f.GetMeta("id")
201 ret.SetMeta("id", id)
202 if f.Kind == "" {
203 ret.SetMeta("kind", "FakePLS")
204 } else {
205 ret.SetMeta("kind", f.Kind)
206 }
207 ret.SetMeta("assertExtra", true)
208 }
209 return ret, nil
210 }
211
212 func (f *FakePLS) GetMeta(key string) (interface{}, error) {
213 if f.failGetMeta {
214 return nil, errors.New("FakePLS.GetMeta")
215 }
216 switch key {
217 case "id":
218 if f.StringID != "" {
219 return f.StringID, nil
220 }
221 return f.IntID, nil
222 case "kind":
223 if f.Kind == "" {
224 return "FakePLS", nil
225 }
226 return f.Kind, nil
227 }
228 return nil, ErrMetaFieldUnset
229 }
230
231 func (f *FakePLS) SetMeta(key string, val interface{}) error {
232 if f.failSaveMeta {
233 return errors.New("FakePL.SetMeta")
234 }
235 if key == "id" {
236 switch x := val.(type) {
237 case int64:
238 f.IntID = x
239 case string:
240 f.StringID = x
241 }
242 return nil
243 }
244 if key == "kind" {
245 f.Kind = val.(string)
246 return nil
247 }
248 return ErrMetaFieldUnset
249 }
250
251 func (f *FakePLS) Problem() error {
252 if f.failProblem {
253 return errors.New("FakePLS.Problem")
254 }
255 return nil
256 }
257
258 func TestKeyForObj(t *testing.T) {
259 t.Parallel()
260
261 Convey("Test interface.KeyForObj", t, func() {
262 c := info.Set(context.Background(), fakeInfo{})
263 c = SetRawFactory(c, fakeDatastoreFactory)
264 ds := Get(c)
265
266 k := ds.NewKey("Hello", "world", 0, nil)
267
268 Convey("good", func() {
269 Convey("struct containing $key", func() {
270 type keyStruct struct {
271 Key Key `gae:"$key"`
272 }
273
274 ks := &keyStruct{k}
275 So(ds.KeyForObj(ks), ShouldEqual, k)
276 })
277
278 Convey("struct containing default $id and $kind", func() {
279 type idStruct struct {
280 id string `gae:"$id,wut"`
281 knd string `gae:"$kind,SuperKind"`
282 }
283
284 So(ds.KeyForObj(&idStruct{}).String(), ShouldEqu al, `/SuperKind,wut`)
285 })
286
287 Convey("struct containing $id and $parent", func() {
288 So(ds.KeyForObj(&CommonStruct{ID: 4}).String(), ShouldEqual, `/CommonStruct,4`)
289
290 So(ds.KeyForObj(&CommonStruct{ID: 4, Parent: k}) .String(), ShouldEqual, `/Hello,world/CommonStruct,4`)
291 })
292
293 Convey("a propmap with $key", func() {
294 pm := PropertyMap{}
295 pm.SetMeta("key", k)
296 So(ds.KeyForObj(pm).String(), ShouldEqual, `/Hel lo,world`)
297 })
298
299 Convey("a propmap with $id, $kind, $parent", func() {
300 pm := PropertyMap{}
301 pm.SetMeta("id", 100)
302 pm.SetMeta("kind", "Sup")
303 So(ds.KeyForObj(pm).String(), ShouldEqual, `/Sup ,100`)
304
305 pm.SetMeta("parent", k)
306 So(ds.KeyForObj(pm).String(), ShouldEqual, `/Hel lo,world/Sup,100`)
307 })
308
309 Convey("a pls with $id, $parent", func() {
310 pls := GetPLS(&CommonStruct{ID: 1})
311 So(ds.KeyForObj(pls).String(), ShouldEqual, `/Co mmonStruct,1`)
312
313 pls.SetMeta("parent", k)
314 So(ds.KeyForObj(pls).String(), ShouldEqual, `/He llo,world/CommonStruct,1`)
315 })
316
317 })
318
319 Convey("bad", func() {
320 Convey("a propmap without $kind", func() {
321 pm := PropertyMap{}
322 pm.SetMeta("id", 100)
323 So(func() { ds.KeyForObj(pm) }, ShouldPanic)
324 })
325 })
326 })
327 }
328
329 func TestPut(t *testing.T) {
330 t.Parallel()
331
332 Convey("Test Put/PutMulti", t, func() {
333 c := info.Set(context.Background(), fakeInfo{})
334 c = SetRawFactory(c, fakeDatastoreFactory)
335 ds := Get(c)
336
337 Convey("bad", func() {
338 Convey("static can't serialize", func() {
339 bss := []badStruct{{}, {}}
340 So(ds.PutMulti(bss).Error(), ShouldContainSubstr ing, "invalid PutMulti input")
341 })
342
343 Convey("static ptr can't serialize", func() {
344 bss := []*badStruct{{}, {}}
345 So(ds.PutMulti(bss).Error(), ShouldContainSubstr ing, "invalid PutMulti input")
346 })
347
348 Convey("static bad type (non-slice)", func() {
349 So(ds.PutMulti(100).Error(), ShouldContainSubstr ing, "invalid PutMulti input")
350 })
351
352 Convey("static bad type (slice of bad type)", func() {
353 So(ds.PutMulti([]int{}).Error(), ShouldContainSu bstring, "invalid PutMulti input")
354 })
355
356 Convey("dynamic can't serialize", func() {
357 fplss := []FakePLS{{failSave: true}, {}}
358 So(ds.PutMulti(fplss).Error(), ShouldContainSubs tring, "FakePLS.Save")
359 })
360
361 Convey("can't get keys", func() {
362 fplss := []FakePLS{{failGetMeta: true}, {}}
363 So(ds.PutMulti(fplss).Error(), ShouldContainSubs tring, "unable to extract $kind")
364 })
365
366 Convey("get single error for RPC failure", func() {
367 fplss := []FakePLS{{Kind: "FailAll"}, {}}
368 So(ds.PutMulti(fplss).Error(), ShouldEqual, "Put Multi fail all")
369 })
370
371 Convey("get multi error for individual failures", func() {
372 fplss := []FakePLS{{}, {Kind: "Fail"}}
373 So(ds.PutMulti(fplss), ShouldResemble, errors.Mu ltiError{nil, errors.New("PutMulti fail")})
374 })
375
376 Convey("put with non-modifyable type is an error", func( ) {
377 cs := CommonStruct{}
378 So(ds.Put(cs).Error(), ShouldContainSubstring, " invalid Put input type")
379 })
380 })
381
382 Convey("ok", func() {
383 Convey("[]S", func() {
384 css := make([]CommonStruct, 7)
385 for i := range css {
386 if i == 4 {
387 css[i].ID = 200
388 }
389 css[i].Value = int64(i)
390 }
391 So(ds.PutMulti(css), ShouldBeNil)
392 for i, cs := range css {
393 expect := int64(i + 1)
394 if i == 4 {
395 expect = 200
396 }
397 So(cs.ID, ShouldEqual, expect)
398 }
399 })
400
401 Convey("[]*S", func() {
402 css := make([]*CommonStruct, 7)
403 for i := range css {
404 css[i] = &CommonStruct{Value: int64(i)}
405 if i == 4 {
406 css[i].ID = 200
407 }
408 }
409 So(ds.PutMulti(css), ShouldBeNil)
410 for i, cs := range css {
411 expect := int64(i + 1)
412 if i == 4 {
413 expect = 200
414 }
415 So(cs.ID, ShouldEqual, expect)
416 }
417
418 s := &CommonStruct{}
419 So(ds.Put(s), ShouldBeNil)
420 So(s.ID, ShouldEqual, 1)
421 })
422
423 Convey("[]P", func() {
424 fplss := make([]FakePLS, 7)
425 for i := range fplss {
426 fplss[i].Value = int64(i)
427 if i == 4 {
428 fplss[i].IntID = int64(200)
429 }
430 }
431 So(ds.PutMulti(fplss), ShouldBeNil)
432 for i, fpls := range fplss {
433 expect := int64(i + 1)
434 if i == 4 {
435 expect = 200
436 }
437 So(fpls.IntID, ShouldEqual, expect)
438 }
439
440 pm := PropertyMap{"Value": {MkProperty(0)}, "$ki nd": {MkPropertyNI("Pmap")}}
441 So(ds.Put(pm), ShouldBeNil)
442 So(ds.KeyForObj(pm).IntID(), ShouldEqual, 1)
443 })
444
445 Convey("[]P (map)", func() {
446 pms := make([]PropertyMap, 7)
447 for i := range pms {
448 pms[i] = PropertyMap{
449 "$kind": {MkProperty("Pmap")},
450 "Value": {MkProperty(i)},
451 }
452 if i == 4 {
453 pms[i].SetMeta("id", int64(200))
454 }
455 }
456 So(ds.PutMulti(pms), ShouldBeNil)
457 for i, pm := range pms {
458 expect := int64(i + 1)
459 if i == 4 {
460 expect = 200
461 }
462 So(ds.KeyForObj(pm).String(), ShouldEqua l, fmt.Sprintf("/Pmap,%d", expect))
463 }
464 })
465
466 Convey("[]*P", func() {
467 fplss := make([]*FakePLS, 7)
468 for i := range fplss {
469 fplss[i] = &FakePLS{Value: int64(i)}
470 if i == 4 {
471 fplss[i].IntID = int64(200)
472 }
473 }
474 So(ds.PutMulti(fplss), ShouldBeNil)
475 for i, fpls := range fplss {
476 expect := int64(i + 1)
477 if i == 4 {
478 expect = 200
479 }
480 So(fpls.IntID, ShouldEqual, expect)
481 }
482 })
483
484 Convey("[]*P (map)", func() {
485 pms := make([]*PropertyMap, 7)
486 for i := range pms {
487 pms[i] = &PropertyMap{
488 "$kind": {MkProperty("Pmap")},
489 "Value": {MkProperty(i)},
490 }
491 if i == 4 {
492 pms[i].SetMeta("id", int64(200))
493 }
494 }
495 So(ds.PutMulti(pms), ShouldBeNil)
496 for i, pm := range pms {
497 expect := int64(i + 1)
498 if i == 4 {
499 expect = 200
500 }
501 So(ds.KeyForObj(*pm).String(), ShouldEqu al, fmt.Sprintf("/Pmap,%d", expect))
502 }
503 })
504
505 Convey("[]I", func() {
506 ifs := []interface{}{
507 &CommonStruct{Value: 0},
508 &FakePLS{Value: 1},
509 PropertyMap{"Value": {MkProperty(2)}, "$ kind": {MkPropertyNI("Pmap")}},
510 &PropertyMap{"Value": {MkProperty(3)}, " $kind": {MkPropertyNI("Pmap")}},
511 }
512 So(ds.PutMulti(ifs), ShouldBeNil)
513 for i := range ifs {
514 switch i {
515 case 0:
516 So(ifs[i].(*CommonStruct).ID, Sh ouldEqual, 1)
517 case 1:
518 fpls := ifs[i].(*FakePLS)
519 So(fpls.IntID, ShouldEqual, 2)
520 case 2:
521 So(ds.KeyForObj(ifs[i].(Property Map)).String(), ShouldEqual, "/Pmap,3")
522 case 3:
523 So(ds.KeyForObj(*ifs[i].(*Proper tyMap)).String(), ShouldEqual, "/Pmap,4")
524 }
525 }
526 })
527
528 })
529
530 })
531 }
532
533 func TestDelete(t *testing.T) {
534 t.Parallel()
535
536 Convey("Test Delete/DeleteMulti", t, func() {
537 c := info.Set(context.Background(), fakeInfo{})
538 c = SetRawFactory(c, fakeDatastoreFactory)
539 ds := Get(c)
540 So(ds, ShouldNotBeNil)
541
542 Convey("bad", func() {
543 Convey("get single error for RPC failure", func() {
544 keys := []Key{
545 NewKey("aid", "ns", "FailAll", "", 1, ni l),
546 NewKey("aid", "ns", "Ok", "", 1, nil),
547 }
548 So(ds.DeleteMulti(keys).Error(), ShouldEqual, "D eleteMulti fail all")
549 })
550
551 Convey("get multi error for individual failure", func() {
552 keys := []Key{
553 ds.NewKey("Ok", "", 1, nil),
554 ds.NewKey("Fail", "", 2, nil),
555 }
556 So(ds.DeleteMulti(keys).Error(), ShouldEqual, "D eleteMulti fail")
557 })
558
559 Convey("get single error when deleting a single", func() {
560 k := ds.NewKey("Fail", "", 1, nil)
561 So(ds.Delete(k).Error(), ShouldEqual, "DeleteMul ti fail")
562 })
563 })
564
565 })
566 }
567
568 func TestGet(t *testing.T) {
569 t.Parallel()
570
571 Convey("Test Get/GetMulti", t, func() {
572 c := info.Set(context.Background(), fakeInfo{})
573 c = SetRawFactory(c, fakeDatastoreFactory)
574 ds := Get(c)
575 So(ds, ShouldNotBeNil)
576
577 Convey("bad", func() {
578 Convey("static can't serialize", func() {
579 toGet := []badStruct{{}, {}}
580 So(ds.GetMulti(toGet).Error(), ShouldContainSubs tring, "invalid GetMulti input")
581 })
582
583 Convey("can't get keys", func() {
584 fplss := []FakePLS{{failGetMeta: true}, {}}
585 So(ds.GetMulti(fplss).Error(), ShouldContainSubs tring, "unable to extract $kind")
586 })
587
588 Convey("get single error for RPC failure", func() {
589 fplss := []FakePLS{
590 {IntID: 1, Kind: "FailAll"},
591 {IntID: 2},
592 }
593 So(ds.GetMulti(fplss).Error(), ShouldEqual, "Get Multi fail all")
594 })
595
596 Convey("get multi error for individual failures", func() {
597 fplss := []FakePLS{{IntID: 1}, {IntID: 2, Kind: "Fail"}}
598 So(ds.GetMulti(fplss), ShouldResemble, errors.Mu ltiError{nil, errors.New("GetMulti fail")})
599 })
600
601 Convey("get with non-modifiable type is an error", func( ) {
602 cs := CommonStruct{}
603 So(ds.Get(cs).Error(), ShouldContainSubstring, " invalid Get input type")
604 })
605 })
606
607 Convey("ok", func() {
608 Convey("Get", func() {
609 cs := &CommonStruct{ID: 1}
610 So(ds.Get(cs), ShouldBeNil)
611 So(cs.Value, ShouldEqual, 1)
612 })
613
614 Convey("Raw access too", func() {
615 rds := ds.Raw()
616 So(rds.GetMulti([]Key{rds.NewKey("Kind", "", 1, nil)}, func(pm PropertyMap, err error) {
617 So(err, ShouldBeNil)
618 So(pm["Value"][0].Value(), ShouldEqual, 1)
619 }), ShouldBeNil)
620 })
621 })
622
623 })
624 }
625
626 func TestGetAll(t *testing.T) {
627 t.Parallel()
628
629 Convey("Test GetAll", t, func() {
630 c := info.Set(context.Background(), fakeInfo{})
631 c = SetRawFactory(c, fakeDatastoreFactory)
632 ds := Get(c)
633 So(ds, ShouldNotBeNil)
634
635 q := ds.NewQuery("").Limit(5)
636
637 Convey("bad", func() {
638 Convey("nil target", func() {
639 So(ds.GetAll(q, (*[]PropertyMap)(nil)).Error(), ShouldContainSubstring, "dst: <nil>")
640 })
641
642 Convey("bad type", func() {
643 output := 100
644 So(ds.GetAll(q, &output).Error(), ShouldContainS ubstring, "invalid GetAll input type")
645 })
646
647 Convey("bad type (non pointer)", func() {
648 So(ds.GetAll(q, "moo").Error(), ShouldContainSub string, "must have a ptr-to-slice")
649 })
650
651 Convey("bad type (underspecified)", func() {
652 output := []PropertyLoadSaver(nil)
653 So(ds.GetAll(q, &output).Error(), ShouldContainS ubstring, "invalid GetAll input type")
654 })
655 })
656
657 Convey("ok", func() {
658 Convey("*[]S", func() {
659 output := []CommonStruct(nil)
660 So(ds.GetAll(q, &output), ShouldBeNil)
661 So(len(output), ShouldEqual, 5)
662 for i, o := range output {
663 So(o.ID, ShouldEqual, i+1)
664 So(o.Value, ShouldEqual, i)
665 }
666 })
667
668 Convey("*[]*S", func() {
669 output := []*CommonStruct(nil)
670 So(ds.GetAll(q, &output), ShouldBeNil)
671 So(len(output), ShouldEqual, 5)
672 for i, o := range output {
673 So(o.ID, ShouldEqual, i+1)
674 So(o.Value, ShouldEqual, i)
675 }
676 })
677
678 Convey("*[]P", func() {
679 output := []FakePLS(nil)
680 So(ds.GetAll(q, &output), ShouldBeNil)
681 So(len(output), ShouldEqual, 5)
682 for i, o := range output {
683 So(o.gotLoaded, ShouldBeTrue)
684 So(o.IntID, ShouldEqual, i+1)
685 So(o.Value, ShouldEqual, i)
686 }
687 })
688
689 Convey("*[]P (map)", func() {
690 output := []PropertyMap(nil)
691 So(ds.GetAll(q, &output), ShouldBeNil)
692 So(len(output), ShouldEqual, 5)
693 for i, o := range output {
694 k, err := o.GetMeta("key")
695 So(err, ShouldBeNil)
696 So(k.(Key).IntID(), ShouldEqual, i+1)
697 So(o["Value"][0].Value().(int64), Should Equal, i)
698 }
699 })
700
701 Convey("*[]*P", func() {
702 output := []*FakePLS(nil)
703 So(ds.GetAll(q, &output), ShouldBeNil)
704 So(len(output), ShouldEqual, 5)
705 for i, o := range output {
706 So(o.gotLoaded, ShouldBeTrue)
707 So(o.IntID, ShouldEqual, i+1)
708 So(o.Value, ShouldEqual, i)
709 }
710 })
711
712 Convey("*[]*P (map)", func() {
713 output := []*PropertyMap(nil)
714 So(ds.GetAll(q, &output), ShouldBeNil)
715 So(len(output), ShouldEqual, 5)
716 for i, op := range output {
717 o := *op
718 k, err := o.GetMeta("key")
719 So(err, ShouldBeNil)
720 So(k.(Key).IntID(), ShouldEqual, i+1)
721 So(o["Value"][0].Value().(int64), Should Equal, i)
722 }
723 })
724
725 Convey("*[]Key", func() {
726 output := []Key(nil)
727 So(ds.GetAll(q, &output), ShouldBeNil)
728 So(len(output), ShouldEqual, 5)
729 for i, k := range output {
730 So(k.IntID(), ShouldEqual, i+1)
731 }
732 })
733
734 })
735 })
736 }
737
738 func TestRun(t *testing.T) {
739 t.Parallel()
740
741 Convey("Test Run", t, func() {
742 c := info.Set(context.Background(), fakeInfo{})
743 c = SetRawFactory(c, fakeDatastoreFactory)
744 ds := Get(c)
745 So(ds, ShouldNotBeNil)
746
747 q := ds.NewQuery("").Limit(5)
748
749 Convey("bad", func() {
750 Convey("bad proto type", func() {
751 So(ds.Run(q, 100, func(obj interface{}, _ func() (Cursor, error)) bool {
752 panic("never here!")
753 }).Error(), ShouldContainSubstring, "invalid Run proto type")
754 })
755
756 Convey("early abort on error", func() {
757 rq := q.(*fakeQuery).Fail(3)
758 i := 0
759 So(ds.Run(rq, CommonStruct{}, func(_ interface{} , _ func() (Cursor, error)) bool {
760 i++
761 return true
762 }).Error(), ShouldEqual, "Query fail")
763 So(i, ShouldEqual, 3)
764 })
765
766 Convey("return error on serialization failure", func() {
767 So(ds.Run(q, permaBad{}, func(_ interface{}, _ f unc() (Cursor, error)) bool {
768 panic("never here")
769 }).Error(), ShouldEqual, "permaBad")
770 })
771 })
772
773 Convey("ok", func() {
774 Convey("*S", func() {
775 i := 0
776 So(ds.Run(q, (*CommonStruct)(nil), func(obj inte rface{}, _ func() (Cursor, error)) bool {
777 cs := obj.(*CommonStruct)
778 So(cs.ID, ShouldEqual, i+1)
779 So(cs.Value, ShouldEqual, i)
780 i++
781 return true
782 }), ShouldBeNil)
783 })
784
785 Convey("*P", func() {
786 i := 0
787 So(ds.Run(q.Limit(12), (*FakePLS)(nil), func(obj interface{}, _ func() (Cursor, error)) bool {
788 fpls := obj.(*FakePLS)
789 So(fpls.gotLoaded, ShouldBeTrue)
790 if i == 10 {
791 So(fpls.StringID, ShouldEqual, " eleven")
792 } else {
793 So(fpls.IntID, ShouldEqual, i+1)
794 }
795 So(fpls.Value, ShouldEqual, i)
796 i++
797 return true
798 }), ShouldBeNil)
799 })
800
801 Convey("*P (map)", func() {
802 i := 0
803 So(ds.Run(q, (*PropertyMap)(nil), func(obj inter face{}, _ func() (Cursor, error)) bool {
804 pm := *obj.(*PropertyMap)
805 k, err := pm.GetMeta("key")
806 So(err, ShouldBeNil)
807 So(k.(Key).IntID(), ShouldEqual, i+1)
808 So(pm["Value"][0].Value(), ShouldEqual, i)
809 i++
810 return true
811 }), ShouldBeNil)
812 })
813
814 Convey("S", func() {
815 i := 0
816 So(ds.Run(q, CommonStruct{}, func(obj interface{ }, _ func() (Cursor, error)) bool {
817 cs := obj.(CommonStruct)
818 So(cs.ID, ShouldEqual, i+1)
819 So(cs.Value, ShouldEqual, i)
820 i++
821 return true
822 }), ShouldBeNil)
823 })
824
825 Convey("P", func() {
826 i := 0
827 So(ds.Run(q, FakePLS{}, func(obj interface{}, _ func() (Cursor, error)) bool {
828 fpls := obj.(FakePLS)
829 So(fpls.gotLoaded, ShouldBeTrue)
830 So(fpls.IntID, ShouldEqual, i+1)
831 So(fpls.Value, ShouldEqual, i)
832 i++
833 return true
834 }), ShouldBeNil)
835 })
836
837 Convey("P (map)", func() {
838 i := 0
839 So(ds.Run(q, (PropertyMap)(nil), func(obj interf ace{}, _ func() (Cursor, error)) bool {
840 pm := obj.(PropertyMap)
841 k, err := pm.GetMeta("key")
842 So(err, ShouldBeNil)
843 So(k.(Key).IntID(), ShouldEqual, i+1)
844 So(pm["Value"][0].Value(), ShouldEqual, i)
845 i++
846 return true
847 }), ShouldBeNil)
848 })
849
850 Convey("*Key", func() {
851 i := 0
852 So(ds.Run(q, (*Key)(nil), func(obj interface{}, _ func() (Cursor, error)) bool {
853 So(obj.(Key).IntID(), ShouldEqual, i+1)
854 i++
855 return true
856 }), ShouldBeNil)
857 })
858
859 })
860 })
861 }
OLDNEW
« no previous file with comments | « service/datastore/datastore.go ('k') | service/datastore/interface.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698