go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/cv/internal/run/rdb/notifier_test.go (about) 1 // Copyright 2023 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 rdb 16 17 import ( 18 "context" 19 "testing" 20 "time" 21 22 "github.com/golang/mock/gomock" 23 . "github.com/smartystreets/goconvey/convey" 24 "google.golang.org/grpc/codes" 25 "google.golang.org/protobuf/types/known/emptypb" 26 27 "go.chromium.org/luci/common/proto" 28 . "go.chromium.org/luci/common/testing/assertions" 29 "go.chromium.org/luci/cv/internal/common" 30 "go.chromium.org/luci/cv/internal/cvtesting" 31 "go.chromium.org/luci/cv/internal/run" 32 "go.chromium.org/luci/cv/internal/tryjob" 33 34 bpb "go.chromium.org/luci/buildbucket/proto" 35 "go.chromium.org/luci/gae/service/datastore" 36 "go.chromium.org/luci/grpc/appstatus" 37 rdbpb "go.chromium.org/luci/resultdb/proto/v1" 38 "go.chromium.org/luci/server/tq/tqtesting" 39 ) 40 41 func TestNotifier(t *testing.T) { 42 43 Convey(`MarkInvocationSubmitted`, t, func() { 44 ct := cvtesting.Test{} 45 ctx, cancel := ct.SetUp(t) 46 defer cancel() 47 48 mcf := NewMockRecorderClientFactory(ct.GoMockCtl) 49 notifier := NewNotifier(ct.TQDispatcher, mcf) 50 51 epoch := ct.Clock.Now().UTC() 52 runID := common.MakeRunID("infra", epoch, 1, []byte("aaa")) 53 54 r := &run.Run{ 55 ID: common.RunID(runID), 56 Status: run.Status_SUCCEEDED, 57 CreateTime: epoch, 58 StartTime: epoch.Add(time.Minute * 2), 59 EndTime: epoch.Add(time.Minute * 25), 60 Mode: run.FullRun, 61 Tryjobs: &run.Tryjobs{ 62 State: &tryjob.ExecutionState{ 63 Executions: []*tryjob.ExecutionState_Execution{ 64 { 65 Attempts: []*tryjob.ExecutionState_Execution_Attempt{ 66 { 67 ExternalId: string(tryjob.MustBuildbucketID("cr-buildbucket.appspot.com", 100004)), 68 Status: tryjob.Status_ENDED, 69 Reused: true, 70 Result: &tryjob.Result{ 71 Backend: &tryjob.Result_Buildbucket_{ 72 Buildbucket: &tryjob.Result_Buildbucket{ 73 Infra: &bpb.BuildInfra{ 74 Resultdb: &bpb.BuildInfra_ResultDB{ 75 Hostname: "resultdb.example.com", 76 Invocation: "invocations/build:12345", 77 }, 78 }, 79 }, 80 }, 81 }, 82 }, 83 { 84 ExternalId: string(tryjob.MustBuildbucketID("cr-buildbucket.appspot.com", 100005)), 85 Status: tryjob.Status_ENDED, 86 Result: &tryjob.Result{ 87 Backend: &tryjob.Result_Buildbucket_{ 88 Buildbucket: &tryjob.Result_Buildbucket{ 89 Infra: &bpb.BuildInfra{ 90 Resultdb: &bpb.BuildInfra_ResultDB{ 91 Hostname: "resultdb.example.com", 92 Invocation: "invocations/build:67890", 93 }, 94 }, 95 }, 96 }, 97 }, 98 }, 99 }, 100 }, 101 }, 102 Status: tryjob.ExecutionState_SUCCEEDED, 103 }, 104 }, 105 } 106 So(datastore.Put(ctx, r), ShouldBeNil) 107 108 Convey(`Permission Denied`, func() { 109 mcf.mc.EXPECT().MarkInvocationSubmitted(gomock.Any(), proto.MatcherEqual(&rdbpb.MarkInvocationSubmittedRequest{ 110 Invocation: "invocations/build:12345", 111 })).Return(&emptypb.Empty{}, appstatus.Error(codes.PermissionDenied, "permission denied")) 112 mcf.mc.EXPECT().MarkInvocationSubmitted(gomock.Any(), proto.MatcherEqual(&rdbpb.MarkInvocationSubmittedRequest{ 113 Invocation: "invocations/build:67890", 114 })).Return(&emptypb.Empty{}, appstatus.Error(codes.PermissionDenied, "permission denied")) 115 116 err := MarkInvocationSubmitted(ctx, mcf, runID) 117 So(err, ShouldErrLike, "failed to mark invocation submitted") 118 }) 119 120 Convey(`Valid`, func() { 121 mcf.mc.EXPECT().MarkInvocationSubmitted(gomock.Any(), proto.MatcherEqual(&rdbpb.MarkInvocationSubmittedRequest{ 122 Invocation: "invocations/build:12345", 123 })).Return(&emptypb.Empty{}, nil) 124 mcf.mc.EXPECT().MarkInvocationSubmitted(gomock.Any(), proto.MatcherEqual(&rdbpb.MarkInvocationSubmittedRequest{ 125 Invocation: "invocations/build:67890", 126 })).Return(&emptypb.Empty{}, nil) 127 128 err := datastore.RunInTransaction(ctx, func(ctx context.Context) error { 129 return notifier.Schedule(ctx, runID) 130 }, nil) 131 So(err, ShouldBeNil) 132 133 So(ct.TQ.Tasks(), ShouldHaveLength, 1) 134 ct.TQ.Run(ctx, tqtesting.StopAfterTask(notifierTaskClass)) 135 }) 136 }) 137 }