Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(497)

Unified Diff: go/src/infra/gae/libs/gae/helper/datastore_test.go

Issue 1227183003: Change RawDatastore to do less reflection. (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@move_dummy
Patch Set: fix No/ShouldIndex Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: go/src/infra/gae/libs/gae/helper/datastore_test.go
diff --git a/go/src/infra/gae/libs/gae/helper/datastore_test.go b/go/src/infra/gae/libs/gae/helper/datastore_test.go
index 9fd3b49de82e4d75d2ac26ccb1f6e65ef84ed58d..43f9ee8c6f861959310c5929999b207b83b3d182 100644
--- a/go/src/infra/gae/libs/gae/helper/datastore_test.go
+++ b/go/src/infra/gae/libs/gae/helper/datastore_test.go
@@ -22,18 +22,10 @@ import (
. "github.com/smartystreets/goconvey/convey"
)
-func mp(value interface{}, noIndexes ...bool) (ret gae.DSProperty) {
- ni := false
- if len(noIndexes) > 1 {
- panic("YOU FOOL! YOU CANNOT HOPE TO PASS THAT MANY VALUES!")
- } else if len(noIndexes) == 1 {
- ni = noIndexes[0]
- }
- if err := ret.SetValue(value, ni); err != nil {
- panic(err)
- }
- return
-}
+var (
+ mp = gae.MkDSProperty
+ mpNI = gae.MkDSPropertyNI
+)
const testAppID = "testApp"
@@ -347,7 +339,7 @@ type MismatchTypes struct {
}
type BadSpecial struct {
- ID int `gae:"$id"`
+ ID int64 `gae:"$id"`
id string `gae:"$id"`
}
@@ -357,19 +349,16 @@ type Doubler struct {
B bool
}
-func (d *Doubler) Load(props gae.DSPropertyMap) ([]string, error) {
- return GetStructPLS(d).Load(props)
+func (d *Doubler) Load(props gae.DSPropertyMap) error {
+ return GetPLS(d).Load(props)
}
-func (d *Doubler) Save() (gae.DSPropertyMap, error) {
- // Save the default gae.DSProperty slice to an in-memory buffer (a gae.DSPropertyList).
- pls := GetStructPLS(d)
- props, err := pls.Save()
+func (d *Doubler) Save(withMeta bool) (gae.DSPropertyMap, error) {
+ pls := GetPLS(d)
+ propMap, err := pls.Save(withMeta)
if err != nil {
return nil, err
}
- var propMap gae.DSPropertyMap
- propMap.Load(props) // we know this returns nil/nil
// Edit that map and send it on.
for _, props := range propMap {
@@ -377,23 +366,27 @@ func (d *Doubler) Save() (gae.DSPropertyMap, error) {
switch v := props[i].Value().(type) {
case string:
// + means string concatenation.
- props[i].SetValue(v+v, props[i].NoIndex())
+ props[i].SetValue(v+v, props[i].IndexSetting())
case int64:
// + means integer addition.
- props[i].SetValue(v+v, props[i].NoIndex())
+ props[i].SetValue(v+v, props[i].IndexSetting())
}
}
}
- return propMap.Save()
+ return propMap, nil
}
+func (d *Doubler) GetMeta(string) (interface{}, error) { return nil, gae.ErrDSMetaFieldUnset }
+func (d *Doubler) SetMeta(string, interface{}) error { return gae.ErrDSMetaFieldUnset }
+func (d *Doubler) Problem() error { return nil }
+
var _ gae.DSPropertyLoadSaver = (*Doubler)(nil)
type Deriver struct {
S, Derived, Ignored string
}
-func (e *Deriver) Load(props gae.DSPropertyMap) ([]string, error) {
+func (e *Deriver) Load(props gae.DSPropertyMap) error {
for name, p := range props {
if name != "S" {
continue
@@ -401,15 +394,19 @@ func (e *Deriver) Load(props gae.DSPropertyMap) ([]string, error) {
e.S = p[0].Value().(string)
e.Derived = "derived+" + e.S
}
- return nil, nil
+ return nil
}
-func (e *Deriver) Save() (gae.DSPropertyMap, error) {
+func (e *Deriver) Save(withMeta bool) (gae.DSPropertyMap, error) {
return map[string][]gae.DSProperty{
"S": {mp(e.S)},
}, nil
}
+func (d *Deriver) GetMeta(string) (interface{}, error) { return nil, gae.ErrDSMetaFieldUnset }
+func (d *Deriver) SetMeta(string, interface{}) error { return gae.ErrDSMetaFieldUnset }
+func (d *Deriver) Problem() error { return nil }
+
var _ gae.DSPropertyLoadSaver = (*Deriver)(nil)
type BK struct {
@@ -425,7 +422,7 @@ func (c *Convertable) ToDSProperty() (ret gae.DSProperty, err error) {
for i, v := range *c {
buf[i] = strconv.FormatInt(v, 10)
}
- err = ret.SetValue(strings.Join(buf, ","), true)
+ err = ret.SetValue(strings.Join(buf, ","), gae.NoIndex)
return
}
@@ -457,7 +454,7 @@ type Convertable2 struct {
}
func (c *Convertable2) ToDSProperty() (ret gae.DSProperty, err error) {
- err = ret.SetValue(c.Data, false)
+ err = ret.SetValue(c.Data, gae.ShouldIndex)
return
}
@@ -487,7 +484,7 @@ func (j *JSONKVProp) ToDSProperty() (ret gae.DSProperty, err error) {
if err != nil {
return
}
- err = ret.SetValue(data, true)
+ err = ret.SetValue(data, gae.NoIndex)
return
}
@@ -513,7 +510,7 @@ func (c *Complex) ToDSProperty() (ret gae.DSProperty, err error) {
// (note that this won't REALLY work, since GeoPoints are limited to a very
// limited range of values, but it's nice to pretend ;)). You'd probably
// really end up with a packed binary representation.
- err = ret.SetValue(gae.DSGeoPoint{Lat: real(*c), Lng: imag(*c)}, false)
+ err = ret.SetValue(gae.DSGeoPoint{Lat: real(*c), Lng: imag(*c)}, gae.ShouldIndex)
return
}
@@ -545,7 +542,6 @@ type testCase struct {
saveErr string
actualNoIndex bool
plsLoadErr string
- convErr string
loadErr string
}
@@ -601,7 +597,7 @@ var testCases = []testCase{
{
desc: "geopoint as props",
src: &G0{G: testGeoPt0},
- want: &gae.DSPropertyMap{
+ want: gae.DSPropertyMap{
"G": {mp(testGeoPt0)},
},
},
@@ -639,7 +635,7 @@ var testCases = []testCase{
desc: "overflow",
src: &O0{I: 1 << 48},
want: &O1{},
- convErr: "overflow",
+ loadErr: "overflow",
},
{
desc: "time",
@@ -649,8 +645,8 @@ var testCases = []testCase{
{
desc: "time as props",
src: &T{T: time.Unix(1e9, 0).UTC()},
- want: &gae.DSPropertyMap{
- "T": {mp(time.Unix(1e9, 0).UTC(), false)},
+ want: gae.DSPropertyMap{
+ "T": {mp(time.Unix(1e9, 0).UTC())},
},
},
{
@@ -683,13 +679,13 @@ var testCases = []testCase{
desc: "missing fields",
src: &X0{S: "one", I: 2, i: 3},
want: &X2{},
- convErr: "no such struct field",
+ loadErr: "no such struct field",
},
{
desc: "save string load bool",
src: &X0{S: "one", I: 2, i: 3},
want: &X3{I: 2},
- convErr: "type mismatch",
+ loadErr: "type mismatch",
},
{
desc: "basic slice",
@@ -700,7 +696,7 @@ var testCases = []testCase{
desc: "save []float64 load float64",
src: &Y0{B: true, F: []float64{7, 8, 9}},
want: &Y1{B: true},
- convErr: "requires a slice",
+ loadErr: "requires a slice",
},
{
desc: "save single []int64 load int64",
@@ -720,15 +716,15 @@ var testCases = []testCase{
{
desc: "use convertable slice (to map)",
src: &Impossible{[]ImpossibleInner{{Convertable{1, 5, 9}}, {Convertable{2, 4, 6}}}},
- want: &gae.DSPropertyMap{
- "Nested.wot": {mp("1,5,9", true), mp("2,4,6", true)},
+ want: gae.DSPropertyMap{
+ "Nested.wot": {mpNI("1,5,9"), mpNI("2,4,6")},
},
},
{
desc: "convertable slice (bad load)",
- src: &gae.DSPropertyMap{"Nested.wot": {mp([]byte("ohai"), true)}},
+ src: gae.DSPropertyMap{"Nested.wot": {mpNI([]byte("ohai"))}},
want: &Impossible{[]ImpossibleInner{{}}},
- convErr: "nope",
+ loadErr: "nope",
},
{
desc: "use convertable struct",
@@ -769,11 +765,10 @@ var testCases = []testCase{
"what": []interface{}{"is", "really", 100},
},
},
- want: &gae.DSPropertyMap{
+ want: gae.DSPropertyMap{
"kewelmap": {
- mp([]byte(
- `{"epic":"success","no_way!":[true,"story"],"what":["is","really",100]}`),
- true)},
+ mpNI([]byte(
+ `{"epic":"success","no_way!":[true,"story"],"what":["is","really",100]}`))},
},
},
{
@@ -790,16 +785,16 @@ var testCases = []testCase{
src: &Impossible4{
[]Complex{complex(1, 2), complex(3, 4)},
},
- want: &gae.DSPropertyMap{
+ want: gae.DSPropertyMap{
"Values": {
mp(gae.DSGeoPoint{Lat: 1, Lng: 2}), mp(gae.DSGeoPoint{Lat: 3, Lng: 4})},
},
},
{
desc: "convertable complex slice (bad load)",
- src: &gae.DSPropertyMap{"Values": {mp("hello")}},
+ src: gae.DSPropertyMap{"Values": {mp("hello")}},
want: &Impossible4{[]Complex(nil)},
- convErr: "nope",
+ loadErr: "nope",
},
{
desc: "allow concrete gae.DSKey implementors (save)",
@@ -815,7 +810,7 @@ var testCases = []testCase{
desc: "save []float64 load []int64",
src: &Y0{B: true, F: []float64{7, 8, 9}},
want: &Y2{B: true},
- convErr: "type mismatch",
+ loadErr: "type mismatch",
},
{
desc: "single slice is too long",
@@ -892,13 +887,13 @@ var testCases = []testCase{
{
desc: "short gae.DSByteString as props",
src: &B5{B: gae.DSByteString(makeUint8Slice(3))},
- want: &gae.DSPropertyMap{
+ want: gae.DSPropertyMap{
"B": {mp(gae.DSByteString(makeUint8Slice(3)))},
},
},
{
desc: "[]byte must be noindex",
- src: &gae.DSPropertyMap{
+ src: gae.DSPropertyMap{
"B": {mp(makeUint8Slice(3))},
},
actualNoIndex: true,
@@ -906,7 +901,7 @@ var testCases = []testCase{
{
desc: "save tagged load props",
src: &Tagged{A: 1, B: []int{21, 22, 23}, C: 3, D: 4, E: 5, I: 6, J: 7},
- want: &gae.DSPropertyMap{
+ want: gae.DSPropertyMap{
// A and B are renamed to a and b; A and C are noindex, I is ignored.
// Indexed properties are loaded before raw properties. Thus, the
// result is: b, b, b, D, E, a, c.
@@ -917,9 +912,9 @@ var testCases = []testCase{
},
"D": {mp(4)},
"E": {mp(5)},
- "a": {mp(1, true)},
- "C": {mp(3, true)},
- "J": {mp(7, true)},
+ "a": {mpNI(1)},
+ "C": {mpNI(3)},
+ "J": {mpNI(7)},
},
},
{
@@ -929,12 +924,12 @@ var testCases = []testCase{
},
{
desc: "save props load tagged",
- src: &gae.DSPropertyMap{
- "A": {mp(11, true)},
- "a": {mp(12, true)},
+ src: gae.DSPropertyMap{
+ "A": {mpNI(11)},
+ "a": {mpNI(12)},
},
want: &Tagged{A: 12},
- convErr: `cannot load field "A"`,
+ loadErr: `cannot load field "A"`,
},
{
desc: "invalid tagged1",
@@ -970,14 +965,14 @@ var testCases = []testCase{
{
desc: "save struct load props",
src: &X0{S: "s", I: 1},
- want: &gae.DSPropertyMap{
+ want: gae.DSPropertyMap{
"S": {mp("s")},
"I": {mp(1)},
},
},
{
desc: "save props load struct",
- src: &gae.DSPropertyMap{
+ src: gae.DSPropertyMap{
"S": {mp("s")},
"I": {mp(1)},
},
@@ -985,7 +980,7 @@ var testCases = []testCase{
},
{
desc: "nil-value props",
- src: &gae.DSPropertyMap{
+ src: gae.DSPropertyMap{
"I": {mp(nil)},
"B": {mp(nil)},
"S": {mp(nil)},
@@ -1026,7 +1021,7 @@ var testCases = []testCase{
Z: true,
},
},
- want: &gae.DSPropertyMap{
+ want: gae.DSPropertyMap{
"A": {mp(1)},
"I.W": {
mp(10),
@@ -1044,7 +1039,7 @@ var testCases = []testCase{
},
{
desc: "save props load outer-equivalent",
- src: &gae.DSPropertyMap{
+ src: gae.DSPropertyMap{
"A": {mp(1)},
"I.W": {
mp(10),
@@ -1094,13 +1089,13 @@ var testCases = []testCase{
{
desc: "dotted names save",
src: &Dotted{A: DottedA{B: DottedB{C: 88}}},
- want: &gae.DSPropertyMap{
+ want: gae.DSPropertyMap{
"A0.A1.A2.B3.C4.C5": {mp(88)},
},
},
{
desc: "dotted names load",
- src: &gae.DSPropertyMap{
+ src: gae.DSPropertyMap{
"A0.A1.A2.B3.C4.C5": {mp(99)},
},
want: &Dotted{A: DottedA{B: DottedB{C: 99}}},
@@ -1180,49 +1175,49 @@ var testCases = []testCase{
},
{
desc: "mismatch (string)",
- src: &gae.DSPropertyMap{
+ src: gae.DSPropertyMap{
"K": {mp(199)},
"S": {mp([]byte("cats"))},
"F": {mp(gae.DSByteString("nurbs"))},
},
want: &MismatchTypes{},
- convErr: "type mismatch",
+ loadErr: "type mismatch",
},
{
desc: "mismatch (float)",
- src: &gae.DSPropertyMap{"F": {mp(gae.BSKey("wot"))}},
+ src: gae.DSPropertyMap{"F": {mp(gae.BSKey("wot"))}},
want: &MismatchTypes{},
- convErr: "type mismatch",
+ loadErr: "type mismatch",
},
{
desc: "mismatch (float/overflow)",
- src: &gae.DSPropertyMap{"F": {mp(math.MaxFloat64)}},
+ src: gae.DSPropertyMap{"F": {mp(math.MaxFloat64)}},
want: &MismatchTypes{},
- convErr: "overflows",
+ loadErr: "overflows",
},
{
desc: "mismatch (key)",
- src: &gae.DSPropertyMap{"K": {mp(false)}},
+ src: gae.DSPropertyMap{"K": {mp(false)}},
want: &MismatchTypes{},
- convErr: "type mismatch",
+ loadErr: "type mismatch",
},
{
desc: "mismatch (bool)",
- src: &gae.DSPropertyMap{"B": {mp(testKey0)}},
+ src: gae.DSPropertyMap{"B": {mp(testKey0)}},
want: &MismatchTypes{},
- convErr: "type mismatch",
+ loadErr: "type mismatch",
},
{
desc: "mismatch (time)",
- src: &gae.DSPropertyMap{"T": {mp(gae.DSGeoPoint{})}},
+ src: gae.DSPropertyMap{"T": {mp(gae.DSGeoPoint{})}},
want: &MismatchTypes{},
- convErr: "type mismatch",
+ loadErr: "type mismatch",
},
{
desc: "mismatch (geopoint)",
- src: &gae.DSPropertyMap{"G": {mp(time.Now().UTC())}},
+ src: gae.DSPropertyMap{"G": {mp(time.Now().UTC())}},
want: &MismatchTypes{},
- convErr: "type mismatch",
+ loadErr: "type mismatch",
},
{
desc: "slice of structs",
@@ -1331,7 +1326,7 @@ var testCases = []testCase{
},
},
},
- want: &gae.DSPropertyMap{
+ want: gae.DSPropertyMap{
"red.S": {mp("rouge")},
"red.I": {mp(0)},
"red.Nonymous.S": {mp("rosso0"), mp("rosso1")},
@@ -1351,7 +1346,7 @@ var testCases = []testCase{
},
{
desc: "save props load structs with ragged fields",
- src: &gae.DSPropertyMap{
+ src: gae.DSPropertyMap{
"red.S": {mp("rot")},
"green.Nonymous.I": {mp(10), mp(11), mp(12), mp(13)},
"Blue.Nonymous.S": {mp("blau0"), mp("blau1"), mp("blau2")},
@@ -1390,11 +1385,11 @@ var testCases = []testCase{
Y string
}
}{},
- want: &gae.DSPropertyMap{
+ want: gae.DSPropertyMap{
"B.Y": {mp("")},
- "A.X": {mp("", true)},
- "A.Y": {mp("", true)},
- "B.X": {mp("", true)},
+ "A.X": {mpNI("")},
+ "A.Y": {mpNI("")},
+ "B.X": {mpNI("")},
},
},
{
@@ -1402,7 +1397,7 @@ var testCases = []testCase{
src: &struct {
Inner1 `gae:"foo"`
}{},
- want: &gae.DSPropertyMap{
+ want: gae.DSPropertyMap{
"foo.W": {mp(0)},
"foo.X": {mp("")},
},
@@ -1427,7 +1422,7 @@ var testCases = []testCase{
src: &struct {
i, J int64
}{i: 1, J: 2},
- want: &gae.DSPropertyMap{
+ want: gae.DSPropertyMap{
"J": {mp(2)},
},
},
@@ -1438,7 +1433,7 @@ var testCases = []testCase{
}{
J: json.RawMessage("rawr"),
},
- want: &gae.DSPropertyMap{
+ want: gae.DSPropertyMap{
"J": {mp([]byte("rawr"))},
},
},
@@ -1511,13 +1506,16 @@ func TestRoundTrip(t *testing.T) {
for _, tc := range testCases {
tc := tc
Convey(tc.desc, func() {
- pls, err := GetPLS(tc.src)
- if checkErr(err, tc.plsErr) {
+ pls, ok := tc.src.(gae.DSPropertyLoadSaver)
+ if !ok {
+ pls = GetPLS(tc.src)
+ }
+ if checkErr(pls.Problem(), tc.plsErr) {
return
}
So(pls, ShouldNotBeNil)
- savedProps, err := pls.Save()
+ savedProps, err := pls.Save(false)
if checkErr(err, tc.saveErr) {
return
}
@@ -1525,34 +1523,32 @@ func TestRoundTrip(t *testing.T) {
if tc.actualNoIndex {
for _, props := range savedProps {
- So(props[0].NoIndex(), ShouldBeTrue)
+ So(props[0].IndexSetting(), ShouldEqual, gae.NoIndex)
return
}
So(true, ShouldBeFalse) // shouldn't get here
}
var got interface{}
- if _, ok := tc.want.(*gae.DSPropertyMap); ok {
- got = &gae.DSPropertyMap{}
+ if _, ok := tc.want.(gae.DSPropertyMap); ok {
+ pls = gae.DSPropertyMap{}
+ got = pls
} else {
got = reflect.New(reflect.TypeOf(tc.want).Elem()).Interface()
+ if pls, ok = got.(gae.DSPropertyLoadSaver); !ok {
+ pls = GetPLS(got)
+ }
}
- pls, err = GetPLS(got)
- if checkErr(err, tc.plsLoadErr) {
+ if checkErr(pls.Problem(), tc.plsLoadErr) {
return
}
So(pls, ShouldNotBeNil)
- convErrs, err := pls.Load(savedProps)
+ err = pls.Load(savedProps)
if checkErr(err, tc.loadErr) {
return
}
- if len(tc.convErr) == 0 {
- So(convErrs, ShouldBeNil)
- } else {
- So(convErrs[0], ShouldContainSubstring, tc.convErr)
- }
if tc.want == nil {
return
}
@@ -1575,39 +1571,37 @@ func TestSpecial(t *testing.T) {
Convey("Test special fields", t, func() {
Convey("Can retrieve from struct", func() {
o := &N0{ID: 100}
- pls := GetStructPLS(o)
- val, current, err := pls.GetSpecial("id")
+ pls := GetPLS(o)
+ val, err := pls.GetMeta("id")
So(err, ShouldBeNil)
- So(val, ShouldEqual, "")
- So(current, ShouldEqual, 100)
+ So(val, ShouldEqual, 100)
- val, current, err = pls.GetSpecial("kind")
+ val, err = pls.GetMeta("kind")
So(err, ShouldBeNil)
So(val, ShouldEqual, "whatnow")
- So(current, ShouldEqual, nil)
})
Convey("Getting something not there is an error", func() {
o := &N0{ID: 100}
- pls := GetStructPLS(o)
- _, _, err := pls.GetSpecial("wat")
- So(err, ShouldEqual, gae.ErrDSSpecialFieldUnset)
+ pls := GetPLS(o)
+ _, err := pls.GetMeta("wat")
+ So(err, ShouldEqual, gae.ErrDSMetaFieldUnset)
})
Convey("getting/setting from a bad struct is an error", func() {
o := &Recursive{}
- pls := GetStructPLS(o)
- _, _, err := pls.GetSpecial("wat")
+ pls := GetPLS(o)
+ _, err := pls.GetMeta("wat")
So(err, ShouldNotBeNil)
- err = pls.SetSpecial("wat", 100)
+ err = pls.SetMeta("wat", 100)
So(err, ShouldNotBeNil)
})
Convey("can assign values to exported special fields", func() {
o := &N0{ID: 100}
- pls := GetStructPLS(o)
- err := pls.SetSpecial("id", int64(200))
+ pls := GetPLS(o)
+ err := pls.SetMeta("id", int64(200))
So(err, ShouldBeNil)
So(o.ID, ShouldEqual, 200)
@@ -1615,74 +1609,111 @@ func TestSpecial(t *testing.T) {
Convey("assigning to unsassiagnable fields is a simple error", func() {
o := &N0{ID: 100}
- pls := GetStructPLS(o)
- err := pls.SetSpecial("kind", "hi")
+ pls := GetPLS(o)
+ err := pls.SetMeta("kind", "hi")
So(err.Error(), ShouldContainSubstring, "unexported field")
- err = pls.SetSpecial("noob", "hi")
- So(err, ShouldEqual, gae.ErrDSSpecialFieldUnset)
+ err = pls.SetMeta("noob", "hi")
+ So(err, ShouldEqual, gae.ErrDSMetaFieldUnset)
})
})
Convey("StructPLS Miscellaneous", t, func() {
Convey("multiple overlapping fields is an error", func() {
o := &BadSpecial{}
- pls := GetStructPLS(o)
- convErr, err := pls.Load(nil)
- So(convErr, ShouldBeNil)
+ pls := GetPLS(o)
+ err := pls.Load(nil)
So(err, ShouldErrLike, "multiple times")
e := pls.Problem()
- _, err = pls.Save()
+ _, err = pls.Save(true)
So(err, ShouldEqual, e)
- _, err = pls.Load(nil)
+ err = pls.Load(nil)
So(err, ShouldEqual, e)
})
- Convey("can transform a list of things into a list of PLSs", func() {
- o := []interface{}{
- &N0{X0: X0{S: "hi", I: 5}},
- &N0{Nonymous: X0{S: "hi", I: 5}},
- &gae.DSPropertyMap{
- "Nerd": {mp(10), mp(false)},
- "What": {mp("is"), mp("up")},
- },
+ Convey("empty property names are invalid", func() {
+ So(validPropertyName(""), ShouldBeFalse)
+ })
+
+ Convey("attempting to get a PLS for a non *struct is an error", func() {
+ pls := GetPLS((*[]string)(nil))
+ So(pls.Problem(), ShouldEqual, gae.ErrDSInvalidEntityType)
+ })
+
+ Convey("convertible meta default types", func() {
+ type OKDefaults struct {
+ When string `gae:"$when,tomorrow"`
+ Amount int64 `gae:"$amt,100"`
}
- plss, err := MultiGetPLS(o)
+ pls := GetPLS(&OKDefaults{})
+ So(pls.Problem(), ShouldBeNil)
+
+ v, err := pls.GetMeta("when")
So(err, ShouldBeNil)
- for i, pls := range plss {
- pmap, err := pls.Save()
- targ := gae.DSPropertyLoadSaver(&gae.DSPropertyMap{})
- obj := interface{}(targ)
- if i < 2 {
- obj = &N0{}
- targ = GetStructPLS(obj)
- }
- convErr, err := targ.Load(pmap)
- So(err, ShouldBeNil)
- So(convErr, ShouldBeNil)
- So(obj, ShouldResemble, o[i])
+ So(v, ShouldEqual, "tomorrow")
+
+ v, err = pls.GetMeta("amt")
+ So(err, ShouldBeNil)
+ So(v, ShouldEqual, int64(100))
+ })
+
+ Convey("meta fields can be saved", func() {
+ type OKDefaults struct {
+ When string `gae:"$when,tomorrow"`
+ Amount int64 `gae:"$amt,100"`
}
+ pls := GetPLS(&OKDefaults{})
+ pm, err := pls.Save(true)
+ So(err, ShouldBeNil)
+ So(pm, ShouldResemble, gae.DSPropertyMap{
+ "$when": {gae.MkDSPropertyNI("tomorrow")},
+ "$amt": {gae.MkDSPropertyNI(100)},
+ })
+
+ v, err := pm.GetMeta("when")
+ So(err, ShouldBeNil)
+ So(v, ShouldEqual, "tomorrow")
+
+ v, err = pm.GetMeta("amt")
+ So(err, ShouldBeNil)
+ So(v, ShouldEqual, int64(100))
})
- Convey("list of DSPropertyLoadSavers is a shortcut", func() {
- o := []gae.DSPropertyLoadSaver{&gae.DSPropertyMap{}}
- plss, err := MultiGetPLS(o)
+ Convey("default are optional", func() {
+ type OverrideDefault struct {
+ Val int64 `gae:"$val"`
+ }
+ o := &OverrideDefault{}
+ pls := GetPLS(o)
+
+ v, err := pls.GetMeta("val")
So(err, ShouldBeNil)
- So(&plss[0], ShouldEqual, &o[0]) // identical underlying array
+ So(v, ShouldEqual, int64(0))
})
- Convey("attempting to transform a bad object is an error", func() {
- o := []int{100}
- _, err := MultiGetPLS(o)
- So(err, ShouldEqual, gae.ErrDSInvalidEntityType)
+ Convey("overridable defaults", func() {
+ type OverrideDefault struct {
+ Val int64 `gae:"$val,100"`
+ }
+ o := &OverrideDefault{}
+ pls := GetPLS(o)
+
+ v, err := pls.GetMeta("val")
+ So(err, ShouldBeNil)
+ So(v, ShouldEqual, int64(100))
- f := false
- _, err = MultiGetPLS(&f)
- So(err, ShouldErrLike, "bad type")
+ o.Val = 10
+ v, err = pls.GetMeta("val")
+ So(err, ShouldBeNil)
+ So(v, ShouldEqual, int64(10))
})
- Convey("empty property names are invalid", func() {
- So(validPropertyName(""), ShouldBeFalse)
+ Convey("Bad default meta type", func() {
+ type BadDefault struct {
+ Val time.Time `gae:"$meta,tomorrow"`
+ }
+ pls := GetPLS(&BadDefault{})
+ So(pls.Problem().Error(), ShouldContainSubstring, "bad type")
})
})
}
« no previous file with comments | « go/src/infra/gae/libs/gae/helper/datastore_impl.go ('k') | go/src/infra/gae/libs/gae/helper/helper.infra_testing » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698