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 20 matching lines...) Expand all Loading... |
31 ns string | 31 ns string |
32 } | 32 } |
33 | 33 |
34 func (f *fakeDatastore) mkKey(elems ...interface{}) *Key { | 34 func (f *fakeDatastore) mkKey(elems ...interface{}) *Key { |
35 return MakeKey(f.aid, f.ns, elems...) | 35 return MakeKey(f.aid, f.ns, elems...) |
36 } | 36 } |
37 | 37 |
38 func (f *fakeDatastore) Run(fq *FinalizedQuery, cb RawRunCB) error { | 38 func (f *fakeDatastore) Run(fq *FinalizedQuery, cb RawRunCB) error { |
39 lim, _ := fq.Limit() | 39 lim, _ := fq.Limit() |
40 | 40 |
| 41 cursCB := func() (Cursor, error) { |
| 42 return fakeCursor("CURSOR"), nil |
| 43 } |
| 44 |
41 for i := int32(0); i < lim; i++ { | 45 for i := int32(0); i < lim; i++ { |
42 if v, ok := fq.eqFilts["$err_single"]; ok { | 46 if v, ok := fq.eqFilts["$err_single"]; ok { |
43 idx := fq.eqFilts["$err_single_idx"][0].Value().(int64) | 47 idx := fq.eqFilts["$err_single_idx"][0].Value().(int64) |
44 if idx == int64(i) { | 48 if idx == int64(i) { |
45 return errors.New(v[0].Value().(string)) | 49 return errors.New(v[0].Value().(string)) |
46 } | 50 } |
47 } | 51 } |
48 k := f.mkKey("Kind", i+1) | 52 k := f.mkKey("Kind", i+1) |
49 if i == 10 { | 53 if i == 10 { |
50 k = f.mkKey("Kind", "eleven") | 54 k = f.mkKey("Kind", "eleven") |
51 } | 55 } |
52 pm := PropertyMap{"Value": {MkProperty(i)}} | 56 pm := PropertyMap{"Value": {MkProperty(i)}} |
53 » » if !cb(k, pm, nil) { | 57 » » if err := cb(k, pm, cursCB); err != nil { |
54 » » » break | 58 » » » if err == Stop { |
| 59 » » » » err = nil |
| 60 » » » } |
| 61 » » » return err |
55 } | 62 } |
56 } | 63 } |
57 return nil | 64 return nil |
58 } | 65 } |
59 | 66 |
60 func (f *fakeDatastore) PutMulti(keys []*Key, vals []PropertyMap, cb PutMultiCB)
error { | 67 func (f *fakeDatastore) PutMulti(keys []*Key, vals []PropertyMap, cb PutMultiCB)
error { |
61 if keys[0].Kind() == "FailAll" { | 68 if keys[0].Kind() == "FailAll" { |
62 return errors.New("PutMulti fail all") | 69 return errors.New("PutMulti fail all") |
63 } | 70 } |
64 _, assertExtra := vals[0].GetMeta("assertExtra") | 71 _, assertExtra := vals[0].GetMeta("assertExtra") |
(...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
644 Convey("ok", func() { | 651 Convey("ok", func() { |
645 Convey("Get", func() { | 652 Convey("Get", func() { |
646 cs := &CommonStruct{ID: 1} | 653 cs := &CommonStruct{ID: 1} |
647 So(ds.Get(cs), ShouldBeNil) | 654 So(ds.Get(cs), ShouldBeNil) |
648 So(cs.Value, ShouldEqual, 1) | 655 So(cs.Value, ShouldEqual, 1) |
649 }) | 656 }) |
650 | 657 |
651 Convey("Raw access too", func() { | 658 Convey("Raw access too", func() { |
652 rds := ds.Raw() | 659 rds := ds.Raw() |
653 keys := []*Key{ds.MakeKey("Kind", 1)} | 660 keys := []*Key{ds.MakeKey("Kind", 1)} |
654 » » » » So(rds.GetMulti(keys, nil, func(pm PropertyMap,
err error) { | 661 » » » » So(rds.GetMulti(keys, nil, func(pm PropertyMap,
err error) error { |
655 So(err, ShouldBeNil) | 662 So(err, ShouldBeNil) |
656 So(pm["Value"][0].Value(), ShouldEqual,
1) | 663 So(pm["Value"][0].Value(), ShouldEqual,
1) |
| 664 return nil |
657 }), ShouldBeNil) | 665 }), ShouldBeNil) |
658 }) | 666 }) |
659 | 667 |
660 Convey("but general failure to save is fine on a Get", f
unc() { | 668 Convey("but general failure to save is fine on a Get", f
unc() { |
661 cs := &FakePLS{failSave: true, IntID: 7} | 669 cs := &FakePLS{failSave: true, IntID: 7} |
662 So(ds.Get(cs), ShouldBeNil) | 670 So(ds.Get(cs), ShouldBeNil) |
663 }) | 671 }) |
664 }) | 672 }) |
665 | 673 |
666 }) | 674 }) |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
793 Convey("bad", func() { | 801 Convey("bad", func() { |
794 assertBadTypePanics := func(cb interface{}) { | 802 assertBadTypePanics := func(cb interface{}) { |
795 So(func() { ds.Run(q, cb) }, ShouldPanicLike, | 803 So(func() { ds.Run(q, cb) }, ShouldPanicLike, |
796 "cb does not match the required callback
signature") | 804 "cb does not match the required callback
signature") |
797 } | 805 } |
798 | 806 |
799 Convey("not a function", func() { | 807 Convey("not a function", func() { |
800 assertBadTypePanics("I am a potato") | 808 assertBadTypePanics("I am a potato") |
801 }) | 809 }) |
802 | 810 |
| 811 Convey("nil", func() { |
| 812 assertBadTypePanics(nil) |
| 813 }) |
| 814 |
| 815 Convey("interface", func() { |
| 816 assertBadTypePanics(func(pls PropertyLoadSaver)
{}) |
| 817 }) |
| 818 |
803 Convey("bad proto type", func() { | 819 Convey("bad proto type", func() { |
804 » » » » cb := func(v int, _ CursorCB) bool { | 820 » » » » cb := func(v int) { |
805 panic("never here!") | 821 panic("never here!") |
806 } | 822 } |
807 So(func() { ds.Run(q, cb) }, ShouldPanicLike, | 823 So(func() { ds.Run(q, cb) }, ShouldPanicLike, |
808 "invalid argument type: int") | 824 "invalid argument type: int") |
809 }) | 825 }) |
810 | 826 |
811 Convey("wrong # args", func() { | 827 Convey("wrong # args", func() { |
812 » » » » assertBadTypePanics(func(v CommonStruct, _ Curso
rCB) { | 828 » » » » assertBadTypePanics(func(v CommonStruct, _ Curso
rCB, _ int) { |
813 panic("never here!") | 829 panic("never here!") |
814 }) | 830 }) |
815 }) | 831 }) |
816 | 832 |
817 Convey("wrong ret type", func() { | 833 Convey("wrong ret type", func() { |
818 » » » » assertBadTypePanics(func(v CommonStruct, _ Curso
rCB) error { | 834 » » » » assertBadTypePanics(func(v CommonStruct) bool { |
| 835 » » » » » panic("never here!") |
| 836 » » » » }) |
| 837 » » » }) |
| 838 |
| 839 » » » Convey("wrong # rets", func() { |
| 840 » » » » assertBadTypePanics(func(v CommonStruct) (int, e
rror) { |
819 panic("never here!") | 841 panic("never here!") |
820 }) | 842 }) |
821 }) | 843 }) |
822 | 844 |
823 Convey("bad 2nd arg", func() { | 845 Convey("bad 2nd arg", func() { |
824 » » » » assertBadTypePanics(func(v CommonStruct, _ Curso
r) bool { | 846 » » » » assertBadTypePanics(func(v CommonStruct, _ Curso
r) error { |
825 panic("never here!") | 847 panic("never here!") |
826 }) | 848 }) |
827 }) | 849 }) |
828 | 850 |
829 Convey("early abort on error", func() { | 851 Convey("early abort on error", func() { |
830 q = q.Eq("$err_single", "Query fail").Eq("$err_s
ingle_idx", 3) | 852 q = q.Eq("$err_single", "Query fail").Eq("$err_s
ingle_idx", 3) |
831 i := 0 | 853 i := 0 |
832 » » » » So(ds.Run(q, func(c CommonStruct, _ CursorCB) bo
ol { | 854 » » » » So(ds.Run(q, func(c CommonStruct) { |
833 i++ | 855 i++ |
834 return true | |
835 }), ShouldErrLike, "Query fail") | 856 }), ShouldErrLike, "Query fail") |
836 So(i, ShouldEqual, 3) | 857 So(i, ShouldEqual, 3) |
837 }) | 858 }) |
838 | 859 |
839 Convey("return error on serialization failure", func() { | 860 Convey("return error on serialization failure", func() { |
840 » » » » So(ds.Run(q, func(_ permaBad, _ CursorCB) bool { | 861 » » » » So(ds.Run(q, func(_ permaBad) { |
841 panic("never here") | 862 panic("never here") |
842 }).Error(), ShouldEqual, "permaBad") | 863 }).Error(), ShouldEqual, "permaBad") |
843 }) | 864 }) |
844 }) | 865 }) |
845 | 866 |
846 Convey("ok", func() { | 867 Convey("ok", func() { |
| 868 Convey("can return error to stop", func() { |
| 869 i := 0 |
| 870 So(ds.Run(q, func(c CommonStruct) error { |
| 871 i++ |
| 872 return Stop |
| 873 }), ShouldBeNil) |
| 874 So(i, ShouldEqual, 1) |
| 875 |
| 876 i = 0 |
| 877 So(ds.Run(q, func(c CommonStruct, _ CursorCB) er
ror { |
| 878 i++ |
| 879 return fmt.Errorf("my error") |
| 880 }), ShouldErrLike, "my error") |
| 881 So(i, ShouldEqual, 1) |
| 882 }) |
| 883 |
| 884 Convey("Can optionally get cursor function", func() { |
| 885 i := 0 |
| 886 So(ds.Run(q, func(c CommonStruct, ccb CursorCB)
{ |
| 887 i++ |
| 888 curs, err := ccb() |
| 889 So(err, ShouldBeNil) |
| 890 So(curs.String(), ShouldEqual, "CURSOR") |
| 891 }), ShouldBeNil) |
| 892 So(i, ShouldEqual, 5) |
| 893 }) |
| 894 |
847 Convey("*S", func() { | 895 Convey("*S", func() { |
848 i := 0 | 896 i := 0 |
849 » » » » So(ds.Run(q, func(cs *CommonStruct, _ CursorCB)
bool { | 897 » » » » So(ds.Run(q, func(cs *CommonStruct) { |
850 So(cs.ID, ShouldEqual, i+1) | 898 So(cs.ID, ShouldEqual, i+1) |
851 So(cs.Value, ShouldEqual, i) | 899 So(cs.Value, ShouldEqual, i) |
852 i++ | 900 i++ |
853 return true | |
854 }), ShouldBeNil) | 901 }), ShouldBeNil) |
855 }) | 902 }) |
856 | 903 |
857 Convey("*P", func() { | 904 Convey("*P", func() { |
858 i := 0 | 905 i := 0 |
859 » » » » So(ds.Run(q.Limit(12), func(fpls *FakePLS, _ Cur
sorCB) bool { | 906 » » » » So(ds.Run(q.Limit(12), func(fpls *FakePLS) { |
860 So(fpls.gotLoaded, ShouldBeTrue) | 907 So(fpls.gotLoaded, ShouldBeTrue) |
861 if i == 10 { | 908 if i == 10 { |
862 So(fpls.StringID, ShouldEqual, "
eleven") | 909 So(fpls.StringID, ShouldEqual, "
eleven") |
863 } else { | 910 } else { |
864 So(fpls.IntID, ShouldEqual, i+1) | 911 So(fpls.IntID, ShouldEqual, i+1) |
865 } | 912 } |
866 So(fpls.Value, ShouldEqual, i) | 913 So(fpls.Value, ShouldEqual, i) |
867 i++ | 914 i++ |
868 return true | |
869 }), ShouldBeNil) | 915 }), ShouldBeNil) |
870 }) | 916 }) |
871 | 917 |
872 Convey("*P (map)", func() { | 918 Convey("*P (map)", func() { |
873 i := 0 | 919 i := 0 |
874 » » » » So(ds.Run(q, func(pm *PropertyMap, _ CursorCB) b
ool { | 920 » » » » So(ds.Run(q, func(pm *PropertyMap) { |
875 k, ok := pm.GetMeta("key") | 921 k, ok := pm.GetMeta("key") |
876 So(ok, ShouldBeTrue) | 922 So(ok, ShouldBeTrue) |
877 So(k.(*Key).IntID(), ShouldEqual, i+1) | 923 So(k.(*Key).IntID(), ShouldEqual, i+1) |
878 So((*pm)["Value"][0].Value(), ShouldEqua
l, i) | 924 So((*pm)["Value"][0].Value(), ShouldEqua
l, i) |
879 i++ | 925 i++ |
880 return true | |
881 }), ShouldBeNil) | 926 }), ShouldBeNil) |
882 }) | 927 }) |
883 | 928 |
884 Convey("S", func() { | 929 Convey("S", func() { |
885 i := 0 | 930 i := 0 |
886 » » » » So(ds.Run(q, func(cs CommonStruct, _ CursorCB) b
ool { | 931 » » » » So(ds.Run(q, func(cs CommonStruct) { |
887 So(cs.ID, ShouldEqual, i+1) | 932 So(cs.ID, ShouldEqual, i+1) |
888 So(cs.Value, ShouldEqual, i) | 933 So(cs.Value, ShouldEqual, i) |
889 i++ | 934 i++ |
890 return true | |
891 }), ShouldBeNil) | 935 }), ShouldBeNil) |
892 }) | 936 }) |
893 | 937 |
894 Convey("P", func() { | 938 Convey("P", func() { |
895 i := 0 | 939 i := 0 |
896 » » » » So(ds.Run(q, func(fpls FakePLS, _ CursorCB) bool
{ | 940 » » » » So(ds.Run(q, func(fpls FakePLS) { |
897 So(fpls.gotLoaded, ShouldBeTrue) | 941 So(fpls.gotLoaded, ShouldBeTrue) |
898 So(fpls.IntID, ShouldEqual, i+1) | 942 So(fpls.IntID, ShouldEqual, i+1) |
899 So(fpls.Value, ShouldEqual, i) | 943 So(fpls.Value, ShouldEqual, i) |
900 i++ | 944 i++ |
901 return true | |
902 }), ShouldBeNil) | 945 }), ShouldBeNil) |
903 }) | 946 }) |
904 | 947 |
905 Convey("P (map)", func() { | 948 Convey("P (map)", func() { |
906 i := 0 | 949 i := 0 |
907 » » » » So(ds.Run(q, func(pm PropertyMap, _ CursorCB) bo
ol { | 950 » » » » So(ds.Run(q, func(pm PropertyMap) { |
908 k, ok := pm.GetMeta("key") | 951 k, ok := pm.GetMeta("key") |
909 So(ok, ShouldBeTrue) | 952 So(ok, ShouldBeTrue) |
910 So(k.(*Key).IntID(), ShouldEqual, i+1) | 953 So(k.(*Key).IntID(), ShouldEqual, i+1) |
911 So(pm["Value"][0].Value(), ShouldEqual,
i) | 954 So(pm["Value"][0].Value(), ShouldEqual,
i) |
912 i++ | 955 i++ |
913 return true | |
914 }), ShouldBeNil) | 956 }), ShouldBeNil) |
915 }) | 957 }) |
916 | 958 |
917 Convey("Key", func() { | 959 Convey("Key", func() { |
918 i := 0 | 960 i := 0 |
919 » » » » So(ds.Run(q, func(k *Key, _ CursorCB) bool { | 961 » » » » So(ds.Run(q, func(k *Key) { |
920 So(k.IntID(), ShouldEqual, i+1) | 962 So(k.IntID(), ShouldEqual, i+1) |
921 i++ | 963 i++ |
922 return true | |
923 }), ShouldBeNil) | 964 }), ShouldBeNil) |
924 }) | 965 }) |
925 | 966 |
926 }) | 967 }) |
927 }) | 968 }) |
928 } | 969 } |
929 | 970 |
930 type fixedDataDatastore struct { | 971 type fixedDataDatastore struct { |
931 RawInterface | 972 RawInterface |
932 | 973 |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1212 Convey("extra field with bad type", func() { | 1253 Convey("extra field with bad type", func() { |
1213 type Bad struct { | 1254 type Bad struct { |
1214 A int64 `gae:",extra"` | 1255 A int64 `gae:",extra"` |
1215 } | 1256 } |
1216 So(func() { GetPLS(&Bad{}) }, ShouldPanicLike, | 1257 So(func() { GetPLS(&Bad{}) }, ShouldPanicLike, |
1217 "struct 'extra' field has invalid type i
nt64") | 1258 "struct 'extra' field has invalid type i
nt64") |
1218 }) | 1259 }) |
1219 }) | 1260 }) |
1220 }) | 1261 }) |
1221 } | 1262 } |
OLD | NEW |