| 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 |