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 » rdsS "github.com/luci/gae/service/rawdatastore" | 12 » dsS "github.com/luci/gae/service/datastore" |
| 13 » infoS "github.com/luci/gae/service/info" |
13 . "github.com/smartystreets/goconvey/convey" | 14 . "github.com/smartystreets/goconvey/convey" |
14 "golang.org/x/net/context" | 15 "golang.org/x/net/context" |
15 ) | 16 ) |
16 | 17 |
17 func TestDatastoreKinder(t *testing.T) { | 18 func TestDatastoreKinder(t *testing.T) { |
18 t.Parallel() | 19 t.Parallel() |
19 | 20 |
20 Convey("Datastore keys", t, func() { | 21 Convey("Datastore keys", t, func() { |
21 c := Use(context.Background()) | 22 c := Use(context.Background()) |
22 » » rds := rdsS.Get(c) | 23 » » ds := dsS.Get(c) |
23 » » So(rds, ShouldNotBeNil) | 24 » » So(ds, ShouldNotBeNil) |
24 | 25 |
25 Convey("implements DSNewKeyer", func() { | 26 Convey("implements DSNewKeyer", func() { |
26 Convey("NewKey", func() { | 27 Convey("NewKey", func() { |
27 » » » » key := rds.NewKey("nerd", "stringID", 0, nil) | 28 » » » » key := ds.NewKey("nerd", "stringID", 0, nil) |
28 So(key, ShouldNotBeNil) | 29 So(key, ShouldNotBeNil) |
29 So(key.Kind(), ShouldEqual, "nerd") | 30 So(key.Kind(), ShouldEqual, "nerd") |
30 So(key.StringID(), ShouldEqual, "stringID") | 31 So(key.StringID(), ShouldEqual, "stringID") |
31 So(key.IntID(), ShouldEqual, 0) | 32 So(key.IntID(), ShouldEqual, 0) |
32 So(key.Parent(), ShouldBeNil) | 33 So(key.Parent(), ShouldBeNil) |
33 So(key.AppID(), ShouldEqual, "dev~app") | 34 So(key.AppID(), ShouldEqual, "dev~app") |
34 So(key.Namespace(), ShouldEqual, "") | 35 So(key.Namespace(), ShouldEqual, "") |
35 So(key.String(), ShouldEqual, "/nerd,stringID") | 36 So(key.String(), ShouldEqual, "/nerd,stringID") |
36 » » » » So(rdsS.KeyIncomplete(key), ShouldBeFalse) | 37 » » » » So(dsS.KeyIncomplete(key), ShouldBeFalse) |
37 » » » » So(rdsS.KeyValid(key, false, "dev~app", ""), Sho
uldBeTrue) | 38 » » » » So(dsS.KeyValid(key, false, "dev~app", ""), Shou
ldBeTrue) |
38 }) | 39 }) |
39 }) | 40 }) |
40 | 41 |
41 }) | 42 }) |
42 } | 43 } |
43 | 44 |
44 func testGetMeta(c context.Context, k rdsS.Key) int64 { | 45 type MetaGroup struct { |
45 » rds := rdsS.Get(c) | 46 » _id int64 `gae:"$id,1"` |
46 » retval := int64(0) | 47 » _kind string `gae:"$kind,__entity_group__"` |
47 » err := rds.GetMulti([]rdsS.Key{rds.NewKey("__entity_group__", "", 1, rds
S.KeyRoot(k))}, func(val rdsS.PropertyMap, err error) { | 48 » Parent dsS.Key `gae:"$parent"` |
48 » » if err != nil { | 49 |
49 » » » panic(err) | 50 » Version int64 `gae:"__version__"` |
50 » » } | 51 } |
51 » » retval = val["__version__"][0].Value().(int64) | 52 |
52 » }) | 53 func testGetMeta(c context.Context, k dsS.Key) int64 { |
53 » if err != nil { | 54 » ds := dsS.Get(c) |
| 55 » mg := &MetaGroup{Parent: dsS.KeyRoot(k)} |
| 56 » if err := ds.Get(mg); err != nil { |
54 panic(err) | 57 panic(err) |
55 } | 58 } |
56 » return retval | 59 » return mg.Version |
57 } | 60 } |
58 | 61 |
59 var pls = rdsS.GetPLS | 62 var pls = dsS.GetPLS |
| 63 |
| 64 type Foo struct { |
| 65 » Id int64 `gae:"$id"` |
| 66 » Parent dsS.Key `gae:"$parent"` |
| 67 |
| 68 » Val int |
| 69 } |
60 | 70 |
61 func TestDatastoreSingleReadWriter(t *testing.T) { | 71 func TestDatastoreSingleReadWriter(t *testing.T) { |
62 t.Parallel() | 72 t.Parallel() |
63 | 73 |
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 | |
106 Convey("Datastore single reads and writes", t, func() { | 74 Convey("Datastore single reads and writes", t, func() { |
107 c := Use(context.Background()) | 75 c := Use(context.Background()) |
108 » » rds := rdsS.Get(c) | 76 » » ds := dsS.Get(c) |
109 » » So(rds, ShouldNotBeNil) | 77 » » So(ds, ShouldNotBeNil) |
110 | 78 |
111 » » Convey("implements DSSingleReadWriter", func() { | 79 » » Convey("getting objects that DNE is an error", func() { |
112 » » » type Foo struct { | 80 » » » So(ds.Get(&Foo{Id: 1}), ShouldEqual, dsS.ErrNoSuchEntity
) |
113 » » » » Val int | 81 » » }) |
114 » » » } | 82 |
115 | 83 » » Convey("bad namespaces fail", func() { |
116 » » » Convey("getting objects that DNE is an error", func() { | 84 » » » _, err := infoS.Get(c).Namespace("$$blzyall") |
117 » » » » _, err := getOnePM(rds, rds.NewKey("Foo", "", 1,
nil)) | 85 » » » So(err.Error(), ShouldContainSubstring, "namespace \"$$b
lzyall\" does not match") |
118 » » » » So(err, ShouldEqual, rdsS.ErrNoSuchEntity) | 86 » » }) |
119 » » » }) | 87 |
120 | 88 » » Convey("Can Put stuff", func() { |
121 » » » Convey("Can Put stuff", func() { | 89 » » » // with an incomplete key! |
122 » » » » // with an incomplete key! | 90 » » » f := &Foo{Val: 10} |
123 » » » » k := rds.NewKey("Foo", "", 0, nil) | 91 » » » So(ds.Put(f), ShouldBeNil) |
124 » » » » f := &Foo{Val: 10} | 92 » » » k := ds.KeyForObj(f) |
125 » » » » k = putOne(rds, k, f) | 93 » » » So(k.String(), ShouldEqual, "/Foo,1") |
126 » » » » So(k.String(), ShouldEqual, "/Foo,1") | 94 |
127 | 95 » » » Convey("and Get it back", func() { |
128 » » » » Convey("and Get it back", func() { | 96 » » » » newFoo := &Foo{Id: 1} |
129 » » » » » newFoo := &Foo{} | 97 » » » » So(ds.Get(newFoo), ShouldBeNil) |
130 » » » » » getOne(rds, k, newFoo) | 98 » » » » So(newFoo, ShouldResemble, f) |
131 » » » » » So(newFoo, ShouldResemble, f) | 99 |
132 | 100 » » » » Convey("but it's hidden from a different namespa
ce", func() { |
133 » » » » » Convey("and we can Delete it", func() { | 101 » » » » » c, err := infoS.Get(c).Namespace("whomba
t") |
134 » » » » » » delOne(rds, k) | 102 » » » » » So(err, ShouldBeNil) |
135 » » » » » » _, err := getOnePM(rds, k) | 103 » » » » » ds = dsS.Get(c) |
136 » » » » » » So(err, ShouldEqual, rdsS.ErrNoS
uchEntity) | 104 » » » » » So(ds.Get(f), ShouldEqual, dsS.ErrNoSuch
Entity) |
137 » » » » » }) | 105 » » » » }) |
138 » » » » }) | 106 |
139 » » » » Convey("Deleteing with a bogus key is bad", func
() { | 107 » » » » Convey("and we can Delete it", func() { |
140 » » » » » So(delOneErr(rds, rds.NewKey("Foo", "wat
", 100, nil)), ShouldEqual, rdsS.ErrInvalidKey) | 108 » » » » » So(ds.Delete(k), ShouldBeNil) |
141 » » » » }) | 109 » » » » » So(ds.Get(newFoo), ShouldEqual, dsS.ErrN
oSuchEntity) |
142 » » » » Convey("Deleteing a DNE entity is fine", func()
{ | 110 » » » » }) |
143 » » » » » delOne(rds, rds.NewKey("Foo", "wat", 0,
nil)) | 111 |
144 » » » » }) | 112 » » » }) |
145 | 113 » » » Convey("Deleteing with a bogus key is bad", func() { |
146 » » » » Convey("with multiple puts", func() { | 114 » » » » So(ds.Delete(ds.NewKey("Foo", "wat", 100, nil)),
ShouldEqual, dsS.ErrInvalidKey) |
147 » » » » » So(testGetMeta(c, k), ShouldEqual, 1) | 115 » » » }) |
148 | 116 » » » Convey("Deleteing a DNE entity is fine", func() { |
149 » » » » » keys := []rdsS.Key{} | 117 » » » » So(ds.Delete(ds.NewKey("Foo", "wat", 0, nil)), S
houldBeNil) |
150 » » » » » vals := []rdsS.PropertyLoadSaver{} | 118 » » » }) |
151 | 119 |
152 » » » » » pkey := k | 120 » » » Convey("with multiple puts", func() { |
153 » » » » » for i := 0; i < 10; i++ { | 121 » » » » So(testGetMeta(c, k), ShouldEqual, 1) |
154 » » » » » » keys = append(keys, rds.NewKey("
Foo", "", 0, pkey)) | 122 |
155 » » » » » » vals = append(vals, pls(&Foo{Val
: 10})) | 123 » » » » foos := make([]Foo, 10) |
| 124 » » » » for i := range foos { |
| 125 » » » » » foos[i].Val = 10 |
| 126 » » » » » foos[i].Parent = k |
| 127 » » » » } |
| 128 » » » » So(ds.PutMulti(foos), ShouldBeNil) |
| 129 » » » » So(testGetMeta(c, k), ShouldEqual, 11) |
| 130 |
| 131 » » » » keys := make([]dsS.Key, len(foos)) |
| 132 » » » » for i, f := range foos { |
| 133 » » » » » keys[i] = ds.KeyForObj(&f) |
| 134 » » » » } |
| 135 |
| 136 » » » » Convey("ensure that group versions persist acros
s deletes", func() { |
| 137 » » » » » So(ds.DeleteMulti(append(keys, k)), Shou
ldBeNil) |
| 138 |
| 139 » » » » » // TODO(riannucci): replace with a Count
query instead of this cast |
| 140 » » » » » /* |
| 141 » » » » » » ents := ds.(*dsImpl).data.store.
GetCollection("ents:") |
| 142 » » » » » » num, _ := ents.GetTotals() |
| 143 » » » » » » // /__entity_root_ids__,Foo |
| 144 » » » » » » // /Foo,1/__entity_group__,1 |
| 145 » » » » » » // /Foo,1/__entity_group_ids__,1 |
| 146 » » » » » » So(num, ShouldEqual, 3) |
| 147 » » » » » */ |
| 148 |
| 149 » » » » » So(testGetMeta(c, k), ShouldEqual, 22) |
| 150 |
| 151 » » » » » So(ds.Put(&Foo{Id: 1}), ShouldBeNil) |
| 152 » » » » » So(testGetMeta(c, k), ShouldEqual, 23) |
| 153 » » » » }) |
| 154 |
| 155 » » » » Convey("can Get", func() { |
| 156 » » » » » vals := make([]dsS.PropertyMap, len(keys
)) |
| 157 » » » » » for i := range vals { |
| 158 » » » » » » vals[i] = dsS.PropertyMap{} |
| 159 » » » » » » vals[i].SetMeta("key", keys[i]) |
156 } | 160 } |
157 » » » » » i := 0 | 161 » » » » » So(ds.GetMulti(vals), ShouldBeNil) |
158 » » » » » err := rds.PutMulti(keys, vals, func(k r
dsS.Key, err error) { | 162 |
159 » » » » » » So(err, ShouldBeNil) | 163 » » » » » for i, val := range vals { |
160 » » » » » » keys[i] = k | 164 » » » » » » So(val, ShouldResemble, dsS.Prop
ertyMap{ |
161 » » » » » » i++ | 165 » » » » » » » "Val": {dsS.MkProperty(
10)}, |
162 » » » » » }) | 166 » » » » » » » "$key": {dsS.MkPropertyN
I(keys[i])}, |
163 » » » » » So(err, ShouldBeNil) | |
164 » » » » » So(testGetMeta(c, k), ShouldEqual, 11) | |
165 | |
166 » » » » » Convey("ensure that group versions persi
st across deletes", func() { | |
167 » » » » » » keys = append(keys, pkey) | |
168 » » » » » » err := rds.DeleteMulti(keys, fun
c(err error) { | |
169 » » » » » » » So(err, ShouldBeNil) | |
170 }) | 167 }) |
171 » » » » » » So(err, ShouldBeNil) | 168 » » » » » } |
172 | 169 » » » » }) |
173 » » » » » » // TODO(riannucci): replace with
a Count query instead of this cast | 170 |
174 » » » » » » /* | |
175 » » » » » » » ents := rds.(*dsImpl).da
ta.store.GetCollection("ents:") | |
176 » » » » » » » num, _ := ents.GetTotals
() | |
177 » » » » » » » // /__entity_root_ids__,
Foo | |
178 » » » » » » » // /Foo,1/__entity_group
__,1 | |
179 » » » » » » » // /Foo,1/__entity_group
_ids__,1 | |
180 » » » » » » » So(num, ShouldEqual, 3) | |
181 » » » » » » */ | |
182 | |
183 » » » » » » So(testGetMeta(c, k), ShouldEqua
l, 22) | |
184 | |
185 » » » » » » putOne(rds, k, f) | |
186 » » » » » » So(testGetMeta(c, k), ShouldEqua
l, 23) | |
187 » » » » » }) | |
188 | |
189 » » » » » Convey("can Get", func() { | |
190 » » » » » » vals := []rdsS.PropertyMap{} | |
191 » » » » » » err := rds.GetMulti(keys, func(p
m rdsS.PropertyMap, err error) { | |
192 » » » » » » » So(err, ShouldBeNil) | |
193 » » » » » » » vals = append(vals, pm) | |
194 » » » » » » }) | |
195 » » » » » » So(err, ShouldBeNil) | |
196 | |
197 » » » » » » for _, val := range vals { | |
198 » » » » » » » So(val, ShouldResemble,
rdsS.PropertyMap{"Val": {rdsS.MkProperty(10)}}) | |
199 » » » » » » } | |
200 » » » » » }) | |
201 » » » » }) | |
202 }) | 171 }) |
203 }) | 172 }) |
204 | 173 |
205 Convey("implements DSTransactioner", func() { | 174 Convey("implements DSTransactioner", func() { |
206 type Foo struct { | |
207 Val int | |
208 } | |
209 Convey("Put", func() { | 175 Convey("Put", func() { |
210 f := &Foo{Val: 10} | 176 f := &Foo{Val: 10} |
211 » » » » origKey := rds.NewKey("Foo", "", 0, nil) | 177 » » » » So(ds.Put(f), ShouldBeNil) |
212 » » » » k := putOne(rds, origKey, f) | 178 » » » » k := ds.KeyForObj(f) |
213 So(k.String(), ShouldEqual, "/Foo,1") | 179 So(k.String(), ShouldEqual, "/Foo,1") |
214 | 180 |
215 Convey("can Put new entity groups", func() { | 181 Convey("can Put new entity groups", func() { |
216 » » » » » err := rds.RunInTransaction(func(c conte
xt.Context) error { | 182 » » » » » err := ds.RunInTransaction(func(c contex
t.Context) error { |
217 » » » » » » rds := rdsS.Get(c) | 183 » » » » » » ds := dsS.Get(c) |
218 | 184 |
219 » » » » » » f1 := &Foo{Val: 100} | 185 » » » » » » f := &Foo{Val: 100} |
220 » » » » » » k := putOne(rds, origKey, f1) | 186 » » » » » » So(ds.Put(f), ShouldBeNil) |
221 » » » » » » So(k.String(), ShouldEqual, "/Fo
o,2") | 187 » » » » » » So(f.Id, ShouldEqual, 2) |
222 | 188 |
223 » » » » » » f2 := &Foo{Val: 200} | 189 » » » » » » f.Id = 0 |
224 » » » » » » k = putOne(rds, origKey, f2) | 190 » » » » » » f.Val = 200 |
225 » » » » » » So(k.String(), ShouldEqual, "/Fo
o,3") | 191 » » » » » » So(ds.Put(f), ShouldBeNil) |
226 | 192 » » » » » » So(f.Id, ShouldEqual, 3) |
227 » » » » » » return nil | 193 |
228 » » » » » }, &rdsS.TransactionOptions{XG: true}) | 194 » » » » » » return nil |
229 » » » » » So(err, ShouldBeNil) | 195 » » » » » }, &dsS.TransactionOptions{XG: true}) |
230 | 196 » » » » » So(err, ShouldBeNil) |
231 » » » » » f := &Foo{} | 197 |
232 » » » » » getOne(rds, rds.NewKey("Foo", "", 2, nil
), f) | 198 » » » » » f := &Foo{Id: 2} |
| 199 » » » » » So(ds.Get(f), ShouldBeNil) |
233 So(f.Val, ShouldEqual, 100) | 200 So(f.Val, ShouldEqual, 100) |
234 | 201 |
235 » » » » » getOne(rds, rds.NewKey("Foo", "", 3, nil
), f) | 202 » » » » » f.Id = 3 |
| 203 » » » » » So(ds.Get(f), ShouldBeNil) |
236 So(f.Val, ShouldEqual, 200) | 204 So(f.Val, ShouldEqual, 200) |
237 }) | 205 }) |
238 | 206 |
239 Convey("can Put new entities in a current group"
, func() { | 207 Convey("can Put new entities in a current group"
, func() { |
240 » » » » » par := k | 208 » » » » » err := ds.RunInTransaction(func(c contex
t.Context) error { |
241 » » » » » err := rds.RunInTransaction(func(c conte
xt.Context) error { | 209 » » » » » » ds := dsS.Get(c) |
242 » » » » » » rds := rdsS.Get(c) | 210 |
243 » » » » » » So(rds, ShouldNotBeNil) | 211 » » » » » » f := &Foo{Val: 100, Parent: k} |
244 | 212 » » » » » » So(ds.Put(f), ShouldBeNil) |
245 » » » » » » f1 := &Foo{Val: 100} | 213 » » » » » » So(ds.KeyForObj(f).String(), Sho
uldEqual, "/Foo,1/Foo,1") |
246 » » » » » » k := putOne(rds, rds.NewKey("Foo
", "", 0, par), f1) | 214 |
247 » » » » » » So(k.String(), ShouldEqual, "/Fo
o,1/Foo,1") | 215 » » » » » » f.Id = 0 |
248 | 216 » » » » » » f.Val = 200 |
249 » » » » » » f2 := &Foo{Val: 200} | 217 » » » » » » So(ds.Put(f), ShouldBeNil) |
250 » » » » » » k = putOne(rds, rds.NewKey("Foo"
, "", 0, par), f2) | 218 » » » » » » So(ds.KeyForObj(f).String(), Sho
uldEqual, "/Foo,1/Foo,2") |
251 » » » » » » So(k.String(), ShouldEqual, "/Fo
o,1/Foo,2") | 219 |
252 | 220 » » » » » » return nil |
253 » » » » » » return nil | 221 » » » » » }, nil) |
254 » » » » » }, nil) | 222 » » » » » So(err, ShouldBeNil) |
255 » » » » » So(err, ShouldBeNil) | 223 |
256 | 224 » » » » » f := &Foo{Id: 1, Parent: k} |
257 » » » » » f := &Foo{} | 225 » » » » » So(ds.Get(f), ShouldBeNil) |
258 » » » » » getOne(rds, rds.NewKey("Foo", "", 1, k),
f) | |
259 So(f.Val, ShouldEqual, 100) | 226 So(f.Val, ShouldEqual, 100) |
260 | 227 |
261 » » » » » getOne(rds, rds.NewKey("Foo", "", 2, k),
f) | 228 » » » » » f.Id = 2 |
| 229 » » » » » So(ds.Get(f), ShouldBeNil) |
262 So(f.Val, ShouldEqual, 200) | 230 So(f.Val, ShouldEqual, 200) |
263 }) | 231 }) |
264 | 232 |
265 Convey("Deletes work too", func() { | 233 Convey("Deletes work too", func() { |
266 » » » » » err := rds.RunInTransaction(func(c conte
xt.Context) error { | 234 » » » » » err := ds.RunInTransaction(func(c contex
t.Context) error { |
267 » » » » » » rds := rdsS.Get(c) | 235 » » » » » » return dsS.Get(c).Delete(k) |
268 » » » » » » So(rds, ShouldNotBeNil) | 236 » » » » » }, nil) |
269 » » » » » » delOne(rds, k) | 237 » » » » » So(err, ShouldBeNil) |
270 » » » » » » return nil | 238 » » » » » So(ds.Get(&Foo{Id: 1}), ShouldEqual, dsS
.ErrNoSuchEntity) |
271 » » » » » }, nil) | |
272 » » » » » So(err, ShouldBeNil) | |
273 » » » » » _, err = getOnePM(rds, k) | |
274 » » » » » So(err, ShouldEqual, rdsS.ErrNoSuchEntit
y) | |
275 }) | 239 }) |
276 | 240 |
277 Convey("A Get counts against your group count",
func() { | 241 Convey("A Get counts against your group count",
func() { |
278 » » » » » err := rds.RunInTransaction(func(c conte
xt.Context) error { | 242 » » » » » err := ds.RunInTransaction(func(c contex
t.Context) error { |
279 » » » » » » rds := rdsS.Get(c) | 243 » » » » » » ds := dsS.Get(c) |
280 | 244 |
281 » » » » » » _, err := getOnePM(rds, rds.NewK
ey("Foo", "", 20, nil)) | 245 » » » » » » pm := dsS.PropertyMap{} |
282 » » » » » » So(err, ShouldEqual, rdsS.ErrNoS
uchEntity) | 246 » » » » » » pm.SetMeta("key", ds.NewKey("Foo
", "", 20, nil)) |
283 | 247 » » » » » » So(ds.Get(pm), ShouldEqual, dsS.
ErrNoSuchEntity) |
284 » » » » » » err = rds.GetMulti([]rdsS.Key{k}
, func(_ rdsS.PropertyMap, err error) { | 248 |
285 » » » » » » » So(err, ShouldBeNil) | 249 » » » » » » pm.SetMeta("key", k) |
286 » » » » » » }) | 250 » » » » » » So(ds.Get(pm).Error(), ShouldCon
tainSubstring, "cross-group") |
287 » » » » » » So(err.Error(), ShouldContainSub
string, "cross-group") | |
288 return nil | 251 return nil |
289 }, nil) | 252 }, nil) |
290 So(err, ShouldBeNil) | 253 So(err, ShouldBeNil) |
291 }) | 254 }) |
292 | 255 |
293 Convey("Get takes a snapshot", func() { | 256 Convey("Get takes a snapshot", func() { |
294 » » » » » err := rds.RunInTransaction(func(c conte
xt.Context) error { | 257 » » » » » err := ds.RunInTransaction(func(c contex
t.Context) error { |
295 » » » » » » txnDS := rdsS.Get(c) | 258 » » » » » » txnDS := dsS.Get(c) |
296 » » » » » » So(txnDS, ShouldNotBeNil) | 259 |
297 | 260 » » » » » » So(txnDS.Get(f), ShouldBeNil) |
298 » » » » » » getOne(txnDS, k, f) | |
299 So(f.Val, ShouldEqual, 10) | 261 So(f.Val, ShouldEqual, 10) |
300 | 262 |
301 // Don't ever do this in a real
program unless you want to guarantee | 263 // Don't ever do this in a real
program unless you want to guarantee |
302 // a failed transaction :) | 264 // a failed transaction :) |
303 f.Val = 11 | 265 f.Val = 11 |
304 » » » » » » putOne(rds, k, f) | 266 » » » » » » So(ds.Put(f), ShouldBeNil) |
305 | 267 |
306 » » » » » » getOne(txnDS, k, f) | 268 » » » » » » So(txnDS.Get(f), ShouldBeNil) |
307 » » » » » » So(f.Val, ShouldEqual, 10) | 269 » » » » » » So(f.Val, ShouldEqual, 10) |
308 | 270 |
309 » » » » » » return nil | 271 » » » » » » return nil |
310 » » » » » }, nil) | 272 » » » » » }, nil) |
311 » » » » » So(err, ShouldBeNil) | 273 » » » » » So(err, ShouldBeNil) |
312 | 274 |
313 » » » » » f := &Foo{} | 275 » » » » » f := &Foo{Id: 1} |
314 » » » » » getOne(rds, k, f) | 276 » » » » » So(ds.Get(f), ShouldBeNil) |
315 So(f.Val, ShouldEqual, 11) | 277 So(f.Val, ShouldEqual, 11) |
316 }) | 278 }) |
317 | 279 |
318 Convey("and snapshots are consistent even after
Puts", func() { | 280 Convey("and snapshots are consistent even after
Puts", func() { |
319 » » » » » err := rds.RunInTransaction(func(c conte
xt.Context) error { | 281 » » » » » err := ds.RunInTransaction(func(c contex
t.Context) error { |
320 » » » » » » txnDS := rdsS.Get(c) | 282 » » » » » » txnDS := dsS.Get(c) |
321 » » » » » » So(txnDS, ShouldNotBeNil) | 283 |
322 | 284 » » » » » » f := &Foo{Id: 1} |
323 » » » » » » f := &Foo{} | 285 » » » » » » So(txnDS.Get(f), ShouldBeNil) |
324 » » » » » » getOne(txnDS, k, f) | |
325 So(f.Val, ShouldEqual, 10) | 286 So(f.Val, ShouldEqual, 10) |
326 | 287 |
327 // Don't ever do this in a real
program unless you want to guarantee | 288 // Don't ever do this in a real
program unless you want to guarantee |
328 // a failed transaction :) | 289 // a failed transaction :) |
329 f.Val = 11 | 290 f.Val = 11 |
330 » » » » » » putOne(rds, k, f) | 291 » » » » » » So(ds.Put(f), ShouldBeNil) |
331 | 292 |
332 » » » » » » getOne(txnDS, k, f) | 293 » » » » » » So(txnDS.Get(f), ShouldBeNil) |
333 So(f.Val, ShouldEqual, 10) | 294 So(f.Val, ShouldEqual, 10) |
334 | 295 |
335 f.Val = 20 | 296 f.Val = 20 |
336 » » » » » » putOne(txnDS, k, f) | 297 » » » » » » So(txnDS.Put(f), ShouldBeNil) |
337 | 298 |
338 » » » » » » getOne(txnDS, k, f) | 299 » » » » » » So(txnDS.Get(f), ShouldBeNil) |
339 So(f.Val, ShouldEqual, 10) // st
ill gets 10 | 300 So(f.Val, ShouldEqual, 10) // st
ill gets 10 |
340 | 301 |
341 return nil | 302 return nil |
342 }, nil) | 303 }, nil) |
343 So(err.Error(), ShouldContainSubstring,
"concurrent") | 304 So(err.Error(), ShouldContainSubstring,
"concurrent") |
344 | 305 |
345 » » » » » f := &Foo{} | 306 » » » » » f := &Foo{Id: 1} |
346 » » » » » getOne(rds, k, f) | 307 » » » » » So(ds.Get(f), ShouldBeNil) |
347 So(f.Val, ShouldEqual, 11) | 308 So(f.Val, ShouldEqual, 11) |
348 }) | 309 }) |
349 | 310 |
350 Convey("Reusing a transaction context is bad new
s", func() { | 311 Convey("Reusing a transaction context is bad new
s", func() { |
351 » » » » » k := rds.NewKey("Foo", "", 1, nil) | 312 » » » » » txnDS := dsS.Interface(nil) |
352 » » » » » txnDS := rdsS.Interface(nil) | 313 » » » » » err := ds.RunInTransaction(func(c contex
t.Context) error { |
353 » » » » » err := rds.RunInTransaction(func(c conte
xt.Context) error { | 314 » » » » » » txnDS = dsS.Get(c) |
354 » » » » » » txnDS = rdsS.Get(c) | 315 » » » » » » So(txnDS.Get(f), ShouldBeNil) |
355 » » » » » » getOnePM(txnDS, k) | 316 » » » » » » return nil |
356 » » » » » » return nil | 317 » » » » » }, nil) |
357 » » » » » }, nil) | 318 » » » » » So(err, ShouldBeNil) |
358 » » » » » So(err, ShouldBeNil) | 319 » » » » » So(txnDS.Get(f).Error(), ShouldContainSu
bstring, "expired") |
359 » » » » » err = txnDS.GetMulti([]rdsS.Key{k}, func
(_ rdsS.PropertyMap, err error) { | |
360 » » » » » » So(err, ShouldBeNil) | |
361 » » » » » }) | |
362 » » » » » So(err.Error(), ShouldContainSubstring,
"expired") | |
363 }) | 320 }) |
364 | 321 |
365 Convey("Nested transactions are rejected", func(
) { | 322 Convey("Nested transactions are rejected", func(
) { |
366 » » » » » err := rds.RunInTransaction(func(c conte
xt.Context) error { | 323 » » » » » err := ds.RunInTransaction(func(c contex
t.Context) error { |
367 » » » » » » err := rdsS.Get(c).RunInTransact
ion(func(c context.Context) error { | 324 » » » » » » err := dsS.Get(c).RunInTransacti
on(func(c context.Context) error { |
368 panic("noooo") | 325 panic("noooo") |
369 }, nil) | 326 }, nil) |
370 So(err.Error(), ShouldContainSub
string, "nested transactions") | 327 So(err.Error(), ShouldContainSub
string, "nested transactions") |
371 return nil | 328 return nil |
372 }, nil) | 329 }, nil) |
373 So(err, ShouldBeNil) | 330 So(err, ShouldBeNil) |
374 }) | 331 }) |
375 | 332 |
376 Convey("Concurrent transactions only accept one
set of changes", func() { | 333 Convey("Concurrent transactions only accept one
set of changes", func() { |
377 // Note: I think this implementation is
actually /slightly/ wrong. | 334 // Note: I think this implementation is
actually /slightly/ wrong. |
378 // Accorting to my read of the docs for
appengine, when you open a | 335 // Accorting to my read of the docs for
appengine, when you open a |
379 // transaction it actually (essentially)
holds a reference to the | 336 // transaction it actually (essentially)
holds a reference to the |
380 // entire datastore. Our implementation
takes a snapshot of the | 337 // entire datastore. Our implementation
takes a snapshot of the |
381 // entity group as soon as something obs
erves/affects it. | 338 // entity group as soon as something obs
erves/affects it. |
382 // | 339 // |
383 // That said... I'm not sure if there's
really a semantic difference. | 340 // That said... I'm not sure if there's
really a semantic difference. |
384 » » » » » err := rds.RunInTransaction(func(c conte
xt.Context) error { | 341 » » » » » err := ds.RunInTransaction(func(c contex
t.Context) error { |
385 » » » » » » txnDS := rdsS.Get(c) | 342 » » » » » » So(dsS.Get(c).Put(&Foo{Id: 1, Va
l: 21}), ShouldBeNil) |
386 » » » » » » f := &Foo{Val: 21} | |
387 » » » » » » putOne(txnDS, k, f) | |
388 | 343 |
389 » » » » » » err := rds.RunInTransaction(func
(c context.Context) error { | 344 » » » » » » err := ds.RunInTransaction(func(
c context.Context) error { |
390 » » » » » » » txnDS := rdsS.Get(c) | 345 » » » » » » » So(dsS.Get(c).Put(&Foo{I
d: 1, Val: 27}), ShouldBeNil) |
391 » » » » » » » f := &Foo{Val: 27} | |
392 » » » » » » » putOne(txnDS, k, f) | |
393 return nil | 346 return nil |
394 }, nil) | 347 }, nil) |
395 So(err, ShouldBeNil) | 348 So(err, ShouldBeNil) |
396 | 349 |
397 return nil | 350 return nil |
398 }, nil) | 351 }, nil) |
399 So(err.Error(), ShouldContainSubstring,
"concurrent") | 352 So(err.Error(), ShouldContainSubstring,
"concurrent") |
400 | 353 |
401 » » » » » f := &Foo{} | 354 » » » » » f := &Foo{Id: 1} |
402 » » » » » getOne(rds, k, f) | 355 » » » » » So(ds.Get(f), ShouldBeNil) |
403 So(f.Val, ShouldEqual, 27) | 356 So(f.Val, ShouldEqual, 27) |
404 }) | 357 }) |
405 | 358 |
406 Convey("XG", func() { | 359 Convey("XG", func() { |
407 Convey("Modifying two groups with XG=fal
se is invalid", func() { | 360 Convey("Modifying two groups with XG=fal
se is invalid", func() { |
408 » » » » » » err := rds.RunInTransaction(func
(c context.Context) error { | 361 » » » » » » err := ds.RunInTransaction(func(
c context.Context) error { |
409 » » » » » » » rds := rdsS.Get(c) | 362 » » » » » » » ds := dsS.Get(c) |
410 » » » » » » » f := &Foo{Val: 200} | 363 » » » » » » » f := &Foo{Id: 1, Val: 20
0} |
411 » » » » » » » putOne(rds, k, f) | 364 » » » » » » » So(ds.Put(f), ShouldBeNi
l) |
412 | 365 |
413 » » » » » » » _, err := putOneErr(rds,
rds.NewKey("Foo", "", 2, nil), f) | 366 » » » » » » » f.Id = 2 |
| 367 » » » » » » » err := ds.Put(f) |
414 So(err.Error(), ShouldCo
ntainSubstring, "cross-group") | 368 So(err.Error(), ShouldCo
ntainSubstring, "cross-group") |
415 return err | 369 return err |
416 }, nil) | 370 }, nil) |
417 So(err.Error(), ShouldContainSub
string, "cross-group") | 371 So(err.Error(), ShouldContainSub
string, "cross-group") |
418 }) | 372 }) |
419 | 373 |
420 Convey("Modifying >25 groups with XG=tru
e is invald", func() { | 374 Convey("Modifying >25 groups with XG=tru
e is invald", func() { |
421 » » » » » » err := rds.RunInTransaction(func
(c context.Context) error { | 375 » » » » » » err := ds.RunInTransaction(func(
c context.Context) error { |
422 » » » » » » » rds := rdsS.Get(c) | 376 » » » » » » » ds := dsS.Get(c) |
| 377 » » » » » » » foos := make([]Foo, 25) |
423 for i := int64(1); i < 2
6; i++ { | 378 for i := int64(1); i < 2
6; i++ { |
424 » » » » » » » » k := rds.NewKey(
"Foo", "", i, nil) | 379 » » » » » » » » foos[i-1].Id = i |
425 » » » » » » » » f := &Foo{Val: 2
00} | 380 » » » » » » » » foos[i-1].Val =
200 |
426 » » » » » » » » putOne(rds, k, f
) | |
427 } | 381 } |
428 » » » » » » » f := &Foo{Val: 200} | 382 » » » » » » » So(ds.PutMulti(foos), Sh
ouldBeNil) |
429 » » » » » » » _, err := putOneErr(rds,
rds.NewKey("Foo", "", 27, nil), f) | 383 » » » » » » » err := ds.Put(&Foo{Id: 2
6}) |
430 So(err.Error(), ShouldCo
ntainSubstring, "too many entity groups") | 384 So(err.Error(), ShouldCo
ntainSubstring, "too many entity groups") |
431 return err | 385 return err |
432 » » » » » » }, &rdsS.TransactionOptions{XG:
true}) | 386 » » » » » » }, &dsS.TransactionOptions{XG: t
rue}) |
433 So(err.Error(), ShouldContainSub
string, "too many entity groups") | 387 So(err.Error(), ShouldContainSub
string, "too many entity groups") |
434 }) | 388 }) |
435 }) | 389 }) |
436 | 390 |
437 Convey("Errors and panics", func() { | 391 Convey("Errors and panics", func() { |
438 Convey("returning an error aborts", func
() { | 392 Convey("returning an error aborts", func
() { |
439 » » » » » » err := rds.RunInTransaction(func
(c context.Context) error { | 393 » » » » » » err := ds.RunInTransaction(func(
c context.Context) error { |
440 » » » » » » » rds := rdsS.Get(c) | 394 » » » » » » » ds := dsS.Get(c) |
441 » » » » » » » f := &Foo{Val: 200} | 395 » » » » » » » So(ds.Put(&Foo{Id: 1, Va
l: 200}), ShouldBeNil) |
442 » » » » » » » putOne(rds, k, f) | |
443 | |
444 return fmt.Errorf("thing
y") | 396 return fmt.Errorf("thing
y") |
445 }, nil) | 397 }, nil) |
446 So(err.Error(), ShouldEqual, "th
ingy") | 398 So(err.Error(), ShouldEqual, "th
ingy") |
447 | 399 |
448 » » » » » » f := &Foo{} | 400 » » » » » » f := &Foo{Id: 1} |
449 » » » » » » getOne(rds, k, f) | 401 » » » » » » So(ds.Get(f), ShouldBeNil) |
450 So(f.Val, ShouldEqual, 10) | 402 So(f.Val, ShouldEqual, 10) |
451 }) | 403 }) |
452 | 404 |
453 Convey("panicing aborts", func() { | 405 Convey("panicing aborts", func() { |
454 So(func() { | 406 So(func() { |
455 » » » » » » » rds.RunInTransaction(fun
c(c context.Context) error { | 407 » » » » » » » ds.RunInTransaction(func
(c context.Context) error { |
456 » » » » » » » » rds := rdsS.Get(
c) | 408 » » » » » » » » ds := dsS.Get(c) |
457 » » » » » » » » f := &Foo{Val: 2
00} | 409 » » » » » » » » So(ds.Put(&Foo{V
al: 200}), ShouldBeNil) |
458 » » » » » » » » putOne(rds, k, f
) | |
459 panic("wheeeeee"
) | 410 panic("wheeeeee"
) |
460 }, nil) | 411 }, nil) |
461 }, ShouldPanic) | 412 }, ShouldPanic) |
462 | 413 |
463 » » » » » » f := &Foo{} | 414 » » » » » » f := &Foo{Id: 1} |
464 » » » » » » getOne(rds, k, f) | 415 » » » » » » So(ds.Get(f), ShouldBeNil) |
465 So(f.Val, ShouldEqual, 10) | 416 So(f.Val, ShouldEqual, 10) |
466 }) | 417 }) |
467 }) | 418 }) |
468 }) | 419 }) |
469 }) | 420 }) |
470 | 421 |
471 }) | 422 }) |
472 } | 423 } |
473 | 424 |
474 const MaxUint = ^uint(0) | 425 const MaxUint = ^uint(0) |
475 const MaxInt = int(MaxUint >> 1) | 426 const MaxInt = int(MaxUint >> 1) |
476 const IntIs32Bits = int64(MaxInt) < math.MaxInt64 | 427 const IntIs32Bits = int64(MaxInt) < math.MaxInt64 |
477 | 428 |
478 func TestDatastoreQueryer(t *testing.T) { | 429 func TestDatastoreQueryer(t *testing.T) { |
479 Convey("Datastore Query suport", t, func() { | 430 Convey("Datastore Query suport", t, func() { |
480 c := Use(context.Background()) | 431 c := Use(context.Background()) |
481 » » rds := rdsS.Get(c) | 432 » » ds := dsS.Get(c) |
482 » » So(rds, ShouldNotBeNil) | 433 » » So(ds, ShouldNotBeNil) |
483 | 434 |
484 Convey("can create good queries", func() { | 435 Convey("can create good queries", func() { |
485 » » » q := rds.NewQuery("Foo").KeysOnly().Limit(10).Offset(39) | 436 » » » q := ds.NewQuery("Foo").KeysOnly().Limit(10).Offset(39) |
486 q = q.Start(queryCursor("kosmik")).End(queryCursor("krab
s")) | 437 q = q.Start(queryCursor("kosmik")).End(queryCursor("krab
s")) |
487 So(q, ShouldNotBeNil) | 438 So(q, ShouldNotBeNil) |
488 So(q.(*queryImpl).err, ShouldBeNil) | 439 So(q.(*queryImpl).err, ShouldBeNil) |
489 qi := q.(*queryImpl).checkCorrectness("", false) | 440 qi := q.(*queryImpl).checkCorrectness("", false) |
490 So(qi.err, ShouldBeNil) | 441 So(qi.err, ShouldBeNil) |
491 }) | 442 }) |
492 | 443 |
493 Convey("normalize ensures orders make sense", func() { | 444 Convey("normalize ensures orders make sense", func() { |
494 » » » q := rds.NewQuery("Cool") | 445 » » » q := ds.NewQuery("Cool") |
495 q = q.Filter("cat =", 19).Filter("bob =", 10).Order("bob
").Order("bob") | 446 q = q.Filter("cat =", 19).Filter("bob =", 10).Order("bob
").Order("bob") |
496 | 447 |
497 Convey("removes dups and equality orders", func() { | 448 Convey("removes dups and equality orders", func() { |
498 q = q.Order("wat") | 449 q = q.Order("wat") |
499 qi := q.(*queryImpl).normalize().checkCorrectnes
s("", false) | 450 qi := q.(*queryImpl).normalize().checkCorrectnes
s("", false) |
500 So(qi.err, ShouldBeNil) | 451 So(qi.err, ShouldBeNil) |
501 So(qi.order, ShouldResemble, []queryOrder{{"wat"
, qASC}}) | 452 So(qi.order, ShouldResemble, []queryOrder{{"wat"
, qASC}}) |
502 }) | 453 }) |
503 | 454 |
504 Convey("keeps inequality orders", func() { | 455 Convey("keeps inequality orders", func() { |
505 q = q.Order("wat") | 456 q = q.Order("wat") |
506 q := q.Filter("bob >", 10).Filter("wat <", 29) | 457 q := q.Filter("bob >", 10).Filter("wat <", 29) |
507 qi := q.(*queryImpl).normalize().checkCorrectnes
s("", false) | 458 qi := q.(*queryImpl).normalize().checkCorrectnes
s("", false) |
508 So(qi.order, ShouldResemble, []queryOrder{{"bob"
, qASC}, {"wat", qASC}}) | 459 So(qi.order, ShouldResemble, []queryOrder{{"bob"
, qASC}, {"wat", qASC}}) |
509 So(qi.err.Error(), ShouldContainSubstring, "Only
one inequality") | 460 So(qi.err.Error(), ShouldContainSubstring, "Only
one inequality") |
510 }) | 461 }) |
511 | 462 |
512 Convey("if we equality-filter on __key__, order is ditch
ed", func() { | 463 Convey("if we equality-filter on __key__, order is ditch
ed", func() { |
513 q = q.Order("wat") | 464 q = q.Order("wat") |
514 » » » » q := q.Filter("__key__ =", rds.NewKey("Foo", "wa
t", 0, nil)) | 465 » » » » q := q.Filter("__key__ =", ds.NewKey("Foo", "wat
", 0, nil)) |
515 qi := q.(*queryImpl).normalize().checkCorrectnes
s("", false) | 466 qi := q.(*queryImpl).normalize().checkCorrectnes
s("", false) |
516 So(qi.order, ShouldResemble, []queryOrder(nil)) | 467 So(qi.order, ShouldResemble, []queryOrder(nil)) |
517 So(qi.err, ShouldBeNil) | 468 So(qi.err, ShouldBeNil) |
518 }) | 469 }) |
519 | 470 |
520 Convey("if we order by key and something else, key domin
ates", func() { | 471 Convey("if we order by key and something else, key domin
ates", func() { |
521 q := q.Order("__key__").Order("wat") | 472 q := q.Order("__key__").Order("wat") |
522 qi := q.(*queryImpl).normalize().checkCorrectnes
s("", false) | 473 qi := q.(*queryImpl).normalize().checkCorrectnes
s("", false) |
523 So(qi.order, ShouldResemble, []queryOrder{{"__ke
y__", qASC}}) | 474 So(qi.order, ShouldResemble, []queryOrder{{"__ke
y__", qASC}}) |
524 So(qi.err, ShouldBeNil) | 475 So(qi.err, ShouldBeNil) |
525 }) | 476 }) |
526 }) | 477 }) |
527 | 478 |
528 Convey("can create bad queries", func() { | 479 Convey("can create bad queries", func() { |
529 » » » q := rds.NewQuery("Foo") | 480 » » » q := ds.NewQuery("Foo") |
530 | 481 |
531 Convey("bad filter ops", func() { | 482 Convey("bad filter ops", func() { |
532 q := q.Filter("Bob !", "value") | 483 q := q.Filter("Bob !", "value") |
533 So(q.(*queryImpl).err.Error(), ShouldContainSubs
tring, "invalid operator \"!\"") | 484 So(q.(*queryImpl).err.Error(), ShouldContainSubs
tring, "invalid operator \"!\"") |
534 }) | 485 }) |
535 Convey("bad filter", func() { | 486 Convey("bad filter", func() { |
536 q := q.Filter("Bob", "value") | 487 q := q.Filter("Bob", "value") |
537 So(q.(*queryImpl).err.Error(), ShouldContainSubs
tring, "invalid filter") | 488 So(q.(*queryImpl).err.Error(), ShouldContainSubs
tring, "invalid filter") |
538 }) | 489 }) |
539 Convey("bad order", func() { | 490 Convey("bad order", func() { |
(...skipping 20 matching lines...) Expand all Loading... |
560 if !IntIs32Bits { | 511 if !IntIs32Bits { |
561 q := q.Offset(MaxInt) | 512 q := q.Offset(MaxInt) |
562 So(q.(*queryImpl).err.Error(), ShouldCon
tainSubstring, "query offset overflow") | 513 So(q.(*queryImpl).err.Error(), ShouldCon
tainSubstring, "query offset overflow") |
563 } | 514 } |
564 }) | 515 }) |
565 Convey("Bad cursors", func() { | 516 Convey("Bad cursors", func() { |
566 q := q.Start(queryCursor("")).End(queryCursor(""
)) | 517 q := q.Start(queryCursor("")).End(queryCursor(""
)) |
567 So(q.(*queryImpl).err.Error(), ShouldContainSubs
tring, "invalid cursor") | 518 So(q.(*queryImpl).err.Error(), ShouldContainSubs
tring, "invalid cursor") |
568 }) | 519 }) |
569 Convey("Bad ancestors", func() { | 520 Convey("Bad ancestors", func() { |
570 » » » » q := q.Ancestor(rds.NewKey("Goop", "wat", 10, ni
l)) | 521 » » » » q := q.Ancestor(ds.NewKey("Goop", "wat", 10, nil
)) |
571 So(q, ShouldNotBeNil) | 522 So(q, ShouldNotBeNil) |
572 qi := q.(*queryImpl).checkCorrectness("", false) | 523 qi := q.(*queryImpl).checkCorrectness("", false) |
573 » » » » So(qi.err, ShouldEqual, rdsS.ErrInvalidKey) | 524 » » » » So(qi.err, ShouldEqual, dsS.ErrInvalidKey) |
574 }) | 525 }) |
575 Convey("nil ancestors", func() { | 526 Convey("nil ancestors", func() { |
576 qi := q.Ancestor(nil).(*queryImpl).checkCorrectn
ess("", false) | 527 qi := q.Ancestor(nil).(*queryImpl).checkCorrectn
ess("", false) |
577 So(qi.err.Error(), ShouldContainSubstring, "nil
query ancestor") | 528 So(qi.err.Error(), ShouldContainSubstring, "nil
query ancestor") |
578 }) | 529 }) |
579 Convey("Bad key filters", func() { | 530 Convey("Bad key filters", func() { |
580 » » » » q := q.Filter("__key__ =", rds.NewKey("Goop", "w
at", 10, nil)) | 531 » » » » q := q.Filter("__key__ =", ds.NewKey("Goop", "wa
t", 10, nil)) |
581 qi := q.(*queryImpl).checkCorrectness("", false) | 532 qi := q.(*queryImpl).checkCorrectness("", false) |
582 » » » » So(qi.err, ShouldEqual, rdsS.ErrInvalidKey) | 533 » » » » So(qi.err, ShouldEqual, dsS.ErrInvalidKey) |
583 }) | 534 }) |
584 Convey("non-ancestor queries in a transaction", func() { | 535 Convey("non-ancestor queries in a transaction", func() { |
585 qi := q.(*queryImpl).checkCorrectness("", true) | 536 qi := q.(*queryImpl).checkCorrectness("", true) |
586 So(qi.err.Error(), ShouldContainSubstring, "Only
ancestor queries") | 537 So(qi.err.Error(), ShouldContainSubstring, "Only
ancestor queries") |
587 }) | 538 }) |
588 Convey("absurd numbers of filters are prohibited", func(
) { | 539 Convey("absurd numbers of filters are prohibited", func(
) { |
589 » » » » q := q.Ancestor(rds.NewKey("thing", "wat", 0, ni
l)) | 540 » » » » q := q.Ancestor(ds.NewKey("thing", "wat", 0, nil
)) |
590 for i := 0; i < 100; i++ { | 541 for i := 0; i < 100; i++ { |
591 q = q.Filter("something =", 10) | 542 q = q.Filter("something =", 10) |
592 } | 543 } |
593 qi := q.(*queryImpl).checkCorrectness("", false) | 544 qi := q.(*queryImpl).checkCorrectness("", false) |
594 So(qi.err.Error(), ShouldContainSubstring, "quer
y is too large") | 545 So(qi.err.Error(), ShouldContainSubstring, "quer
y is too large") |
595 }) | 546 }) |
596 Convey("filters for __key__ that aren't keys", func() { | 547 Convey("filters for __key__ that aren't keys", func() { |
597 q := q.Filter("__key__ = ", 10) | 548 q := q.Filter("__key__ = ", 10) |
598 qi := q.(*queryImpl).checkCorrectness("", false) | 549 qi := q.(*queryImpl).checkCorrectness("", false) |
599 So(qi.err.Error(), ShouldContainSubstring, "must
be a Key") | 550 So(qi.err.Error(), ShouldContainSubstring, "must
be a Key") |
600 }) | 551 }) |
601 Convey("multiple inequalities", func() { | 552 Convey("multiple inequalities", func() { |
602 q := q.Filter("bob > ", 19).Filter("charlie < ",
20) | 553 q := q.Filter("bob > ", 19).Filter("charlie < ",
20) |
603 qi := q.(*queryImpl).checkCorrectness("", false) | 554 qi := q.(*queryImpl).checkCorrectness("", false) |
604 So(qi.err.Error(), ShouldContainSubstring, "one
inequality filter") | 555 So(qi.err.Error(), ShouldContainSubstring, "one
inequality filter") |
605 }) | 556 }) |
606 Convey("bad sort orders", func() { | 557 Convey("bad sort orders", func() { |
607 q := q.Filter("bob > ", 19).Order("-charlie") | 558 q := q.Filter("bob > ", 19).Order("-charlie") |
608 qi := q.(*queryImpl).checkCorrectness("", false) | 559 qi := q.(*queryImpl).checkCorrectness("", false) |
609 So(qi.err.Error(), ShouldContainSubstring, "firs
t sort property") | 560 So(qi.err.Error(), ShouldContainSubstring, "firs
t sort property") |
610 }) | 561 }) |
611 Convey("kindless with non-__key__ filters", func() { | 562 Convey("kindless with non-__key__ filters", func() { |
612 » » » » q := rds.NewQuery("").Filter("face <", 25.3) | 563 » » » » q := ds.NewQuery("").Filter("face <", 25.3) |
613 qi := q.(*queryImpl).checkCorrectness("", false) | 564 qi := q.(*queryImpl).checkCorrectness("", false) |
614 So(qi.err.Error(), ShouldContainSubstring, "kind
is required for non-__key__") | 565 So(qi.err.Error(), ShouldContainSubstring, "kind
is required for non-__key__") |
615 }) | 566 }) |
616 Convey("kindless with non-__key__ orders", func() { | 567 Convey("kindless with non-__key__ orders", func() { |
617 » » » » q := rds.NewQuery("").Order("face") | 568 » » » » q := ds.NewQuery("").Order("face") |
618 qi := q.(*queryImpl).checkCorrectness("", false) | 569 qi := q.(*queryImpl).checkCorrectness("", false) |
619 So(qi.err.Error(), ShouldContainSubstring, "kind
is required for all orders") | 570 So(qi.err.Error(), ShouldContainSubstring, "kind
is required for all orders") |
620 }) | 571 }) |
621 Convey("kindless with decending-__key__ orders", func()
{ | 572 Convey("kindless with decending-__key__ orders", func()
{ |
622 » » » » q := rds.NewQuery("").Order("-__key__") | 573 » » » » q := ds.NewQuery("").Order("-__key__") |
623 qi := q.(*queryImpl).checkCorrectness("", false) | 574 qi := q.(*queryImpl).checkCorrectness("", false) |
624 So(qi.err.Error(), ShouldContainSubstring, "kind
is required for all orders") | 575 So(qi.err.Error(), ShouldContainSubstring, "kind
is required for all orders") |
625 }) | 576 }) |
626 }) | 577 }) |
627 | 578 |
628 }) | 579 }) |
629 } | 580 } |
OLD | NEW |