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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 if v, ok := fq.eqFilts["$err_single"]; ok { | 75 if v, ok := fq.eqFilts["$err_single"]; ok { |
76 idx := fq.eqFilts["$err_single_idx"][0].Value().(int64) | 76 idx := fq.eqFilts["$err_single_idx"][0].Value().(int64) |
77 if idx == int64(i) { | 77 if idx == int64(i) { |
78 return errors.New(v[0].Value().(string)) | 78 return errors.New(v[0].Value().(string)) |
79 } | 79 } |
80 } | 80 } |
81 k := f.mkKey("Kind", i+1) | 81 k := f.mkKey("Kind", i+1) |
82 if i == 10 { | 82 if i == 10 { |
83 k = f.mkKey("Kind", "eleven") | 83 k = f.mkKey("Kind", "eleven") |
84 } | 84 } |
85 » » pm := PropertyMap{"Value": {MkProperty(i)}} | 85 » » pm := PropertyMap{"Value": MkProperty(i)} |
86 if err := cb(k, pm, cursCB); err != nil { | 86 if err := cb(k, pm, cursCB); err != nil { |
87 if err == Stop { | 87 if err == Stop { |
88 err = nil | 88 err = nil |
89 } | 89 } |
90 return err | 90 return err |
91 } | 91 } |
92 } | 92 } |
93 return nil | 93 return nil |
94 } | 94 } |
95 | 95 |
96 func (f *fakeDatastore) PutMulti(keys []*Key, vals []PropertyMap, cb NewKeyCB) e
rror { | 96 func (f *fakeDatastore) PutMulti(keys []*Key, vals []PropertyMap, cb NewKeyCB) e
rror { |
97 if keys[0].Kind() == "FailAll" { | 97 if keys[0].Kind() == "FailAll" { |
98 return errFailAll | 98 return errFailAll |
99 } | 99 } |
100 _, assertExtra := vals[0].GetMeta("assertExtra") | 100 _, assertExtra := vals[0].GetMeta("assertExtra") |
101 for i, k := range keys { | 101 for i, k := range keys { |
102 err := error(nil) | 102 err := error(nil) |
103 if k.Kind() == "Fail" { | 103 if k.Kind() == "Fail" { |
104 err = errFail | 104 err = errFail |
105 } else { | 105 } else { |
106 » » » So(vals[i]["Value"], ShouldResemble, []Property{MkProper
ty(i)}) | 106 » » » So(vals[i].Slice("Value"), ShouldResemble, PropertySlice
{MkProperty(i)}) |
107 if assertExtra { | 107 if assertExtra { |
108 » » » » So(vals[i]["Extra"], ShouldResemble, []Property{
MkProperty("whoa")}) | 108 » » » » So(vals[i].Slice("Extra"), ShouldResemble, Prope
rtySlice{MkProperty("whoa")}) |
109 } | 109 } |
110 if k.IsIncomplete() { | 110 if k.IsIncomplete() { |
111 k = NewKey(k.AppID(), k.Namespace(), k.Kind(), "
", int64(i+1), k.Parent()) | 111 k = NewKey(k.AppID(), k.Namespace(), k.Kind(), "
", int64(i+1), k.Parent()) |
112 } | 112 } |
113 } | 113 } |
114 cb(k, err) | 114 cb(k, err) |
115 } | 115 } |
116 return nil | 116 return nil |
117 } | 117 } |
118 | 118 |
119 const noSuchEntityID = 0xdead | 119 const noSuchEntityID = 0xdead |
120 | 120 |
121 func (f *fakeDatastore) GetMulti(keys []*Key, _meta MultiMetaGetter, cb GetMulti
CB) error { | 121 func (f *fakeDatastore) GetMulti(keys []*Key, _meta MultiMetaGetter, cb GetMulti
CB) error { |
122 if keys[0].Kind() == "FailAll" { | 122 if keys[0].Kind() == "FailAll" { |
123 return errFailAll | 123 return errFailAll |
124 } | 124 } |
125 for i, k := range keys { | 125 for i, k := range keys { |
126 if k.Kind() == "Fail" { | 126 if k.Kind() == "Fail" { |
127 cb(nil, errFail) | 127 cb(nil, errFail) |
128 } else if k.Kind() == "DNE" || k.IntID() == noSuchEntityID { | 128 } else if k.Kind() == "DNE" || k.IntID() == noSuchEntityID { |
129 cb(nil, ErrNoSuchEntity) | 129 cb(nil, ErrNoSuchEntity) |
130 } else { | 130 } else { |
131 » » » cb(PropertyMap{"Value": {MkProperty(i + 1)}}, nil) | 131 » » » cb(PropertyMap{"Value": MkProperty(i + 1)}, nil) |
132 } | 132 } |
133 } | 133 } |
134 return nil | 134 return nil |
135 } | 135 } |
136 | 136 |
137 func (f *fakeDatastore) DeleteMulti(keys []*Key, cb DeleteMultiCB) error { | 137 func (f *fakeDatastore) DeleteMulti(keys []*Key, cb DeleteMultiCB) error { |
138 if keys[0].Kind() == "FailAll" { | 138 if keys[0].Kind() == "FailAll" { |
139 return errFailAll | 139 return errFailAll |
140 } | 140 } |
141 for _, k := range keys { | 141 for _, k := range keys { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 failSetMeta bool | 190 failSetMeta bool |
191 } | 191 } |
192 | 192 |
193 var _ PropertyLoadSaver = (*FakePLS)(nil) | 193 var _ PropertyLoadSaver = (*FakePLS)(nil) |
194 | 194 |
195 func (f *FakePLS) Load(pm PropertyMap) error { | 195 func (f *FakePLS) Load(pm PropertyMap) error { |
196 if f.failLoad { | 196 if f.failLoad { |
197 return errors.New("FakePLS.Load") | 197 return errors.New("FakePLS.Load") |
198 } | 198 } |
199 f.gotLoaded = true | 199 f.gotLoaded = true |
200 » f.Value = pm["Value"][0].Value().(int64) | 200 » f.Value = pm.Slice("Value")[0].Value().(int64) |
201 return nil | 201 return nil |
202 } | 202 } |
203 | 203 |
204 func (f *FakePLS) Save(withMeta bool) (PropertyMap, error) { | 204 func (f *FakePLS) Save(withMeta bool) (PropertyMap, error) { |
205 if f.failSave { | 205 if f.failSave { |
206 return nil, errors.New("FakePLS.Save") | 206 return nil, errors.New("FakePLS.Save") |
207 } | 207 } |
208 ret := PropertyMap{ | 208 ret := PropertyMap{ |
209 » » "Value": {MkProperty(f.Value)}, | 209 » » "Value": MkProperty(f.Value), |
210 » » "Extra": {MkProperty("whoa")}, | 210 » » "Extra": MkProperty("whoa"), |
211 } | 211 } |
212 if withMeta { | 212 if withMeta { |
213 id, _ := f.GetMeta("id") | 213 id, _ := f.GetMeta("id") |
214 So(ret.SetMeta("id", id), ShouldBeTrue) | 214 So(ret.SetMeta("id", id), ShouldBeTrue) |
215 if f.Kind == "" { | 215 if f.Kind == "" { |
216 So(ret.SetMeta("kind", "FakePLS"), ShouldBeTrue) | 216 So(ret.SetMeta("kind", "FakePLS"), ShouldBeTrue) |
217 } else { | 217 } else { |
218 So(ret.SetMeta("kind", f.Kind), ShouldBeTrue) | 218 So(ret.SetMeta("kind", f.Kind), ShouldBeTrue) |
219 } | 219 } |
220 So(ret.SetMeta("assertExtra", true), ShouldBeTrue) | 220 So(ret.SetMeta("assertExtra", true), ShouldBeTrue) |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 case "kind": | 294 case "kind": |
295 return "plsChan", true | 295 return "plsChan", true |
296 case "id": | 296 case "id": |
297 return "whyDoIExist", true | 297 return "whyDoIExist", true |
298 } | 298 } |
299 return nil, false | 299 return nil, false |
300 } | 300 } |
301 | 301 |
302 func (c plsChan) GetAllMeta() PropertyMap { | 302 func (c plsChan) GetAllMeta() PropertyMap { |
303 return PropertyMap{ | 303 return PropertyMap{ |
304 » » "kind": []Property{MkProperty("plsChan")}, | 304 » » "kind": MkProperty("plsChan"), |
305 » » "id": []Property{MkProperty("whyDoIExist")}, | 305 » » "id": MkProperty("whyDoIExist"), |
306 } | 306 } |
307 } | 307 } |
308 | 308 |
309 type MGSWithNoKind struct { | 309 type MGSWithNoKind struct { |
310 S string | 310 S string |
311 } | 311 } |
312 | 312 |
313 func (s *MGSWithNoKind) GetMeta(key string) (interface{}, bool) { | 313 func (s *MGSWithNoKind) GetMeta(key string) (interface{}, bool) { |
314 return nil, false | 314 return nil, false |
315 } | 315 } |
316 | 316 |
317 func (s *MGSWithNoKind) GetAllMeta() PropertyMap { | 317 func (s *MGSWithNoKind) GetAllMeta() PropertyMap { |
318 » return PropertyMap{"$kind": []Property{MkProperty("ohai")}} | 318 » return PropertyMap{"$kind": MkProperty("ohai")} |
319 } | 319 } |
320 | 320 |
321 func (s *MGSWithNoKind) SetMeta(key string, val interface{}) bool { | 321 func (s *MGSWithNoKind) SetMeta(key string, val interface{}) bool { |
322 return false | 322 return false |
323 } | 323 } |
324 | 324 |
325 var _ MetaGetterSetter = (*MGSWithNoKind)(nil) | 325 var _ MetaGetterSetter = (*MGSWithNoKind)(nil) |
326 | 326 |
327 func TestKeyForObj(t *testing.T) { | 327 func TestKeyForObj(t *testing.T) { |
328 t.Parallel() | 328 t.Parallel() |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
661 } | 661 } |
662 So(ds.Put(fplss), ShouldBeNil) | 662 So(ds.Put(fplss), ShouldBeNil) |
663 for i, fpls := range fplss { | 663 for i, fpls := range fplss { |
664 expect := int64(i + 1) | 664 expect := int64(i + 1) |
665 if i == 4 { | 665 if i == 4 { |
666 expect = 200 | 666 expect = 200 |
667 } | 667 } |
668 So(fpls.IntID, ShouldEqual, expe
ct) | 668 So(fpls.IntID, ShouldEqual, expe
ct) |
669 } | 669 } |
670 | 670 |
671 » » » » » pm := PropertyMap{"Value": {MkProperty(0
)}, "$kind": {MkPropertyNI("Pmap")}} | 671 » » » » » pm := PropertyMap{"Value": MkProperty(0)
, "$kind": MkPropertyNI("Pmap")} |
672 So(ds.Put(pm), ShouldBeNil) | 672 So(ds.Put(pm), ShouldBeNil) |
673 So(ds.KeyForObj(pm).IntID(), ShouldEqual
, 1) | 673 So(ds.KeyForObj(pm).IntID(), ShouldEqual
, 1) |
674 }) | 674 }) |
675 | 675 |
676 Convey("[]P (map)", func() { | 676 Convey("[]P (map)", func() { |
677 pms := make([]PropertyMap, 7) | 677 pms := make([]PropertyMap, 7) |
678 for i := range pms { | 678 for i := range pms { |
679 pms[i] = PropertyMap{ | 679 pms[i] = PropertyMap{ |
680 » » » » » » » "$kind": {MkProperty("Pm
ap")}, | 680 » » » » » » » "$kind": MkProperty("Pma
p"), |
681 » » » » » » » "Value": {MkProperty(i)}
, | 681 » » » » » » » "Value": MkProperty(i), |
682 } | 682 } |
683 if i == 4 { | 683 if i == 4 { |
684 So(pms[i].SetMeta("id",
int64(200)), ShouldBeTrue) | 684 So(pms[i].SetMeta("id",
int64(200)), ShouldBeTrue) |
685 } | 685 } |
686 } | 686 } |
687 So(ds.Put(pms), ShouldBeNil) | 687 So(ds.Put(pms), ShouldBeNil) |
688 for i, pm := range pms { | 688 for i, pm := range pms { |
689 expect := int64(i + 1) | 689 expect := int64(i + 1) |
690 if i == 4 { | 690 if i == 4 { |
691 expect = 200 | 691 expect = 200 |
(...skipping 17 matching lines...) Expand all Loading... |
709 expect = 200 | 709 expect = 200 |
710 } | 710 } |
711 So(fpls.IntID, ShouldEqual, expe
ct) | 711 So(fpls.IntID, ShouldEqual, expe
ct) |
712 } | 712 } |
713 }) | 713 }) |
714 | 714 |
715 Convey("[]*P (map)", func() { | 715 Convey("[]*P (map)", func() { |
716 pms := make([]*PropertyMap, 7) | 716 pms := make([]*PropertyMap, 7) |
717 for i := range pms { | 717 for i := range pms { |
718 pms[i] = &PropertyMap{ | 718 pms[i] = &PropertyMap{ |
719 » » » » » » » "$kind": {MkProperty("Pm
ap")}, | 719 » » » » » » » "$kind": MkProperty("Pma
p"), |
720 » » » » » » » "Value": {MkProperty(i)}
, | 720 » » » » » » » "Value": MkProperty(i), |
721 } | 721 } |
722 if i == 4 { | 722 if i == 4 { |
723 So(pms[i].SetMeta("id",
int64(200)), ShouldBeTrue) | 723 So(pms[i].SetMeta("id",
int64(200)), ShouldBeTrue) |
724 } | 724 } |
725 } | 725 } |
726 So(ds.Put(pms), ShouldBeNil) | 726 So(ds.Put(pms), ShouldBeNil) |
727 for i, pm := range pms { | 727 for i, pm := range pms { |
728 expect := int64(i + 1) | 728 expect := int64(i + 1) |
729 if i == 4 { | 729 if i == 4 { |
730 expect = 200 | 730 expect = 200 |
731 } | 731 } |
732 So(ds.KeyForObj(*pm).String(), S
houldEqual, fmt.Sprintf("s~aid:ns:/Pmap,%d", expect)) | 732 So(ds.KeyForObj(*pm).String(), S
houldEqual, fmt.Sprintf("s~aid:ns:/Pmap,%d", expect)) |
733 } | 733 } |
734 }) | 734 }) |
735 | 735 |
736 Convey("[]I", func() { | 736 Convey("[]I", func() { |
737 ifs := []interface{}{ | 737 ifs := []interface{}{ |
738 &CommonStruct{Value: 0}, | 738 &CommonStruct{Value: 0}, |
739 &FakePLS{Value: 1}, | 739 &FakePLS{Value: 1}, |
740 » » » » » » PropertyMap{"Value": {MkProperty
(2)}, "$kind": {MkPropertyNI("Pmap")}}, | 740 » » » » » » PropertyMap{"Value": MkProperty(
2), "$kind": MkPropertyNI("Pmap")}, |
741 » » » » » » &PropertyMap{"Value": {MkPropert
y(3)}, "$kind": {MkPropertyNI("Pmap")}}, | 741 » » » » » » &PropertyMap{"Value": MkProperty
(3), "$kind": MkPropertyNI("Pmap")}, |
742 } | 742 } |
743 So(ds.Put(ifs), ShouldBeNil) | 743 So(ds.Put(ifs), ShouldBeNil) |
744 for i := range ifs { | 744 for i := range ifs { |
745 switch i { | 745 switch i { |
746 case 0: | 746 case 0: |
747 So(ifs[i].(*CommonStruct
).ID, ShouldEqual, 1) | 747 So(ifs[i].(*CommonStruct
).ID, ShouldEqual, 1) |
748 case 1: | 748 case 1: |
749 fpls := ifs[i].(*FakePLS
) | 749 fpls := ifs[i].(*FakePLS
) |
750 So(fpls.IntID, ShouldEqu
al, 2) | 750 So(fpls.IntID, ShouldEqu
al, 2) |
751 case 2: | 751 case 2: |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1017 cs := &CommonStruct{ID: 1} | 1017 cs := &CommonStruct{ID: 1} |
1018 So(ds.Get(cs), ShouldBeNil) | 1018 So(ds.Get(cs), ShouldBeNil) |
1019 So(cs.Value, ShouldEqual, 1) | 1019 So(cs.Value, ShouldEqual, 1) |
1020 }) | 1020 }) |
1021 | 1021 |
1022 Convey("Raw access too", func() { | 1022 Convey("Raw access too", func() { |
1023 rds := ds.Raw() | 1023 rds := ds.Raw() |
1024 keys := []*Key{ds.MakeKey("Kind", 1)} | 1024 keys := []*Key{ds.MakeKey("Kind", 1)} |
1025 So(rds.GetMulti(keys, nil, func(pm Prope
rtyMap, err error) error { | 1025 So(rds.GetMulti(keys, nil, func(pm Prope
rtyMap, err error) error { |
1026 So(err, ShouldBeNil) | 1026 So(err, ShouldBeNil) |
1027 » » » » » » So(pm["Value"][0].Value(), Shoul
dEqual, 1) | 1027 » » » » » » So(pm.Slice("Value")[0].Value(),
ShouldEqual, 1) |
1028 return nil | 1028 return nil |
1029 }), ShouldBeNil) | 1029 }), ShouldBeNil) |
1030 }) | 1030 }) |
1031 | 1031 |
1032 Convey("but general failure to save is fine on a
Get", func() { | 1032 Convey("but general failure to save is fine on a
Get", func() { |
1033 cs := &FakePLS{failSave: true, IntID: 7} | 1033 cs := &FakePLS{failSave: true, IntID: 7} |
1034 So(ds.Get(cs), ShouldBeNil) | 1034 So(ds.Get(cs), ShouldBeNil) |
1035 }) | 1035 }) |
1036 | 1036 |
1037 Convey("vararg", func() { | 1037 Convey("vararg", func() { |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1138 }) | 1138 }) |
1139 | 1139 |
1140 Convey("*[]P (map)", func() { | 1140 Convey("*[]P (map)", func() { |
1141 output := []PropertyMap(nil) | 1141 output := []PropertyMap(nil) |
1142 So(ds.GetAll(q, &output), ShouldBeNil) | 1142 So(ds.GetAll(q, &output), ShouldBeNil) |
1143 So(len(output), ShouldEqual, 5) | 1143 So(len(output), ShouldEqual, 5) |
1144 for i, o := range output { | 1144 for i, o := range output { |
1145 k, ok := o.GetMeta("key") | 1145 k, ok := o.GetMeta("key") |
1146 So(ok, ShouldBeTrue) | 1146 So(ok, ShouldBeTrue) |
1147 So(k.(*Key).IntID(), ShouldEqual, i+1) | 1147 So(k.(*Key).IntID(), ShouldEqual, i+1) |
1148 » » » » » So(o["Value"][0].Value().(int64), Should
Equal, i) | 1148 » » » » » So(o.Slice("Value")[0].Value().(int64),
ShouldEqual, i) |
1149 } | 1149 } |
1150 }) | 1150 }) |
1151 | 1151 |
1152 Convey("*[]P (chan)", func() { | 1152 Convey("*[]P (chan)", func() { |
1153 output := []plsChan(nil) | 1153 output := []plsChan(nil) |
1154 So(ds.GetAll(q, &output), ShouldBeNil) | 1154 So(ds.GetAll(q, &output), ShouldBeNil) |
1155 So(output, ShouldHaveLength, 5) | 1155 So(output, ShouldHaveLength, 5) |
1156 for _, o := range output { | 1156 for _, o := range output { |
1157 So(ds.KeyForObj(o).StringID(), ShouldEqu
al, "whyDoIExist") | 1157 So(ds.KeyForObj(o).StringID(), ShouldEqu
al, "whyDoIExist") |
1158 } | 1158 } |
(...skipping 12 matching lines...) Expand all Loading... |
1171 | 1171 |
1172 Convey("*[]*P (map)", func() { | 1172 Convey("*[]*P (map)", func() { |
1173 output := []*PropertyMap(nil) | 1173 output := []*PropertyMap(nil) |
1174 So(ds.GetAll(q, &output), ShouldBeNil) | 1174 So(ds.GetAll(q, &output), ShouldBeNil) |
1175 So(len(output), ShouldEqual, 5) | 1175 So(len(output), ShouldEqual, 5) |
1176 for i, op := range output { | 1176 for i, op := range output { |
1177 o := *op | 1177 o := *op |
1178 k, ok := o.GetMeta("key") | 1178 k, ok := o.GetMeta("key") |
1179 So(ok, ShouldBeTrue) | 1179 So(ok, ShouldBeTrue) |
1180 So(k.(*Key).IntID(), ShouldEqual, i+1) | 1180 So(k.(*Key).IntID(), ShouldEqual, i+1) |
1181 » » » » » So(o["Value"][0].Value().(int64), Should
Equal, i) | 1181 » » » » » So(o.Slice("Value")[0].Value().(int64),
ShouldEqual, i) |
1182 } | 1182 } |
1183 }) | 1183 }) |
1184 | 1184 |
1185 Convey("*[]*P (chan)", func() { | 1185 Convey("*[]*P (chan)", func() { |
1186 output := []*plsChan(nil) | 1186 output := []*plsChan(nil) |
1187 So(ds.GetAll(q, &output), ShouldBeNil) | 1187 So(ds.GetAll(q, &output), ShouldBeNil) |
1188 So(output, ShouldHaveLength, 5) | 1188 So(output, ShouldHaveLength, 5) |
1189 for _, o := range output { | 1189 for _, o := range output { |
1190 So(ds.KeyForObj(o).StringID(), ShouldEqu
al, "whyDoIExist") | 1190 So(ds.KeyForObj(o).StringID(), ShouldEqu
al, "whyDoIExist") |
1191 } | 1191 } |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1331 i++ | 1331 i++ |
1332 }), ShouldBeNil) | 1332 }), ShouldBeNil) |
1333 }) | 1333 }) |
1334 | 1334 |
1335 Convey("*P (map)", func() { | 1335 Convey("*P (map)", func() { |
1336 i := 0 | 1336 i := 0 |
1337 So(ds.Run(q, func(pm *PropertyMap) { | 1337 So(ds.Run(q, func(pm *PropertyMap) { |
1338 k, ok := pm.GetMeta("key") | 1338 k, ok := pm.GetMeta("key") |
1339 So(ok, ShouldBeTrue) | 1339 So(ok, ShouldBeTrue) |
1340 So(k.(*Key).IntID(), ShouldEqual, i+1) | 1340 So(k.(*Key).IntID(), ShouldEqual, i+1) |
1341 » » » » » So((*pm)["Value"][0].Value(), ShouldEqua
l, i) | 1341 » » » » » So((*pm).Slice("Value")[0].Value(), Shou
ldEqual, i) |
1342 i++ | 1342 i++ |
1343 }), ShouldBeNil) | 1343 }), ShouldBeNil) |
1344 }) | 1344 }) |
1345 | 1345 |
1346 Convey("*P (chan)", func() { | 1346 Convey("*P (chan)", func() { |
1347 So(ds.Run(q, func(c *plsChan) { | 1347 So(ds.Run(q, func(c *plsChan) { |
1348 So(ds.KeyForObj(c).StringID(), ShouldEqu
al, "whyDoIExist") | 1348 So(ds.KeyForObj(c).StringID(), ShouldEqu
al, "whyDoIExist") |
1349 }), ShouldBeNil) | 1349 }), ShouldBeNil) |
1350 }) | 1350 }) |
1351 | 1351 |
(...skipping 15 matching lines...) Expand all Loading... |
1367 i++ | 1367 i++ |
1368 }), ShouldBeNil) | 1368 }), ShouldBeNil) |
1369 }) | 1369 }) |
1370 | 1370 |
1371 Convey("P (map)", func() { | 1371 Convey("P (map)", func() { |
1372 i := 0 | 1372 i := 0 |
1373 So(ds.Run(q, func(pm PropertyMap) { | 1373 So(ds.Run(q, func(pm PropertyMap) { |
1374 k, ok := pm.GetMeta("key") | 1374 k, ok := pm.GetMeta("key") |
1375 So(ok, ShouldBeTrue) | 1375 So(ok, ShouldBeTrue) |
1376 So(k.(*Key).IntID(), ShouldEqual, i+1) | 1376 So(k.(*Key).IntID(), ShouldEqual, i+1) |
1377 » » » » » So(pm["Value"][0].Value(), ShouldEqual,
i) | 1377 » » » » » So(pm.Slice("Value")[0].Value(), ShouldE
qual, i) |
1378 i++ | 1378 i++ |
1379 }), ShouldBeNil) | 1379 }), ShouldBeNil) |
1380 }) | 1380 }) |
1381 | 1381 |
1382 Convey("P (chan)", func() { | 1382 Convey("P (chan)", func() { |
1383 So(ds.Run(q, func(c plsChan) { | 1383 So(ds.Run(q, func(c plsChan) { |
1384 So(ds.KeyForObj(c).StringID(), ShouldEqu
al, "whyDoIExist") | 1384 So(ds.KeyForObj(c).StringID(), ShouldEqu
al, "whyDoIExist") |
1385 }), ShouldBeNil) | 1385 }), ShouldBeNil) |
1386 }) | 1386 }) |
1387 | 1387 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1431 | 1431 |
1432 func TestSchemaChange(t *testing.T) { | 1432 func TestSchemaChange(t *testing.T) { |
1433 t.Parallel() | 1433 t.Parallel() |
1434 | 1434 |
1435 Convey("Test changing schemas", t, func() { | 1435 Convey("Test changing schemas", t, func() { |
1436 fds := fixedDataDatastore{} | 1436 fds := fixedDataDatastore{} |
1437 ds := &datastoreImpl{&fds, "", ""} | 1437 ds := &datastoreImpl{&fds, "", ""} |
1438 | 1438 |
1439 Convey("Can add fields", func() { | 1439 Convey("Can add fields", func() { |
1440 initial := PropertyMap{ | 1440 initial := PropertyMap{ |
1441 » » » » "$key": {mpNI(ds.MakeKey("Val", 10))}, | 1441 » » » » "$key": mpNI(ds.MakeKey("Val", 10)), |
1442 » » » » "Val": {mp(100)}, | 1442 » » » » "Val": mp(100), |
1443 } | 1443 } |
1444 So(ds.Put(initial), ShouldBeNil) | 1444 So(ds.Put(initial), ShouldBeNil) |
1445 | 1445 |
1446 type Val struct { | 1446 type Val struct { |
1447 ID int64 `gae:"$id"` | 1447 ID int64 `gae:"$id"` |
1448 | 1448 |
1449 Val int64 | 1449 Val int64 |
1450 TwoVal int64 // whoa, TWO vals! amazing | 1450 TwoVal int64 // whoa, TWO vals! amazing |
1451 } | 1451 } |
1452 tv := &Val{ID: 10, TwoVal: 2} | 1452 tv := &Val{ID: 10, TwoVal: 2} |
1453 So(ds.Get(tv), ShouldBeNil) | 1453 So(ds.Get(tv), ShouldBeNil) |
1454 So(tv, ShouldResemble, &Val{ID: 10, Val: 100, TwoVal: 2}
) | 1454 So(tv, ShouldResemble, &Val{ID: 10, Val: 100, TwoVal: 2}
) |
1455 }) | 1455 }) |
1456 | 1456 |
1457 Convey("Removing fields", func() { | 1457 Convey("Removing fields", func() { |
1458 initial := PropertyMap{ | 1458 initial := PropertyMap{ |
1459 » » » » "$key": {mpNI(ds.MakeKey("Val", 10))}, | 1459 » » » » "$key": mpNI(ds.MakeKey("Val", 10)), |
1460 » » » » "Val": {mp(100)}, | 1460 » » » » "Val": mp(100), |
1461 » » » » "TwoVal": {mp(200)}, | 1461 » » » » "TwoVal": mp(200), |
1462 } | 1462 } |
1463 So(ds.Put(initial), ShouldBeNil) | 1463 So(ds.Put(initial), ShouldBeNil) |
1464 | 1464 |
1465 Convey("is normally an error", func() { | 1465 Convey("is normally an error", func() { |
1466 type Val struct { | 1466 type Val struct { |
1467 ID int64 `gae:"$id"` | 1467 ID int64 `gae:"$id"` |
1468 | 1468 |
1469 Val int64 | 1469 Val int64 |
1470 } | 1470 } |
1471 tv := &Val{ID: 10} | 1471 tv := &Val{ID: 10} |
1472 So(ds.Get(tv), ShouldErrLike, | 1472 So(ds.Get(tv), ShouldErrLike, |
1473 `gae: cannot load field "TwoVal" into a
"datastore.Val`) | 1473 `gae: cannot load field "TwoVal" into a
"datastore.Val`) |
1474 So(tv, ShouldResemble, &Val{ID: 10, Val: 100}) | 1474 So(tv, ShouldResemble, &Val{ID: 10, Val: 100}) |
1475 }) | 1475 }) |
1476 | 1476 |
1477 Convey("Unless you have an ,extra field!", func() { | 1477 Convey("Unless you have an ,extra field!", func() { |
1478 type Val struct { | 1478 type Val struct { |
1479 ID int64 `gae:"$id"` | 1479 ID int64 `gae:"$id"` |
1480 | 1480 |
1481 Val int64 | 1481 Val int64 |
1482 Extra PropertyMap `gae:",extra"` | 1482 Extra PropertyMap `gae:",extra"` |
1483 } | 1483 } |
1484 tv := &Val{ID: 10} | 1484 tv := &Val{ID: 10} |
1485 So(ds.Get(tv), ShouldBeNil) | 1485 So(ds.Get(tv), ShouldBeNil) |
1486 So(tv, ShouldResemble, &Val{ | 1486 So(tv, ShouldResemble, &Val{ |
1487 ID: 10, | 1487 ID: 10, |
1488 Val: 100, | 1488 Val: 100, |
1489 Extra: PropertyMap{ | 1489 Extra: PropertyMap{ |
1490 » » » » » » "TwoVal": {mp(200)}, | 1490 » » » » » » "TwoVal": PropertySlice{mp(200)}
, |
1491 }, | 1491 }, |
1492 }) | 1492 }) |
1493 }) | 1493 }) |
1494 }) | 1494 }) |
1495 | 1495 |
1496 Convey("Can round-trip extra fields", func() { | 1496 Convey("Can round-trip extra fields", func() { |
1497 type Expando struct { | 1497 type Expando struct { |
1498 ID int64 `gae:"$id"` | 1498 ID int64 `gae:"$id"` |
1499 | 1499 |
1500 Something int | 1500 Something int |
1501 Extra PropertyMap `gae:",extra"` | 1501 Extra PropertyMap `gae:",extra"` |
1502 } | 1502 } |
1503 ex := &Expando{10, 17, PropertyMap{ | 1503 ex := &Expando{10, 17, PropertyMap{ |
1504 » » » » "Hello": {mp("Hello")}, | 1504 » » » » "Hello": mp("Hello"), |
1505 » » » » "World": {mp(true)}, | 1505 » » » » "World": mp(true), |
1506 }} | 1506 }} |
1507 So(ds.Put(ex), ShouldBeNil) | 1507 So(ds.Put(ex), ShouldBeNil) |
1508 | 1508 |
1509 ex = &Expando{ID: 10} | 1509 ex = &Expando{ID: 10} |
1510 So(ds.Get(ex), ShouldBeNil) | 1510 So(ds.Get(ex), ShouldBeNil) |
1511 So(ex, ShouldResemble, &Expando{ | 1511 So(ex, ShouldResemble, &Expando{ |
1512 ID: 10, | 1512 ID: 10, |
1513 Something: 17, | 1513 Something: 17, |
1514 Extra: PropertyMap{ | 1514 Extra: PropertyMap{ |
1515 » » » » » "Hello": {mp("Hello")}, | 1515 » » » » » "Hello": PropertySlice{mp("Hello")}, |
1516 » » » » » "World": {mp(true)}, | 1516 » » » » » "World": PropertySlice{mp(true)}, |
1517 }, | 1517 }, |
1518 }) | 1518 }) |
1519 }) | 1519 }) |
1520 | 1520 |
1521 Convey("Can read-but-not-write", func() { | 1521 Convey("Can read-but-not-write", func() { |
1522 initial := PropertyMap{ | 1522 initial := PropertyMap{ |
1523 » » » » "$key": {mpNI(ds.MakeKey("Convert", 10))}, | 1523 » » » » "$key": mpNI(ds.MakeKey("Convert", 10)), |
1524 » » » » "Val": {mp(100)}, | 1524 » » » » "Val": mp(100), |
1525 » » » » "TwoVal": {mp(200)}, | 1525 » » » » "TwoVal": mp(200), |
1526 } | 1526 } |
1527 So(ds.Put(initial), ShouldBeNil) | 1527 So(ds.Put(initial), ShouldBeNil) |
1528 type Convert struct { | 1528 type Convert struct { |
1529 ID int64 `gae:"$id"` | 1529 ID int64 `gae:"$id"` |
1530 | 1530 |
1531 Val int64 | 1531 Val int64 |
1532 NewVal int64 | 1532 NewVal int64 |
1533 Extra PropertyMap `gae:"-,extra"` | 1533 Extra PropertyMap `gae:"-,extra"` |
1534 } | 1534 } |
1535 c := &Convert{ID: 10} | 1535 c := &Convert{ID: 10} |
1536 So(ds.Get(c), ShouldBeNil) | 1536 So(ds.Get(c), ShouldBeNil) |
1537 So(c, ShouldResemble, &Convert{ | 1537 So(c, ShouldResemble, &Convert{ |
1538 » » » » ID: 10, Val: 100, NewVal: 0, Extra: PropertyMap{
"TwoVal": {mp(200)}}, | 1538 » » » » ID: 10, Val: 100, NewVal: 0, Extra: PropertyMap{
"TwoVal": PropertySlice{mp(200)}}, |
1539 }) | 1539 }) |
1540 » » » c.NewVal = c.Extra["TwoVal"][0].Value().(int64) | 1540 » » » c.NewVal = c.Extra.Slice("TwoVal")[0].Value().(int64) |
1541 So(ds.Put(c), ShouldBeNil) | 1541 So(ds.Put(c), ShouldBeNil) |
1542 | 1542 |
1543 c = &Convert{ID: 10} | 1543 c = &Convert{ID: 10} |
1544 So(ds.Get(c), ShouldBeNil) | 1544 So(ds.Get(c), ShouldBeNil) |
1545 So(c, ShouldResemble, &Convert{ | 1545 So(c, ShouldResemble, &Convert{ |
1546 ID: 10, Val: 100, NewVal: 200, Extra: nil, | 1546 ID: 10, Val: 100, NewVal: 200, Extra: nil, |
1547 }) | 1547 }) |
1548 }) | 1548 }) |
1549 | 1549 |
1550 Convey("Can black hole", func() { | 1550 Convey("Can black hole", func() { |
1551 initial := PropertyMap{ | 1551 initial := PropertyMap{ |
1552 » » » » "$key": {mpNI(ds.MakeKey("BlackHole", 10))}, | 1552 » » » » "$key": mpNI(ds.MakeKey("BlackHole", 10)), |
1553 » » » » "Val": {mp(100)}, | 1553 » » » » "Val": mp(100), |
1554 » » » » "TwoVal": {mp(200)}, | 1554 » » » » "TwoVal": mp(200), |
1555 } | 1555 } |
1556 So(ds.Put(initial), ShouldBeNil) | 1556 So(ds.Put(initial), ShouldBeNil) |
1557 type BlackHole struct { | 1557 type BlackHole struct { |
1558 ID int64 `gae:"$id"` | 1558 ID int64 `gae:"$id"` |
1559 | 1559 |
1560 NewStuff string | 1560 NewStuff string |
1561 blackHole PropertyMap `gae:"-,extra"` | 1561 blackHole PropertyMap `gae:"-,extra"` |
1562 } | 1562 } |
1563 b := &BlackHole{ID: 10, NewStuff: "(╯°□°)╯︵ ┻━┻"} | 1563 b := &BlackHole{ID: 10, NewStuff: "(╯°□°)╯︵ ┻━┻"} |
1564 So(ds.Get(b), ShouldBeNil) | 1564 So(ds.Get(b), ShouldBeNil) |
1565 So(b, ShouldResemble, &BlackHole{ID: 10, NewStuff: "(╯°□
°)╯︵ ┻━┻"}) | 1565 So(b, ShouldResemble, &BlackHole{ID: 10, NewStuff: "(╯°□
°)╯︵ ┻━┻"}) |
1566 }) | 1566 }) |
1567 | 1567 |
1568 Convey("Can change field types", func() { | 1568 Convey("Can change field types", func() { |
1569 initial := PropertyMap{ | 1569 initial := PropertyMap{ |
1570 » » » » "$key": {mpNI(ds.MakeKey("IntChange", 10))}, | 1570 » » » » "$key": mpNI(ds.MakeKey("IntChange", 10)), |
1571 » » » » "Val": {mp(100)}, | 1571 » » » » "Val": mp(100), |
1572 } | 1572 } |
1573 So(ds.Put(initial), ShouldBeNil) | 1573 So(ds.Put(initial), ShouldBeNil) |
1574 | 1574 |
1575 type IntChange struct { | 1575 type IntChange struct { |
1576 ID int64 `gae:"$id"` | 1576 ID int64 `gae:"$id"` |
1577 Val string | 1577 Val string |
1578 Extra PropertyMap `gae:"-,extra"` | 1578 Extra PropertyMap `gae:"-,extra"` |
1579 } | 1579 } |
1580 i := &IntChange{ID: 10} | 1580 i := &IntChange{ID: 10} |
1581 So(ds.Get(i), ShouldBeNil) | 1581 So(ds.Get(i), ShouldBeNil) |
1582 » » » So(i, ShouldResemble, &IntChange{ID: 10, Extra: Property
Map{"Val": {mp(100)}}}) | 1582 » » » So(i, ShouldResemble, &IntChange{ID: 10, Extra: Property
Map{"Val": PropertySlice{mp(100)}}}) |
1583 » » » i.Val = fmt.Sprint(i.Extra["Val"][0].Value()) | 1583 » » » i.Val = fmt.Sprint(i.Extra.Slice("Val")[0].Value()) |
1584 So(ds.Put(i), ShouldBeNil) | 1584 So(ds.Put(i), ShouldBeNil) |
1585 | 1585 |
1586 i = &IntChange{ID: 10} | 1586 i = &IntChange{ID: 10} |
1587 So(ds.Get(i), ShouldBeNil) | 1587 So(ds.Get(i), ShouldBeNil) |
1588 So(i, ShouldResemble, &IntChange{ID: 10, Val: "100"}) | 1588 So(i, ShouldResemble, &IntChange{ID: 10, Val: "100"}) |
1589 }) | 1589 }) |
1590 | 1590 |
1591 Convey("Native fields have priority over Extra fields", func() { | 1591 Convey("Native fields have priority over Extra fields", func() { |
1592 type Dup struct { | 1592 type Dup struct { |
1593 ID int64 `gae:"$id"` | 1593 ID int64 `gae:"$id"` |
1594 Val int64 | 1594 Val int64 |
1595 Extra PropertyMap `gae:",extra"` | 1595 Extra PropertyMap `gae:",extra"` |
1596 } | 1596 } |
1597 d := &Dup{ID: 10, Val: 100, Extra: PropertyMap{ | 1597 d := &Dup{ID: 10, Val: 100, Extra: PropertyMap{ |
1598 » » » » "Val": {mp(200)}, | 1598 » » » » "Val": PropertySlice{mp(200)}, |
1599 » » » » "Other": {mp("other")}, | 1599 » » » » "Other": PropertySlice{mp("other")}, |
1600 }} | 1600 }} |
1601 So(ds.Put(d), ShouldBeNil) | 1601 So(ds.Put(d), ShouldBeNil) |
1602 | 1602 |
1603 d = &Dup{ID: 10} | 1603 d = &Dup{ID: 10} |
1604 So(ds.Get(d), ShouldBeNil) | 1604 So(ds.Get(d), ShouldBeNil) |
1605 So(d, ShouldResemble, &Dup{ | 1605 So(d, ShouldResemble, &Dup{ |
1606 » » » » ID: 10, Val: 100, Extra: PropertyMap{"Other": {m
p("other")}}, | 1606 » » » » ID: 10, Val: 100, Extra: PropertyMap{"Other": Pr
opertySlice{mp("other")}}, |
1607 }) | 1607 }) |
1608 }) | 1608 }) |
1609 | 1609 |
1610 Convey("Can change repeated field to non-repeating field", func(
) { | 1610 Convey("Can change repeated field to non-repeating field", func(
) { |
1611 initial := PropertyMap{ | 1611 initial := PropertyMap{ |
1612 » » » » "$key": {mpNI(ds.MakeKey("NonRepeating", 10))}, | 1612 » » » » "$key": mpNI(ds.MakeKey("NonRepeating", 10)), |
1613 » » » » "Val": {mp(100), mp(200), mp(400)}, | 1613 » » » » "Val": PropertySlice{mp(100), mp(200), mp(400)}
, |
1614 } | 1614 } |
1615 So(ds.Put(initial), ShouldBeNil) | 1615 So(ds.Put(initial), ShouldBeNil) |
1616 | 1616 |
1617 type NonRepeating struct { | 1617 type NonRepeating struct { |
1618 ID int64 `gae:"$id"` | 1618 ID int64 `gae:"$id"` |
1619 Val int64 | 1619 Val int64 |
1620 Extra PropertyMap `gae:",extra"` | 1620 Extra PropertyMap `gae:",extra"` |
1621 } | 1621 } |
1622 n := &NonRepeating{ID: 10} | 1622 n := &NonRepeating{ID: 10} |
1623 So(ds.Get(n), ShouldBeNil) | 1623 So(ds.Get(n), ShouldBeNil) |
1624 So(n, ShouldResemble, &NonRepeating{ | 1624 So(n, ShouldResemble, &NonRepeating{ |
1625 ID: 10, Val: 0, Extra: PropertyMap{ | 1625 ID: 10, Val: 0, Extra: PropertyMap{ |
1626 » » » » » "Val": {mp(100), mp(200), mp(400)}, | 1626 » » » » » "Val": PropertySlice{mp(100), mp(200), m
p(400)}, |
1627 }, | 1627 }, |
1628 }) | 1628 }) |
1629 }) | 1629 }) |
1630 | 1630 |
1631 Convey("Deals correctly with recursive types", func() { | 1631 Convey("Deals correctly with recursive types", func() { |
1632 initial := PropertyMap{ | 1632 initial := PropertyMap{ |
1633 » » » » "$key": {mpNI(ds.MakeKey("Outer", 10))}, | 1633 » » » » "$key": mpNI(ds.MakeKey("Outer", 10)), |
1634 » » » » "I.A": {mp(1), mp(2), mp(4)}, | 1634 » » » » "I.A": PropertySlice{mp(1), mp(2), mp(4)}, |
1635 » » » » "I.B": {mp(10), mp(20), mp(40)}, | 1635 » » » » "I.B": PropertySlice{mp(10), mp(20), mp(40)}, |
1636 » » » » "I.C": {mp(100), mp(200), mp(400)}, | 1636 » » » » "I.C": PropertySlice{mp(100), mp(200), mp(400)}
, |
1637 } | 1637 } |
1638 So(ds.Put(initial), ShouldBeNil) | 1638 So(ds.Put(initial), ShouldBeNil) |
1639 type Inner struct { | 1639 type Inner struct { |
1640 A int64 | 1640 A int64 |
1641 B int64 | 1641 B int64 |
1642 } | 1642 } |
1643 type Outer struct { | 1643 type Outer struct { |
1644 ID int64 `gae:"$id"` | 1644 ID int64 `gae:"$id"` |
1645 | 1645 |
1646 I []Inner | 1646 I []Inner |
1647 Extra PropertyMap `gae:",extra"` | 1647 Extra PropertyMap `gae:",extra"` |
1648 } | 1648 } |
1649 o := &Outer{ID: 10} | 1649 o := &Outer{ID: 10} |
1650 So(ds.Get(o), ShouldBeNil) | 1650 So(ds.Get(o), ShouldBeNil) |
1651 So(o, ShouldResemble, &Outer{ | 1651 So(o, ShouldResemble, &Outer{ |
1652 ID: 10, | 1652 ID: 10, |
1653 I: []Inner{ | 1653 I: []Inner{ |
1654 {1, 10}, | 1654 {1, 10}, |
1655 {2, 20}, | 1655 {2, 20}, |
1656 {4, 40}, | 1656 {4, 40}, |
1657 }, | 1657 }, |
1658 Extra: PropertyMap{ | 1658 Extra: PropertyMap{ |
1659 » » » » » "I.C": {mp(100), mp(200), mp(400)}, | 1659 » » » » » "I.C": PropertySlice{mp(100), mp(200), m
p(400)}, |
1660 }, | 1660 }, |
1661 }) | 1661 }) |
1662 }) | 1662 }) |
1663 | 1663 |
1664 Convey("Problems", func() { | 1664 Convey("Problems", func() { |
1665 Convey("multiple extra fields", func() { | 1665 Convey("multiple extra fields", func() { |
1666 type Bad struct { | 1666 type Bad struct { |
1667 A PropertyMap `gae:",extra"` | 1667 A PropertyMap `gae:",extra"` |
1668 B PropertyMap `gae:",extra"` | 1668 B PropertyMap `gae:",extra"` |
1669 } | 1669 } |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1914 if err != nil { | 1914 if err != nil { |
1915 panic(fmt.Errorf("failed to find absolute path f
or `%s`", sameLevelDir)) | 1915 panic(fmt.Errorf("failed to find absolute path f
or `%s`", sameLevelDir)) |
1916 } | 1916 } |
1917 | 1917 |
1918 ids, err := FindAndParseIndexYAML(abs) | 1918 ids, err := FindAndParseIndexYAML(abs) |
1919 So(err, ShouldBeNil) | 1919 So(err, ShouldBeNil) |
1920 So(ids[1].Kind, ShouldEqual, "Test Foo") | 1920 So(ids[1].Kind, ShouldEqual, "Test Foo") |
1921 }) | 1921 }) |
1922 }) | 1922 }) |
1923 } | 1923 } |
OLD | NEW |