go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/buildbucket/appengine/tasks/tasks_test.go (about) 1 // Copyright 2020 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package tasks 16 17 import ( 18 "context" 19 "testing" 20 "time" 21 22 "go.chromium.org/luci/gae/filter/txndefer" 23 "go.chromium.org/luci/gae/impl/memory" 24 "go.chromium.org/luci/gae/service/datastore" 25 "go.chromium.org/luci/server/tq" 26 27 taskdef "go.chromium.org/luci/buildbucket/appengine/tasks/defs" 28 29 . "github.com/smartystreets/goconvey/convey" 30 . "go.chromium.org/luci/common/testing/assertions" 31 ) 32 33 func TestTasks(t *testing.T) { 34 t.Parallel() 35 36 Convey("tasks", t, func() { 37 ctx := txndefer.FilterRDS(memory.Use(context.Background())) 38 datastore.GetTestable(ctx).AutoIndex(true) 39 datastore.GetTestable(ctx).Consistent(true) 40 41 ctx, sch := tq.TestingContext(ctx, nil) 42 43 Convey("CancelSwarmingTask", func() { 44 Convey("invalid", func() { 45 Convey("nil", func() { 46 So(CancelSwarmingTask(ctx, nil), ShouldErrLike, "hostname is required") 47 So(sch.Tasks(), ShouldBeEmpty) 48 }) 49 50 Convey("empty", func() { 51 task := &taskdef.CancelSwarmingTaskGo{} 52 So(CancelSwarmingTask(ctx, task), ShouldErrLike, "hostname is required") 53 So(sch.Tasks(), ShouldBeEmpty) 54 }) 55 56 Convey("hostname", func() { 57 task := &taskdef.CancelSwarmingTaskGo{ 58 TaskId: "id", 59 } 60 So(CancelSwarmingTask(ctx, task), ShouldErrLike, "hostname is required") 61 So(sch.Tasks(), ShouldBeEmpty) 62 }) 63 64 Convey("task id", func() { 65 task := &taskdef.CancelSwarmingTaskGo{ 66 Hostname: "example.com", 67 } 68 So(CancelSwarmingTask(ctx, task), ShouldErrLike, "task_id is required") 69 So(sch.Tasks(), ShouldBeEmpty) 70 }) 71 }) 72 73 Convey("valid", func() { 74 Convey("empty realm", func() { 75 task := &taskdef.CancelSwarmingTaskGo{ 76 Hostname: "example.com", 77 TaskId: "id", 78 } 79 So(datastore.RunInTransaction(ctx, func(ctx context.Context) error { 80 return CancelSwarmingTask(ctx, task) 81 }, nil), ShouldBeNil) 82 So(sch.Tasks(), ShouldHaveLength, 1) 83 }) 84 85 Convey("non-empty realm", func() { 86 task := &taskdef.CancelSwarmingTaskGo{ 87 Hostname: "example.com", 88 TaskId: "id", 89 Realm: "realm", 90 } 91 So(datastore.RunInTransaction(ctx, func(ctx context.Context) error { 92 return CancelSwarmingTask(ctx, task) 93 }, nil), ShouldBeNil) 94 So(sch.Tasks(), ShouldHaveLength, 1) 95 }) 96 }) 97 }) 98 99 Convey("CreateSwarmingTask", func() { 100 Convey("invalid", func() { 101 Convey("nil", func() { 102 So(CreateSwarmingTask(ctx, nil), ShouldErrLike, "build_id is required") 103 So(sch.Tasks(), ShouldBeEmpty) 104 }) 105 106 Convey("empty", func() { 107 task := &taskdef.CreateSwarmingTask{} 108 So(CreateSwarmingTask(ctx, task), ShouldErrLike, "build_id is required") 109 So(sch.Tasks(), ShouldBeEmpty) 110 }) 111 112 Convey("zero", func() { 113 task := &taskdef.CreateSwarmingTask{ 114 BuildId: 0, 115 } 116 So(CreateSwarmingTask(ctx, task), ShouldErrLike, "build_id is required") 117 So(sch.Tasks(), ShouldBeEmpty) 118 }) 119 }) 120 121 Convey("valid", func() { 122 task := &taskdef.CreateSwarmingTask{ 123 BuildId: 1, 124 } 125 So(datastore.RunInTransaction(ctx, func(ctx context.Context) error { 126 return CreateSwarmingTask(ctx, task) 127 }, nil), ShouldBeNil) 128 So(sch.Tasks(), ShouldHaveLength, 1) 129 }) 130 }) 131 132 Convey("ExportBigQuery", func() { 133 Convey("invalid", func() { 134 135 Convey("zero", func() { 136 137 So(ExportBigQuery(ctx, 0, false), ShouldErrLike, "build_id is invalid") 138 So(sch.Tasks(), ShouldBeEmpty) 139 }) 140 }) 141 142 Convey("valid - to python", func() { 143 So(datastore.RunInTransaction(ctx, func(ctx context.Context) error { 144 return ExportBigQuery(ctx, 1, false) 145 }, nil), ShouldBeNil) 146 So(sch.Tasks(), ShouldHaveLength, 1) 147 So(sch.Tasks().Payloads()[0], ShouldResembleProto, &taskdef.ExportBigQuery{ 148 BuildId: 1, 149 }) 150 }) 151 152 Convey("valid - to Go", func() { 153 So(datastore.RunInTransaction(ctx, func(ctx context.Context) error { 154 return ExportBigQuery(ctx, 1, true) 155 }, nil), ShouldBeNil) 156 So(sch.Tasks(), ShouldHaveLength, 1) 157 So(sch.Tasks().Payloads()[0], ShouldResembleProto, &taskdef.ExportBigQueryGo{ 158 BuildId: 1, 159 }) 160 }) 161 }) 162 163 Convey("FinalizeResultDB", func() { 164 Convey("invalid", func() { 165 Convey("nil", func() { 166 So(FinalizeResultDB(ctx, nil), ShouldErrLike, "build_id is required") 167 So(sch.Tasks(), ShouldBeEmpty) 168 }) 169 170 Convey("empty", func() { 171 task := &taskdef.FinalizeResultDBGo{} 172 So(FinalizeResultDB(ctx, task), ShouldErrLike, "build_id is required") 173 So(sch.Tasks(), ShouldBeEmpty) 174 }) 175 176 Convey("zero", func() { 177 task := &taskdef.FinalizeResultDBGo{ 178 BuildId: 0, 179 } 180 So(FinalizeResultDB(ctx, task), ShouldErrLike, "build_id is required") 181 So(sch.Tasks(), ShouldBeEmpty) 182 }) 183 }) 184 185 Convey("valid", func() { 186 task := &taskdef.FinalizeResultDBGo{ 187 BuildId: 1, 188 } 189 So(datastore.RunInTransaction(ctx, func(ctx context.Context) error { 190 return FinalizeResultDB(ctx, task) 191 }, nil), ShouldBeNil) 192 So(sch.Tasks(), ShouldHaveLength, 1) 193 }) 194 }) 195 196 Convey("NotifyPubSub", func() { 197 Convey("invalid", func() { 198 Convey("nil", func() { 199 So(notifyPubSub(ctx, nil), ShouldErrLike, "build_id is required") 200 So(sch.Tasks(), ShouldBeEmpty) 201 }) 202 203 Convey("empty", func() { 204 task := &taskdef.NotifyPubSub{} 205 So(notifyPubSub(ctx, task), ShouldErrLike, "build_id is required") 206 So(sch.Tasks(), ShouldBeEmpty) 207 }) 208 209 Convey("zero", func() { 210 task := &taskdef.NotifyPubSub{ 211 BuildId: 0, 212 } 213 So(notifyPubSub(ctx, task), ShouldErrLike, "build_id is required") 214 So(sch.Tasks(), ShouldBeEmpty) 215 }) 216 }) 217 218 Convey("valid", func() { 219 task := &taskdef.NotifyPubSub{ 220 BuildId: 1, 221 Callback: true, 222 } 223 So(datastore.RunInTransaction(ctx, func(ctx context.Context) error { 224 return notifyPubSub(ctx, task) 225 }, nil), ShouldBeNil) 226 So(sch.Tasks(), ShouldHaveLength, 1) 227 }) 228 }) 229 230 Convey("CreateSwarmingBuildTask", func() { 231 Convey("invalid", func() { 232 Convey("nil", func() { 233 So(CreateSwarmingBuildTask(ctx, nil), ShouldErrLike, "build_id is required") 234 So(sch.Tasks(), ShouldBeEmpty) 235 }) 236 237 Convey("empty", func() { 238 task := &taskdef.CreateSwarmingBuildTask{} 239 So(CreateSwarmingBuildTask(ctx, task), ShouldErrLike, "build_id is required") 240 So(sch.Tasks(), ShouldBeEmpty) 241 }) 242 243 Convey("zero", func() { 244 task := &taskdef.CreateSwarmingBuildTask{ 245 BuildId: 0, 246 } 247 So(CreateSwarmingBuildTask(ctx, task), ShouldErrLike, "build_id is required") 248 So(sch.Tasks(), ShouldBeEmpty) 249 }) 250 }) 251 252 Convey("valid", func() { 253 task := &taskdef.CreateSwarmingBuildTask{ 254 BuildId: 1, 255 } 256 So(datastore.RunInTransaction(ctx, func(ctx context.Context) error { 257 return CreateSwarmingBuildTask(ctx, task) 258 }, nil), ShouldBeNil) 259 So(sch.Tasks(), ShouldHaveLength, 1) 260 }) 261 }) 262 263 Convey("SyncSwarmingBuildTask", func() { 264 Convey("invalid", func() { 265 Convey("nil", func() { 266 So(SyncSwarmingBuildTask(ctx, nil, time.Second), ShouldErrLike, "build_id is required") 267 So(sch.Tasks(), ShouldBeEmpty) 268 }) 269 270 Convey("empty", func() { 271 task := &taskdef.SyncSwarmingBuildTask{} 272 So(SyncSwarmingBuildTask(ctx, task, time.Second), ShouldErrLike, "build_id is required") 273 So(sch.Tasks(), ShouldBeEmpty) 274 }) 275 276 Convey("zero generation", func() { 277 task := &taskdef.SyncSwarmingBuildTask{ 278 BuildId: 123, 279 Generation: 0, 280 } 281 So(SyncSwarmingBuildTask(ctx, task, time.Second), ShouldErrLike, "generation should be larger than 0") 282 So(sch.Tasks(), ShouldBeEmpty) 283 }) 284 }) 285 286 Convey("valid", func() { 287 task := &taskdef.SyncSwarmingBuildTask{ 288 BuildId: 123, 289 Generation: 1, 290 } 291 So(SyncSwarmingBuildTask(ctx, task, time.Second), ShouldBeNil) 292 So(sch.Tasks(), ShouldHaveLength, 1) 293 }) 294 }) 295 296 Convey("SyncWithBackend", func() { 297 Convey("invalid", func() { 298 Convey("empty backend", func() { 299 So(SyncWithBackend(ctx, "", "project"), ShouldErrLike, "backend is required") 300 So(sch.Tasks(), ShouldBeEmpty) 301 }) 302 303 Convey("empty project", func() { 304 So(SyncWithBackend(ctx, "backend", ""), ShouldErrLike, "project is required") 305 So(sch.Tasks(), ShouldBeEmpty) 306 }) 307 }) 308 309 Convey("valid", func() { 310 So(SyncWithBackend(ctx, "backend", "project"), ShouldBeNil) 311 So(sch.Tasks(), ShouldHaveLength, 1) 312 }) 313 }) 314 315 Convey("CancelBackendTask", func() { 316 Convey("invalid", func() { 317 Convey("empty target", func() { 318 So(CancelBackendTask(ctx, &taskdef.CancelBackendTask{ 319 Project: "project", 320 TaskId: "123", 321 }), ShouldErrLike, "target is required") 322 }) 323 324 Convey("empty task_id", func() { 325 So(CancelBackendTask(ctx, &taskdef.CancelBackendTask{ 326 Project: "project", 327 Target: "123", 328 }), ShouldErrLike, "task_id is required") 329 }) 330 Convey("invalid project", func() { 331 So(CancelBackendTask(ctx, &taskdef.CancelBackendTask{ 332 TaskId: "123", 333 Target: "123", 334 }), ShouldErrLike, "project is required") 335 }) 336 }) 337 338 Convey("valid", func() { 339 So(CancelBackendTask(ctx, &taskdef.CancelBackendTask{ 340 Target: "abc", 341 TaskId: "123", 342 Project: "project", 343 }), ShouldBeNil) 344 So(sch.Tasks(), ShouldHaveLength, 1) 345 }) 346 }) 347 348 Convey("CheckBuildLiveness", func() { 349 Convey("invalid", func() { 350 Convey("build id", func() { 351 So(CheckBuildLiveness(ctx, 0, 0, time.Duration(1)), ShouldErrLike, "build_id is invalid") 352 So(sch.Tasks(), ShouldBeEmpty) 353 }) 354 }) 355 356 Convey("valid", func() { 357 So(datastore.RunInTransaction(ctx, func(ctx context.Context) error { 358 return CheckBuildLiveness(ctx, 123, 60, time.Duration(1)) 359 }, nil), ShouldBeNil) 360 So(sch.Tasks(), ShouldHaveLength, 1) 361 }) 362 }) 363 }) 364 }