| Index: service/datastore/datastore_test.go
 | 
| diff --git a/service/datastore/datastore_test.go b/service/datastore/datastore_test.go
 | 
| index a8fb836b35cb7b94bf11833fc9a27057620ab6b3..d9cfec360dad1a23a2600039b80156abc3c2c0e2 100644
 | 
| --- a/service/datastore/datastore_test.go
 | 
| +++ b/service/datastore/datastore_test.go
 | 
| @@ -180,10 +180,6 @@ func (f *FakePLS) Save(withMeta bool) (PropertyMap, error) {
 | 
|  	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) {
 | 
|  	if f.failGetMeta {
 | 
|  		return nil, errors.New("FakePLS.GetMeta")
 | 
| @@ -216,7 +212,7 @@ func (f *FakePLS) GetAllMeta() PropertyMap {
 | 
|  
 | 
|  func (f *FakePLS) SetMeta(key string, val interface{}) error {
 | 
|  	if f.failSetMeta {
 | 
| -		return errors.New("FakePL.SetMeta")
 | 
| +		return errors.New("FakePLS.SetMeta")
 | 
|  	}
 | 
|  	if key == "id" {
 | 
|  		switch x := val.(type) {
 | 
| @@ -245,10 +241,6 @@ 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
 | 
|  }
 | 
| @@ -343,6 +335,17 @@ func TestKeyForObj(t *testing.T) {
 | 
|  				So(pm.SetMeta("id", 100), ShouldBeNil)
 | 
|  				So(func() { ds.KeyForObj(pm) }, ShouldPanic)
 | 
|  			})
 | 
| +
 | 
| +			Convey("a bad object", func() {
 | 
| +				type BadObj struct {
 | 
| +					ID int64 `gae:"$id"`
 | 
| +
 | 
| +					NonSerializableField complex64
 | 
| +				}
 | 
| +
 | 
| +				_, err := ds.KeyForObjErr(&BadObj{ID: 1})
 | 
| +				So(err, ShouldErrLike, `field "NonSerializableField" has invalid type: complex64`)
 | 
| +			})
 | 
|  		})
 | 
|  	})
 | 
|  }
 | 
| @@ -358,35 +361,35 @@ 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(ds.PutMulti(bss), ShouldErrLike, "invalid PutMulti input")
 | 
|  			})
 | 
|  
 | 
|  			Convey("static ptr can't serialize", func() {
 | 
|  				bss := []*badStruct{{}, {}}
 | 
| -				So(ds.PutMulti(bss).Error(), ShouldContainSubstring, "invalid PutMulti input")
 | 
| +				So(ds.PutMulti(bss), ShouldErrLike, "invalid PutMulti input")
 | 
|  			})
 | 
|  
 | 
|  			Convey("static bad type (non-slice)", func() {
 | 
| -				So(ds.PutMulti(100).Error(), ShouldContainSubstring, "invalid PutMulti input")
 | 
| +				So(ds.PutMulti(100), ShouldErrLike, "invalid PutMulti input")
 | 
|  			})
 | 
|  
 | 
|  			Convey("static bad type (slice of bad type)", func() {
 | 
| -				So(ds.PutMulti([]int{}).Error(), ShouldContainSubstring, "invalid PutMulti input")
 | 
| +				So(ds.PutMulti([]int{}), ShouldErrLike, "invalid PutMulti input")
 | 
|  			})
 | 
|  
 | 
|  			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, "FakePLS.GetMeta")
 | 
|  			})
 | 
|  
 | 
|  			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 +399,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")
 | 
|  			})
 | 
|  		})
 | 
|  
 | 
| @@ -603,12 +606,12 @@ 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(ds.GetMulti(toGet), ShouldErrLike, "invalid GetMulti input")
 | 
|  			})
 | 
|  
 | 
|  			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, "FakePLS.GetMeta")
 | 
|  			})
 | 
|  
 | 
|  			Convey("get single error for RPC failure", func() {
 | 
| @@ -626,12 +629,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 +677,21 @@ 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(ds.GetAll(q, &output), ShouldErrLike, "invalid GetAll input type")
 | 
|  			})
 | 
|  
 | 
|  			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")
 | 
|  			})
 | 
|  		})
 | 
|  
 | 
| @@ -788,8 +792,7 @@ func TestRun(t *testing.T) {
 | 
|  				defer func() {
 | 
|  					err, _ := recover().(error)
 | 
|  					So(err, ShouldNotBeNil)
 | 
| -					So(err.Error(), ShouldContainSubstring,
 | 
| -						"cb does not match the required callback signature")
 | 
| +					So(err, ShouldErrLike, "cb does not match the required callback signature")
 | 
|  				}()
 | 
|  				So(ds.Run(q, cb), ShouldBeNil)
 | 
|  			}
 | 
| 
 |