OLD | NEW |
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 » "github.com/luci/gae" | 12 » rdsS "github.com/luci/gae/service/rawdatastore" |
13 » "github.com/luci/gae/helper" | |
14 . "github.com/smartystreets/goconvey/convey" | 13 . "github.com/smartystreets/goconvey/convey" |
15 "golang.org/x/net/context" | 14 "golang.org/x/net/context" |
16 ) | 15 ) |
17 | 16 |
18 func TestDatastoreKinder(t *testing.T) { | 17 func TestDatastoreKinder(t *testing.T) { |
19 t.Parallel() | 18 t.Parallel() |
20 | 19 |
21 Convey("Datastore keys", t, func() { | 20 Convey("Datastore keys", t, func() { |
22 c := Use(context.Background()) | 21 c := Use(context.Background()) |
23 » » rds := gae.GetRDS(c) | 22 » » rds := rdsS.Get(c) |
24 So(rds, ShouldNotBeNil) | 23 So(rds, ShouldNotBeNil) |
25 | 24 |
26 Convey("implements DSNewKeyer", func() { | 25 Convey("implements DSNewKeyer", func() { |
27 Convey("NewKey", func() { | 26 Convey("NewKey", func() { |
28 key := rds.NewKey("nerd", "stringID", 0, nil) | 27 key := rds.NewKey("nerd", "stringID", 0, nil) |
29 So(key, ShouldNotBeNil) | 28 So(key, ShouldNotBeNil) |
30 So(key.Kind(), ShouldEqual, "nerd") | 29 So(key.Kind(), ShouldEqual, "nerd") |
31 So(key.StringID(), ShouldEqual, "stringID") | 30 So(key.StringID(), ShouldEqual, "stringID") |
32 So(key.IntID(), ShouldEqual, 0) | 31 So(key.IntID(), ShouldEqual, 0) |
33 So(key.Parent(), ShouldBeNil) | 32 So(key.Parent(), ShouldBeNil) |
34 So(key.AppID(), ShouldEqual, "dev~app") | 33 So(key.AppID(), ShouldEqual, "dev~app") |
35 So(key.Namespace(), ShouldEqual, "") | 34 So(key.Namespace(), ShouldEqual, "") |
36 So(key.String(), ShouldEqual, "/nerd,stringID") | 35 So(key.String(), ShouldEqual, "/nerd,stringID") |
37 » » » » So(helper.DSKeyIncomplete(key), ShouldBeFalse) | 36 » » » » So(rdsS.KeyIncomplete(key), ShouldBeFalse) |
38 » » » » So(helper.DSKeyValid(key, "", false), ShouldBeTr
ue) | 37 » » » » So(rdsS.KeyValid(key, "", false), ShouldBeTrue) |
39 }) | 38 }) |
40 }) | 39 }) |
41 | 40 |
42 }) | 41 }) |
43 } | 42 } |
44 | 43 |
45 func testGetMeta(c context.Context, k gae.DSKey) int64 { | 44 func testGetMeta(c context.Context, k rdsS.Key) int64 { |
46 » rds := gae.GetRDS(c) | 45 » rds := rdsS.Get(c) |
47 » k = rds.NewKey("__entity_group__", "", 1, helper.DSKeyRoot(k)) | 46 » k = rds.NewKey("__entity_group__", "", 1, rdsS.KeyRoot(k)) |
48 » pmap := gae.DSPropertyMap{} | 47 » pmap := rdsS.PropertyMap{} |
49 rds.Get(k, pmap) | 48 rds.Get(k, pmap) |
50 return pmap["__version__"][0].Value().(int64) | 49 return pmap["__version__"][0].Value().(int64) |
51 } | 50 } |
52 | 51 |
53 var pls = helper.GetPLS | 52 var pls = rdsS.GetPLS |
54 | 53 |
55 func TestDatastoreSingleReadWriter(t *testing.T) { | 54 func TestDatastoreSingleReadWriter(t *testing.T) { |
56 t.Parallel() | 55 t.Parallel() |
57 | 56 |
58 Convey("Datastore single reads and writes", t, func() { | 57 Convey("Datastore single reads and writes", t, func() { |
59 c := Use(context.Background()) | 58 c := Use(context.Background()) |
60 » » rds := gae.GetRDS(c) | 59 » » rds := rdsS.Get(c) |
61 So(rds, ShouldNotBeNil) | 60 So(rds, ShouldNotBeNil) |
62 | 61 |
63 Convey("implements DSSingleReadWriter", func() { | 62 Convey("implements DSSingleReadWriter", func() { |
64 type Foo struct { | 63 type Foo struct { |
65 Val int | 64 Val int |
66 } | 65 } |
67 | 66 |
68 Convey("invalid keys break", func() { | 67 Convey("invalid keys break", func() { |
69 k := rds.NewKey("Foo", "", 0, nil) | 68 k := rds.NewKey("Foo", "", 0, nil) |
70 » » » » So(rds.Get(k, nil), ShouldEqual, gae.ErrDSInvali
dKey) | 69 » » » » So(rds.Get(k, nil), ShouldEqual, rdsS.ErrInvalid
Key) |
71 | 70 |
72 _, err := rds.Put(rds.NewKey("Foo", "", 0, k), p
ls(&Foo{})) | 71 _, err := rds.Put(rds.NewKey("Foo", "", 0, k), p
ls(&Foo{})) |
73 » » » » So(err, ShouldEqual, gae.ErrDSInvalidKey) | 72 » » » » So(err, ShouldEqual, rdsS.ErrInvalidKey) |
74 }) | 73 }) |
75 | 74 |
76 Convey("getting objects that DNE is an error", func() { | 75 Convey("getting objects that DNE is an error", func() { |
77 k := rds.NewKey("Foo", "", 1, nil) | 76 k := rds.NewKey("Foo", "", 1, nil) |
78 » » » » So(rds.Get(k, nil), ShouldEqual, gae.ErrDSNoSuch
Entity) | 77 » » » » So(rds.Get(k, nil), ShouldEqual, rdsS.ErrNoSuchE
ntity) |
79 }) | 78 }) |
80 | 79 |
81 Convey("Can Put stuff", func() { | 80 Convey("Can Put stuff", func() { |
82 // with an incomplete key! | 81 // with an incomplete key! |
83 k := rds.NewKey("Foo", "", 0, nil) | 82 k := rds.NewKey("Foo", "", 0, nil) |
84 f := &Foo{Val: 10} | 83 f := &Foo{Val: 10} |
85 k, err := rds.Put(k, pls(f)) | 84 k, err := rds.Put(k, pls(f)) |
86 So(err, ShouldBeNil) | 85 So(err, ShouldBeNil) |
87 So(k.String(), ShouldEqual, "/Foo,1") | 86 So(k.String(), ShouldEqual, "/Foo,1") |
88 | 87 |
89 Convey("and Get it back", func() { | 88 Convey("and Get it back", func() { |
90 newFoo := &Foo{} | 89 newFoo := &Foo{} |
91 err := rds.Get(k, pls(newFoo)) | 90 err := rds.Get(k, pls(newFoo)) |
92 So(err, ShouldBeNil) | 91 So(err, ShouldBeNil) |
93 So(newFoo, ShouldResemble, f) | 92 So(newFoo, ShouldResemble, f) |
94 | 93 |
95 Convey("and we can Delete it", func() { | 94 Convey("and we can Delete it", func() { |
96 err := rds.Delete(k) | 95 err := rds.Delete(k) |
97 So(err, ShouldBeNil) | 96 So(err, ShouldBeNil) |
98 | 97 |
99 err = rds.Get(k, pls(newFoo)) | 98 err = rds.Get(k, pls(newFoo)) |
100 » » » » » » So(err, ShouldEqual, gae.ErrDSNo
SuchEntity) | 99 » » » » » » So(err, ShouldEqual, rdsS.ErrNoS
uchEntity) |
101 }) | 100 }) |
102 }) | 101 }) |
103 Convey("Deleteing with a bogus key is bad", func
() { | 102 Convey("Deleteing with a bogus key is bad", func
() { |
104 err := rds.Delete(rds.NewKey("Foo", "wat
", 100, nil)) | 103 err := rds.Delete(rds.NewKey("Foo", "wat
", 100, nil)) |
105 » » » » » So(err, ShouldEqual, gae.ErrDSInvalidKey
) | 104 » » » » » So(err, ShouldEqual, rdsS.ErrInvalidKey) |
106 }) | 105 }) |
107 Convey("Deleteing a DNE entity is fine", func()
{ | 106 Convey("Deleteing a DNE entity is fine", func()
{ |
108 err := rds.Delete(rds.NewKey("Foo", "wat
", 0, nil)) | 107 err := rds.Delete(rds.NewKey("Foo", "wat
", 0, nil)) |
109 So(err, ShouldBeNil) | 108 So(err, ShouldBeNil) |
110 }) | 109 }) |
111 | 110 |
112 Convey("with multiple puts", func() { | 111 Convey("with multiple puts", func() { |
113 So(testGetMeta(c, k), ShouldEqual, 1) | 112 So(testGetMeta(c, k), ShouldEqual, 1) |
114 | 113 |
115 » » » » » keys := []gae.DSKey{} | 114 » » » » » keys := []rdsS.Key{} |
116 » » » » » plss := []gae.DSPropertyLoadSaver{} | 115 » » » » » plss := []rdsS.PropertyLoadSaver{} |
117 | 116 |
118 pkey := k | 117 pkey := k |
119 for i := 0; i < 10; i++ { | 118 for i := 0; i < 10; i++ { |
120 keys = append(keys, rds.NewKey("
Foo", "", 0, pkey)) | 119 keys = append(keys, rds.NewKey("
Foo", "", 0, pkey)) |
121 plss = append(plss, pls(&Foo{Val
: 10})) | 120 plss = append(plss, pls(&Foo{Val
: 10})) |
122 } | 121 } |
123 keys, err := rds.PutMulti(keys, plss) | 122 keys, err := rds.PutMulti(keys, plss) |
124 So(err, ShouldBeNil) | 123 So(err, ShouldBeNil) |
125 So(testGetMeta(c, k), ShouldEqual, 11) | 124 So(testGetMeta(c, k), ShouldEqual, 11) |
126 | 125 |
(...skipping 11 matching lines...) Expand all Loading... |
138 So(num, ShouldEqual, 3) | 137 So(num, ShouldEqual, 3) |
139 | 138 |
140 So(curVersion(ents, groupMetaKey
(k)), ShouldEqual, 22) | 139 So(curVersion(ents, groupMetaKey
(k)), ShouldEqual, 22) |
141 | 140 |
142 k, err := rds.Put(k, pls(f)) | 141 k, err := rds.Put(k, pls(f)) |
143 So(err, ShouldBeNil) | 142 So(err, ShouldBeNil) |
144 So(testGetMeta(c, k), ShouldEqua
l, 23) | 143 So(testGetMeta(c, k), ShouldEqua
l, 23) |
145 }) | 144 }) |
146 | 145 |
147 Convey("can GetMulti", func() { | 146 Convey("can GetMulti", func() { |
148 » » » » » » plss := make([]gae.DSPropertyLoa
dSaver, len(keys)) | 147 » » » » » » plss := make([]rdsS.PropertyLoad
Saver, len(keys)) |
149 for i := range plss { | 148 for i := range plss { |
150 » » » » » » » plss[i] = gae.DSProperty
Map{} | 149 » » » » » » » plss[i] = rdsS.PropertyM
ap{} |
151 } | 150 } |
152 err := rds.GetMulti(keys, plss) | 151 err := rds.GetMulti(keys, plss) |
153 So(err, ShouldBeNil) | 152 So(err, ShouldBeNil) |
154 for _, pls := range plss { | 153 for _, pls := range plss { |
155 » » » » » » » So(pls.(gae.DSPropertyMa
p), ShouldResemble, gae.DSPropertyMap{ | 154 » » » » » » » So(pls.(rdsS.PropertyMap
), ShouldResemble, rdsS.PropertyMap{ |
156 » » » » » » » » "Val": {gae.MkDS
Property(10)}, | 155 » » » » » » » » "Val": {rdsS.MkP
roperty(10)}, |
157 }) | 156 }) |
158 } | 157 } |
159 }) | 158 }) |
160 }) | 159 }) |
161 }) | 160 }) |
162 }) | 161 }) |
163 | 162 |
164 Convey("implements DSTransactioner", func() { | 163 Convey("implements DSTransactioner", func() { |
165 type Foo struct { | 164 type Foo struct { |
166 Val int | 165 Val int |
167 } | 166 } |
168 Convey("Put", func() { | 167 Convey("Put", func() { |
169 k := rds.NewKey("Foo", "", 0, nil) | 168 k := rds.NewKey("Foo", "", 0, nil) |
170 f := &Foo{Val: 10} | 169 f := &Foo{Val: 10} |
171 k, err := rds.Put(k, pls(f)) | 170 k, err := rds.Put(k, pls(f)) |
172 So(err, ShouldBeNil) | 171 So(err, ShouldBeNil) |
173 So(k.String(), ShouldEqual, "/Foo,1") | 172 So(k.String(), ShouldEqual, "/Foo,1") |
174 | 173 |
175 Convey("can Put new entity groups", func() { | 174 Convey("can Put new entity groups", func() { |
176 err := rds.RunInTransaction(func(c conte
xt.Context) error { | 175 err := rds.RunInTransaction(func(c conte
xt.Context) error { |
177 » » » » » » rds := gae.GetRDS(c) | 176 » » » » » » rds := rdsS.Get(c) |
178 So(rds, ShouldNotBeNil) | 177 So(rds, ShouldNotBeNil) |
179 | 178 |
180 f1 := &Foo{Val: 100} | 179 f1 := &Foo{Val: 100} |
181 k, err := rds.Put(rds.NewKey("Fo
o", "", 0, nil), pls(f1)) | 180 k, err := rds.Put(rds.NewKey("Fo
o", "", 0, nil), pls(f1)) |
182 So(err, ShouldBeNil) | 181 So(err, ShouldBeNil) |
183 So(k.String(), ShouldEqual, "/Fo
o,2") | 182 So(k.String(), ShouldEqual, "/Fo
o,2") |
184 | 183 |
185 f2 := &Foo{Val: 200} | 184 f2 := &Foo{Val: 200} |
186 k, err = rds.Put(rds.NewKey("Foo
", "", 0, nil), pls(f2)) | 185 k, err = rds.Put(rds.NewKey("Foo
", "", 0, nil), pls(f2)) |
187 So(err, ShouldBeNil) | 186 So(err, ShouldBeNil) |
188 So(k.String(), ShouldEqual, "/Fo
o,3") | 187 So(k.String(), ShouldEqual, "/Fo
o,3") |
189 | 188 |
190 return nil | 189 return nil |
191 » » » » » }, &gae.DSTransactionOptions{XG: true}) | 190 » » » » » }, &rdsS.TransactionOptions{XG: true}) |
192 So(err, ShouldBeNil) | 191 So(err, ShouldBeNil) |
193 | 192 |
194 f := &Foo{} | 193 f := &Foo{} |
195 So(rds.Get(rds.NewKey("Foo", "", 2, nil)
, pls(f)), ShouldBeNil) | 194 So(rds.Get(rds.NewKey("Foo", "", 2, nil)
, pls(f)), ShouldBeNil) |
196 So(f.Val, ShouldEqual, 100) | 195 So(f.Val, ShouldEqual, 100) |
197 | 196 |
198 f = &Foo{} | 197 f = &Foo{} |
199 So(rds.Get(rds.NewKey("Foo", "", 3, nil)
, pls(f)), ShouldBeNil) | 198 So(rds.Get(rds.NewKey("Foo", "", 3, nil)
, pls(f)), ShouldBeNil) |
200 So(f.Val, ShouldEqual, 200) | 199 So(f.Val, ShouldEqual, 200) |
201 }) | 200 }) |
202 | 201 |
203 Convey("can Put new entities in a current group"
, func() { | 202 Convey("can Put new entities in a current group"
, func() { |
204 err := rds.RunInTransaction(func(c conte
xt.Context) error { | 203 err := rds.RunInTransaction(func(c conte
xt.Context) error { |
205 » » » » » » rds := gae.GetRDS(c) | 204 » » » » » » rds := rdsS.Get(c) |
206 So(rds, ShouldNotBeNil) | 205 So(rds, ShouldNotBeNil) |
207 | 206 |
208 par := k | 207 par := k |
209 | 208 |
210 f1 := &Foo{Val: 100} | 209 f1 := &Foo{Val: 100} |
211 k, err := rds.Put(rds.NewKey("Fo
o", "", 0, par), pls(f1)) | 210 k, err := rds.Put(rds.NewKey("Fo
o", "", 0, par), pls(f1)) |
212 So(err, ShouldBeNil) | 211 So(err, ShouldBeNil) |
213 So(k.String(), ShouldEqual, "/Fo
o,1/Foo,1") | 212 So(k.String(), ShouldEqual, "/Fo
o,1/Foo,1") |
214 | 213 |
215 f2 := &Foo{Val: 200} | 214 f2 := &Foo{Val: 200} |
216 k, err = rds.Put(rds.NewKey("Foo
", "", 0, par), pls(f2)) | 215 k, err = rds.Put(rds.NewKey("Foo
", "", 0, par), pls(f2)) |
217 So(err, ShouldBeNil) | 216 So(err, ShouldBeNil) |
218 So(k.String(), ShouldEqual, "/Fo
o,1/Foo,2") | 217 So(k.String(), ShouldEqual, "/Fo
o,1/Foo,2") |
219 | 218 |
220 return nil | 219 return nil |
221 }, nil) | 220 }, nil) |
222 So(err, ShouldBeNil) | 221 So(err, ShouldBeNil) |
223 | 222 |
224 f1 := &Foo{} | 223 f1 := &Foo{} |
225 So(rds.Get(rds.NewKey("Foo", "", 1, k),
pls(f1)), ShouldBeNil) | 224 So(rds.Get(rds.NewKey("Foo", "", 1, k),
pls(f1)), ShouldBeNil) |
226 So(f1.Val, ShouldEqual, 100) | 225 So(f1.Val, ShouldEqual, 100) |
227 | 226 |
228 f2 := &Foo{} | 227 f2 := &Foo{} |
229 So(rds.Get(rds.NewKey("Foo", "", 2, k),
pls(f2)), ShouldBeNil) | 228 So(rds.Get(rds.NewKey("Foo", "", 2, k),
pls(f2)), ShouldBeNil) |
230 So(f2.Val, ShouldEqual, 200) | 229 So(f2.Val, ShouldEqual, 200) |
231 }) | 230 }) |
232 | 231 |
233 Convey("Deletes work too", func() { | 232 Convey("Deletes work too", func() { |
234 err := rds.RunInTransaction(func(c conte
xt.Context) error { | 233 err := rds.RunInTransaction(func(c conte
xt.Context) error { |
235 » » » » » » rds := gae.GetRDS(c) | 234 » » » » » » rds := rdsS.Get(c) |
236 So(rds, ShouldNotBeNil) | 235 So(rds, ShouldNotBeNil) |
237 So(rds.Delete(k), ShouldBeNil) | 236 So(rds.Delete(k), ShouldBeNil) |
238 return nil | 237 return nil |
239 }, nil) | 238 }, nil) |
240 So(err, ShouldBeNil) | 239 So(err, ShouldBeNil) |
241 » » » » » So(rds.Get(k, nil), ShouldEqual, gae.Err
DSNoSuchEntity) | 240 » » » » » So(rds.Get(k, nil), ShouldEqual, rdsS.Er
rNoSuchEntity) |
242 }) | 241 }) |
243 | 242 |
244 Convey("A Get counts against your group count",
func() { | 243 Convey("A Get counts against your group count",
func() { |
245 err := rds.RunInTransaction(func(c conte
xt.Context) error { | 244 err := rds.RunInTransaction(func(c conte
xt.Context) error { |
246 » » » » » » rds := gae.GetRDS(c) | 245 » » » » » » rds := rdsS.Get(c) |
247 » » » » » » So(rds.Get(rds.NewKey("Foo", "",
20, nil), nil), ShouldEqual, gae.ErrDSNoSuchEntity) | 246 » » » » » » So(rds.Get(rds.NewKey("Foo", "",
20, nil), nil), ShouldEqual, rdsS.ErrNoSuchEntity) |
248 So(rds.Get(k, nil).Error(), Shou
ldContainSubstring, "cross-group") | 247 So(rds.Get(k, nil).Error(), Shou
ldContainSubstring, "cross-group") |
249 return nil | 248 return nil |
250 }, nil) | 249 }, nil) |
251 So(err, ShouldBeNil) | 250 So(err, ShouldBeNil) |
252 }) | 251 }) |
253 | 252 |
254 Convey("Get takes a snapshot", func() { | 253 Convey("Get takes a snapshot", func() { |
255 err := rds.RunInTransaction(func(c conte
xt.Context) error { | 254 err := rds.RunInTransaction(func(c conte
xt.Context) error { |
256 » » » » » » txnDS := gae.GetRDS(c) | 255 » » » » » » txnDS := rdsS.Get(c) |
257 So(txnDS, ShouldNotBeNil) | 256 So(txnDS, ShouldNotBeNil) |
258 | 257 |
259 So(txnDS.Get(k, pls(f)), ShouldB
eNil) | 258 So(txnDS.Get(k, pls(f)), ShouldB
eNil) |
260 So(f.Val, ShouldEqual, 10) | 259 So(f.Val, ShouldEqual, 10) |
261 | 260 |
262 // Don't ever do this in a real
program unless you want to guarantee | 261 // Don't ever do this in a real
program unless you want to guarantee |
263 // a failed transaction :) | 262 // a failed transaction :) |
264 f.Val = 11 | 263 f.Val = 11 |
265 _, err := rds.Put(k, pls(f)) | 264 _, err := rds.Put(k, pls(f)) |
266 So(err, ShouldBeNil) | 265 So(err, ShouldBeNil) |
267 | 266 |
268 So(txnDS.Get(k, pls(f)), ShouldB
eNil) | 267 So(txnDS.Get(k, pls(f)), ShouldB
eNil) |
269 So(f.Val, ShouldEqual, 10) | 268 So(f.Val, ShouldEqual, 10) |
270 | 269 |
271 return nil | 270 return nil |
272 }, nil) | 271 }, nil) |
273 So(err, ShouldBeNil) | 272 So(err, ShouldBeNil) |
274 | 273 |
275 f := &Foo{} | 274 f := &Foo{} |
276 So(rds.Get(k, pls(f)), ShouldBeNil) | 275 So(rds.Get(k, pls(f)), ShouldBeNil) |
277 So(f.Val, ShouldEqual, 11) | 276 So(f.Val, ShouldEqual, 11) |
278 }) | 277 }) |
279 | 278 |
280 Convey("and snapshots are consistent even after
Puts", func() { | 279 Convey("and snapshots are consistent even after
Puts", func() { |
281 err := rds.RunInTransaction(func(c conte
xt.Context) error { | 280 err := rds.RunInTransaction(func(c conte
xt.Context) error { |
282 » » » » » » txnDS := gae.GetRDS(c) | 281 » » » » » » txnDS := rdsS.Get(c) |
283 So(txnDS, ShouldNotBeNil) | 282 So(txnDS, ShouldNotBeNil) |
284 | 283 |
285 f := &Foo{} | 284 f := &Foo{} |
286 So(txnDS.Get(k, pls(f)), ShouldB
eNil) | 285 So(txnDS.Get(k, pls(f)), ShouldB
eNil) |
287 So(f.Val, ShouldEqual, 10) | 286 So(f.Val, ShouldEqual, 10) |
288 | 287 |
289 // 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 |
290 // a failed transaction :) | 289 // a failed transaction :) |
291 f.Val = 11 | 290 f.Val = 11 |
292 | 291 |
(...skipping 14 matching lines...) Expand all Loading... |
307 }, nil) | 306 }, nil) |
308 So(err.Error(), ShouldContainSubstring,
"concurrent") | 307 So(err.Error(), ShouldContainSubstring,
"concurrent") |
309 | 308 |
310 f := &Foo{} | 309 f := &Foo{} |
311 So(rds.Get(k, pls(f)), ShouldBeNil) | 310 So(rds.Get(k, pls(f)), ShouldBeNil) |
312 So(f.Val, ShouldEqual, 11) | 311 So(f.Val, ShouldEqual, 11) |
313 }) | 312 }) |
314 | 313 |
315 Convey("Reusing a transaction context is bad new
s", func() { | 314 Convey("Reusing a transaction context is bad new
s", func() { |
316 k := rds.NewKey("Foo", "", 1, nil) | 315 k := rds.NewKey("Foo", "", 1, nil) |
317 » » » » » txnDS := gae.RawDatastore(nil) | 316 » » » » » txnDS := rdsS.Interface(nil) |
318 err := rds.RunInTransaction(func(c conte
xt.Context) error { | 317 err := rds.RunInTransaction(func(c conte
xt.Context) error { |
319 » » » » » » txnDS = gae.GetRDS(c) | 318 » » » » » » txnDS = rdsS.Get(c) |
320 » » » » » » So(txnDS.Get(k, gae.DSPropertyMa
p{}), ShouldBeNil) | 319 » » » » » » So(txnDS.Get(k, rdsS.PropertyMap
{}), ShouldBeNil) |
321 return nil | 320 return nil |
322 }, nil) | 321 }, nil) |
323 So(err, ShouldBeNil) | 322 So(err, ShouldBeNil) |
324 » » » » » So(txnDS.Get(k, gae.DSPropertyMap{}).Err
or(), ShouldContainSubstring, "expired") | 323 » » » » » So(txnDS.Get(k, rdsS.PropertyMap{}).Erro
r(), ShouldContainSubstring, "expired") |
325 }) | 324 }) |
326 | 325 |
327 Convey("Nested transactions are rejected", func(
) { | 326 Convey("Nested transactions are rejected", func(
) { |
328 err := rds.RunInTransaction(func(c conte
xt.Context) error { | 327 err := rds.RunInTransaction(func(c conte
xt.Context) error { |
329 » » » » » » err := gae.GetRDS(c).RunInTransa
ction(func(c context.Context) error { | 328 » » » » » » err := rdsS.Get(c).RunInTransact
ion(func(c context.Context) error { |
330 panic("noooo") | 329 panic("noooo") |
331 }, nil) | 330 }, nil) |
332 So(err.Error(), ShouldContainSub
string, "nested transactions") | 331 So(err.Error(), ShouldContainSub
string, "nested transactions") |
333 return nil | 332 return nil |
334 }, nil) | 333 }, nil) |
335 So(err, ShouldBeNil) | 334 So(err, ShouldBeNil) |
336 }) | 335 }) |
337 | 336 |
338 Convey("Concurrent transactions only accept one
set of changes", func() { | 337 Convey("Concurrent transactions only accept one
set of changes", func() { |
339 // Note: I think this implementation is
actually /slightly/ wrong. | 338 // Note: I think this implementation is
actually /slightly/ wrong. |
340 // Accorting to my read of the docs for
appengine, when you open a | 339 // Accorting to my read of the docs for
appengine, when you open a |
341 // transaction it actually (essentially)
holds a reference to the | 340 // transaction it actually (essentially)
holds a reference to the |
342 // entire datastore. Our implementation
takes a snapshot of the | 341 // entire datastore. Our implementation
takes a snapshot of the |
343 // entity group as soon as something obs
erves/affects it. | 342 // entity group as soon as something obs
erves/affects it. |
344 // | 343 // |
345 // That said... I'm not sure if there's
really a semantic difference. | 344 // That said... I'm not sure if there's
really a semantic difference. |
346 err := rds.RunInTransaction(func(c conte
xt.Context) error { | 345 err := rds.RunInTransaction(func(c conte
xt.Context) error { |
347 » » » » » » txnDS := gae.GetRDS(c) | 346 » » » » » » txnDS := rdsS.Get(c) |
348 f := &Foo{Val: 21} | 347 f := &Foo{Val: 21} |
349 _, err = txnDS.Put(k, pls(f)) | 348 _, err = txnDS.Put(k, pls(f)) |
350 So(err, ShouldBeNil) | 349 So(err, ShouldBeNil) |
351 | 350 |
352 err := rds.RunInTransaction(func
(c context.Context) error { | 351 err := rds.RunInTransaction(func
(c context.Context) error { |
353 » » » » » » » txnDS := gae.GetRDS(c) | 352 » » » » » » » txnDS := rdsS.Get(c) |
354 f := &Foo{Val: 27} | 353 f := &Foo{Val: 27} |
355 _, err := txnDS.Put(k, p
ls(f)) | 354 _, err := txnDS.Put(k, p
ls(f)) |
356 So(err, ShouldBeNil) | 355 So(err, ShouldBeNil) |
357 return nil | 356 return nil |
358 }, nil) | 357 }, nil) |
359 So(err, ShouldBeNil) | 358 So(err, ShouldBeNil) |
360 | 359 |
361 return nil | 360 return nil |
362 }, nil) | 361 }, nil) |
363 So(err.Error(), ShouldContainSubstring,
"concurrent") | 362 So(err.Error(), ShouldContainSubstring,
"concurrent") |
364 | 363 |
365 f := &Foo{} | 364 f := &Foo{} |
366 So(rds.Get(k, pls(f)), ShouldBeNil) | 365 So(rds.Get(k, pls(f)), ShouldBeNil) |
367 So(f.Val, ShouldEqual, 27) | 366 So(f.Val, ShouldEqual, 27) |
368 }) | 367 }) |
369 | 368 |
370 Convey("XG", func() { | 369 Convey("XG", func() { |
371 Convey("Modifying two groups with XG=fal
se is invalid", func() { | 370 Convey("Modifying two groups with XG=fal
se is invalid", func() { |
372 err := rds.RunInTransaction(func
(c context.Context) error { | 371 err := rds.RunInTransaction(func
(c context.Context) error { |
373 » » » » » » » rds := gae.GetRDS(c) | 372 » » » » » » » rds := rdsS.Get(c) |
374 f := &Foo{Val: 200} | 373 f := &Foo{Val: 200} |
375 _, err := rds.Put(k, pls
(f)) | 374 _, err := rds.Put(k, pls
(f)) |
376 So(err, ShouldBeNil) | 375 So(err, ShouldBeNil) |
377 | 376 |
378 _, err = rds.Put(rds.New
Key("Foo", "", 2, nil), pls(f)) | 377 _, err = rds.Put(rds.New
Key("Foo", "", 2, nil), pls(f)) |
379 So(err.Error(), ShouldCo
ntainSubstring, "cross-group") | 378 So(err.Error(), ShouldCo
ntainSubstring, "cross-group") |
380 return err | 379 return err |
381 }, nil) | 380 }, nil) |
382 So(err.Error(), ShouldContainSub
string, "cross-group") | 381 So(err.Error(), ShouldContainSub
string, "cross-group") |
383 }) | 382 }) |
384 | 383 |
385 Convey("Modifying >25 groups with XG=tru
e is invald", func() { | 384 Convey("Modifying >25 groups with XG=tru
e is invald", func() { |
386 err := rds.RunInTransaction(func
(c context.Context) error { | 385 err := rds.RunInTransaction(func
(c context.Context) error { |
387 » » » » » » » rds := gae.GetRDS(c) | 386 » » » » » » » rds := rdsS.Get(c) |
388 for i := int64(1); i < 2
6; i++ { | 387 for i := int64(1); i < 2
6; i++ { |
389 k := rds.NewKey(
"Foo", "", i, nil) | 388 k := rds.NewKey(
"Foo", "", i, nil) |
390 f := &Foo{Val: 2
00} | 389 f := &Foo{Val: 2
00} |
391 _, err := rds.Pu
t(k, pls(f)) | 390 _, err := rds.Pu
t(k, pls(f)) |
392 So(err, ShouldBe
Nil) | 391 So(err, ShouldBe
Nil) |
393 } | 392 } |
394 f := &Foo{Val: 200} | 393 f := &Foo{Val: 200} |
395 _, err := rds.Put(rds.Ne
wKey("Foo", "", 27, nil), pls(f)) | 394 _, err := rds.Put(rds.Ne
wKey("Foo", "", 27, nil), pls(f)) |
396 So(err.Error(), ShouldCo
ntainSubstring, "too many entity groups") | 395 So(err.Error(), ShouldCo
ntainSubstring, "too many entity groups") |
397 return err | 396 return err |
398 » » » » » » }, &gae.DSTransactionOptions{XG:
true}) | 397 » » » » » » }, &rdsS.TransactionOptions{XG:
true}) |
399 So(err.Error(), ShouldContainSub
string, "too many entity groups") | 398 So(err.Error(), ShouldContainSub
string, "too many entity groups") |
400 }) | 399 }) |
401 }) | 400 }) |
402 | 401 |
403 Convey("Errors and panics", func() { | 402 Convey("Errors and panics", func() { |
404 Convey("returning an error aborts", func
() { | 403 Convey("returning an error aborts", func
() { |
405 err := rds.RunInTransaction(func
(c context.Context) error { | 404 err := rds.RunInTransaction(func
(c context.Context) error { |
406 » » » » » » » rds := gae.GetRDS(c) | 405 » » » » » » » rds := rdsS.Get(c) |
407 f := &Foo{Val: 200} | 406 f := &Foo{Val: 200} |
408 _, err := rds.Put(k, pls
(f)) | 407 _, err := rds.Put(k, pls
(f)) |
409 So(err, ShouldBeNil) | 408 So(err, ShouldBeNil) |
410 | 409 |
411 return fmt.Errorf("thing
y") | 410 return fmt.Errorf("thing
y") |
412 }, nil) | 411 }, nil) |
413 So(err.Error(), ShouldEqual, "th
ingy") | 412 So(err.Error(), ShouldEqual, "th
ingy") |
414 | 413 |
415 f := &Foo{} | 414 f := &Foo{} |
416 So(rds.Get(k, pls(f)), ShouldBeN
il) | 415 So(rds.Get(k, pls(f)), ShouldBeN
il) |
417 So(f.Val, ShouldEqual, 10) | 416 So(f.Val, ShouldEqual, 10) |
418 }) | 417 }) |
419 | 418 |
420 Convey("panicing aborts", func() { | 419 Convey("panicing aborts", func() { |
421 So(func() { | 420 So(func() { |
422 rds.RunInTransaction(fun
c(c context.Context) error { | 421 rds.RunInTransaction(fun
c(c context.Context) error { |
423 » » » » » » » » rds := gae.GetRD
S(c) | 422 » » » » » » » » rds := rdsS.Get(
c) |
424 f := &Foo{Val: 2
00} | 423 f := &Foo{Val: 2
00} |
425 _, err := rds.Pu
t(k, pls(f)) | 424 _, err := rds.Pu
t(k, pls(f)) |
426 So(err, ShouldBe
Nil) | 425 So(err, ShouldBe
Nil) |
427 panic("wheeeeee"
) | 426 panic("wheeeeee"
) |
428 }, nil) | 427 }, nil) |
429 }, ShouldPanic) | 428 }, ShouldPanic) |
430 | 429 |
431 f := &Foo{} | 430 f := &Foo{} |
432 So(rds.Get(k, pls(f)), ShouldBeN
il) | 431 So(rds.Get(k, pls(f)), ShouldBeN
il) |
433 So(f.Val, ShouldEqual, 10) | 432 So(f.Val, ShouldEqual, 10) |
434 }) | 433 }) |
435 }) | 434 }) |
436 }) | 435 }) |
437 }) | 436 }) |
438 | 437 |
439 }) | 438 }) |
440 } | 439 } |
441 | 440 |
442 const MaxUint = ^uint(0) | 441 const MaxUint = ^uint(0) |
443 const MaxInt = int(MaxUint >> 1) | 442 const MaxInt = int(MaxUint >> 1) |
444 const IntIs32Bits = int64(MaxInt) < math.MaxInt64 | 443 const IntIs32Bits = int64(MaxInt) < math.MaxInt64 |
445 | 444 |
446 func TestDatastoreQueryer(t *testing.T) { | 445 func TestDatastoreQueryer(t *testing.T) { |
447 Convey("Datastore Query suport", t, func() { | 446 Convey("Datastore Query suport", t, func() { |
448 c := Use(context.Background()) | 447 c := Use(context.Background()) |
449 » » rds := gae.GetRDS(c) | 448 » » rds := rdsS.Get(c) |
450 So(rds, ShouldNotBeNil) | 449 So(rds, ShouldNotBeNil) |
451 | 450 |
452 Convey("can create good queries", func() { | 451 Convey("can create good queries", func() { |
453 q := rds.NewQuery("Foo").KeysOnly().Limit(10).Offset(39) | 452 q := rds.NewQuery("Foo").KeysOnly().Limit(10).Offset(39) |
454 q = q.Start(queryCursor("kosmik")).End(queryCursor("krab
s")) | 453 q = q.Start(queryCursor("kosmik")).End(queryCursor("krab
s")) |
455 So(q, ShouldNotBeNil) | 454 So(q, ShouldNotBeNil) |
456 So(q.(*queryImpl).err, ShouldBeNil) | 455 So(q.(*queryImpl).err, ShouldBeNil) |
457 qi := q.(*queryImpl).checkCorrectness("", false) | 456 qi := q.(*queryImpl).checkCorrectness("", false) |
458 So(qi.err, ShouldBeNil) | 457 So(qi.err, ShouldBeNil) |
459 }) | 458 }) |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
531 } | 530 } |
532 }) | 531 }) |
533 Convey("Bad cursors", func() { | 532 Convey("Bad cursors", func() { |
534 q := q.Start(queryCursor("")).End(queryCursor(""
)) | 533 q := q.Start(queryCursor("")).End(queryCursor(""
)) |
535 So(q.(*queryImpl).err.Error(), ShouldContainSubs
tring, "invalid cursor") | 534 So(q.(*queryImpl).err.Error(), ShouldContainSubs
tring, "invalid cursor") |
536 }) | 535 }) |
537 Convey("Bad ancestors", func() { | 536 Convey("Bad ancestors", func() { |
538 q := q.Ancestor(rds.NewKey("Goop", "wat", 10, ni
l)) | 537 q := q.Ancestor(rds.NewKey("Goop", "wat", 10, ni
l)) |
539 So(q, ShouldNotBeNil) | 538 So(q, ShouldNotBeNil) |
540 qi := q.(*queryImpl).checkCorrectness("", false) | 539 qi := q.(*queryImpl).checkCorrectness("", false) |
541 » » » » So(qi.err, ShouldEqual, gae.ErrDSInvalidKey) | 540 » » » » So(qi.err, ShouldEqual, rdsS.ErrInvalidKey) |
542 }) | 541 }) |
543 Convey("nil ancestors", func() { | 542 Convey("nil ancestors", func() { |
544 qi := q.Ancestor(nil).(*queryImpl).checkCorrectn
ess("", false) | 543 qi := q.Ancestor(nil).(*queryImpl).checkCorrectn
ess("", false) |
545 So(qi.err.Error(), ShouldContainSubstring, "nil
query ancestor") | 544 So(qi.err.Error(), ShouldContainSubstring, "nil
query ancestor") |
546 }) | 545 }) |
547 Convey("Bad key filters", func() { | 546 Convey("Bad key filters", func() { |
548 q := q.Filter("__key__ =", rds.NewKey("Goop", "w
at", 10, nil)) | 547 q := q.Filter("__key__ =", rds.NewKey("Goop", "w
at", 10, nil)) |
549 qi := q.(*queryImpl).checkCorrectness("", false) | 548 qi := q.(*queryImpl).checkCorrectness("", false) |
550 » » » » So(qi.err, ShouldEqual, gae.ErrDSInvalidKey) | 549 » » » » So(qi.err, ShouldEqual, rdsS.ErrInvalidKey) |
551 }) | 550 }) |
552 Convey("non-ancestor queries in a transaction", func() { | 551 Convey("non-ancestor queries in a transaction", func() { |
553 qi := q.(*queryImpl).checkCorrectness("", true) | 552 qi := q.(*queryImpl).checkCorrectness("", true) |
554 So(qi.err.Error(), ShouldContainSubstring, "Only
ancestor queries") | 553 So(qi.err.Error(), ShouldContainSubstring, "Only
ancestor queries") |
555 }) | 554 }) |
556 Convey("absurd numbers of filters are prohibited", func(
) { | 555 Convey("absurd numbers of filters are prohibited", func(
) { |
557 q := q.Ancestor(rds.NewKey("thing", "wat", 0, ni
l)) | 556 q := q.Ancestor(rds.NewKey("thing", "wat", 0, ni
l)) |
558 for i := 0; i < 100; i++ { | 557 for i := 0; i < 100; i++ { |
559 q = q.Filter("something =", 10) | 558 q = q.Filter("something =", 10) |
560 } | 559 } |
(...skipping 27 matching lines...) Expand all Loading... |
588 }) | 587 }) |
589 Convey("kindless with decending-__key__ orders", func()
{ | 588 Convey("kindless with decending-__key__ orders", func()
{ |
590 q := rds.NewQuery("").Order("-__key__") | 589 q := rds.NewQuery("").Order("-__key__") |
591 qi := q.(*queryImpl).checkCorrectness("", false) | 590 qi := q.(*queryImpl).checkCorrectness("", false) |
592 So(qi.err.Error(), ShouldContainSubstring, "kind
is required for all orders") | 591 So(qi.err.Error(), ShouldContainSubstring, "kind
is required for all orders") |
593 }) | 592 }) |
594 }) | 593 }) |
595 | 594 |
596 }) | 595 }) |
597 } | 596 } |
OLD | NEW |