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

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

Issue 2302743002: Interface update, per-method Contexts. (Closed)
Patch Set: Lightning talk licenses. Created 4 years, 3 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/dumper/dumper.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The LUCI Authors. All rights reserved. 1 // Copyright 2015 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0 2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file. 3 // that can be found in the LICENSE file.
4 4
5 // adapted from github.com/golang/appengine/datastore 5 // adapted from github.com/golang/appengine/datastore
6 6
7 package datastore 7 package datastore
8 8
9 import ( 9 import (
10 "bytes" 10 "bytes"
11 "fmt" 11 "fmt"
12 "io/ioutil" 12 "io/ioutil"
13 "os" 13 "os"
14 "path/filepath" 14 "path/filepath"
15 "runtime" 15 "runtime"
16 "testing" 16 "testing"
17 17
18 "github.com/luci/gae/service/info" 18 "github.com/luci/gae/service/info"
19 "github.com/luci/luci-go/common/errors" 19 "github.com/luci/luci-go/common/errors"
20
21 "golang.org/x/net/context"
22
20 . "github.com/luci/luci-go/common/testing/assertions" 23 . "github.com/luci/luci-go/common/testing/assertions"
21 . "github.com/smartystreets/goconvey/convey" 24 . "github.com/smartystreets/goconvey/convey"
22 "golang.org/x/net/context"
23 ) 25 )
24 26
25 func fakeDatastoreFactory(c context.Context, wantTxn bool) RawInterface { 27 func fakeDatastoreFactory(c context.Context) RawInterface {
26 » i := info.Get(c) 28 » return &fakeDatastore{Context: c}
27 » fds := fakeDatastore{
28 » » aid: i.FullyQualifiedAppID(),
29 » }
30 » fds.ns, _ = i.GetNamespace()
31 » return &fds
32 } 29 }
33 30
34 var ( 31 var (
35 errFail = errors.New("Individual element fail") 32 errFail = errors.New("Individual element fail")
36 errFailAll = errors.New("Operation fail") 33 errFailAll = errors.New("Operation fail")
37 ) 34 )
38 35
39 type fakeDatastore struct { 36 type fakeDatastore struct {
37 context.Context
40 RawInterface 38 RawInterface
41 aid string
42 ns string
43 }
44
45 func (f *fakeDatastore) mkKey(elems ...interface{}) *Key {
46 return MakeKey(f.aid, f.ns, elems...)
47 }
48
49 func (f *fakeDatastore) newKey(kind, stringID string, intID int64, parent *Key) *Key {
50 return NewKey(f.aid, f.ns, kind, stringID, intID, parent)
51 } 39 }
52 40
53 func (f *fakeDatastore) AllocateIDs(keys []*Key, cb NewKeyCB) error { 41 func (f *fakeDatastore) AllocateIDs(keys []*Key, cb NewKeyCB) error {
54 if keys[0].Kind() == "FailAll" { 42 if keys[0].Kind() == "FailAll" {
55 return errFailAll 43 return errFailAll
56 } 44 }
57 for i, k := range keys { 45 for i, k := range keys {
58 if k.Kind() == "Fail" { 46 if k.Kind() == "Fail" {
59 cb(nil, errFail) 47 cb(nil, errFail)
60 } else { 48 } else {
61 » » » cb(f.newKey(k.Kind(), "", int64(i+1), k.Parent()), nil) 49 » » » cb(NewKey(f, k.Kind(), "", int64(i+1), k.Parent()), nil)
62 } 50 }
63 } 51 }
64 return nil 52 return nil
65 } 53 }
66 54
67 func (f *fakeDatastore) Run(fq *FinalizedQuery, cb RawRunCB) error { 55 func (f *fakeDatastore) Run(fq *FinalizedQuery, cb RawRunCB) error {
68 lim, _ := fq.Limit() 56 lim, _ := fq.Limit()
69 57
70 cursCB := func() (Cursor, error) { 58 cursCB := func() (Cursor, error) {
71 return fakeCursor("CURSOR"), nil 59 return fakeCursor("CURSOR"), nil
72 } 60 }
73 61
74 for i := int32(0); i < lim; i++ { 62 for i := int32(0); i < lim; i++ {
75 if v, ok := fq.eqFilts["$err_single"]; ok { 63 if v, ok := fq.eqFilts["$err_single"]; ok {
76 idx := fq.eqFilts["$err_single_idx"][0].Value().(int64) 64 idx := fq.eqFilts["$err_single_idx"][0].Value().(int64)
77 if idx == int64(i) { 65 if idx == int64(i) {
78 return errors.New(v[0].Value().(string)) 66 return errors.New(v[0].Value().(string))
79 } 67 }
80 } 68 }
81 » » k := f.mkKey("Kind", i+1) 69 » » k := MakeKey(f, "Kind", i+1)
82 if i == 10 { 70 if i == 10 {
83 » » » k = f.mkKey("Kind", "eleven") 71 » » » k = MakeKey(f, "Kind", "eleven")
84 } 72 }
85 pm := PropertyMap{"Value": MkProperty(i)} 73 pm := PropertyMap{"Value": MkProperty(i)}
86 if err := cb(k, pm, cursCB); err != nil { 74 if err := cb(k, pm, cursCB); err != nil {
87 if err == Stop { 75 if err == Stop {
88 err = nil 76 err = nil
89 } 77 }
90 return err 78 return err
91 } 79 }
92 } 80 }
93 return nil 81 return nil
94 } 82 }
95 83
96 func (f *fakeDatastore) PutMulti(keys []*Key, vals []PropertyMap, cb NewKeyCB) e rror { 84 func (f *fakeDatastore) PutMulti(keys []*Key, vals []PropertyMap, cb NewKeyCB) e rror {
97 if keys[0].Kind() == "FailAll" { 85 if keys[0].Kind() == "FailAll" {
98 return errFailAll 86 return errFailAll
99 } 87 }
100 _, assertExtra := vals[0].GetMeta("assertExtra") 88 _, assertExtra := vals[0].GetMeta("assertExtra")
101 for i, k := range keys { 89 for i, k := range keys {
102 err := error(nil) 90 err := error(nil)
103 if k.Kind() == "Fail" { 91 if k.Kind() == "Fail" {
104 err = errFail 92 err = errFail
105 } else { 93 } else {
106 So(vals[i].Slice("Value"), ShouldResemble, PropertySlice {MkProperty(i)}) 94 So(vals[i].Slice("Value"), ShouldResemble, PropertySlice {MkProperty(i)})
107 if assertExtra { 95 if assertExtra {
108 So(vals[i].Slice("Extra"), ShouldResemble, Prope rtySlice{MkProperty("whoa")}) 96 So(vals[i].Slice("Extra"), ShouldResemble, Prope rtySlice{MkProperty("whoa")})
109 } 97 }
110 if k.IsIncomplete() { 98 if k.IsIncomplete() {
111 » » » » k = NewKey(k.AppID(), k.Namespace(), k.Kind(), " ", int64(i+1), k.Parent()) 99 » » » » k = k.KeyContext().NewKey(k.Kind(), "", int64(i+ 1), k.Parent())
112 } 100 }
113 } 101 }
114 cb(k, err) 102 cb(k, err)
115 } 103 }
116 return nil 104 return nil
117 } 105 }
118 106
119 const noSuchEntityID = 0xdead 107 const noSuchEntityID = 0xdead
120 108
121 func (f *fakeDatastore) GetMulti(keys []*Key, _meta MultiMetaGetter, cb GetMulti CB) error { 109 func (f *fakeDatastore) GetMulti(keys []*Key, _meta MultiMetaGetter, cb GetMulti CB) error {
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 } 311 }
324 312
325 var _ MetaGetterSetter = (*MGSWithNoKind)(nil) 313 var _ MetaGetterSetter = (*MGSWithNoKind)(nil)
326 314
327 func TestKeyForObj(t *testing.T) { 315 func TestKeyForObj(t *testing.T) {
328 t.Parallel() 316 t.Parallel()
329 317
330 Convey("Test interface.KeyForObj", t, func() { 318 Convey("Test interface.KeyForObj", t, func() {
331 c := info.Set(context.Background(), fakeInfo{}) 319 c := info.Set(context.Background(), fakeInfo{})
332 c = SetRawFactory(c, fakeDatastoreFactory) 320 c = SetRawFactory(c, fakeDatastoreFactory)
333 ds := Get(c)
334 321
335 » » k := ds.MakeKey("Hello", "world") 322 » » k := MakeKey(c, "Hello", "world")
336 323
337 Convey("good", func() { 324 Convey("good", func() {
338 Convey("struct containing $key", func() { 325 Convey("struct containing $key", func() {
339 type keyStruct struct { 326 type keyStruct struct {
340 Key *Key `gae:"$key"` 327 Key *Key `gae:"$key"`
341 } 328 }
342 329
343 ks := &keyStruct{k} 330 ks := &keyStruct{k}
344 » » » » So(ds.KeyForObj(ks), ShouldEqual, k) 331 » » » » So(KeyForObj(c, ks), ShouldEqual, k)
345 }) 332 })
346 333
347 Convey("struct containing default $id and $kind", func() { 334 Convey("struct containing default $id and $kind", func() {
348 type idStruct struct { 335 type idStruct struct {
349 id string `gae:"$id,wut"` 336 id string `gae:"$id,wut"`
350 knd string `gae:"$kind,SuperKind"` 337 knd string `gae:"$kind,SuperKind"`
351 } 338 }
352 339
353 » » » » So(ds.KeyForObj(&idStruct{}).String(), ShouldEqu al, `s~aid:ns:/SuperKind,"wut"`) 340 » » » » So(KeyForObj(c, &idStruct{}).String(), ShouldEqu al, `s~aid:ns:/SuperKind,"wut"`)
354 }) 341 })
355 342
356 Convey("struct containing $id and $parent", func() { 343 Convey("struct containing $id and $parent", func() {
357 » » » » So(ds.KeyForObj(&CommonStruct{ID: 4}).String(), ShouldEqual, `s~aid:ns:/CommonStruct,4`) 344 » » » » So(KeyForObj(c, &CommonStruct{ID: 4}).String(), ShouldEqual, `s~aid:ns:/CommonStruct,4`)
358 345
359 » » » » So(ds.KeyForObj(&CommonStruct{ID: 4, Parent: k}) .String(), ShouldEqual, `s~aid:ns:/Hello,"world"/CommonStruct,4`) 346 » » » » So(KeyForObj(c, &CommonStruct{ID: 4, Parent: k}) .String(), ShouldEqual, `s~aid:ns:/Hello,"world"/CommonStruct,4`)
360 }) 347 })
361 348
362 Convey("a propmap with $key", func() { 349 Convey("a propmap with $key", func() {
363 pm := PropertyMap{} 350 pm := PropertyMap{}
364 So(pm.SetMeta("key", k), ShouldBeTrue) 351 So(pm.SetMeta("key", k), ShouldBeTrue)
365 » » » » So(ds.KeyForObj(pm).String(), ShouldEqual, `s~ai d:ns:/Hello,"world"`) 352 » » » » So(KeyForObj(c, pm).String(), ShouldEqual, `s~ai d:ns:/Hello,"world"`)
366 }) 353 })
367 354
368 Convey("a propmap with $id, $kind, $parent", func() { 355 Convey("a propmap with $id, $kind, $parent", func() {
369 pm := PropertyMap{} 356 pm := PropertyMap{}
370 So(pm.SetMeta("id", 100), ShouldBeTrue) 357 So(pm.SetMeta("id", 100), ShouldBeTrue)
371 So(pm.SetMeta("kind", "Sup"), ShouldBeTrue) 358 So(pm.SetMeta("kind", "Sup"), ShouldBeTrue)
372 » » » » So(ds.KeyForObj(pm).String(), ShouldEqual, `s~ai d:ns:/Sup,100`) 359 » » » » So(KeyForObj(c, pm).String(), ShouldEqual, `s~ai d:ns:/Sup,100`)
373 360
374 So(pm.SetMeta("parent", k), ShouldBeTrue) 361 So(pm.SetMeta("parent", k), ShouldBeTrue)
375 » » » » So(ds.KeyForObj(pm).String(), ShouldEqual, `s~ai d:ns:/Hello,"world"/Sup,100`) 362 » » » » So(KeyForObj(c, pm).String(), ShouldEqual, `s~ai d:ns:/Hello,"world"/Sup,100`)
376 }) 363 })
377 364
378 Convey("a pls with $id, $parent", func() { 365 Convey("a pls with $id, $parent", func() {
379 pls := GetPLS(&CommonStruct{ID: 1}) 366 pls := GetPLS(&CommonStruct{ID: 1})
380 » » » » So(ds.KeyForObj(pls).String(), ShouldEqual, `s~a id:ns:/CommonStruct,1`) 367 » » » » So(KeyForObj(c, pls).String(), ShouldEqual, `s~a id:ns:/CommonStruct,1`)
381 368
382 So(pls.SetMeta("parent", k), ShouldBeTrue) 369 So(pls.SetMeta("parent", k), ShouldBeTrue)
383 » » » » So(ds.KeyForObj(pls).String(), ShouldEqual, `s~a id:ns:/Hello,"world"/CommonStruct,1`) 370 » » » » So(KeyForObj(c, pls).String(), ShouldEqual, `s~a id:ns:/Hello,"world"/CommonStruct,1`)
384 }) 371 })
385 }) 372 })
386 373
387 Convey("bad", func() { 374 Convey("bad", func() {
388 Convey("a propmap without $kind", func() { 375 Convey("a propmap without $kind", func() {
389 pm := PropertyMap{} 376 pm := PropertyMap{}
390 So(pm.SetMeta("id", 100), ShouldBeTrue) 377 So(pm.SetMeta("id", 100), ShouldBeTrue)
391 » » » » So(func() { ds.KeyForObj(pm) }, ShouldPanic) 378 » » » » So(func() { KeyForObj(c, pm) }, ShouldPanic)
392 }) 379 })
393 380
394 Convey("a bad object", func() { 381 Convey("a bad object", func() {
395 type BadObj struct { 382 type BadObj struct {
396 ID int64 `gae:"$id"` 383 ID int64 `gae:"$id"`
397 384
398 NonSerializableField complex64 385 NonSerializableField complex64
399 } 386 }
400 387
401 » » » » So(func() { ds.KeyForObjErr(&BadObj{ID: 1}) }, S houldPanicLike, 388 » » » » So(func() { KeyForObj(c, &BadObj{ID: 1}) }, Shou ldPanicLike,
402 `field "NonSerializableField" has invali d type: complex64`) 389 `field "NonSerializableField" has invali d type: complex64`)
403 }) 390 })
404 }) 391 })
405 }) 392 })
406 } 393 }
407 394
408 func TestPopulateKey(t *testing.T) { 395 func TestPopulateKey(t *testing.T) {
409 t.Parallel() 396 t.Parallel()
410 397
411 Convey("Test PopulateKey", t, func() { 398 Convey("Test PopulateKey", t, func() {
412 » » k := NewKey("app", "namespace", "kind", "", 1337, nil) 399 » » k := KeyContext{"app", "namespace"}.NewKey("kind", "", 1337, nil )
413 400
414 Convey("Can set the key of a common struct.", func() { 401 Convey("Can set the key of a common struct.", func() {
415 var cs CommonStruct 402 var cs CommonStruct
416 403
417 So(PopulateKey(&cs, k), ShouldBeTrue) 404 So(PopulateKey(&cs, k), ShouldBeTrue)
418 So(cs.ID, ShouldEqual, 1337) 405 So(cs.ID, ShouldEqual, 1337)
419 }) 406 })
420 407
421 Convey("Will not set the value of a singleton struct.", func() { 408 Convey("Will not set the value of a singleton struct.", func() {
422 var ss SingletonStruct 409 var ss SingletonStruct
(...skipping 15 matching lines...) Expand all
438 }) 425 })
439 }) 426 })
440 } 427 }
441 428
442 func TestAllocateIDs(t *testing.T) { 429 func TestAllocateIDs(t *testing.T) {
443 t.Parallel() 430 t.Parallel()
444 431
445 Convey("A testing environment", t, func() { 432 Convey("A testing environment", t, func() {
446 c := info.Set(context.Background(), fakeInfo{}) 433 c := info.Set(context.Background(), fakeInfo{})
447 c = SetRawFactory(c, fakeDatastoreFactory) 434 c = SetRawFactory(c, fakeDatastoreFactory)
448 ds := Get(c)
449 435
450 Convey("Testing AllocateIDs", func() { 436 Convey("Testing AllocateIDs", func() {
451 Convey("Will return nil if no entities are supplied.", f unc() { 437 Convey("Will return nil if no entities are supplied.", f unc() {
452 » » » » So(ds.AllocateIDs(), ShouldBeNil) 438 » » » » So(AllocateIDs(c), ShouldBeNil)
453 }) 439 })
454 440
455 Convey("single struct", func() { 441 Convey("single struct", func() {
456 cs := CommonStruct{Value: 1} 442 cs := CommonStruct{Value: 1}
457 » » » » So(ds.AllocateIDs(&cs), ShouldBeNil) 443 » » » » So(AllocateIDs(c, &cs), ShouldBeNil)
458 So(cs.ID, ShouldEqual, 1) 444 So(cs.ID, ShouldEqual, 1)
459 }) 445 })
460 446
461 Convey("struct slice", func() { 447 Convey("struct slice", func() {
462 csSlice := []*CommonStruct{{Value: 1}, {Value: 2 }} 448 csSlice := []*CommonStruct{{Value: 1}, {Value: 2 }}
463 » » » » So(ds.AllocateIDs(csSlice), ShouldBeNil) 449 » » » » So(AllocateIDs(c, csSlice), ShouldBeNil)
464 So(csSlice, ShouldResemble, []*CommonStruct{{ID: 1, Value: 1}, {ID: 2, Value: 2}}) 450 So(csSlice, ShouldResemble, []*CommonStruct{{ID: 1, Value: 1}, {ID: 2, Value: 2}})
465 }) 451 })
466 452
467 Convey("single key will fail", func() { 453 Convey("single key will fail", func() {
468 » » » » singleKey := ds.MakeKey("FooParent", "BarParent" , "Foo", "Bar") 454 » » » » singleKey := MakeKey(c, "FooParent", "BarParent" , "Foo", "Bar")
469 » » » » So(func() { ds.AllocateIDs(singleKey) }, ShouldP anicLike, 455 » » » » So(func() { AllocateIDs(c, singleKey) }, ShouldP anicLike,
470 "invalid input type (*datastore.Key): no t a PLS, pointer-to-struct, or slice thereof") 456 "invalid input type (*datastore.Key): no t a PLS, pointer-to-struct, or slice thereof")
471 }) 457 })
472 458
473 Convey("key slice", func() { 459 Convey("key slice", func() {
474 » » » » k0 := ds.MakeKey("Foo", "Bar") 460 » » » » k0 := MakeKey(c, "Foo", "Bar")
475 » » » » k1 := ds.MakeKey("Baz", "Qux") 461 » » » » k1 := MakeKey(c, "Baz", "Qux")
476 keySlice := []*Key{k0, k1} 462 keySlice := []*Key{k0, k1}
477 » » » » So(ds.AllocateIDs(keySlice), ShouldBeNil) 463 » » » » So(AllocateIDs(c, keySlice), ShouldBeNil)
478 » » » » So(keySlice[0].Equal(ds.MakeKey("Foo", 1)), Shou ldBeTrue) 464 » » » » So(keySlice[0].Equal(MakeKey(c, "Foo", 1)), Shou ldBeTrue)
479 » » » » So(keySlice[1].Equal(ds.MakeKey("Baz", 2)), Shou ldBeTrue) 465 » » » » So(keySlice[1].Equal(MakeKey(c, "Baz", 2)), Shou ldBeTrue)
480 466
481 // The original keys should not have changed. 467 // The original keys should not have changed.
482 » » » » So(k0.Equal(ds.MakeKey("Foo", "Bar")), ShouldBeT rue) 468 » » » » So(k0.Equal(MakeKey(c, "Foo", "Bar")), ShouldBeT rue)
483 » » » » So(k1.Equal(ds.MakeKey("Baz", "Qux")), ShouldBeT rue) 469 » » » » So(k1.Equal(MakeKey(c, "Baz", "Qux")), ShouldBeT rue)
484 }) 470 })
485 471
486 Convey("fail all key slice", func() { 472 Convey("fail all key slice", func() {
487 » » » » keySlice := []*Key{ds.MakeKey("FailAll", "oops") , ds.MakeKey("Baz", "Qux")} 473 » » » » keySlice := []*Key{MakeKey(c, "FailAll", "oops") , MakeKey(c, "Baz", "Qux")}
488 » » » » So(ds.AllocateIDs(keySlice), ShouldEqual, errFai lAll) 474 » » » » So(AllocateIDs(c, keySlice), ShouldEqual, errFai lAll)
489 So(keySlice[0].StringID(), ShouldEqual, "oops") 475 So(keySlice[0].StringID(), ShouldEqual, "oops")
490 So(keySlice[1].StringID(), ShouldEqual, "Qux") 476 So(keySlice[1].StringID(), ShouldEqual, "Qux")
491 }) 477 })
492 478
493 Convey("fail key slice", func() { 479 Convey("fail key slice", func() {
494 » » » » keySlice := []*Key{ds.MakeKey("Fail", "oops"), d s.MakeKey("Baz", "Qux")} 480 » » » » keySlice := []*Key{MakeKey(c, "Fail", "oops"), M akeKey(c, "Baz", "Qux")}
495 » » » » So(ds.AllocateIDs(keySlice), ShouldResemble, err ors.MultiError{errFail, nil}) 481 » » » » So(AllocateIDs(c, keySlice), ShouldResemble, err ors.MultiError{errFail, nil})
496 So(keySlice[0].StringID(), ShouldEqual, "oops") 482 So(keySlice[0].StringID(), ShouldEqual, "oops")
497 So(keySlice[1].IntID(), ShouldEqual, 2) 483 So(keySlice[1].IntID(), ShouldEqual, 2)
498 }) 484 })
499 485
500 Convey("vararg with errors", func() { 486 Convey("vararg with errors", func() {
501 successSlice := []CommonStruct{{Value: 0}, {Valu e: 1}} 487 successSlice := []CommonStruct{{Value: 0}, {Valu e: 1}}
502 failSlice := []FakePLS{{Kind: "Fail"}, {Value: 3 }} 488 failSlice := []FakePLS{{Kind: "Fail"}, {Value: 3 }}
503 emptySlice := []CommonStruct(nil) 489 emptySlice := []CommonStruct(nil)
504 cs0 := CommonStruct{Value: 4} 490 cs0 := CommonStruct{Value: 4}
505 cs1 := FakePLS{Kind: "Fail", Value: 5} 491 cs1 := FakePLS{Kind: "Fail", Value: 5}
506 » » » » keySlice := []*Key{ds.MakeKey("Foo", "Bar"), ds. MakeKey("Baz", "Qux")} 492 » » » » keySlice := []*Key{MakeKey(c, "Foo", "Bar"), Mak eKey(c, "Baz", "Qux")}
507 fpls := FakePLS{StringID: "ohai", Value: 6} 493 fpls := FakePLS{StringID: "ohai", Value: 6}
508 494
509 » » » » err := ds.AllocateIDs(successSlice, failSlice, e mptySlice, &cs0, &cs1, keySlice, &fpls) 495 » » » » err := AllocateIDs(c, successSlice, failSlice, e mptySlice, &cs0, &cs1, keySlice, &fpls)
510 So(err, ShouldResemble, errors.MultiError{ 496 So(err, ShouldResemble, errors.MultiError{
511 nil, errors.MultiError{errFail, nil}, ni l, nil, errFail, nil, nil}) 497 nil, errors.MultiError{errFail, nil}, ni l, nil, errFail, nil, nil})
512 So(successSlice[0].ID, ShouldEqual, 1) 498 So(successSlice[0].ID, ShouldEqual, 1)
513 So(successSlice[1].ID, ShouldEqual, 2) 499 So(successSlice[1].ID, ShouldEqual, 2)
514 So(failSlice[1].IntID, ShouldEqual, 4) 500 So(failSlice[1].IntID, ShouldEqual, 4)
515 So(cs0.ID, ShouldEqual, 5) 501 So(cs0.ID, ShouldEqual, 5)
516 » » » » So(keySlice[0].Equal(ds.MakeKey("Foo", 7)), Shou ldBeTrue) 502 » » » » So(keySlice[0].Equal(MakeKey(c, "Foo", 7)), Shou ldBeTrue)
517 » » » » So(keySlice[1].Equal(ds.MakeKey("Baz", 8)), Shou ldBeTrue) 503 » » » » So(keySlice[1].Equal(MakeKey(c, "Baz", 8)), Shou ldBeTrue)
518 So(fpls.IntID, ShouldEqual, 9) 504 So(fpls.IntID, ShouldEqual, 9)
519 }) 505 })
520 }) 506 })
521 }) 507 })
522 } 508 }
523 509
524 func TestPut(t *testing.T) { 510 func TestPut(t *testing.T) {
525 t.Parallel() 511 t.Parallel()
526 512
527 Convey("A testing environment", t, func() { 513 Convey("A testing environment", t, func() {
528 c := info.Set(context.Background(), fakeInfo{}) 514 c := info.Set(context.Background(), fakeInfo{})
529 c = SetRawFactory(c, fakeDatastoreFactory) 515 c = SetRawFactory(c, fakeDatastoreFactory)
530 ds := Get(c)
531 516
532 Convey("Testing Put", func() { 517 Convey("Testing Put", func() {
533 Convey("bad", func() { 518 Convey("bad", func() {
534 Convey("static can't serialize", func() { 519 Convey("static can't serialize", func() {
535 bss := []badStruct{{}, {}} 520 bss := []badStruct{{}, {}}
536 » » » » » So(func() { ds.Put(bss) }, ShouldPanicLi ke, 521 » » » » » So(func() { Put(c, bss) }, ShouldPanicLi ke,
537 `field "Compy" has invalid type` ) 522 `field "Compy" has invalid type` )
538 }) 523 })
539 524
540 Convey("static ptr can't serialize", func() { 525 Convey("static ptr can't serialize", func() {
541 bss := []*badStruct{{}, {}} 526 bss := []*badStruct{{}, {}}
542 » » » » » So(func() { ds.Put(bss) }, ShouldPanicLi ke, 527 » » » » » So(func() { Put(c, bss) }, ShouldPanicLi ke,
543 `field "Compy" has invalid type: complex64`) 528 `field "Compy" has invalid type: complex64`)
544 }) 529 })
545 530
546 Convey("static bad type", func() { 531 Convey("static bad type", func() {
547 » » » » » So(func() { ds.Put(100) }, ShouldPanicLi ke, 532 » » » » » So(func() { Put(c, 100) }, ShouldPanicLi ke,
548 "invalid input type (int): not a PLS, pointer-to-struct, or slice thereof") 533 "invalid input type (int): not a PLS, pointer-to-struct, or slice thereof")
549 }) 534 })
550 535
551 Convey("static bad type (slice of bad type)", fu nc() { 536 Convey("static bad type (slice of bad type)", fu nc() {
552 » » » » » So(func() { ds.Put([]int{}) }, ShouldPan icLike, 537 » » » » » So(func() { Put(c, []int{}) }, ShouldPan icLike,
553 "invalid input type ([]int): not a PLS, pointer-to-struct, or slice thereof") 538 "invalid input type ([]int): not a PLS, pointer-to-struct, or slice thereof")
554 }) 539 })
555 540
556 Convey("dynamic can't serialize", func() { 541 Convey("dynamic can't serialize", func() {
557 fplss := []FakePLS{{failSave: true}, {}} 542 fplss := []FakePLS{{failSave: true}, {}}
558 » » » » » So(ds.Put(fplss), ShouldErrLike, "FakePL S.Save") 543 » » » » » So(Put(c, fplss), ShouldErrLike, "FakePL S.Save")
559 }) 544 })
560 545
561 Convey("can't get keys", func() { 546 Convey("can't get keys", func() {
562 fplss := []FakePLS{{failGetMeta: true}, {}} 547 fplss := []FakePLS{{failGetMeta: true}, {}}
563 » » » » » So(ds.Put(fplss), ShouldErrLike, "unable to extract $kind") 548 » » » » » So(Put(c, fplss), ShouldErrLike, "unable to extract $kind")
564 }) 549 })
565 550
566 Convey("get single error for RPC failure", func( ) { 551 Convey("get single error for RPC failure", func( ) {
567 fplss := []FakePLS{{Kind: "FailAll"}, {} } 552 fplss := []FakePLS{{Kind: "FailAll"}, {} }
568 » » » » » So(ds.Put(fplss), ShouldEqual, errFailAl l) 553 » » » » » So(Put(c, fplss), ShouldEqual, errFailAl l)
569 }) 554 })
570 555
571 Convey("get multi error for individual failures" , func() { 556 Convey("get multi error for individual failures" , func() {
572 fplss := []FakePLS{{}, {Kind: "Fail"}} 557 fplss := []FakePLS{{}, {Kind: "Fail"}}
573 » » » » » So(ds.Put(fplss), ShouldResemble, errors .MultiError{nil, errFail}) 558 » » » » » So(Put(c, fplss), ShouldResemble, errors .MultiError{nil, errFail})
574 }) 559 })
575 560
576 Convey("get with *Key is an error", func() { 561 Convey("get with *Key is an error", func() {
577 » » » » » So(func() { ds.Get(&Key{}) }, ShouldPani cLike, 562 » » » » » So(func() { Get(c, &Key{}) }, ShouldPani cLike,
578 "invalid input type (*datastore. Key): not a PLS, pointer-to-struct, or slice thereof") 563 "invalid input type (*datastore. Key): not a PLS, pointer-to-struct, or slice thereof")
579 }) 564 })
580 565
581 Convey("struct with no $kind is an error", func( ) { 566 Convey("struct with no $kind is an error", func( ) {
582 s := MGSWithNoKind{} 567 s := MGSWithNoKind{}
583 » » » » » So(ds.Put(&s), ShouldErrLike, "unable to extract $kind") 568 » » » » » So(Put(c, &s), ShouldErrLike, "unable to extract $kind")
584 }) 569 })
585 570
586 Convey("struct with invalid but non-nil key is a n error", func() { 571 Convey("struct with invalid but non-nil key is a n error", func() {
587 type BadParent struct { 572 type BadParent struct {
588 ID int64 `gae:"$id"` 573 ID int64 `gae:"$id"`
589 Parent *Key `gae:"$parent"` 574 Parent *Key `gae:"$parent"`
590 } 575 }
591 // having an Incomplete parent makes an invalid key 576 // having an Incomplete parent makes an invalid key
592 » » » » » bp := &BadParent{ID: 1, Parent: ds.MakeK ey("Something", 0)} 577 » » » » » bp := &BadParent{ID: 1, Parent: MakeKey( c, "Something", 0)}
593 » » » » » So(ds.Put(bp), ShouldErrLike, ErrInvalid Key) 578 » » » » » So(Put(c, bp), ShouldErrLike, ErrInvalid Key)
594 }) 579 })
595 580
596 Convey("vararg with errors", func() { 581 Convey("vararg with errors", func() {
597 successSlice := []CommonStruct{{Value: 0 }, {Value: 1}} 582 successSlice := []CommonStruct{{Value: 0 }, {Value: 1}}
598 failSlice := []FakePLS{{Kind: "Fail"}, { Value: 3}} 583 failSlice := []FakePLS{{Kind: "Fail"}, { Value: 3}}
599 emptySlice := []CommonStruct(nil) 584 emptySlice := []CommonStruct(nil)
600 cs0 := CommonStruct{Value: 4} 585 cs0 := CommonStruct{Value: 4}
601 failPLS := FakePLS{Kind: "Fail", Value: 5} 586 failPLS := FakePLS{Kind: "Fail", Value: 5}
602 fpls := FakePLS{StringID: "ohai", Value: 6} 587 fpls := FakePLS{StringID: "ohai", Value: 6}
603 588
604 » » » » » err := ds.Put(successSlice, failSlice, e mptySlice, &cs0, &failPLS, &fpls) 589 » » » » » err := Put(c, successSlice, failSlice, e mptySlice, &cs0, &failPLS, &fpls)
605 So(err, ShouldResemble, errors.MultiErro r{ 590 So(err, ShouldResemble, errors.MultiErro r{
606 nil, errors.MultiError{errFail, nil}, nil, nil, errFail, nil}) 591 nil, errors.MultiError{errFail, nil}, nil, nil, errFail, nil})
607 So(successSlice[0].ID, ShouldEqual, 1) 592 So(successSlice[0].ID, ShouldEqual, 1)
608 So(successSlice[1].ID, ShouldEqual, 2) 593 So(successSlice[1].ID, ShouldEqual, 2)
609 So(cs0.ID, ShouldEqual, 5) 594 So(cs0.ID, ShouldEqual, 5)
610 }) 595 })
611 }) 596 })
612 597
613 Convey("ok", func() { 598 Convey("ok", func() {
614 Convey("[]S", func() { 599 Convey("[]S", func() {
615 css := make([]CommonStruct, 7) 600 css := make([]CommonStruct, 7)
616 for i := range css { 601 for i := range css {
617 if i == 4 { 602 if i == 4 {
618 css[i].ID = 200 603 css[i].ID = 200
619 } 604 }
620 css[i].Value = int64(i) 605 css[i].Value = int64(i)
621 } 606 }
622 » » » » » So(ds.Put(css), ShouldBeNil) 607 » » » » » So(Put(c, css), ShouldBeNil)
623 for i, cs := range css { 608 for i, cs := range css {
624 expect := int64(i + 1) 609 expect := int64(i + 1)
625 if i == 4 { 610 if i == 4 {
626 expect = 200 611 expect = 200
627 } 612 }
628 So(cs.ID, ShouldEqual, expect) 613 So(cs.ID, ShouldEqual, expect)
629 } 614 }
630 }) 615 })
631 616
632 Convey("[]*S", func() { 617 Convey("[]*S", func() {
633 css := make([]*CommonStruct, 7) 618 css := make([]*CommonStruct, 7)
634 for i := range css { 619 for i := range css {
635 css[i] = &CommonStruct{Value: in t64(i)} 620 css[i] = &CommonStruct{Value: in t64(i)}
636 if i == 4 { 621 if i == 4 {
637 css[i].ID = 200 622 css[i].ID = 200
638 } 623 }
639 } 624 }
640 » » » » » So(ds.Put(css), ShouldBeNil) 625 » » » » » So(Put(c, css), ShouldBeNil)
641 for i, cs := range css { 626 for i, cs := range css {
642 expect := int64(i + 1) 627 expect := int64(i + 1)
643 if i == 4 { 628 if i == 4 {
644 expect = 200 629 expect = 200
645 } 630 }
646 So(cs.ID, ShouldEqual, expect) 631 So(cs.ID, ShouldEqual, expect)
647 } 632 }
648 633
649 s := &CommonStruct{} 634 s := &CommonStruct{}
650 » » » » » So(ds.Put(s), ShouldBeNil) 635 » » » » » So(Put(c, s), ShouldBeNil)
651 So(s.ID, ShouldEqual, 1) 636 So(s.ID, ShouldEqual, 1)
652 }) 637 })
653 638
654 Convey("[]P", func() { 639 Convey("[]P", func() {
655 fplss := make([]FakePLS, 7) 640 fplss := make([]FakePLS, 7)
656 for i := range fplss { 641 for i := range fplss {
657 fplss[i].Value = int64(i) 642 fplss[i].Value = int64(i)
658 if i == 4 { 643 if i == 4 {
659 fplss[i].IntID = int64(2 00) 644 fplss[i].IntID = int64(2 00)
660 } 645 }
661 } 646 }
662 » » » » » So(ds.Put(fplss), ShouldBeNil) 647 » » » » » So(Put(c, fplss), ShouldBeNil)
663 for i, fpls := range fplss { 648 for i, fpls := range fplss {
664 expect := int64(i + 1) 649 expect := int64(i + 1)
665 if i == 4 { 650 if i == 4 {
666 expect = 200 651 expect = 200
667 } 652 }
668 So(fpls.IntID, ShouldEqual, expe ct) 653 So(fpls.IntID, ShouldEqual, expe ct)
669 } 654 }
670 655
671 pm := PropertyMap{"Value": MkProperty(0) , "$kind": MkPropertyNI("Pmap")} 656 pm := PropertyMap{"Value": MkProperty(0) , "$kind": MkPropertyNI("Pmap")}
672 » » » » » So(ds.Put(pm), ShouldBeNil) 657 » » » » » So(Put(c, pm), ShouldBeNil)
673 » » » » » So(ds.KeyForObj(pm).IntID(), ShouldEqual , 1) 658 » » » » » So(KeyForObj(c, pm).IntID(), ShouldEqual , 1)
674 }) 659 })
675 660
676 Convey("[]P (map)", func() { 661 Convey("[]P (map)", func() {
677 pms := make([]PropertyMap, 7) 662 pms := make([]PropertyMap, 7)
678 for i := range pms { 663 for i := range pms {
679 pms[i] = PropertyMap{ 664 pms[i] = PropertyMap{
680 "$kind": MkProperty("Pma p"), 665 "$kind": MkProperty("Pma p"),
681 "Value": MkProperty(i), 666 "Value": MkProperty(i),
682 } 667 }
683 if i == 4 { 668 if i == 4 {
684 So(pms[i].SetMeta("id", int64(200)), ShouldBeTrue) 669 So(pms[i].SetMeta("id", int64(200)), ShouldBeTrue)
685 } 670 }
686 } 671 }
687 » » » » » So(ds.Put(pms), ShouldBeNil) 672 » » » » » So(Put(c, pms), ShouldBeNil)
688 for i, pm := range pms { 673 for i, pm := range pms {
689 expect := int64(i + 1) 674 expect := int64(i + 1)
690 if i == 4 { 675 if i == 4 {
691 expect = 200 676 expect = 200
692 } 677 }
693 » » » » » » So(ds.KeyForObj(pm).String(), Sh ouldEqual, fmt.Sprintf("s~aid:ns:/Pmap,%d", expect)) 678 » » » » » » So(KeyForObj(c, pm).String(), Sh ouldEqual, fmt.Sprintf("s~aid:ns:/Pmap,%d", expect))
694 } 679 }
695 }) 680 })
696 681
697 Convey("[]*P", func() { 682 Convey("[]*P", func() {
698 fplss := make([]*FakePLS, 7) 683 fplss := make([]*FakePLS, 7)
699 for i := range fplss { 684 for i := range fplss {
700 fplss[i] = &FakePLS{Value: int64 (i)} 685 fplss[i] = &FakePLS{Value: int64 (i)}
701 if i == 4 { 686 if i == 4 {
702 fplss[i].IntID = int64(2 00) 687 fplss[i].IntID = int64(2 00)
703 } 688 }
704 } 689 }
705 » » » » » So(ds.Put(fplss), ShouldBeNil) 690 » » » » » So(Put(c, fplss), ShouldBeNil)
706 for i, fpls := range fplss { 691 for i, fpls := range fplss {
707 expect := int64(i + 1) 692 expect := int64(i + 1)
708 if i == 4 { 693 if i == 4 {
709 expect = 200 694 expect = 200
710 } 695 }
711 So(fpls.IntID, ShouldEqual, expe ct) 696 So(fpls.IntID, ShouldEqual, expe ct)
712 } 697 }
713 }) 698 })
714 699
715 Convey("[]*P (map)", func() { 700 Convey("[]*P (map)", func() {
716 pms := make([]*PropertyMap, 7) 701 pms := make([]*PropertyMap, 7)
717 for i := range pms { 702 for i := range pms {
718 pms[i] = &PropertyMap{ 703 pms[i] = &PropertyMap{
719 "$kind": MkProperty("Pma p"), 704 "$kind": MkProperty("Pma p"),
720 "Value": MkProperty(i), 705 "Value": MkProperty(i),
721 } 706 }
722 if i == 4 { 707 if i == 4 {
723 So(pms[i].SetMeta("id", int64(200)), ShouldBeTrue) 708 So(pms[i].SetMeta("id", int64(200)), ShouldBeTrue)
724 } 709 }
725 } 710 }
726 » » » » » So(ds.Put(pms), ShouldBeNil) 711 » » » » » So(Put(c, pms), ShouldBeNil)
727 for i, pm := range pms { 712 for i, pm := range pms {
728 expect := int64(i + 1) 713 expect := int64(i + 1)
729 if i == 4 { 714 if i == 4 {
730 expect = 200 715 expect = 200
731 } 716 }
732 » » » » » » So(ds.KeyForObj(*pm).String(), S houldEqual, fmt.Sprintf("s~aid:ns:/Pmap,%d", expect)) 717 » » » » » » So(KeyForObj(c, *pm).String(), S houldEqual, fmt.Sprintf("s~aid:ns:/Pmap,%d", expect))
733 } 718 }
734 }) 719 })
735 720
736 Convey("[]I", func() { 721 Convey("[]I", func() {
737 ifs := []interface{}{ 722 ifs := []interface{}{
738 &CommonStruct{Value: 0}, 723 &CommonStruct{Value: 0},
739 &FakePLS{Value: 1}, 724 &FakePLS{Value: 1},
740 PropertyMap{"Value": MkProperty( 2), "$kind": MkPropertyNI("Pmap")}, 725 PropertyMap{"Value": MkProperty( 2), "$kind": MkPropertyNI("Pmap")},
741 &PropertyMap{"Value": MkProperty (3), "$kind": MkPropertyNI("Pmap")}, 726 &PropertyMap{"Value": MkProperty (3), "$kind": MkPropertyNI("Pmap")},
742 } 727 }
743 » » » » » So(ds.Put(ifs), ShouldBeNil) 728 » » » » » So(Put(c, ifs), ShouldBeNil)
744 for i := range ifs { 729 for i := range ifs {
745 switch i { 730 switch i {
746 case 0: 731 case 0:
747 So(ifs[i].(*CommonStruct ).ID, ShouldEqual, 1) 732 So(ifs[i].(*CommonStruct ).ID, ShouldEqual, 1)
748 case 1: 733 case 1:
749 fpls := ifs[i].(*FakePLS ) 734 fpls := ifs[i].(*FakePLS )
750 So(fpls.IntID, ShouldEqu al, 2) 735 So(fpls.IntID, ShouldEqu al, 2)
751 case 2: 736 case 2:
752 » » » » » » » So(ds.KeyForObj(ifs[i].( PropertyMap)).String(), ShouldEqual, "s~aid:ns:/Pmap,3") 737 » » » » » » » So(KeyForObj(c, ifs[i].( PropertyMap)).String(), ShouldEqual, "s~aid:ns:/Pmap,3")
753 case 3: 738 case 3:
754 » » » » » » » So(ds.KeyForObj(*ifs[i]. (*PropertyMap)).String(), ShouldEqual, "s~aid:ns:/Pmap,4") 739 » » » » » » » So(KeyForObj(c, *ifs[i]. (*PropertyMap)).String(), ShouldEqual, "s~aid:ns:/Pmap,4")
755 } 740 }
756 } 741 }
757 }) 742 })
758 }) 743 })
759 }) 744 })
760
761 Convey("Testing PutMulti", func() {
762 Convey("Fails for something other than a slice.", func() {
763 cs := CommonStruct{}
764 So(func() { ds.PutMulti(&cs) }, ShouldPanicLike,
765 "argument must be a slice, not *datastor e.CommonStruct")
766 })
767
768 Convey("Succeeds for a slice.", func() {
769 cs := []CommonStruct{{Value: 0}, {Value: 1}}
770 So(ds.PutMulti(cs), ShouldBeNil)
771 So(cs[0].ID, ShouldEqual, 1)
772 So(cs[1].ID, ShouldEqual, 2)
773 })
774
775 Convey("Returns an item error in a MultiError.", func() {
776 cs := []FakePLS{{Value: 0}, {Kind: "Fail"}}
777 err := ds.PutMulti(cs)
778 So(err, ShouldResemble, errors.MultiError{nil, e rrFail})
779 So(cs[0].IntID, ShouldEqual, 1)
780 })
781 })
782 }) 745 })
783 } 746 }
784 747
785 func TestExists(t *testing.T) { 748 func TestExists(t *testing.T) {
786 t.Parallel() 749 t.Parallel()
787 750
788 Convey("A testing environment", t, func() { 751 Convey("A testing environment", t, func() {
789 c := info.Set(context.Background(), fakeInfo{}) 752 c := info.Set(context.Background(), fakeInfo{})
790 c = SetRawFactory(c, fakeDatastoreFactory) 753 c = SetRawFactory(c, fakeDatastoreFactory)
791 ds := Get(c)
792 754
793 » » k := ds.MakeKey("Hello", "world") 755 » » k := MakeKey(c, "Hello", "world")
794 756
795 Convey("Exists", func() { 757 Convey("Exists", func() {
796 // Single key. 758 // Single key.
797 » » » er, err := ds.Exists(k) 759 » » » er, err := Exists(c, k)
798 So(err, ShouldBeNil) 760 So(err, ShouldBeNil)
799 So(er.All(), ShouldBeTrue) 761 So(er.All(), ShouldBeTrue)
800 762
801 // Single key failure. 763 // Single key failure.
802 » » » _, err = ds.Exists(ds.MakeKey("Fail", "boom")) 764 » » » _, err = Exists(c, MakeKey(c, "Fail", "boom"))
803 So(err, ShouldEqual, errFail) 765 So(err, ShouldEqual, errFail)
804 766
805 // Single slice of keys. 767 // Single slice of keys.
806 » » » er, err = ds.Exists([]*Key{k, ds.MakeKey("hello", "other ")}) 768 » » » er, err = Exists(c, []*Key{k, MakeKey(c, "hello", "other ")})
807 So(err, ShouldBeNil) 769 So(err, ShouldBeNil)
808 So(er.All(), ShouldBeTrue) 770 So(er.All(), ShouldBeTrue)
809 771
810 // Single slice of keys failure. 772 // Single slice of keys failure.
811 » » » er, err = ds.Exists([]*Key{k, ds.MakeKey("Fail", "boom") }) 773 » » » er, err = Exists(c, []*Key{k, MakeKey(c, "Fail", "boom") })
812 So(err, ShouldResemble, errors.MultiError{nil, errFail}) 774 So(err, ShouldResemble, errors.MultiError{nil, errFail})
813 So(er.Get(0, 0), ShouldBeTrue) 775 So(er.Get(0, 0), ShouldBeTrue)
814 776
815 // Single key missing. 777 // Single key missing.
816 » » » er, err = ds.Exists(ds.MakeKey("DNE", "nope")) 778 » » » er, err = Exists(c, MakeKey(c, "DNE", "nope"))
817 So(err, ShouldBeNil) 779 So(err, ShouldBeNil)
818 So(er.Any(), ShouldBeFalse) 780 So(er.Any(), ShouldBeFalse)
819 781
820 // Multi-arg keys with one missing. 782 // Multi-arg keys with one missing.
821 » » » er, err = ds.Exists(k, ds.MakeKey("DNE", "other")) 783 » » » er, err = Exists(c, k, MakeKey(c, "DNE", "other"))
822 So(err, ShouldBeNil) 784 So(err, ShouldBeNil)
823 So(er.Get(0), ShouldBeTrue) 785 So(er.Get(0), ShouldBeTrue)
824 So(er.Get(1), ShouldBeFalse) 786 So(er.Get(1), ShouldBeFalse)
825 787
826 // Multi-arg keys with two missing. 788 // Multi-arg keys with two missing.
827 » » » er, err = ds.Exists(ds.MakeKey("DNE", "nope"), ds.MakeKe y("DNE", "other")) 789 » » » er, err = Exists(c, MakeKey(c, "DNE", "nope"), MakeKey(c , "DNE", "other"))
828 So(err, ShouldBeNil) 790 So(err, ShouldBeNil)
829 So(er.Any(), ShouldBeFalse) 791 So(er.Any(), ShouldBeFalse)
830 792
831 // Single struct pointer. 793 // Single struct pointer.
832 » » » er, err = ds.Exists(&CommonStruct{ID: 1}) 794 » » » er, err = Exists(c, &CommonStruct{ID: 1})
833 So(err, ShouldBeNil) 795 So(err, ShouldBeNil)
834 So(er.All(), ShouldBeTrue) 796 So(er.All(), ShouldBeTrue)
835 797
836 // Multi-arg mixed key/struct/slices. 798 // Multi-arg mixed key/struct/slices.
837 » » » er, err = ds.Exists( 799 » » » er, err = Exists(c,
838 &CommonStruct{ID: 1}, 800 &CommonStruct{ID: 1},
839 []*CommonStruct(nil), 801 []*CommonStruct(nil),
840 » » » » []*Key{ds.MakeKey("DNE", "nope"), ds.MakeKey("he llo", "ohai")}, 802 » » » » []*Key{MakeKey(c, "DNE", "nope"), MakeKey(c, "he llo", "ohai")},
841 ) 803 )
842 So(err, ShouldBeNil) 804 So(err, ShouldBeNil)
843 So(er.Get(0), ShouldBeTrue) 805 So(er.Get(0), ShouldBeTrue)
844 So(er.Get(1), ShouldBeTrue) 806 So(er.Get(1), ShouldBeTrue)
845 So(er.Get(2), ShouldBeFalse) 807 So(er.Get(2), ShouldBeFalse)
846 So(er.Get(2, 0), ShouldBeFalse) 808 So(er.Get(2, 0), ShouldBeFalse)
847 So(er.Get(2, 1), ShouldBeTrue) 809 So(er.Get(2, 1), ShouldBeTrue)
848 }) 810 })
849
850 Convey("ExistsMulti", func() {
851 Convey("Returns no error if there are no failures.", fun c() {
852 bl, err := ds.ExistsMulti([]*Key{k, ds.MakeKey(" DNE", "nope"), ds.MakeKey("hello", "ohai")})
853 So(err, ShouldBeNil)
854 So(bl, ShouldResemble, BoolList{true, false, tru e})
855 })
856
857 Convey("Returns an item error in a MultiError.", func() {
858 _, err := ds.ExistsMulti([]*Key{k, ds.MakeKey("F ail", "boom")})
859 So(err, ShouldResemble, errors.MultiError{nil, e rrFail})
860 })
861 })
862 }) 811 })
863 } 812 }
864 813
865 func TestDelete(t *testing.T) { 814 func TestDelete(t *testing.T) {
866 t.Parallel() 815 t.Parallel()
867 816
868 Convey("A testing environment", t, func() { 817 Convey("A testing environment", t, func() {
869 c := info.Set(context.Background(), fakeInfo{}) 818 c := info.Set(context.Background(), fakeInfo{})
870 c = SetRawFactory(c, fakeDatastoreFactory) 819 c = SetRawFactory(c, fakeDatastoreFactory)
871 ds := Get(c)
872 So(ds, ShouldNotBeNil)
873 820
874 Convey("Testing Delete", func() { 821 Convey("Testing Delete", func() {
875 Convey("bad", func() { 822 Convey("bad", func() {
876 Convey("get single error for RPC failure", func( ) { 823 Convey("get single error for RPC failure", func( ) {
877 keys := []*Key{ 824 keys := []*Key{
878 » » » » » » MakeKey("s~aid", "ns", "FailAll" , 1), 825 » » » » » » MakeKey(c, "s~aid", "ns", "FailA ll", 1),
879 » » » » » » MakeKey("s~aid", "ns", "Ok", 1), 826 » » » » » » MakeKey(c, "s~aid", "ns", "Ok", 1),
880 } 827 }
881 » » » » » So(ds.Delete(keys), ShouldEqual, errFail All) 828 » » » » » So(Delete(c, keys), ShouldEqual, errFail All)
882 }) 829 })
883 830
884 Convey("get multi error for individual failure", func() { 831 Convey("get multi error for individual failure", func() {
885 keys := []*Key{ 832 keys := []*Key{
886 » » » » » » ds.MakeKey("Ok", 1), 833 » » » » » » MakeKey(c, "Ok", 1),
887 » » » » » » ds.MakeKey("Fail", 2), 834 » » » » » » MakeKey(c, "Fail", 2),
888 } 835 }
889 » » » » » So(ds.Delete(keys), ShouldResemble, erro rs.MultiError{nil, errFail}) 836 » » » » » So(Delete(c, keys), ShouldResemble, erro rs.MultiError{nil, errFail})
890 }) 837 })
891 838
892 Convey("put with non-modifyable type is an error ", func() { 839 Convey("put with non-modifyable type is an error ", func() {
893 cs := CommonStruct{} 840 cs := CommonStruct{}
894 » » » » » So(func() { ds.Put(cs) }, ShouldPanicLik e, 841 » » » » » So(func() { Put(c, cs) }, ShouldPanicLik e,
895 "invalid input type (datastore.C ommonStruct): not a pointer") 842 "invalid input type (datastore.C ommonStruct): not a pointer")
896 }) 843 })
897 844
898 Convey("get single error when deleting a single" , func() { 845 Convey("get single error when deleting a single" , func() {
899 » » » » » k := ds.MakeKey("Fail", 1) 846 » » » » » k := MakeKey(c, "Fail", 1)
900 » » » » » So(ds.Delete(k), ShouldEqual, errFail) 847 » » » » » So(Delete(c, k), ShouldEqual, errFail)
901 }) 848 })
902 }) 849 })
903 850
904 Convey("good", func() { 851 Convey("good", func() {
905 // Single struct pointer. 852 // Single struct pointer.
906 » » » » So(ds.Delete(&CommonStruct{ID: 1}), ShouldBeNil) 853 » » » » So(Delete(c, &CommonStruct{ID: 1}), ShouldBeNil)
907 854
908 // Single key. 855 // Single key.
909 » » » » So(ds.Delete(ds.MakeKey("hello", "ohai")), Shoul dBeNil) 856 » » » » So(Delete(c, MakeKey(c, "hello", "ohai")), Shoul dBeNil)
910 857
911 // Single struct DNE. 858 // Single struct DNE.
912 » » » » So(ds.Delete(&CommonStruct{ID: noSuchEntityID}), ShouldEqual, ErrNoSuchEntity) 859 » » » » So(Delete(c, &CommonStruct{ID: noSuchEntityID}), ShouldEqual, ErrNoSuchEntity)
913 860
914 // Single key DNE. 861 // Single key DNE.
915 » » » » So(ds.Delete(ds.MakeKey("DNE", "nope")), ShouldE qual, ErrNoSuchEntity) 862 » » » » So(Delete(c, MakeKey(c, "DNE", "nope")), ShouldE qual, ErrNoSuchEntity)
916 863
917 // Mixed key/struct/slices. 864 // Mixed key/struct/slices.
918 » » » » err := ds.Delete( 865 » » » » err := Delete(c,
919 &CommonStruct{ID: 1}, 866 &CommonStruct{ID: 1},
920 » » » » » []*Key{ds.MakeKey("hello", "ohai"), ds.M akeKey("DNE", "nope")}, 867 » » » » » []*Key{MakeKey(c, "hello", "ohai"), Make Key(c, "DNE", "nope")},
921 ) 868 )
922 So(err, ShouldResemble, errors.MultiError{nil, e rrors.MultiError{nil, ErrNoSuchEntity}}) 869 So(err, ShouldResemble, errors.MultiError{nil, e rrors.MultiError{nil, ErrNoSuchEntity}})
923 }) 870 })
924 }) 871 })
925
926 Convey("Testing DeleteMulti", func() {
927 Convey("Succeeds for valid keys.", func() {
928 So(ds.DeleteMulti([]*Key{ds.MakeKey("hello", "oh ai")}), ShouldBeNil)
929 So(ds.DeleteMulti([]*Key{ds.MakeKey("hello", "oh ai"), ds.MakeKey("hello", "sup")}), ShouldBeNil)
930 })
931
932 Convey("Returns an item error in a MultiError.", func() {
933 So(ds.DeleteMulti([]*Key{ds.MakeKey("DNE", "oops ")}), ShouldResemble, errors.MultiError{ErrNoSuchEntity})
934 })
935 })
936 }) 872 })
937 } 873 }
938 874
939 func TestGet(t *testing.T) { 875 func TestGet(t *testing.T) {
940 t.Parallel() 876 t.Parallel()
941 877
942 Convey("A testing environment", t, func() { 878 Convey("A testing environment", t, func() {
943 c := info.Set(context.Background(), fakeInfo{}) 879 c := info.Set(context.Background(), fakeInfo{})
944 c = SetRawFactory(c, fakeDatastoreFactory) 880 c = SetRawFactory(c, fakeDatastoreFactory)
945 ds := Get(c)
946 So(ds, ShouldNotBeNil)
947 881
948 Convey("Testing Get", func() { 882 Convey("Testing Get", func() {
949 Convey("bad", func() { 883 Convey("bad", func() {
950 Convey("static can't serialize", func() { 884 Convey("static can't serialize", func() {
951 toGet := []badStruct{{}, {}} 885 toGet := []badStruct{{}, {}}
952 » » » » » So(func() { ds.Get(toGet) }, ShouldPanic Like, 886 » » » » » So(func() { Get(c, toGet) }, ShouldPanic Like,
953 `field "Compy" has invalid type: complex64`) 887 `field "Compy" has invalid type: complex64`)
954 }) 888 })
955 889
956 Convey("can't get keys", func() { 890 Convey("can't get keys", func() {
957 fplss := []FakePLS{{failGetMeta: true}, {}} 891 fplss := []FakePLS{{failGetMeta: true}, {}}
958 » » » » » So(ds.Get(fplss), ShouldErrLike, "unable to extract $kind") 892 » » » » » So(Get(c, fplss), ShouldErrLike, "unable to extract $kind")
959 }) 893 })
960 894
961 Convey("get single error for RPC failure", func( ) { 895 Convey("get single error for RPC failure", func( ) {
962 fplss := []FakePLS{ 896 fplss := []FakePLS{
963 {IntID: 1, Kind: "FailAll"}, 897 {IntID: 1, Kind: "FailAll"},
964 {IntID: 2}, 898 {IntID: 2},
965 } 899 }
966 » » » » » So(ds.Get(fplss), ShouldEqual, errFailAl l) 900 » » » » » So(Get(c, fplss), ShouldEqual, errFailAl l)
967 }) 901 })
968 902
969 Convey("get multi error for individual failures" , func() { 903 Convey("get multi error for individual failures" , func() {
970 fplss := []FakePLS{{IntID: 1}, {IntID: 2 , Kind: "Fail"}} 904 fplss := []FakePLS{{IntID: 1}, {IntID: 2 , Kind: "Fail"}}
971 » » » » » So(ds.Get(fplss), ShouldResemble, errors .MultiError{nil, errFail}) 905 » » » » » So(Get(c, fplss), ShouldResemble, errors .MultiError{nil, errFail})
972 }) 906 })
973 907
974 Convey("get with non-modifiable type is an error ", func() { 908 Convey("get with non-modifiable type is an error ", func() {
975 cs := CommonStruct{} 909 cs := CommonStruct{}
976 » » » » » So(func() { ds.Get(cs) }, ShouldPanicLik e, 910 » » » » » So(func() { Get(c, cs) }, ShouldPanicLik e,
977 "invalid input type (datastore.C ommonStruct): not a pointer") 911 "invalid input type (datastore.C ommonStruct): not a pointer")
978 }) 912 })
979 913
980 Convey("get with nil is an error", func() { 914 Convey("get with nil is an error", func() {
981 » » » » » So(func() { ds.Get(nil) }, ShouldPanicLi ke, 915 » » » » » So(func() { Get(c, nil) }, ShouldPanicLi ke,
982 "cannot use nil as single argume nt") 916 "cannot use nil as single argume nt")
983 }) 917 })
984 918
985 Convey("get with ptr-to-nonstruct is an error", func() { 919 Convey("get with ptr-to-nonstruct is an error", func() {
986 val := 100 920 val := 100
987 » » » » » So(func() { ds.Get(&val) }, ShouldPanicL ike, 921 » » » » » So(func() { Get(c, &val) }, ShouldPanicL ike,
988 "invalid input type (*int): not a PLS, pointer-to-struct, or slice thereof") 922 "invalid input type (*int): not a PLS, pointer-to-struct, or slice thereof")
989 }) 923 })
990 924
991 Convey("failure to save metadata is no problem t hough", func() { 925 Convey("failure to save metadata is no problem t hough", func() {
992 // It just won't save the key 926 // It just won't save the key
993 cs := &FakePLS{IntID: 10, failSetMeta: t rue} 927 cs := &FakePLS{IntID: 10, failSetMeta: t rue}
994 » » » » » So(ds.Get(cs), ShouldBeNil) 928 » » » » » So(Get(c, cs), ShouldBeNil)
995 }) 929 })
996 930
997 Convey("vararg with errors", func() { 931 Convey("vararg with errors", func() {
998 successSlice := []CommonStruct{{ID: 1}, {ID: 2}} 932 successSlice := []CommonStruct{{ID: 1}, {ID: 2}}
999 failSlice := []CommonStruct{{ID: noSuchE ntityID}, {ID: 3}} 933 failSlice := []CommonStruct{{ID: noSuchE ntityID}, {ID: 3}}
1000 emptySlice := []CommonStruct(nil) 934 emptySlice := []CommonStruct(nil)
1001 cs0 := CommonStruct{ID: 4} 935 cs0 := CommonStruct{ID: 4}
1002 failPLS := CommonStruct{ID: noSuchEntity ID} 936 failPLS := CommonStruct{ID: noSuchEntity ID}
1003 fpls := FakePLS{StringID: "ohai"} 937 fpls := FakePLS{StringID: "ohai"}
1004 938
1005 » » » » » err := ds.Get(successSlice, failSlice, e mptySlice, &cs0, &failPLS, &fpls) 939 » » » » » err := Get(c, successSlice, failSlice, e mptySlice, &cs0, &failPLS, &fpls)
1006 So(err, ShouldResemble, errors.MultiErro r{ 940 So(err, ShouldResemble, errors.MultiErro r{
1007 nil, errors.MultiError{ErrNoSuch Entity, nil}, nil, nil, ErrNoSuchEntity, nil}) 941 nil, errors.MultiError{ErrNoSuch Entity, nil}, nil, nil, ErrNoSuchEntity, nil})
1008 So(successSlice[0].Value, ShouldEqual, 1 ) 942 So(successSlice[0].Value, ShouldEqual, 1 )
1009 So(successSlice[1].Value, ShouldEqual, 2 ) 943 So(successSlice[1].Value, ShouldEqual, 2 )
1010 So(cs0.Value, ShouldEqual, 5) 944 So(cs0.Value, ShouldEqual, 5)
1011 So(fpls.Value, ShouldEqual, 7) 945 So(fpls.Value, ShouldEqual, 7)
1012 }) 946 })
1013 }) 947 })
1014 948
1015 Convey("ok", func() { 949 Convey("ok", func() {
1016 Convey("Get", func() { 950 Convey("Get", func() {
1017 cs := &CommonStruct{ID: 1} 951 cs := &CommonStruct{ID: 1}
1018 » » » » » So(ds.Get(cs), ShouldBeNil) 952 » » » » » So(Get(c, cs), ShouldBeNil)
1019 So(cs.Value, ShouldEqual, 1) 953 So(cs.Value, ShouldEqual, 1)
1020 }) 954 })
1021 955
1022 Convey("Raw access too", func() { 956 Convey("Raw access too", func() {
1023 » » » » » rds := ds.Raw() 957 » » » » » rds := Raw(c)
1024 » » » » » keys := []*Key{ds.MakeKey("Kind", 1)} 958 » » » » » keys := []*Key{MakeKey(c, "Kind", 1)}
1025 So(rds.GetMulti(keys, nil, func(pm Prope rtyMap, err error) error { 959 So(rds.GetMulti(keys, nil, func(pm Prope rtyMap, err error) error {
1026 So(err, ShouldBeNil) 960 So(err, ShouldBeNil)
1027 So(pm.Slice("Value")[0].Value(), ShouldEqual, 1) 961 So(pm.Slice("Value")[0].Value(), ShouldEqual, 1)
1028 return nil 962 return nil
1029 }), ShouldBeNil) 963 }), ShouldBeNil)
1030 }) 964 })
1031 965
1032 Convey("but general failure to save is fine on a Get", func() { 966 Convey("but general failure to save is fine on a Get", func() {
1033 cs := &FakePLS{failSave: true, IntID: 7} 967 cs := &FakePLS{failSave: true, IntID: 7}
1034 » » » » » So(ds.Get(cs), ShouldBeNil) 968 » » » » » So(Get(c, cs), ShouldBeNil)
1035 }) 969 })
1036 970
1037 Convey("vararg", func() { 971 Convey("vararg", func() {
1038 successSlice := []CommonStruct{{ID: 1}, {ID: 2}} 972 successSlice := []CommonStruct{{ID: 1}, {ID: 2}}
1039 cs := CommonStruct{ID: 3} 973 cs := CommonStruct{ID: 3}
1040 974
1041 » » » » » err := ds.Get(successSlice, &cs) 975 » » » » » err := Get(c, successSlice, &cs)
1042 So(err, ShouldBeNil) 976 So(err, ShouldBeNil)
1043 So(successSlice[0].Value, ShouldEqual, 1 ) 977 So(successSlice[0].Value, ShouldEqual, 1 )
1044 So(successSlice[1].Value, ShouldEqual, 2 ) 978 So(successSlice[1].Value, ShouldEqual, 2 )
1045 So(cs.Value, ShouldEqual, 3) 979 So(cs.Value, ShouldEqual, 3)
1046 }) 980 })
1047 }) 981 })
1048 }) 982 })
1049
1050 Convey("Testing GetMulti", func() {
1051 Convey("Fails for something other than a slice.", func() {
1052 cs := CommonStruct{}
1053 So(func() { ds.GetMulti(&cs) }, ShouldPanicLike,
1054 "argument must be a slice, not *datastor e.CommonStruct")
1055 })
1056
1057 Convey("Succeeds for a slice.", func() {
1058 cs := []CommonStruct{{ID: 1}}
1059 So(ds.GetMulti(cs), ShouldBeNil)
1060 So(cs[0].Value, ShouldEqual, 1)
1061 })
1062
1063 Convey("Returns an item error in a MultiError.", func() {
1064 cs := []CommonStruct{{ID: 1}, {ID: noSuchEntityI D}}
1065 err := ds.GetMulti(cs)
1066 So(err, ShouldResemble, errors.MultiError{nil, E rrNoSuchEntity})
1067 So(cs[0].Value, ShouldEqual, 1)
1068 })
1069 })
1070 }) 983 })
1071 } 984 }
1072 985
1073 func TestGetAll(t *testing.T) { 986 func TestGetAll(t *testing.T) {
1074 t.Parallel() 987 t.Parallel()
1075 988
1076 Convey("Test GetAll", t, func() { 989 Convey("Test GetAll", t, func() {
1077 c := info.Set(context.Background(), fakeInfo{}) 990 c := info.Set(context.Background(), fakeInfo{})
1078 c = SetRawFactory(c, fakeDatastoreFactory) 991 c = SetRawFactory(c, fakeDatastoreFactory)
1079 ds := Get(c)
1080 So(ds, ShouldNotBeNil)
1081 992
1082 q := NewQuery("").Limit(5) 993 q := NewQuery("").Limit(5)
1083 994
1084 Convey("bad", func() { 995 Convey("bad", func() {
1085 Convey("nil target", func() { 996 Convey("nil target", func() {
1086 » » » » So(func() { ds.GetAll(q, (*[]PropertyMap)(nil)) }, ShouldPanicLike, 997 » » » » So(func() { GetAll(c, q, (*[]PropertyMap)(nil)) }, ShouldPanicLike,
1087 "invalid GetAll dst: <nil>") 998 "invalid GetAll dst: <nil>")
1088 }) 999 })
1089 1000
1090 Convey("bad type", func() { 1001 Convey("bad type", func() {
1091 output := 100 1002 output := 100
1092 » » » » So(func() { ds.GetAll(q, &output) }, ShouldPanic Like, 1003 » » » » So(func() { GetAll(c, q, &output) }, ShouldPanic Like,
1093 "invalid argument type: expected slice, got int") 1004 "invalid argument type: expected slice, got int")
1094 }) 1005 })
1095 1006
1096 Convey("bad type (non pointer)", func() { 1007 Convey("bad type (non pointer)", func() {
1097 » » » » So(func() { ds.GetAll(q, "moo") }, ShouldPanicLi ke, 1008 » » » » So(func() { GetAll(c, q, "moo") }, ShouldPanicLi ke,
1098 "invalid GetAll dst: must have a ptr-to- slice") 1009 "invalid GetAll dst: must have a ptr-to- slice")
1099 }) 1010 })
1100 1011
1101 Convey("bad type (underspecified)", func() { 1012 Convey("bad type (underspecified)", func() {
1102 output := []PropertyLoadSaver(nil) 1013 output := []PropertyLoadSaver(nil)
1103 » » » » So(func() { ds.GetAll(q, &output) }, ShouldPanic Like, 1014 » » » » So(func() { GetAll(c, q, &output) }, ShouldPanic Like,
1104 "invalid GetAll dst (non-concrete elemen t type): *[]datastore.PropertyLoadSaver") 1015 "invalid GetAll dst (non-concrete elemen t type): *[]datastore.PropertyLoadSaver")
1105 }) 1016 })
1106 }) 1017 })
1107 1018
1108 Convey("ok", func() { 1019 Convey("ok", func() {
1109 Convey("*[]S", func() { 1020 Convey("*[]S", func() {
1110 output := []CommonStruct(nil) 1021 output := []CommonStruct(nil)
1111 » » » » So(ds.GetAll(q, &output), ShouldBeNil) 1022 » » » » So(GetAll(c, q, &output), ShouldBeNil)
1112 So(len(output), ShouldEqual, 5) 1023 So(len(output), ShouldEqual, 5)
1113 for i, o := range output { 1024 for i, o := range output {
1114 So(o.ID, ShouldEqual, i+1) 1025 So(o.ID, ShouldEqual, i+1)
1115 So(o.Value, ShouldEqual, i) 1026 So(o.Value, ShouldEqual, i)
1116 } 1027 }
1117 }) 1028 })
1118 1029
1119 Convey("*[]*S", func() { 1030 Convey("*[]*S", func() {
1120 output := []*CommonStruct(nil) 1031 output := []*CommonStruct(nil)
1121 » » » » So(ds.GetAll(q, &output), ShouldBeNil) 1032 » » » » So(GetAll(c, q, &output), ShouldBeNil)
1122 So(len(output), ShouldEqual, 5) 1033 So(len(output), ShouldEqual, 5)
1123 for i, o := range output { 1034 for i, o := range output {
1124 So(o.ID, ShouldEqual, i+1) 1035 So(o.ID, ShouldEqual, i+1)
1125 So(o.Value, ShouldEqual, i) 1036 So(o.Value, ShouldEqual, i)
1126 } 1037 }
1127 }) 1038 })
1128 1039
1129 Convey("*[]P", func() { 1040 Convey("*[]P", func() {
1130 output := []FakePLS(nil) 1041 output := []FakePLS(nil)
1131 » » » » So(ds.GetAll(q, &output), ShouldBeNil) 1042 » » » » So(GetAll(c, q, &output), ShouldBeNil)
1132 So(len(output), ShouldEqual, 5) 1043 So(len(output), ShouldEqual, 5)
1133 for i, o := range output { 1044 for i, o := range output {
1134 So(o.gotLoaded, ShouldBeTrue) 1045 So(o.gotLoaded, ShouldBeTrue)
1135 So(o.IntID, ShouldEqual, i+1) 1046 So(o.IntID, ShouldEqual, i+1)
1136 So(o.Value, ShouldEqual, i) 1047 So(o.Value, ShouldEqual, i)
1137 } 1048 }
1138 }) 1049 })
1139 1050
1140 Convey("*[]P (map)", func() { 1051 Convey("*[]P (map)", func() {
1141 output := []PropertyMap(nil) 1052 output := []PropertyMap(nil)
1142 » » » » So(ds.GetAll(q, &output), ShouldBeNil) 1053 » » » » So(GetAll(c, q, &output), ShouldBeNil)
1143 So(len(output), ShouldEqual, 5) 1054 So(len(output), ShouldEqual, 5)
1144 for i, o := range output { 1055 for i, o := range output {
1145 k, ok := o.GetMeta("key") 1056 k, ok := o.GetMeta("key")
1146 So(ok, ShouldBeTrue) 1057 So(ok, ShouldBeTrue)
1147 So(k.(*Key).IntID(), ShouldEqual, i+1) 1058 So(k.(*Key).IntID(), ShouldEqual, i+1)
1148 So(o.Slice("Value")[0].Value().(int64), ShouldEqual, i) 1059 So(o.Slice("Value")[0].Value().(int64), ShouldEqual, i)
1149 } 1060 }
1150 }) 1061 })
1151 1062
1152 Convey("*[]P (chan)", func() { 1063 Convey("*[]P (chan)", func() {
1153 output := []plsChan(nil) 1064 output := []plsChan(nil)
1154 » » » » So(ds.GetAll(q, &output), ShouldBeNil) 1065 » » » » So(GetAll(c, q, &output), ShouldBeNil)
1155 So(output, ShouldHaveLength, 5) 1066 So(output, ShouldHaveLength, 5)
1156 for _, o := range output { 1067 for _, o := range output {
1157 » » » » » So(ds.KeyForObj(o).StringID(), ShouldEqu al, "whyDoIExist") 1068 » » » » » So(KeyForObj(c, o).StringID(), ShouldEqu al, "whyDoIExist")
1158 } 1069 }
1159 }) 1070 })
1160 1071
1161 Convey("*[]*P", func() { 1072 Convey("*[]*P", func() {
1162 output := []*FakePLS(nil) 1073 output := []*FakePLS(nil)
1163 » » » » So(ds.GetAll(q, &output), ShouldBeNil) 1074 » » » » So(GetAll(c, q, &output), ShouldBeNil)
1164 So(len(output), ShouldEqual, 5) 1075 So(len(output), ShouldEqual, 5)
1165 for i, o := range output { 1076 for i, o := range output {
1166 So(o.gotLoaded, ShouldBeTrue) 1077 So(o.gotLoaded, ShouldBeTrue)
1167 So(o.IntID, ShouldEqual, i+1) 1078 So(o.IntID, ShouldEqual, i+1)
1168 So(o.Value, ShouldEqual, i) 1079 So(o.Value, ShouldEqual, i)
1169 } 1080 }
1170 }) 1081 })
1171 1082
1172 Convey("*[]*P (map)", func() { 1083 Convey("*[]*P (map)", func() {
1173 output := []*PropertyMap(nil) 1084 output := []*PropertyMap(nil)
1174 » » » » So(ds.GetAll(q, &output), ShouldBeNil) 1085 » » » » So(GetAll(c, q, &output), ShouldBeNil)
1175 So(len(output), ShouldEqual, 5) 1086 So(len(output), ShouldEqual, 5)
1176 for i, op := range output { 1087 for i, op := range output {
1177 o := *op 1088 o := *op
1178 k, ok := o.GetMeta("key") 1089 k, ok := o.GetMeta("key")
1179 So(ok, ShouldBeTrue) 1090 So(ok, ShouldBeTrue)
1180 So(k.(*Key).IntID(), ShouldEqual, i+1) 1091 So(k.(*Key).IntID(), ShouldEqual, i+1)
1181 So(o.Slice("Value")[0].Value().(int64), ShouldEqual, i) 1092 So(o.Slice("Value")[0].Value().(int64), ShouldEqual, i)
1182 } 1093 }
1183 }) 1094 })
1184 1095
1185 Convey("*[]*P (chan)", func() { 1096 Convey("*[]*P (chan)", func() {
1186 output := []*plsChan(nil) 1097 output := []*plsChan(nil)
1187 » » » » So(ds.GetAll(q, &output), ShouldBeNil) 1098 » » » » So(GetAll(c, q, &output), ShouldBeNil)
1188 So(output, ShouldHaveLength, 5) 1099 So(output, ShouldHaveLength, 5)
1189 for _, o := range output { 1100 for _, o := range output {
1190 » » » » » So(ds.KeyForObj(o).StringID(), ShouldEqu al, "whyDoIExist") 1101 » » » » » So(KeyForObj(c, o).StringID(), ShouldEqu al, "whyDoIExist")
1191 } 1102 }
1192 }) 1103 })
1193 1104
1194 Convey("*[]*Key", func() { 1105 Convey("*[]*Key", func() {
1195 output := []*Key(nil) 1106 output := []*Key(nil)
1196 » » » » So(ds.GetAll(q, &output), ShouldBeNil) 1107 » » » » So(GetAll(c, q, &output), ShouldBeNil)
1197 So(len(output), ShouldEqual, 5) 1108 So(len(output), ShouldEqual, 5)
1198 for i, k := range output { 1109 for i, k := range output {
1199 So(k.IntID(), ShouldEqual, i+1) 1110 So(k.IntID(), ShouldEqual, i+1)
1200 } 1111 }
1201 }) 1112 })
1202 1113
1203 }) 1114 })
1204 }) 1115 })
1205 } 1116 }
1206 1117
1207 func TestRun(t *testing.T) { 1118 func TestRun(t *testing.T) {
1208 t.Parallel() 1119 t.Parallel()
1209 1120
1210 Convey("Test Run", t, func() { 1121 Convey("Test Run", t, func() {
1211 c := info.Set(context.Background(), fakeInfo{}) 1122 c := info.Set(context.Background(), fakeInfo{})
1212 c = SetRawFactory(c, fakeDatastoreFactory) 1123 c = SetRawFactory(c, fakeDatastoreFactory)
1213 ds := Get(c)
1214 So(ds, ShouldNotBeNil)
1215 1124
1216 q := NewQuery("kind").Limit(5) 1125 q := NewQuery("kind").Limit(5)
1217 1126
1218 Convey("bad", func() { 1127 Convey("bad", func() {
1219 assertBadTypePanics := func(cb interface{}) { 1128 assertBadTypePanics := func(cb interface{}) {
1220 » » » » So(func() { ds.Run(q, cb) }, ShouldPanicLike, 1129 » » » » So(func() { Run(c, q, cb) }, ShouldPanicLike,
1221 "cb does not match the required callback signature") 1130 "cb does not match the required callback signature")
1222 } 1131 }
1223 1132
1224 Convey("not a function", func() { 1133 Convey("not a function", func() {
1225 assertBadTypePanics("I am a potato") 1134 assertBadTypePanics("I am a potato")
1226 }) 1135 })
1227 1136
1228 Convey("nil", func() { 1137 Convey("nil", func() {
1229 assertBadTypePanics(nil) 1138 assertBadTypePanics(nil)
1230 }) 1139 })
1231 1140
1232 Convey("interface", func() { 1141 Convey("interface", func() {
1233 assertBadTypePanics(func(pls PropertyLoadSaver) {}) 1142 assertBadTypePanics(func(pls PropertyLoadSaver) {})
1234 }) 1143 })
1235 1144
1236 Convey("bad proto type", func() { 1145 Convey("bad proto type", func() {
1237 cb := func(v int) { 1146 cb := func(v int) {
1238 panic("never here!") 1147 panic("never here!")
1239 } 1148 }
1240 » » » » So(func() { ds.Run(q, cb) }, ShouldPanicLike, 1149 » » » » So(func() { Run(c, q, cb) }, ShouldPanicLike,
1241 "invalid argument type: int is not a PLS or pointer-to-struct") 1150 "invalid argument type: int is not a PLS or pointer-to-struct")
1242 }) 1151 })
1243 1152
1244 Convey("wrong # args", func() { 1153 Convey("wrong # args", func() {
1245 assertBadTypePanics(func(v CommonStruct, _ Curso rCB, _ int) { 1154 assertBadTypePanics(func(v CommonStruct, _ Curso rCB, _ int) {
1246 panic("never here!") 1155 panic("never here!")
1247 }) 1156 })
1248 }) 1157 })
1249 1158
1250 Convey("wrong ret type", func() { 1159 Convey("wrong ret type", func() {
(...skipping 10 matching lines...) Expand all
1261 1170
1262 Convey("bad 2nd arg", func() { 1171 Convey("bad 2nd arg", func() {
1263 assertBadTypePanics(func(v CommonStruct, _ Curso r) error { 1172 assertBadTypePanics(func(v CommonStruct, _ Curso r) error {
1264 panic("never here!") 1173 panic("never here!")
1265 }) 1174 })
1266 }) 1175 })
1267 1176
1268 Convey("early abort on error", func() { 1177 Convey("early abort on error", func() {
1269 q = q.Eq("$err_single", "Query fail").Eq("$err_s ingle_idx", 3) 1178 q = q.Eq("$err_single", "Query fail").Eq("$err_s ingle_idx", 3)
1270 i := 0 1179 i := 0
1271 » » » » So(ds.Run(q, func(c CommonStruct) { 1180 » » » » So(Run(c, q, func(c CommonStruct) {
1272 i++ 1181 i++
1273 }), ShouldErrLike, "Query fail") 1182 }), ShouldErrLike, "Query fail")
1274 So(i, ShouldEqual, 3) 1183 So(i, ShouldEqual, 3)
1275 }) 1184 })
1276 1185
1277 Convey("return error on serialization failure", func() { 1186 Convey("return error on serialization failure", func() {
1278 » » » » So(ds.Run(q, func(_ permaBad) { 1187 » » » » So(Run(c, q, func(_ permaBad) {
1279 panic("never here") 1188 panic("never here")
1280 }).Error(), ShouldEqual, "permaBad") 1189 }).Error(), ShouldEqual, "permaBad")
1281 }) 1190 })
1282 }) 1191 })
1283 1192
1284 Convey("ok", func() { 1193 Convey("ok", func() {
1285 Convey("can return error to stop", func() { 1194 Convey("can return error to stop", func() {
1286 i := 0 1195 i := 0
1287 » » » » So(ds.Run(q, func(c CommonStruct) error { 1196 » » » » So(Run(c, q, func(c CommonStruct) error {
1288 i++ 1197 i++
1289 return Stop 1198 return Stop
1290 }), ShouldBeNil) 1199 }), ShouldBeNil)
1291 So(i, ShouldEqual, 1) 1200 So(i, ShouldEqual, 1)
1292 1201
1293 i = 0 1202 i = 0
1294 » » » » So(ds.Run(q, func(c CommonStruct, _ CursorCB) er ror { 1203 » » » » So(Run(c, q, func(c CommonStruct, _ CursorCB) er ror {
1295 i++ 1204 i++
1296 return fmt.Errorf("my error") 1205 return fmt.Errorf("my error")
1297 }), ShouldErrLike, "my error") 1206 }), ShouldErrLike, "my error")
1298 So(i, ShouldEqual, 1) 1207 So(i, ShouldEqual, 1)
1299 }) 1208 })
1300 1209
1301 Convey("Can optionally get cursor function", func() { 1210 Convey("Can optionally get cursor function", func() {
1302 i := 0 1211 i := 0
1303 » » » » So(ds.Run(q, func(c CommonStruct, ccb CursorCB) { 1212 » » » » So(Run(c, q, func(c CommonStruct, ccb CursorCB) {
1304 i++ 1213 i++
1305 curs, err := ccb() 1214 curs, err := ccb()
1306 So(err, ShouldBeNil) 1215 So(err, ShouldBeNil)
1307 So(curs.String(), ShouldEqual, "CURSOR") 1216 So(curs.String(), ShouldEqual, "CURSOR")
1308 }), ShouldBeNil) 1217 }), ShouldBeNil)
1309 So(i, ShouldEqual, 5) 1218 So(i, ShouldEqual, 5)
1310 }) 1219 })
1311 1220
1312 Convey("*S", func() { 1221 Convey("*S", func() {
1313 i := 0 1222 i := 0
1314 » » » » So(ds.Run(q, func(cs *CommonStruct) { 1223 » » » » So(Run(c, q, func(cs *CommonStruct) {
1315 So(cs.ID, ShouldEqual, i+1) 1224 So(cs.ID, ShouldEqual, i+1)
1316 So(cs.Value, ShouldEqual, i) 1225 So(cs.Value, ShouldEqual, i)
1317 i++ 1226 i++
1318 }), ShouldBeNil) 1227 }), ShouldBeNil)
1319 }) 1228 })
1320 1229
1321 Convey("*P", func() { 1230 Convey("*P", func() {
1322 i := 0 1231 i := 0
1323 » » » » So(ds.Run(q.Limit(12), func(fpls *FakePLS) { 1232 » » » » So(Run(c, q.Limit(12), func(fpls *FakePLS) {
1324 So(fpls.gotLoaded, ShouldBeTrue) 1233 So(fpls.gotLoaded, ShouldBeTrue)
1325 if i == 10 { 1234 if i == 10 {
1326 So(fpls.StringID, ShouldEqual, " eleven") 1235 So(fpls.StringID, ShouldEqual, " eleven")
1327 } else { 1236 } else {
1328 So(fpls.IntID, ShouldEqual, i+1) 1237 So(fpls.IntID, ShouldEqual, i+1)
1329 } 1238 }
1330 So(fpls.Value, ShouldEqual, i) 1239 So(fpls.Value, ShouldEqual, i)
1331 i++ 1240 i++
1332 }), ShouldBeNil) 1241 }), ShouldBeNil)
1333 }) 1242 })
1334 1243
1335 Convey("*P (map)", func() { 1244 Convey("*P (map)", func() {
1336 i := 0 1245 i := 0
1337 » » » » So(ds.Run(q, func(pm *PropertyMap) { 1246 » » » » So(Run(c, q, func(pm *PropertyMap) {
1338 k, ok := pm.GetMeta("key") 1247 k, ok := pm.GetMeta("key")
1339 So(ok, ShouldBeTrue) 1248 So(ok, ShouldBeTrue)
1340 So(k.(*Key).IntID(), ShouldEqual, i+1) 1249 So(k.(*Key).IntID(), ShouldEqual, i+1)
1341 So((*pm).Slice("Value")[0].Value(), Shou ldEqual, i) 1250 So((*pm).Slice("Value")[0].Value(), Shou ldEqual, i)
1342 i++ 1251 i++
1343 }), ShouldBeNil) 1252 }), ShouldBeNil)
1344 }) 1253 })
1345 1254
1346 Convey("*P (chan)", func() { 1255 Convey("*P (chan)", func() {
1347 » » » » So(ds.Run(q, func(c *plsChan) { 1256 » » » » So(Run(c, q, func(ch *plsChan) {
1348 » » » » » So(ds.KeyForObj(c).StringID(), ShouldEqu al, "whyDoIExist") 1257 » » » » » So(KeyForObj(c, ch).StringID(), ShouldEq ual, "whyDoIExist")
1349 }), ShouldBeNil) 1258 }), ShouldBeNil)
1350 }) 1259 })
1351 1260
1352 Convey("S", func() { 1261 Convey("S", func() {
1353 i := 0 1262 i := 0
1354 » » » » So(ds.Run(q, func(cs CommonStruct) { 1263 » » » » So(Run(c, q, func(cs CommonStruct) {
1355 So(cs.ID, ShouldEqual, i+1) 1264 So(cs.ID, ShouldEqual, i+1)
1356 So(cs.Value, ShouldEqual, i) 1265 So(cs.Value, ShouldEqual, i)
1357 i++ 1266 i++
1358 }), ShouldBeNil) 1267 }), ShouldBeNil)
1359 }) 1268 })
1360 1269
1361 Convey("P", func() { 1270 Convey("P", func() {
1362 i := 0 1271 i := 0
1363 » » » » So(ds.Run(q, func(fpls FakePLS) { 1272 » » » » So(Run(c, q, func(fpls FakePLS) {
1364 So(fpls.gotLoaded, ShouldBeTrue) 1273 So(fpls.gotLoaded, ShouldBeTrue)
1365 So(fpls.IntID, ShouldEqual, i+1) 1274 So(fpls.IntID, ShouldEqual, i+1)
1366 So(fpls.Value, ShouldEqual, i) 1275 So(fpls.Value, ShouldEqual, i)
1367 i++ 1276 i++
1368 }), ShouldBeNil) 1277 }), ShouldBeNil)
1369 }) 1278 })
1370 1279
1371 Convey("P (map)", func() { 1280 Convey("P (map)", func() {
1372 i := 0 1281 i := 0
1373 » » » » So(ds.Run(q, func(pm PropertyMap) { 1282 » » » » So(Run(c, q, func(pm PropertyMap) {
1374 k, ok := pm.GetMeta("key") 1283 k, ok := pm.GetMeta("key")
1375 So(ok, ShouldBeTrue) 1284 So(ok, ShouldBeTrue)
1376 So(k.(*Key).IntID(), ShouldEqual, i+1) 1285 So(k.(*Key).IntID(), ShouldEqual, i+1)
1377 So(pm.Slice("Value")[0].Value(), ShouldE qual, i) 1286 So(pm.Slice("Value")[0].Value(), ShouldE qual, i)
1378 i++ 1287 i++
1379 }), ShouldBeNil) 1288 }), ShouldBeNil)
1380 }) 1289 })
1381 1290
1382 Convey("P (chan)", func() { 1291 Convey("P (chan)", func() {
1383 » » » » So(ds.Run(q, func(c plsChan) { 1292 » » » » So(Run(c, q, func(ch plsChan) {
1384 » » » » » So(ds.KeyForObj(c).StringID(), ShouldEqu al, "whyDoIExist") 1293 » » » » » So(KeyForObj(c, ch).StringID(), ShouldEq ual, "whyDoIExist")
1385 }), ShouldBeNil) 1294 }), ShouldBeNil)
1386 }) 1295 })
1387 1296
1388 Convey("Key", func() { 1297 Convey("Key", func() {
1389 i := 0 1298 i := 0
1390 » » » » So(ds.Run(q, func(k *Key) { 1299 » » » » So(Run(c, q, func(k *Key) {
1391 So(k.IntID(), ShouldEqual, i+1) 1300 So(k.IntID(), ShouldEqual, i+1)
1392 i++ 1301 i++
1393 }), ShouldBeNil) 1302 }), ShouldBeNil)
1394 }) 1303 })
1395 1304
1396 }) 1305 })
1397 }) 1306 })
1398 } 1307 }
1399 1308
1400 type fixedDataDatastore struct { 1309 type fixedDataDatastore struct {
(...skipping 26 matching lines...) Expand all
1427 cb(k, nil) 1336 cb(k, nil)
1428 } 1337 }
1429 return nil 1338 return nil
1430 } 1339 }
1431 1340
1432 func TestSchemaChange(t *testing.T) { 1341 func TestSchemaChange(t *testing.T) {
1433 t.Parallel() 1342 t.Parallel()
1434 1343
1435 Convey("Test changing schemas", t, func() { 1344 Convey("Test changing schemas", t, func() {
1436 fds := fixedDataDatastore{} 1345 fds := fixedDataDatastore{}
1437 » » ds := &datastoreImpl{&fds, "", ""} 1346 » » c := info.Set(context.Background(), fakeInfo{})
1347 » » c = SetRaw(c, &fds)
1438 1348
1439 Convey("Can add fields", func() { 1349 Convey("Can add fields", func() {
1440 initial := PropertyMap{ 1350 initial := PropertyMap{
1441 » » » » "$key": mpNI(ds.MakeKey("Val", 10)), 1351 » » » » "$key": mpNI(MakeKey(c, "Val", 10)),
1442 "Val": mp(100), 1352 "Val": mp(100),
1443 } 1353 }
1444 » » » So(ds.Put(initial), ShouldBeNil) 1354 » » » So(Put(c, initial), ShouldBeNil)
1445 1355
1446 type Val struct { 1356 type Val struct {
1447 ID int64 `gae:"$id"` 1357 ID int64 `gae:"$id"`
1448 1358
1449 Val int64 1359 Val int64
1450 TwoVal int64 // whoa, TWO vals! amazing 1360 TwoVal int64 // whoa, TWO vals! amazing
1451 } 1361 }
1452 tv := &Val{ID: 10, TwoVal: 2} 1362 tv := &Val{ID: 10, TwoVal: 2}
1453 » » » So(ds.Get(tv), ShouldBeNil) 1363 » » » So(Get(c, tv), ShouldBeNil)
1454 So(tv, ShouldResemble, &Val{ID: 10, Val: 100, TwoVal: 2} ) 1364 So(tv, ShouldResemble, &Val{ID: 10, Val: 100, TwoVal: 2} )
1455 }) 1365 })
1456 1366
1457 Convey("Removing fields", func() { 1367 Convey("Removing fields", func() {
1458 initial := PropertyMap{ 1368 initial := PropertyMap{
1459 » » » » "$key": mpNI(ds.MakeKey("Val", 10)), 1369 » » » » "$key": mpNI(MakeKey(c, "Val", 10)),
1460 "Val": mp(100), 1370 "Val": mp(100),
1461 "TwoVal": mp(200), 1371 "TwoVal": mp(200),
1462 } 1372 }
1463 » » » So(ds.Put(initial), ShouldBeNil) 1373 » » » So(Put(c, initial), ShouldBeNil)
1464 1374
1465 Convey("is normally an error", func() { 1375 Convey("is normally an error", func() {
1466 type Val struct { 1376 type Val struct {
1467 ID int64 `gae:"$id"` 1377 ID int64 `gae:"$id"`
1468 1378
1469 Val int64 1379 Val int64
1470 } 1380 }
1471 tv := &Val{ID: 10} 1381 tv := &Val{ID: 10}
1472 » » » » So(ds.Get(tv), ShouldErrLike, 1382 » » » » So(Get(c, tv), ShouldErrLike,
1473 `gae: cannot load field "TwoVal" into a "datastore.Val`) 1383 `gae: cannot load field "TwoVal" into a "datastore.Val`)
1474 So(tv, ShouldResemble, &Val{ID: 10, Val: 100}) 1384 So(tv, ShouldResemble, &Val{ID: 10, Val: 100})
1475 }) 1385 })
1476 1386
1477 Convey("Unless you have an ,extra field!", func() { 1387 Convey("Unless you have an ,extra field!", func() {
1478 type Val struct { 1388 type Val struct {
1479 ID int64 `gae:"$id"` 1389 ID int64 `gae:"$id"`
1480 1390
1481 Val int64 1391 Val int64
1482 Extra PropertyMap `gae:",extra"` 1392 Extra PropertyMap `gae:",extra"`
1483 } 1393 }
1484 tv := &Val{ID: 10} 1394 tv := &Val{ID: 10}
1485 » » » » So(ds.Get(tv), ShouldBeNil) 1395 » » » » So(Get(c, tv), ShouldBeNil)
1486 So(tv, ShouldResemble, &Val{ 1396 So(tv, ShouldResemble, &Val{
1487 ID: 10, 1397 ID: 10,
1488 Val: 100, 1398 Val: 100,
1489 Extra: PropertyMap{ 1399 Extra: PropertyMap{
1490 "TwoVal": PropertySlice{mp(200)} , 1400 "TwoVal": PropertySlice{mp(200)} ,
1491 }, 1401 },
1492 }) 1402 })
1493 }) 1403 })
1494 }) 1404 })
1495 1405
1496 Convey("Can round-trip extra fields", func() { 1406 Convey("Can round-trip extra fields", func() {
1497 type Expando struct { 1407 type Expando struct {
1498 ID int64 `gae:"$id"` 1408 ID int64 `gae:"$id"`
1499 1409
1500 Something int 1410 Something int
1501 Extra PropertyMap `gae:",extra"` 1411 Extra PropertyMap `gae:",extra"`
1502 } 1412 }
1503 ex := &Expando{10, 17, PropertyMap{ 1413 ex := &Expando{10, 17, PropertyMap{
1504 "Hello": mp("Hello"), 1414 "Hello": mp("Hello"),
1505 "World": mp(true), 1415 "World": mp(true),
1506 }} 1416 }}
1507 » » » So(ds.Put(ex), ShouldBeNil) 1417 » » » So(Put(c, ex), ShouldBeNil)
1508 1418
1509 ex = &Expando{ID: 10} 1419 ex = &Expando{ID: 10}
1510 » » » So(ds.Get(ex), ShouldBeNil) 1420 » » » So(Get(c, ex), ShouldBeNil)
1511 So(ex, ShouldResemble, &Expando{ 1421 So(ex, ShouldResemble, &Expando{
1512 ID: 10, 1422 ID: 10,
1513 Something: 17, 1423 Something: 17,
1514 Extra: PropertyMap{ 1424 Extra: PropertyMap{
1515 "Hello": PropertySlice{mp("Hello")}, 1425 "Hello": PropertySlice{mp("Hello")},
1516 "World": PropertySlice{mp(true)}, 1426 "World": PropertySlice{mp(true)},
1517 }, 1427 },
1518 }) 1428 })
1519 }) 1429 })
1520 1430
1521 Convey("Can read-but-not-write", func() { 1431 Convey("Can read-but-not-write", func() {
1522 initial := PropertyMap{ 1432 initial := PropertyMap{
1523 » » » » "$key": mpNI(ds.MakeKey("Convert", 10)), 1433 » » » » "$key": mpNI(MakeKey(c, "Convert", 10)),
1524 "Val": mp(100), 1434 "Val": mp(100),
1525 "TwoVal": mp(200), 1435 "TwoVal": mp(200),
1526 } 1436 }
1527 » » » So(ds.Put(initial), ShouldBeNil) 1437 » » » So(Put(c, initial), ShouldBeNil)
1528 type Convert struct { 1438 type Convert struct {
1529 ID int64 `gae:"$id"` 1439 ID int64 `gae:"$id"`
1530 1440
1531 Val int64 1441 Val int64
1532 NewVal int64 1442 NewVal int64
1533 Extra PropertyMap `gae:"-,extra"` 1443 Extra PropertyMap `gae:"-,extra"`
1534 } 1444 }
1535 » » » c := &Convert{ID: 10} 1445 » » » cnv := &Convert{ID: 10}
1536 » » » So(ds.Get(c), ShouldBeNil) 1446 » » » So(Get(c, cnv), ShouldBeNil)
1537 » » » So(c, ShouldResemble, &Convert{ 1447 » » » So(cnv, ShouldResemble, &Convert{
1538 ID: 10, Val: 100, NewVal: 0, Extra: PropertyMap{ "TwoVal": PropertySlice{mp(200)}}, 1448 ID: 10, Val: 100, NewVal: 0, Extra: PropertyMap{ "TwoVal": PropertySlice{mp(200)}},
1539 }) 1449 })
1540 » » » c.NewVal = c.Extra.Slice("TwoVal")[0].Value().(int64) 1450 » » » cnv.NewVal = cnv.Extra.Slice("TwoVal")[0].Value().(int64 )
1541 » » » So(ds.Put(c), ShouldBeNil) 1451 » » » So(Put(c, cnv), ShouldBeNil)
1542 1452
1543 » » » c = &Convert{ID: 10} 1453 » » » cnv = &Convert{ID: 10}
1544 » » » So(ds.Get(c), ShouldBeNil) 1454 » » » So(Get(c, cnv), ShouldBeNil)
1545 » » » So(c, ShouldResemble, &Convert{ 1455 » » » So(cnv, ShouldResemble, &Convert{
1546 ID: 10, Val: 100, NewVal: 200, Extra: nil, 1456 ID: 10, Val: 100, NewVal: 200, Extra: nil,
1547 }) 1457 })
1548 }) 1458 })
1549 1459
1550 Convey("Can black hole", func() { 1460 Convey("Can black hole", func() {
1551 initial := PropertyMap{ 1461 initial := PropertyMap{
1552 » » » » "$key": mpNI(ds.MakeKey("BlackHole", 10)), 1462 » » » » "$key": mpNI(MakeKey(c, "BlackHole", 10)),
1553 "Val": mp(100), 1463 "Val": mp(100),
1554 "TwoVal": mp(200), 1464 "TwoVal": mp(200),
1555 } 1465 }
1556 » » » So(ds.Put(initial), ShouldBeNil) 1466 » » » So(Put(c, initial), ShouldBeNil)
1557 type BlackHole struct { 1467 type BlackHole struct {
1558 ID int64 `gae:"$id"` 1468 ID int64 `gae:"$id"`
1559 1469
1560 NewStuff string 1470 NewStuff string
1561 blackHole PropertyMap `gae:"-,extra"` 1471 blackHole PropertyMap `gae:"-,extra"`
1562 } 1472 }
1563 b := &BlackHole{ID: 10, NewStuff: "(╯°□°)╯︵ ┻━┻"} 1473 b := &BlackHole{ID: 10, NewStuff: "(╯°□°)╯︵ ┻━┻"}
1564 » » » So(ds.Get(b), ShouldBeNil) 1474 » » » So(Get(c, b), ShouldBeNil)
1565 So(b, ShouldResemble, &BlackHole{ID: 10, NewStuff: "(╯°□ °)╯︵ ┻━┻"}) 1475 So(b, ShouldResemble, &BlackHole{ID: 10, NewStuff: "(╯°□ °)╯︵ ┻━┻"})
1566 }) 1476 })
1567 1477
1568 Convey("Can change field types", func() { 1478 Convey("Can change field types", func() {
1569 initial := PropertyMap{ 1479 initial := PropertyMap{
1570 » » » » "$key": mpNI(ds.MakeKey("IntChange", 10)), 1480 » » » » "$key": mpNI(MakeKey(c, "IntChange", 10)),
1571 "Val": mp(100), 1481 "Val": mp(100),
1572 } 1482 }
1573 » » » So(ds.Put(initial), ShouldBeNil) 1483 » » » So(Put(c, initial), ShouldBeNil)
1574 1484
1575 type IntChange struct { 1485 type IntChange struct {
1576 ID int64 `gae:"$id"` 1486 ID int64 `gae:"$id"`
1577 Val string 1487 Val string
1578 Extra PropertyMap `gae:"-,extra"` 1488 Extra PropertyMap `gae:"-,extra"`
1579 } 1489 }
1580 i := &IntChange{ID: 10} 1490 i := &IntChange{ID: 10}
1581 » » » So(ds.Get(i), ShouldBeNil) 1491 » » » So(Get(c, i), ShouldBeNil)
1582 So(i, ShouldResemble, &IntChange{ID: 10, Extra: Property Map{"Val": PropertySlice{mp(100)}}}) 1492 So(i, ShouldResemble, &IntChange{ID: 10, Extra: Property Map{"Val": PropertySlice{mp(100)}}})
1583 i.Val = fmt.Sprint(i.Extra.Slice("Val")[0].Value()) 1493 i.Val = fmt.Sprint(i.Extra.Slice("Val")[0].Value())
1584 » » » So(ds.Put(i), ShouldBeNil) 1494 » » » So(Put(c, i), ShouldBeNil)
1585 1495
1586 i = &IntChange{ID: 10} 1496 i = &IntChange{ID: 10}
1587 » » » So(ds.Get(i), ShouldBeNil) 1497 » » » So(Get(c, i), ShouldBeNil)
1588 So(i, ShouldResemble, &IntChange{ID: 10, Val: "100"}) 1498 So(i, ShouldResemble, &IntChange{ID: 10, Val: "100"})
1589 }) 1499 })
1590 1500
1591 Convey("Native fields have priority over Extra fields", func() { 1501 Convey("Native fields have priority over Extra fields", func() {
1592 type Dup struct { 1502 type Dup struct {
1593 ID int64 `gae:"$id"` 1503 ID int64 `gae:"$id"`
1594 Val int64 1504 Val int64
1595 Extra PropertyMap `gae:",extra"` 1505 Extra PropertyMap `gae:",extra"`
1596 } 1506 }
1597 d := &Dup{ID: 10, Val: 100, Extra: PropertyMap{ 1507 d := &Dup{ID: 10, Val: 100, Extra: PropertyMap{
1598 "Val": PropertySlice{mp(200)}, 1508 "Val": PropertySlice{mp(200)},
1599 "Other": PropertySlice{mp("other")}, 1509 "Other": PropertySlice{mp("other")},
1600 }} 1510 }}
1601 » » » So(ds.Put(d), ShouldBeNil) 1511 » » » So(Put(c, d), ShouldBeNil)
1602 1512
1603 d = &Dup{ID: 10} 1513 d = &Dup{ID: 10}
1604 » » » So(ds.Get(d), ShouldBeNil) 1514 » » » So(Get(c, d), ShouldBeNil)
1605 So(d, ShouldResemble, &Dup{ 1515 So(d, ShouldResemble, &Dup{
1606 ID: 10, Val: 100, Extra: PropertyMap{"Other": Pr opertySlice{mp("other")}}, 1516 ID: 10, Val: 100, Extra: PropertyMap{"Other": Pr opertySlice{mp("other")}},
1607 }) 1517 })
1608 }) 1518 })
1609 1519
1610 Convey("Can change repeated field to non-repeating field", func( ) { 1520 Convey("Can change repeated field to non-repeating field", func( ) {
1611 initial := PropertyMap{ 1521 initial := PropertyMap{
1612 » » » » "$key": mpNI(ds.MakeKey("NonRepeating", 10)), 1522 » » » » "$key": mpNI(MakeKey(c, "NonRepeating", 10)),
1613 "Val": PropertySlice{mp(100), mp(200), mp(400)} , 1523 "Val": PropertySlice{mp(100), mp(200), mp(400)} ,
1614 } 1524 }
1615 » » » So(ds.Put(initial), ShouldBeNil) 1525 » » » So(Put(c, initial), ShouldBeNil)
1616 1526
1617 type NonRepeating struct { 1527 type NonRepeating struct {
1618 ID int64 `gae:"$id"` 1528 ID int64 `gae:"$id"`
1619 Val int64 1529 Val int64
1620 Extra PropertyMap `gae:",extra"` 1530 Extra PropertyMap `gae:",extra"`
1621 } 1531 }
1622 n := &NonRepeating{ID: 10} 1532 n := &NonRepeating{ID: 10}
1623 » » » So(ds.Get(n), ShouldBeNil) 1533 » » » So(Get(c, n), ShouldBeNil)
1624 So(n, ShouldResemble, &NonRepeating{ 1534 So(n, ShouldResemble, &NonRepeating{
1625 ID: 10, Val: 0, Extra: PropertyMap{ 1535 ID: 10, Val: 0, Extra: PropertyMap{
1626 "Val": PropertySlice{mp(100), mp(200), m p(400)}, 1536 "Val": PropertySlice{mp(100), mp(200), m p(400)},
1627 }, 1537 },
1628 }) 1538 })
1629 }) 1539 })
1630 1540
1631 Convey("Deals correctly with recursive types", func() { 1541 Convey("Deals correctly with recursive types", func() {
1632 initial := PropertyMap{ 1542 initial := PropertyMap{
1633 » » » » "$key": mpNI(ds.MakeKey("Outer", 10)), 1543 » » » » "$key": mpNI(MakeKey(c, "Outer", 10)),
1634 "I.A": PropertySlice{mp(1), mp(2), mp(4)}, 1544 "I.A": PropertySlice{mp(1), mp(2), mp(4)},
1635 "I.B": PropertySlice{mp(10), mp(20), mp(40)}, 1545 "I.B": PropertySlice{mp(10), mp(20), mp(40)},
1636 "I.C": PropertySlice{mp(100), mp(200), mp(400)} , 1546 "I.C": PropertySlice{mp(100), mp(200), mp(400)} ,
1637 } 1547 }
1638 » » » So(ds.Put(initial), ShouldBeNil) 1548 » » » So(Put(c, initial), ShouldBeNil)
1639 type Inner struct { 1549 type Inner struct {
1640 A int64 1550 A int64
1641 B int64 1551 B int64
1642 } 1552 }
1643 type Outer struct { 1553 type Outer struct {
1644 ID int64 `gae:"$id"` 1554 ID int64 `gae:"$id"`
1645 1555
1646 I []Inner 1556 I []Inner
1647 Extra PropertyMap `gae:",extra"` 1557 Extra PropertyMap `gae:",extra"`
1648 } 1558 }
1649 o := &Outer{ID: 10} 1559 o := &Outer{ID: 10}
1650 » » » So(ds.Get(o), ShouldBeNil) 1560 » » » So(Get(c, o), ShouldBeNil)
1651 So(o, ShouldResemble, &Outer{ 1561 So(o, ShouldResemble, &Outer{
1652 ID: 10, 1562 ID: 10,
1653 I: []Inner{ 1563 I: []Inner{
1654 {1, 10}, 1564 {1, 10},
1655 {2, 20}, 1565 {2, 20},
1656 {4, 40}, 1566 {4, 40},
1657 }, 1567 },
1658 Extra: PropertyMap{ 1568 Extra: PropertyMap{
1659 "I.C": PropertySlice{mp(100), mp(200), m p(400)}, 1569 "I.C": PropertySlice{mp(100), mp(200), m p(400)},
1660 }, 1570 },
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
1914 if err != nil { 1824 if err != nil {
1915 panic(fmt.Errorf("failed to find absolute path f or `%s`", sameLevelDir)) 1825 panic(fmt.Errorf("failed to find absolute path f or `%s`", sameLevelDir))
1916 } 1826 }
1917 1827
1918 ids, err := FindAndParseIndexYAML(abs) 1828 ids, err := FindAndParseIndexYAML(abs)
1919 So(err, ShouldBeNil) 1829 So(err, ShouldBeNil)
1920 So(ids[1].Kind, ShouldEqual, "Test Foo") 1830 So(ids[1].Kind, ShouldEqual, "Test Foo")
1921 }) 1831 })
1922 }) 1832 })
1923 } 1833 }
OLDNEW
« no previous file with comments | « service/datastore/datastore.go ('k') | service/datastore/dumper/dumper.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698