OLD | NEW |
1 // Copyright 2016 The LUCI Authors. All rights reserved. | 1 // Copyright 2016 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 package cloud | 5 package cloud |
6 | 6 |
7 import ( | 7 import ( |
8 "crypto/rand" | 8 "crypto/rand" |
9 "encoding/hex" | 9 "encoding/hex" |
10 "fmt" | 10 "fmt" |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 | 75 |
76 testTime := ds.RoundTime(time.Date(2016, 1, 1, 0, 0, 0, 0, time.
UTC)) | 76 testTime := ds.RoundTime(time.Date(2016, 1, 1, 0, 0, 0, 0, time.
UTC)) |
77 | 77 |
78 c = Use(c, client) | 78 c = Use(c, client) |
79 | 79 |
80 Convey(`Supports namespaces`, func() { | 80 Convey(`Supports namespaces`, func() { |
81 namespaces := []string{"foo", "bar", "baz"} | 81 namespaces := []string{"foo", "bar", "baz"} |
82 | 82 |
83 // Clear all used entities from all namespaces. | 83 // Clear all used entities from all namespaces. |
84 for _, ns := range namespaces { | 84 for _, ns := range namespaces { |
85 » » » » nsCtx := info.Get(c).MustNamespace(ns) | 85 » » » » nsCtx := info.MustNamespace(c, ns) |
86 » » » » di := ds.Get(nsCtx) | |
87 | 86 |
88 keys := make([]*ds.Key, len(namespaces)) | 87 keys := make([]*ds.Key, len(namespaces)) |
89 for i := range keys { | 88 for i := range keys { |
90 » » » » » keys[i] = di.MakeKey("Test", i+1) | 89 » » » » » keys[i] = ds.MakeKey(nsCtx, "Test", i+1) |
91 } | 90 } |
92 » » » » So(errors.Filter(di.DeleteMulti(keys), ds.ErrNoS
uchEntity), ShouldBeNil) | 91 » » » » So(errors.Filter(ds.Delete(nsCtx, keys), ds.ErrN
oSuchEntity), ShouldBeNil) |
93 } | 92 } |
94 | 93 |
95 // Put one entity per namespace. | 94 // Put one entity per namespace. |
96 for i, ns := range namespaces { | 95 for i, ns := range namespaces { |
97 » » » » nsCtx := info.Get(c).MustNamespace(ns) | 96 » » » » nsCtx := info.MustNamespace(c, ns) |
98 | 97 |
99 pmap := ds.PropertyMap{"$kind": mkp("Test"), "$i
d": mkp(i + 1), "Value": mkp(i)} | 98 pmap := ds.PropertyMap{"$kind": mkp("Test"), "$i
d": mkp(i + 1), "Value": mkp(i)} |
100 » » » » So(ds.Get(nsCtx).Put(pmap), ShouldBeNil) | 99 » » » » So(ds.Put(nsCtx, pmap), ShouldBeNil) |
101 } | 100 } |
102 | 101 |
103 // Make sure that entity only exists in that namespace. | 102 // Make sure that entity only exists in that namespace. |
104 for _, ns := range namespaces { | 103 for _, ns := range namespaces { |
105 » » » » nsCtx := info.Get(c).MustNamespace(ns) | 104 » » » » nsCtx := info.MustNamespace(c, ns) |
106 | 105 |
107 for i := range namespaces { | 106 for i := range namespaces { |
108 pmap := ds.PropertyMap{"$kind": mkp("Tes
t"), "$id": mkp(i + 1)} | 107 pmap := ds.PropertyMap{"$kind": mkp("Tes
t"), "$id": mkp(i + 1)} |
109 » » » » » err := ds.Get(nsCtx).Get(pmap) | 108 » » » » » err := ds.Get(nsCtx, pmap) |
110 | 109 |
111 if namespaces[i] == ns { | 110 if namespaces[i] == ns { |
112 So(err, ShouldBeNil) | 111 So(err, ShouldBeNil) |
113 } else { | 112 } else { |
114 So(err, ShouldEqual, ds.ErrNoSuc
hEntity) | 113 So(err, ShouldEqual, ds.ErrNoSuc
hEntity) |
115 } | 114 } |
116 } | 115 } |
117 } | 116 } |
118 }) | 117 }) |
119 | 118 |
120 Convey(`In a clean random testing namespace`, func() { | 119 Convey(`In a clean random testing namespace`, func() { |
121 // Enter a namespace for this round of tests. | 120 // Enter a namespace for this round of tests. |
122 randNamespace := make([]byte, 32) | 121 randNamespace := make([]byte, 32) |
123 if _, err := rand.Read(randNamespace); err != nil { | 122 if _, err := rand.Read(randNamespace); err != nil { |
124 panic(err) | 123 panic(err) |
125 } | 124 } |
126 » » » c = info.Get(c).MustNamespace(fmt.Sprintf("testing-%s",
hex.EncodeToString(randNamespace))) | 125 » » » c = info.MustNamespace(c, fmt.Sprintf("testing-%s", hex.
EncodeToString(randNamespace))) |
127 » » » di := ds.Get(c) | |
128 | 126 |
129 // Execute a kindless query to clear the namespace. | 127 // Execute a kindless query to clear the namespace. |
130 q := ds.NewQuery("").KeysOnly(true) | 128 q := ds.NewQuery("").KeysOnly(true) |
131 var allKeys []*ds.Key | 129 var allKeys []*ds.Key |
132 » » » So(di.GetAll(q, &allKeys), ShouldBeNil) | 130 » » » So(ds.GetAll(c, q, &allKeys), ShouldBeNil) |
133 » » » So(di.DeleteMulti(allKeys), ShouldBeNil) | 131 » » » So(ds.Delete(c, allKeys), ShouldBeNil) |
134 | 132 |
135 Convey(`Can allocate an ID range`, func() { | 133 Convey(`Can allocate an ID range`, func() { |
136 var keys []*ds.Key | 134 var keys []*ds.Key |
137 » » » » keys = append(keys, di.NewIncompleteKeys(10, "Ba
r", di.MakeKey("Foo", 12))...) | 135 » » » » keys = append(keys, ds.NewIncompleteKeys(c, 10,
"Bar", ds.MakeKey(c, "Foo", 12))...) |
138 » » » » keys = append(keys, di.NewIncompleteKeys(10, "Ba
z", di.MakeKey("Foo", 12))...) | 136 » » » » keys = append(keys, ds.NewIncompleteKeys(c, 10,
"Baz", ds.MakeKey(c, "Foo", 12))...) |
139 | 137 |
140 seen := map[string]struct{}{} | 138 seen := map[string]struct{}{} |
141 » » » » So(di.AllocateIDs(keys), ShouldBeNil) | 139 » » » » So(ds.AllocateIDs(c, keys), ShouldBeNil) |
142 for _, k := range keys { | 140 for _, k := range keys { |
143 So(k.IsIncomplete(), ShouldBeFalse) | 141 So(k.IsIncomplete(), ShouldBeFalse) |
144 seen[k.String()] = struct{}{} | 142 seen[k.String()] = struct{}{} |
145 } | 143 } |
146 | 144 |
147 » » » » So(di.AllocateIDs(keys), ShouldBeNil) | 145 » » » » So(ds.AllocateIDs(c, keys), ShouldBeNil) |
148 for _, k := range keys { | 146 for _, k := range keys { |
149 So(k.IsIncomplete(), ShouldBeFalse) | 147 So(k.IsIncomplete(), ShouldBeFalse) |
150 | 148 |
151 _, ok := seen[k.String()] | 149 _, ok := seen[k.String()] |
152 So(ok, ShouldBeFalse) | 150 So(ok, ShouldBeFalse) |
153 } | 151 } |
154 }) | 152 }) |
155 | 153 |
156 Convey(`Can get, put, and delete entities`, func() { | 154 Convey(`Can get, put, and delete entities`, func() { |
157 // Put: "foo", "bar", "baz". | 155 // Put: "foo", "bar", "baz". |
158 put := []ds.PropertyMap{ | 156 put := []ds.PropertyMap{ |
159 {"$kind": mkp("test"), "$id": mkp("foo")
, "Value": mkp(1337)}, | 157 {"$kind": mkp("test"), "$id": mkp("foo")
, "Value": mkp(1337)}, |
160 {"$kind": mkp("test"), "$id": mkp("bar")
, "Value": mkp(42)}, | 158 {"$kind": mkp("test"), "$id": mkp("bar")
, "Value": mkp(42)}, |
161 {"$kind": mkp("test"), "$id": mkp("baz")
, "Value": mkp(0xd065)}, | 159 {"$kind": mkp("test"), "$id": mkp("baz")
, "Value": mkp(0xd065)}, |
162 } | 160 } |
163 » » » » So(di.PutMulti(put), ShouldBeNil) | 161 » » » » So(ds.Put(c, put), ShouldBeNil) |
164 delete(put[0], "$key") | 162 delete(put[0], "$key") |
165 delete(put[1], "$key") | 163 delete(put[1], "$key") |
166 delete(put[2], "$key") | 164 delete(put[2], "$key") |
167 | 165 |
168 // Delete: "bar". | 166 // Delete: "bar". |
169 » » » » So(di.Delete(di.MakeKey("test", "bar")), ShouldB
eNil) | 167 » » » » So(ds.Delete(c, ds.MakeKey(c, "test", "bar")), S
houldBeNil) |
170 | 168 |
171 // Get: "foo", "bar", "baz" | 169 // Get: "foo", "bar", "baz" |
172 get := []ds.PropertyMap{ | 170 get := []ds.PropertyMap{ |
173 {"$kind": mkp("test"), "$id": mkp("foo")
}, | 171 {"$kind": mkp("test"), "$id": mkp("foo")
}, |
174 {"$kind": mkp("test"), "$id": mkp("bar")
}, | 172 {"$kind": mkp("test"), "$id": mkp("bar")
}, |
175 {"$kind": mkp("test"), "$id": mkp("baz")
}, | 173 {"$kind": mkp("test"), "$id": mkp("baz")
}, |
176 } | 174 } |
177 | 175 |
178 » » » » err := di.GetMulti(get) | 176 » » » » err := ds.Get(c, get) |
179 So(err, ShouldHaveSameTypeAs, errors.MultiError(
nil)) | 177 So(err, ShouldHaveSameTypeAs, errors.MultiError(
nil)) |
180 | 178 |
181 merr := err.(errors.MultiError) | 179 merr := err.(errors.MultiError) |
182 So(len(merr), ShouldEqual, 3) | 180 So(len(merr), ShouldEqual, 3) |
183 So(merr[0], ShouldBeNil) | 181 So(merr[0], ShouldBeNil) |
184 So(merr[1], ShouldEqual, ds.ErrNoSuchEntity) | 182 So(merr[1], ShouldEqual, ds.ErrNoSuchEntity) |
185 So(merr[2], ShouldBeNil) | 183 So(merr[2], ShouldBeNil) |
186 | 184 |
187 // put[1] will not be retrieved (delete) | 185 // put[1] will not be retrieved (delete) |
188 put[1] = get[1] | 186 put[1] = get[1] |
189 So(get, ShouldResemble, put) | 187 So(get, ShouldResemble, put) |
190 }) | 188 }) |
191 | 189 |
192 Convey(`Can put and get all supported entity fields.`, f
unc() { | 190 Convey(`Can put and get all supported entity fields.`, f
unc() { |
193 put := ds.PropertyMap{ | 191 put := ds.PropertyMap{ |
194 "$id": mkpNI("foo"), | 192 "$id": mkpNI("foo"), |
195 "$kind": mkpNI("FooType"), | 193 "$kind": mkpNI("FooType"), |
196 "Number": mkp(1337), | 194 "Number": mkp(1337), |
197 "String": mkpNI("hello"), | 195 "String": mkpNI("hello"), |
198 "Bytes": mkp([]byte("world")), | 196 "Bytes": mkp([]byte("world")), |
199 "Time": mkp(testTime), | 197 "Time": mkp(testTime), |
200 "Float": mkpNI(3.14), | 198 "Float": mkpNI(3.14), |
201 » » » » » "Key": mkp(di.MakeKey("Parent", "Pare
ntID", "Child", 1337)), | 199 » » » » » "Key": mkp(ds.MakeKey(c, "Parent", "P
arentID", "Child", 1337)), |
202 | 200 |
203 "ComplexSlice": mkp(1337, "string", []by
te("bytes"), testTime, float32(3.14), | 201 "ComplexSlice": mkp(1337, "string", []by
te("bytes"), testTime, float32(3.14), |
204 » » » » » » float64(2.71), true, di.MakeKey(
"SomeKey", "SomeID")), | 202 » » » » » » float64(2.71), true, ds.MakeKey(
c, "SomeKey", "SomeID")), |
205 } | 203 } |
206 » » » » So(di.Put(put), ShouldBeNil) | 204 » » » » So(ds.Put(c, put), ShouldBeNil) |
207 delete(put, "$key") | 205 delete(put, "$key") |
208 | 206 |
209 get := ds.PropertyMap{ | 207 get := ds.PropertyMap{ |
210 "$id": mkpNI("foo"), | 208 "$id": mkpNI("foo"), |
211 "$kind": mkpNI("FooType"), | 209 "$kind": mkpNI("FooType"), |
212 } | 210 } |
213 » » » » So(di.Get(get), ShouldBeNil) | 211 » » » » So(ds.Get(c, get), ShouldBeNil) |
214 So(get, ShouldResemble, put) | 212 So(get, ShouldResemble, put) |
215 }) | 213 }) |
216 | 214 |
217 Convey(`With several entities installed`, func() { | 215 Convey(`With several entities installed`, func() { |
218 » » » » So(di.PutMulti([]ds.PropertyMap{ | 216 » » » » So(ds.Put(c, []ds.PropertyMap{ |
219 {"$kind": mkp("Test"), "$id": mkp("foo")
, "FooBar": mkp(true)}, | 217 {"$kind": mkp("Test"), "$id": mkp("foo")
, "FooBar": mkp(true)}, |
220 {"$kind": mkp("Test"), "$id": mkp("bar")
, "FooBar": mkp(true)}, | 218 {"$kind": mkp("Test"), "$id": mkp("bar")
, "FooBar": mkp(true)}, |
221 {"$kind": mkp("Test"), "$id": mkp("baz")
}, | 219 {"$kind": mkp("Test"), "$id": mkp("baz")
}, |
222 {"$kind": mkp("Test"), "$id": mkp("qux")
}, | 220 {"$kind": mkp("Test"), "$id": mkp("qux")
}, |
223 }), ShouldBeNil) | 221 }), ShouldBeNil) |
224 | 222 |
225 q := ds.NewQuery("Test") | 223 q := ds.NewQuery("Test") |
226 | 224 |
227 Convey(`Can query for entities with FooBar == tr
ue.`, func() { | 225 Convey(`Can query for entities with FooBar == tr
ue.`, func() { |
228 var results []ds.PropertyMap | 226 var results []ds.PropertyMap |
229 q = q.Eq("FooBar", true) | 227 q = q.Eq("FooBar", true) |
230 » » » » » So(di.GetAll(q, &results), ShouldBeNil) | 228 » » » » » So(ds.GetAll(c, q, &results), ShouldBeNi
l) |
231 | 229 |
232 So(results, ShouldResemble, []ds.Propert
yMap{ | 230 So(results, ShouldResemble, []ds.Propert
yMap{ |
233 » » » » » » {"$key": mkpNI(di.MakeKey("Test"
, "bar")), "FooBar": mkp(true)}, | 231 » » » » » » {"$key": mkpNI(ds.MakeKey(c, "Te
st", "bar")), "FooBar": mkp(true)}, |
234 » » » » » » {"$key": mkpNI(di.MakeKey("Test"
, "foo")), "FooBar": mkp(true)}, | 232 » » » » » » {"$key": mkpNI(ds.MakeKey(c, "Te
st", "foo")), "FooBar": mkp(true)}, |
235 }) | 233 }) |
236 }) | 234 }) |
237 | 235 |
238 Convey(`Can query for entities whose __key__ > "
baz".`, func() { | 236 Convey(`Can query for entities whose __key__ > "
baz".`, func() { |
239 var results []ds.PropertyMap | 237 var results []ds.PropertyMap |
240 » » » » » q = q.Gt("__key__", di.MakeKey("Test", "
baz")) | 238 » » » » » q = q.Gt("__key__", ds.MakeKey(c, "Test"
, "baz")) |
241 » » » » » So(di.GetAll(q, &results), ShouldBeNil) | 239 » » » » » So(ds.GetAll(c, q, &results), ShouldBeNi
l) |
242 | 240 |
243 So(results, ShouldResemble, []ds.Propert
yMap{ | 241 So(results, ShouldResemble, []ds.Propert
yMap{ |
244 » » » » » » {"$key": mkpNI(di.MakeKey("Test"
, "foo")), "FooBar": mkp(true)}, | 242 » » » » » » {"$key": mkpNI(ds.MakeKey(c, "Te
st", "foo")), "FooBar": mkp(true)}, |
245 » » » » » » {"$key": mkpNI(di.MakeKey("Test"
, "qux"))}, | 243 » » » » » » {"$key": mkpNI(ds.MakeKey(c, "Te
st", "qux"))}, |
246 }) | 244 }) |
247 }) | 245 }) |
248 | 246 |
249 Convey(`Can transactionally get and put.`, func(
) { | 247 Convey(`Can transactionally get and put.`, func(
) { |
250 » » » » » err := di.RunInTransaction(func(c contex
t.Context) error { | 248 » » » » » err := ds.RunInTransaction(c, func(c con
text.Context) error { |
251 » » » » » » di := ds.Get(c) | |
252 | |
253 pmap := ds.PropertyMap{"$kind":
mkp("Test"), "$id": mkp("qux")} | 249 pmap := ds.PropertyMap{"$kind":
mkp("Test"), "$id": mkp("qux")} |
254 » » » » » » if err := di.Get(pmap); err != n
il { | 250 » » » » » » if err := ds.Get(c, pmap); err !
= nil { |
255 return err | 251 return err |
256 } | 252 } |
257 | 253 |
258 pmap["ExtraField"] = mkp("Presen
t!") | 254 pmap["ExtraField"] = mkp("Presen
t!") |
259 » » » » » » return di.Put(pmap) | 255 » » » » » » return ds.Put(c, pmap) |
260 }, nil) | 256 }, nil) |
261 So(err, ShouldBeNil) | 257 So(err, ShouldBeNil) |
262 | 258 |
263 pmap := ds.PropertyMap{"$kind": mkp("Tes
t"), "$id": mkp("qux")} | 259 pmap := ds.PropertyMap{"$kind": mkp("Tes
t"), "$id": mkp("qux")} |
264 » » » » » err = di.RunInTransaction(func(c context
.Context) error { | 260 » » » » » err = ds.RunInTransaction(c, func(c cont
ext.Context) error { |
265 » » » » » » return ds.Get(c).Get(pmap) | 261 » » » » » » return ds.Get(c, pmap) |
266 }, nil) | 262 }, nil) |
267 So(err, ShouldBeNil) | 263 So(err, ShouldBeNil) |
268 So(pmap, ShouldResemble, ds.PropertyMap{
"$kind": mkp("Test"), "$id": mkp("qux"), "ExtraField": mkp("Present!")}) | 264 So(pmap, ShouldResemble, ds.PropertyMap{
"$kind": mkp("Test"), "$id": mkp("qux"), "ExtraField": mkp("Present!")}) |
269 }) | 265 }) |
270 | 266 |
271 Convey(`Can fail in a transaction with no effect
.`, func() { | 267 Convey(`Can fail in a transaction with no effect
.`, func() { |
272 testError := errors.New("test error") | 268 testError := errors.New("test error") |
273 | 269 |
274 » » » » » err := di.RunInTransaction(func(c contex
t.Context) error { | 270 » » » » » noTxnPM := ds.PropertyMap{"$kind": mkp("
Test"), "$id": mkp("no txn")} |
275 » » » » » » di := ds.Get(c) | 271 » » » » » err := ds.RunInTransaction(c, func(c con
text.Context) error { |
| 272 » » » » » » So(ds.CurrentTransaction(c), Sho
uldNotBeNil) |
276 | 273 |
277 pmap := ds.PropertyMap{"$kind":
mkp("Test"), "$id": mkp("quux")} | 274 pmap := ds.PropertyMap{"$kind":
mkp("Test"), "$id": mkp("quux")} |
278 » » » » » » if err := di.Put(pmap); err != n
il { | 275 » » » » » » if err := ds.Put(c, pmap); err !
= nil { |
| 276 » » » » » » » return err |
| 277 » » » » » » } |
| 278 |
| 279 » » » » » » // Put an entity outside of the
transaction so we can confirm that |
| 280 » » » » » » // it was added even when the tr
ansaction fails. |
| 281 » » » » » » if err := ds.Put(ds.WithTransact
ion(c, nil), noTxnPM); err != nil { |
279 return err | 282 return err |
280 } | 283 } |
281 return testError | 284 return testError |
282 }, nil) | 285 }, nil) |
283 So(err, ShouldEqual, testError) | 286 So(err, ShouldEqual, testError) |
284 | 287 |
| 288 // Confirm that noTxnPM was added. |
| 289 So(ds.CurrentTransaction(c), ShouldBeNil
) |
| 290 So(ds.Get(c, noTxnPM), ShouldBeNil) |
| 291 |
285 pmap := ds.PropertyMap{"$kind": mkp("Tes
t"), "$id": mkp("quux")} | 292 pmap := ds.PropertyMap{"$kind": mkp("Tes
t"), "$id": mkp("quux")} |
286 » » » » » err = di.RunInTransaction(func(c context
.Context) error { | 293 » » » » » err = ds.RunInTransaction(c, func(c cont
ext.Context) error { |
287 » » » » » » return ds.Get(c).Get(pmap) | 294 » » » » » » return ds.Get(c, pmap) |
288 }, nil) | 295 }, nil) |
289 So(err, ShouldEqual, ds.ErrNoSuchEntity) | 296 So(err, ShouldEqual, ds.ErrNoSuchEntity) |
290 }) | 297 }) |
291 }) | 298 }) |
292 }) | 299 }) |
293 }) | 300 }) |
294 } | 301 } |
OLD | NEW |