| 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 » "infra/gae/libs/gae" | 9 » "infra/gae/libs/meta" |
| 10 » "infra/gae/libs/gae/helper" | 10 » "infra/gae/libs/wrapper" |
| 11 "math" | 11 "math" |
| 12 "testing" | 12 "testing" |
| 13 | 13 |
| 14 . "github.com/smartystreets/goconvey/convey" | 14 . "github.com/smartystreets/goconvey/convey" |
| 15 "golang.org/x/net/context" | 15 "golang.org/x/net/context" |
| 16 |
| 17 "appengine/datastore" |
| 16 ) | 18 ) |
| 17 | 19 |
| 18 func TestDatastoreKinder(t *testing.T) { | 20 func TestDatastoreKinder(t *testing.T) { |
| 19 t.Parallel() | 21 t.Parallel() |
| 20 | 22 |
| 21 » Convey("Datastore keys", t, func() { | 23 » Convey("Datastore kinds and keys", t, func() { |
| 22 c := Use(context.Background()) | 24 c := Use(context.Background()) |
| 23 » » rds := gae.GetRDS(c) | 25 » » ds := wrapper.GetDS(c) |
| 24 » » So(rds, ShouldNotBeNil) | 26 » » So(ds, ShouldNotBeNil) |
| 27 |
| 28 » » Convey("implements DSKinder", func() { |
| 29 » » » type Foo struct{} |
| 30 » » » So(ds.Kind(&Foo{}), ShouldEqual, "Foo") |
| 31 |
| 32 » » » Convey("which can be tweaked by DSKindSetter", func() { |
| 33 » » » » ds.SetKindNameResolver(func(interface{}) string
{ return "spam" }) |
| 34 » » » » So(ds.Kind(&Foo{}), ShouldEqual, "spam") |
| 35 |
| 36 » » » » Convey("and it retains the function so you can s
tack them", func() { |
| 37 » » » » » cur := ds.KindNameResolver() |
| 38 » » » » » ds.SetKindNameResolver(func(o interface{
}) string { return "wat" + cur(o) }) |
| 39 » » » » » So(ds.Kind(&Foo{}), ShouldEqual, "watspa
m") |
| 40 » » » » }) |
| 41 » » » }) |
| 42 » » }) |
| 25 | 43 |
| 26 Convey("implements DSNewKeyer", func() { | 44 Convey("implements DSNewKeyer", func() { |
| 27 Convey("NewKey", func() { | 45 Convey("NewKey", func() { |
| 28 » » » » key := rds.NewKey("nerd", "stringID", 0, nil) | 46 » » » » key := ds.NewKey("nerd", "stringID", 0, nil) |
| 29 So(key, ShouldNotBeNil) | 47 So(key, ShouldNotBeNil) |
| 30 So(key.Kind(), ShouldEqual, "nerd") | 48 So(key.Kind(), ShouldEqual, "nerd") |
| 31 So(key.StringID(), ShouldEqual, "stringID") | 49 So(key.StringID(), ShouldEqual, "stringID") |
| 32 So(key.IntID(), ShouldEqual, 0) | 50 So(key.IntID(), ShouldEqual, 0) |
| 33 So(key.Parent(), ShouldBeNil) | 51 So(key.Parent(), ShouldBeNil) |
| 34 » » » » So(key.AppID(), ShouldEqual, "dev~app") | 52 » » » » So(key.AppID(), ShouldEqual, "dev~my~app") |
| 35 So(key.Namespace(), ShouldEqual, "") | 53 So(key.Namespace(), ShouldEqual, "") |
| 36 So(key.String(), ShouldEqual, "/nerd,stringID") | 54 So(key.String(), ShouldEqual, "/nerd,stringID") |
| 37 » » » » So(helper.DSKeyIncomplete(key), ShouldBeFalse) | 55 » » » » So(key.Incomplete(), ShouldBeFalse) |
| 38 » » » » So(helper.DSKeyValid(key, "", false), ShouldBeTr
ue) | 56 » » » » So(keyValid("", key, userKeyOnly), ShouldBeTrue) |
| 57 |
| 58 » » » » chkey := ds.NewKey("wat", "", 100, key) |
| 59 » » » » So(chkey, ShouldNotBeNil) |
| 60 » » » » So(chkey.Kind(), ShouldEqual, "wat") |
| 61 » » » » So(chkey.StringID(), ShouldEqual, "") |
| 62 » » » » So(chkey.IntID(), ShouldEqual, 100) |
| 63 » » » » So(chkey.Parent(), ShouldEqual, key) |
| 64 » » » » So(chkey.AppID(), ShouldEqual, "dev~my~app") |
| 65 » » » » So(chkey.Namespace(), ShouldEqual, "") |
| 66 » » » » So(chkey.String(), ShouldEqual, "/nerd,stringID/
wat,100") |
| 67 » » » » So(key.Incomplete(), ShouldBeFalse) |
| 68 » » » » So(keyValid("", chkey, userKeyOnly), ShouldBeTru
e) |
| 69 |
| 70 » » » » incompl := ds.NewKey("sup", "", 0, key) |
| 71 » » » » So(incompl, ShouldNotBeNil) |
| 72 » » » » So(incompl.Incomplete(), ShouldBeTrue) |
| 73 » » » » So(keyValid("", incompl, userKeyOnly), ShouldBeT
rue) |
| 74 » » » » So(incompl.String(), ShouldEqual, "/nerd,stringI
D/sup,0") |
| 75 |
| 76 » » » » bad := ds.NewKey("nooo", "", 10, incompl) |
| 77 » » » » So(bad, ShouldNotBeNil) |
| 78 » » » » So(bad.Incomplete(), ShouldBeFalse) |
| 79 » » » » So(keyValid("", bad, userKeyOnly), ShouldBeFalse
) |
| 80 » » » » So(bad.String(), ShouldEqual, "/nerd,stringID/su
p,0/nooo,10") |
| 81 |
| 82 » » » » So(rootKey(bad), ShouldEqual, key) |
| 83 |
| 84 » » » » Convey("other key validation", func() { |
| 85 » » » » » So(keyValid("", nil, userKeyOnly), Shoul
dBeFalse) |
| 86 |
| 87 » » » » » key := ds.NewKey("", "", 0, nil) |
| 88 » » » » » So(key, ShouldNotBeNil) |
| 89 |
| 90 » » » » » So(keyValid("", key, userKeyOnly), Shoul
dBeFalse) |
| 91 |
| 92 » » » » » key = ds.NewKey("noop", "power level", 9
000, nil) |
| 93 » » » » » So(key, ShouldNotBeNil) |
| 94 |
| 95 » » » » » So(keyValid("", key, userKeyOnly), Shoul
dBeFalse) |
| 96 » » » » }) |
| 97 » » » }) |
| 98 |
| 99 » » » Convey("NewKeyObj", func() { |
| 100 » » » » type Foo struct { |
| 101 » » » » » _knd string `goon:"kind,coool"
` |
| 102 » » » » » ID int64 `goon:"id"` |
| 103 » » » » » Parent *datastore.Key `goon:"parent"` |
| 104 » » » » } |
| 105 » » » » f := &Foo{ID: 100} |
| 106 » » » » k := ds.NewKeyObj(f) |
| 107 » » » » So(k.String(), ShouldEqual, "/coool,100") |
| 108 |
| 109 » » » » f.Parent = k |
| 110 » » » » f._knd = "weevils" |
| 111 » » » » f.ID = 19 |
| 112 » » » » k = ds.NewKeyObj(f) |
| 113 » » » » So(k.String(), ShouldEqual, "/coool,100/weevils,
19") |
| 114 |
| 115 » » » » Convey("panics when you do a dumb thing", func()
{ |
| 116 » » » » » type Foo struct { |
| 117 » » » » » » ID []byte `goon:"id"` |
| 118 » » » » » } |
| 119 » » » » » So(func() { ds.NewKeyObj(&Foo{}) }, Shou
ldPanic) |
| 120 » » » » }) |
| 121 » » » }) |
| 122 |
| 123 » » » Convey("NewKeyObjError", func() { |
| 124 » » » » type Foo struct { |
| 125 » » » » » ID []byte `goon:"id"` |
| 126 » » » » } |
| 127 » » » » _, err := ds.NewKeyObjError(&Foo{}) |
| 128 » » » » So(err.Error(), ShouldContainSubstring, "must be
int64 or string") |
| 39 }) | 129 }) |
| 40 }) | 130 }) |
| 41 | 131 |
| 42 }) | 132 }) |
| 43 } | 133 } |
| 44 | 134 |
| 45 func testGetMeta(c context.Context, k gae.DSKey) int64 { | |
| 46 rds := gae.GetRDS(c) | |
| 47 k = rds.NewKey("__entity_group__", "", 1, helper.DSKeyRoot(k)) | |
| 48 pmap := gae.DSPropertyMap{} | |
| 49 rds.Get(k, &pmap) | |
| 50 return pmap["__version__"][0].Value().(int64) | |
| 51 } | |
| 52 | |
| 53 func TestDatastoreSingleReadWriter(t *testing.T) { | 135 func TestDatastoreSingleReadWriter(t *testing.T) { |
| 54 t.Parallel() | 136 t.Parallel() |
| 55 | 137 |
| 56 Convey("Datastore single reads and writes", t, func() { | 138 Convey("Datastore single reads and writes", t, func() { |
| 57 c := Use(context.Background()) | 139 c := Use(context.Background()) |
| 58 » » rds := gae.GetRDS(c) | 140 » » ds := wrapper.GetDS(c) |
| 59 » » So(rds, ShouldNotBeNil) | 141 » » So(ds, ShouldNotBeNil) |
| 60 | 142 |
| 61 Convey("implements DSSingleReadWriter", func() { | 143 Convey("implements DSSingleReadWriter", func() { |
| 62 type Foo struct { | 144 type Foo struct { |
| 63 » » » » Val int | 145 » » » » ID int64 `goon:"id" datastore:"-"` |
| 146 » » » » Parent *datastore.Key `goon:"parent" datastore:"
-"` |
| 147 » » » » Val int |
| 64 } | 148 } |
| 65 | 149 |
| 66 Convey("invalid keys break", func() { | 150 Convey("invalid keys break", func() { |
| 67 » » » » k := rds.NewKey("Foo", "", 0, nil) | 151 » » » » k := ds.NewKeyObj(&Foo{}) |
| 68 » » » » So(rds.Get(k, nil), ShouldEqual, gae.ErrDSInvali
dKey) | 152 » » » » f := &Foo{Parent: k} |
| 69 | 153 » » » » So(ds.Get(f), ShouldEqual, datastore.ErrInvalidK
ey) |
| 70 » » » » _, err := rds.Put(rds.NewKey("Foo", "", 0, k), &
Foo{}) | 154 |
| 71 » » » » So(err, ShouldEqual, gae.ErrDSInvalidKey) | 155 » » » » _, err := ds.Put(f) |
| 156 » » » » So(err, ShouldEqual, datastore.ErrInvalidKey) |
| 72 }) | 157 }) |
| 73 | 158 |
| 74 Convey("getting objects that DNE is an error", func() { | 159 Convey("getting objects that DNE is an error", func() { |
| 75 » » » » k := rds.NewKey("Foo", "", 1, nil) | 160 » » » » So(ds.Get(&Foo{ID: 1}), ShouldEqual, datastore.E
rrNoSuchEntity) |
| 76 » » » » So(rds.Get(k, nil), ShouldEqual, gae.ErrDSNoSuch
Entity) | |
| 77 }) | 161 }) |
| 78 | 162 |
| 79 Convey("Can Put stuff", func() { | 163 Convey("Can Put stuff", func() { |
| 80 // with an incomplete key! | 164 // with an incomplete key! |
| 81 k := rds.NewKey("Foo", "", 0, nil) | |
| 82 f := &Foo{Val: 10} | 165 f := &Foo{Val: 10} |
| 83 » » » » k, err := rds.Put(k, f) | 166 » » » » k, err := ds.Put(f) |
| 84 So(err, ShouldBeNil) | 167 So(err, ShouldBeNil) |
| 85 So(k.String(), ShouldEqual, "/Foo,1") | 168 So(k.String(), ShouldEqual, "/Foo,1") |
| 169 So(ds.NewKeyObj(f), ShouldResemble, k) |
| 86 | 170 |
| 87 Convey("and Get it back", func() { | 171 Convey("and Get it back", func() { |
| 88 » » » » » newFoo := &Foo{} | 172 » » » » » newFoo := &Foo{ID: 1} |
| 89 » » » » » err := rds.Get(k, newFoo) | 173 » » » » » err := ds.Get(newFoo) |
| 90 So(err, ShouldBeNil) | 174 So(err, ShouldBeNil) |
| 91 So(newFoo, ShouldResemble, f) | 175 So(newFoo, ShouldResemble, f) |
| 92 | 176 |
| 93 Convey("and we can Delete it", func() { | 177 Convey("and we can Delete it", func() { |
| 94 » » » » » » err := rds.Delete(k) | 178 » » » » » » err := ds.Delete(ds.NewKey("Foo"
, "", 1, nil)) |
| 95 So(err, ShouldBeNil) | 179 So(err, ShouldBeNil) |
| 96 | 180 |
| 97 » » » » » » err = rds.Get(k, newFoo) | 181 » » » » » » err = ds.Get(newFoo) |
| 98 » » » » » » So(err, ShouldEqual, gae.ErrDSNo
SuchEntity) | 182 » » » » » » So(err, ShouldEqual, datastore.E
rrNoSuchEntity) |
| 99 }) | 183 }) |
| 100 }) | 184 }) |
| 101 Convey("Deleteing with a bogus key is bad", func
() { | 185 Convey("Deleteing with a bogus key is bad", func
() { |
| 102 » » » » » err := rds.Delete(rds.NewKey("Foo", "wat
", 100, nil)) | 186 » » » » » err := ds.Delete(ds.NewKey("Foo", "wat",
100, nil)) |
| 103 » » » » » So(err, ShouldEqual, gae.ErrDSInvalidKey
) | 187 » » » » » So(err, ShouldEqual, datastore.ErrInvali
dKey) |
| 104 }) | 188 }) |
| 105 Convey("Deleteing a DNE entity is fine", func()
{ | 189 Convey("Deleteing a DNE entity is fine", func()
{ |
| 106 » » » » » err := rds.Delete(rds.NewKey("Foo", "wat
", 0, nil)) | 190 » » » » » err := ds.Delete(ds.NewKey("Foo", "wat",
0, nil)) |
| 107 So(err, ShouldBeNil) | 191 So(err, ShouldBeNil) |
| 108 }) | 192 }) |
| 109 | 193 |
| 110 Convey("serialization breaks in the normal ways"
, func() { | 194 Convey("serialization breaks in the normal ways"
, func() { |
| 111 type BadFoo struct { | 195 type BadFoo struct { |
| 112 » » » » » » Val uint8 | 196 » » » » » » _kind string `goon:"kind,Foo"` |
| 197 » » » » » » ID int64 `goon:"id" datastor
e:"-"` |
| 198 » » » » » » Val uint8 |
| 113 } | 199 } |
| 114 » » » » » _, err := rds.Put(k, &BadFoo{}) | 200 » » » » » _, err := ds.Put(&BadFoo{}) |
| 115 » » » » » So(err.Error(), ShouldContainSubstring,
"invalid type: uint8") | 201 » » » » » So(err.Error(), ShouldContainSubstring, |
| 116 | 202 » » » » » » "unsupported struct field type:
uint8") |
| 117 » » » » » err = rds.Get(k, &BadFoo{}) | 203 |
| 118 » » » » » So(err.Error(), ShouldContainSubstring,
"invalid type: uint8") | 204 » » » » » err = ds.Get(&BadFoo{ID: 1}) |
| 205 » » » » » So(err.Error(), ShouldContainSubstring, |
| 206 » » » » » » "type mismatch: int versus uint8
") |
| 119 }) | 207 }) |
| 120 | 208 |
| 121 Convey("check that metadata works", func() { | 209 Convey("check that metadata works", func() { |
| 122 » » » » » So(testGetMeta(c, k), ShouldEqual, 1) | 210 » » » » » val, _ := meta.GetEntityGroupVersion(c,
k) |
| 123 | 211 » » » » » So(val, ShouldEqual, 1) |
| 124 » » » » » pkey := k | 212 |
| 125 for i := 0; i < 10; i++ { | 213 for i := 0; i < 10; i++ { |
| 126 » » » » » » k := rds.NewKey("Foo", "", 0, pk
ey) | 214 » » » » » » _, err = ds.Put(&Foo{Val: 10, Pa
rent: k}) |
| 127 » » » » » » _, err = rds.Put(k, &Foo{Val: 10
}) | |
| 128 So(err, ShouldBeNil) | 215 So(err, ShouldBeNil) |
| 129 } | 216 } |
| 130 » » » » » So(testGetMeta(c, k), ShouldEqual, 11) | 217 » » » » » val, _ = meta.GetEntityGroupVersion(c, k
) |
| 218 » » » » » So(val, ShouldEqual, 11) |
| 131 | 219 |
| 132 Convey("ensure that group versions persi
st across deletes", func() { | 220 Convey("ensure that group versions persi
st across deletes", func() { |
| 133 » » » » » » So(rds.Delete(k), ShouldBeNil) | 221 » » » » » » So(ds.Delete(k), ShouldBeNil) |
| 134 for i := int64(1); i < 11; i++ { | 222 for i := int64(1); i < 11; i++ { |
| 135 » » » » » » » So(rds.Delete(rds.NewKey
("Foo", "", i, k)), ShouldBeNil) | 223 » » » » » » » So(ds.Delete(ds.NewKey("
Foo", "", i, k)), ShouldBeNil) |
| 136 } | 224 } |
| 137 // TODO(riannucci): replace with
a Count query instead of this cast | 225 // TODO(riannucci): replace with
a Count query instead of this cast |
| 138 » » » » » » ents := rds.(*dsImpl).data.store
.GetCollection("ents:") | 226 » » » » » » ents := ds.(*dsImpl).data.store.
GetCollection("ents:") |
| 139 num, _ := ents.GetTotals() | 227 num, _ := ents.GetTotals() |
| 140 // /__entity_root_ids__,Foo | 228 // /__entity_root_ids__,Foo |
| 141 // /Foo,1/__entity_group__,1 | 229 // /Foo,1/__entity_group__,1 |
| 142 // /Foo,1/__entity_group_ids__,1 | 230 // /Foo,1/__entity_group_ids__,1 |
| 143 So(num, ShouldEqual, 3) | 231 So(num, ShouldEqual, 3) |
| 144 | 232 |
| 145 version, err := curVersion(ents,
groupMetaKey(k)) | 233 version, err := curVersion(ents,
groupMetaKey(k)) |
| 146 So(err, ShouldBeNil) | 234 So(err, ShouldBeNil) |
| 147 So(version, ShouldEqual, 22) | 235 So(version, ShouldEqual, 22) |
| 148 | 236 |
| 149 » » » » » » k, err := rds.Put(k, f) | 237 » » » » » » k, err := ds.Put(f) |
| 150 So(err, ShouldBeNil) | 238 So(err, ShouldBeNil) |
| 151 » » » » » » So(testGetMeta(c, k), ShouldEqua
l, 23) | 239 » » » » » » val, _ := meta.GetEntityGroupVer
sion(c, k) |
| 240 » » » » » » So(val, ShouldEqual, 23) |
| 152 }) | 241 }) |
| 153 }) | 242 }) |
| 154 }) | 243 }) |
| 155 }) | 244 }) |
| 156 | 245 |
| 157 Convey("implements DSTransactioner", func() { | 246 Convey("implements DSTransactioner", func() { |
| 158 type Foo struct { | 247 type Foo struct { |
| 159 » » » » Val int | 248 » » » » ID int64 `goon:"id" datastore:"-"` |
| 249 » » » » Parent *datastore.Key `goon:"parent" datastore:"
-"` |
| 250 » » » » Val int |
| 160 } | 251 } |
| 161 Convey("Put", func() { | 252 Convey("Put", func() { |
| 162 k := rds.NewKey("Foo", "", 0, nil) | |
| 163 f := &Foo{Val: 10} | 253 f := &Foo{Val: 10} |
| 164 » » » » k, err := rds.Put(k, f) | 254 » » » » k, err := ds.Put(f) |
| 165 So(err, ShouldBeNil) | 255 So(err, ShouldBeNil) |
| 166 So(k.String(), ShouldEqual, "/Foo,1") | 256 So(k.String(), ShouldEqual, "/Foo,1") |
| 257 So(ds.NewKeyObj(f), ShouldResemble, k) |
| 167 | 258 |
| 168 Convey("can Put new entity groups", func() { | 259 Convey("can Put new entity groups", func() { |
| 169 » » » » » err := rds.RunInTransaction(func(c conte
xt.Context) error { | 260 » » » » » err := ds.RunInTransaction(func(c contex
t.Context) error { |
| 170 » » » » » » rds := gae.GetRDS(c) | 261 » » » » » » ds := wrapper.GetDS(c) |
| 171 » » » » » » So(rds, ShouldNotBeNil) | 262 » » » » » » So(ds, ShouldNotBeNil) |
| 172 | 263 |
| 173 f1 := &Foo{Val: 100} | 264 f1 := &Foo{Val: 100} |
| 174 » » » » » » k, err := rds.Put(rds.NewKey("Fo
o", "", 0, nil), f1) | 265 » » » » » » k, err := ds.Put(f1) |
| 175 So(err, ShouldBeNil) | 266 So(err, ShouldBeNil) |
| 176 So(k.String(), ShouldEqual, "/Fo
o,2") | 267 So(k.String(), ShouldEqual, "/Fo
o,2") |
| 177 | 268 |
| 178 f2 := &Foo{Val: 200} | 269 f2 := &Foo{Val: 200} |
| 179 » » » » » » k, err = rds.Put(rds.NewKey("Foo
", "", 0, nil), f2) | 270 » » » » » » k, err = ds.Put(f2) |
| 180 So(err, ShouldBeNil) | 271 So(err, ShouldBeNil) |
| 181 So(k.String(), ShouldEqual, "/Fo
o,3") | 272 So(k.String(), ShouldEqual, "/Fo
o,3") |
| 182 | 273 |
| 183 return nil | 274 return nil |
| 184 » » » » » }, &gae.DSTransactionOptions{XG: true}) | 275 » » » » » }, &datastore.TransactionOptions{XG: tru
e}) |
| 185 So(err, ShouldBeNil) | 276 So(err, ShouldBeNil) |
| 186 | 277 |
| 187 » » » » » f := &Foo{} | 278 » » » » » f := &Foo{ID: 2} |
| 188 » » » » » So(rds.Get(rds.NewKey("Foo", "", 2, nil)
, f), ShouldBeNil) | 279 » » » » » So(ds.Get(f), ShouldBeNil) |
| 189 So(f.Val, ShouldEqual, 100) | 280 So(f.Val, ShouldEqual, 100) |
| 190 | 281 |
| 191 » » » » » f = &Foo{} | 282 » » » » » f = &Foo{ID: 3} |
| 192 » » » » » So(rds.Get(rds.NewKey("Foo", "", 3, nil)
, f), ShouldBeNil) | 283 » » » » » So(ds.Get(f), ShouldBeNil) |
| 193 So(f.Val, ShouldEqual, 200) | 284 So(f.Val, ShouldEqual, 200) |
| 194 }) | 285 }) |
| 195 | 286 |
| 196 Convey("can Put new entities in a current group"
, func() { | 287 Convey("can Put new entities in a current group"
, func() { |
| 197 » » » » » err := rds.RunInTransaction(func(c conte
xt.Context) error { | 288 » » » » » err := ds.RunInTransaction(func(c contex
t.Context) error { |
| 198 » » » » » » rds := gae.GetRDS(c) | 289 » » » » » » ds := wrapper.GetDS(c) |
| 199 » » » » » » So(rds, ShouldNotBeNil) | 290 » » » » » » So(ds, ShouldNotBeNil) |
| 200 | 291 |
| 201 » » » » » » par := k | 292 » » » » » » f1 := &Foo{Val: 100, Parent: ds.
NewKeyObj(f)} |
| 202 | 293 » » » » » » k, err := ds.Put(f1) |
| 203 » » » » » » f1 := &Foo{Val: 100} | |
| 204 » » » » » » k, err := rds.Put(rds.NewKey("Fo
o", "", 0, par), f1) | |
| 205 So(err, ShouldBeNil) | 294 So(err, ShouldBeNil) |
| 206 So(k.String(), ShouldEqual, "/Fo
o,1/Foo,1") | 295 So(k.String(), ShouldEqual, "/Fo
o,1/Foo,1") |
| 207 | 296 |
| 208 » » » » » » f2 := &Foo{Val: 200} | 297 » » » » » » f2 := &Foo{Val: 200, Parent: ds.
NewKeyObj(f)} |
| 209 » » » » » » k, err = rds.Put(rds.NewKey("Foo
", "", 0, par), f2) | 298 » » » » » » k, err = ds.Put(f2) |
| 210 So(err, ShouldBeNil) | 299 So(err, ShouldBeNil) |
| 211 So(k.String(), ShouldEqual, "/Fo
o,1/Foo,2") | 300 So(k.String(), ShouldEqual, "/Fo
o,1/Foo,2") |
| 212 | 301 |
| 213 return nil | 302 return nil |
| 214 }, nil) | 303 }, nil) |
| 215 So(err, ShouldBeNil) | 304 So(err, ShouldBeNil) |
| 216 | 305 |
| 217 » » » » » f1 := &Foo{} | 306 » » » » » f1 := &Foo{ID: 1, Parent: ds.NewKeyObj(&
Foo{ID: 1})} |
| 218 » » » » » So(rds.Get(rds.NewKey("Foo", "", 1, k),
f1), ShouldBeNil) | 307 » » » » » So(ds.Get(f1), ShouldBeNil) |
| 219 So(f1.Val, ShouldEqual, 100) | 308 So(f1.Val, ShouldEqual, 100) |
| 220 | 309 |
| 221 » » » » » f2 := &Foo{} | 310 » » » » » f2 := &Foo{ID: 2, Parent: f1.Parent} |
| 222 » » » » » So(rds.Get(rds.NewKey("Foo", "", 2, k),
f2), ShouldBeNil) | 311 » » » » » So(ds.Get(f2), ShouldBeNil) |
| 223 So(f2.Val, ShouldEqual, 200) | 312 So(f2.Val, ShouldEqual, 200) |
| 224 }) | 313 }) |
| 225 | 314 |
| 226 Convey("Deletes work too", func() { | 315 Convey("Deletes work too", func() { |
| 227 » » » » » err := rds.RunInTransaction(func(c conte
xt.Context) error { | 316 » » » » » err := ds.RunInTransaction(func(c contex
t.Context) error { |
| 228 » » » » » » rds := gae.GetRDS(c) | 317 » » » » » » ds := wrapper.GetDS(c) |
| 229 » » » » » » So(rds, ShouldNotBeNil) | 318 » » » » » » So(ds, ShouldNotBeNil) |
| 230 » » » » » » So(rds.Delete(k), ShouldBeNil) | 319 » » » » » » So(ds.Delete(ds.NewKeyObj(f)), S
houldBeNil) |
| 231 return nil | 320 return nil |
| 232 }, nil) | 321 }, nil) |
| 233 So(err, ShouldBeNil) | 322 So(err, ShouldBeNil) |
| 234 » » » » » So(rds.Get(k, f), ShouldEqual, gae.ErrDS
NoSuchEntity) | 323 » » » » » So(ds.Get(f), ShouldEqual, datastore.Err
NoSuchEntity) |
| 235 }) | 324 }) |
| 236 | 325 |
| 237 Convey("A Get counts against your group count",
func() { | 326 Convey("A Get counts against your group count",
func() { |
| 238 » » » » » err := rds.RunInTransaction(func(c conte
xt.Context) error { | 327 » » » » » err := ds.RunInTransaction(func(c contex
t.Context) error { |
| 239 » » » » » » rds := gae.GetRDS(c) | 328 » » » » » » ds := wrapper.GetDS(c) |
| 240 » » » » » » f := &Foo{} | 329 » » » » » » f := &Foo{ID: 20} |
| 241 » » » » » » So(rds.Get(rds.NewKey("Foo", "",
20, nil), f), ShouldEqual, gae.ErrDSNoSuchEntity) | 330 » » » » » » So(ds.Get(f), ShouldEqual, datas
tore.ErrNoSuchEntity) |
| 242 | 331 |
| 243 » » » » » » So(rds.Get(k, f).Error(), Should
ContainSubstring, "cross-group") | 332 » » » » » » f.ID = 1 |
| 333 » » » » » » So(ds.Get(f).Error(), ShouldCont
ainSubstring, "cross-group") |
| 244 return nil | 334 return nil |
| 245 }, nil) | 335 }, nil) |
| 246 So(err, ShouldBeNil) | 336 So(err, ShouldBeNil) |
| 247 }) | 337 }) |
| 248 | 338 |
| 249 Convey("Get takes a snapshot", func() { | 339 Convey("Get takes a snapshot", func() { |
| 250 » » » » » err := rds.RunInTransaction(func(c conte
xt.Context) error { | 340 » » » » » err := ds.RunInTransaction(func(c contex
t.Context) error { |
| 251 » » » » » » txnDS := gae.GetRDS(c) | 341 » » » » » » txnDS := wrapper.GetDS(c) |
| 252 So(txnDS, ShouldNotBeNil) | 342 So(txnDS, ShouldNotBeNil) |
| 253 | 343 |
| 254 » » » » » » So(txnDS.Get(k, f), ShouldBeNil) | 344 » » » » » » f := &Foo{ID: 1} |
| 345 » » » » » » So(txnDS.Get(f), ShouldBeNil) |
| 255 So(f.Val, ShouldEqual, 10) | 346 So(f.Val, ShouldEqual, 10) |
| 256 | 347 |
| 257 // Don't ever do this in a real
program unless you want to guarantee | 348 // Don't ever do this in a real
program unless you want to guarantee |
| 258 // a failed transaction :) | 349 // a failed transaction :) |
| 259 f.Val = 11 | 350 f.Val = 11 |
| 260 » » » » » » _, err := rds.Put(k, f) | 351 » » » » » » _, err := ds.Put(f) |
| 261 So(err, ShouldBeNil) | 352 So(err, ShouldBeNil) |
| 262 | 353 |
| 263 » » » » » » So(txnDS.Get(k, f), ShouldBeNil) | 354 » » » » » » So(txnDS.Get(f), ShouldBeNil) |
| 264 So(f.Val, ShouldEqual, 10) | 355 So(f.Val, ShouldEqual, 10) |
| 265 | 356 |
| 266 return nil | 357 return nil |
| 267 }, nil) | 358 }, nil) |
| 268 So(err, ShouldBeNil) | 359 So(err, ShouldBeNil) |
| 269 | 360 |
| 270 » » » » » f := &Foo{} | 361 » » » » » f := &Foo{ID: 1} |
| 271 » » » » » So(rds.Get(k, f), ShouldBeNil) | 362 » » » » » So(ds.Get(f), ShouldBeNil) |
| 272 So(f.Val, ShouldEqual, 11) | 363 So(f.Val, ShouldEqual, 11) |
| 364 |
| 273 }) | 365 }) |
| 274 | 366 |
| 275 Convey("and snapshots are consistent even after
Puts", func() { | 367 Convey("and snapshots are consistent even after
Puts", func() { |
| 276 » » » » » err := rds.RunInTransaction(func(c conte
xt.Context) error { | 368 » » » » » err := ds.RunInTransaction(func(c contex
t.Context) error { |
| 277 » » » » » » txnDS := gae.GetRDS(c) | 369 » » » » » » txnDS := wrapper.GetDS(c) |
| 278 So(txnDS, ShouldNotBeNil) | 370 So(txnDS, ShouldNotBeNil) |
| 279 | 371 |
| 280 » » » » » » f := &Foo{} | 372 » » » » » » f := &Foo{ID: 1} |
| 281 » » » » » » So(txnDS.Get(k, f), ShouldBeNil) | 373 » » » » » » So(txnDS.Get(f), ShouldBeNil) |
| 282 So(f.Val, ShouldEqual, 10) | 374 So(f.Val, ShouldEqual, 10) |
| 283 | 375 |
| 284 // Don't ever do this in a real
program unless you want to guarantee | 376 // Don't ever do this in a real
program unless you want to guarantee |
| 285 // a failed transaction :) | 377 // a failed transaction :) |
| 286 f.Val = 11 | 378 f.Val = 11 |
| 287 » » » » » » _, err := rds.Put(k, f) | 379 » » » » » » _, err := ds.Put(f) |
| 288 So(err, ShouldBeNil) | 380 So(err, ShouldBeNil) |
| 289 | 381 |
| 290 » » » » » » So(txnDS.Get(k, f), ShouldBeNil) | 382 » » » » » » So(txnDS.Get(f), ShouldBeNil) |
| 291 So(f.Val, ShouldEqual, 10) | 383 So(f.Val, ShouldEqual, 10) |
| 292 | 384 |
| 293 f.Val = 20 | 385 f.Val = 20 |
| 294 » » » » » » _, err = txnDS.Put(k, f) | 386 » » » » » » _, err = txnDS.Put(f) |
| 295 So(err, ShouldBeNil) | 387 So(err, ShouldBeNil) |
| 296 | 388 |
| 297 » » » » » » So(txnDS.Get(k, f), ShouldBeNil) | 389 » » » » » » So(txnDS.Get(f), ShouldBeNil) |
| 298 So(f.Val, ShouldEqual, 10) // st
ill gets 10 | 390 So(f.Val, ShouldEqual, 10) // st
ill gets 10 |
| 299 | 391 |
| 300 return nil | 392 return nil |
| 301 }, nil) | 393 }, nil) |
| 302 So(err.Error(), ShouldContainSubstring,
"concurrent") | 394 So(err.Error(), ShouldContainSubstring,
"concurrent") |
| 303 | 395 |
| 304 » » » » » f := &Foo{} | 396 » » » » » f := &Foo{ID: 1} |
| 305 » » » » » So(rds.Get(k, f), ShouldBeNil) | 397 » » » » » So(ds.Get(f), ShouldBeNil) |
| 306 So(f.Val, ShouldEqual, 11) | 398 So(f.Val, ShouldEqual, 11) |
| 307 }) | 399 }) |
| 308 | 400 |
| 309 Convey("Reusing a transaction context is bad new
s", func() { | 401 Convey("Reusing a transaction context is bad new
s", func() { |
| 310 » » » » » k := rds.NewKey("Foo", "", 1, nil) | 402 » » » » » txnDS := wrapper.Datastore(nil) |
| 311 » » » » » txnDS := gae.RawDatastore(nil) | 403 » » » » » err := ds.RunInTransaction(func(c contex
t.Context) error { |
| 312 » » » » » err := rds.RunInTransaction(func(c conte
xt.Context) error { | 404 » » » » » » txnDS = wrapper.GetDS(c) |
| 313 » » » » » » txnDS = gae.GetRDS(c) | 405 » » » » » » So(txnDS.Get(&Foo{ID: 1}), Shoul
dBeNil) |
| 314 » » » » » » So(txnDS.Get(k, &Foo{}), ShouldB
eNil) | |
| 315 return nil | 406 return nil |
| 316 }, nil) | 407 }, nil) |
| 317 So(err, ShouldBeNil) | 408 So(err, ShouldBeNil) |
| 318 » » » » » So(txnDS.Get(k, &Foo{}).Error(), ShouldC
ontainSubstring, "expired") | 409 » » » » » So(txnDS.Get(&Foo{ID: 1}).Error(), Shoul
dContainSubstring, "expired") |
| 319 }) | 410 }) |
| 320 | 411 |
| 321 Convey("Nested transactions are rejected", func(
) { | 412 Convey("Nested transactions are rejected", func(
) { |
| 322 » » » » » err := rds.RunInTransaction(func(c conte
xt.Context) error { | 413 » » » » » err := ds.RunInTransaction(func(c contex
t.Context) error { |
| 323 » » » » » » err := gae.GetRDS(c).RunInTransa
ction(func(c context.Context) error { | 414 » » » » » » err := wrapper.GetDS(c).RunInTra
nsaction(func(c context.Context) error { |
| 324 panic("noooo") | 415 panic("noooo") |
| 325 }, nil) | 416 }, nil) |
| 326 So(err.Error(), ShouldContainSub
string, "nested transactions") | 417 So(err.Error(), ShouldContainSub
string, "nested transactions") |
| 327 return nil | 418 return nil |
| 328 }, nil) | 419 }, nil) |
| 329 So(err, ShouldBeNil) | 420 So(err, ShouldBeNil) |
| 330 }) | 421 }) |
| 331 | 422 |
| 332 Convey("Concurrent transactions only accept one
set of changes", func() { | 423 Convey("Concurrent transactions only accept one
set of changes", func() { |
| 333 // Note: I think this implementation is
actually /slightly/ wrong. | 424 // Note: I think this implementation is
actually /slightly/ wrong. |
| 334 // Accorting to my read of the docs for
appengine, when you open a | 425 // Accorting to my read of the docs for
appengine, when you open a |
| 335 // transaction it actually (essentially)
holds a reference to the | 426 // transaction it actually (essentially)
holds a reference to the |
| 336 // entire datastore. Our implementation
takes a snapshot of the | 427 // entire datastore. Our implementation
takes a snapshot of the |
| 337 // entity group as soon as something obs
erves/affects it. | 428 // entity group as soon as something obs
erves/affects it. |
| 338 // | 429 // |
| 339 // That said... I'm not sure if there's
really a semantic difference. | 430 // That said... I'm not sure if there's
really a semantic difference. |
| 340 » » » » » err := rds.RunInTransaction(func(c conte
xt.Context) error { | 431 » » » » » err := ds.RunInTransaction(func(c contex
t.Context) error { |
| 341 » » » » » » txnDS := gae.GetRDS(c) | 432 » » » » » » txnDS := wrapper.GetDS(c) |
| 342 » » » » » » f := &Foo{Val: 21} | 433 » » » » » » f := &Foo{ID: 1, Val: 21} |
| 343 » » » » » » _, err = txnDS.Put(k, f) | 434 » » » » » » _, err = txnDS.Put(f) |
| 344 So(err, ShouldBeNil) | 435 So(err, ShouldBeNil) |
| 345 | 436 |
| 346 » » » » » » err := rds.RunInTransaction(func
(c context.Context) error { | 437 » » » » » » err := ds.RunInTransaction(func(
c context.Context) error { |
| 347 » » » » » » » txnDS := gae.GetRDS(c) | 438 » » » » » » » txnDS := wrapper.GetDS(c
) |
| 348 » » » » » » » f := &Foo{Val: 27} | 439 » » » » » » » f := &Foo{ID: 1, Val: 27
} |
| 349 » » » » » » » _, err := txnDS.Put(k, f
) | 440 » » » » » » » _, err := txnDS.Put(f) |
| 350 So(err, ShouldBeNil) | 441 So(err, ShouldBeNil) |
| 351 return nil | 442 return nil |
| 352 }, nil) | 443 }, nil) |
| 353 So(err, ShouldBeNil) | 444 So(err, ShouldBeNil) |
| 354 | 445 |
| 355 return nil | 446 return nil |
| 356 }, nil) | 447 }, nil) |
| 357 So(err.Error(), ShouldContainSubstring,
"concurrent") | 448 So(err.Error(), ShouldContainSubstring,
"concurrent") |
| 358 | 449 |
| 359 » » » » » f := &Foo{} | 450 » » » » » f := &Foo{ID: 1} |
| 360 » » » » » So(rds.Get(k, f), ShouldBeNil) | 451 » » » » » So(ds.Get(f), ShouldBeNil) |
| 361 So(f.Val, ShouldEqual, 27) | 452 So(f.Val, ShouldEqual, 27) |
| 362 }) | 453 }) |
| 363 | 454 |
| 364 Convey("XG", func() { | 455 Convey("XG", func() { |
| 365 Convey("Modifying two groups with XG=fal
se is invalid", func() { | 456 Convey("Modifying two groups with XG=fal
se is invalid", func() { |
| 366 » » » » » » err := rds.RunInTransaction(func
(c context.Context) error { | 457 » » » » » » err := ds.RunInTransaction(func(
c context.Context) error { |
| 367 » » » » » » » rds := gae.GetRDS(c) | 458 » » » » » » » ds := wrapper.GetDS(c) |
| 368 » » » » » » » f := &Foo{Val: 200} | 459 » » » » » » » f := &Foo{ID: 1, Val: 20
0} |
| 369 » » » » » » » _, err := rds.Put(k, f) | 460 » » » » » » » _, err := ds.Put(f) |
| 370 So(err, ShouldBeNil) | 461 So(err, ShouldBeNil) |
| 371 | 462 |
| 372 » » » » » » » _, err = rds.Put(rds.New
Key("Foo", "", 2, nil), f) | 463 » » » » » » » f.ID = 2 |
| 464 » » » » » » » _, err = ds.Put(f) |
| 373 So(err.Error(), ShouldCo
ntainSubstring, "cross-group") | 465 So(err.Error(), ShouldCo
ntainSubstring, "cross-group") |
| 374 return err | 466 return err |
| 375 }, nil) | 467 }, nil) |
| 376 So(err.Error(), ShouldContainSub
string, "cross-group") | 468 So(err.Error(), ShouldContainSub
string, "cross-group") |
| 377 }) | 469 }) |
| 378 | 470 |
| 379 Convey("Modifying >25 groups with XG=tru
e is invald", func() { | 471 Convey("Modifying >25 groups with XG=tru
e is invald", func() { |
| 380 » » » » » » err := rds.RunInTransaction(func
(c context.Context) error { | 472 » » » » » » err := ds.RunInTransaction(func(
c context.Context) error { |
| 381 » » » » » » » rds := gae.GetRDS(c) | 473 » » » » » » » ds := wrapper.GetDS(c) |
| 382 for i := int64(1); i < 2
6; i++ { | 474 for i := int64(1); i < 2
6; i++ { |
| 383 » » » » » » » » k := rds.NewKey(
"Foo", "", i, nil) | 475 » » » » » » » » f := &Foo{ID: i,
Val: 200} |
| 384 » » » » » » » » f := &Foo{Val: 2
00} | 476 » » » » » » » » _, err := ds.Put
(f) |
| 385 » » » » » » » » _, err := rds.Pu
t(k, f) | |
| 386 So(err, ShouldBe
Nil) | 477 So(err, ShouldBe
Nil) |
| 387 } | 478 } |
| 388 » » » » » » » f := &Foo{Val: 200} | 479 » » » » » » » f := &Foo{ID: 27, Val: 2
00} |
| 389 » » » » » » » _, err := rds.Put(rds.Ne
wKey("Foo", "", 27, nil), f) | 480 » » » » » » » _, err := ds.Put(f) |
| 390 So(err.Error(), ShouldCo
ntainSubstring, "too many entity groups") | 481 So(err.Error(), ShouldCo
ntainSubstring, "too many entity groups") |
| 391 return err | 482 return err |
| 392 » » » » » » }, &gae.DSTransactionOptions{XG:
true}) | 483 » » » » » » }, &datastore.TransactionOptions
{XG: true}) |
| 393 So(err.Error(), ShouldContainSub
string, "too many entity groups") | 484 So(err.Error(), ShouldContainSub
string, "too many entity groups") |
| 394 }) | 485 }) |
| 395 }) | 486 }) |
| 396 | 487 |
| 397 Convey("Errors and panics", func() { | 488 Convey("Errors and panics", func() { |
| 398 Convey("returning an error aborts", func
() { | 489 Convey("returning an error aborts", func
() { |
| 399 » » » » » » err := rds.RunInTransaction(func
(c context.Context) error { | 490 » » » » » » err := ds.RunInTransaction(func(
c context.Context) error { |
| 400 » » » » » » » rds := gae.GetRDS(c) | 491 » » » » » » » ds := wrapper.GetDS(c) |
| 401 » » » » » » » f := &Foo{Val: 200} | 492 » » » » » » » f := &Foo{ID: 1, Val: 20
0} |
| 402 » » » » » » » _, err := rds.Put(k, f) | 493 » » » » » » » _, err := ds.Put(f) |
| 403 So(err, ShouldBeNil) | 494 So(err, ShouldBeNil) |
| 404 | 495 |
| 405 return fmt.Errorf("thing
y") | 496 return fmt.Errorf("thing
y") |
| 406 }, nil) | 497 }, nil) |
| 407 So(err.Error(), ShouldEqual, "th
ingy") | 498 So(err.Error(), ShouldEqual, "th
ingy") |
| 408 | 499 |
| 409 » » » » » » f := &Foo{} | 500 » » » » » » f := &Foo{ID: 1} |
| 410 » » » » » » So(rds.Get(k, f), ShouldBeNil) | 501 » » » » » » So(ds.Get(f), ShouldBeNil) |
| 411 So(f.Val, ShouldEqual, 10) | 502 So(f.Val, ShouldEqual, 10) |
| 412 }) | 503 }) |
| 413 | 504 |
| 414 Convey("panicing aborts", func() { | 505 Convey("panicing aborts", func() { |
| 415 So(func() { | 506 So(func() { |
| 416 » » » » » » » rds.RunInTransaction(fun
c(c context.Context) error { | 507 » » » » » » » ds.RunInTransaction(func
(c context.Context) error { |
| 417 » » » » » » » » rds := gae.GetRD
S(c) | 508 » » » » » » » » ds := wrapper.Ge
tDS(c) |
| 418 » » » » » » » » f := &Foo{Val: 2
00} | 509 » » » » » » » » f := &Foo{ID: 1,
Val: 200} |
| 419 » » » » » » » » _, err := rds.Pu
t(k, f) | 510 » » » » » » » » _, err := ds.Put
(f) |
| 420 So(err, ShouldBe
Nil) | 511 So(err, ShouldBe
Nil) |
| 421 panic("wheeeeee"
) | 512 panic("wheeeeee"
) |
| 422 }, nil) | 513 }, nil) |
| 423 }, ShouldPanic) | 514 }, ShouldPanic) |
| 424 | 515 |
| 425 » » » » » » f := &Foo{} | 516 » » » » » » f := &Foo{ID: 1} |
| 426 » » » » » » So(rds.Get(k, f), ShouldBeNil) | 517 » » » » » » So(ds.Get(f), ShouldBeNil) |
| 427 So(f.Val, ShouldEqual, 10) | 518 So(f.Val, ShouldEqual, 10) |
| 428 }) | 519 }) |
| 429 }) | 520 }) |
| 430 }) | 521 }) |
| 431 }) | 522 }) |
| 432 | 523 |
| 433 }) | 524 }) |
| 434 } | 525 } |
| 435 | 526 |
| 436 const MaxUint = ^uint(0) | 527 const MaxUint = ^uint(0) |
| 437 const MaxInt = int(MaxUint >> 1) | 528 const MaxInt = int(MaxUint >> 1) |
| 438 const IntIs32Bits = int64(MaxInt) < math.MaxInt64 | 529 const IntIs32Bits = int64(MaxInt) < math.MaxInt64 |
| 439 | 530 |
| 440 func TestDatastoreQueryer(t *testing.T) { | 531 func TestDatastoreQueryer(t *testing.T) { |
| 441 Convey("Datastore Query suport", t, func() { | 532 Convey("Datastore Query suport", t, func() { |
| 442 c := Use(context.Background()) | 533 c := Use(context.Background()) |
| 443 » » rds := gae.GetRDS(c) | 534 » » ds := wrapper.GetDS(c) |
| 444 » » So(rds, ShouldNotBeNil) | 535 » » So(ds, ShouldNotBeNil) |
| 445 | 536 |
| 446 Convey("can create good queries", func() { | 537 Convey("can create good queries", func() { |
| 447 » » » q := rds.NewQuery("Foo").KeysOnly().Limit(10).Offset(39) | 538 » » » q := ds.NewQuery("Foo").KeysOnly().Limit(10).Offset(39) |
| 448 q = q.Start(queryCursor("kosmik")).End(queryCursor("krab
s")) | 539 q = q.Start(queryCursor("kosmik")).End(queryCursor("krab
s")) |
| 449 So(q, ShouldNotBeNil) | 540 So(q, ShouldNotBeNil) |
| 450 So(q.(*queryImpl).err, ShouldBeNil) | 541 So(q.(*queryImpl).err, ShouldBeNil) |
| 451 qi := q.(*queryImpl).checkCorrectness("", false) | 542 qi := q.(*queryImpl).checkCorrectness("", false) |
| 452 So(qi.err, ShouldBeNil) | 543 So(qi.err, ShouldBeNil) |
| 453 }) | 544 }) |
| 454 | 545 |
| 455 Convey("normalize ensures orders make sense", func() { | 546 Convey("normalize ensures orders make sense", func() { |
| 456 » » » q := rds.NewQuery("Cool") | 547 » » » q := ds.NewQuery("Cool") |
| 457 q = q.Filter("cat =", 19).Filter("bob =", 10).Order("bob
").Order("bob") | 548 q = q.Filter("cat =", 19).Filter("bob =", 10).Order("bob
").Order("bob") |
| 458 | 549 |
| 459 Convey("removes dups and equality orders", func() { | 550 Convey("removes dups and equality orders", func() { |
| 460 q = q.Order("wat") | 551 q = q.Order("wat") |
| 461 qi := q.(*queryImpl).normalize().checkCorrectnes
s("", false) | 552 qi := q.(*queryImpl).normalize().checkCorrectnes
s("", false) |
| 462 So(qi.err, ShouldBeNil) | 553 So(qi.err, ShouldBeNil) |
| 463 So(qi.order, ShouldResemble, []queryOrder{{"wat"
, qASC}}) | 554 So(qi.order, ShouldResemble, []queryOrder{{"wat"
, qASC}}) |
| 464 }) | 555 }) |
| 465 | 556 |
| 466 Convey("keeps inequality orders", func() { | 557 Convey("keeps inequality orders", func() { |
| 467 q = q.Order("wat") | 558 q = q.Order("wat") |
| 468 q := q.Filter("bob >", 10).Filter("wat <", 29) | 559 q := q.Filter("bob >", 10).Filter("wat <", 29) |
| 469 qi := q.(*queryImpl).normalize().checkCorrectnes
s("", false) | 560 qi := q.(*queryImpl).normalize().checkCorrectnes
s("", false) |
| 470 So(qi.order, ShouldResemble, []queryOrder{{"bob"
, qASC}, {"wat", qASC}}) | 561 So(qi.order, ShouldResemble, []queryOrder{{"bob"
, qASC}, {"wat", qASC}}) |
| 471 So(qi.err.Error(), ShouldContainSubstring, "Only
one inequality") | 562 So(qi.err.Error(), ShouldContainSubstring, "Only
one inequality") |
| 472 }) | 563 }) |
| 473 | 564 |
| 474 Convey("if we equality-filter on __key__, order is ditch
ed", func() { | 565 Convey("if we equality-filter on __key__, order is ditch
ed", func() { |
| 475 q = q.Order("wat") | 566 q = q.Order("wat") |
| 476 » » » » q := q.Filter("__key__ =", rds.NewKey("Foo", "wa
t", 0, nil)) | 567 » » » » q := q.Filter("__key__ =", ds.NewKey("Foo", "wat
", 0, nil)) |
| 477 qi := q.(*queryImpl).normalize().checkCorrectnes
s("", false) | 568 qi := q.(*queryImpl).normalize().checkCorrectnes
s("", false) |
| 478 So(qi.order, ShouldResemble, []queryOrder(nil)) | 569 So(qi.order, ShouldResemble, []queryOrder(nil)) |
| 479 So(qi.err, ShouldBeNil) | 570 So(qi.err, ShouldBeNil) |
| 480 }) | 571 }) |
| 481 | 572 |
| 482 Convey("if we order by key and something else, key domin
ates", func() { | 573 Convey("if we order by key and something else, key domin
ates", func() { |
| 483 q := q.Order("__key__").Order("wat") | 574 q := q.Order("__key__").Order("wat") |
| 484 qi := q.(*queryImpl).normalize().checkCorrectnes
s("", false) | 575 qi := q.(*queryImpl).normalize().checkCorrectnes
s("", false) |
| 485 So(qi.order, ShouldResemble, []queryOrder{{"__ke
y__", qASC}}) | 576 So(qi.order, ShouldResemble, []queryOrder{{"__ke
y__", qASC}}) |
| 486 So(qi.err, ShouldBeNil) | 577 So(qi.err, ShouldBeNil) |
| 487 }) | 578 }) |
| 488 }) | 579 }) |
| 489 | 580 |
| 490 Convey("can create bad queries", func() { | 581 Convey("can create bad queries", func() { |
| 491 » » » q := rds.NewQuery("Foo") | 582 » » » q := ds.NewQuery("Foo") |
| 492 | 583 |
| 493 Convey("bad filter ops", func() { | 584 Convey("bad filter ops", func() { |
| 494 q := q.Filter("Bob !", "value") | 585 q := q.Filter("Bob !", "value") |
| 495 So(q.(*queryImpl).err.Error(), ShouldContainSubs
tring, "invalid operator \"!\"") | 586 So(q.(*queryImpl).err.Error(), ShouldContainSubs
tring, "invalid operator \"!\"") |
| 496 }) | 587 }) |
| 497 Convey("bad filter", func() { | 588 Convey("bad filter", func() { |
| 498 q := q.Filter("Bob", "value") | 589 q := q.Filter("Bob", "value") |
| 499 So(q.(*queryImpl).err.Error(), ShouldContainSubs
tring, "invalid filter") | 590 So(q.(*queryImpl).err.Error(), ShouldContainSubs
tring, "invalid filter") |
| 500 }) | 591 }) |
| 501 Convey("bad order", func() { | 592 Convey("bad order", func() { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 522 if !IntIs32Bits { | 613 if !IntIs32Bits { |
| 523 q := q.Offset(MaxInt) | 614 q := q.Offset(MaxInt) |
| 524 So(q.(*queryImpl).err.Error(), ShouldCon
tainSubstring, "query offset overflow") | 615 So(q.(*queryImpl).err.Error(), ShouldCon
tainSubstring, "query offset overflow") |
| 525 } | 616 } |
| 526 }) | 617 }) |
| 527 Convey("Bad cursors", func() { | 618 Convey("Bad cursors", func() { |
| 528 q := q.Start(queryCursor("")).End(queryCursor(""
)) | 619 q := q.Start(queryCursor("")).End(queryCursor(""
)) |
| 529 So(q.(*queryImpl).err.Error(), ShouldContainSubs
tring, "invalid cursor") | 620 So(q.(*queryImpl).err.Error(), ShouldContainSubs
tring, "invalid cursor") |
| 530 }) | 621 }) |
| 531 Convey("Bad ancestors", func() { | 622 Convey("Bad ancestors", func() { |
| 532 » » » » q := q.Ancestor(rds.NewKey("Goop", "wat", 10, ni
l)) | 623 » » » » q := q.Ancestor(ds.NewKey("Goop", "wat", 10, nil
)) |
| 533 So(q, ShouldNotBeNil) | 624 So(q, ShouldNotBeNil) |
| 534 qi := q.(*queryImpl).checkCorrectness("", false) | 625 qi := q.(*queryImpl).checkCorrectness("", false) |
| 535 » » » » So(qi.err, ShouldEqual, gae.ErrDSInvalidKey) | 626 » » » » So(qi.err, ShouldEqual, datastore.ErrInvalidKey) |
| 536 }) | 627 }) |
| 537 Convey("nil ancestors", func() { | 628 Convey("nil ancestors", func() { |
| 538 qi := q.Ancestor(nil).(*queryImpl).checkCorrectn
ess("", false) | 629 qi := q.Ancestor(nil).(*queryImpl).checkCorrectn
ess("", false) |
| 539 So(qi.err.Error(), ShouldContainSubstring, "nil
query ancestor") | 630 So(qi.err.Error(), ShouldContainSubstring, "nil
query ancestor") |
| 540 }) | 631 }) |
| 541 Convey("Bad key filters", func() { | 632 Convey("Bad key filters", func() { |
| 542 » » » » q := q.Filter("__key__ =", rds.NewKey("Goop", "w
at", 10, nil)) | 633 » » » » q := q.Filter("__key__ =", ds.NewKey("Goop", "wa
t", 10, nil)) |
| 543 qi := q.(*queryImpl).checkCorrectness("", false) | 634 qi := q.(*queryImpl).checkCorrectness("", false) |
| 544 » » » » So(qi.err, ShouldEqual, gae.ErrDSInvalidKey) | 635 » » » » So(qi.err, ShouldEqual, datastore.ErrInvalidKey) |
| 545 }) | 636 }) |
| 546 Convey("non-ancestor queries in a transaction", func() { | 637 Convey("non-ancestor queries in a transaction", func() { |
| 547 qi := q.(*queryImpl).checkCorrectness("", true) | 638 qi := q.(*queryImpl).checkCorrectness("", true) |
| 548 So(qi.err.Error(), ShouldContainSubstring, "Only
ancestor queries") | 639 So(qi.err.Error(), ShouldContainSubstring, "Only
ancestor queries") |
| 549 }) | 640 }) |
| 550 Convey("absurd numbers of filters are prohibited", func(
) { | 641 Convey("absurd numbers of filters are prohibited", func(
) { |
| 551 » » » » q := q.Ancestor(rds.NewKey("thing", "wat", 0, ni
l)) | 642 » » » » q := q.Ancestor(ds.NewKey("thing", "wat", 0, nil
)) |
| 552 for i := 0; i < 100; i++ { | 643 for i := 0; i < 100; i++ { |
| 553 q = q.Filter("something =", 10) | 644 q = q.Filter("something =", 10) |
| 554 } | 645 } |
| 555 qi := q.(*queryImpl).checkCorrectness("", false) | 646 qi := q.(*queryImpl).checkCorrectness("", false) |
| 556 So(qi.err.Error(), ShouldContainSubstring, "quer
y is too large") | 647 So(qi.err.Error(), ShouldContainSubstring, "quer
y is too large") |
| 557 }) | 648 }) |
| 558 Convey("filters for __key__ that aren't keys", func() { | 649 Convey("filters for __key__ that aren't keys", func() { |
| 559 q := q.Filter("__key__ = ", 10) | 650 q := q.Filter("__key__ = ", 10) |
| 560 qi := q.(*queryImpl).checkCorrectness("", false) | 651 qi := q.(*queryImpl).checkCorrectness("", false) |
| 561 So(qi.err.Error(), ShouldContainSubstring, "must
be a Key") | 652 So(qi.err.Error(), ShouldContainSubstring, "must
be a Key") |
| 562 }) | 653 }) |
| 563 Convey("multiple inequalities", func() { | 654 Convey("multiple inequalities", func() { |
| 564 q := q.Filter("bob > ", 19).Filter("charlie < ",
20) | 655 q := q.Filter("bob > ", 19).Filter("charlie < ",
20) |
| 565 qi := q.(*queryImpl).checkCorrectness("", false) | 656 qi := q.(*queryImpl).checkCorrectness("", false) |
| 566 So(qi.err.Error(), ShouldContainSubstring, "one
inequality filter") | 657 So(qi.err.Error(), ShouldContainSubstring, "one
inequality filter") |
| 567 }) | 658 }) |
| 568 Convey("bad sort orders", func() { | 659 Convey("bad sort orders", func() { |
| 569 q := q.Filter("bob > ", 19).Order("-charlie") | 660 q := q.Filter("bob > ", 19).Order("-charlie") |
| 570 qi := q.(*queryImpl).checkCorrectness("", false) | 661 qi := q.(*queryImpl).checkCorrectness("", false) |
| 571 So(qi.err.Error(), ShouldContainSubstring, "firs
t sort property") | 662 So(qi.err.Error(), ShouldContainSubstring, "firs
t sort property") |
| 572 }) | 663 }) |
| 573 Convey("kindless with non-__key__ filters", func() { | 664 Convey("kindless with non-__key__ filters", func() { |
| 574 » » » » q := rds.NewQuery("").Filter("face <", 25.3) | 665 » » » » q := ds.NewQuery("").Filter("face <", 25.3) |
| 575 qi := q.(*queryImpl).checkCorrectness("", false) | 666 qi := q.(*queryImpl).checkCorrectness("", false) |
| 576 So(qi.err.Error(), ShouldContainSubstring, "kind
is required for non-__key__") | 667 So(qi.err.Error(), ShouldContainSubstring, "kind
is required for non-__key__") |
| 577 }) | 668 }) |
| 578 Convey("kindless with non-__key__ orders", func() { | 669 Convey("kindless with non-__key__ orders", func() { |
| 579 » » » » q := rds.NewQuery("").Order("face") | 670 » » » » q := ds.NewQuery("").Order("face") |
| 580 qi := q.(*queryImpl).checkCorrectness("", false) | 671 qi := q.(*queryImpl).checkCorrectness("", false) |
| 581 So(qi.err.Error(), ShouldContainSubstring, "kind
is required for all orders") | 672 So(qi.err.Error(), ShouldContainSubstring, "kind
is required for all orders") |
| 582 }) | 673 }) |
| 583 Convey("kindless with decending-__key__ orders", func()
{ | 674 Convey("kindless with decending-__key__ orders", func()
{ |
| 584 » » » » q := rds.NewQuery("").Order("-__key__") | 675 » » » » q := ds.NewQuery("").Order("-__key__") |
| 585 qi := q.(*queryImpl).checkCorrectness("", false) | 676 qi := q.(*queryImpl).checkCorrectness("", false) |
| 586 So(qi.err.Error(), ShouldContainSubstring, "kind
is required for all orders") | 677 So(qi.err.Error(), ShouldContainSubstring, "kind
is required for all orders") |
| 587 }) | 678 }) |
| 588 }) | 679 }) |
| 589 | 680 |
| 590 }) | 681 }) |
| 591 } | 682 } |
| OLD | NEW |