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

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: more docs 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
« no previous file with comments | « impl/memory/raw_datastore_data.go ('k') | impl/prod/context.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 dsS "github.com/luci/gae/service/datastore" 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 ds := dsS.Get(c) 23 ds := dsS.Get(c)
(...skipping 11 matching lines...) Expand all
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(dsS.KeyIncomplete(key), ShouldBeFalse) 37 So(dsS.KeyIncomplete(key), ShouldBeFalse)
37 So(dsS.KeyValid(key, false, "dev~app", ""), Shou ldBeTrue) 38 So(dsS.KeyValid(key, false, "dev~app", ""), Shou ldBeTrue)
38 }) 39 })
39 }) 40 })
40 41
41 }) 42 })
42 } 43 }
43 44
45 type MetaGroup struct {
46 _id int64 `gae:"$id,1"`
47 _kind string `gae:"$kind,__entity_group__"`
48 Parent dsS.Key `gae:"$parent"`
49
50 Version int64 `gae:"__version__"`
51 }
52
44 func testGetMeta(c context.Context, k dsS.Key) int64 { 53 func testGetMeta(c context.Context, k dsS.Key) int64 {
45 ds := dsS.Get(c) 54 ds := dsS.Get(c)
46 » retval := int64(0) 55 » mg := &MetaGroup{Parent: dsS.KeyRoot(k)}
47 » err := ds.GetMulti([]dsS.Key{ds.NewKey("__entity_group__", "", 1, dsS.Ke yRoot(k))}, func(val dsS.PropertyMap, err error) { 56 » if err := ds.Get(mg); err != nil {
48 » » if err != nil {
49 » » » panic(err)
50 » » }
51 » » retval = val["__version__"][0].Value().(int64)
52 » })
53 » if err != nil {
54 panic(err) 57 panic(err)
55 } 58 }
56 » return retval 59 » return mg.Version
57 } 60 }
58 61
59 var pls = dsS.GetPLS 62 var pls = dsS.GetPLS
60 63
64 type Foo struct {
65 Id int64 `gae:"$id"`
66 Parent dsS.Key `gae:"$parent"`
67
68 Val int
69 }
70
61 func TestDatastoreSingleReadWriter(t *testing.T) { 71 func TestDatastoreSingleReadWriter(t *testing.T) {
62 t.Parallel() 72 t.Parallel()
63 73
64 getOnePM := func(ds dsS.Interface, key dsS.Key) (pmap dsS.PropertyMap, e rr error) {
65 blankErr := ds.GetMulti([]dsS.Key{key}, func(itmPmap dsS.Propert yMap, itmErr error) {
66 pmap = itmPmap
67 err = itmErr
68 })
69 So(blankErr, ShouldBeNil)
70 return
71 }
72
73 delOneErr := func(ds dsS.Interface, key dsS.Key) (err error) {
74 blankErr := ds.DeleteMulti([]dsS.Key{key}, func(itmErr error) {
75 err = itmErr
76 })
77 So(blankErr, ShouldBeNil)
78 return
79 }
80
81 delOne := func(ds dsS.Interface, key dsS.Key) {
82 So(delOneErr(ds, key), ShouldBeNil)
83 }
84
85 getOne := func(ds dsS.Interface, key dsS.Key, dst interface{}) {
86 pm, err := getOnePM(ds, key)
87 So(err, ShouldBeNil)
88 So(pls(dst).Load(pm), ShouldBeNil)
89 }
90
91 putOneErr := func(ds dsS.Interface, key dsS.Key, val interface{}) (retKe y dsS.Key, err error) {
92 blankErr := ds.PutMulti([]dsS.Key{key}, []dsS.PropertyLoadSaver{ pls(val)}, func(itmKey dsS.Key, itmErr error) {
93 err = itmErr
94 retKey = itmKey
95 })
96 So(blankErr, ShouldBeNil)
97 return
98 }
99
100 putOne := func(ds dsS.Interface, key dsS.Key, val interface{}) (retKey d sS.Key) {
101 key, err := putOneErr(ds, 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 ds := dsS.Get(c) 76 ds := dsS.Get(c)
109 So(ds, 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(ds, ds.NewKey("Foo", "", 1, n il)) 85 » » » So(err.Error(), ShouldContainSubstring, "namespace \"$$b lzyall\" does not match")
118 » » » » So(err, ShouldEqual, dsS.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 := ds.NewKey("Foo", "", 0, nil) 91 » » » So(ds.Put(f), ShouldBeNil)
124 » » » » f := &Foo{Val: 10} 92 » » » k := ds.KeyForObj(f)
125 » » » » k = putOne(ds, 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(ds, 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(ds, k) 102 » » » » » So(err, ShouldBeNil)
135 » » » » » » _, err := getOnePM(ds, k) 103 » » » » » ds = dsS.Get(c)
136 » » » » » » So(err, ShouldEqual, dsS.ErrNoSu chEntity) 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(ds, ds.NewKey("Foo", "wat", 100, nil)), ShouldEqual, dsS.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(ds, ds.NewKey("Foo", "wat", 0, ni l)) 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 := []dsS.Key{} 117 » » » » So(ds.Delete(ds.NewKey("Foo", "wat", 0, nil)), S houldBeNil)
150 » » » » » vals := []dsS.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, ds.NewKey("F oo", "", 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 := ds.PutMulti(keys, vals, func(k ds S.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 := ds.DeleteMulti(keys, func (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 := ds.(*dsImpl).dat a.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(ds, k, f)
186 » » » » » » So(testGetMeta(c, k), ShouldEqua l, 23)
187 » » » » » })
188
189 » » » » » Convey("can Get", func() {
190 » » » » » » vals := []dsS.PropertyMap{}
191 » » » » » » err := ds.GetMulti(keys, func(pm dsS.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, dsS.PropertyMap{"Val": {dsS.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 := ds.NewKey("Foo", "", 0, nil) 177 » » » » So(ds.Put(f), ShouldBeNil)
212 » » » » k := putOne(ds, 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 := ds.RunInTransaction(func(c contex t.Context) error { 182 err := ds.RunInTransaction(func(c contex t.Context) error {
217 ds := dsS.Get(c) 183 ds := dsS.Get(c)
218 184
219 » » » » » » f1 := &Foo{Val: 100} 185 » » » » » » f := &Foo{Val: 100}
220 » » » » » » k := putOne(ds, 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(ds, origKey, f2) 190 » » » » » » f.Val = 200
225 » » » » » » So(k.String(), ShouldEqual, "/Fo o,3") 191 » » » » » » So(ds.Put(f), ShouldBeNil)
192 » » » » » » So(f.Id, ShouldEqual, 3)
226 193
227 return nil 194 return nil
228 }, &dsS.TransactionOptions{XG: true}) 195 }, &dsS.TransactionOptions{XG: true})
229 So(err, ShouldBeNil) 196 So(err, ShouldBeNil)
230 197
231 » » » » » f := &Foo{} 198 » » » » » f := &Foo{Id: 2}
232 » » » » » getOne(ds, ds.NewKey("Foo", "", 2, nil), f) 199 » » » » » So(ds.Get(f), ShouldBeNil)
233 So(f.Val, ShouldEqual, 100) 200 So(f.Val, ShouldEqual, 100)
234 201
235 » » » » » getOne(ds, ds.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
241 err := ds.RunInTransaction(func(c contex t.Context) error { 208 err := ds.RunInTransaction(func(c contex t.Context) error {
242 ds := dsS.Get(c) 209 ds := dsS.Get(c)
243 » » » » » » So(ds, ShouldNotBeNil) 210
244 211 » » » » » » f := &Foo{Val: 100, Parent: k}
245 » » » » » » f1 := &Foo{Val: 100} 212 » » » » » » So(ds.Put(f), ShouldBeNil)
246 » » » » » » k := putOne(ds, ds.NewKey("Foo", "", 0, par), f1) 213 » » » » » » So(ds.KeyForObj(f).String(), Sho uldEqual, "/Foo,1/Foo,1")
247 » » » » » » So(k.String(), ShouldEqual, "/Fo o,1/Foo,1") 214
248 215 » » » » » » f.Id = 0
249 » » » » » » f2 := &Foo{Val: 200} 216 » » » » » » f.Val = 200
250 » » » » » » k = putOne(ds, ds.NewKey("Foo", "", 0, par), f2) 217 » » » » » » So(ds.Put(f), ShouldBeNil)
251 » » » » » » So(k.String(), ShouldEqual, "/Fo o,1/Foo,2") 218 » » » » » » So(ds.KeyForObj(f).String(), Sho uldEqual, "/Foo,1/Foo,2")
252 219
253 return nil 220 return nil
254 }, nil) 221 }, nil)
255 So(err, ShouldBeNil) 222 So(err, ShouldBeNil)
256 223
257 » » » » » f := &Foo{} 224 » » » » » f := &Foo{Id: 1, Parent: k}
258 » » » » » getOne(ds, ds.NewKey("Foo", "", 1, k), f ) 225 » » » » » So(ds.Get(f), ShouldBeNil)
259 So(f.Val, ShouldEqual, 100) 226 So(f.Val, ShouldEqual, 100)
260 227
261 » » » » » getOne(ds, ds.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 := ds.RunInTransaction(func(c contex t.Context) error { 234 err := ds.RunInTransaction(func(c contex t.Context) error {
235 return dsS.Get(c).Delete(k)
236 }, nil)
237 So(err, ShouldBeNil)
238 So(ds.Get(&Foo{Id: 1}), ShouldEqual, dsS .ErrNoSuchEntity)
239 })
240
241 Convey("A Get counts against your group count", func() {
242 err := ds.RunInTransaction(func(c contex t.Context) error {
267 ds := dsS.Get(c) 243 ds := dsS.Get(c)
268 » » » » » » So(ds, ShouldNotBeNil) 244
269 » » » » » » delOne(ds, k) 245 » » » » » » pm := dsS.PropertyMap{}
246 » » » » » » pm.SetMeta("key", ds.NewKey("Foo ", "", 20, nil))
247 » » » » » » So(ds.Get(pm), ShouldEqual, dsS. ErrNoSuchEntity)
248
249 » » » » » » pm.SetMeta("key", k)
250 » » » » » » So(ds.Get(pm).Error(), ShouldCon tainSubstring, "cross-group")
270 return nil 251 return nil
271 }, nil) 252 }, nil)
272 So(err, ShouldBeNil) 253 So(err, ShouldBeNil)
273 _, err = getOnePM(ds, k)
274 So(err, ShouldEqual, dsS.ErrNoSuchEntity )
275 })
276
277 Convey("A Get counts against your group count", func() {
278 err := ds.RunInTransaction(func(c contex t.Context) error {
279 ds := dsS.Get(c)
280
281 _, err := getOnePM(ds, ds.NewKey ("Foo", "", 20, nil))
282 So(err, ShouldEqual, dsS.ErrNoSu chEntity)
283
284 err = ds.GetMulti([]dsS.Key{k}, func(_ dsS.PropertyMap, err error) {
285 So(err, ShouldBeNil)
286 })
287 So(err.Error(), ShouldContainSub string, "cross-group")
288 return nil
289 }, nil)
290 So(err, ShouldBeNil)
291 }) 254 })
292 255
293 Convey("Get takes a snapshot", func() { 256 Convey("Get takes a snapshot", func() {
294 err := ds.RunInTransaction(func(c contex t.Context) error { 257 err := ds.RunInTransaction(func(c contex t.Context) error {
295 txnDS := dsS.Get(c) 258 txnDS := dsS.Get(c)
296 So(txnDS, ShouldNotBeNil)
297 259
298 » » » » » » getOne(txnDS, k, f) 260 » » » » » » So(txnDS.Get(f), ShouldBeNil)
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(ds, 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(ds, 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 := ds.RunInTransaction(func(c contex t.Context) error { 281 err := ds.RunInTransaction(func(c contex t.Context) error {
320 txnDS := dsS.Get(c) 282 txnDS := dsS.Get(c)
321 So(txnDS, ShouldNotBeNil)
322 283
323 » » » » » » f := &Foo{} 284 » » » » » » f := &Foo{Id: 1}
324 » » » » » » getOne(txnDS, k, f) 285 » » » » » » So(txnDS.Get(f), ShouldBeNil)
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(ds, 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(ds, 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 := ds.NewKey("Foo", "", 1, nil)
352 txnDS := dsS.Interface(nil) 312 txnDS := dsS.Interface(nil)
353 err := ds.RunInTransaction(func(c contex t.Context) error { 313 err := ds.RunInTransaction(func(c contex t.Context) error {
354 txnDS = dsS.Get(c) 314 txnDS = dsS.Get(c)
355 » » » » » » getOnePM(txnDS, k) 315 » » » » » » So(txnDS.Get(f), ShouldBeNil)
356 return nil 316 return nil
357 }, nil) 317 }, nil)
358 So(err, ShouldBeNil) 318 So(err, ShouldBeNil)
359 » » » » » err = txnDS.GetMulti([]dsS.Key{k}, func( _ dsS.PropertyMap, err error) { 319 » » » » » So(txnDS.Get(f).Error(), ShouldContainSu bstring, "expired")
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 := ds.RunInTransaction(func(c contex t.Context) error { 323 err := ds.RunInTransaction(func(c contex t.Context) error {
367 err := dsS.Get(c).RunInTransacti on(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 := ds.RunInTransaction(func(c contex t.Context) error { 341 err := ds.RunInTransaction(func(c contex t.Context) error {
385 » » » » » » txnDS := dsS.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 := ds.RunInTransaction(func( c context.Context) error { 344 err := ds.RunInTransaction(func( c context.Context) error {
390 » » » » » » » txnDS := dsS.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(ds, 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 := ds.RunInTransaction(func( c context.Context) error { 361 err := ds.RunInTransaction(func( c context.Context) error {
409 ds := dsS.Get(c) 362 ds := dsS.Get(c)
410 » » » » » » » f := &Foo{Val: 200} 363 » » » » » » » f := &Foo{Id: 1, Val: 20 0}
411 » » » » » » » putOne(ds, k, f) 364 » » » » » » » So(ds.Put(f), ShouldBeNi l)
412 365
413 » » » » » » » _, err := putOneErr(ds, ds.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 := ds.RunInTransaction(func( c context.Context) error { 375 err := ds.RunInTransaction(func( c context.Context) error {
422 ds := dsS.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 := ds.NewKey(" Foo", "", i, nil) 379 » » » » » » » » foos[i-1].Id = i
425 » » » » » » » » f := &Foo{Val: 2 00} 380 » » » » » » » » foos[i-1].Val = 200
426 » » » » » » » » putOne(ds, k, f)
427 } 381 }
428 » » » » » » » f := &Foo{Val: 200} 382 » » » » » » » So(ds.PutMulti(foos), Sh ouldBeNil)
429 » » » » » » » _, err := putOneErr(ds, ds.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 }, &dsS.TransactionOptions{XG: t rue}) 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 := ds.RunInTransaction(func( c context.Context) error { 393 err := ds.RunInTransaction(func( c context.Context) error {
440 ds := dsS.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(ds, 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(ds, 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 ds.RunInTransaction(func (c context.Context) error { 407 ds.RunInTransaction(func (c context.Context) error {
456 ds := dsS.Get(c) 408 ds := dsS.Get(c)
457 » » » » » » » » f := &Foo{Val: 2 00} 409 » » » » » » » » So(ds.Put(&Foo{V al: 200}), ShouldBeNil)
458 » » » » » » » » putOne(ds, 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(ds, 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)
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
620 }) 571 })
621 Convey("kindless with decending-__key__ orders", func() { 572 Convey("kindless with decending-__key__ orders", func() {
622 q := ds.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
« no previous file with comments | « impl/memory/raw_datastore_data.go ('k') | impl/prod/context.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698