Index: service/datastore/datastore_test.go |
diff --git a/service/datastore/datastore_test.go b/service/datastore/datastore_test.go |
index a9f38f11ce4294d140d427ed3373f9bfa3644bca..86246c84607a067b0362f8492a1d494f1bcdc50e 100644 |
--- a/service/datastore/datastore_test.go |
+++ b/service/datastore/datastore_test.go |
@@ -12,6 +12,7 @@ import ( |
"github.com/luci/gae/service/info" |
"github.com/luci/luci-go/common/errors" |
+ . "github.com/luci/luci-go/common/testing/assertions" |
. "github.com/smartystreets/goconvey/convey" |
"golang.org/x/net/context" |
) |
@@ -24,78 +25,40 @@ func fakeDatastoreFactory(c context.Context) RawInterface { |
} |
} |
-type fakeQuery struct { |
- Query |
- |
- limit int |
- |
- err error |
- errSingle error |
- errSingleIdx int |
-} |
- |
-func (q *fakeQuery) KeysOnly() Query { |
- return q |
-} |
- |
-func (q *fakeQuery) Limit(i int) Query { |
- q.limit = i |
- return q |
-} |
- |
-func (q *fakeQuery) FailAll() Query { |
- q.err = errors.New("Query fail all") |
- return q |
-} |
- |
-func (q *fakeQuery) Fail(i int) Query { |
- q.errSingleIdx = i |
- q.errSingle = errors.New("Query fail") |
- return q |
-} |
- |
type fakeDatastore struct { |
RawInterface |
aid string |
ns string |
} |
-func (f *fakeDatastore) NewKey(kind, stringID string, intID int64, parent Key) Key { |
- id := interface{}(stringID) |
- if stringID == "" { |
- id = intID |
- } |
- return mkKey(f.aid, f.ns, kind, id, parent) |
+func (f *fakeDatastore) mkKey(elems ...interface{}) *Key { |
+ return MakeKey(f.aid, f.ns, elems...) |
} |
-func (f *fakeDatastore) NewQuery(string) Query { |
- return &fakeQuery{} |
-} |
+func (f *fakeDatastore) Run(fq *FinalizedQuery, cb RawRunCB) error { |
+ lim, _ := fq.Limit() |
-func (f *fakeDatastore) Run(q Query, cb RawRunCB) error { |
- rq := q.(*fakeQuery) |
- if rq.err != nil { |
- return rq.err |
- } |
- for i := 0; i < rq.limit; i++ { |
- if rq.errSingle != nil && i == rq.errSingleIdx { |
- return rq.errSingle |
- } else { |
- k := f.NewKey("Kind", "", int64(i+1), nil) |
- if i == 10 { |
- k = f.NewKey("Kind", "eleven", 0, nil) |
- } |
- pm := PropertyMap{"Value": {MkProperty(i)}} |
- if !cb(k, pm, nil) { |
- break |
+ for i := int32(0); i < lim; i++ { |
+ if v, ok := fq.eqFilts["$err_single"]; ok { |
+ idx := fq.eqFilts["$err_single_idx"][0].Value().(int64) |
+ if idx == int64(i) { |
+ return errors.New(v[0].Value().(string)) |
} |
} |
+ k := f.mkKey("Kind", i+1) |
+ if i == 10 { |
+ k = f.mkKey("Kind", "eleven") |
+ } |
+ pm := PropertyMap{"Value": {MkProperty(i)}} |
+ if !cb(k, pm, nil) { |
+ break |
+ } |
} |
return nil |
} |
-func (f *fakeDatastore) PutMulti(keys []Key, vals []PropertyMap, cb PutMultiCB) error { |
- if keys[0].Kind() == "FailAll" { |
+func (f *fakeDatastore) PutMulti(keys []*Key, vals []PropertyMap, cb PutMultiCB) error { |
+ if keys[0].Last().Kind == "FailAll" { |
return errors.New("PutMulti fail all") |
} |
assertExtra := false |
@@ -104,7 +67,7 @@ func (f *fakeDatastore) PutMulti(keys []Key, vals []PropertyMap, cb PutMultiCB) |
} |
for i, k := range keys { |
err := error(nil) |
- if k.Kind() == "Fail" { |
+ if k.Last().Kind == "Fail" { |
err = errors.New("PutMulti fail") |
} else { |
So(vals[i]["Value"], ShouldResemble, []Property{MkProperty(i)}) |
@@ -112,7 +75,7 @@ func (f *fakeDatastore) PutMulti(keys []Key, vals []PropertyMap, cb PutMultiCB) |
So(vals[i]["Extra"], ShouldResemble, []Property{MkProperty("whoa")}) |
} |
if k.Incomplete() { |
- k = mkKey(k.AppID(), k.Namespace(), k.Kind(), int64(i+1), k.Parent()) |
+ k = NewKey(k.AppID(), k.Namespace(), k.Last().Kind, "", int64(i+1), k.Parent()) |
} |
} |
cb(k, err) |
@@ -120,12 +83,12 @@ func (f *fakeDatastore) PutMulti(keys []Key, vals []PropertyMap, cb PutMultiCB) |
return nil |
} |
-func (f *fakeDatastore) GetMulti(keys []Key, _meta MultiMetaGetter, cb GetMultiCB) error { |
- if keys[0].Kind() == "FailAll" { |
+func (f *fakeDatastore) GetMulti(keys []*Key, _meta MultiMetaGetter, cb GetMultiCB) error { |
+ if keys[0].Last().Kind == "FailAll" { |
return errors.New("GetMulti fail all") |
} |
for i, k := range keys { |
- if k.Kind() == "Fail" { |
+ if k.Last().Kind == "Fail" { |
cb(nil, errors.New("GetMulti fail")) |
} else { |
cb(PropertyMap{"Value": {MkProperty(i + 1)}}, nil) |
@@ -134,12 +97,12 @@ func (f *fakeDatastore) GetMulti(keys []Key, _meta MultiMetaGetter, cb GetMultiC |
return nil |
} |
-func (f *fakeDatastore) DeleteMulti(keys []Key, cb DeleteMultiCB) error { |
- if keys[0].Kind() == "FailAll" { |
+func (f *fakeDatastore) DeleteMulti(keys []*Key, cb DeleteMultiCB) error { |
+ if keys[0].Last().Kind == "FailAll" { |
return errors.New("DeleteMulti fail all") |
} |
for _, k := range keys { |
- if k.Kind() == "Fail" { |
+ if k.Last().Kind == "Fail" { |
cb(errors.New("DeleteMulti fail")) |
} else { |
cb(nil) |
@@ -155,7 +118,7 @@ type badStruct struct { |
type CommonStruct struct { |
ID int64 `gae:"$id"` |
- Parent Key `gae:"$parent"` |
+ Parent *Key `gae:"$parent"` |
Value int64 |
} |
@@ -204,13 +167,13 @@ func (f *FakePLS) Save(withMeta bool) (PropertyMap, error) { |
} |
if withMeta { |
id, _ := f.GetMeta("id") |
- ret.SetMeta("id", id) |
+ So(ret.SetMeta("id", id), ShouldBeNil) |
if f.Kind == "" { |
- ret.SetMeta("kind", "FakePLS") |
+ So(ret.SetMeta("kind", "FakePLS"), ShouldBeNil) |
} else { |
- ret.SetMeta("kind", f.Kind) |
+ So(ret.SetMeta("kind", f.Kind), ShouldBeNil) |
} |
- ret.SetMeta("assertExtra", true) |
+ So(ret.SetMeta("assertExtra", true), ShouldBeNil) |
} |
return ret, nil |
} |
@@ -273,12 +236,12 @@ func TestKeyForObj(t *testing.T) { |
c = SetRawFactory(c, fakeDatastoreFactory) |
ds := Get(c) |
- k := ds.NewKey("Hello", "world", 0, nil) |
+ k := ds.MakeKey("Hello", "world") |
Convey("good", func() { |
Convey("struct containing $key", func() { |
type keyStruct struct { |
- Key Key `gae:"$key"` |
+ Key *Key `gae:"$key"` |
} |
ks := &keyStruct{k} |
@@ -291,37 +254,37 @@ func TestKeyForObj(t *testing.T) { |
knd string `gae:"$kind,SuperKind"` |
} |
- So(ds.KeyForObj(&idStruct{}).String(), ShouldEqual, `/SuperKind,wut`) |
+ So(ds.KeyForObj(&idStruct{}).String(), ShouldEqual, `s~aid:ns:/SuperKind,"wut"`) |
}) |
Convey("struct containing $id and $parent", func() { |
- So(ds.KeyForObj(&CommonStruct{ID: 4}).String(), ShouldEqual, `/CommonStruct,4`) |
+ So(ds.KeyForObj(&CommonStruct{ID: 4}).String(), ShouldEqual, `s~aid:ns:/CommonStruct,4`) |
- So(ds.KeyForObj(&CommonStruct{ID: 4, Parent: k}).String(), ShouldEqual, `/Hello,world/CommonStruct,4`) |
+ So(ds.KeyForObj(&CommonStruct{ID: 4, Parent: k}).String(), ShouldEqual, `s~aid:ns:/Hello,"world"/CommonStruct,4`) |
}) |
Convey("a propmap with $key", func() { |
pm := PropertyMap{} |
- pm.SetMeta("key", k) |
- So(ds.KeyForObj(pm).String(), ShouldEqual, `/Hello,world`) |
+ So(pm.SetMeta("key", k), ShouldBeNil) |
+ So(ds.KeyForObj(pm).String(), ShouldEqual, `s~aid:ns:/Hello,"world"`) |
}) |
Convey("a propmap with $id, $kind, $parent", func() { |
pm := PropertyMap{} |
- pm.SetMeta("id", 100) |
- pm.SetMeta("kind", "Sup") |
- So(ds.KeyForObj(pm).String(), ShouldEqual, `/Sup,100`) |
+ So(pm.SetMeta("id", 100), ShouldBeNil) |
+ So(pm.SetMeta("kind", "Sup"), ShouldBeNil) |
+ So(ds.KeyForObj(pm).String(), ShouldEqual, `s~aid:ns:/Sup,100`) |
- pm.SetMeta("parent", k) |
- So(ds.KeyForObj(pm).String(), ShouldEqual, `/Hello,world/Sup,100`) |
+ So(pm.SetMeta("parent", k), ShouldBeNil) |
+ So(ds.KeyForObj(pm).String(), ShouldEqual, `s~aid:ns:/Hello,"world"/Sup,100`) |
}) |
Convey("a pls with $id, $parent", func() { |
pls := GetPLS(&CommonStruct{ID: 1}) |
- So(ds.KeyForObj(pls).String(), ShouldEqual, `/CommonStruct,1`) |
+ So(ds.KeyForObj(pls).String(), ShouldEqual, `s~aid:ns:/CommonStruct,1`) |
- pls.SetMeta("parent", k) |
- So(ds.KeyForObj(pls).String(), ShouldEqual, `/Hello,world/CommonStruct,1`) |
+ So(pls.SetMeta("parent", k), ShouldBeNil) |
+ So(ds.KeyForObj(pls).String(), ShouldEqual, `s~aid:ns:/Hello,"world"/CommonStruct,1`) |
}) |
}) |
@@ -329,7 +292,7 @@ func TestKeyForObj(t *testing.T) { |
Convey("bad", func() { |
Convey("a propmap without $kind", func() { |
pm := PropertyMap{} |
- pm.SetMeta("id", 100) |
+ So(pm.SetMeta("id", 100), ShouldBeNil) |
So(func() { ds.KeyForObj(pm) }, ShouldPanic) |
}) |
}) |
@@ -449,7 +412,7 @@ func TestPut(t *testing.T) { |
pm := PropertyMap{"Value": {MkProperty(0)}, "$kind": {MkPropertyNI("Pmap")}} |
So(ds.Put(pm), ShouldBeNil) |
- So(ds.KeyForObj(pm).IntID(), ShouldEqual, 1) |
+ So(ds.KeyForObj(pm).Last().IntID, ShouldEqual, 1) |
}) |
Convey("[]P (map)", func() { |
@@ -460,7 +423,7 @@ func TestPut(t *testing.T) { |
"Value": {MkProperty(i)}, |
} |
if i == 4 { |
- pms[i].SetMeta("id", int64(200)) |
+ So(pms[i].SetMeta("id", int64(200)), ShouldBeNil) |
} |
} |
So(ds.PutMulti(pms), ShouldBeNil) |
@@ -469,7 +432,7 @@ func TestPut(t *testing.T) { |
if i == 4 { |
expect = 200 |
} |
- So(ds.KeyForObj(pm).String(), ShouldEqual, fmt.Sprintf("/Pmap,%d", expect)) |
+ So(ds.KeyForObj(pm).String(), ShouldEqual, fmt.Sprintf("s~aid:ns:/Pmap,%d", expect)) |
} |
}) |
@@ -499,7 +462,7 @@ func TestPut(t *testing.T) { |
"Value": {MkProperty(i)}, |
} |
if i == 4 { |
- pms[i].SetMeta("id", int64(200)) |
+ So(pms[i].SetMeta("id", int64(200)), ShouldBeNil) |
} |
} |
So(ds.PutMulti(pms), ShouldBeNil) |
@@ -508,7 +471,7 @@ func TestPut(t *testing.T) { |
if i == 4 { |
expect = 200 |
} |
- So(ds.KeyForObj(*pm).String(), ShouldEqual, fmt.Sprintf("/Pmap,%d", expect)) |
+ So(ds.KeyForObj(*pm).String(), ShouldEqual, fmt.Sprintf("s~aid:ns:/Pmap,%d", expect)) |
} |
}) |
@@ -528,9 +491,9 @@ func TestPut(t *testing.T) { |
fpls := ifs[i].(*FakePLS) |
So(fpls.IntID, ShouldEqual, 2) |
case 2: |
- So(ds.KeyForObj(ifs[i].(PropertyMap)).String(), ShouldEqual, "/Pmap,3") |
+ So(ds.KeyForObj(ifs[i].(PropertyMap)).String(), ShouldEqual, "s~aid:ns:/Pmap,3") |
case 3: |
- So(ds.KeyForObj(*ifs[i].(*PropertyMap)).String(), ShouldEqual, "/Pmap,4") |
+ So(ds.KeyForObj(*ifs[i].(*PropertyMap)).String(), ShouldEqual, "s~aid:ns:/Pmap,4") |
} |
} |
}) |
@@ -551,23 +514,23 @@ func TestDelete(t *testing.T) { |
Convey("bad", func() { |
Convey("get single error for RPC failure", func() { |
- keys := []Key{ |
- mkKey("s~aid", "ns", "FailAll", 1, nil), |
- mkKey("s~aid", "ns", "Ok", 1, nil), |
+ keys := []*Key{ |
+ MakeKey("s~aid", "ns", "FailAll", 1), |
+ MakeKey("s~aid", "ns", "Ok", 1), |
} |
So(ds.DeleteMulti(keys).Error(), ShouldEqual, "DeleteMulti fail all") |
}) |
Convey("get multi error for individual failure", func() { |
- keys := []Key{ |
- ds.NewKey("Ok", "", 1, nil), |
- ds.NewKey("Fail", "", 2, nil), |
+ keys := []*Key{ |
+ ds.MakeKey("Ok", 1), |
+ ds.MakeKey("Fail", 2), |
} |
So(ds.DeleteMulti(keys).Error(), ShouldEqual, "DeleteMulti fail") |
}) |
Convey("get single error when deleting a single", func() { |
- k := ds.NewKey("Fail", "", 1, nil) |
+ k := ds.MakeKey("Fail", 1) |
So(ds.Delete(k).Error(), ShouldEqual, "DeleteMulti fail") |
}) |
}) |
@@ -628,7 +591,7 @@ func TestGet(t *testing.T) { |
Convey("Raw access too", func() { |
rds := ds.Raw() |
- keys := []Key{rds.NewKey("Kind", "", 1, nil)} |
+ keys := []*Key{ds.MakeKey("Kind", 1)} |
So(rds.GetMulti(keys, nil, func(pm PropertyMap, err error) { |
So(err, ShouldBeNil) |
So(pm["Value"][0].Value(), ShouldEqual, 1) |
@@ -648,7 +611,7 @@ func TestGetAll(t *testing.T) { |
ds := Get(c) |
So(ds, ShouldNotBeNil) |
- q := ds.NewQuery("").Limit(5) |
+ q := NewQuery("").Limit(5) |
Convey("bad", func() { |
Convey("nil target", func() { |
@@ -709,7 +672,7 @@ func TestGetAll(t *testing.T) { |
for i, o := range output { |
k, err := o.GetMeta("key") |
So(err, ShouldBeNil) |
- So(k.(Key).IntID(), ShouldEqual, i+1) |
+ So(k.(*Key).Last().IntID, ShouldEqual, i+1) |
So(o["Value"][0].Value().(int64), ShouldEqual, i) |
} |
}) |
@@ -733,17 +696,17 @@ func TestGetAll(t *testing.T) { |
o := *op |
k, err := o.GetMeta("key") |
So(err, ShouldBeNil) |
- So(k.(Key).IntID(), ShouldEqual, i+1) |
+ So(k.(*Key).Last().IntID, ShouldEqual, i+1) |
So(o["Value"][0].Value().(int64), ShouldEqual, i) |
} |
}) |
- Convey("*[]Key", func() { |
- output := []Key(nil) |
+ Convey("*[]*Key", func() { |
+ output := []*Key(nil) |
So(ds.GetAll(q, &output), ShouldBeNil) |
So(len(output), ShouldEqual, 5) |
for i, k := range output { |
- So(k.IntID(), ShouldEqual, i+1) |
+ So(k.Last().IntID, ShouldEqual, i+1) |
} |
}) |
@@ -760,7 +723,7 @@ func TestRun(t *testing.T) { |
ds := Get(c) |
So(ds, ShouldNotBeNil) |
- q := ds.NewQuery("").Limit(5) |
+ q := NewQuery("kind").Limit(5) |
Convey("bad", func() { |
assertBadTypePanics := func(cb interface{}) { |
@@ -770,7 +733,7 @@ func TestRun(t *testing.T) { |
So(err.Error(), ShouldContainSubstring, |
"cb does not match the required callback signature") |
}() |
- ds.Run(q, cb) |
+ So(ds.Run(q, cb), ShouldBeNil) |
} |
Convey("not a function", func() { |
@@ -802,12 +765,12 @@ func TestRun(t *testing.T) { |
}) |
Convey("early abort on error", func() { |
- rq := q.(*fakeQuery).Fail(3) |
+ q = q.Eq("$err_single", "Query fail").Eq("$err_single_idx", 3) |
i := 0 |
- So(ds.Run(rq, func(c CommonStruct, _ CursorCB) bool { |
+ So(ds.Run(q, func(c CommonStruct, _ CursorCB) bool { |
i++ |
return true |
- }).Error(), ShouldEqual, "Query fail") |
+ }), ShouldErrLike, "Query fail") |
So(i, ShouldEqual, 3) |
}) |
@@ -849,7 +812,7 @@ func TestRun(t *testing.T) { |
So(ds.Run(q, func(pm *PropertyMap, _ CursorCB) bool { |
k, err := pm.GetMeta("key") |
So(err, ShouldBeNil) |
- So(k.(Key).IntID(), ShouldEqual, i+1) |
+ So(k.(*Key).Last().IntID, ShouldEqual, i+1) |
So((*pm)["Value"][0].Value(), ShouldEqual, i) |
i++ |
return true |
@@ -882,7 +845,7 @@ func TestRun(t *testing.T) { |
So(ds.Run(q, func(pm PropertyMap, _ CursorCB) bool { |
k, err := pm.GetMeta("key") |
So(err, ShouldBeNil) |
- So(k.(Key).IntID(), ShouldEqual, i+1) |
+ So(k.(*Key).Last().IntID, ShouldEqual, i+1) |
So(pm["Value"][0].Value(), ShouldEqual, i) |
i++ |
return true |
@@ -891,8 +854,8 @@ func TestRun(t *testing.T) { |
Convey("Key", func() { |
i := 0 |
- So(ds.Run(q, func(k Key, _ CursorCB) bool { |
- So(k.IntID(), ShouldEqual, i+1) |
+ So(ds.Run(q, func(k *Key, _ CursorCB) bool { |
+ So(k.Last().IntID, ShouldEqual, i+1) |
i++ |
return true |
}), ShouldBeNil) |