OLD | NEW |
1 // Copyright 2015 The LUCI Authors. All rights reserved. | 1 // Copyright 2015 The LUCI Authors. All rights reserved. |
2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
4 | 4 |
5 // +build appengine | 5 // +build appengine |
6 | 6 |
7 package prod | 7 package prod |
8 | 8 |
9 import ( | 9 import ( |
10 "testing" | 10 "testing" |
(...skipping 10 matching lines...) Expand all Loading... |
21 ) | 21 ) |
22 | 22 |
23 var ( | 23 var ( |
24 mp = datastore.MkProperty | 24 mp = datastore.MkProperty |
25 mpNI = datastore.MkPropertyNI | 25 mpNI = datastore.MkPropertyNI |
26 ) | 26 ) |
27 | 27 |
28 type TestStruct struct { | 28 type TestStruct struct { |
29 ID int64 `gae:"$id"` | 29 ID int64 `gae:"$id"` |
30 | 30 |
31 » ValueI []int64 | 31 » ValueI []int64 |
32 » ValueB []bool | 32 » ValueB []bool |
33 » ValueS []string | 33 » ValueS []string |
34 » ValueF []float64 | 34 » ValueF []float64 |
35 » ValueBS [][]byte // "ByteString" | 35 » ValueBS [][]byte // "ByteString" |
36 » ValueK []*datastore.Key | 36 » ValueK []*datastore.Key |
37 » ValueBK []blobstore.Key | 37 » ValueBK []blobstore.Key |
38 » ValueGP []datastore.GeoPoint | 38 » ValueGP []datastore.GeoPoint |
| 39 » ValueSingle string |
| 40 » ValueSingleSlice []string |
39 } | 41 } |
40 | 42 |
41 func TestBasicDatastore(t *testing.T) { | 43 func TestBasicDatastore(t *testing.T) { |
42 t.Parallel() | 44 t.Parallel() |
43 | 45 |
44 Convey("basic", t, func() { | 46 Convey("basic", t, func() { |
45 inst, err := aetest.NewInstance(&aetest.Options{ | 47 inst, err := aetest.NewInstance(&aetest.Options{ |
46 StronglyConsistentDatastore: true, | 48 StronglyConsistentDatastore: true, |
47 }) | 49 }) |
48 So(err, ShouldBeNil) | 50 So(err, ShouldBeNil) |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 ValueK: []*datastore.Key{ | 124 ValueK: []*datastore.Key{ |
123 ds.NewKey("Something", "Cool", 0, nil), | 125 ds.NewKey("Something", "Cool", 0, nil), |
124 ds.NewKey("Something", "", 1, nil), | 126 ds.NewKey("Something", "", 1, nil), |
125 ds.NewKey("Something", "Recursive", 0, | 127 ds.NewKey("Something", "Recursive", 0, |
126 ds.NewKey("Parent", "", 2, nil))
, | 128 ds.NewKey("Parent", "", 2, nil))
, |
127 }, | 129 }, |
128 ValueBK: []blobstore.Key{"bellow", "hello"}, | 130 ValueBK: []blobstore.Key{"bellow", "hello"}, |
129 ValueGP: []datastore.GeoPoint{ | 131 ValueGP: []datastore.GeoPoint{ |
130 {Lat: 120.7, Lng: 95.5}, | 132 {Lat: 120.7, Lng: 95.5}, |
131 }, | 133 }, |
| 134 ValueSingle: "ohai", |
| 135 ValueSingleSlice: []string{"kthxbye"}, |
132 } | 136 } |
133 So(ds.Put(&orig), ShouldBeNil) | 137 So(ds.Put(&orig), ShouldBeNil) |
134 | 138 |
135 ret := TestStruct{ID: orig.ID} | 139 ret := TestStruct{ID: orig.ID} |
136 So(ds.Get(&ret), ShouldBeNil) | 140 So(ds.Get(&ret), ShouldBeNil) |
137 So(ret, ShouldResemble, orig) | 141 So(ret, ShouldResemble, orig) |
138 | 142 |
| 143 // make sure single- and multi- properties are preserved
. |
| 144 pmap := datastore.PropertyMap{ |
| 145 "$id": mpNI(orig.ID), |
| 146 "$kind": mpNI("TestStruct"), |
| 147 } |
| 148 So(ds.Get(pmap), ShouldBeNil) |
| 149 So(pmap["ValueSingle"], ShouldHaveSameTypeAs, datastore.
Property{}) |
| 150 So(pmap["ValueSingleSlice"], ShouldHaveSameTypeAs, datas
tore.PropertySlice(nil)) |
| 151 |
139 // can't be sure the indexes have caught up... so sleep | 152 // can't be sure the indexes have caught up... so sleep |
140 time.Sleep(time.Second) | 153 time.Sleep(time.Second) |
141 | 154 |
142 Convey("Can query", func() { | 155 Convey("Can query", func() { |
143 q := datastore.NewQuery("TestStruct") | 156 q := datastore.NewQuery("TestStruct") |
144 ds.Run(q, func(ts *TestStruct) { | 157 ds.Run(q, func(ts *TestStruct) { |
145 So(*ts, ShouldResemble, orig) | 158 So(*ts, ShouldResemble, orig) |
146 }) | 159 }) |
147 count, err := ds.Count(q) | 160 count, err := ds.Count(q) |
148 So(err, ShouldBeNil) | 161 So(err, ShouldBeNil) |
149 So(count, ShouldEqual, 1) | 162 So(count, ShouldEqual, 1) |
150 }) | 163 }) |
151 | 164 |
152 Convey("Can project", func() { | 165 Convey("Can project", func() { |
153 q := datastore.NewQuery("TestStruct").Project("V
alueS") | 166 q := datastore.NewQuery("TestStruct").Project("V
alueS") |
154 rslts := []datastore.PropertyMap{} | 167 rslts := []datastore.PropertyMap{} |
155 So(ds.GetAll(q, &rslts), ShouldBeNil) | 168 So(ds.GetAll(q, &rslts), ShouldBeNil) |
156 So(rslts, ShouldResemble, []datastore.PropertyMa
p{ | 169 So(rslts, ShouldResemble, []datastore.PropertyMa
p{ |
157 { | 170 { |
158 » » » » » » "$key": {mpNI(ds.KeyForObj(&or
ig))}, | 171 » » » » » » "$key": mpNI(ds.KeyForObj(&ori
g)), |
159 » » » » » » "ValueS": {mp("hello")}, | 172 » » » » » » "ValueS": mp("hello"), |
160 }, | 173 }, |
161 { | 174 { |
162 » » » » » » "$key": {mpNI(ds.KeyForObj(&or
ig))}, | 175 » » » » » » "$key": mpNI(ds.KeyForObj(&ori
g)), |
163 » » » » » » "ValueS": {mp("world")}, | 176 » » » » » » "ValueS": mp("world"), |
164 }, | 177 }, |
165 }) | 178 }) |
166 | 179 |
167 q = datastore.NewQuery("TestStruct").Project("Va
lueBS") | 180 q = datastore.NewQuery("TestStruct").Project("Va
lueBS") |
168 rslts = []datastore.PropertyMap{} | 181 rslts = []datastore.PropertyMap{} |
169 So(ds.GetAll(q, &rslts), ShouldBeNil) | 182 So(ds.GetAll(q, &rslts), ShouldBeNil) |
170 So(rslts, ShouldResemble, []datastore.PropertyMa
p{ | 183 So(rslts, ShouldResemble, []datastore.PropertyMa
p{ |
171 { | 184 { |
172 » » » » » » "$key": {mpNI(ds.KeyForObj(&o
rig))}, | 185 » » » » » » "$key": mpNI(ds.KeyForObj(&or
ig)), |
173 » » » » » » "ValueBS": {mp("allo")}, | 186 » » » » » » "ValueBS": mp("allo"), |
174 }, | 187 }, |
175 { | 188 { |
176 » » » » » » "$key": {mpNI(ds.KeyForObj(&o
rig))}, | 189 » » » » » » "$key": mpNI(ds.KeyForObj(&or
ig)), |
177 » » » » » » "ValueBS": {mp("hello")}, | 190 » » » » » » "ValueBS": mp("hello"), |
178 }, | 191 }, |
179 { | 192 { |
180 » » » » » » "$key": {mpNI(ds.KeyForObj(&o
rig))}, | 193 » » » » » » "$key": mpNI(ds.KeyForObj(&or
ig)), |
181 » » » » » » "ValueBS": {mp("world")}, | 194 » » » » » » "ValueBS": mp("world"), |
182 }, | 195 }, |
183 { | 196 { |
184 » » » » » » "$key": {mpNI(ds.KeyForObj(&o
rig))}, | 197 » » » » » » "$key": mpNI(ds.KeyForObj(&or
ig)), |
185 » » » » » » "ValueBS": {mp("zurple")}, | 198 » » » » » » "ValueBS": mp("zurple"), |
186 }, | 199 }, |
187 }) | 200 }) |
188 | 201 |
189 count, err := ds.Count(q) | 202 count, err := ds.Count(q) |
190 So(err, ShouldBeNil) | 203 So(err, ShouldBeNil) |
191 So(count, ShouldEqual, 4) | 204 So(count, ShouldEqual, 4) |
192 | 205 |
193 q = datastore.NewQuery("TestStruct").Lte("ValueI
", 7).Project("ValueS").Distinct(true) | 206 q = datastore.NewQuery("TestStruct").Lte("ValueI
", 7).Project("ValueS").Distinct(true) |
194 rslts = []datastore.PropertyMap{} | 207 rslts = []datastore.PropertyMap{} |
195 So(ds.GetAll(q, &rslts), ShouldBeNil) | 208 So(ds.GetAll(q, &rslts), ShouldBeNil) |
196 So(rslts, ShouldResemble, []datastore.PropertyMa
p{ | 209 So(rslts, ShouldResemble, []datastore.PropertyMa
p{ |
197 { | 210 { |
198 » » » » » » "$key": {mpNI(ds.KeyForObj(&or
ig))}, | 211 » » » » » » "$key": mpNI(ds.KeyForObj(&ori
g)), |
199 » » » » » » "ValueI": {mp(1)}, | 212 » » » » » » "ValueI": mp(1), |
200 » » » » » » "ValueS": {mp("hello")}, | 213 » » » » » » "ValueS": mp("hello"), |
201 }, | 214 }, |
202 { | 215 { |
203 » » » » » » "$key": {mpNI(ds.KeyForObj(&or
ig))}, | 216 » » » » » » "$key": mpNI(ds.KeyForObj(&ori
g)), |
204 » » » » » » "ValueI": {mp(1)}, | 217 » » » » » » "ValueI": mp(1), |
205 » » » » » » "ValueS": {mp("world")}, | 218 » » » » » » "ValueS": mp("world"), |
206 }, | 219 }, |
207 { | 220 { |
208 » » » » » » "$key": {mpNI(ds.KeyForObj(&or
ig))}, | 221 » » » » » » "$key": mpNI(ds.KeyForObj(&ori
g)), |
209 » » » » » » "ValueI": {mp(7)}, | 222 » » » » » » "ValueI": mp(7), |
210 » » » » » » "ValueS": {mp("hello")}, | 223 » » » » » » "ValueS": mp("hello"), |
211 }, | 224 }, |
212 { | 225 { |
213 » » » » » » "$key": {mpNI(ds.KeyForObj(&or
ig))}, | 226 » » » » » » "$key": mpNI(ds.KeyForObj(&ori
g)), |
214 » » » » » » "ValueI": {mp(7)}, | 227 » » » » » » "ValueI": mp(7), |
215 » » » » » » "ValueS": {mp("world")}, | 228 » » » » » » "ValueS": mp("world"), |
216 }, | 229 }, |
217 }) | 230 }) |
218 | 231 |
219 count, err = ds.Count(q) | 232 count, err = ds.Count(q) |
220 So(err, ShouldBeNil) | 233 So(err, ShouldBeNil) |
221 So(count, ShouldEqual, 4) | 234 So(count, ShouldEqual, 4) |
222 }) | 235 }) |
223 }) | 236 }) |
224 | 237 |
225 Convey("Can Put/Get (time)", func() { | 238 Convey("Can Put/Get (time)", func() { |
226 // time comparisons in Go are wonky, so this is pulled o
ut | 239 // time comparisons in Go are wonky, so this is pulled o
ut |
227 pm := datastore.PropertyMap{ | 240 pm := datastore.PropertyMap{ |
228 » » » » "$key": {mpNI(ds.NewKey("Something", "value", 0,
nil))}, | 241 » » » » "$key": mpNI(ds.NewKey("Something", "value", 0,
nil)), |
229 » » » » "Time": { | 242 » » » » "Time": datastore.PropertySlice{ |
230 mp(time.Date(1938, time.January, 1, 1, 1
, 1, 1, time.UTC)), | 243 mp(time.Date(1938, time.January, 1, 1, 1
, 1, 1, time.UTC)), |
231 mp(time.Time{}), | 244 mp(time.Time{}), |
232 }, | 245 }, |
233 } | 246 } |
234 So(ds.Put(&pm), ShouldBeNil) | 247 So(ds.Put(&pm), ShouldBeNil) |
235 | 248 |
236 rslt := datastore.PropertyMap{} | 249 rslt := datastore.PropertyMap{} |
237 rslt.SetMeta("key", ds.KeyForObj(pm)) | 250 rslt.SetMeta("key", ds.KeyForObj(pm)) |
238 So(ds.Get(&rslt), ShouldBeNil) | 251 So(ds.Get(&rslt), ShouldBeNil) |
239 | 252 |
240 » » » So(pm["Time"][0].Value(), ShouldResemble, rslt["Time"][0
].Value()) | 253 » » » So(pm.Slice("Time")[0].Value(), ShouldResemble, rslt.Sli
ce("Time")[0].Value()) |
241 | 254 |
242 q := datastore.NewQuery("Something").Project("Time") | 255 q := datastore.NewQuery("Something").Project("Time") |
243 all := []datastore.PropertyMap{} | 256 all := []datastore.PropertyMap{} |
244 So(ds.GetAll(q, &all), ShouldBeNil) | 257 So(ds.GetAll(q, &all), ShouldBeNil) |
245 So(len(all), ShouldEqual, 2) | 258 So(len(all), ShouldEqual, 2) |
246 » » » prop := all[0]["Time"][0] | 259 » » » prop := all[0].Slice("Time")[0] |
247 So(prop.Type(), ShouldEqual, datastore.PTInt) | 260 So(prop.Type(), ShouldEqual, datastore.PTInt) |
248 | 261 |
249 tval, err := prop.Project(datastore.PTTime) | 262 tval, err := prop.Project(datastore.PTTime) |
250 So(err, ShouldBeNil) | 263 So(err, ShouldBeNil) |
251 So(tval, ShouldResemble, time.Time{}.UTC()) | 264 So(tval, ShouldResemble, time.Time{}.UTC()) |
252 | 265 |
253 » » » tval, err = all[1]["Time"][0].Project(datastore.PTTime) | 266 » » » tval, err = all[1].Slice("Time")[0].Project(datastore.PT
Time) |
254 So(err, ShouldBeNil) | 267 So(err, ShouldBeNil) |
255 » » » So(tval, ShouldResemble, pm["Time"][0].Value()) | 268 » » » So(tval, ShouldResemble, pm.Slice("Time")[0].Value()) |
256 | 269 |
257 ent := datastore.PropertyMap{ | 270 ent := datastore.PropertyMap{ |
258 » » » » "$key": {mpNI(ds.MakeKey("Something", "value"))}
, | 271 » » » » "$key": mpNI(ds.MakeKey("Something", "value")), |
259 } | 272 } |
260 So(ds.Get(&ent), ShouldBeNil) | 273 So(ds.Get(&ent), ShouldBeNil) |
261 So(ent["Time"], ShouldResemble, pm["Time"]) | 274 So(ent["Time"], ShouldResemble, pm["Time"]) |
262 }) | 275 }) |
263 | 276 |
264 Convey("memcache: Set (nil) is the same as Set ([]byte{})", func
() { | 277 Convey("memcache: Set (nil) is the same as Set ([]byte{})", func
() { |
265 So(mc.Set(mc.NewItem("bob")), ShouldBeNil) // normally w
ould panic because Value is nil | 278 So(mc.Set(mc.NewItem("bob")), ShouldBeNil) // normally w
ould panic because Value is nil |
266 | 279 |
267 bob, err := mc.Get("bob") | 280 bob, err := mc.Get("bob") |
268 So(err, ShouldBeNil) | 281 So(err, ShouldBeNil) |
269 So(bob.Value(), ShouldResemble, []byte{}) | 282 So(bob.Value(), ShouldResemble, []byte{}) |
270 }) | 283 }) |
271 }) | 284 }) |
272 } | 285 } |
OLD | NEW |