Index: service/datastore/datastore_test.go |
diff --git a/service/datastore/datastore_test.go b/service/datastore/datastore_test.go |
index a8fb836b35cb7b94bf11833fc9a27057620ab6b3..c24efb33e37609becdc1900da71888e4b47bfffd 100644 |
--- a/service/datastore/datastore_test.go |
+++ b/service/datastore/datastore_test.go |
@@ -61,10 +61,7 @@ func (f *fakeDatastore) PutMulti(keys []*Key, vals []PropertyMap, cb PutMultiCB) |
if keys[0].Kind() == "FailAll" { |
return errors.New("PutMulti fail all") |
} |
- assertExtra := false |
- if _, err := vals[0].GetMeta("assertExtra"); err == nil { |
- assertExtra = true |
- } |
+ _, assertExtra := vals[0].GetMeta("assertExtra") |
for i, k := range keys { |
err := error(nil) |
if k.Kind() == "Fail" { |
@@ -169,54 +166,50 @@ func (f *FakePLS) Save(withMeta bool) (PropertyMap, error) { |
} |
if withMeta { |
id, _ := f.GetMeta("id") |
- So(ret.SetMeta("id", id), ShouldBeNil) |
+ So(ret.SetMeta("id", id), ShouldBeTrue) |
if f.Kind == "" { |
- So(ret.SetMeta("kind", "FakePLS"), ShouldBeNil) |
+ So(ret.SetMeta("kind", "FakePLS"), ShouldBeTrue) |
} else { |
- So(ret.SetMeta("kind", f.Kind), ShouldBeNil) |
+ So(ret.SetMeta("kind", f.Kind), ShouldBeTrue) |
} |
- So(ret.SetMeta("assertExtra", true), ShouldBeNil) |
+ So(ret.SetMeta("assertExtra", true), ShouldBeTrue) |
} |
return ret, nil |
} |
-func (f *FakePLS) GetMetaDefault(key string, dflt interface{}) interface{} { |
- return GetMetaDefaultImpl(f.GetMeta, key, dflt) |
-} |
- |
-func (f *FakePLS) GetMeta(key string) (interface{}, error) { |
+func (f *FakePLS) GetMeta(key string) (interface{}, bool) { |
if f.failGetMeta { |
- return nil, errors.New("FakePLS.GetMeta") |
+ return nil, false |
} |
switch key { |
case "id": |
if f.StringID != "" { |
- return f.StringID, nil |
+ return f.StringID, true |
} |
- return f.IntID, nil |
+ return f.IntID, true |
case "kind": |
if f.Kind == "" { |
- return "FakePLS", nil |
+ return "FakePLS", true |
} |
- return f.Kind, nil |
+ return f.Kind, true |
} |
- return nil, ErrMetaFieldUnset |
+ return nil, false |
} |
func (f *FakePLS) GetAllMeta() PropertyMap { |
ret := PropertyMap{} |
- if id, err := f.GetMeta("id"); err != nil { |
- So(ret.SetMeta("id", id), ShouldBeNil) |
+ if id, ok := f.GetMeta("id"); !ok { |
+ ret.SetMeta("id", id) |
} |
- if kind, err := f.GetMeta("kind"); err != nil { |
- So(ret.SetMeta("kind", kind), ShouldBeNil) |
+ if kind, ok := f.GetMeta("kind"); !ok { |
+ ret.SetMeta("kind", kind) |
} |
return ret |
} |
-func (f *FakePLS) SetMeta(key string, val interface{}) error { |
+func (f *FakePLS) SetMeta(key string, val interface{}) bool { |
if f.failSetMeta { |
- return errors.New("FakePL.SetMeta") |
+ return false |
} |
if key == "id" { |
switch x := val.(type) { |
@@ -225,13 +218,13 @@ func (f *FakePLS) SetMeta(key string, val interface{}) error { |
case string: |
f.StringID = x |
} |
- return nil |
+ return true |
} |
if key == "kind" { |
f.Kind = val.(string) |
- return nil |
+ return true |
} |
- return ErrMetaFieldUnset |
+ return false |
} |
func (f *FakePLS) Problem() error { |
@@ -245,20 +238,16 @@ type MGSWithNoKind struct { |
S string |
} |
-func (s *MGSWithNoKind) GetMetaDefault(key string, dflt interface{}) interface{} { |
- return GetMetaDefaultImpl(s.GetMeta, key, dflt) |
-} |
- |
-func (s *MGSWithNoKind) GetMeta(key string) (interface{}, error) { |
- return nil, ErrMetaFieldUnset |
+func (s *MGSWithNoKind) GetMeta(key string) (interface{}, bool) { |
+ return nil, false |
} |
func (s *MGSWithNoKind) GetAllMeta() PropertyMap { |
return PropertyMap{} |
} |
-func (s *MGSWithNoKind) SetMeta(key string, val interface{}) error { |
- return ErrMetaFieldUnset |
+func (s *MGSWithNoKind) SetMeta(key string, val interface{}) bool { |
+ return false |
} |
var _ MetaGetterSetter = (*MGSWithNoKind)(nil) |
@@ -300,17 +289,17 @@ func TestKeyForObj(t *testing.T) { |
Convey("a propmap with $key", func() { |
pm := PropertyMap{} |
- So(pm.SetMeta("key", k), ShouldBeNil) |
+ So(pm.SetMeta("key", k), ShouldBeTrue) |
So(ds.KeyForObj(pm).String(), ShouldEqual, `s~aid:ns:/Hello,"world"`) |
}) |
Convey("a propmap with $id, $kind, $parent", func() { |
pm := PropertyMap{} |
- So(pm.SetMeta("id", 100), ShouldBeNil) |
- So(pm.SetMeta("kind", "Sup"), ShouldBeNil) |
+ So(pm.SetMeta("id", 100), ShouldBeTrue) |
+ So(pm.SetMeta("kind", "Sup"), ShouldBeTrue) |
So(ds.KeyForObj(pm).String(), ShouldEqual, `s~aid:ns:/Sup,100`) |
- So(pm.SetMeta("parent", k), ShouldBeNil) |
+ So(pm.SetMeta("parent", k), ShouldBeTrue) |
So(ds.KeyForObj(pm).String(), ShouldEqual, `s~aid:ns:/Hello,"world"/Sup,100`) |
}) |
@@ -318,7 +307,7 @@ func TestKeyForObj(t *testing.T) { |
pls := GetPLS(&CommonStruct{ID: 1}) |
So(ds.KeyForObj(pls).String(), ShouldEqual, `s~aid:ns:/CommonStruct,1`) |
- So(pls.SetMeta("parent", k), ShouldBeNil) |
+ So(pls.SetMeta("parent", k), ShouldBeTrue) |
So(ds.KeyForObj(pls).String(), ShouldEqual, `s~aid:ns:/Hello,"world"/CommonStruct,1`) |
}) |
@@ -340,9 +329,20 @@ func TestKeyForObj(t *testing.T) { |
Convey("bad", func() { |
Convey("a propmap without $kind", func() { |
pm := PropertyMap{} |
- So(pm.SetMeta("id", 100), ShouldBeNil) |
+ So(pm.SetMeta("id", 100), ShouldBeTrue) |
So(func() { ds.KeyForObj(pm) }, ShouldPanic) |
}) |
+ |
+ Convey("a bad object", func() { |
+ type BadObj struct { |
+ ID int64 `gae:"$id"` |
+ |
+ NonSerializableField complex64 |
+ } |
+ |
+ So(func() { ds.KeyForObjErr(&BadObj{ID: 1}) }, ShouldPanicLike, |
+ `field "NonSerializableField" has invalid type: complex64`) |
+ }) |
}) |
}) |
} |
@@ -358,35 +358,39 @@ func TestPut(t *testing.T) { |
Convey("bad", func() { |
Convey("static can't serialize", func() { |
bss := []badStruct{{}, {}} |
- So(ds.PutMulti(bss).Error(), ShouldContainSubstring, "invalid PutMulti input") |
+ So(func() { ds.PutMulti(bss) }, ShouldPanicLike, |
+ `field "Compy" has invalid type`) |
}) |
Convey("static ptr can't serialize", func() { |
bss := []*badStruct{{}, {}} |
- So(ds.PutMulti(bss).Error(), ShouldContainSubstring, "invalid PutMulti input") |
+ So(func() { ds.PutMulti(bss) }, ShouldPanicLike, |
+ `field "Compy" has invalid type: complex64`) |
}) |
Convey("static bad type (non-slice)", func() { |
- So(ds.PutMulti(100).Error(), ShouldContainSubstring, "invalid PutMulti input") |
+ So(func() { ds.PutMulti(100) }, ShouldPanicLike, |
+ "invalid argument type: expected slice, got int") |
}) |
Convey("static bad type (slice of bad type)", func() { |
- So(ds.PutMulti([]int{}).Error(), ShouldContainSubstring, "invalid PutMulti input") |
+ So(func() { ds.PutMulti([]int{}) }, ShouldPanicLike, |
+ "invalid argument type: []int") |
}) |
Convey("dynamic can't serialize", func() { |
fplss := []FakePLS{{failSave: true}, {}} |
- So(ds.PutMulti(fplss).Error(), ShouldContainSubstring, "FakePLS.Save") |
+ So(ds.PutMulti(fplss), ShouldErrLike, "FakePLS.Save") |
}) |
Convey("can't get keys", func() { |
fplss := []FakePLS{{failGetMeta: true}, {}} |
- So(ds.PutMulti(fplss).Error(), ShouldContainSubstring, "unable to extract $kind") |
+ So(ds.PutMulti(fplss), ShouldErrLike, "unable to extract $kind") |
}) |
Convey("get single error for RPC failure", func() { |
fplss := []FakePLS{{Kind: "FailAll"}, {}} |
- So(ds.PutMulti(fplss).Error(), ShouldEqual, "PutMulti fail all") |
+ So(ds.PutMulti(fplss), ShouldErrLike, "PutMulti fail all") |
}) |
Convey("get multi error for individual failures", func() { |
@@ -396,12 +400,12 @@ func TestPut(t *testing.T) { |
Convey("put with non-modifyable type is an error", func() { |
cs := CommonStruct{} |
- So(ds.Put(cs).Error(), ShouldContainSubstring, "invalid Put input type") |
+ So(ds.Put(cs), ShouldErrLike, "invalid Put input type") |
}) |
Convey("struct with no $kind is an error", func() { |
s := MGSWithNoKind{} |
- So(ds.Put(&s).Error(), ShouldContainSubstring, "unable to extract $kind") |
+ So(ds.Put(&s), ShouldErrLike, "unable to extract $kind") |
}) |
}) |
@@ -476,7 +480,7 @@ func TestPut(t *testing.T) { |
"Value": {MkProperty(i)}, |
} |
if i == 4 { |
- So(pms[i].SetMeta("id", int64(200)), ShouldBeNil) |
+ So(pms[i].SetMeta("id", int64(200)), ShouldBeTrue) |
} |
} |
So(ds.PutMulti(pms), ShouldBeNil) |
@@ -515,7 +519,7 @@ func TestPut(t *testing.T) { |
"Value": {MkProperty(i)}, |
} |
if i == 4 { |
- So(pms[i].SetMeta("id", int64(200)), ShouldBeNil) |
+ So(pms[i].SetMeta("id", int64(200)), ShouldBeTrue) |
} |
} |
So(ds.PutMulti(pms), ShouldBeNil) |
@@ -603,12 +607,13 @@ func TestGet(t *testing.T) { |
Convey("bad", func() { |
Convey("static can't serialize", func() { |
toGet := []badStruct{{}, {}} |
- So(ds.GetMulti(toGet).Error(), ShouldContainSubstring, "invalid GetMulti input") |
+ So(func() { ds.GetMulti(toGet) }, ShouldPanicLike, |
+ `field "Compy" has invalid type: complex64`) |
}) |
Convey("can't get keys", func() { |
fplss := []FakePLS{{failGetMeta: true}, {}} |
- So(ds.GetMulti(fplss).Error(), ShouldContainSubstring, "unable to extract $kind") |
+ So(ds.GetMulti(fplss), ShouldErrLike, "unable to extract $kind") |
}) |
Convey("get single error for RPC failure", func() { |
@@ -626,12 +631,13 @@ func TestGet(t *testing.T) { |
Convey("get with non-modifiable type is an error", func() { |
cs := CommonStruct{} |
- So(ds.Get(cs).Error(), ShouldContainSubstring, "invalid Get input type") |
+ So(ds.Get(cs), ShouldErrLike, "invalid Get input type") |
}) |
- Convey("failure to save metadata is an issue too", func() { |
- cs := &FakePLS{failGetMeta: true} |
- So(ds.Get(cs).Error(), ShouldContainSubstring, "unable to extract $kind") |
+ Convey("failure to save metadata is no problem though", func() { |
+ // It just won't save the key |
+ cs := &FakePLS{IntID: 10, failSetMeta: true} |
+ So(ds.Get(cs), ShouldBeNil) |
}) |
}) |
@@ -673,21 +679,22 @@ func TestGetAll(t *testing.T) { |
Convey("bad", func() { |
Convey("nil target", func() { |
- So(ds.GetAll(q, (*[]PropertyMap)(nil)).Error(), ShouldContainSubstring, "dst: <nil>") |
+ So(ds.GetAll(q, (*[]PropertyMap)(nil)), ShouldErrLike, "dst: <nil>") |
}) |
Convey("bad type", func() { |
output := 100 |
- So(ds.GetAll(q, &output).Error(), ShouldContainSubstring, "invalid GetAll input type") |
+ So(func() { ds.GetAll(q, &output) }, ShouldPanicLike, |
+ "invalid argument type: expected slice, got int") |
}) |
Convey("bad type (non pointer)", func() { |
- So(ds.GetAll(q, "moo").Error(), ShouldContainSubstring, "must have a ptr-to-slice") |
+ So(ds.GetAll(q, "moo"), ShouldErrLike, "must have a ptr-to-slice") |
}) |
Convey("bad type (underspecified)", func() { |
output := []PropertyLoadSaver(nil) |
- So(ds.GetAll(q, &output).Error(), ShouldContainSubstring, "invalid GetAll input type") |
+ So(ds.GetAll(q, &output), ShouldErrLike, "invalid GetAll input type") |
}) |
}) |
@@ -728,8 +735,8 @@ func TestGetAll(t *testing.T) { |
So(ds.GetAll(q, &output), ShouldBeNil) |
So(len(output), ShouldEqual, 5) |
for i, o := range output { |
- k, err := o.GetMeta("key") |
- So(err, ShouldBeNil) |
+ k, ok := o.GetMeta("key") |
+ So(ok, ShouldBeTrue) |
So(k.(*Key).IntID(), ShouldEqual, i+1) |
So(o["Value"][0].Value().(int64), ShouldEqual, i) |
} |
@@ -752,8 +759,8 @@ func TestGetAll(t *testing.T) { |
So(len(output), ShouldEqual, 5) |
for i, op := range output { |
o := *op |
- k, err := o.GetMeta("key") |
- So(err, ShouldBeNil) |
+ k, ok := o.GetMeta("key") |
+ So(ok, ShouldBeTrue) |
So(k.(*Key).IntID(), ShouldEqual, i+1) |
So(o["Value"][0].Value().(int64), ShouldEqual, i) |
} |
@@ -785,13 +792,8 @@ func TestRun(t *testing.T) { |
Convey("bad", func() { |
assertBadTypePanics := func(cb interface{}) { |
- defer func() { |
- err, _ := recover().(error) |
- So(err, ShouldNotBeNil) |
- So(err.Error(), ShouldContainSubstring, |
- "cb does not match the required callback signature") |
- }() |
- So(ds.Run(q, cb), ShouldBeNil) |
+ So(func() { ds.Run(q, cb) }, ShouldPanicLike, |
+ "cb does not match the required callback signature") |
} |
Convey("not a function", func() { |
@@ -799,9 +801,11 @@ func TestRun(t *testing.T) { |
}) |
Convey("bad proto type", func() { |
- assertBadTypePanics(func(v int, _ CursorCB) bool { |
+ cb := func(v int, _ CursorCB) bool { |
panic("never here!") |
- }) |
+ } |
+ So(func() { ds.Run(q, cb) }, ShouldPanicLike, |
+ "invalid argument type: int") |
}) |
Convey("wrong # args", func() { |
@@ -868,8 +872,8 @@ func TestRun(t *testing.T) { |
Convey("*P (map)", func() { |
i := 0 |
So(ds.Run(q, func(pm *PropertyMap, _ CursorCB) bool { |
- k, err := pm.GetMeta("key") |
- So(err, ShouldBeNil) |
+ k, ok := pm.GetMeta("key") |
+ So(ok, ShouldBeTrue) |
So(k.(*Key).IntID(), ShouldEqual, i+1) |
So((*pm)["Value"][0].Value(), ShouldEqual, i) |
i++ |
@@ -901,8 +905,8 @@ func TestRun(t *testing.T) { |
Convey("P (map)", func() { |
i := 0 |
So(ds.Run(q, func(pm PropertyMap, _ CursorCB) bool { |
- k, err := pm.GetMeta("key") |
- So(err, ShouldBeNil) |
+ k, ok := pm.GetMeta("key") |
+ So(ok, ShouldBeTrue) |
So(k.(*Key).IntID(), ShouldEqual, i+1) |
So(pm["Value"][0].Value(), ShouldEqual, i) |
i++ |