blob: ad7ce79ed546f1ac915b12060f2c1056022ca25d [file] [log] [blame]
// Copyright 2021 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package util
import (
"fmt"
"testing"
"time"
gerritpb "go.chromium.org/luci/common/proto/gerrit"
"go.chromium.org/luci/gae/service/datastore"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/timestamppb"
"go.chromium.org/luci/cv/internal/changelist"
"go.chromium.org/luci/cv/internal/common"
"go.chromium.org/luci/cv/internal/cvtesting"
gf "go.chromium.org/luci/cv/internal/gerrit/gerritfake"
"go.chromium.org/luci/cv/internal/run"
. "github.com/smartystreets/goconvey/convey"
)
func TestIsActionTakenOnGerritCL(t *testing.T) {
t.Parallel()
Convey("IsActionTakenOnGerritCL works", t, func() {
ct := cvtesting.Test{}
ctx, cancel := ct.SetUp()
defer cancel()
const (
lProject = "infra"
gHost = "g-review.example.com"
gChange = 1111
)
var runID = common.MakeRunID(lProject, ct.Clock.Now(), 1, []byte("deadbeef"))
// CL is on PS#2 in Gerrit while PS#1 in datastore
ciInCV := gf.CI(gChange, gf.PS(1))
revisionInCV := ciInCV.GetCurrentRevision()
cl := changelist.MustGobID(gHost, gChange).MustCreateIfNotExists(ctx)
cl.Snapshot = &changelist.Snapshot{
Kind: &changelist.Snapshot_Gerrit{Gerrit: &changelist.Gerrit{
Host: gHost,
Info: ciInCV,
}},
ExternalUpdateTime: timestamppb.New(ct.Clock.Now().Add(-1 * time.Minute)),
}
cl.EVersion++
rcl := &run.RunCL{
ID: cl.ID,
ExternalID: cl.ExternalID,
IndexedID: cl.ID,
Run: datastore.MakeKey(ctx, common.RunKind, string(runID)),
Detail: cl.Snapshot,
}
So(datastore.Put(ctx, cl, rcl), ShouldBeNil)
ciInGerrit := proto.Clone(ciInCV).(*gerritpb.ChangeInfo)
gf.PS(2)(ciInGerrit)
revisionInGerrit := ciInGerrit.GetCurrentRevision()
ct.GFake.AddFrom(gf.WithCIs(gHost, gf.ACLRestricted(lProject), ciInGerrit))
Convey("Action already taken for CL in CV", func() {
expectedActionTime := ct.Clock.Now().Add(-3 * time.Minute)
actionTime, err := IsActionTakenOnGerritCL(ctx, ct.GFake, rcl,
[]gerritpb.QueryOption{gerritpb.QueryOption_CURRENT_REVISION},
func(rcl *run.RunCL, ci *gerritpb.ChangeInfo) time.Time {
So(ci.GetCurrentRevision(), ShouldEqual, revisionInCV)
return expectedActionTime
})
So(err, ShouldBeNil)
So(actionTime, ShouldEqual, expectedActionTime)
})
Convey("Action taken for CL in Gerrit", func() {
expectedActionTime := ct.Clock.Now().Add(-1 * time.Minute)
actionTime, err := IsActionTakenOnGerritCL(ctx, ct.GFake, rcl,
[]gerritpb.QueryOption{gerritpb.QueryOption_CURRENT_REVISION},
func(rcl *run.RunCL, ci *gerritpb.ChangeInfo) time.Time {
switch ci.GetCurrentRevision() {
case revisionInCV:
return time.Time{}
case revisionInGerrit:
return expectedActionTime
default:
panic(fmt.Errorf("impossible revision %s", ci.GetCurrentRevision()))
}
})
So(err, ShouldBeNil)
So(actionTime, ShouldEqual, expectedActionTime)
})
Convey("Action not even taken for CL in Gerrit", func() {
actionTime, err := IsActionTakenOnGerritCL(ctx, ct.GFake, rcl,
[]gerritpb.QueryOption{gerritpb.QueryOption_CURRENT_REVISION},
func(rcl *run.RunCL, ci *gerritpb.ChangeInfo) time.Time {
switch ci.GetCurrentRevision() {
case revisionInCV:
return time.Time{}
case revisionInGerrit:
return time.Time{}
default:
panic(fmt.Errorf("impossible revision %s", ci.GetCurrentRevision()))
}
})
So(err, ShouldBeNil)
So(actionTime.IsZero(), ShouldBeTrue)
})
Convey("Don't go to Gerrit if CL is refreshed recently", func() {
cl.Snapshot.ExternalUpdateTime = timestamppb.New(ct.Clock.Now().Add(-StaleCLAgeThreshold / 2))
So(datastore.Put(ctx, cl), ShouldBeNil)
actionTime, err := IsActionTakenOnGerritCL(ctx, ct.GFake, rcl,
[]gerritpb.QueryOption{gerritpb.QueryOption_CURRENT_REVISION},
func(rcl *run.RunCL, ci *gerritpb.ChangeInfo) time.Time {
So(ci.GetCurrentRevision(), ShouldEqual, revisionInCV)
return time.Time{}
})
So(err, ShouldBeNil)
So(actionTime.IsZero(), ShouldBeTrue)
})
})
}