OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // 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 "fmt" | 10 "fmt" |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 if f.Kind == "" { | 173 if f.Kind == "" { |
174 So(ret.SetMeta("kind", "FakePLS"), ShouldBeNil) | 174 So(ret.SetMeta("kind", "FakePLS"), ShouldBeNil) |
175 } else { | 175 } else { |
176 So(ret.SetMeta("kind", f.Kind), ShouldBeNil) | 176 So(ret.SetMeta("kind", f.Kind), ShouldBeNil) |
177 } | 177 } |
178 So(ret.SetMeta("assertExtra", true), ShouldBeNil) | 178 So(ret.SetMeta("assertExtra", true), ShouldBeNil) |
179 } | 179 } |
180 return ret, nil | 180 return ret, nil |
181 } | 181 } |
182 | 182 |
183 func (f *FakePLS) GetMetaDefault(key string, dflt interface{}) interface{} { | |
184 return GetMetaDefaultImpl(f.GetMeta, key, dflt) | |
185 } | |
186 | |
187 func (f *FakePLS) GetMeta(key string) (interface{}, error) { | 183 func (f *FakePLS) GetMeta(key string) (interface{}, error) { |
188 if f.failGetMeta { | 184 if f.failGetMeta { |
189 return nil, errors.New("FakePLS.GetMeta") | 185 return nil, errors.New("FakePLS.GetMeta") |
190 } | 186 } |
191 switch key { | 187 switch key { |
192 case "id": | 188 case "id": |
193 if f.StringID != "" { | 189 if f.StringID != "" { |
194 return f.StringID, nil | 190 return f.StringID, nil |
195 } | 191 } |
196 return f.IntID, nil | 192 return f.IntID, nil |
(...skipping 12 matching lines...) Expand all Loading... |
209 So(ret.SetMeta("id", id), ShouldBeNil) | 205 So(ret.SetMeta("id", id), ShouldBeNil) |
210 } | 206 } |
211 if kind, err := f.GetMeta("kind"); err != nil { | 207 if kind, err := f.GetMeta("kind"); err != nil { |
212 So(ret.SetMeta("kind", kind), ShouldBeNil) | 208 So(ret.SetMeta("kind", kind), ShouldBeNil) |
213 } | 209 } |
214 return ret | 210 return ret |
215 } | 211 } |
216 | 212 |
217 func (f *FakePLS) SetMeta(key string, val interface{}) error { | 213 func (f *FakePLS) SetMeta(key string, val interface{}) error { |
218 if f.failSetMeta { | 214 if f.failSetMeta { |
219 » » return errors.New("FakePL.SetMeta") | 215 » » return errors.New("FakePLS.SetMeta") |
220 } | 216 } |
221 if key == "id" { | 217 if key == "id" { |
222 switch x := val.(type) { | 218 switch x := val.(type) { |
223 case int64: | 219 case int64: |
224 f.IntID = x | 220 f.IntID = x |
225 case string: | 221 case string: |
226 f.StringID = x | 222 f.StringID = x |
227 } | 223 } |
228 return nil | 224 return nil |
229 } | 225 } |
230 if key == "kind" { | 226 if key == "kind" { |
231 f.Kind = val.(string) | 227 f.Kind = val.(string) |
232 return nil | 228 return nil |
233 } | 229 } |
234 return ErrMetaFieldUnset | 230 return ErrMetaFieldUnset |
235 } | 231 } |
236 | 232 |
237 func (f *FakePLS) Problem() error { | 233 func (f *FakePLS) Problem() error { |
238 if f.failProblem { | 234 if f.failProblem { |
239 return errors.New("FakePLS.Problem") | 235 return errors.New("FakePLS.Problem") |
240 } | 236 } |
241 return nil | 237 return nil |
242 } | 238 } |
243 | 239 |
244 type MGSWithNoKind struct { | 240 type MGSWithNoKind struct { |
245 S string | 241 S string |
246 } | 242 } |
247 | 243 |
248 func (s *MGSWithNoKind) GetMetaDefault(key string, dflt interface{}) interface{}
{ | |
249 return GetMetaDefaultImpl(s.GetMeta, key, dflt) | |
250 } | |
251 | |
252 func (s *MGSWithNoKind) GetMeta(key string) (interface{}, error) { | 244 func (s *MGSWithNoKind) GetMeta(key string) (interface{}, error) { |
253 return nil, ErrMetaFieldUnset | 245 return nil, ErrMetaFieldUnset |
254 } | 246 } |
255 | 247 |
256 func (s *MGSWithNoKind) GetAllMeta() PropertyMap { | 248 func (s *MGSWithNoKind) GetAllMeta() PropertyMap { |
257 return PropertyMap{} | 249 return PropertyMap{} |
258 } | 250 } |
259 | 251 |
260 func (s *MGSWithNoKind) SetMeta(key string, val interface{}) error { | 252 func (s *MGSWithNoKind) SetMeta(key string, val interface{}) error { |
261 return ErrMetaFieldUnset | 253 return ErrMetaFieldUnset |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 }) | 328 }) |
337 | 329 |
338 }) | 330 }) |
339 | 331 |
340 Convey("bad", func() { | 332 Convey("bad", func() { |
341 Convey("a propmap without $kind", func() { | 333 Convey("a propmap without $kind", func() { |
342 pm := PropertyMap{} | 334 pm := PropertyMap{} |
343 So(pm.SetMeta("id", 100), ShouldBeNil) | 335 So(pm.SetMeta("id", 100), ShouldBeNil) |
344 So(func() { ds.KeyForObj(pm) }, ShouldPanic) | 336 So(func() { ds.KeyForObj(pm) }, ShouldPanic) |
345 }) | 337 }) |
| 338 |
| 339 Convey("a bad object", func() { |
| 340 type BadObj struct { |
| 341 ID int64 `gae:"$id"` |
| 342 |
| 343 NonSerializableField complex64 |
| 344 } |
| 345 |
| 346 _, err := ds.KeyForObjErr(&BadObj{ID: 1}) |
| 347 So(err, ShouldErrLike, `field "NonSerializableFi
eld" has invalid type: complex64`) |
| 348 }) |
346 }) | 349 }) |
347 }) | 350 }) |
348 } | 351 } |
349 | 352 |
350 func TestPut(t *testing.T) { | 353 func TestPut(t *testing.T) { |
351 t.Parallel() | 354 t.Parallel() |
352 | 355 |
353 Convey("Test Put/PutMulti", t, func() { | 356 Convey("Test Put/PutMulti", t, func() { |
354 c := info.Set(context.Background(), fakeInfo{}) | 357 c := info.Set(context.Background(), fakeInfo{}) |
355 c = SetRawFactory(c, fakeDatastoreFactory) | 358 c = SetRawFactory(c, fakeDatastoreFactory) |
356 ds := Get(c) | 359 ds := Get(c) |
357 | 360 |
358 Convey("bad", func() { | 361 Convey("bad", func() { |
359 Convey("static can't serialize", func() { | 362 Convey("static can't serialize", func() { |
360 bss := []badStruct{{}, {}} | 363 bss := []badStruct{{}, {}} |
361 » » » » So(ds.PutMulti(bss).Error(), ShouldContainSubstr
ing, "invalid PutMulti input") | 364 » » » » So(ds.PutMulti(bss), ShouldErrLike, "invalid Put
Multi input") |
362 }) | 365 }) |
363 | 366 |
364 Convey("static ptr can't serialize", func() { | 367 Convey("static ptr can't serialize", func() { |
365 bss := []*badStruct{{}, {}} | 368 bss := []*badStruct{{}, {}} |
366 » » » » So(ds.PutMulti(bss).Error(), ShouldContainSubstr
ing, "invalid PutMulti input") | 369 » » » » So(ds.PutMulti(bss), ShouldErrLike, "invalid Put
Multi input") |
367 }) | 370 }) |
368 | 371 |
369 Convey("static bad type (non-slice)", func() { | 372 Convey("static bad type (non-slice)", func() { |
370 » » » » So(ds.PutMulti(100).Error(), ShouldContainSubstr
ing, "invalid PutMulti input") | 373 » » » » So(ds.PutMulti(100), ShouldErrLike, "invalid Put
Multi input") |
371 }) | 374 }) |
372 | 375 |
373 Convey("static bad type (slice of bad type)", func() { | 376 Convey("static bad type (slice of bad type)", func() { |
374 » » » » So(ds.PutMulti([]int{}).Error(), ShouldContainSu
bstring, "invalid PutMulti input") | 377 » » » » So(ds.PutMulti([]int{}), ShouldErrLike, "invalid
PutMulti input") |
375 }) | 378 }) |
376 | 379 |
377 Convey("dynamic can't serialize", func() { | 380 Convey("dynamic can't serialize", func() { |
378 fplss := []FakePLS{{failSave: true}, {}} | 381 fplss := []FakePLS{{failSave: true}, {}} |
379 » » » » So(ds.PutMulti(fplss).Error(), ShouldContainSubs
tring, "FakePLS.Save") | 382 » » » » So(ds.PutMulti(fplss), ShouldErrLike, "FakePLS.S
ave") |
380 }) | 383 }) |
381 | 384 |
382 Convey("can't get keys", func() { | 385 Convey("can't get keys", func() { |
383 fplss := []FakePLS{{failGetMeta: true}, {}} | 386 fplss := []FakePLS{{failGetMeta: true}, {}} |
384 » » » » So(ds.PutMulti(fplss).Error(), ShouldContainSubs
tring, "unable to extract $kind") | 387 » » » » So(ds.PutMulti(fplss), ShouldErrLike, "FakePLS.G
etMeta") |
385 }) | 388 }) |
386 | 389 |
387 Convey("get single error for RPC failure", func() { | 390 Convey("get single error for RPC failure", func() { |
388 fplss := []FakePLS{{Kind: "FailAll"}, {}} | 391 fplss := []FakePLS{{Kind: "FailAll"}, {}} |
389 » » » » So(ds.PutMulti(fplss).Error(), ShouldEqual, "Put
Multi fail all") | 392 » » » » So(ds.PutMulti(fplss), ShouldErrLike, "PutMulti
fail all") |
390 }) | 393 }) |
391 | 394 |
392 Convey("get multi error for individual failures", func()
{ | 395 Convey("get multi error for individual failures", func()
{ |
393 fplss := []FakePLS{{}, {Kind: "Fail"}} | 396 fplss := []FakePLS{{}, {Kind: "Fail"}} |
394 So(ds.PutMulti(fplss), ShouldResemble, errors.Mu
ltiError{nil, errors.New("PutMulti fail")}) | 397 So(ds.PutMulti(fplss), ShouldResemble, errors.Mu
ltiError{nil, errors.New("PutMulti fail")}) |
395 }) | 398 }) |
396 | 399 |
397 Convey("put with non-modifyable type is an error", func(
) { | 400 Convey("put with non-modifyable type is an error", func(
) { |
398 cs := CommonStruct{} | 401 cs := CommonStruct{} |
399 » » » » So(ds.Put(cs).Error(), ShouldContainSubstring, "
invalid Put input type") | 402 » » » » So(ds.Put(cs), ShouldErrLike, "invalid Put input
type") |
400 }) | 403 }) |
401 | 404 |
402 Convey("struct with no $kind is an error", func() { | 405 Convey("struct with no $kind is an error", func() { |
403 s := MGSWithNoKind{} | 406 s := MGSWithNoKind{} |
404 » » » » So(ds.Put(&s).Error(), ShouldContainSubstring, "
unable to extract $kind") | 407 » » » » So(ds.Put(&s), ShouldErrLike, "unable to extract
$kind") |
405 }) | 408 }) |
406 }) | 409 }) |
407 | 410 |
408 Convey("ok", func() { | 411 Convey("ok", func() { |
409 Convey("[]S", func() { | 412 Convey("[]S", func() { |
410 css := make([]CommonStruct, 7) | 413 css := make([]CommonStruct, 7) |
411 for i := range css { | 414 for i := range css { |
412 if i == 4 { | 415 if i == 4 { |
413 css[i].ID = 200 | 416 css[i].ID = 200 |
414 } | 417 } |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
596 | 599 |
597 Convey("Test Get/GetMulti", t, func() { | 600 Convey("Test Get/GetMulti", t, func() { |
598 c := info.Set(context.Background(), fakeInfo{}) | 601 c := info.Set(context.Background(), fakeInfo{}) |
599 c = SetRawFactory(c, fakeDatastoreFactory) | 602 c = SetRawFactory(c, fakeDatastoreFactory) |
600 ds := Get(c) | 603 ds := Get(c) |
601 So(ds, ShouldNotBeNil) | 604 So(ds, ShouldNotBeNil) |
602 | 605 |
603 Convey("bad", func() { | 606 Convey("bad", func() { |
604 Convey("static can't serialize", func() { | 607 Convey("static can't serialize", func() { |
605 toGet := []badStruct{{}, {}} | 608 toGet := []badStruct{{}, {}} |
606 » » » » So(ds.GetMulti(toGet).Error(), ShouldContainSubs
tring, "invalid GetMulti input") | 609 » » » » So(ds.GetMulti(toGet), ShouldErrLike, "invalid G
etMulti input") |
607 }) | 610 }) |
608 | 611 |
609 Convey("can't get keys", func() { | 612 Convey("can't get keys", func() { |
610 fplss := []FakePLS{{failGetMeta: true}, {}} | 613 fplss := []FakePLS{{failGetMeta: true}, {}} |
611 » » » » So(ds.GetMulti(fplss).Error(), ShouldContainSubs
tring, "unable to extract $kind") | 614 » » » » So(ds.GetMulti(fplss), ShouldErrLike, "FakePLS.G
etMeta") |
612 }) | 615 }) |
613 | 616 |
614 Convey("get single error for RPC failure", func() { | 617 Convey("get single error for RPC failure", func() { |
615 fplss := []FakePLS{ | 618 fplss := []FakePLS{ |
616 {IntID: 1, Kind: "FailAll"}, | 619 {IntID: 1, Kind: "FailAll"}, |
617 {IntID: 2}, | 620 {IntID: 2}, |
618 } | 621 } |
619 So(ds.GetMulti(fplss).Error(), ShouldEqual, "Get
Multi fail all") | 622 So(ds.GetMulti(fplss).Error(), ShouldEqual, "Get
Multi fail all") |
620 }) | 623 }) |
621 | 624 |
622 Convey("get multi error for individual failures", func()
{ | 625 Convey("get multi error for individual failures", func()
{ |
623 fplss := []FakePLS{{IntID: 1}, {IntID: 2, Kind:
"Fail"}} | 626 fplss := []FakePLS{{IntID: 1}, {IntID: 2, Kind:
"Fail"}} |
624 So(ds.GetMulti(fplss), ShouldResemble, errors.Mu
ltiError{nil, errors.New("GetMulti fail")}) | 627 So(ds.GetMulti(fplss), ShouldResemble, errors.Mu
ltiError{nil, errors.New("GetMulti fail")}) |
625 }) | 628 }) |
626 | 629 |
627 Convey("get with non-modifiable type is an error", func(
) { | 630 Convey("get with non-modifiable type is an error", func(
) { |
628 cs := CommonStruct{} | 631 cs := CommonStruct{} |
629 » » » » So(ds.Get(cs).Error(), ShouldContainSubstring, "
invalid Get input type") | 632 » » » » So(ds.Get(cs), ShouldErrLike, "invalid Get input
type") |
630 }) | 633 }) |
631 | 634 |
632 » » » Convey("failure to save metadata is an issue too", func(
) { | 635 » » » Convey("failure to save metadata is no problem though",
func() { |
633 » » » » cs := &FakePLS{failGetMeta: true} | 636 » » » » // It just won't save the key |
634 » » » » So(ds.Get(cs).Error(), ShouldContainSubstring, "
unable to extract $kind") | 637 » » » » cs := &FakePLS{IntID: 10, failSetMeta: true} |
| 638 » » » » So(ds.Get(cs), ShouldBeNil) |
635 }) | 639 }) |
636 }) | 640 }) |
637 | 641 |
638 Convey("ok", func() { | 642 Convey("ok", func() { |
639 Convey("Get", func() { | 643 Convey("Get", func() { |
640 cs := &CommonStruct{ID: 1} | 644 cs := &CommonStruct{ID: 1} |
641 So(ds.Get(cs), ShouldBeNil) | 645 So(ds.Get(cs), ShouldBeNil) |
642 So(cs.Value, ShouldEqual, 1) | 646 So(cs.Value, ShouldEqual, 1) |
643 }) | 647 }) |
644 | 648 |
(...skipping 21 matching lines...) Expand all Loading... |
666 Convey("Test GetAll", t, func() { | 670 Convey("Test GetAll", t, func() { |
667 c := info.Set(context.Background(), fakeInfo{}) | 671 c := info.Set(context.Background(), fakeInfo{}) |
668 c = SetRawFactory(c, fakeDatastoreFactory) | 672 c = SetRawFactory(c, fakeDatastoreFactory) |
669 ds := Get(c) | 673 ds := Get(c) |
670 So(ds, ShouldNotBeNil) | 674 So(ds, ShouldNotBeNil) |
671 | 675 |
672 q := NewQuery("").Limit(5) | 676 q := NewQuery("").Limit(5) |
673 | 677 |
674 Convey("bad", func() { | 678 Convey("bad", func() { |
675 Convey("nil target", func() { | 679 Convey("nil target", func() { |
676 » » » » So(ds.GetAll(q, (*[]PropertyMap)(nil)).Error(),
ShouldContainSubstring, "dst: <nil>") | 680 » » » » So(ds.GetAll(q, (*[]PropertyMap)(nil)), ShouldEr
rLike, "dst: <nil>") |
677 }) | 681 }) |
678 | 682 |
679 Convey("bad type", func() { | 683 Convey("bad type", func() { |
680 output := 100 | 684 output := 100 |
681 » » » » So(ds.GetAll(q, &output).Error(), ShouldContainS
ubstring, "invalid GetAll input type") | 685 » » » » So(ds.GetAll(q, &output), ShouldErrLike, "invali
d GetAll input type") |
682 }) | 686 }) |
683 | 687 |
684 Convey("bad type (non pointer)", func() { | 688 Convey("bad type (non pointer)", func() { |
685 » » » » So(ds.GetAll(q, "moo").Error(), ShouldContainSub
string, "must have a ptr-to-slice") | 689 » » » » So(ds.GetAll(q, "moo"), ShouldErrLike, "must hav
e a ptr-to-slice") |
686 }) | 690 }) |
687 | 691 |
688 Convey("bad type (underspecified)", func() { | 692 Convey("bad type (underspecified)", func() { |
689 output := []PropertyLoadSaver(nil) | 693 output := []PropertyLoadSaver(nil) |
690 » » » » So(ds.GetAll(q, &output).Error(), ShouldContainS
ubstring, "invalid GetAll input type") | 694 » » » » So(ds.GetAll(q, &output), ShouldErrLike, "invali
d GetAll input type") |
691 }) | 695 }) |
692 }) | 696 }) |
693 | 697 |
694 Convey("ok", func() { | 698 Convey("ok", func() { |
695 Convey("*[]S", func() { | 699 Convey("*[]S", func() { |
696 output := []CommonStruct(nil) | 700 output := []CommonStruct(nil) |
697 So(ds.GetAll(q, &output), ShouldBeNil) | 701 So(ds.GetAll(q, &output), ShouldBeNil) |
698 So(len(output), ShouldEqual, 5) | 702 So(len(output), ShouldEqual, 5) |
699 for i, o := range output { | 703 for i, o := range output { |
700 So(o.ID, ShouldEqual, i+1) | 704 So(o.ID, ShouldEqual, i+1) |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
781 ds := Get(c) | 785 ds := Get(c) |
782 So(ds, ShouldNotBeNil) | 786 So(ds, ShouldNotBeNil) |
783 | 787 |
784 q := NewQuery("kind").Limit(5) | 788 q := NewQuery("kind").Limit(5) |
785 | 789 |
786 Convey("bad", func() { | 790 Convey("bad", func() { |
787 assertBadTypePanics := func(cb interface{}) { | 791 assertBadTypePanics := func(cb interface{}) { |
788 defer func() { | 792 defer func() { |
789 err, _ := recover().(error) | 793 err, _ := recover().(error) |
790 So(err, ShouldNotBeNil) | 794 So(err, ShouldNotBeNil) |
791 » » » » » So(err.Error(), ShouldContainSubstring, | 795 » » » » » So(err, ShouldErrLike, "cb does not matc
h the required callback signature") |
792 » » » » » » "cb does not match the required
callback signature") | |
793 }() | 796 }() |
794 So(ds.Run(q, cb), ShouldBeNil) | 797 So(ds.Run(q, cb), ShouldBeNil) |
795 } | 798 } |
796 | 799 |
797 Convey("not a function", func() { | 800 Convey("not a function", func() { |
798 assertBadTypePanics("I am a potato") | 801 assertBadTypePanics("I am a potato") |
799 }) | 802 }) |
800 | 803 |
801 Convey("bad proto type", func() { | 804 Convey("bad proto type", func() { |
802 assertBadTypePanics(func(v int, _ CursorCB) bool
{ | 805 assertBadTypePanics(func(v int, _ CursorCB) bool
{ |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
915 So(ds.Run(q, func(k *Key, _ CursorCB) bool { | 918 So(ds.Run(q, func(k *Key, _ CursorCB) bool { |
916 So(k.IntID(), ShouldEqual, i+1) | 919 So(k.IntID(), ShouldEqual, i+1) |
917 i++ | 920 i++ |
918 return true | 921 return true |
919 }), ShouldBeNil) | 922 }), ShouldBeNil) |
920 }) | 923 }) |
921 | 924 |
922 }) | 925 }) |
923 }) | 926 }) |
924 } | 927 } |
OLD | NEW |