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

Side by Side Diff: memory/taskqueue_test.go

Issue 1243323002: Refactor a bit. (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: fix golint Created 5 years, 5 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
« no previous file with comments | « memory/taskqueue_data.go ('k') | memory/testing_utils_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "math/rand"
10 "net/http"
11 "testing"
12 "time"
13
14 "github.com/luci/gae"
15 "github.com/luci/luci-go/common/clock"
16 "github.com/luci/luci-go/common/clock/testclock"
17 . "github.com/smartystreets/goconvey/convey"
18 "golang.org/x/net/context"
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 c, tc := testclock.UseTime(context.Background(), now)
27 c = gae.SetMathRand(c, rand.New(rand.NewSource(clock.Now(c).Unix Nano())))
28 c = Use(c)
29
30 tq := gae.GetTQ(c).(interface {
31 gae.TaskQueue
32 gae.TQTestable
33 })
34
35 So(tq, ShouldNotBeNil)
36
37 Convey("implements TQMultiReadWriter", func() {
38 Convey("Add", func() {
39 t := &gae.TQTask{Path: "/hello/world"}
40
41 Convey("works", func() {
42 t.Delay = 4 * time.Second
43 t.Header = http.Header{}
44 t.Header.Add("Cat", "tabby")
45 t.Payload = []byte("watwatwat")
46 t.RetryOptions = &gae.TQRetryOptions{Age Limit: 7 * time.Second}
47 _, err := tq.Add(t, "")
48 So(err, ShouldBeNil)
49 name := "Z_UjshxM9ecyMQfGbZmUGOEcgxWU0_5 CGLl_-RntudwAw2DqQ5-58bzJiWQN4OKzeuUb9O4JrPkUw2rOvk2Ax46THojnQ6avBQgZdrKcJmrwQ6o 4qKfJdiyUbGXvy691yRfzLeQhs6cBhWrgf3wH-VPMcA4SC-zlbJ2U8An7I0zJQA5nBFnMNoMgT-2peGo ay3rCSbj4z9VFFm9kS_i6JCaQH518ujLDSNCYdjTq6B6lcWrZAh0U_q3a1S2nXEwrKiw_t9MTNQFgAQZ WyGBbvZQPmeRYtu8SPaWzTfd25v_YWgBuVL2rRSPSMvlDwE04nNdtvVzE8vNNiA1zRimmdzKeqATQF9_ ReUvj4D7U8dcS703DZWfKMBLgBffY9jqCassOOOw77V72Oq5EVauUw3Qw0L6bBsfM9FtahTKUdabzRZj XUoze3EK4KXPt3-wdidau-8JrVf2XFocjjZbwHoxcGvbtT3b4nGLDlgwdC00bwaFBZWff"
50 So(*tq.GetScheduledTasks()["default"][na me], ShouldResemble, gae.TQTask{
51 ETA: now.Add(4 * time.S econd),
52 Header: http.Header{"Cat": []string{"tabby"}},
53 Method: "POST",
54 Name: name,
55 Path: "/hello/world",
56 Payload: []byte("watwatwat" ),
57 RetryOptions: &gae.TQRetryOption s{AgeLimit: 7 * time.Second},
58 })
59 })
60
61 Convey("cannot add to bad queues", func() {
62 _, err := tq.Add(nil, "waaat")
63 So(err.Error(), ShouldContainSubstring, "UNKNOWN_QUEUE")
64
65 Convey("but you can add Queues when test ing", func() {
66 tq.CreateQueue("waaat")
67 _, err := tq.Add(t, "waaat")
68 So(err, ShouldBeNil)
69
70 Convey("you just can't add them twice", func() {
71 So(func() { tq.CreateQue ue("waaat") }, ShouldPanic)
72 })
73 })
74 })
75
76 Convey("supplies a URL if it's missing", func() {
77 t.Path = ""
78 tr, err := tq.Add(t, "")
79 So(err, ShouldBeNil)
80 So(tr.Path, ShouldEqual, "/_ah/queue/def ault")
81 })
82
83 Convey("cannot add twice", func() {
84 t.Name = "bob"
85 _, err := tq.Add(t, "")
86 So(err, ShouldBeNil)
87
88 // can't add the same one twice!
89 _, err = tq.Add(t, "")
90 So(err, ShouldEqual, gae.ErrTQTaskAlread yAdded)
91 })
92
93 Convey("cannot add deleted task", func() {
94 t.Name = "bob"
95 _, err := tq.Add(t, "")
96 So(err, ShouldBeNil)
97
98 err = tq.Delete(t, "")
99 So(err, ShouldBeNil)
100
101 // can't add a deleted task!
102 _, err = tq.Add(t, "")
103 So(err, ShouldEqual, gae.ErrTQTaskAlread yAdded)
104 })
105
106 Convey("cannot set ETA+Delay", func() {
107 t.ETA = clock.Now(c).Add(time.Hour)
108 tc.Add(time.Second)
109 t.Delay = time.Hour
110 So(func() { tq.Add(t, "") }, ShouldPanic )
111 })
112
113 Convey("must use a reasonable method", func() {
114 t.Method = "Crystal"
115 _, err := tq.Add(t, "")
116 So(err.Error(), ShouldContainSubstring, "bad method")
117 })
118
119 Convey("payload gets dumped for non POST/PUT met hods", func() {
120 t.Method = "HEAD"
121 t.Payload = []byte("coool")
122 tq, err := tq.Add(t, "")
123 So(err, ShouldBeNil)
124 So(tq.Payload, ShouldBeNil)
125
126 // check that it didn't modify our origi nal
127 So(t.Payload, ShouldResemble, []byte("co ool"))
128 })
129
130 Convey("invalid names are rejected", func() {
131 t.Name = "happy times"
132 _, err := tq.Add(t, "")
133 So(err.Error(), ShouldContainSubstring, "INVALID_TASK_NAME")
134 })
135
136 Convey("AddMulti also works", func() {
137 t2 := dupTask(t)
138 t2.Path = "/hi/city"
139
140 expect := []*gae.TQTask{t, t2}
141
142 tasks, err := tq.AddMulti(expect, "defau lt")
143 So(err, ShouldBeNil)
144 So(len(tasks), ShouldEqual, 2)
145 So(len(tq.GetScheduledTasks()["default"] ), ShouldEqual, 2)
146
147 for i := range expect {
148 Convey(fmt.Sprintf("task %d: %s" , i, expect[i].Path), func() {
149 expect[i].Method = "POST "
150 expect[i].ETA = now
151 So(expect[i].Name, Shoul dEqual, "")
152 So(len(tasks[i].Name), S houldEqual, 500)
153 tasks[i].Name = ""
154 So(tasks[i], ShouldResem ble, expect[i])
155 })
156 }
157 })
158 })
159
160 Convey("Delete", func() {
161 t := &gae.TQTask{Path: "/hello/world"}
162 tEnQ, err := tq.Add(t, "")
163 So(err, ShouldBeNil)
164
165 Convey("works", func() {
166 t.Name = tEnQ.Name
167 err := tq.Delete(t, "")
168 So(err, ShouldBeNil)
169 So(len(tq.GetScheduledTasks()["default"] ), ShouldEqual, 0)
170 So(len(tq.GetTombstonedTasks()["default" ]), ShouldEqual, 1)
171 So(tq.GetTombstonedTasks()["default"][tE nQ.Name], ShouldResemble, tEnQ)
172 })
173
174 Convey("cannot delete a task twice", func() {
175 err := tq.Delete(tEnQ, "")
176 So(err, ShouldBeNil)
177
178 err = tq.Delete(tEnQ, "")
179 So(err.Error(), ShouldContainSubstring, "TOMBSTONED_TASK")
180
181 Convey("but you can if you do a reset", func() {
182 tq.ResetTasks()
183
184 tEnQ, err := tq.Add(t, "")
185 So(err, ShouldBeNil)
186 err = tq.Delete(tEnQ, "")
187 So(err, ShouldBeNil)
188 })
189 })
190
191 Convey("cannot delete from bogus queues", func() {
192 err := tq.Delete(t, "wat")
193 So(err.Error(), ShouldContainSubstring, "UNKNOWN_QUEUE")
194 })
195
196 Convey("cannot delete a missing task", func() {
197 t.Name = "tarntioarenstyw"
198 err := tq.Delete(t, "")
199 So(err.Error(), ShouldContainSubstring, "UNKNOWN_TASK")
200 })
201
202 Convey("DeleteMulti also works", func() {
203 t2 := dupTask(t)
204 t2.Path = "/hi/city"
205 tEnQ2, err := tq.Add(t2, "")
206 So(err, ShouldBeNil)
207
208 Convey("usually works", func() {
209 err = tq.DeleteMulti([]*gae.TQTa sk{tEnQ, tEnQ2}, "")
210 So(err, ShouldBeNil)
211 So(len(tq.GetScheduledTasks()["d efault"]), ShouldEqual, 0)
212 So(len(tq.GetTombstonedTasks()[" default"]), ShouldEqual, 2)
213 })
214 })
215 })
216 })
217
218 Convey("works with transactions", func() {
219 t := &gae.TQTask{Path: "/hello/world"}
220 tEnQ, err := tq.Add(t, "")
221 So(err, ShouldBeNil)
222
223 t2 := &gae.TQTask{Path: "/hi/city"}
224 tEnQ2, err := tq.Add(t2, "")
225 So(err, ShouldBeNil)
226
227 err = tq.Delete(tEnQ2, "")
228 So(err, ShouldBeNil)
229
230 Convey("can view regular tasks", func() {
231 gae.GetRDS(c).RunInTransaction(func(c context.Co ntext) error {
232 tq := gae.GetTQ(c).(interface {
233 gae.TQTestable
234 gae.TaskQueue
235 })
236
237 So(tq.GetScheduledTasks()["default"][tEn Q.Name], ShouldResemble, tEnQ)
238 So(tq.GetTombstonedTasks()["default"][tE nQ2.Name], ShouldResemble, tEnQ2)
239 So(tq.GetTransactionTasks()["default"], ShouldBeNil)
240 return nil
241 }, nil)
242 })
243
244 Convey("can add a new task", func() {
245 tEnQ3 := (*gae.TQTask)(nil)
246
247 gae.GetRDS(c).RunInTransaction(func(c context.Co ntext) error {
248 tq := gae.GetTQ(c).(interface {
249 gae.TQTestable
250 gae.TaskQueue
251 })
252
253 t3 := &gae.TQTask{Path: "/sandwitch/vict ory"}
254 tEnQ3, err = tq.Add(t3, "")
255 So(err, ShouldBeNil)
256
257 So(tq.GetScheduledTasks()["default"][tEn Q.Name], ShouldResemble, tEnQ)
258 So(tq.GetTombstonedTasks()["default"][tE nQ2.Name], ShouldResemble, tEnQ2)
259 So(tq.GetTransactionTasks()["default"][0 ], ShouldResemble, tEnQ3)
260 return nil
261 }, nil)
262
263 // name gets generated at transaction-commit-tim e
264 for name := range tq.GetScheduledTasks()["defaul t"] {
265 if name == tEnQ.Name {
266 continue
267 }
268 tEnQ3.Name = name
269 break
270 }
271
272 So(tq.GetScheduledTasks()["default"][tEnQ.Name], ShouldResemble, tEnQ)
273 So(tq.GetScheduledTasks()["default"][tEnQ3.Name] , ShouldResemble, tEnQ3)
274 So(tq.GetTombstonedTasks()["default"][tEnQ2.Name ], ShouldResemble, tEnQ2)
275 So(tq.GetTransactionTasks()["default"], ShouldBe Nil)
276 })
277
278 Convey("can a new task (but reset the state in a test)", func() {
279 tEnQ3 := (*gae.TQTask)(nil)
280
281 ttq := interface {
282 gae.TQTestable
283 gae.TaskQueue
284 }(nil)
285
286 gae.GetRDS(c).RunInTransaction(func(c context.Co ntext) error {
287 ttq = gae.GetTQ(c).(interface {
288 gae.TQTestable
289 gae.TaskQueue
290 })
291
292 t3 := &gae.TQTask{Path: "/sandwitch/vict ory"}
293 tEnQ3, err = ttq.Add(t3, "")
294 So(err, ShouldBeNil)
295
296 So(ttq.GetScheduledTasks()["default"][tE nQ.Name], ShouldResemble, tEnQ)
297 So(ttq.GetTombstonedTasks()["default"][t EnQ2.Name], ShouldResemble, tEnQ2)
298 So(ttq.GetTransactionTasks()["default"][ 0], ShouldResemble, tEnQ3)
299
300 ttq.ResetTasks()
301
302 So(len(ttq.GetScheduledTasks()["default" ]), ShouldEqual, 0)
303 So(len(ttq.GetTombstonedTasks()["default "]), ShouldEqual, 0)
304 So(len(ttq.GetTransactionTasks()["defaul t"]), ShouldEqual, 0)
305
306 return nil
307 }, nil)
308
309 So(len(tq.GetScheduledTasks()["default"]), Shoul dEqual, 0)
310 So(len(tq.GetTombstonedTasks()["default"]), Shou ldEqual, 0)
311 So(len(tq.GetTransactionTasks()["default"]), Sho uldEqual, 0)
312
313 Convey("and reusing a closed context is bad time s", func() {
314 _, err := ttq.Add(nil, "")
315 So(err.Error(), ShouldContainSubstring, "expired")
316 })
317 })
318
319 Convey("you can AddMulti as well", func() {
320 gae.GetRDS(c).RunInTransaction(func(c context.Co ntext) error {
321 tq := gae.GetTQ(c).(interface {
322 gae.TQTestable
323 gae.TaskQueue
324 })
325 _, err := tq.AddMulti([]*gae.TQTask{t, t , t}, "")
326 So(err, ShouldBeNil)
327 So(len(tq.GetScheduledTasks()["default"] ), ShouldEqual, 1)
328 So(len(tq.GetTransactionTasks()["default "]), ShouldEqual, 3)
329 return nil
330 }, nil)
331 So(len(tq.GetScheduledTasks()["default"]), Shoul dEqual, 4)
332 So(len(tq.GetTransactionTasks()["default"]), Sho uldEqual, 0)
333 })
334
335 Convey("unless you add too many things", func() {
336 gae.GetRDS(c).RunInTransaction(func(c context.Co ntext) error {
337 for i := 0; i < 5; i++ {
338 _, err = gae.GetTQ(c).Add(t, "")
339 So(err, ShouldBeNil)
340 }
341 _, err = gae.GetTQ(c).Add(t, "")
342 So(err.Error(), ShouldContainSubstring, "BAD_REQUEST")
343 return nil
344 }, nil)
345 })
346
347 Convey("unless you Add to a bad queue", func() {
348 gae.GetRDS(c).RunInTransaction(func(c context.Co ntext) error {
349 _, err = gae.GetTQ(c).Add(t, "meat")
350 So(err.Error(), ShouldContainSubstring, "UNKNOWN_QUEUE")
351
352 Convey("unless you add it!", func() {
353 gae.GetTQ(c).(gae.TQTestable).Cr eateQueue("meat")
354 _, err = gae.GetTQ(c).Add(t, "me at")
355 So(err, ShouldBeNil)
356 })
357
358 return nil
359 }, nil)
360 })
361
362 Convey("No other features are available, however", func( ) {
363 err := error(nil)
364 func() {
365 defer func() { err = recover().(error) } ()
366 gae.GetRDS(c).RunInTransaction(func(c co ntext.Context) error {
367 gae.GetTQ(c).Delete(t, "")
368 return nil
369 }, nil)
370 }()
371 So(err.Error(), ShouldContainSubstring, "TaskQue ue.Delete")
372 })
373
374 Convey("adding a new task only happens if we don't errou t", func() {
375 gae.GetRDS(c).RunInTransaction(func(c context.Co ntext) error {
376 t3 := &gae.TQTask{Path: "/sandwitch/vict ory"}
377 _, err = gae.GetTQ(c).Add(t3, "")
378 So(err, ShouldBeNil)
379 return fmt.Errorf("nooooo")
380 }, nil)
381
382 So(tq.GetScheduledTasks()["default"][tEnQ.Name], ShouldResemble, tEnQ)
383 So(tq.GetTombstonedTasks()["default"][tEnQ2.Name ], ShouldResemble, tEnQ2)
384 So(tq.GetTransactionTasks()["default"], ShouldBe Nil)
385 })
386
387 Convey("likewise, a panic doesn't schedule anything", fu nc() {
388 func() {
389 defer func() { recover() }()
390 gae.GetRDS(c).RunInTransaction(func(c co ntext.Context) error {
391 tq := gae.GetTQ(c).(interface {
392 gae.TQTestable
393 gae.TaskQueue
394 })
395
396 t3 := &gae.TQTask{Path: "/sandwi tch/victory"}
397 _, err = tq.Add(t3, "")
398 So(err, ShouldBeNil)
399
400 panic(fmt.Errorf("nooooo"))
401 }, nil)
402 }()
403
404 So(tq.GetScheduledTasks()["default"][tEnQ.Name], ShouldResemble, tEnQ)
405 So(tq.GetTombstonedTasks()["default"][tEnQ2.Name ], ShouldResemble, tEnQ2)
406 So(tq.GetTransactionTasks()["default"], ShouldBe Nil)
407 })
408
409 })
410 })
411 }
OLDNEW
« no previous file with comments | « memory/taskqueue_data.go ('k') | memory/testing_utils_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698