Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(194)

Side by Side Diff: go/src/infra/gae/libs/wrapper/memory/taskqueue_test.go

Issue 1152383003: Simple memory testing for gae/wrapper (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@better_context_lite
Patch Set: add go-slab dependency Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 package memory
6
7 import (
8 "fmt"
9 "infra/gae/libs/wrapper"
10 "math/rand"
11 "net/http"
12 "testing"
13 "time"
14
15 . "github.com/smartystreets/goconvey/convey"
16 "golang.org/x/net/context"
17
18 "appengine/taskqueue"
19 )
20
21 func TestTaskQueue(t *testing.T) {
22 t.Parallel()
23
24 Convey("TaskQueue", t, func() {
25 now := time.Date(2000, time.January, 1, 1, 1, 1, 1, time.UTC)
26 timeNow := func(context.Context) time.Time {
27 ret := now
28 now = now.Add(time.Second)
29 return ret
30 }
31 c := wrapper.SetTimeNowFactory(context.Background(), timeNow)
32 c = wrapper.SetMathRand(c, rand.New(rand.NewSource(wrapper.GetTi meNow(c).UnixNano())))
33 c = Use(Enable(c))
34
35 tq := wrapper.GetTQ(c).(interface {
36 wrapper.TQMultiReadWriter
37 wrapper.TQTestable
38 })
39
40 So(tq, ShouldNotBeNil)
41
42 Convey("implements TQMultiReadWriter", func() {
43 Convey("Add", func() {
44 t := &taskqueue.Task{Path: "/hello/world"}
45
46 Convey("works", func() {
47 curTime := now
48 t.Delay = 4 * time.Second
49 t.Header = http.Header{}
50 t.Header.Add("Cat", "tabby")
51 t.Payload = []byte("watwatwat")
52 t.RetryOptions = &taskqueue.RetryOptions {AgeLimit: 7 * time.Second}
53 _, err := tq.Add(t, "")
54 So(err, ShouldBeNil)
55 name := "Z_UjshxM9ecyMQfGbZmUGOEcgxWU0_5 CGLl_-RntudwAw2DqQ5-58bzJiWQN4OKzeuUb9O4JrPkUw2rOvk2Ax46THojnQ6avBQgZdrKcJmrwQ6o 4qKfJdiyUbGXvy691yRfzLeQhs6cBhWrgf3wH-VPMcA4SC-zlbJ2U8An7I0zJQA5nBFnMNoMgT-2peGo ay3rCSbj4z9VFFm9kS_i6JCaQH518ujLDSNCYdjTq6B6lcWrZAh0U_q3a1S2nXEwrKiw_t9MTNQFgAQZ WyGBbvZQPmeRYtu8SPaWzTfd25v_YWgBuVL2rRSPSMvlDwE04nNdtvVzE8vNNiA1zRimmdzKeqATQF9_ ReUvj4D7U8dcS703DZWfKMBLgBffY9jqCassOOOw77V72Oq5EVauUw3Qw0L6bBsfM9FtahTKUdabzRZj XUoze3EK4KXPt3-wdidau-8JrVf2XFocjjZbwHoxcGvbtT3b4nGLDlgwdC00bwaFBZWff"
56 So(*tq.GetScheduledTasks()["default"][na me], ShouldResemble, taskqueue.Task{
57 ETA: curTime.Add(4 * ti me.Second),
58 Header: http.Header{"Cat": []string{"tabby"}},
59 Method: "POST",
60 Name: name,
61 Path: "/hello/world",
62 Payload: []byte("watwatwat" ),
63 RetryOptions: &taskqueue.RetryOp tions{AgeLimit: 7 * time.Second},
64 })
65 })
66
67 Convey("cannot add to bad queues", func() {
68 _, err := tq.Add(nil, "waaat")
69 So(err.Error(), ShouldContainSubstring, "UNKNOWN_QUEUE")
70
71 Convey("but you can add Queues when test ing", func() {
72 tq.CreateQueue("waaat")
73 _, err := tq.Add(t, "waaat")
74 So(err, ShouldBeNil)
75
76 Convey("you just can't add them twice", func() {
77 So(func() { tq.CreateQue ue("waaat") }, ShouldPanic)
78 })
79 })
80 })
81
82 Convey("requires a URL", func() {
83 t.Path = ""
84 tr, err := tq.Add(t, "")
85 So(err.Error(), ShouldContainSubstring, "INVALID_URL")
86 So(tr, ShouldBeNil)
87 })
88
89 Convey("cannot add twice", func() {
90 t.Name = "bob"
91 _, err := tq.Add(t, "")
92 So(err, ShouldBeNil)
93
94 // can't add the same one twice!
95 _, err = tq.Add(t, "")
96 So(err, ShouldEqual, taskqueue.ErrTaskAl readyAdded)
97 })
98
99 Convey("cannot add deleted task", func() {
100 t.Name = "bob"
101 _, err := tq.Add(t, "")
102 So(err, ShouldBeNil)
103
104 err = tq.Delete(t, "")
105 So(err, ShouldBeNil)
106
107 // can't add a deleted task!
108 _, err = tq.Add(t, "")
109 So(err, ShouldEqual, taskqueue.ErrTaskAl readyAdded)
110 })
111
112 Convey("cannot set ETA+Delay", func() {
113 t.ETA = wrapper.GetTimeNow(c).Add(time.H our)
114 t.Delay = time.Hour
115 So(func() { tq.Add(t, "") }, ShouldPanic )
116 })
117
118 Convey("must use a reasonable method", func() {
119 t.Method = "Crystal"
120 _, err := tq.Add(t, "")
121 So(err.Error(), ShouldContainSubstring, "bad method")
122 })
123
124 Convey("payload gets dumped for non POST/PUT met hods", func() {
125 t.Method = "HEAD"
126 t.Payload = []byte("coool")
127 tq, err := tq.Add(t, "")
128 So(err, ShouldBeNil)
129 So(tq.Payload, ShouldBeNil)
130
131 // check that it didn't modify our origi nal
132 So(t.Payload, ShouldResemble, []byte("co ool"))
133 })
134
135 Convey("invalid names are rejected", func() {
136 t.Name = "happy times"
137 _, err := tq.Add(t, "")
138 So(err.Error(), ShouldContainSubstring, "INVALID_TASK_NAME")
139 })
140
141 Convey("can be broken", func() {
142 tq.BreakFeatures(nil, "Add")
143 _, err := tq.Add(t, "")
144 So(err.Error(), ShouldContainSubstring, "TRANSIENT_ERROR")
145 })
146
147 Convey("AddMulti also works", func() {
148 curTime := now
149
150 t2 := dupTask(t)
151 t2.Path = "/hi/city"
152
153 expect := []*taskqueue.Task{t, t2}
154
155 tasks, err := tq.AddMulti(expect, "defau lt")
156 So(err, ShouldBeNil)
157 So(len(tasks), ShouldEqual, 2)
158 So(len(tq.GetScheduledTasks()["default"] ), ShouldEqual, 2)
159
160 for i := range expect {
161 Convey(fmt.Sprintf("task %d: %s" , i, expect[i].Path), func() {
162 expect[i].Method = "POST "
163 expect[i].ETA = curTime. Add(time.Duration(i) * time.Second)
164 So(expect[i].Name, Shoul dEqual, "")
165 So(len(tasks[i].Name), S houldEqual, 500)
166 tasks[i].Name = ""
167 So(tasks[i], ShouldResem ble, expect[i])
168 })
169 }
170
171 Convey("can be broken", func() {
172 tq.BreakFeatures(nil, "AddMulti" )
173 _, err := tq.AddMulti([]*taskque ue.Task{t}, "")
174 So(err.Error(), ShouldContainSub string, "TRANSIENT_ERROR")
175 })
176
177 Convey("is not broken by Add", func() {
178 tq.BreakFeatures(nil, "Add")
179 _, err := tq.AddMulti([]*taskque ue.Task{t}, "")
180 So(err, ShouldBeNil)
181 })
182 })
183 })
184
185 Convey("Delete", func() {
186 t := &taskqueue.Task{Path: "/hello/world"}
187 tEnQ, err := tq.Add(t, "")
188 So(err, ShouldBeNil)
189
190 Convey("works", func() {
191 t.Name = tEnQ.Name
192 err := tq.Delete(t, "")
193 So(err, ShouldBeNil)
194 So(len(tq.GetScheduledTasks()["default"] ), ShouldEqual, 0)
195 So(len(tq.GetTombstonedTasks()["default" ]), ShouldEqual, 1)
196 So(tq.GetTombstonedTasks()["default"][tE nQ.Name], ShouldResemble, tEnQ)
197 })
198
199 Convey("cannot delete a task twice", func() {
200 err := tq.Delete(tEnQ, "")
201 So(err, ShouldBeNil)
202
203 err = tq.Delete(tEnQ, "")
204 So(err.Error(), ShouldContainSubstring, "TOMBSTONED_TASK")
205
206 Convey("but you can if you do a reset", func() {
207 tq.ResetTasks()
208
209 tEnQ, err := tq.Add(t, "")
210 So(err, ShouldBeNil)
211 err = tq.Delete(tEnQ, "")
212 So(err, ShouldBeNil)
213 })
214 })
215
216 Convey("cannot delete from bogus queues", func() {
217 err := tq.Delete(t, "wat")
218 So(err.Error(), ShouldContainSubstring, "UNKNOWN_QUEUE")
219 })
220
221 Convey("cannot delete a missing task", func() {
222 t.Name = "tarntioarenstyw"
223 err := tq.Delete(t, "")
224 So(err.Error(), ShouldContainSubstring, "UNKNOWN_TASK")
225 })
226
227 Convey("can be broken", func() {
228 tq.BreakFeatures(nil, "Delete")
229 err := tq.Delete(t, "")
230 So(err.Error(), ShouldContainSubstring, "TRANSIENT_ERROR")
231 })
232
233 Convey("DeleteMulti also works", func() {
234 t2 := dupTask(t)
235 t2.Path = "/hi/city"
236 tEnQ2, err := tq.Add(t2, "")
237 So(err, ShouldBeNil)
238
239 Convey("usually works", func() {
240 err = tq.DeleteMulti([]*taskqueu e.Task{tEnQ, tEnQ2}, "")
241 So(err, ShouldBeNil)
242 So(len(tq.GetScheduledTasks()["d efault"]), ShouldEqual, 0)
243 So(len(tq.GetTombstonedTasks()[" default"]), ShouldEqual, 2)
244 })
245
246 Convey("can be broken", func() {
247 tq.BreakFeatures(nil, "DeleteMul ti")
248 err = tq.DeleteMulti([]*taskqueu e.Task{tEnQ, tEnQ2}, "")
249 So(err.Error(), ShouldContainSub string, "TRANSIENT_ERROR")
250 })
251
252 Convey("is not broken by Delete", func() {
253 tq.BreakFeatures(nil, "Delete")
254 err = tq.DeleteMulti([]*taskqueu e.Task{tEnQ, tEnQ2}, "")
255 So(err, ShouldBeNil)
256 })
257 })
258 })
259 })
260
261 Convey("works with transactions", func() {
262 t := &taskqueue.Task{Path: "/hello/world"}
263 tEnQ, err := tq.Add(t, "")
264 So(err, ShouldBeNil)
265
266 t2 := &taskqueue.Task{Path: "/hi/city"}
267 tEnQ2, err := tq.Add(t2, "")
268 So(err, ShouldBeNil)
269
270 err = tq.Delete(tEnQ2, "")
271 So(err, ShouldBeNil)
272
273 Convey("can view regular tasks", func() {
274 wrapper.GetDS(c).RunInTransaction(func(c context .Context) error {
275 tq := wrapper.GetTQ(c).(interface {
276 wrapper.TQTestable
277 wrapper.TaskQueue
278 })
279
280 So(tq.GetScheduledTasks()["default"][tEn Q.Name], ShouldResemble, tEnQ)
281 So(tq.GetTombstonedTasks()["default"][tE nQ2.Name], ShouldResemble, tEnQ2)
282 So(tq.GetTransactionTasks()["default"], ShouldBeNil)
283 return nil
284 }, nil)
285 })
286
287 Convey("can add a new task", func() {
288 tEnQ3 := (*taskqueue.Task)(nil)
289
290 wrapper.GetDS(c).RunInTransaction(func(c context .Context) error {
291 tq := wrapper.GetTQ(c).(interface {
292 wrapper.TQTestable
293 wrapper.TaskQueue
294 })
295
296 t3 := &taskqueue.Task{Path: "/sandwitch/ victory"}
297 tEnQ3, err = tq.Add(t3, "")
298 So(err, ShouldBeNil)
299
300 So(tq.GetScheduledTasks()["default"][tEn Q.Name], ShouldResemble, tEnQ)
301 So(tq.GetTombstonedTasks()["default"][tE nQ2.Name], ShouldResemble, tEnQ2)
302 So(tq.GetTransactionTasks()["default"][0 ], ShouldResemble, tEnQ3)
303 return nil
304 }, nil)
305
306 // name gets generated at transaction-commit-tim e
307 for name := range tq.GetScheduledTasks()["defaul t"] {
308 if name == tEnQ.Name {
309 continue
310 }
311 tEnQ3.Name = name
312 break
313 }
314
315 So(tq.GetScheduledTasks()["default"][tEnQ.Name], ShouldResemble, tEnQ)
316 So(tq.GetScheduledTasks()["default"][tEnQ3.Name] , ShouldResemble, tEnQ3)
317 So(tq.GetTombstonedTasks()["default"][tEnQ2.Name ], ShouldResemble, tEnQ2)
318 So(tq.GetTransactionTasks()["default"], ShouldBe Nil)
319 })
320
321 Convey("can a new task (but reset the state in a test)", func() {
322 tEnQ3 := (*taskqueue.Task)(nil)
323
324 ttq := interface {
325 wrapper.TQTestable
326 wrapper.TaskQueue
327 }(nil)
328
329 wrapper.GetDS(c).RunInTransaction(func(c context .Context) error {
330 ttq = wrapper.GetTQ(c).(interface {
331 wrapper.TQTestable
332 wrapper.TaskQueue
333 })
334
335 t3 := &taskqueue.Task{Path: "/sandwitch/ victory"}
336 tEnQ3, err = ttq.Add(t3, "")
337 So(err, ShouldBeNil)
338
339 So(ttq.GetScheduledTasks()["default"][tE nQ.Name], ShouldResemble, tEnQ)
340 So(ttq.GetTombstonedTasks()["default"][t EnQ2.Name], ShouldResemble, tEnQ2)
341 So(ttq.GetTransactionTasks()["default"][ 0], ShouldResemble, tEnQ3)
342
343 ttq.ResetTasks()
344
345 So(len(ttq.GetScheduledTasks()["default" ]), ShouldEqual, 0)
346 So(len(ttq.GetTombstonedTasks()["default "]), ShouldEqual, 0)
347 So(len(ttq.GetTransactionTasks()["defaul t"]), ShouldEqual, 0)
348
349 return nil
350 }, nil)
351
352 So(len(tq.GetScheduledTasks()["default"]), Shoul dEqual, 0)
353 So(len(tq.GetTombstonedTasks()["default"]), Shou ldEqual, 0)
354 So(len(tq.GetTransactionTasks()["default"]), Sho uldEqual, 0)
355
356 Convey("and reusing a closed context is bad time s", func() {
357 _, err := ttq.Add(nil, "")
358 So(err.Error(), ShouldContainSubstring, "expired")
359 })
360 })
361
362 Convey("you can AddMulti as well", func() {
363 wrapper.GetDS(c).RunInTransaction(func(c context .Context) error {
364 tq := wrapper.GetTQ(c).(interface {
365 wrapper.TQTestable
366 wrapper.TaskQueue
367 })
368 _, err := tq.AddMulti([]*taskqueue.Task{ t, t, t}, "")
369 So(err, ShouldBeNil)
370 So(len(tq.GetScheduledTasks()["default"] ), ShouldEqual, 1)
371 So(len(tq.GetTransactionTasks()["default "]), ShouldEqual, 3)
372 return nil
373 }, nil)
374 So(len(tq.GetScheduledTasks()["default"]), Shoul dEqual, 4)
375 So(len(tq.GetTransactionTasks()["default"]), Sho uldEqual, 0)
376 })
377
378 Convey("unless you add too many things", func() {
379 wrapper.GetDS(c).RunInTransaction(func(c context .Context) error {
380 for i := 0; i < 5; i++ {
381 _, err = wrapper.GetTQ(c).Add(t, "")
382 So(err, ShouldBeNil)
383 }
384 _, err = wrapper.GetTQ(c).Add(t, "")
385 So(err.Error(), ShouldContainSubstring, "BAD_REQUEST")
386 return nil
387 }, nil)
388 })
389
390 Convey("unless you Add to a bad queue", func() {
391 wrapper.GetDS(c).RunInTransaction(func(c context .Context) error {
392 _, err = wrapper.GetTQ(c).Add(t, "meat")
393 So(err.Error(), ShouldContainSubstring, "UNKNOWN_QUEUE")
394
395 Convey("unless you add it!", func() {
396 wrapper.GetTQ(c).(wrapper.TQTest able).CreateQueue("meat")
397 _, err = wrapper.GetTQ(c).Add(t, "meat")
398 So(err, ShouldBeNil)
399 })
400
401 return nil
402 }, nil)
403 })
404
405 Convey("unless Add is broken", func() {
406 tq.BreakFeatures(nil, "Add")
407 wrapper.GetDS(c).RunInTransaction(func(c context .Context) error {
408 _, err = wrapper.GetTQ(c).Add(t, "")
409 So(err.Error(), ShouldContainSubstring, "TRANSIENT_ERROR")
410 return nil
411 }, nil)
412 })
413
414 Convey("unless AddMulti is broken", func() {
415 tq.BreakFeatures(nil, "AddMulti")
416 wrapper.GetDS(c).RunInTransaction(func(c context .Context) error {
417 _, err = wrapper.GetTQ(c).AddMulti(nil, "")
418 So(err.Error(), ShouldContainSubstring, "TRANSIENT_ERROR")
419 return nil
420 }, nil)
421 })
422
423 Convey("No other features are available, however", func( ) {
424 err := error(nil)
425 func() {
426 defer func() { err = recover().(error) } ()
427 wrapper.GetDS(c).RunInTransaction(func(c context.Context) error {
428 wrapper.GetTQ(c).Delete(t, "")
429 return nil
430 }, nil)
431 }()
432 So(err.Error(), ShouldContainSubstring, "TaskQue ue.Delete")
433 })
434
435 Convey("adding a new task only happens if we don't errou t", func() {
436 wrapper.GetDS(c).RunInTransaction(func(c context .Context) error {
437 t3 := &taskqueue.Task{Path: "/sandwitch/ victory"}
438 _, err = wrapper.GetTQ(c).Add(t3, "")
439 So(err, ShouldBeNil)
440 return fmt.Errorf("nooooo")
441 }, nil)
442
443 So(tq.GetScheduledTasks()["default"][tEnQ.Name], ShouldResemble, tEnQ)
444 So(tq.GetTombstonedTasks()["default"][tEnQ2.Name ], ShouldResemble, tEnQ2)
445 So(tq.GetTransactionTasks()["default"], ShouldBe Nil)
446 })
447
448 Convey("likewise, a panic doesn't schedule anything", fu nc() {
449 func() {
450 defer func() { recover() }()
451 wrapper.GetDS(c).RunInTransaction(func(c context.Context) error {
452 tq := wrapper.GetTQ(c).(interfac e {
453 wrapper.TQTestable
454 wrapper.TaskQueue
455 })
456
457 t3 := &taskqueue.Task{Path: "/sa ndwitch/victory"}
458 _, err = tq.Add(t3, "")
459 So(err, ShouldBeNil)
460
461 panic(fmt.Errorf("nooooo"))
462 }, nil)
463 }()
464
465 So(tq.GetScheduledTasks()["default"][tEnQ.Name], ShouldResemble, tEnQ)
466 So(tq.GetTombstonedTasks()["default"][tEnQ2.Name ], ShouldResemble, tEnQ2)
467 So(tq.GetTransactionTasks()["default"], ShouldBe Nil)
468 })
469
470 })
471 })
472 }
OLDNEW
« no previous file with comments | « go/src/infra/gae/libs/wrapper/memory/taskqueue_data.go ('k') | go/src/infra/gae/libs/wrapper/unsafe/doc.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698