| 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 | 
|---|