| OLD | NEW |
| 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" |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 | 139 |
| 140 type CommonStruct struct { | 140 type CommonStruct struct { |
| 141 ID int64 `gae:"$id"` | 141 ID int64 `gae:"$id"` |
| 142 Parent *Key `gae:"$parent"` | 142 Parent *Key `gae:"$parent"` |
| 143 | 143 |
| 144 Value int64 | 144 Value int64 |
| 145 } | 145 } |
| 146 | 146 |
| 147 type permaBad struct { | 147 type permaBad struct { |
| 148 PropertyLoadSaver | 148 PropertyLoadSaver |
| 149 MetaGetterSetter |
| 149 } | 150 } |
| 150 | 151 |
| 151 func (f *permaBad) Load(pm PropertyMap) error { | 152 func (f *permaBad) Load(pm PropertyMap) error { |
| 152 return errors.New("permaBad") | 153 return errors.New("permaBad") |
| 153 } | 154 } |
| 154 | 155 |
| 155 type SingletonStruct struct { | 156 type SingletonStruct struct { |
| 156 id int64 `gae:"$id,1"` | 157 id int64 `gae:"$id,1"` |
| 157 } | 158 } |
| 158 | 159 |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 Convey("get single error for RPC failure", func(
) { | 466 Convey("get single error for RPC failure", func(
) { |
| 466 fplss := []FakePLS{{Kind: "FailAll"}, {}
} | 467 fplss := []FakePLS{{Kind: "FailAll"}, {}
} |
| 467 So(ds.Put(fplss), ShouldEqual, errFailAl
l) | 468 So(ds.Put(fplss), ShouldEqual, errFailAl
l) |
| 468 }) | 469 }) |
| 469 | 470 |
| 470 Convey("get multi error for individual failures"
, func() { | 471 Convey("get multi error for individual failures"
, func() { |
| 471 fplss := []FakePLS{{}, {Kind: "Fail"}} | 472 fplss := []FakePLS{{}, {Kind: "Fail"}} |
| 472 So(ds.Put(fplss), ShouldResemble, errors
.MultiError{nil, errFail}) | 473 So(ds.Put(fplss), ShouldResemble, errors
.MultiError{nil, errFail}) |
| 473 }) | 474 }) |
| 474 | 475 |
| 475 Convey("put with non-modifyable type is an error
", func() { | |
| 476 cs := CommonStruct{} | |
| 477 So(func() { ds.Put(cs) }, ShouldPanicLik
e, | |
| 478 "invalid input type (datastore.C
ommonStruct): not a pointer") | |
| 479 }) | |
| 480 | |
| 481 Convey("get with *Key is an error", func() { | 476 Convey("get with *Key is an error", func() { |
| 482 So(func() { ds.Get(&Key{}) }, ShouldPani
cLike, | 477 So(func() { ds.Get(&Key{}) }, ShouldPani
cLike, |
| 483 "invalid input type (*datastore.
Key): not user datatype") | 478 "invalid input type (*datastore.
Key): not user datatype") |
| 484 }) | 479 }) |
| 485 | 480 |
| 486 Convey("struct with no $kind is an error", func(
) { | 481 Convey("struct with no $kind is an error", func(
) { |
| 487 s := MGSWithNoKind{} | 482 s := MGSWithNoKind{} |
| 488 So(ds.Put(&s), ShouldErrLike, "unable to
extract $kind") | 483 So(ds.Put(&s), ShouldErrLike, "unable to
extract $kind") |
| 489 }) | 484 }) |
| 490 | 485 |
| 491 Convey("struct with invalid but non-nil key is a
n error", func() { | 486 Convey("struct with invalid but non-nil key is a
n error", func() { |
| 492 type BadParent struct { | 487 type BadParent struct { |
| 493 ID int64 `gae:"$id"` | 488 ID int64 `gae:"$id"` |
| 494 Parent *Key `gae:"$parent"` | 489 Parent *Key `gae:"$parent"` |
| 495 } | 490 } |
| 496 // having an Incomplete parent makes an
invalid key | 491 // having an Incomplete parent makes an
invalid key |
| 497 bp := &BadParent{ID: 1, Parent: ds.MakeK
ey("Something", 0)} | 492 bp := &BadParent{ID: 1, Parent: ds.MakeK
ey("Something", 0)} |
| 498 So(ds.Put(bp), ShouldErrLike, ErrInvalid
Key) | 493 So(ds.Put(bp), ShouldErrLike, ErrInvalid
Key) |
| 499 }) | 494 }) |
| 500 | 495 |
| 501 Convey("vararg with errors", func() { | 496 Convey("vararg with errors", func() { |
| 502 successSlice := []CommonStruct{{Value: 0
}, {Value: 1}} | 497 successSlice := []CommonStruct{{Value: 0
}, {Value: 1}} |
| 503 failSlice := []FakePLS{{Kind: "Fail"}, {
Value: 3}} | 498 failSlice := []FakePLS{{Kind: "Fail"}, {
Value: 3}} |
| 504 emptySlice := []CommonStruct(nil) | 499 emptySlice := []CommonStruct(nil) |
| 505 cs0 := CommonStruct{Value: 4} | 500 cs0 := CommonStruct{Value: 4} |
| 506 » » » » » cs1 := FakePLS{Kind: "Fail", Value: 5} | 501 » » » » » failPLS := FakePLS{Kind: "Fail", Value:
5} |
| 507 fpls := FakePLS{StringID: "ohai", Value:
6} | 502 fpls := FakePLS{StringID: "ohai", Value:
6} |
| 508 | 503 |
| 509 » » » » » err := ds.Put(successSlice, failSlice, e
mptySlice, &cs0, &cs1, &fpls) | 504 » » » » » err := ds.Put(successSlice, failSlice, e
mptySlice, &cs0, &failPLS, &fpls) |
| 510 So(err, ShouldResemble, errors.MultiErro
r{ | 505 So(err, ShouldResemble, errors.MultiErro
r{ |
| 511 nil, errors.MultiError{errFail,
nil}, nil, nil, errFail, nil}) | 506 nil, errors.MultiError{errFail,
nil}, nil, nil, errFail, nil}) |
| 512 So(successSlice[0].ID, ShouldEqual, 1) | 507 So(successSlice[0].ID, ShouldEqual, 1) |
| 513 So(successSlice[1].ID, ShouldEqual, 2) | 508 So(successSlice[1].ID, ShouldEqual, 2) |
| 514 So(cs0.ID, ShouldEqual, 5) | 509 So(cs0.ID, ShouldEqual, 5) |
| 515 }) | 510 }) |
| 516 }) | 511 }) |
| 517 | 512 |
| 518 Convey("ok", func() { | 513 Convey("ok", func() { |
| 519 Convey("[]S", func() { | 514 Convey("[]S", func() { |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 726 er, err = ds.Exists(k, ds.MakeKey("DNE", "other")) | 721 er, err = ds.Exists(k, ds.MakeKey("DNE", "other")) |
| 727 So(err, ShouldBeNil) | 722 So(err, ShouldBeNil) |
| 728 So(er.Get(0), ShouldBeTrue) | 723 So(er.Get(0), ShouldBeTrue) |
| 729 So(er.Get(1), ShouldBeFalse) | 724 So(er.Get(1), ShouldBeFalse) |
| 730 | 725 |
| 731 // Multi-arg keys with two missing. | 726 // Multi-arg keys with two missing. |
| 732 er, err = ds.Exists(ds.MakeKey("DNE", "nope"), ds.MakeKe
y("DNE", "other")) | 727 er, err = ds.Exists(ds.MakeKey("DNE", "nope"), ds.MakeKe
y("DNE", "other")) |
| 733 So(err, ShouldBeNil) | 728 So(err, ShouldBeNil) |
| 734 So(er.Any(), ShouldBeFalse) | 729 So(er.Any(), ShouldBeFalse) |
| 735 | 730 |
| 731 // Single struct pointer. |
| 732 er, err = ds.Exists(&CommonStruct{ID: 1}) |
| 733 So(err, ShouldBeNil) |
| 734 So(er.All(), ShouldBeTrue) |
| 735 |
| 736 // Multi-arg mixed key/struct/slices. | 736 // Multi-arg mixed key/struct/slices. |
| 737 » » » er, err = ds.Exists(&CommonStruct{ID: 1}, []*CommonStruc
t(nil), []*Key{ds.MakeKey("DNE", "nope"), ds.MakeKey("hello", "ohai")}) | 737 » » » er, err = ds.Exists( |
| 738 » » » » &CommonStruct{ID: 1}, |
| 739 » » » » []*CommonStruct(nil), |
| 740 » » » » []*Key{ds.MakeKey("DNE", "nope"), ds.MakeKey("he
llo", "ohai")}, |
| 741 » » » ) |
| 738 So(err, ShouldBeNil) | 742 So(err, ShouldBeNil) |
| 739 So(er.Get(0), ShouldBeTrue) | 743 So(er.Get(0), ShouldBeTrue) |
| 740 So(er.Get(1), ShouldBeTrue) | 744 So(er.Get(1), ShouldBeTrue) |
| 741 So(er.Get(2), ShouldBeFalse) | 745 So(er.Get(2), ShouldBeFalse) |
| 742 So(er.Get(2, 0), ShouldBeFalse) | 746 So(er.Get(2, 0), ShouldBeFalse) |
| 743 So(er.Get(2, 1), ShouldBeTrue) | 747 So(er.Get(2, 1), ShouldBeTrue) |
| 744 }) | 748 }) |
| 745 | 749 |
| 746 Convey("ExistsMulti", func() { | 750 Convey("ExistsMulti", func() { |
| 747 Convey("Returns no error if there are no failures.", fun
c() { | 751 Convey("Returns no error if there are no failures.", fun
c() { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 778 }) | 782 }) |
| 779 | 783 |
| 780 Convey("get multi error for individual failure",
func() { | 784 Convey("get multi error for individual failure",
func() { |
| 781 keys := []*Key{ | 785 keys := []*Key{ |
| 782 ds.MakeKey("Ok", 1), | 786 ds.MakeKey("Ok", 1), |
| 783 ds.MakeKey("Fail", 2), | 787 ds.MakeKey("Fail", 2), |
| 784 } | 788 } |
| 785 So(ds.Delete(keys), ShouldResemble, erro
rs.MultiError{nil, errFail}) | 789 So(ds.Delete(keys), ShouldResemble, erro
rs.MultiError{nil, errFail}) |
| 786 }) | 790 }) |
| 787 | 791 |
| 792 Convey("put with non-modifyable type is an error
", func() { |
| 793 cs := CommonStruct{} |
| 794 So(func() { ds.Put(cs) }, ShouldPanicLik
e, |
| 795 "invalid input type (datastore.C
ommonStruct): not a pointer") |
| 796 }) |
| 797 |
| 788 Convey("get single error when deleting a single"
, func() { | 798 Convey("get single error when deleting a single"
, func() { |
| 789 k := ds.MakeKey("Fail", 1) | 799 k := ds.MakeKey("Fail", 1) |
| 790 So(ds.Delete(k), ShouldEqual, errFail) | 800 So(ds.Delete(k), ShouldEqual, errFail) |
| 791 }) | 801 }) |
| 792 }) | 802 }) |
| 793 | 803 |
| 794 Convey("good", func() { | 804 Convey("good", func() { |
| 795 » » » » // Single struct. | 805 » » » » // Single struct pointer. |
| 796 So(ds.Delete(&CommonStruct{ID: 1}), ShouldBeNil) | 806 So(ds.Delete(&CommonStruct{ID: 1}), ShouldBeNil) |
| 797 | 807 |
| 798 // Single key. | 808 // Single key. |
| 799 So(ds.Delete(ds.MakeKey("hello", "ohai")), Shoul
dBeNil) | 809 So(ds.Delete(ds.MakeKey("hello", "ohai")), Shoul
dBeNil) |
| 800 | 810 |
| 801 // Single struct DNE. | 811 // Single struct DNE. |
| 802 So(ds.Delete(&CommonStruct{ID: noSuchEntityID}),
ShouldEqual, ErrNoSuchEntity) | 812 So(ds.Delete(&CommonStruct{ID: noSuchEntityID}),
ShouldEqual, ErrNoSuchEntity) |
| 803 | 813 |
| 804 // Single key DNE. | 814 // Single key DNE. |
| 805 So(ds.Delete(ds.MakeKey("DNE", "nope")), ShouldE
qual, ErrNoSuchEntity) | 815 So(ds.Delete(ds.MakeKey("DNE", "nope")), ShouldE
qual, ErrNoSuchEntity) |
| 806 | 816 |
| 807 // Mixed key/struct/slices. | 817 // Mixed key/struct/slices. |
| 808 » » » » err := ds.Delete(&CommonStruct{ID: 1}, []*Key{ds
.MakeKey("hello", "ohai"), ds.MakeKey("DNE", "nope")}) | 818 » » » » err := ds.Delete( |
| 819 » » » » » &CommonStruct{ID: 1}, |
| 820 » » » » » []*Key{ds.MakeKey("hello", "ohai"), ds.M
akeKey("DNE", "nope")}, |
| 821 » » » » ) |
| 809 So(err, ShouldResemble, errors.MultiError{nil, e
rrors.MultiError{nil, ErrNoSuchEntity}}) | 822 So(err, ShouldResemble, errors.MultiError{nil, e
rrors.MultiError{nil, ErrNoSuchEntity}}) |
| 810 }) | 823 }) |
| 811 }) | 824 }) |
| 812 | 825 |
| 813 Convey("Testing DeleteMulti", func() { | 826 Convey("Testing DeleteMulti", func() { |
| 814 Convey("Succeeds for valid keys.", func() { | 827 Convey("Succeeds for valid keys.", func() { |
| 815 So(ds.DeleteMulti([]*Key{ds.MakeKey("hello", "oh
ai")}), ShouldBeNil) | 828 So(ds.DeleteMulti([]*Key{ds.MakeKey("hello", "oh
ai")}), ShouldBeNil) |
| 816 So(ds.DeleteMulti([]*Key{ds.MakeKey("hello", "oh
ai"), ds.MakeKey("hello", "sup")}), ShouldBeNil) | 829 So(ds.DeleteMulti([]*Key{ds.MakeKey("hello", "oh
ai"), ds.MakeKey("hello", "sup")}), ShouldBeNil) |
| 817 }) | 830 }) |
| 818 | 831 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 879 // It just won't save the key | 892 // It just won't save the key |
| 880 cs := &FakePLS{IntID: 10, failSetMeta: t
rue} | 893 cs := &FakePLS{IntID: 10, failSetMeta: t
rue} |
| 881 So(ds.Get(cs), ShouldBeNil) | 894 So(ds.Get(cs), ShouldBeNil) |
| 882 }) | 895 }) |
| 883 | 896 |
| 884 Convey("vararg with errors", func() { | 897 Convey("vararg with errors", func() { |
| 885 successSlice := []CommonStruct{{ID: 1},
{ID: 2}} | 898 successSlice := []CommonStruct{{ID: 1},
{ID: 2}} |
| 886 failSlice := []CommonStruct{{ID: noSuchE
ntityID}, {ID: 3}} | 899 failSlice := []CommonStruct{{ID: noSuchE
ntityID}, {ID: 3}} |
| 887 emptySlice := []CommonStruct(nil) | 900 emptySlice := []CommonStruct(nil) |
| 888 cs0 := CommonStruct{ID: 4} | 901 cs0 := CommonStruct{ID: 4} |
| 889 » » » » » cs1 := CommonStruct{ID: noSuchEntityID} | 902 » » » » » failPLS := CommonStruct{ID: noSuchEntity
ID} |
| 890 fpls := FakePLS{StringID: "ohai"} | 903 fpls := FakePLS{StringID: "ohai"} |
| 891 | 904 |
| 892 » » » » » err := ds.Get(successSlice, failSlice, e
mptySlice, &cs0, &cs1, &fpls) | 905 » » » » » err := ds.Get(successSlice, failSlice, e
mptySlice, &cs0, &failPLS, &fpls) |
| 893 So(err, ShouldResemble, errors.MultiErro
r{ | 906 So(err, ShouldResemble, errors.MultiErro
r{ |
| 894 nil, errors.MultiError{ErrNoSuch
Entity, nil}, nil, nil, ErrNoSuchEntity, nil}) | 907 nil, errors.MultiError{ErrNoSuch
Entity, nil}, nil, nil, ErrNoSuchEntity, nil}) |
| 895 So(successSlice[0].Value, ShouldEqual, 1
) | 908 So(successSlice[0].Value, ShouldEqual, 1
) |
| 896 So(successSlice[1].Value, ShouldEqual, 2
) | 909 So(successSlice[1].Value, ShouldEqual, 2
) |
| 897 So(cs0.Value, ShouldEqual, 5) | 910 So(cs0.Value, ShouldEqual, 5) |
| 898 So(fpls.Value, ShouldEqual, 7) | 911 So(fpls.Value, ShouldEqual, 7) |
| 899 }) | 912 }) |
| 900 }) | 913 }) |
| 901 | 914 |
| 902 Convey("ok", func() { | 915 Convey("ok", func() { |
| (...skipping 898 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1801 if err != nil { | 1814 if err != nil { |
| 1802 panic(fmt.Errorf("failed to find absolute path f
or `%s`", sameLevelDir)) | 1815 panic(fmt.Errorf("failed to find absolute path f
or `%s`", sameLevelDir)) |
| 1803 } | 1816 } |
| 1804 | 1817 |
| 1805 ids, err := FindAndParseIndexYAML(abs) | 1818 ids, err := FindAndParseIndexYAML(abs) |
| 1806 So(err, ShouldBeNil) | 1819 So(err, ShouldBeNil) |
| 1807 So(ids[1].Kind, ShouldEqual, "Test Foo") | 1820 So(ids[1].Kind, ShouldEqual, "Test Foo") |
| 1808 }) | 1821 }) |
| 1809 }) | 1822 }) |
| 1810 } | 1823 } |
| OLD | NEW |