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  }