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

Side by Side Diff: impl/memory/raw_datastore_test.go

Issue 1259593005: Add 'user friendly' datastore API. (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: 100% coverage of new code Created 5 years, 4 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 unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package memory 5 package memory
6 6
7 import ( 7 import (
8 "fmt" 8 "fmt"
9 "math" 9 "math"
10 "testing" 10 "testing"
11 11
12 » rdsS "github.com/luci/gae/service/rawdatastore" 12 » dsS "github.com/luci/gae/service/datastore"
13 » infoS "github.com/luci/gae/service/info"
13 . "github.com/smartystreets/goconvey/convey" 14 . "github.com/smartystreets/goconvey/convey"
14 "golang.org/x/net/context" 15 "golang.org/x/net/context"
15 ) 16 )
16 17
17 func TestDatastoreKinder(t *testing.T) { 18 func TestDatastoreKinder(t *testing.T) {
18 t.Parallel() 19 t.Parallel()
19 20
20 Convey("Datastore keys", t, func() { 21 Convey("Datastore keys", t, func() {
21 c := Use(context.Background()) 22 c := Use(context.Background())
22 » » rds := rdsS.Get(c) 23 » » ds := dsS.Get(c)
23 » » So(rds, ShouldNotBeNil) 24 » » So(ds, ShouldNotBeNil)
24 25
25 Convey("implements DSNewKeyer", func() { 26 Convey("implements DSNewKeyer", func() {
26 Convey("NewKey", func() { 27 Convey("NewKey", func() {
27 » » » » key := rds.NewKey("nerd", "stringID", 0, nil) 28 » » » » key := ds.NewKey("nerd", "stringID", 0, nil)
28 So(key, ShouldNotBeNil) 29 So(key, ShouldNotBeNil)
29 So(key.Kind(), ShouldEqual, "nerd") 30 So(key.Kind(), ShouldEqual, "nerd")
30 So(key.StringID(), ShouldEqual, "stringID") 31 So(key.StringID(), ShouldEqual, "stringID")
31 So(key.IntID(), ShouldEqual, 0) 32 So(key.IntID(), ShouldEqual, 0)
32 So(key.Parent(), ShouldBeNil) 33 So(key.Parent(), ShouldBeNil)
33 So(key.AppID(), ShouldEqual, "dev~app") 34 So(key.AppID(), ShouldEqual, "dev~app")
34 So(key.Namespace(), ShouldEqual, "") 35 So(key.Namespace(), ShouldEqual, "")
35 So(key.String(), ShouldEqual, "/nerd,stringID") 36 So(key.String(), ShouldEqual, "/nerd,stringID")
36 » » » » So(rdsS.KeyIncomplete(key), ShouldBeFalse) 37 » » » » So(dsS.KeyIncomplete(key), ShouldBeFalse)
37 » » » » So(rdsS.KeyValid(key, false, "dev~app", ""), Sho uldBeTrue) 38 » » » » So(dsS.KeyValid(key, false, "dev~app", ""), Shou ldBeTrue)
38 }) 39 })
39 }) 40 })
40 41
41 }) 42 })
42 } 43 }
43 44
44 func testGetMeta(c context.Context, k rdsS.Key) int64 { 45 type MetaGroup struct {
45 » rds := rdsS.Get(c) 46 » _id int64 `gae:"$id,1"`
46 » retval := int64(0) 47 » _kind string `gae:"$kind,__entity_group__"`
47 » err := rds.GetMulti([]rdsS.Key{rds.NewKey("__entity_group__", "", 1, rds S.KeyRoot(k))}, func(val rdsS.PropertyMap, err error) { 48 » Parent dsS.Key `gae:"$parent"`
48 » » if err != nil { 49
49 » » » panic(err) 50 » Version int64 `gae:"__version__"`
50 » » } 51 }
51 » » retval = val["__version__"][0].Value().(int64) 52
52 » }) 53 func testGetMeta(c context.Context, k dsS.Key) int64 {
53 » if err != nil { 54 » ds := dsS.Get(c)
55 » mg := &MetaGroup{Parent: dsS.KeyRoot(k)}
56 » if err := ds.Get(mg); err != nil {
54 panic(err) 57 panic(err)
55 } 58 }
56 » return retval 59 » return mg.Version
57 } 60 }
58 61
59 var pls = rdsS.GetPLS 62 var pls = dsS.GetPLS
63
64 type Foo struct {
65 » Id int64 `gae:"$id"`
66 » Parent dsS.Key `gae:"$parent"`
67
68 » Val int
69 }
60 70
61 func TestDatastoreSingleReadWriter(t *testing.T) { 71 func TestDatastoreSingleReadWriter(t *testing.T) {
62 t.Parallel() 72 t.Parallel()
63 73
64 getOnePM := func(rds rdsS.Interface, key rdsS.Key) (pmap rdsS.PropertyMa p, err error) {
65 blankErr := rds.GetMulti([]rdsS.Key{key}, func(itmPmap rdsS.Prop ertyMap, itmErr error) {
66 pmap = itmPmap
67 err = itmErr
68 })
69 So(blankErr, ShouldBeNil)
70 return
71 }
72
73 delOneErr := func(rds rdsS.Interface, key rdsS.Key) (err error) {
74 blankErr := rds.DeleteMulti([]rdsS.Key{key}, func(itmErr error) {
75 err = itmErr
76 })
77 So(blankErr, ShouldBeNil)
78 return
79 }
80
81 delOne := func(rds rdsS.Interface, key rdsS.Key) {
82 So(delOneErr(rds, key), ShouldBeNil)
83 }
84
85 getOne := func(rds rdsS.Interface, key rdsS.Key, dst interface{}) {
86 pm, err := getOnePM(rds, key)
87 So(err, ShouldBeNil)
88 So(pls(dst).Load(pm), ShouldBeNil)
89 }
90
91 putOneErr := func(rds rdsS.Interface, key rdsS.Key, val interface{}) (re tKey rdsS.Key, err error) {
92 blankErr := rds.PutMulti([]rdsS.Key{key}, []rdsS.PropertyLoadSav er{pls(val)}, func(itmKey rdsS.Key, itmErr error) {
93 err = itmErr
94 retKey = itmKey
95 })
96 So(blankErr, ShouldBeNil)
97 return
98 }
99
100 putOne := func(rds rdsS.Interface, key rdsS.Key, val interface{}) (retKe y rdsS.Key) {
101 key, err := putOneErr(rds, key, val)
102 So(err, ShouldBeNil)
103 return key
104 }
105
106 Convey("Datastore single reads and writes", t, func() { 74 Convey("Datastore single reads and writes", t, func() {
107 c := Use(context.Background()) 75 c := Use(context.Background())
108 » » rds := rdsS.Get(c) 76 » » ds := dsS.Get(c)
109 » » So(rds, ShouldNotBeNil) 77 » » So(ds, ShouldNotBeNil)
110 78
111 » » Convey("implements DSSingleReadWriter", func() { 79 » » Convey("getting objects that DNE is an error", func() {
112 » » » type Foo struct { 80 » » » So(ds.Get(&Foo{Id: 1}), ShouldEqual, dsS.ErrNoSuchEntity )
113 » » » » Val int 81 » » })
114 » » » } 82
115 83 » » Convey("bad namespaces fail", func() {
116 » » » Convey("getting objects that DNE is an error", func() { 84 » » » _, err := infoS.Get(c).Namespace("$$blzyall")
117 » » » » _, err := getOnePM(rds, rds.NewKey("Foo", "", 1, nil)) 85 » » » So(err.Error(), ShouldContainSubstring, "namespace \"$$b lzyall\" does not match")
118 » » » » So(err, ShouldEqual, rdsS.ErrNoSuchEntity) 86 » » })
119 » » » }) 87
120 88 » » Convey("Can Put stuff", func() {
121 » » » Convey("Can Put stuff", func() { 89 » » » // with an incomplete key!
122 » » » » // with an incomplete key! 90 » » » f := &Foo{Val: 10}
123 » » » » k := rds.NewKey("Foo", "", 0, nil) 91 » » » So(ds.Put(f), ShouldBeNil)
124 » » » » f := &Foo{Val: 10} 92 » » » k := ds.KeyForObj(f)
125 » » » » k = putOne(rds, k, f) 93 » » » So(k.String(), ShouldEqual, "/Foo,1")
126 » » » » So(k.String(), ShouldEqual, "/Foo,1") 94
127 95 » » » Convey("and Get it back", func() {
128 » » » » Convey("and Get it back", func() { 96 » » » » newFoo := &Foo{Id: 1}
129 » » » » » newFoo := &Foo{} 97 » » » » So(ds.Get(newFoo), ShouldBeNil)
130 » » » » » getOne(rds, k, newFoo) 98 » » » » So(newFoo, ShouldResemble, f)
131 » » » » » So(newFoo, ShouldResemble, f) 99
132 100 » » » » Convey("but it's hidden from a different namespa ce", func() {
133 » » » » » Convey("and we can Delete it", func() { 101 » » » » » c, err := infoS.Get(c).Namespace("whomba t")
134 » » » » » » delOne(rds, k) 102 » » » » » So(err, ShouldBeNil)
135 » » » » » » _, err := getOnePM(rds, k) 103 » » » » » ds = dsS.Get(c)
136 » » » » » » So(err, ShouldEqual, rdsS.ErrNoS uchEntity) 104 » » » » » So(ds.Get(f), ShouldEqual, dsS.ErrNoSuch Entity)
137 » » » » » }) 105 » » » » })
138 » » » » }) 106
139 » » » » Convey("Deleteing with a bogus key is bad", func () { 107 » » » » Convey("and we can Delete it", func() {
140 » » » » » So(delOneErr(rds, rds.NewKey("Foo", "wat ", 100, nil)), ShouldEqual, rdsS.ErrInvalidKey) 108 » » » » » So(ds.Delete(k), ShouldBeNil)
141 » » » » }) 109 » » » » » So(ds.Get(newFoo), ShouldEqual, dsS.ErrN oSuchEntity)
142 » » » » Convey("Deleteing a DNE entity is fine", func() { 110 » » » » })
143 » » » » » delOne(rds, rds.NewKey("Foo", "wat", 0, nil)) 111
144 » » » » }) 112 » » » })
145 113 » » » Convey("Deleteing with a bogus key is bad", func() {
146 » » » » Convey("with multiple puts", func() { 114 » » » » So(ds.Delete(ds.NewKey("Foo", "wat", 100, nil)), ShouldEqual, dsS.ErrInvalidKey)
147 » » » » » So(testGetMeta(c, k), ShouldEqual, 1) 115 » » » })
148 116 » » » Convey("Deleteing a DNE entity is fine", func() {
149 » » » » » keys := []rdsS.Key{} 117 » » » » So(ds.Delete(ds.NewKey("Foo", "wat", 0, nil)), S houldBeNil)
150 » » » » » vals := []rdsS.PropertyLoadSaver{} 118 » » » })
151 119
152 » » » » » pkey := k 120 » » » Convey("with multiple puts", func() {
153 » » » » » for i := 0; i < 10; i++ { 121 » » » » So(testGetMeta(c, k), ShouldEqual, 1)
154 » » » » » » keys = append(keys, rds.NewKey(" Foo", "", 0, pkey)) 122
155 » » » » » » vals = append(vals, pls(&Foo{Val : 10})) 123 » » » » foos := make([]Foo, 10)
124 » » » » for i := range foos {
125 » » » » » foos[i].Val = 10
126 » » » » » foos[i].Parent = k
127 » » » » }
128 » » » » So(ds.PutMulti(foos), ShouldBeNil)
129 » » » » So(testGetMeta(c, k), ShouldEqual, 11)
130
131 » » » » keys := make([]dsS.Key, len(foos))
132 » » » » for i, f := range foos {
133 » » » » » keys[i] = ds.KeyForObj(&f)
134 » » » » }
135
136 » » » » Convey("ensure that group versions persist acros s deletes", func() {
137 » » » » » So(ds.DeleteMulti(append(keys, k)), Shou ldBeNil)
138
139 » » » » » // TODO(riannucci): replace with a Count query instead of this cast
140 » » » » » /*
141 » » » » » » ents := ds.(*dsImpl).data.store. GetCollection("ents:")
142 » » » » » » num, _ := ents.GetTotals()
143 » » » » » » // /__entity_root_ids__,Foo
144 » » » » » » // /Foo,1/__entity_group__,1
145 » » » » » » // /Foo,1/__entity_group_ids__,1
146 » » » » » » So(num, ShouldEqual, 3)
147 » » » » » */
148
149 » » » » » So(testGetMeta(c, k), ShouldEqual, 22)
150
151 » » » » » So(ds.Put(&Foo{Id: 1}), ShouldBeNil)
152 » » » » » So(testGetMeta(c, k), ShouldEqual, 23)
153 » » » » })
154
155 » » » » Convey("can Get", func() {
156 » » » » » vals := make([]dsS.PropertyMap, len(keys ))
157 » » » » » for i := range vals {
158 » » » » » » vals[i] = dsS.PropertyMap{}
159 » » » » » » vals[i].SetMeta("key", keys[i])
156 } 160 }
157 » » » » » i := 0 161 » » » » » So(ds.GetMulti(vals), ShouldBeNil)
158 » » » » » err := rds.PutMulti(keys, vals, func(k r dsS.Key, err error) { 162
159 » » » » » » So(err, ShouldBeNil) 163 » » » » » for i, val := range vals {
160 » » » » » » keys[i] = k 164 » » » » » » So(val, ShouldResemble, dsS.Prop ertyMap{
161 » » » » » » i++ 165 » » » » » » » "Val": {dsS.MkProperty( 10)},
162 » » » » » }) 166 » » » » » » » "$key": {dsS.MkPropertyN I(keys[i])},
163 » » » » » So(err, ShouldBeNil)
164 » » » » » So(testGetMeta(c, k), ShouldEqual, 11)
165
166 » » » » » Convey("ensure that group versions persi st across deletes", func() {
167 » » » » » » keys = append(keys, pkey)
168 » » » » » » err := rds.DeleteMulti(keys, fun c(err error) {
169 » » » » » » » So(err, ShouldBeNil)
170 }) 167 })
171 » » » » » » So(err, ShouldBeNil) 168 » » » » » }
172 169 » » » » })
173 » » » » » » // TODO(riannucci): replace with a Count query instead of this cast 170
174 » » » » » » /*
175 » » » » » » » ents := rds.(*dsImpl).da ta.store.GetCollection("ents:")
176 » » » » » » » num, _ := ents.GetTotals ()
177 » » » » » » » // /__entity_root_ids__, Foo
178 » » » » » » » // /Foo,1/__entity_group __,1
179 » » » » » » » // /Foo,1/__entity_group _ids__,1
180 » » » » » » » So(num, ShouldEqual, 3)
181 » » » » » » */
182
183 » » » » » » So(testGetMeta(c, k), ShouldEqua l, 22)
184
185 » » » » » » putOne(rds, k, f)
186 » » » » » » So(testGetMeta(c, k), ShouldEqua l, 23)
187 » » » » » })
188
189 » » » » » Convey("can Get", func() {
190 » » » » » » vals := []rdsS.PropertyMap{}
191 » » » » » » err := rds.GetMulti(keys, func(p m rdsS.PropertyMap, err error) {
192 » » » » » » » So(err, ShouldBeNil)
193 » » » » » » » vals = append(vals, pm)
194 » » » » » » })
195 » » » » » » So(err, ShouldBeNil)
196
197 » » » » » » for _, val := range vals {
198 » » » » » » » So(val, ShouldResemble, rdsS.PropertyMap{"Val": {rdsS.MkProperty(10)}})
199 » » » » » » }
200 » » » » » })
201 » » » » })
202 }) 171 })
203 }) 172 })
204 173
205 Convey("implements DSTransactioner", func() { 174 Convey("implements DSTransactioner", func() {
206 type Foo struct {
207 Val int
208 }
209 Convey("Put", func() { 175 Convey("Put", func() {
210 f := &Foo{Val: 10} 176 f := &Foo{Val: 10}
211 » » » » origKey := rds.NewKey("Foo", "", 0, nil) 177 » » » » So(ds.Put(f), ShouldBeNil)
212 » » » » k := putOne(rds, origKey, f) 178 » » » » k := ds.KeyForObj(f)
213 So(k.String(), ShouldEqual, "/Foo,1") 179 So(k.String(), ShouldEqual, "/Foo,1")
214 180
215 Convey("can Put new entity groups", func() { 181 Convey("can Put new entity groups", func() {
216 » » » » » err := rds.RunInTransaction(func(c conte xt.Context) error { 182 » » » » » err := ds.RunInTransaction(func(c contex t.Context) error {
217 » » » » » » rds := rdsS.Get(c) 183 » » » » » » ds := dsS.Get(c)
218 184
219 » » » » » » f1 := &Foo{Val: 100} 185 » » » » » » f := &Foo{Val: 100}
220 » » » » » » k := putOne(rds, origKey, f1) 186 » » » » » » So(ds.Put(f), ShouldBeNil)
221 » » » » » » So(k.String(), ShouldEqual, "/Fo o,2") 187 » » » » » » So(f.Id, ShouldEqual, 2)
222 188
223 » » » » » » f2 := &Foo{Val: 200} 189 » » » » » » f.Id = 0
224 » » » » » » k = putOne(rds, origKey, f2) 190 » » » » » » f.Val = 200
225 » » » » » » So(k.String(), ShouldEqual, "/Fo o,3") 191 » » » » » » So(ds.Put(f), ShouldBeNil)
226 192 » » » » » » So(f.Id, ShouldEqual, 3)
227 » » » » » » return nil 193
228 » » » » » }, &rdsS.TransactionOptions{XG: true}) 194 » » » » » » return nil
229 » » » » » So(err, ShouldBeNil) 195 » » » » » }, &dsS.TransactionOptions{XG: true})
230 196 » » » » » So(err, ShouldBeNil)
231 » » » » » f := &Foo{} 197
232 » » » » » getOne(rds, rds.NewKey("Foo", "", 2, nil ), f) 198 » » » » » f := &Foo{Id: 2}
199 » » » » » So(ds.Get(f), ShouldBeNil)
233 So(f.Val, ShouldEqual, 100) 200 So(f.Val, ShouldEqual, 100)
234 201
235 » » » » » getOne(rds, rds.NewKey("Foo", "", 3, nil ), f) 202 » » » » » f.Id = 3
203 » » » » » So(ds.Get(f), ShouldBeNil)
236 So(f.Val, ShouldEqual, 200) 204 So(f.Val, ShouldEqual, 200)
237 }) 205 })
238 206
239 Convey("can Put new entities in a current group" , func() { 207 Convey("can Put new entities in a current group" , func() {
240 » » » » » par := k 208 » » » » » err := ds.RunInTransaction(func(c contex t.Context) error {
241 » » » » » err := rds.RunInTransaction(func(c conte xt.Context) error { 209 » » » » » » ds := dsS.Get(c)
242 » » » » » » rds := rdsS.Get(c) 210
243 » » » » » » So(rds, ShouldNotBeNil) 211 » » » » » » f := &Foo{Val: 100, Parent: k}
244 212 » » » » » » So(ds.Put(f), ShouldBeNil)
245 » » » » » » f1 := &Foo{Val: 100} 213 » » » » » » So(ds.KeyForObj(f).String(), Sho uldEqual, "/Foo,1/Foo,1")
246 » » » » » » k := putOne(rds, rds.NewKey("Foo ", "", 0, par), f1) 214
247 » » » » » » So(k.String(), ShouldEqual, "/Fo o,1/Foo,1") 215 » » » » » » f.Id = 0
248 216 » » » » » » f.Val = 200
249 » » » » » » f2 := &Foo{Val: 200} 217 » » » » » » So(ds.Put(f), ShouldBeNil)
250 » » » » » » k = putOne(rds, rds.NewKey("Foo" , "", 0, par), f2) 218 » » » » » » So(ds.KeyForObj(f).String(), Sho uldEqual, "/Foo,1/Foo,2")
251 » » » » » » So(k.String(), ShouldEqual, "/Fo o,1/Foo,2") 219
252 220 » » » » » » return nil
253 » » » » » » return nil 221 » » » » » }, nil)
254 » » » » » }, nil) 222 » » » » » So(err, ShouldBeNil)
255 » » » » » So(err, ShouldBeNil) 223
256 224 » » » » » f := &Foo{Id: 1, Parent: k}
257 » » » » » f := &Foo{} 225 » » » » » So(ds.Get(f), ShouldBeNil)
258 » » » » » getOne(rds, rds.NewKey("Foo", "", 1, k), f)
259 So(f.Val, ShouldEqual, 100) 226 So(f.Val, ShouldEqual, 100)
260 227
261 » » » » » getOne(rds, rds.NewKey("Foo", "", 2, k), f) 228 » » » » » f.Id = 2
229 » » » » » So(ds.Get(f), ShouldBeNil)
262 So(f.Val, ShouldEqual, 200) 230 So(f.Val, ShouldEqual, 200)
263 }) 231 })
264 232
265 Convey("Deletes work too", func() { 233 Convey("Deletes work too", func() {
266 » » » » » err := rds.RunInTransaction(func(c conte xt.Context) error { 234 » » » » » err := ds.RunInTransaction(func(c contex t.Context) error {
267 » » » » » » rds := rdsS.Get(c) 235 » » » » » » return dsS.Get(c).Delete(k)
268 » » » » » » So(rds, ShouldNotBeNil) 236 » » » » » }, nil)
269 » » » » » » delOne(rds, k) 237 » » » » » So(err, ShouldBeNil)
270 » » » » » » return nil 238 » » » » » So(ds.Get(&Foo{Id: 1}), ShouldEqual, dsS .ErrNoSuchEntity)
271 » » » » » }, nil)
272 » » » » » So(err, ShouldBeNil)
273 » » » » » _, err = getOnePM(rds, k)
274 » » » » » So(err, ShouldEqual, rdsS.ErrNoSuchEntit y)
275 }) 239 })
276 240
277 Convey("A Get counts against your group count", func() { 241 Convey("A Get counts against your group count", func() {
278 » » » » » err := rds.RunInTransaction(func(c conte xt.Context) error { 242 » » » » » err := ds.RunInTransaction(func(c contex t.Context) error {
279 » » » » » » rds := rdsS.Get(c) 243 » » » » » » ds := dsS.Get(c)
280 244
281 » » » » » » _, err := getOnePM(rds, rds.NewK ey("Foo", "", 20, nil)) 245 » » » » » » pm := dsS.PropertyMap{}
282 » » » » » » So(err, ShouldEqual, rdsS.ErrNoS uchEntity) 246 » » » » » » pm.SetMeta("key", ds.NewKey("Foo ", "", 20, nil))
283 247 » » » » » » So(ds.Get(pm), ShouldEqual, dsS. ErrNoSuchEntity)
284 » » » » » » err = rds.GetMulti([]rdsS.Key{k} , func(_ rdsS.PropertyMap, err error) { 248
285 » » » » » » » So(err, ShouldBeNil) 249 » » » » » » pm.SetMeta("key", k)
286 » » » » » » }) 250 » » » » » » So(ds.Get(pm).Error(), ShouldCon tainSubstring, "cross-group")
287 » » » » » » So(err.Error(), ShouldContainSub string, "cross-group")
288 return nil 251 return nil
289 }, nil) 252 }, nil)
290 So(err, ShouldBeNil) 253 So(err, ShouldBeNil)
291 }) 254 })
292 255
293 Convey("Get takes a snapshot", func() { 256 Convey("Get takes a snapshot", func() {
294 » » » » » err := rds.RunInTransaction(func(c conte xt.Context) error { 257 » » » » » err := ds.RunInTransaction(func(c contex t.Context) error {
295 » » » » » » txnDS := rdsS.Get(c) 258 » » » » » » txnDS := dsS.Get(c)
296 » » » » » » So(txnDS, ShouldNotBeNil) 259
297 260 » » » » » » So(txnDS.Get(f), ShouldBeNil)
298 » » » » » » getOne(txnDS, k, f)
299 So(f.Val, ShouldEqual, 10) 261 So(f.Val, ShouldEqual, 10)
300 262
301 // Don't ever do this in a real program unless you want to guarantee 263 // Don't ever do this in a real program unless you want to guarantee
302 // a failed transaction :) 264 // a failed transaction :)
303 f.Val = 11 265 f.Val = 11
304 » » » » » » putOne(rds, k, f) 266 » » » » » » So(ds.Put(f), ShouldBeNil)
305 267
306 » » » » » » getOne(txnDS, k, f) 268 » » » » » » So(txnDS.Get(f), ShouldBeNil)
307 » » » » » » So(f.Val, ShouldEqual, 10) 269 » » » » » » So(f.Val, ShouldEqual, 10)
308 270
309 » » » » » » return nil 271 » » » » » » return nil
310 » » » » » }, nil) 272 » » » » » }, nil)
311 » » » » » So(err, ShouldBeNil) 273 » » » » » So(err, ShouldBeNil)
312 274
313 » » » » » f := &Foo{} 275 » » » » » f := &Foo{Id: 1}
314 » » » » » getOne(rds, k, f) 276 » » » » » So(ds.Get(f), ShouldBeNil)
315 So(f.Val, ShouldEqual, 11) 277 So(f.Val, ShouldEqual, 11)
316 }) 278 })
317 279
318 Convey("and snapshots are consistent even after Puts", func() { 280 Convey("and snapshots are consistent even after Puts", func() {
319 » » » » » err := rds.RunInTransaction(func(c conte xt.Context) error { 281 » » » » » err := ds.RunInTransaction(func(c contex t.Context) error {
320 » » » » » » txnDS := rdsS.Get(c) 282 » » » » » » txnDS := dsS.Get(c)
321 » » » » » » So(txnDS, ShouldNotBeNil) 283
322 284 » » » » » » f := &Foo{Id: 1}
323 » » » » » » f := &Foo{} 285 » » » » » » So(txnDS.Get(f), ShouldBeNil)
324 » » » » » » getOne(txnDS, k, f)
325 So(f.Val, ShouldEqual, 10) 286 So(f.Val, ShouldEqual, 10)
326 287
327 // Don't ever do this in a real program unless you want to guarantee 288 // Don't ever do this in a real program unless you want to guarantee
328 // a failed transaction :) 289 // a failed transaction :)
329 f.Val = 11 290 f.Val = 11
330 » » » » » » putOne(rds, k, f) 291 » » » » » » So(ds.Put(f), ShouldBeNil)
331 292
332 » » » » » » getOne(txnDS, k, f) 293 » » » » » » So(txnDS.Get(f), ShouldBeNil)
333 So(f.Val, ShouldEqual, 10) 294 So(f.Val, ShouldEqual, 10)
334 295
335 f.Val = 20 296 f.Val = 20
336 » » » » » » putOne(txnDS, k, f) 297 » » » » » » So(txnDS.Put(f), ShouldBeNil)
337 298
338 » » » » » » getOne(txnDS, k, f) 299 » » » » » » So(txnDS.Get(f), ShouldBeNil)
339 So(f.Val, ShouldEqual, 10) // st ill gets 10 300 So(f.Val, ShouldEqual, 10) // st ill gets 10
340 301
341 return nil 302 return nil
342 }, nil) 303 }, nil)
343 So(err.Error(), ShouldContainSubstring, "concurrent") 304 So(err.Error(), ShouldContainSubstring, "concurrent")
344 305
345 » » » » » f := &Foo{} 306 » » » » » f := &Foo{Id: 1}
346 » » » » » getOne(rds, k, f) 307 » » » » » So(ds.Get(f), ShouldBeNil)
347 So(f.Val, ShouldEqual, 11) 308 So(f.Val, ShouldEqual, 11)
348 }) 309 })
349 310
350 Convey("Reusing a transaction context is bad new s", func() { 311 Convey("Reusing a transaction context is bad new s", func() {
351 » » » » » k := rds.NewKey("Foo", "", 1, nil) 312 » » » » » txnDS := dsS.Interface(nil)
352 » » » » » txnDS := rdsS.Interface(nil) 313 » » » » » err := ds.RunInTransaction(func(c contex t.Context) error {
353 » » » » » err := rds.RunInTransaction(func(c conte xt.Context) error { 314 » » » » » » txnDS = dsS.Get(c)
354 » » » » » » txnDS = rdsS.Get(c) 315 » » » » » » So(txnDS.Get(f), ShouldBeNil)
355 » » » » » » getOnePM(txnDS, k) 316 » » » » » » return nil
356 » » » » » » return nil 317 » » » » » }, nil)
357 » » » » » }, nil) 318 » » » » » So(err, ShouldBeNil)
358 » » » » » So(err, ShouldBeNil) 319 » » » » » So(txnDS.Get(f).Error(), ShouldContainSu bstring, "expired")
359 » » » » » err = txnDS.GetMulti([]rdsS.Key{k}, func (_ rdsS.PropertyMap, err error) {
360 » » » » » » So(err, ShouldBeNil)
361 » » » » » })
362 » » » » » So(err.Error(), ShouldContainSubstring, "expired")
363 }) 320 })
364 321
365 Convey("Nested transactions are rejected", func( ) { 322 Convey("Nested transactions are rejected", func( ) {
366 » » » » » err := rds.RunInTransaction(func(c conte xt.Context) error { 323 » » » » » err := ds.RunInTransaction(func(c contex t.Context) error {
367 » » » » » » err := rdsS.Get(c).RunInTransact ion(func(c context.Context) error { 324 » » » » » » err := dsS.Get(c).RunInTransacti on(func(c context.Context) error {
368 panic("noooo") 325 panic("noooo")
369 }, nil) 326 }, nil)
370 So(err.Error(), ShouldContainSub string, "nested transactions") 327 So(err.Error(), ShouldContainSub string, "nested transactions")
371 return nil 328 return nil
372 }, nil) 329 }, nil)
373 So(err, ShouldBeNil) 330 So(err, ShouldBeNil)
374 }) 331 })
375 332
376 Convey("Concurrent transactions only accept one set of changes", func() { 333 Convey("Concurrent transactions only accept one set of changes", func() {
377 // Note: I think this implementation is actually /slightly/ wrong. 334 // Note: I think this implementation is actually /slightly/ wrong.
378 // Accorting to my read of the docs for appengine, when you open a 335 // Accorting to my read of the docs for appengine, when you open a
379 // transaction it actually (essentially) holds a reference to the 336 // transaction it actually (essentially) holds a reference to the
380 // entire datastore. Our implementation takes a snapshot of the 337 // entire datastore. Our implementation takes a snapshot of the
381 // entity group as soon as something obs erves/affects it. 338 // entity group as soon as something obs erves/affects it.
382 // 339 //
383 // That said... I'm not sure if there's really a semantic difference. 340 // That said... I'm not sure if there's really a semantic difference.
384 » » » » » err := rds.RunInTransaction(func(c conte xt.Context) error { 341 » » » » » err := ds.RunInTransaction(func(c contex t.Context) error {
385 » » » » » » txnDS := rdsS.Get(c) 342 » » » » » » So(dsS.Get(c).Put(&Foo{Id: 1, Va l: 21}), ShouldBeNil)
386 » » » » » » f := &Foo{Val: 21}
387 » » » » » » putOne(txnDS, k, f)
388 343
389 » » » » » » err := rds.RunInTransaction(func (c context.Context) error { 344 » » » » » » err := ds.RunInTransaction(func( c context.Context) error {
390 » » » » » » » txnDS := rdsS.Get(c) 345 » » » » » » » So(dsS.Get(c).Put(&Foo{I d: 1, Val: 27}), ShouldBeNil)
391 » » » » » » » f := &Foo{Val: 27}
392 » » » » » » » putOne(txnDS, k, f)
393 return nil 346 return nil
394 }, nil) 347 }, nil)
395 So(err, ShouldBeNil) 348 So(err, ShouldBeNil)
396 349
397 return nil 350 return nil
398 }, nil) 351 }, nil)
399 So(err.Error(), ShouldContainSubstring, "concurrent") 352 So(err.Error(), ShouldContainSubstring, "concurrent")
400 353
401 » » » » » f := &Foo{} 354 » » » » » f := &Foo{Id: 1}
402 » » » » » getOne(rds, k, f) 355 » » » » » So(ds.Get(f), ShouldBeNil)
403 So(f.Val, ShouldEqual, 27) 356 So(f.Val, ShouldEqual, 27)
404 }) 357 })
405 358
406 Convey("XG", func() { 359 Convey("XG", func() {
407 Convey("Modifying two groups with XG=fal se is invalid", func() { 360 Convey("Modifying two groups with XG=fal se is invalid", func() {
408 » » » » » » err := rds.RunInTransaction(func (c context.Context) error { 361 » » » » » » err := ds.RunInTransaction(func( c context.Context) error {
409 » » » » » » » rds := rdsS.Get(c) 362 » » » » » » » ds := dsS.Get(c)
410 » » » » » » » f := &Foo{Val: 200} 363 » » » » » » » f := &Foo{Id: 1, Val: 20 0}
411 » » » » » » » putOne(rds, k, f) 364 » » » » » » » So(ds.Put(f), ShouldBeNi l)
412 365
413 » » » » » » » _, err := putOneErr(rds, rds.NewKey("Foo", "", 2, nil), f) 366 » » » » » » » f.Id = 2
367 » » » » » » » err := ds.Put(f)
414 So(err.Error(), ShouldCo ntainSubstring, "cross-group") 368 So(err.Error(), ShouldCo ntainSubstring, "cross-group")
415 return err 369 return err
416 }, nil) 370 }, nil)
417 So(err.Error(), ShouldContainSub string, "cross-group") 371 So(err.Error(), ShouldContainSub string, "cross-group")
418 }) 372 })
419 373
420 Convey("Modifying >25 groups with XG=tru e is invald", func() { 374 Convey("Modifying >25 groups with XG=tru e is invald", func() {
421 » » » » » » err := rds.RunInTransaction(func (c context.Context) error { 375 » » » » » » err := ds.RunInTransaction(func( c context.Context) error {
422 » » » » » » » rds := rdsS.Get(c) 376 » » » » » » » ds := dsS.Get(c)
377 » » » » » » » foos := make([]Foo, 25)
423 for i := int64(1); i < 2 6; i++ { 378 for i := int64(1); i < 2 6; i++ {
424 » » » » » » » » k := rds.NewKey( "Foo", "", i, nil) 379 » » » » » » » » foos[i-1].Id = i
425 » » » » » » » » f := &Foo{Val: 2 00} 380 » » » » » » » » foos[i-1].Val = 200
426 » » » » » » » » putOne(rds, k, f )
427 } 381 }
428 » » » » » » » f := &Foo{Val: 200} 382 » » » » » » » So(ds.PutMulti(foos), Sh ouldBeNil)
429 » » » » » » » _, err := putOneErr(rds, rds.NewKey("Foo", "", 27, nil), f) 383 » » » » » » » err := ds.Put(&Foo{Id: 2 6})
430 So(err.Error(), ShouldCo ntainSubstring, "too many entity groups") 384 So(err.Error(), ShouldCo ntainSubstring, "too many entity groups")
431 return err 385 return err
432 » » » » » » }, &rdsS.TransactionOptions{XG: true}) 386 » » » » » » }, &dsS.TransactionOptions{XG: t rue})
433 So(err.Error(), ShouldContainSub string, "too many entity groups") 387 So(err.Error(), ShouldContainSub string, "too many entity groups")
434 }) 388 })
435 }) 389 })
436 390
437 Convey("Errors and panics", func() { 391 Convey("Errors and panics", func() {
438 Convey("returning an error aborts", func () { 392 Convey("returning an error aborts", func () {
439 » » » » » » err := rds.RunInTransaction(func (c context.Context) error { 393 » » » » » » err := ds.RunInTransaction(func( c context.Context) error {
440 » » » » » » » rds := rdsS.Get(c) 394 » » » » » » » ds := dsS.Get(c)
441 » » » » » » » f := &Foo{Val: 200} 395 » » » » » » » So(ds.Put(&Foo{Id: 1, Va l: 200}), ShouldBeNil)
442 » » » » » » » putOne(rds, k, f)
443
444 return fmt.Errorf("thing y") 396 return fmt.Errorf("thing y")
445 }, nil) 397 }, nil)
446 So(err.Error(), ShouldEqual, "th ingy") 398 So(err.Error(), ShouldEqual, "th ingy")
447 399
448 » » » » » » f := &Foo{} 400 » » » » » » f := &Foo{Id: 1}
449 » » » » » » getOne(rds, k, f) 401 » » » » » » So(ds.Get(f), ShouldBeNil)
450 So(f.Val, ShouldEqual, 10) 402 So(f.Val, ShouldEqual, 10)
451 }) 403 })
452 404
453 Convey("panicing aborts", func() { 405 Convey("panicing aborts", func() {
454 So(func() { 406 So(func() {
455 » » » » » » » rds.RunInTransaction(fun c(c context.Context) error { 407 » » » » » » » ds.RunInTransaction(func (c context.Context) error {
456 » » » » » » » » rds := rdsS.Get( c) 408 » » » » » » » » ds := dsS.Get(c)
457 » » » » » » » » f := &Foo{Val: 2 00} 409 » » » » » » » » So(ds.Put(&Foo{V al: 200}), ShouldBeNil)
458 » » » » » » » » putOne(rds, k, f )
459 panic("wheeeeee" ) 410 panic("wheeeeee" )
460 }, nil) 411 }, nil)
461 }, ShouldPanic) 412 }, ShouldPanic)
462 413
463 » » » » » » f := &Foo{} 414 » » » » » » f := &Foo{Id: 1}
464 » » » » » » getOne(rds, k, f) 415 » » » » » » So(ds.Get(f), ShouldBeNil)
465 So(f.Val, ShouldEqual, 10) 416 So(f.Val, ShouldEqual, 10)
466 }) 417 })
467 }) 418 })
468 }) 419 })
469 }) 420 })
470 421
471 }) 422 })
472 } 423 }
473 424
474 const MaxUint = ^uint(0) 425 const MaxUint = ^uint(0)
475 const MaxInt = int(MaxUint >> 1) 426 const MaxInt = int(MaxUint >> 1)
476 const IntIs32Bits = int64(MaxInt) < math.MaxInt64 427 const IntIs32Bits = int64(MaxInt) < math.MaxInt64
477 428
478 func TestDatastoreQueryer(t *testing.T) { 429 func TestDatastoreQueryer(t *testing.T) {
479 Convey("Datastore Query suport", t, func() { 430 Convey("Datastore Query suport", t, func() {
480 c := Use(context.Background()) 431 c := Use(context.Background())
481 » » rds := rdsS.Get(c) 432 » » ds := dsS.Get(c)
482 » » So(rds, ShouldNotBeNil) 433 » » So(ds, ShouldNotBeNil)
483 434
484 Convey("can create good queries", func() { 435 Convey("can create good queries", func() {
485 » » » q := rds.NewQuery("Foo").KeysOnly().Limit(10).Offset(39) 436 » » » q := ds.NewQuery("Foo").KeysOnly().Limit(10).Offset(39)
486 q = q.Start(queryCursor("kosmik")).End(queryCursor("krab s")) 437 q = q.Start(queryCursor("kosmik")).End(queryCursor("krab s"))
487 So(q, ShouldNotBeNil) 438 So(q, ShouldNotBeNil)
488 So(q.(*queryImpl).err, ShouldBeNil) 439 So(q.(*queryImpl).err, ShouldBeNil)
489 qi := q.(*queryImpl).checkCorrectness("", false) 440 qi := q.(*queryImpl).checkCorrectness("", false)
490 So(qi.err, ShouldBeNil) 441 So(qi.err, ShouldBeNil)
491 }) 442 })
492 443
493 Convey("normalize ensures orders make sense", func() { 444 Convey("normalize ensures orders make sense", func() {
494 » » » q := rds.NewQuery("Cool") 445 » » » q := ds.NewQuery("Cool")
495 q = q.Filter("cat =", 19).Filter("bob =", 10).Order("bob ").Order("bob") 446 q = q.Filter("cat =", 19).Filter("bob =", 10).Order("bob ").Order("bob")
496 447
497 Convey("removes dups and equality orders", func() { 448 Convey("removes dups and equality orders", func() {
498 q = q.Order("wat") 449 q = q.Order("wat")
499 qi := q.(*queryImpl).normalize().checkCorrectnes s("", false) 450 qi := q.(*queryImpl).normalize().checkCorrectnes s("", false)
500 So(qi.err, ShouldBeNil) 451 So(qi.err, ShouldBeNil)
501 So(qi.order, ShouldResemble, []queryOrder{{"wat" , qASC}}) 452 So(qi.order, ShouldResemble, []queryOrder{{"wat" , qASC}})
502 }) 453 })
503 454
504 Convey("keeps inequality orders", func() { 455 Convey("keeps inequality orders", func() {
505 q = q.Order("wat") 456 q = q.Order("wat")
506 q := q.Filter("bob >", 10).Filter("wat <", 29) 457 q := q.Filter("bob >", 10).Filter("wat <", 29)
507 qi := q.(*queryImpl).normalize().checkCorrectnes s("", false) 458 qi := q.(*queryImpl).normalize().checkCorrectnes s("", false)
508 So(qi.order, ShouldResemble, []queryOrder{{"bob" , qASC}, {"wat", qASC}}) 459 So(qi.order, ShouldResemble, []queryOrder{{"bob" , qASC}, {"wat", qASC}})
509 So(qi.err.Error(), ShouldContainSubstring, "Only one inequality") 460 So(qi.err.Error(), ShouldContainSubstring, "Only one inequality")
510 }) 461 })
511 462
512 Convey("if we equality-filter on __key__, order is ditch ed", func() { 463 Convey("if we equality-filter on __key__, order is ditch ed", func() {
513 q = q.Order("wat") 464 q = q.Order("wat")
514 » » » » q := q.Filter("__key__ =", rds.NewKey("Foo", "wa t", 0, nil)) 465 » » » » q := q.Filter("__key__ =", ds.NewKey("Foo", "wat ", 0, nil))
515 qi := q.(*queryImpl).normalize().checkCorrectnes s("", false) 466 qi := q.(*queryImpl).normalize().checkCorrectnes s("", false)
516 So(qi.order, ShouldResemble, []queryOrder(nil)) 467 So(qi.order, ShouldResemble, []queryOrder(nil))
517 So(qi.err, ShouldBeNil) 468 So(qi.err, ShouldBeNil)
518 }) 469 })
519 470
520 Convey("if we order by key and something else, key domin ates", func() { 471 Convey("if we order by key and something else, key domin ates", func() {
521 q := q.Order("__key__").Order("wat") 472 q := q.Order("__key__").Order("wat")
522 qi := q.(*queryImpl).normalize().checkCorrectnes s("", false) 473 qi := q.(*queryImpl).normalize().checkCorrectnes s("", false)
523 So(qi.order, ShouldResemble, []queryOrder{{"__ke y__", qASC}}) 474 So(qi.order, ShouldResemble, []queryOrder{{"__ke y__", qASC}})
524 So(qi.err, ShouldBeNil) 475 So(qi.err, ShouldBeNil)
525 }) 476 })
526 }) 477 })
527 478
528 Convey("can create bad queries", func() { 479 Convey("can create bad queries", func() {
529 » » » q := rds.NewQuery("Foo") 480 » » » q := ds.NewQuery("Foo")
530 481
531 Convey("bad filter ops", func() { 482 Convey("bad filter ops", func() {
532 q := q.Filter("Bob !", "value") 483 q := q.Filter("Bob !", "value")
533 So(q.(*queryImpl).err.Error(), ShouldContainSubs tring, "invalid operator \"!\"") 484 So(q.(*queryImpl).err.Error(), ShouldContainSubs tring, "invalid operator \"!\"")
534 }) 485 })
535 Convey("bad filter", func() { 486 Convey("bad filter", func() {
536 q := q.Filter("Bob", "value") 487 q := q.Filter("Bob", "value")
537 So(q.(*queryImpl).err.Error(), ShouldContainSubs tring, "invalid filter") 488 So(q.(*queryImpl).err.Error(), ShouldContainSubs tring, "invalid filter")
538 }) 489 })
539 Convey("bad order", func() { 490 Convey("bad order", func() {
(...skipping 20 matching lines...) Expand all
560 if !IntIs32Bits { 511 if !IntIs32Bits {
561 q := q.Offset(MaxInt) 512 q := q.Offset(MaxInt)
562 So(q.(*queryImpl).err.Error(), ShouldCon tainSubstring, "query offset overflow") 513 So(q.(*queryImpl).err.Error(), ShouldCon tainSubstring, "query offset overflow")
563 } 514 }
564 }) 515 })
565 Convey("Bad cursors", func() { 516 Convey("Bad cursors", func() {
566 q := q.Start(queryCursor("")).End(queryCursor("" )) 517 q := q.Start(queryCursor("")).End(queryCursor("" ))
567 So(q.(*queryImpl).err.Error(), ShouldContainSubs tring, "invalid cursor") 518 So(q.(*queryImpl).err.Error(), ShouldContainSubs tring, "invalid cursor")
568 }) 519 })
569 Convey("Bad ancestors", func() { 520 Convey("Bad ancestors", func() {
570 » » » » q := q.Ancestor(rds.NewKey("Goop", "wat", 10, ni l)) 521 » » » » q := q.Ancestor(ds.NewKey("Goop", "wat", 10, nil ))
571 So(q, ShouldNotBeNil) 522 So(q, ShouldNotBeNil)
572 qi := q.(*queryImpl).checkCorrectness("", false) 523 qi := q.(*queryImpl).checkCorrectness("", false)
573 » » » » So(qi.err, ShouldEqual, rdsS.ErrInvalidKey) 524 » » » » So(qi.err, ShouldEqual, dsS.ErrInvalidKey)
574 }) 525 })
575 Convey("nil ancestors", func() { 526 Convey("nil ancestors", func() {
576 qi := q.Ancestor(nil).(*queryImpl).checkCorrectn ess("", false) 527 qi := q.Ancestor(nil).(*queryImpl).checkCorrectn ess("", false)
577 So(qi.err.Error(), ShouldContainSubstring, "nil query ancestor") 528 So(qi.err.Error(), ShouldContainSubstring, "nil query ancestor")
578 }) 529 })
579 Convey("Bad key filters", func() { 530 Convey("Bad key filters", func() {
580 » » » » q := q.Filter("__key__ =", rds.NewKey("Goop", "w at", 10, nil)) 531 » » » » q := q.Filter("__key__ =", ds.NewKey("Goop", "wa t", 10, nil))
581 qi := q.(*queryImpl).checkCorrectness("", false) 532 qi := q.(*queryImpl).checkCorrectness("", false)
582 » » » » So(qi.err, ShouldEqual, rdsS.ErrInvalidKey) 533 » » » » So(qi.err, ShouldEqual, dsS.ErrInvalidKey)
583 }) 534 })
584 Convey("non-ancestor queries in a transaction", func() { 535 Convey("non-ancestor queries in a transaction", func() {
585 qi := q.(*queryImpl).checkCorrectness("", true) 536 qi := q.(*queryImpl).checkCorrectness("", true)
586 So(qi.err.Error(), ShouldContainSubstring, "Only ancestor queries") 537 So(qi.err.Error(), ShouldContainSubstring, "Only ancestor queries")
587 }) 538 })
588 Convey("absurd numbers of filters are prohibited", func( ) { 539 Convey("absurd numbers of filters are prohibited", func( ) {
589 » » » » q := q.Ancestor(rds.NewKey("thing", "wat", 0, ni l)) 540 » » » » q := q.Ancestor(ds.NewKey("thing", "wat", 0, nil ))
590 for i := 0; i < 100; i++ { 541 for i := 0; i < 100; i++ {
591 q = q.Filter("something =", 10) 542 q = q.Filter("something =", 10)
592 } 543 }
593 qi := q.(*queryImpl).checkCorrectness("", false) 544 qi := q.(*queryImpl).checkCorrectness("", false)
594 So(qi.err.Error(), ShouldContainSubstring, "quer y is too large") 545 So(qi.err.Error(), ShouldContainSubstring, "quer y is too large")
595 }) 546 })
596 Convey("filters for __key__ that aren't keys", func() { 547 Convey("filters for __key__ that aren't keys", func() {
597 q := q.Filter("__key__ = ", 10) 548 q := q.Filter("__key__ = ", 10)
598 qi := q.(*queryImpl).checkCorrectness("", false) 549 qi := q.(*queryImpl).checkCorrectness("", false)
599 So(qi.err.Error(), ShouldContainSubstring, "must be a Key") 550 So(qi.err.Error(), ShouldContainSubstring, "must be a Key")
600 }) 551 })
601 Convey("multiple inequalities", func() { 552 Convey("multiple inequalities", func() {
602 q := q.Filter("bob > ", 19).Filter("charlie < ", 20) 553 q := q.Filter("bob > ", 19).Filter("charlie < ", 20)
603 qi := q.(*queryImpl).checkCorrectness("", false) 554 qi := q.(*queryImpl).checkCorrectness("", false)
604 So(qi.err.Error(), ShouldContainSubstring, "one inequality filter") 555 So(qi.err.Error(), ShouldContainSubstring, "one inequality filter")
605 }) 556 })
606 Convey("bad sort orders", func() { 557 Convey("bad sort orders", func() {
607 q := q.Filter("bob > ", 19).Order("-charlie") 558 q := q.Filter("bob > ", 19).Order("-charlie")
608 qi := q.(*queryImpl).checkCorrectness("", false) 559 qi := q.(*queryImpl).checkCorrectness("", false)
609 So(qi.err.Error(), ShouldContainSubstring, "firs t sort property") 560 So(qi.err.Error(), ShouldContainSubstring, "firs t sort property")
610 }) 561 })
611 Convey("kindless with non-__key__ filters", func() { 562 Convey("kindless with non-__key__ filters", func() {
612 » » » » q := rds.NewQuery("").Filter("face <", 25.3) 563 » » » » q := ds.NewQuery("").Filter("face <", 25.3)
613 qi := q.(*queryImpl).checkCorrectness("", false) 564 qi := q.(*queryImpl).checkCorrectness("", false)
614 So(qi.err.Error(), ShouldContainSubstring, "kind is required for non-__key__") 565 So(qi.err.Error(), ShouldContainSubstring, "kind is required for non-__key__")
615 }) 566 })
616 Convey("kindless with non-__key__ orders", func() { 567 Convey("kindless with non-__key__ orders", func() {
617 » » » » q := rds.NewQuery("").Order("face") 568 » » » » q := ds.NewQuery("").Order("face")
618 qi := q.(*queryImpl).checkCorrectness("", false) 569 qi := q.(*queryImpl).checkCorrectness("", false)
619 So(qi.err.Error(), ShouldContainSubstring, "kind is required for all orders") 570 So(qi.err.Error(), ShouldContainSubstring, "kind is required for all orders")
620 }) 571 })
621 Convey("kindless with decending-__key__ orders", func() { 572 Convey("kindless with decending-__key__ orders", func() {
622 » » » » q := rds.NewQuery("").Order("-__key__") 573 » » » » q := ds.NewQuery("").Order("-__key__")
623 qi := q.(*queryImpl).checkCorrectness("", false) 574 qi := q.(*queryImpl).checkCorrectness("", false)
624 So(qi.err.Error(), ShouldContainSubstring, "kind is required for all orders") 575 So(qi.err.Error(), ShouldContainSubstring, "kind is required for all orders")
625 }) 576 })
626 }) 577 })
627 578
628 }) 579 })
629 } 580 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698