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" |
(...skipping 16 matching lines...) Expand all Loading... |
27 key := rds.NewKey("nerd", "stringID", 0, nil) | 27 key := rds.NewKey("nerd", "stringID", 0, nil) |
28 So(key, ShouldNotBeNil) | 28 So(key, ShouldNotBeNil) |
29 So(key.Kind(), ShouldEqual, "nerd") | 29 So(key.Kind(), ShouldEqual, "nerd") |
30 So(key.StringID(), ShouldEqual, "stringID") | 30 So(key.StringID(), ShouldEqual, "stringID") |
31 So(key.IntID(), ShouldEqual, 0) | 31 So(key.IntID(), ShouldEqual, 0) |
32 So(key.Parent(), ShouldBeNil) | 32 So(key.Parent(), ShouldBeNil) |
33 So(key.AppID(), ShouldEqual, "dev~app") | 33 So(key.AppID(), ShouldEqual, "dev~app") |
34 So(key.Namespace(), ShouldEqual, "") | 34 So(key.Namespace(), ShouldEqual, "") |
35 So(key.String(), ShouldEqual, "/nerd,stringID") | 35 So(key.String(), ShouldEqual, "/nerd,stringID") |
36 So(rdsS.KeyIncomplete(key), ShouldBeFalse) | 36 So(rdsS.KeyIncomplete(key), ShouldBeFalse) |
37 » » » » So(rdsS.KeyValid(key, "", false), ShouldBeTrue) | 37 » » » » So(rdsS.KeyValid(key, false, "dev~app", ""), Sho
uldBeTrue) |
38 }) | 38 }) |
39 }) | 39 }) |
40 | 40 |
41 }) | 41 }) |
42 } | 42 } |
43 | 43 |
44 func testGetMeta(c context.Context, k rdsS.Key) int64 { | 44 func testGetMeta(c context.Context, k rdsS.Key) int64 { |
45 rds := rdsS.Get(c) | 45 rds := rdsS.Get(c) |
46 » k = rds.NewKey("__entity_group__", "", 1, rdsS.KeyRoot(k)) | 46 » retval := int64(0) |
47 » pmap := rdsS.PropertyMap{} | 47 » err := rds.GetMulti([]rdsS.Key{rds.NewKey("__entity_group__", "", 1, rds
S.KeyRoot(k))}, func(val rdsS.PropertyMap, err error) { |
48 » rds.Get(k, pmap) | 48 » » if err != nil { |
49 » return pmap["__version__"][0].Value().(int64) | 49 » » » panic(err) |
| 50 » » } |
| 51 » » retval = val["__version__"][0].Value().(int64) |
| 52 » }) |
| 53 » if err != nil { |
| 54 » » panic(err) |
| 55 » } |
| 56 » return retval |
50 } | 57 } |
51 | 58 |
52 var pls = rdsS.GetPLS | 59 var pls = rdsS.GetPLS |
53 | 60 |
54 func TestDatastoreSingleReadWriter(t *testing.T) { | 61 func TestDatastoreSingleReadWriter(t *testing.T) { |
55 t.Parallel() | 62 t.Parallel() |
56 | 63 |
| 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 |
57 Convey("Datastore single reads and writes", t, func() { | 106 Convey("Datastore single reads and writes", t, func() { |
58 c := Use(context.Background()) | 107 c := Use(context.Background()) |
59 rds := rdsS.Get(c) | 108 rds := rdsS.Get(c) |
60 So(rds, ShouldNotBeNil) | 109 So(rds, ShouldNotBeNil) |
61 | 110 |
62 Convey("implements DSSingleReadWriter", func() { | 111 Convey("implements DSSingleReadWriter", func() { |
63 type Foo struct { | 112 type Foo struct { |
64 Val int | 113 Val int |
65 } | 114 } |
66 | 115 |
67 Convey("invalid keys break", func() { | |
68 k := rds.NewKey("Foo", "", 0, nil) | |
69 So(rds.Get(k, nil), ShouldEqual, rdsS.ErrInvalid
Key) | |
70 | |
71 _, err := rds.Put(rds.NewKey("Foo", "", 0, k), p
ls(&Foo{})) | |
72 So(err, ShouldEqual, rdsS.ErrInvalidKey) | |
73 }) | |
74 | |
75 Convey("getting objects that DNE is an error", func() { | 116 Convey("getting objects that DNE is an error", func() { |
76 » » » » k := rds.NewKey("Foo", "", 1, nil) | 117 » » » » _, err := getOnePM(rds, rds.NewKey("Foo", "", 1,
nil)) |
77 » » » » So(rds.Get(k, nil), ShouldEqual, rdsS.ErrNoSuchE
ntity) | 118 » » » » So(err, ShouldEqual, rdsS.ErrNoSuchEntity) |
78 }) | 119 }) |
79 | 120 |
80 Convey("Can Put stuff", func() { | 121 Convey("Can Put stuff", func() { |
81 // with an incomplete key! | 122 // with an incomplete key! |
82 k := rds.NewKey("Foo", "", 0, nil) | 123 k := rds.NewKey("Foo", "", 0, nil) |
83 f := &Foo{Val: 10} | 124 f := &Foo{Val: 10} |
84 » » » » k, err := rds.Put(k, pls(f)) | 125 » » » » k = putOne(rds, k, f) |
85 » » » » So(err, ShouldBeNil) | |
86 So(k.String(), ShouldEqual, "/Foo,1") | 126 So(k.String(), ShouldEqual, "/Foo,1") |
87 | 127 |
88 Convey("and Get it back", func() { | 128 Convey("and Get it back", func() { |
89 newFoo := &Foo{} | 129 newFoo := &Foo{} |
90 » » » » » err := rds.Get(k, pls(newFoo)) | 130 » » » » » getOne(rds, k, newFoo) |
91 » » » » » So(err, ShouldBeNil) | |
92 So(newFoo, ShouldResemble, f) | 131 So(newFoo, ShouldResemble, f) |
93 | 132 |
94 Convey("and we can Delete it", func() { | 133 Convey("and we can Delete it", func() { |
95 » » » » » » err := rds.Delete(k) | 134 » » » » » » delOne(rds, k) |
96 » » » » » » So(err, ShouldBeNil) | 135 » » » » » » _, err := getOnePM(rds, k) |
97 | |
98 » » » » » » err = rds.Get(k, pls(newFoo)) | |
99 So(err, ShouldEqual, rdsS.ErrNoS
uchEntity) | 136 So(err, ShouldEqual, rdsS.ErrNoS
uchEntity) |
100 }) | 137 }) |
101 }) | 138 }) |
102 Convey("Deleteing with a bogus key is bad", func
() { | 139 Convey("Deleteing with a bogus key is bad", func
() { |
103 » » » » » err := rds.Delete(rds.NewKey("Foo", "wat
", 100, nil)) | 140 » » » » » So(delOneErr(rds, rds.NewKey("Foo", "wat
", 100, nil)), ShouldEqual, rdsS.ErrInvalidKey) |
104 » » » » » So(err, ShouldEqual, rdsS.ErrInvalidKey) | |
105 }) | 141 }) |
106 Convey("Deleteing a DNE entity is fine", func()
{ | 142 Convey("Deleteing a DNE entity is fine", func()
{ |
107 » » » » » err := rds.Delete(rds.NewKey("Foo", "wat
", 0, nil)) | 143 » » » » » delOne(rds, rds.NewKey("Foo", "wat", 0,
nil)) |
108 » » » » » So(err, ShouldBeNil) | |
109 }) | 144 }) |
110 | 145 |
111 Convey("with multiple puts", func() { | 146 Convey("with multiple puts", func() { |
112 So(testGetMeta(c, k), ShouldEqual, 1) | 147 So(testGetMeta(c, k), ShouldEqual, 1) |
113 | 148 |
114 keys := []rdsS.Key{} | 149 keys := []rdsS.Key{} |
115 » » » » » plss := []rdsS.PropertyLoadSaver{} | 150 » » » » » vals := []rdsS.PropertyLoadSaver{} |
116 | 151 |
117 pkey := k | 152 pkey := k |
118 for i := 0; i < 10; i++ { | 153 for i := 0; i < 10; i++ { |
119 keys = append(keys, rds.NewKey("
Foo", "", 0, pkey)) | 154 keys = append(keys, rds.NewKey("
Foo", "", 0, pkey)) |
120 » » » » » » plss = append(plss, pls(&Foo{Val
: 10})) | 155 » » » » » » vals = append(vals, pls(&Foo{Val
: 10})) |
121 } | 156 } |
122 » » » » » keys, err := rds.PutMulti(keys, plss) | 157 » » » » » i := 0 |
| 158 » » » » » err := rds.PutMulti(keys, vals, func(k r
dsS.Key, err error) { |
| 159 » » » » » » So(err, ShouldBeNil) |
| 160 » » » » » » keys[i] = k |
| 161 » » » » » » i++ |
| 162 » » » » » }) |
123 So(err, ShouldBeNil) | 163 So(err, ShouldBeNil) |
124 So(testGetMeta(c, k), ShouldEqual, 11) | 164 So(testGetMeta(c, k), ShouldEqual, 11) |
125 | 165 |
126 Convey("ensure that group versions persi
st across deletes", func() { | 166 Convey("ensure that group versions persi
st across deletes", func() { |
127 » » » » » » So(rds.Delete(k), ShouldBeNil) | 167 » » » » » » keys = append(keys, pkey) |
128 » » » » » » for i := int64(1); i < 11; i++ { | 168 » » » » » » err := rds.DeleteMulti(keys, fun
c(err error) { |
129 » » » » » » » So(rds.Delete(rds.NewKey
("Foo", "", i, k)), ShouldBeNil) | 169 » » » » » » » So(err, ShouldBeNil) |
130 » » » » » » } | 170 » » » » » » }) |
| 171 » » » » » » So(err, ShouldBeNil) |
| 172 |
131 // TODO(riannucci): replace with
a Count query instead of this cast | 173 // TODO(riannucci): replace with
a Count query instead of this cast |
132 » » » » » » ents := rds.(*dsImpl).data.store
.GetCollection("ents:") | 174 » » » » » » /* |
133 » » » » » » num, _ := ents.GetTotals() | 175 » » » » » » » ents := rds.(*dsImpl).da
ta.store.GetCollection("ents:") |
134 » » » » » » // /__entity_root_ids__,Foo | 176 » » » » » » » num, _ := ents.GetTotals
() |
135 » » » » » » // /Foo,1/__entity_group__,1 | 177 » » » » » » » // /__entity_root_ids__,
Foo |
136 » » » » » » // /Foo,1/__entity_group_ids__,1 | 178 » » » » » » » // /Foo,1/__entity_group
__,1 |
137 » » » » » » So(num, ShouldEqual, 3) | 179 » » » » » » » // /Foo,1/__entity_group
_ids__,1 |
| 180 » » » » » » » So(num, ShouldEqual, 3) |
| 181 » » » » » » */ |
138 | 182 |
139 » » » » » » So(curVersion(ents, groupMetaKey
(k)), ShouldEqual, 22) | 183 » » » » » » So(testGetMeta(c, k), ShouldEqua
l, 22) |
140 | 184 |
141 » » » » » » k, err := rds.Put(k, pls(f)) | 185 » » » » » » putOne(rds, k, f) |
142 » » » » » » So(err, ShouldBeNil) | |
143 So(testGetMeta(c, k), ShouldEqua
l, 23) | 186 So(testGetMeta(c, k), ShouldEqua
l, 23) |
144 }) | 187 }) |
145 | 188 |
146 » » » » » Convey("can GetMulti", func() { | 189 » » » » » Convey("can Get", func() { |
147 » » » » » » plss := make([]rdsS.PropertyLoad
Saver, len(keys)) | 190 » » » » » » vals := []rdsS.PropertyMap{} |
148 » » » » » » for i := range plss { | 191 » » » » » » err := rds.GetMulti(keys, func(p
m rdsS.PropertyMap, err error) { |
149 » » » » » » » plss[i] = rdsS.PropertyM
ap{} | 192 » » » » » » » So(err, ShouldBeNil) |
150 » » » » » » } | 193 » » » » » » » vals = append(vals, pm) |
151 » » » » » » err := rds.GetMulti(keys, plss) | 194 » » » » » » }) |
152 So(err, ShouldBeNil) | 195 So(err, ShouldBeNil) |
153 » » » » » » for _, pls := range plss { | 196 |
154 » » » » » » » So(pls.(rdsS.PropertyMap
), ShouldResemble, rdsS.PropertyMap{ | 197 » » » » » » for _, val := range vals { |
155 » » » » » » » » "Val": {rdsS.MkP
roperty(10)}, | 198 » » » » » » » So(val, ShouldResemble,
rdsS.PropertyMap{"Val": {rdsS.MkProperty(10)}}) |
156 » » » » » » » }) | |
157 } | 199 } |
158 }) | 200 }) |
159 }) | 201 }) |
160 }) | 202 }) |
161 }) | 203 }) |
162 | 204 |
163 Convey("implements DSTransactioner", func() { | 205 Convey("implements DSTransactioner", func() { |
164 type Foo struct { | 206 type Foo struct { |
165 Val int | 207 Val int |
166 } | 208 } |
167 Convey("Put", func() { | 209 Convey("Put", func() { |
168 k := rds.NewKey("Foo", "", 0, nil) | |
169 f := &Foo{Val: 10} | 210 f := &Foo{Val: 10} |
170 » » » » k, err := rds.Put(k, pls(f)) | 211 » » » » origKey := rds.NewKey("Foo", "", 0, nil) |
171 » » » » So(err, ShouldBeNil) | 212 » » » » k := putOne(rds, origKey, f) |
172 So(k.String(), ShouldEqual, "/Foo,1") | 213 So(k.String(), ShouldEqual, "/Foo,1") |
173 | 214 |
174 Convey("can Put new entity groups", func() { | 215 Convey("can Put new entity groups", func() { |
175 err := rds.RunInTransaction(func(c conte
xt.Context) error { | 216 err := rds.RunInTransaction(func(c conte
xt.Context) error { |
176 rds := rdsS.Get(c) | 217 rds := rdsS.Get(c) |
177 So(rds, ShouldNotBeNil) | |
178 | 218 |
179 f1 := &Foo{Val: 100} | 219 f1 := &Foo{Val: 100} |
180 » » » » » » k, err := rds.Put(rds.NewKey("Fo
o", "", 0, nil), pls(f1)) | 220 » » » » » » k := putOne(rds, origKey, f1) |
181 » » » » » » So(err, ShouldBeNil) | |
182 So(k.String(), ShouldEqual, "/Fo
o,2") | 221 So(k.String(), ShouldEqual, "/Fo
o,2") |
183 | 222 |
184 f2 := &Foo{Val: 200} | 223 f2 := &Foo{Val: 200} |
185 » » » » » » k, err = rds.Put(rds.NewKey("Foo
", "", 0, nil), pls(f2)) | 224 » » » » » » k = putOne(rds, origKey, f2) |
186 » » » » » » So(err, ShouldBeNil) | |
187 So(k.String(), ShouldEqual, "/Fo
o,3") | 225 So(k.String(), ShouldEqual, "/Fo
o,3") |
188 | 226 |
189 return nil | 227 return nil |
190 }, &rdsS.TransactionOptions{XG: true}) | 228 }, &rdsS.TransactionOptions{XG: true}) |
191 So(err, ShouldBeNil) | 229 So(err, ShouldBeNil) |
192 | 230 |
193 f := &Foo{} | 231 f := &Foo{} |
194 » » » » » So(rds.Get(rds.NewKey("Foo", "", 2, nil)
, pls(f)), ShouldBeNil) | 232 » » » » » getOne(rds, rds.NewKey("Foo", "", 2, nil
), f) |
195 So(f.Val, ShouldEqual, 100) | 233 So(f.Val, ShouldEqual, 100) |
196 | 234 |
197 » » » » » f = &Foo{} | 235 » » » » » getOne(rds, rds.NewKey("Foo", "", 3, nil
), f) |
198 » » » » » So(rds.Get(rds.NewKey("Foo", "", 3, nil)
, pls(f)), ShouldBeNil) | |
199 So(f.Val, ShouldEqual, 200) | 236 So(f.Val, ShouldEqual, 200) |
200 }) | 237 }) |
201 | 238 |
202 Convey("can Put new entities in a current group"
, func() { | 239 Convey("can Put new entities in a current group"
, func() { |
| 240 par := k |
203 err := rds.RunInTransaction(func(c conte
xt.Context) error { | 241 err := rds.RunInTransaction(func(c conte
xt.Context) error { |
204 rds := rdsS.Get(c) | 242 rds := rdsS.Get(c) |
205 So(rds, ShouldNotBeNil) | 243 So(rds, ShouldNotBeNil) |
206 | 244 |
207 par := k | |
208 | |
209 f1 := &Foo{Val: 100} | 245 f1 := &Foo{Val: 100} |
210 » » » » » » k, err := rds.Put(rds.NewKey("Fo
o", "", 0, par), pls(f1)) | 246 » » » » » » k := putOne(rds, rds.NewKey("Foo
", "", 0, par), f1) |
211 » » » » » » So(err, ShouldBeNil) | |
212 So(k.String(), ShouldEqual, "/Fo
o,1/Foo,1") | 247 So(k.String(), ShouldEqual, "/Fo
o,1/Foo,1") |
213 | 248 |
214 f2 := &Foo{Val: 200} | 249 f2 := &Foo{Val: 200} |
215 » » » » » » k, err = rds.Put(rds.NewKey("Foo
", "", 0, par), pls(f2)) | 250 » » » » » » k = putOne(rds, rds.NewKey("Foo"
, "", 0, par), f2) |
216 » » » » » » So(err, ShouldBeNil) | |
217 So(k.String(), ShouldEqual, "/Fo
o,1/Foo,2") | 251 So(k.String(), ShouldEqual, "/Fo
o,1/Foo,2") |
218 | 252 |
219 return nil | 253 return nil |
220 }, nil) | 254 }, nil) |
221 So(err, ShouldBeNil) | 255 So(err, ShouldBeNil) |
222 | 256 |
223 » » » » » f1 := &Foo{} | 257 » » » » » f := &Foo{} |
224 » » » » » So(rds.Get(rds.NewKey("Foo", "", 1, k),
pls(f1)), ShouldBeNil) | 258 » » » » » getOne(rds, rds.NewKey("Foo", "", 1, k),
f) |
225 » » » » » So(f1.Val, ShouldEqual, 100) | 259 » » » » » So(f.Val, ShouldEqual, 100) |
226 | 260 |
227 » » » » » f2 := &Foo{} | 261 » » » » » getOne(rds, rds.NewKey("Foo", "", 2, k),
f) |
228 » » » » » So(rds.Get(rds.NewKey("Foo", "", 2, k),
pls(f2)), ShouldBeNil) | 262 » » » » » So(f.Val, ShouldEqual, 200) |
229 » » » » » So(f2.Val, ShouldEqual, 200) | |
230 }) | 263 }) |
231 | 264 |
232 Convey("Deletes work too", func() { | 265 Convey("Deletes work too", func() { |
233 err := rds.RunInTransaction(func(c conte
xt.Context) error { | 266 err := rds.RunInTransaction(func(c conte
xt.Context) error { |
234 rds := rdsS.Get(c) | 267 rds := rdsS.Get(c) |
235 So(rds, ShouldNotBeNil) | 268 So(rds, ShouldNotBeNil) |
236 » » » » » » So(rds.Delete(k), ShouldBeNil) | 269 » » » » » » delOne(rds, k) |
237 return nil | 270 return nil |
238 }, nil) | 271 }, nil) |
239 So(err, ShouldBeNil) | 272 So(err, ShouldBeNil) |
240 » » » » » So(rds.Get(k, nil), ShouldEqual, rdsS.Er
rNoSuchEntity) | 273 » » » » » _, err = getOnePM(rds, k) |
| 274 » » » » » So(err, ShouldEqual, rdsS.ErrNoSuchEntit
y) |
241 }) | 275 }) |
242 | 276 |
243 Convey("A Get counts against your group count",
func() { | 277 Convey("A Get counts against your group count",
func() { |
244 err := rds.RunInTransaction(func(c conte
xt.Context) error { | 278 err := rds.RunInTransaction(func(c conte
xt.Context) error { |
245 rds := rdsS.Get(c) | 279 rds := rdsS.Get(c) |
246 » » » » » » So(rds.Get(rds.NewKey("Foo", "",
20, nil), nil), ShouldEqual, rdsS.ErrNoSuchEntity) | 280 |
247 » » » » » » So(rds.Get(k, nil).Error(), Shou
ldContainSubstring, "cross-group") | 281 » » » » » » _, err := getOnePM(rds, rds.NewK
ey("Foo", "", 20, nil)) |
| 282 » » » » » » So(err, ShouldEqual, rdsS.ErrNoS
uchEntity) |
| 283 |
| 284 » » » » » » err = rds.GetMulti([]rdsS.Key{k}
, func(_ rdsS.PropertyMap, err error) { |
| 285 » » » » » » » So(err, ShouldBeNil) |
| 286 » » » » » » }) |
| 287 » » » » » » So(err.Error(), ShouldContainSub
string, "cross-group") |
248 return nil | 288 return nil |
249 }, nil) | 289 }, nil) |
250 So(err, ShouldBeNil) | 290 So(err, ShouldBeNil) |
251 }) | 291 }) |
252 | 292 |
253 Convey("Get takes a snapshot", func() { | 293 Convey("Get takes a snapshot", func() { |
254 err := rds.RunInTransaction(func(c conte
xt.Context) error { | 294 err := rds.RunInTransaction(func(c conte
xt.Context) error { |
255 txnDS := rdsS.Get(c) | 295 txnDS := rdsS.Get(c) |
256 So(txnDS, ShouldNotBeNil) | 296 So(txnDS, ShouldNotBeNil) |
257 | 297 |
258 » » » » » » So(txnDS.Get(k, pls(f)), ShouldB
eNil) | 298 » » » » » » getOne(txnDS, k, f) |
259 So(f.Val, ShouldEqual, 10) | 299 So(f.Val, ShouldEqual, 10) |
260 | 300 |
261 // Don't ever do this in a real
program unless you want to guarantee | 301 // Don't ever do this in a real
program unless you want to guarantee |
262 // a failed transaction :) | 302 // a failed transaction :) |
263 f.Val = 11 | 303 f.Val = 11 |
264 » » » » » » _, err := rds.Put(k, pls(f)) | 304 » » » » » » putOne(rds, k, f) |
265 » » » » » » So(err, ShouldBeNil) | |
266 | 305 |
267 » » » » » » So(txnDS.Get(k, pls(f)), ShouldB
eNil) | 306 » » » » » » getOne(txnDS, k, f) |
268 So(f.Val, ShouldEqual, 10) | 307 So(f.Val, ShouldEqual, 10) |
269 | 308 |
270 return nil | 309 return nil |
271 }, nil) | 310 }, nil) |
272 So(err, ShouldBeNil) | 311 So(err, ShouldBeNil) |
273 | 312 |
274 f := &Foo{} | 313 f := &Foo{} |
275 » » » » » So(rds.Get(k, pls(f)), ShouldBeNil) | 314 » » » » » getOne(rds, k, f) |
276 So(f.Val, ShouldEqual, 11) | 315 So(f.Val, ShouldEqual, 11) |
277 }) | 316 }) |
278 | 317 |
279 Convey("and snapshots are consistent even after
Puts", func() { | 318 Convey("and snapshots are consistent even after
Puts", func() { |
280 err := rds.RunInTransaction(func(c conte
xt.Context) error { | 319 err := rds.RunInTransaction(func(c conte
xt.Context) error { |
281 txnDS := rdsS.Get(c) | 320 txnDS := rdsS.Get(c) |
282 So(txnDS, ShouldNotBeNil) | 321 So(txnDS, ShouldNotBeNil) |
283 | 322 |
284 f := &Foo{} | 323 f := &Foo{} |
285 » » » » » » So(txnDS.Get(k, pls(f)), ShouldB
eNil) | 324 » » » » » » getOne(txnDS, k, f) |
286 So(f.Val, ShouldEqual, 10) | 325 So(f.Val, ShouldEqual, 10) |
287 | 326 |
288 // Don't ever do this in a real
program unless you want to guarantee | 327 // Don't ever do this in a real
program unless you want to guarantee |
289 // a failed transaction :) | 328 // a failed transaction :) |
290 f.Val = 11 | 329 f.Val = 11 |
| 330 putOne(rds, k, f) |
291 | 331 |
292 » » » » » » _, err := rds.Put(k, pls(f)) | 332 » » » » » » getOne(txnDS, k, f) |
293 » » » » » » So(err, ShouldBeNil) | |
294 | |
295 » » » » » » So(txnDS.Get(k, pls(f)), ShouldB
eNil) | |
296 So(f.Val, ShouldEqual, 10) | 333 So(f.Val, ShouldEqual, 10) |
297 | 334 |
298 f.Val = 20 | 335 f.Val = 20 |
299 » » » » » » _, err = txnDS.Put(k, pls(f)) | 336 » » » » » » putOne(txnDS, k, f) |
300 » » » » » » So(err, ShouldBeNil) | |
301 | 337 |
302 » » » » » » So(txnDS.Get(k, pls(f)), ShouldB
eNil) | 338 » » » » » » getOne(txnDS, k, f) |
303 So(f.Val, ShouldEqual, 10) // st
ill gets 10 | 339 So(f.Val, ShouldEqual, 10) // st
ill gets 10 |
304 | 340 |
305 return nil | 341 return nil |
306 }, nil) | 342 }, nil) |
307 So(err.Error(), ShouldContainSubstring,
"concurrent") | 343 So(err.Error(), ShouldContainSubstring,
"concurrent") |
308 | 344 |
309 f := &Foo{} | 345 f := &Foo{} |
310 » » » » » So(rds.Get(k, pls(f)), ShouldBeNil) | 346 » » » » » getOne(rds, k, f) |
311 So(f.Val, ShouldEqual, 11) | 347 So(f.Val, ShouldEqual, 11) |
312 }) | 348 }) |
313 | 349 |
314 Convey("Reusing a transaction context is bad new
s", func() { | 350 Convey("Reusing a transaction context is bad new
s", func() { |
315 k := rds.NewKey("Foo", "", 1, nil) | 351 k := rds.NewKey("Foo", "", 1, nil) |
316 txnDS := rdsS.Interface(nil) | 352 txnDS := rdsS.Interface(nil) |
317 err := rds.RunInTransaction(func(c conte
xt.Context) error { | 353 err := rds.RunInTransaction(func(c conte
xt.Context) error { |
318 txnDS = rdsS.Get(c) | 354 txnDS = rdsS.Get(c) |
319 » » » » » » So(txnDS.Get(k, rdsS.PropertyMap
{}), ShouldBeNil) | 355 » » » » » » getOnePM(txnDS, k) |
320 return nil | 356 return nil |
321 }, nil) | 357 }, nil) |
322 So(err, ShouldBeNil) | 358 So(err, ShouldBeNil) |
323 » » » » » So(txnDS.Get(k, rdsS.PropertyMap{}).Erro
r(), ShouldContainSubstring, "expired") | 359 » » » » » err = txnDS.GetMulti([]rdsS.Key{k}, func
(_ rdsS.PropertyMap, err error) { |
| 360 » » » » » » So(err, ShouldBeNil) |
| 361 » » » » » }) |
| 362 » » » » » So(err.Error(), ShouldContainSubstring,
"expired") |
324 }) | 363 }) |
325 | 364 |
326 Convey("Nested transactions are rejected", func(
) { | 365 Convey("Nested transactions are rejected", func(
) { |
327 err := rds.RunInTransaction(func(c conte
xt.Context) error { | 366 err := rds.RunInTransaction(func(c conte
xt.Context) error { |
328 err := rdsS.Get(c).RunInTransact
ion(func(c context.Context) error { | 367 err := rdsS.Get(c).RunInTransact
ion(func(c context.Context) error { |
329 panic("noooo") | 368 panic("noooo") |
330 }, nil) | 369 }, nil) |
331 So(err.Error(), ShouldContainSub
string, "nested transactions") | 370 So(err.Error(), ShouldContainSub
string, "nested transactions") |
332 return nil | 371 return nil |
333 }, nil) | 372 }, nil) |
334 So(err, ShouldBeNil) | 373 So(err, ShouldBeNil) |
335 }) | 374 }) |
336 | 375 |
337 Convey("Concurrent transactions only accept one
set of changes", func() { | 376 Convey("Concurrent transactions only accept one
set of changes", func() { |
338 // Note: I think this implementation is
actually /slightly/ wrong. | 377 // Note: I think this implementation is
actually /slightly/ wrong. |
339 // Accorting to my read of the docs for
appengine, when you open a | 378 // Accorting to my read of the docs for
appengine, when you open a |
340 // transaction it actually (essentially)
holds a reference to the | 379 // transaction it actually (essentially)
holds a reference to the |
341 // entire datastore. Our implementation
takes a snapshot of the | 380 // entire datastore. Our implementation
takes a snapshot of the |
342 // entity group as soon as something obs
erves/affects it. | 381 // entity group as soon as something obs
erves/affects it. |
343 // | 382 // |
344 // That said... I'm not sure if there's
really a semantic difference. | 383 // That said... I'm not sure if there's
really a semantic difference. |
345 err := rds.RunInTransaction(func(c conte
xt.Context) error { | 384 err := rds.RunInTransaction(func(c conte
xt.Context) error { |
346 txnDS := rdsS.Get(c) | 385 txnDS := rdsS.Get(c) |
347 f := &Foo{Val: 21} | 386 f := &Foo{Val: 21} |
348 » » » » » » _, err = txnDS.Put(k, pls(f)) | 387 » » » » » » putOne(txnDS, k, f) |
349 » » » » » » So(err, ShouldBeNil) | |
350 | 388 |
351 err := rds.RunInTransaction(func
(c context.Context) error { | 389 err := rds.RunInTransaction(func
(c context.Context) error { |
352 txnDS := rdsS.Get(c) | 390 txnDS := rdsS.Get(c) |
353 f := &Foo{Val: 27} | 391 f := &Foo{Val: 27} |
354 » » » » » » » _, err := txnDS.Put(k, p
ls(f)) | 392 » » » » » » » putOne(txnDS, k, f) |
355 » » » » » » » So(err, ShouldBeNil) | |
356 return nil | 393 return nil |
357 }, nil) | 394 }, nil) |
358 So(err, ShouldBeNil) | 395 So(err, ShouldBeNil) |
359 | 396 |
360 return nil | 397 return nil |
361 }, nil) | 398 }, nil) |
362 So(err.Error(), ShouldContainSubstring,
"concurrent") | 399 So(err.Error(), ShouldContainSubstring,
"concurrent") |
363 | 400 |
364 f := &Foo{} | 401 f := &Foo{} |
365 » » » » » So(rds.Get(k, pls(f)), ShouldBeNil) | 402 » » » » » getOne(rds, k, f) |
366 So(f.Val, ShouldEqual, 27) | 403 So(f.Val, ShouldEqual, 27) |
367 }) | 404 }) |
368 | 405 |
369 Convey("XG", func() { | 406 Convey("XG", func() { |
370 Convey("Modifying two groups with XG=fal
se is invalid", func() { | 407 Convey("Modifying two groups with XG=fal
se is invalid", func() { |
371 err := rds.RunInTransaction(func
(c context.Context) error { | 408 err := rds.RunInTransaction(func
(c context.Context) error { |
372 rds := rdsS.Get(c) | 409 rds := rdsS.Get(c) |
373 f := &Foo{Val: 200} | 410 f := &Foo{Val: 200} |
374 » » » » » » » _, err := rds.Put(k, pls
(f)) | 411 » » » » » » » putOne(rds, k, f) |
375 » » » » » » » So(err, ShouldBeNil) | |
376 | 412 |
377 » » » » » » » _, err = rds.Put(rds.New
Key("Foo", "", 2, nil), pls(f)) | 413 » » » » » » » _, err := putOneErr(rds,
rds.NewKey("Foo", "", 2, nil), f) |
378 So(err.Error(), ShouldCo
ntainSubstring, "cross-group") | 414 So(err.Error(), ShouldCo
ntainSubstring, "cross-group") |
379 return err | 415 return err |
380 }, nil) | 416 }, nil) |
381 So(err.Error(), ShouldContainSub
string, "cross-group") | 417 So(err.Error(), ShouldContainSub
string, "cross-group") |
382 }) | 418 }) |
383 | 419 |
384 Convey("Modifying >25 groups with XG=tru
e is invald", func() { | 420 Convey("Modifying >25 groups with XG=tru
e is invald", func() { |
385 err := rds.RunInTransaction(func
(c context.Context) error { | 421 err := rds.RunInTransaction(func
(c context.Context) error { |
386 rds := rdsS.Get(c) | 422 rds := rdsS.Get(c) |
387 for i := int64(1); i < 2
6; i++ { | 423 for i := int64(1); i < 2
6; i++ { |
388 k := rds.NewKey(
"Foo", "", i, nil) | 424 k := rds.NewKey(
"Foo", "", i, nil) |
389 f := &Foo{Val: 2
00} | 425 f := &Foo{Val: 2
00} |
390 » » » » » » » » _, err := rds.Pu
t(k, pls(f)) | 426 » » » » » » » » putOne(rds, k, f
) |
391 » » » » » » » » So(err, ShouldBe
Nil) | |
392 } | 427 } |
393 f := &Foo{Val: 200} | 428 f := &Foo{Val: 200} |
394 » » » » » » » _, err := rds.Put(rds.Ne
wKey("Foo", "", 27, nil), pls(f)) | 429 » » » » » » » _, err := putOneErr(rds,
rds.NewKey("Foo", "", 27, nil), f) |
395 So(err.Error(), ShouldCo
ntainSubstring, "too many entity groups") | 430 So(err.Error(), ShouldCo
ntainSubstring, "too many entity groups") |
396 return err | 431 return err |
397 }, &rdsS.TransactionOptions{XG:
true}) | 432 }, &rdsS.TransactionOptions{XG:
true}) |
398 So(err.Error(), ShouldContainSub
string, "too many entity groups") | 433 So(err.Error(), ShouldContainSub
string, "too many entity groups") |
399 }) | 434 }) |
400 }) | 435 }) |
401 | 436 |
402 Convey("Errors and panics", func() { | 437 Convey("Errors and panics", func() { |
403 Convey("returning an error aborts", func
() { | 438 Convey("returning an error aborts", func
() { |
404 err := rds.RunInTransaction(func
(c context.Context) error { | 439 err := rds.RunInTransaction(func
(c context.Context) error { |
405 rds := rdsS.Get(c) | 440 rds := rdsS.Get(c) |
406 f := &Foo{Val: 200} | 441 f := &Foo{Val: 200} |
407 » » » » » » » _, err := rds.Put(k, pls
(f)) | 442 » » » » » » » putOne(rds, k, f) |
408 » » » » » » » So(err, ShouldBeNil) | |
409 | 443 |
410 return fmt.Errorf("thing
y") | 444 return fmt.Errorf("thing
y") |
411 }, nil) | 445 }, nil) |
412 So(err.Error(), ShouldEqual, "th
ingy") | 446 So(err.Error(), ShouldEqual, "th
ingy") |
413 | 447 |
414 f := &Foo{} | 448 f := &Foo{} |
415 » » » » » » So(rds.Get(k, pls(f)), ShouldBeN
il) | 449 » » » » » » getOne(rds, k, f) |
416 So(f.Val, ShouldEqual, 10) | 450 So(f.Val, ShouldEqual, 10) |
417 }) | 451 }) |
418 | 452 |
419 Convey("panicing aborts", func() { | 453 Convey("panicing aborts", func() { |
420 So(func() { | 454 So(func() { |
421 rds.RunInTransaction(fun
c(c context.Context) error { | 455 rds.RunInTransaction(fun
c(c context.Context) error { |
422 rds := rdsS.Get(
c) | 456 rds := rdsS.Get(
c) |
423 f := &Foo{Val: 2
00} | 457 f := &Foo{Val: 2
00} |
424 » » » » » » » » _, err := rds.Pu
t(k, pls(f)) | 458 » » » » » » » » putOne(rds, k, f
) |
425 » » » » » » » » So(err, ShouldBe
Nil) | |
426 panic("wheeeeee"
) | 459 panic("wheeeeee"
) |
427 }, nil) | 460 }, nil) |
428 }, ShouldPanic) | 461 }, ShouldPanic) |
429 | 462 |
430 f := &Foo{} | 463 f := &Foo{} |
431 » » » » » » So(rds.Get(k, pls(f)), ShouldBeN
il) | 464 » » » » » » getOne(rds, k, f) |
432 So(f.Val, ShouldEqual, 10) | 465 So(f.Val, ShouldEqual, 10) |
433 }) | 466 }) |
434 }) | 467 }) |
435 }) | 468 }) |
436 }) | 469 }) |
437 | 470 |
438 }) | 471 }) |
439 } | 472 } |
440 | 473 |
441 const MaxUint = ^uint(0) | 474 const MaxUint = ^uint(0) |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
587 }) | 620 }) |
588 Convey("kindless with decending-__key__ orders", func()
{ | 621 Convey("kindless with decending-__key__ orders", func()
{ |
589 q := rds.NewQuery("").Order("-__key__") | 622 q := rds.NewQuery("").Order("-__key__") |
590 qi := q.(*queryImpl).checkCorrectness("", false) | 623 qi := q.(*queryImpl).checkCorrectness("", false) |
591 So(qi.err.Error(), ShouldContainSubstring, "kind
is required for all orders") | 624 So(qi.err.Error(), ShouldContainSubstring, "kind
is required for all orders") |
592 }) | 625 }) |
593 }) | 626 }) |
594 | 627 |
595 }) | 628 }) |
596 } | 629 } |
OLD | NEW |