| 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 package memory | 5 package memory |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "fmt" | 8 "fmt" |
| 9 "math/rand" | 9 "math/rand" |
| 10 "net/http" | 10 "net/http" |
| 11 "testing" | 11 "testing" |
| 12 "time" | 12 "time" |
| 13 | 13 |
| 14 » dsS "github.com/luci/gae/service/datastore" | 14 » ds "github.com/luci/gae/service/datastore" |
| 15 "github.com/luci/gae/service/info" | 15 "github.com/luci/gae/service/info" |
| 16 » tqS "github.com/luci/gae/service/taskqueue" | 16 » tq "github.com/luci/gae/service/taskqueue" |
| 17 |
| 17 "github.com/luci/luci-go/common/clock" | 18 "github.com/luci/luci-go/common/clock" |
| 18 "github.com/luci/luci-go/common/clock/testclock" | 19 "github.com/luci/luci-go/common/clock/testclock" |
| 19 "github.com/luci/luci-go/common/data/rand/mathrand" | 20 "github.com/luci/luci-go/common/data/rand/mathrand" |
| 21 |
| 22 "golang.org/x/net/context" |
| 23 |
| 20 . "github.com/luci/luci-go/common/testing/assertions" | 24 . "github.com/luci/luci-go/common/testing/assertions" |
| 21 . "github.com/smartystreets/goconvey/convey" | 25 . "github.com/smartystreets/goconvey/convey" |
| 22 "golang.org/x/net/context" | |
| 23 ) | 26 ) |
| 24 | 27 |
| 25 func TestTaskQueue(t *testing.T) { | 28 func TestTaskQueue(t *testing.T) { |
| 26 t.Parallel() | 29 t.Parallel() |
| 27 | 30 |
| 28 Convey("TaskQueue", t, func() { | 31 Convey("TaskQueue", t, func() { |
| 29 now := time.Date(2000, time.January, 1, 1, 1, 1, 1, time.UTC) | 32 now := time.Date(2000, time.January, 1, 1, 1, 1, 1, time.UTC) |
| 30 c, tc := testclock.UseTime(context.Background(), now) | 33 c, tc := testclock.UseTime(context.Background(), now) |
| 31 c = mathrand.Set(c, rand.New(rand.NewSource(clock.Now(c).UnixNan
o()))) | 34 c = mathrand.Set(c, rand.New(rand.NewSource(clock.Now(c).UnixNan
o()))) |
| 32 c = Use(c) | 35 c = Use(c) |
| 33 | 36 |
| 34 » » tq := tqS.Get(c) | 37 » » tqt := tq.GetTestable(c) |
| 35 » » tqt := tq.Testable() | |
| 36 So(tqt, ShouldNotBeNil) | 38 So(tqt, ShouldNotBeNil) |
| 37 | 39 |
| 38 » » So(tq, ShouldNotBeNil) | 40 » » So(tq.Raw(c), ShouldNotBeNil) |
| 39 | 41 |
| 40 Convey("implements TQMultiReadWriter", func() { | 42 Convey("implements TQMultiReadWriter", func() { |
| 41 Convey("Add", func() { | 43 Convey("Add", func() { |
| 42 » » » » t := &tqS.Task{Path: "/hello/world"} | 44 » » » » t := &tq.Task{Path: "/hello/world"} |
| 43 | 45 |
| 44 Convey("works", func() { | 46 Convey("works", func() { |
| 45 t.Delay = 4 * time.Second | 47 t.Delay = 4 * time.Second |
| 46 t.Header = http.Header{} | 48 t.Header = http.Header{} |
| 47 t.Header.Add("Cat", "tabby") | 49 t.Header.Add("Cat", "tabby") |
| 48 t.Payload = []byte("watwatwat") | 50 t.Payload = []byte("watwatwat") |
| 49 » » » » » t.RetryOptions = &tqS.RetryOptions{AgeLi
mit: 7 * time.Second} | 51 » » » » » t.RetryOptions = &tq.RetryOptions{AgeLim
it: 7 * time.Second} |
| 50 » » » » » So(tq.Add(t, ""), ShouldBeNil) | 52 » » » » » So(tq.Add(c, "", t), ShouldBeNil) |
| 51 | 53 |
| 52 name := "Z_UjshxM9ecyMQfGbZmUGOEcgxWU0_5
CGLl_-RntudwAw2DqQ5-58bzJiWQN4OKzeuUb9O4JrPkUw2rOvk2Ax46THojnQ6avBQgZdrKcJmrwQ6o
4qKfJdiyUbGXvy691yRfzLeQhs6cBhWrgf3wH-VPMcA4SC-zlbJ2U8An7I0zJQA5nBFnMNoMgT-2peGo
ay3rCSbj4z9VFFm9kS_i6JCaQH518ujLDSNCYdjTq6B6lcWrZAh0U_q3a1S2nXEwrKiw_t9MTNQFgAQZ
WyGBbvZQPmeRYtu8SPaWzTfd25v_YWgBuVL2rRSPSMvlDwE04nNdtvVzE8vNNiA1zRimmdzKeqATQF9_
ReUvj4D7U8dcS703DZWfKMBLgBffY9jqCassOOOw77V72Oq5EVauUw3Qw0L6bBsfM9FtahTKUdabzRZj
XUoze3EK4KXPt3-wdidau-8JrVf2XFocjjZbwHoxcGvbtT3b4nGLDlgwdC00bwaFBZWff" | 54 name := "Z_UjshxM9ecyMQfGbZmUGOEcgxWU0_5
CGLl_-RntudwAw2DqQ5-58bzJiWQN4OKzeuUb9O4JrPkUw2rOvk2Ax46THojnQ6avBQgZdrKcJmrwQ6o
4qKfJdiyUbGXvy691yRfzLeQhs6cBhWrgf3wH-VPMcA4SC-zlbJ2U8An7I0zJQA5nBFnMNoMgT-2peGo
ay3rCSbj4z9VFFm9kS_i6JCaQH518ujLDSNCYdjTq6B6lcWrZAh0U_q3a1S2nXEwrKiw_t9MTNQFgAQZ
WyGBbvZQPmeRYtu8SPaWzTfd25v_YWgBuVL2rRSPSMvlDwE04nNdtvVzE8vNNiA1zRimmdzKeqATQF9_
ReUvj4D7U8dcS703DZWfKMBLgBffY9jqCassOOOw77V72Oq5EVauUw3Qw0L6bBsfM9FtahTKUdabzRZj
XUoze3EK4KXPt3-wdidau-8JrVf2XFocjjZbwHoxcGvbtT3b4nGLDlgwdC00bwaFBZWff" |
| 53 » » » » » So(tqt.GetScheduledTasks()["default"][na
me], ShouldResemble, &tqS.Task{ | 55 » » » » » So(tqt.GetScheduledTasks()["default"][na
me], ShouldResemble, &tq.Task{ |
| 54 ETA: now.Add(4 * time.S
econd), | 56 ETA: now.Add(4 * time.S
econd), |
| 55 Header: http.Header{"Cat":
[]string{"tabby"}}, | 57 Header: http.Header{"Cat":
[]string{"tabby"}}, |
| 56 Method: "POST", | 58 Method: "POST", |
| 57 Name: name, | 59 Name: name, |
| 58 Path: "/hello/world", | 60 Path: "/hello/world", |
| 59 Payload: []byte("watwatwat"
), | 61 Payload: []byte("watwatwat"
), |
| 60 » » » » » » RetryOptions: &tqS.RetryOptions{
AgeLimit: 7 * time.Second}, | 62 » » » » » » RetryOptions: &tq.RetryOptions{A
geLimit: 7 * time.Second}, |
| 61 }) | 63 }) |
| 62 }) | 64 }) |
| 63 | 65 |
| 64 Convey("picks up namespace", func() { | 66 Convey("picks up namespace", func() { |
| 65 » » » » » c, err := info.Get(c).Namespace("coolNam
espace") | 67 » » » » » c, err := info.Namespace(c, "coolNamespa
ce") |
| 66 So(err, ShouldBeNil) | 68 So(err, ShouldBeNil) |
| 67 tq = tqS.Get(c) | |
| 68 | 69 |
| 69 » » » » » t := &tqS.Task{} | 70 » » » » » t := &tq.Task{} |
| 70 » » » » » So(tq.Add(t, ""), ShouldBeNil) | 71 » » » » » So(tq.Add(c, "", t), ShouldBeNil) |
| 71 So(t.Header, ShouldResemble, http.Header
{ | 72 So(t.Header, ShouldResemble, http.Header
{ |
| 72 "X-Appengine-Current-Namespace":
{"coolNamespace"}, | 73 "X-Appengine-Current-Namespace":
{"coolNamespace"}, |
| 73 }) | 74 }) |
| 74 | 75 |
| 75 }) | 76 }) |
| 76 | 77 |
| 77 Convey("cannot add to bad queues", func() { | 78 Convey("cannot add to bad queues", func() { |
| 78 » » » » » So(tq.Add(nil, "waaat").Error(), ShouldC
ontainSubstring, "UNKNOWN_QUEUE") | 79 » » » » » So(tq.Add(c, "waaat", nil).Error(), Shou
ldContainSubstring, "UNKNOWN_QUEUE") |
| 79 | 80 |
| 80 Convey("but you can add Queues when test
ing", func() { | 81 Convey("but you can add Queues when test
ing", func() { |
| 81 tqt.CreateQueue("waaat") | 82 tqt.CreateQueue("waaat") |
| 82 » » » » » » So(tq.Add(t, "waaat"), ShouldBeN
il) | 83 » » » » » » So(tq.Add(c, "waaat", t), Should
BeNil) |
| 83 | 84 |
| 84 Convey("you just can't add them
twice", func() { | 85 Convey("you just can't add them
twice", func() { |
| 85 So(func() { tqt.CreateQu
eue("waaat") }, ShouldPanic) | 86 So(func() { tqt.CreateQu
eue("waaat") }, ShouldPanic) |
| 86 }) | 87 }) |
| 87 }) | 88 }) |
| 88 }) | 89 }) |
| 89 | 90 |
| 90 Convey("supplies a URL if it's missing", func()
{ | 91 Convey("supplies a URL if it's missing", func()
{ |
| 91 t.Path = "" | 92 t.Path = "" |
| 92 » » » » » So(tq.Add(t, ""), ShouldBeNil) | 93 » » » » » So(tq.Add(c, "", t), ShouldBeNil) |
| 93 So(t.Path, ShouldEqual, "/_ah/queue/defa
ult") | 94 So(t.Path, ShouldEqual, "/_ah/queue/defa
ult") |
| 94 }) | 95 }) |
| 95 | 96 |
| 96 Convey("cannot add twice", func() { | 97 Convey("cannot add twice", func() { |
| 97 t.Name = "bob" | 98 t.Name = "bob" |
| 98 » » » » » So(tq.Add(t, ""), ShouldBeNil) | 99 » » » » » So(tq.Add(c, "", t), ShouldBeNil) |
| 99 | 100 |
| 100 // can't add the same one twice! | 101 // can't add the same one twice! |
| 101 » » » » » So(tq.Add(t, ""), ShouldEqual, tqS.ErrTa
skAlreadyAdded) | 102 » » » » » So(tq.Add(c, "", t), ShouldEqual, tq.Err
TaskAlreadyAdded) |
| 102 }) | 103 }) |
| 103 | 104 |
| 104 Convey("cannot add deleted task", func() { | 105 Convey("cannot add deleted task", func() { |
| 105 t.Name = "bob" | 106 t.Name = "bob" |
| 106 » » » » » So(tq.Add(t, ""), ShouldBeNil) | 107 » » » » » So(tq.Add(c, "", t), ShouldBeNil) |
| 107 | 108 |
| 108 » » » » » So(tq.Delete(t, ""), ShouldBeNil) | 109 » » » » » So(tq.Delete(c, "", t), ShouldBeNil) |
| 109 | 110 |
| 110 // can't add a deleted task! | 111 // can't add a deleted task! |
| 111 » » » » » So(tq.Add(t, ""), ShouldEqual, tqS.ErrTa
skAlreadyAdded) | 112 » » » » » So(tq.Add(c, "", t), ShouldEqual, tq.Err
TaskAlreadyAdded) |
| 112 }) | 113 }) |
| 113 | 114 |
| 114 Convey("cannot set ETA+Delay", func() { | 115 Convey("cannot set ETA+Delay", func() { |
| 115 t.ETA = clock.Now(c).Add(time.Hour) | 116 t.ETA = clock.Now(c).Add(time.Hour) |
| 116 tc.Add(time.Second) | 117 tc.Add(time.Second) |
| 117 t.Delay = time.Hour | 118 t.Delay = time.Hour |
| 118 So(func() { | 119 So(func() { |
| 119 » » » » » » So(tq.Add(t, ""), ShouldBeNil) | 120 » » » » » » So(tq.Add(c, "", t), ShouldBeNil
) |
| 120 }, ShouldPanic) | 121 }, ShouldPanic) |
| 121 }) | 122 }) |
| 122 | 123 |
| 123 Convey("must use a reasonable method", func() { | 124 Convey("must use a reasonable method", func() { |
| 124 t.Method = "Crystal" | 125 t.Method = "Crystal" |
| 125 » » » » » So(tq.Add(t, "").Error(), ShouldContainS
ubstring, "bad method") | 126 » » » » » So(tq.Add(c, "", t).Error(), ShouldConta
inSubstring, "bad method") |
| 126 }) | 127 }) |
| 127 | 128 |
| 128 Convey("payload gets dumped for non POST/PUT met
hods", func() { | 129 Convey("payload gets dumped for non POST/PUT met
hods", func() { |
| 129 t.Method = "HEAD" | 130 t.Method = "HEAD" |
| 130 t.Payload = []byte("coool") | 131 t.Payload = []byte("coool") |
| 131 » » » » » So(tq.Add(t, ""), ShouldBeNil) | 132 » » » » » So(tq.Add(c, "", t), ShouldBeNil) |
| 132 So(t.Payload, ShouldBeNil) | 133 So(t.Payload, ShouldBeNil) |
| 133 }) | 134 }) |
| 134 | 135 |
| 135 Convey("invalid names are rejected", func() { | 136 Convey("invalid names are rejected", func() { |
| 136 t.Name = "happy times" | 137 t.Name = "happy times" |
| 137 » » » » » So(tq.Add(t, "").Error(), ShouldContainS
ubstring, "INVALID_TASK_NAME") | 138 » » » » » So(tq.Add(c, "", t).Error(), ShouldConta
inSubstring, "INVALID_TASK_NAME") |
| 138 }) | 139 }) |
| 139 | 140 |
| 140 Convey("AddMulti also works", func() { | 141 Convey("AddMulti also works", func() { |
| 141 t2 := t.Duplicate() | 142 t2 := t.Duplicate() |
| 142 t2.Path = "/hi/city" | 143 t2.Path = "/hi/city" |
| 143 | 144 |
| 144 » » » » » expect := []*tqS.Task{t, t2} | 145 » » » » » expect := []*tq.Task{t, t2} |
| 145 | 146 |
| 146 » » » » » So(tq.AddMulti(expect, "default"), Shoul
dBeNil) | 147 » » » » » So(tq.Add(c, "default", expect...), Shou
ldBeNil) |
| 147 So(len(expect), ShouldEqual, 2) | 148 So(len(expect), ShouldEqual, 2) |
| 148 So(len(tqt.GetScheduledTasks()["default"
]), ShouldEqual, 2) | 149 So(len(tqt.GetScheduledTasks()["default"
]), ShouldEqual, 2) |
| 149 | 150 |
| 150 for i := range expect { | 151 for i := range expect { |
| 151 Convey(fmt.Sprintf("task %d: %s"
, i, expect[i].Path), func() { | 152 Convey(fmt.Sprintf("task %d: %s"
, i, expect[i].Path), func() { |
| 152 So(expect[i].Method, Sho
uldEqual, "POST") | 153 So(expect[i].Method, Sho
uldEqual, "POST") |
| 153 So(expect[i].ETA, Should
HappenOnOrBefore, now) | 154 So(expect[i].ETA, Should
HappenOnOrBefore, now) |
| 154 So(len(expect[i].Name),
ShouldEqual, 500) | 155 So(len(expect[i].Name),
ShouldEqual, 500) |
| 155 }) | 156 }) |
| 156 } | 157 } |
| 157 | 158 |
| 158 Convey("stats work too", func() { | 159 Convey("stats work too", func() { |
| 159 delay := -time.Second * 400 | 160 delay := -time.Second * 400 |
| 160 | 161 |
| 161 » » » » » » t := &tqS.Task{Path: "/somewhere
"} | 162 » » » » » » t := &tq.Task{Path: "/somewhere"
} |
| 162 t.Delay = delay | 163 t.Delay = delay |
| 163 » » » » » » So(tq.Add(t, ""), ShouldBeNil) | 164 » » » » » » So(tq.Add(c, "", t), ShouldBeNil
) |
| 164 | 165 |
| 165 » » » » » » stats, err := tq.Stats("") | 166 » » » » » » stats, err := tq.Stats(c, "") |
| 166 So(err, ShouldBeNil) | 167 So(err, ShouldBeNil) |
| 167 So(stats[0].Tasks, ShouldEqual,
3) | 168 So(stats[0].Tasks, ShouldEqual,
3) |
| 168 So(stats[0].OldestETA, ShouldHap
penOnOrBefore, clock.Now(c).Add(delay)) | 169 So(stats[0].OldestETA, ShouldHap
penOnOrBefore, clock.Now(c).Add(delay)) |
| 169 | 170 |
| 170 » » » » » » _, err = tq.Stats("noexist") | 171 » » » » » » _, err = tq.Stats(c, "noexist") |
| 171 So(err.Error(), ShouldContainSub
string, "UNKNOWN_QUEUE") | 172 So(err.Error(), ShouldContainSub
string, "UNKNOWN_QUEUE") |
| 172 }) | 173 }) |
| 173 | 174 |
| 174 Convey("can purge all tasks", func() { | 175 Convey("can purge all tasks", func() { |
| 175 » » » » » » So(tq.Add(&tqS.Task{Path: "/wut/
nerbs"}, ""), ShouldBeNil) | 176 » » » » » » So(tq.Add(c, "", &tq.Task{Path:
"/wut/nerbs"}), ShouldBeNil) |
| 176 » » » » » » So(tq.Purge(""), ShouldBeNil) | 177 » » » » » » So(tq.Purge(c, ""), ShouldBeNil) |
| 177 | 178 |
| 178 So(len(tqt.GetScheduledTasks()["
default"]), ShouldEqual, 0) | 179 So(len(tqt.GetScheduledTasks()["
default"]), ShouldEqual, 0) |
| 179 So(len(tqt.GetTombstonedTasks()[
"default"]), ShouldEqual, 0) | 180 So(len(tqt.GetTombstonedTasks()[
"default"]), ShouldEqual, 0) |
| 180 So(len(tqt.GetTransactionTasks()
["default"]), ShouldEqual, 0) | 181 So(len(tqt.GetTransactionTasks()
["default"]), ShouldEqual, 0) |
| 181 | 182 |
| 182 Convey("purging a queue which DN
E fails", func() { | 183 Convey("purging a queue which DN
E fails", func() { |
| 183 » » » » » » » So(tq.Purge("noexist").E
rror(), ShouldContainSubstring, "UNKNOWN_QUEUE") | 184 » » » » » » » So(tq.Purge(c, "noexist"
).Error(), ShouldContainSubstring, "UNKNOWN_QUEUE") |
| 184 }) | 185 }) |
| 185 }) | 186 }) |
| 186 | 187 |
| 187 }) | 188 }) |
| 188 }) | 189 }) |
| 189 | 190 |
| 190 Convey("Delete", func() { | 191 Convey("Delete", func() { |
| 191 » » » » t := &tqS.Task{Path: "/hello/world"} | 192 » » » » t := &tq.Task{Path: "/hello/world"} |
| 192 » » » » So(tq.Add(t, ""), ShouldBeNil) | 193 » » » » So(tq.Add(c, "", t), ShouldBeNil) |
| 193 | 194 |
| 194 Convey("works", func() { | 195 Convey("works", func() { |
| 195 » » » » » err := tq.Delete(t, "") | 196 » » » » » err := tq.Delete(c, "", t) |
| 196 So(err, ShouldBeNil) | 197 So(err, ShouldBeNil) |
| 197 So(len(tqt.GetScheduledTasks()["default"
]), ShouldEqual, 0) | 198 So(len(tqt.GetScheduledTasks()["default"
]), ShouldEqual, 0) |
| 198 So(len(tqt.GetTombstonedTasks()["default
"]), ShouldEqual, 1) | 199 So(len(tqt.GetTombstonedTasks()["default
"]), ShouldEqual, 1) |
| 199 So(tqt.GetTombstonedTasks()["default"][t
.Name], ShouldResemble, t) | 200 So(tqt.GetTombstonedTasks()["default"][t
.Name], ShouldResemble, t) |
| 200 }) | 201 }) |
| 201 | 202 |
| 202 Convey("cannot delete a task twice", func() { | 203 Convey("cannot delete a task twice", func() { |
| 203 » » » » » So(tq.Delete(t, ""), ShouldBeNil) | 204 » » » » » So(tq.Delete(c, "", t), ShouldBeNil) |
| 204 | 205 |
| 205 » » » » » So(tq.Delete(t, "").Error(), ShouldConta
inSubstring, "TOMBSTONED_TASK") | 206 » » » » » So(tq.Delete(c, "", t).Error(), ShouldCo
ntainSubstring, "TOMBSTONED_TASK") |
| 206 | 207 |
| 207 Convey("but you can if you do a reset",
func() { | 208 Convey("but you can if you do a reset",
func() { |
| 208 tqt.ResetTasks() | 209 tqt.ResetTasks() |
| 209 | 210 |
| 210 » » » » » » So(tq.Add(t, ""), ShouldBeNil) | 211 » » » » » » So(tq.Add(c, "", t), ShouldBeNil
) |
| 211 » » » » » » So(tq.Delete(t, ""), ShouldBeNil
) | 212 » » » » » » So(tq.Delete(c, "", t), ShouldBe
Nil) |
| 212 }) | 213 }) |
| 213 }) | 214 }) |
| 214 | 215 |
| 215 Convey("cannot delete from bogus queues", func()
{ | 216 Convey("cannot delete from bogus queues", func()
{ |
| 216 » » » » » err := tq.Delete(t, "wat") | 217 » » » » » err := tq.Delete(c, "wat", t) |
| 217 So(err.Error(), ShouldContainSubstring,
"UNKNOWN_QUEUE") | 218 So(err.Error(), ShouldContainSubstring,
"UNKNOWN_QUEUE") |
| 218 }) | 219 }) |
| 219 | 220 |
| 220 Convey("cannot delete a missing task", func() { | 221 Convey("cannot delete a missing task", func() { |
| 221 t.Name = "tarntioarenstyw" | 222 t.Name = "tarntioarenstyw" |
| 222 » » » » » err := tq.Delete(t, "") | 223 » » » » » err := tq.Delete(c, "", t) |
| 223 So(err.Error(), ShouldContainSubstring,
"UNKNOWN_TASK") | 224 So(err.Error(), ShouldContainSubstring,
"UNKNOWN_TASK") |
| 224 }) | 225 }) |
| 225 | 226 |
| 226 Convey("DeleteMulti also works", func() { | 227 Convey("DeleteMulti also works", func() { |
| 227 t2 := t.Duplicate() | 228 t2 := t.Duplicate() |
| 228 t2.Name = "" | 229 t2.Name = "" |
| 229 t2.Path = "/hi/city" | 230 t2.Path = "/hi/city" |
| 230 » » » » » So(tq.Add(t2, ""), ShouldBeNil) | 231 » » » » » So(tq.Add(c, "", t2), ShouldBeNil) |
| 231 | 232 |
| 232 Convey("usually works", func() { | 233 Convey("usually works", func() { |
| 233 » » » » » » So(tq.DeleteMulti([]*tqS.Task{t,
t2}, ""), ShouldBeNil) | 234 » » » » » » So(tq.Delete(c, "", t, t2), Shou
ldBeNil) |
| 234 So(len(tqt.GetScheduledTasks()["
default"]), ShouldEqual, 0) | 235 So(len(tqt.GetScheduledTasks()["
default"]), ShouldEqual, 0) |
| 235 So(len(tqt.GetTombstonedTasks()[
"default"]), ShouldEqual, 2) | 236 So(len(tqt.GetTombstonedTasks()[
"default"]), ShouldEqual, 2) |
| 236 }) | 237 }) |
| 237 }) | 238 }) |
| 238 }) | 239 }) |
| 239 }) | 240 }) |
| 240 | 241 |
| 241 Convey("works with transactions", func() { | 242 Convey("works with transactions", func() { |
| 242 » » » t := &tqS.Task{Path: "/hello/world"} | 243 » » » t := &tq.Task{Path: "/hello/world"} |
| 243 » » » So(tq.Add(t, ""), ShouldBeNil) | 244 » » » So(tq.Add(c, "", t), ShouldBeNil) |
| 244 | 245 |
| 245 » » » t2 := &tqS.Task{Path: "/hi/city"} | 246 » » » t2 := &tq.Task{Path: "/hi/city"} |
| 246 » » » So(tq.Add(t2, ""), ShouldBeNil) | 247 » » » So(tq.Add(c, "", t2), ShouldBeNil) |
| 247 | 248 |
| 248 » » » So(tq.Delete(t2, ""), ShouldBeNil) | 249 » » » So(tq.Delete(c, "", t2), ShouldBeNil) |
| 249 | 250 |
| 250 Convey("can view regular tasks", func() { | 251 Convey("can view regular tasks", func() { |
| 251 » » » » So(dsS.Get(c).RunInTransaction(func(c context.Co
ntext) error { | 252 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 252 » » » » » tqt := tqS.GetRaw(c).Testable() | 253 » » » » » tqt := tq.Raw(c).GetTestable() |
| 253 | 254 |
| 254 So(tqt.GetScheduledTasks()["default"][t.
Name], ShouldResemble, t) | 255 So(tqt.GetScheduledTasks()["default"][t.
Name], ShouldResemble, t) |
| 255 So(tqt.GetTombstonedTasks()["default"][t
2.Name], ShouldResemble, t2) | 256 So(tqt.GetTombstonedTasks()["default"][t
2.Name], ShouldResemble, t2) |
| 256 So(tqt.GetTransactionTasks()["default"],
ShouldBeNil) | 257 So(tqt.GetTransactionTasks()["default"],
ShouldBeNil) |
| 257 return nil | 258 return nil |
| 258 }, nil), ShouldBeNil) | 259 }, nil), ShouldBeNil) |
| 259 }) | 260 }) |
| 260 | 261 |
| 261 Convey("can add a new task", func() { | 262 Convey("can add a new task", func() { |
| 262 » » » » t3 := &tqS.Task{Path: "/sandwitch/victory"} | 263 » » » » t3 := &tq.Task{Path: "/sandwitch/victory"} |
| 263 | 264 |
| 264 » » » » err := dsS.Get(c).RunInTransaction(func(c contex
t.Context) error { | 265 » » » » err := ds.RunInTransaction(c, func(c context.Con
text) error { |
| 265 » » » » » tq := tqS.Get(c) | 266 » » » » » tqt := tq.GetTestable(c) |
| 266 » » » » » tqt := tq.Testable() | |
| 267 | 267 |
| 268 » » » » » So(tq.Add(t3, ""), ShouldBeNil) | 268 » » » » » So(tq.Add(c, "", t3), ShouldBeNil) |
| 269 So(t3.Name, ShouldEqual, "") | 269 So(t3.Name, ShouldEqual, "") |
| 270 | 270 |
| 271 So(tqt.GetScheduledTasks()["default"][t.
Name], ShouldResemble, t) | 271 So(tqt.GetScheduledTasks()["default"][t.
Name], ShouldResemble, t) |
| 272 So(tqt.GetTombstonedTasks()["default"][t
2.Name], ShouldResemble, t2) | 272 So(tqt.GetTombstonedTasks()["default"][t
2.Name], ShouldResemble, t2) |
| 273 So(tqt.GetTransactionTasks()["default"][
0], ShouldResemble, t3) | 273 So(tqt.GetTransactionTasks()["default"][
0], ShouldResemble, t3) |
| 274 return nil | 274 return nil |
| 275 }, nil) | 275 }, nil) |
| 276 So(err, ShouldBeNil) | 276 So(err, ShouldBeNil) |
| 277 | 277 |
| 278 for _, tsk := range tqt.GetScheduledTasks()["def
ault"] { | 278 for _, tsk := range tqt.GetScheduledTasks()["def
ault"] { |
| 279 if tsk.Name == t.Name { | 279 if tsk.Name == t.Name { |
| 280 So(tsk, ShouldResemble, t) | 280 So(tsk, ShouldResemble, t) |
| 281 } else { | 281 } else { |
| 282 tsk.Name = "" | 282 tsk.Name = "" |
| 283 So(tsk, ShouldResemble, t3) | 283 So(tsk, ShouldResemble, t3) |
| 284 } | 284 } |
| 285 } | 285 } |
| 286 | 286 |
| 287 So(tqt.GetTombstonedTasks()["default"][t2.Name],
ShouldResemble, t2) | 287 So(tqt.GetTombstonedTasks()["default"][t2.Name],
ShouldResemble, t2) |
| 288 So(tqt.GetTransactionTasks()["default"], ShouldB
eNil) | 288 So(tqt.GetTransactionTasks()["default"], ShouldB
eNil) |
| 289 }) | 289 }) |
| 290 | 290 |
| 291 Convey("can add a new task (but reset the state in a tes
t)", func() { | 291 Convey("can add a new task (but reset the state in a tes
t)", func() { |
| 292 » » » » t3 := &tqS.Task{Path: "/sandwitch/victory"} | 292 » » » » t3 := &tq.Task{Path: "/sandwitch/victory"} |
| 293 | 293 |
| 294 » » » » ttq := tqS.Interface(nil) | 294 » » » » var txnCtx context.Context |
| 295 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 296 » » » » » txnCtx = c |
| 297 » » » » » tqt := tq.GetTestable(c) |
| 295 | 298 |
| 296 » » » » So(dsS.Get(c).RunInTransaction(func(c context.Co
ntext) error { | 299 » » » » » So(tq.Add(c, "", t3), ShouldBeNil) |
| 297 » » » » » ttq = tqS.Get(c) | |
| 298 » » » » » tqt := ttq.Testable() | |
| 299 | |
| 300 » » » » » So(ttq.Add(t3, ""), ShouldBeNil) | |
| 301 | 300 |
| 302 So(tqt.GetScheduledTasks()["default"][t.
Name], ShouldResemble, t) | 301 So(tqt.GetScheduledTasks()["default"][t.
Name], ShouldResemble, t) |
| 303 So(tqt.GetTombstonedTasks()["default"][t
2.Name], ShouldResemble, t2) | 302 So(tqt.GetTombstonedTasks()["default"][t
2.Name], ShouldResemble, t2) |
| 304 So(tqt.GetTransactionTasks()["default"][
0], ShouldResemble, t3) | 303 So(tqt.GetTransactionTasks()["default"][
0], ShouldResemble, t3) |
| 305 | 304 |
| 306 tqt.ResetTasks() | 305 tqt.ResetTasks() |
| 307 | 306 |
| 308 So(len(tqt.GetScheduledTasks()["default"
]), ShouldEqual, 0) | 307 So(len(tqt.GetScheduledTasks()["default"
]), ShouldEqual, 0) |
| 309 So(len(tqt.GetTombstonedTasks()["default
"]), ShouldEqual, 0) | 308 So(len(tqt.GetTombstonedTasks()["default
"]), ShouldEqual, 0) |
| 310 So(len(tqt.GetTransactionTasks()["defaul
t"]), ShouldEqual, 0) | 309 So(len(tqt.GetTransactionTasks()["defaul
t"]), ShouldEqual, 0) |
| 311 | 310 |
| 312 return nil | 311 return nil |
| 313 }, nil), ShouldBeNil) | 312 }, nil), ShouldBeNil) |
| 314 | 313 |
| 315 So(len(tqt.GetScheduledTasks()["default"]), Shou
ldEqual, 0) | 314 So(len(tqt.GetScheduledTasks()["default"]), Shou
ldEqual, 0) |
| 316 So(len(tqt.GetTombstonedTasks()["default"]), Sho
uldEqual, 0) | 315 So(len(tqt.GetTombstonedTasks()["default"]), Sho
uldEqual, 0) |
| 317 So(len(tqt.GetTransactionTasks()["default"]), Sh
ouldEqual, 0) | 316 So(len(tqt.GetTransactionTasks()["default"]), Sh
ouldEqual, 0) |
| 318 | 317 |
| 319 Convey("and reusing a closed context is bad time
s", func() { | 318 Convey("and reusing a closed context is bad time
s", func() { |
| 320 » » » » » So(ttq.Add(nil, "").Error(), ShouldConta
inSubstring, "expired") | 319 » » » » » So(tq.Add(txnCtx, "", nil).Error(), Shou
ldContainSubstring, "expired") |
| 321 }) | 320 }) |
| 322 }) | 321 }) |
| 323 | 322 |
| 324 Convey("you can AddMulti as well", func() { | 323 Convey("you can AddMulti as well", func() { |
| 325 » » » » So(dsS.Get(c).RunInTransaction(func(c context.Co
ntext) error { | 324 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 326 » » » » » tq := tqS.Get(c) | 325 » » » » » tqt := tq.GetTestable(c) |
| 327 » » » » » tqt := tq.Testable() | |
| 328 | 326 |
| 329 t.Name = "" | 327 t.Name = "" |
| 330 » » » » » tasks := []*tqS.Task{t.Duplicate(), t.Du
plicate(), t.Duplicate()} | 328 » » » » » tasks := []*tq.Task{t.Duplicate(), t.Dup
licate(), t.Duplicate()} |
| 331 » » » » » So(tq.AddMulti(tasks, ""), ShouldBeNil) | 329 » » » » » So(tq.Add(c, "", tasks...), ShouldBeNil) |
| 332 So(len(tqt.GetScheduledTasks()["default"
]), ShouldEqual, 1) | 330 So(len(tqt.GetScheduledTasks()["default"
]), ShouldEqual, 1) |
| 333 So(len(tqt.GetTransactionTasks()["defaul
t"]), ShouldEqual, 3) | 331 So(len(tqt.GetTransactionTasks()["defaul
t"]), ShouldEqual, 3) |
| 334 return nil | 332 return nil |
| 335 }, nil), ShouldBeNil) | 333 }, nil), ShouldBeNil) |
| 336 So(len(tqt.GetScheduledTasks()["default"]), Shou
ldEqual, 4) | 334 So(len(tqt.GetScheduledTasks()["default"]), Shou
ldEqual, 4) |
| 337 So(len(tqt.GetTransactionTasks()["default"]), Sh
ouldEqual, 0) | 335 So(len(tqt.GetTransactionTasks()["default"]), Sh
ouldEqual, 0) |
| 338 }) | 336 }) |
| 339 | 337 |
| 340 Convey("unless you add too many things", func() { | 338 Convey("unless you add too many things", func() { |
| 341 » » » » So(dsS.Get(c).RunInTransaction(func(c context.Co
ntext) error { | 339 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 342 for i := 0; i < 5; i++ { | 340 for i := 0; i < 5; i++ { |
| 343 » » » » » » So(tqS.Get(c).Add(t.Duplicate(),
""), ShouldBeNil) | 341 » » » » » » So(tq.Add(c, "", t.Duplicate()),
ShouldBeNil) |
| 344 } | 342 } |
| 345 » » » » » So(tqS.Get(c).Add(t, "").Error(), Should
ContainSubstring, "BAD_REQUEST") | 343 » » » » » So(tq.Add(c, "", t).Error(), ShouldConta
inSubstring, "BAD_REQUEST") |
| 346 return nil | 344 return nil |
| 347 }, nil), ShouldBeNil) | 345 }, nil), ShouldBeNil) |
| 348 }) | 346 }) |
| 349 | 347 |
| 350 Convey("unless you Add to a bad queue", func() { | 348 Convey("unless you Add to a bad queue", func() { |
| 351 » » » » So(dsS.Get(c).RunInTransaction(func(c context.Co
ntext) error { | 349 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 352 » » » » » So(tqS.Get(c).Add(t, "meat").Error(), Sh
ouldContainSubstring, "UNKNOWN_QUEUE") | 350 » » » » » So(tq.Add(c, "meat", t).Error(), ShouldC
ontainSubstring, "UNKNOWN_QUEUE") |
| 353 | 351 |
| 354 Convey("unless you add it!", func() { | 352 Convey("unless you add it!", func() { |
| 355 » » » » » » tqS.GetRaw(c).Testable().CreateQ
ueue("meat") | 353 » » » » » » tq.Raw(c).GetTestable().CreateQu
eue("meat") |
| 356 » » » » » » So(tqS.Get(c).Add(t, "meat"), Sh
ouldBeNil) | 354 » » » » » » So(tq.Add(c, "meat", t), ShouldB
eNil) |
| 357 }) | 355 }) |
| 358 | 356 |
| 359 return nil | 357 return nil |
| 360 }, nil), ShouldBeNil) | 358 }, nil), ShouldBeNil) |
| 361 }) | 359 }) |
| 362 | 360 |
| 363 Convey("No other features are available, however", func(
) { | 361 Convey("No other features are available, however", func(
) { |
| 364 » » » » So(dsS.Get(c).RunInTransaction(func(c context.Co
ntext) error { | 362 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 365 » » » » » So(tqS.Get(c).Delete(t, "").Error(), Sho
uldContainSubstring, "cannot DeleteMulti from a transaction") | 363 » » » » » So(tq.Delete(c, "", t).Error(), ShouldCo
ntainSubstring, "cannot DeleteMulti from a transaction") |
| 366 » » » » » So(tqS.Get(c).Purge("").Error(), ShouldC
ontainSubstring, "cannot Purge from a transaction") | 364 » » » » » So(tq.Purge(c, "").Error(), ShouldContai
nSubstring, "cannot Purge from a transaction") |
| 367 » » » » » _, err := tqS.Get(c).Stats("") | 365 » » » » » _, err := tq.Stats(c, "") |
| 368 So(err.Error(), ShouldContainSubstring,
"cannot Stats from a transaction") | 366 So(err.Error(), ShouldContainSubstring,
"cannot Stats from a transaction") |
| 369 return nil | 367 return nil |
| 370 }, nil), ShouldBeNil) | 368 }, nil), ShouldBeNil) |
| 371 }) | 369 }) |
| 372 | 370 |
| 373 Convey("can get the non-transactional taskqueue context
though", func() { | 371 Convey("can get the non-transactional taskqueue context
though", func() { |
| 374 » » » » So(dsS.Get(c).RunInTransaction(func(c context.Co
ntext) error { | 372 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 375 » » » » » So(tqS.GetNoTxn(c).Delete(t, ""), Should
BeNil) | 373 » » » » » noTxn := ds.WithoutTransaction(c) |
| 376 » » » » » So(tqS.GetNoTxn(c).Purge(""), ShouldBeNi
l) | 374 » » » » » So(tq.Delete(noTxn, "", t), ShouldBeNil) |
| 377 » » » » » _, err := tqS.GetNoTxn(c).Stats("") | 375 » » » » » So(tq.Purge(noTxn, ""), ShouldBeNil) |
| 376 » » » » » _, err := tq.Stats(noTxn, "") |
| 378 So(err, ShouldBeNil) | 377 So(err, ShouldBeNil) |
| 379 return nil | 378 return nil |
| 380 }, nil), ShouldBeNil) | 379 }, nil), ShouldBeNil) |
| 381 }) | 380 }) |
| 382 | 381 |
| 383 Convey("adding a new task only happens if we don't errou
t", func() { | 382 Convey("adding a new task only happens if we don't errou
t", func() { |
| 384 » » » » So(dsS.Get(c).RunInTransaction(func(c context.Co
ntext) error { | 383 » » » » So(ds.RunInTransaction(c, func(c context.Context
) error { |
| 385 » » » » » t3 := &tqS.Task{Path: "/sandwitch/victor
y"} | 384 » » » » » t3 := &tq.Task{Path: "/sandwitch/victory
"} |
| 386 » » » » » So(tqS.Get(c).Add(t3, ""), ShouldBeNil) | 385 » » » » » So(tq.Add(c, "", t3), ShouldBeNil) |
| 387 return fmt.Errorf("nooooo") | 386 return fmt.Errorf("nooooo") |
| 388 }, nil), ShouldErrLike, "nooooo") | 387 }, nil), ShouldErrLike, "nooooo") |
| 389 | 388 |
| 390 So(tqt.GetScheduledTasks()["default"][t.Name], S
houldResemble, t) | 389 So(tqt.GetScheduledTasks()["default"][t.Name], S
houldResemble, t) |
| 391 So(tqt.GetTombstonedTasks()["default"][t2.Name],
ShouldResemble, t2) | 390 So(tqt.GetTombstonedTasks()["default"][t2.Name],
ShouldResemble, t2) |
| 392 So(tqt.GetTransactionTasks()["default"], ShouldB
eNil) | 391 So(tqt.GetTransactionTasks()["default"], ShouldB
eNil) |
| 393 }) | 392 }) |
| 394 | 393 |
| 395 Convey("likewise, a panic doesn't schedule anything", fu
nc() { | 394 Convey("likewise, a panic doesn't schedule anything", fu
nc() { |
| 396 func() { | 395 func() { |
| 397 defer func() { _ = recover() }() | 396 defer func() { _ = recover() }() |
| 398 » » » » » So(dsS.Get(c).RunInTransaction(func(c co
ntext.Context) error { | 397 » » » » » So(ds.RunInTransaction(c, func(c context
.Context) error { |
| 399 » » » » » » tq := tqS.Get(c) | 398 » » » » » » So(tq.Add(c, "", &tq.Task{Path:
"/sandwitch/victory"}), ShouldBeNil) |
| 400 | |
| 401 » » » » » » So(tq.Add(&tqS.Task{Path: "/sand
witch/victory"}, ""), ShouldBeNil) | |
| 402 | 399 |
| 403 panic(fmt.Errorf("nooooo")) | 400 panic(fmt.Errorf("nooooo")) |
| 404 }, nil), ShouldBeNil) | 401 }, nil), ShouldBeNil) |
| 405 }() | 402 }() |
| 406 | 403 |
| 407 So(tqt.GetScheduledTasks()["default"][t.Name], S
houldResemble, t) | 404 So(tqt.GetScheduledTasks()["default"][t.Name], S
houldResemble, t) |
| 408 So(tqt.GetTombstonedTasks()["default"][t2.Name],
ShouldResemble, t2) | 405 So(tqt.GetTombstonedTasks()["default"][t2.Name],
ShouldResemble, t2) |
| 409 So(tqt.GetTransactionTasks()["default"], ShouldB
eNil) | 406 So(tqt.GetTransactionTasks()["default"], ShouldB
eNil) |
| 410 }) | 407 }) |
| 411 | 408 |
| 412 }) | 409 }) |
| 413 }) | 410 }) |
| 414 } | 411 } |
| OLD | NEW |