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

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

Powered by Google App Engine
This is Rietveld 408576698