go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/cv/internal/run/impl/util/gerrit_test.go (about) 1 // Copyright 2021 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 util 16 17 import ( 18 "fmt" 19 "testing" 20 "time" 21 22 gerritpb "go.chromium.org/luci/common/proto/gerrit" 23 "go.chromium.org/luci/gae/service/datastore" 24 "google.golang.org/protobuf/proto" 25 "google.golang.org/protobuf/types/known/timestamppb" 26 27 "go.chromium.org/luci/cv/internal/changelist" 28 "go.chromium.org/luci/cv/internal/common" 29 "go.chromium.org/luci/cv/internal/cvtesting" 30 gf "go.chromium.org/luci/cv/internal/gerrit/gerritfake" 31 "go.chromium.org/luci/cv/internal/run" 32 33 . "github.com/smartystreets/goconvey/convey" 34 ) 35 36 func TestIsActionTakenOnGerritCL(t *testing.T) { 37 t.Parallel() 38 39 Convey("IsActionTakenOnGerritCL works", t, func() { 40 ct := cvtesting.Test{} 41 ctx, cancel := ct.SetUp(t) 42 defer cancel() 43 44 const ( 45 lProject = "infra" 46 gHost = "g-review.example.com" 47 gChange = 1111 48 ) 49 var runID = common.MakeRunID(lProject, ct.Clock.Now(), 1, []byte("deadbeef")) 50 51 // CL is on PS#2 in Gerrit while PS#1 in datastore 52 ciInCV := gf.CI(gChange, gf.PS(1)) 53 revisionInCV := ciInCV.GetCurrentRevision() 54 cl := changelist.MustGobID(gHost, gChange).MustCreateIfNotExists(ctx) 55 cl.Snapshot = &changelist.Snapshot{ 56 Kind: &changelist.Snapshot_Gerrit{Gerrit: &changelist.Gerrit{ 57 Host: gHost, 58 Info: ciInCV, 59 }}, 60 ExternalUpdateTime: timestamppb.New(ct.Clock.Now().Add(-1 * time.Minute)), 61 } 62 cl.EVersion++ 63 rcl := &run.RunCL{ 64 ID: cl.ID, 65 ExternalID: cl.ExternalID, 66 IndexedID: cl.ID, 67 Run: datastore.MakeKey(ctx, common.RunKind, string(runID)), 68 Detail: cl.Snapshot, 69 } 70 So(datastore.Put(ctx, cl, rcl), ShouldBeNil) 71 72 ciInGerrit := proto.Clone(ciInCV).(*gerritpb.ChangeInfo) 73 gf.PS(2)(ciInGerrit) 74 revisionInGerrit := ciInGerrit.GetCurrentRevision() 75 ct.GFake.AddFrom(gf.WithCIs(gHost, gf.ACLRestricted(lProject), ciInGerrit)) 76 77 Convey("Action already taken for CL in CV", func() { 78 expectedActionTime := ct.Clock.Now().Add(-3 * time.Minute) 79 80 actionTime, err := IsActionTakenOnGerritCL(ctx, ct.GFake, rcl, 81 []gerritpb.QueryOption{gerritpb.QueryOption_CURRENT_REVISION}, 82 func(rcl *run.RunCL, ci *gerritpb.ChangeInfo) time.Time { 83 So(ci.GetCurrentRevision(), ShouldEqual, revisionInCV) 84 return expectedActionTime 85 }) 86 So(err, ShouldBeNil) 87 So(actionTime, ShouldEqual, expectedActionTime) 88 }) 89 90 Convey("Action taken for CL in Gerrit", func() { 91 expectedActionTime := ct.Clock.Now().Add(-1 * time.Minute) 92 93 actionTime, err := IsActionTakenOnGerritCL(ctx, ct.GFake, rcl, 94 []gerritpb.QueryOption{gerritpb.QueryOption_CURRENT_REVISION}, 95 func(rcl *run.RunCL, ci *gerritpb.ChangeInfo) time.Time { 96 switch ci.GetCurrentRevision() { 97 case revisionInCV: 98 return time.Time{} 99 case revisionInGerrit: 100 return expectedActionTime 101 default: 102 panic(fmt.Errorf("impossible revision %s", ci.GetCurrentRevision())) 103 } 104 }) 105 So(err, ShouldBeNil) 106 So(actionTime, ShouldEqual, expectedActionTime) 107 }) 108 109 Convey("Action not even taken for CL in Gerrit", func() { 110 actionTime, err := IsActionTakenOnGerritCL(ctx, ct.GFake, rcl, 111 []gerritpb.QueryOption{gerritpb.QueryOption_CURRENT_REVISION}, 112 func(rcl *run.RunCL, ci *gerritpb.ChangeInfo) time.Time { 113 switch ci.GetCurrentRevision() { 114 case revisionInCV: 115 return time.Time{} 116 case revisionInGerrit: 117 return time.Time{} 118 default: 119 panic(fmt.Errorf("impossible revision %s", ci.GetCurrentRevision())) 120 } 121 }) 122 So(err, ShouldBeNil) 123 So(actionTime.IsZero(), ShouldBeTrue) 124 }) 125 126 Convey("Don't go to Gerrit if CL is refreshed recently", func() { 127 cl.Snapshot.ExternalUpdateTime = timestamppb.New(ct.Clock.Now().Add(-StaleCLAgeThreshold / 2)) 128 So(datastore.Put(ctx, cl), ShouldBeNil) 129 130 actionTime, err := IsActionTakenOnGerritCL(ctx, ct.GFake, rcl, 131 []gerritpb.QueryOption{gerritpb.QueryOption_CURRENT_REVISION}, 132 func(rcl *run.RunCL, ci *gerritpb.ChangeInfo) time.Time { 133 So(ci.GetCurrentRevision(), ShouldEqual, revisionInCV) 134 return time.Time{} 135 }) 136 So(err, ShouldBeNil) 137 So(actionTime.IsZero(), ShouldBeTrue) 138 }) 139 140 }) 141 }