go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/cv/internal/changelist/model_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 changelist
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"testing"
    21  	"time"
    22  
    23  	"google.golang.org/protobuf/types/known/timestamppb"
    24  
    25  	"go.chromium.org/luci/common/clock/testclock"
    26  	gerritpb "go.chromium.org/luci/common/proto/gerrit"
    27  	"go.chromium.org/luci/gae/impl/memory"
    28  	"go.chromium.org/luci/gae/service/datastore"
    29  
    30  	"go.chromium.org/luci/cv/internal/common"
    31  
    32  	. "github.com/smartystreets/goconvey/convey"
    33  	. "go.chromium.org/luci/common/testing/assertions"
    34  )
    35  
    36  func TestCL(t *testing.T) {
    37  	t.Parallel()
    38  
    39  	Convey("CL", t, func() {
    40  		ctx := memory.Use(context.Background())
    41  		epoch := datastore.RoundTime(testclock.TestRecentTimeUTC)
    42  		ctx, _ = testclock.UseTime(ctx, testclock.TestRecentTimeUTC)
    43  
    44  		eid, err := GobID("x-review.example.com", 12)
    45  		So(err, ShouldBeNil)
    46  
    47  		Convey("ExternalID.Get returns nil if CL doesn't exist", func() {
    48  			cl, err := eid.Load(ctx)
    49  			So(err, ShouldBeNil)
    50  			So(cl, ShouldBeNil)
    51  		})
    52  
    53  		Convey("ExternalID.MustCreateIfNotExists creates a CL", func() {
    54  			cl := eid.MustCreateIfNotExists(ctx)
    55  			So(cl, ShouldNotBeNil)
    56  			So(cl.ExternalID, ShouldResemble, eid)
    57  			// ID must be autoset to non-0 value.
    58  			So(cl.ID, ShouldNotEqual, 0)
    59  			So(cl.EVersion, ShouldEqual, 1)
    60  			So(cl.UpdateTime, ShouldEqual, epoch)
    61  			So(cl.RetentionKey, ShouldEqual, fmt.Sprintf("%02d/%010d", cl.ID%retentionKeyShards, epoch.Unix()))
    62  
    63  			Convey("ExternalID.Get loads existing CL", func() {
    64  				cl2, err := eid.Load(ctx)
    65  				So(err, ShouldBeNil)
    66  				So(cl2.ID, ShouldEqual, cl.ID)
    67  				So(cl2.ExternalID, ShouldEqual, eid)
    68  				So(cl2.EVersion, ShouldEqual, 1)
    69  				So(cl2.UpdateTime, ShouldEqual, cl.UpdateTime)
    70  				So(cl2.Snapshot, ShouldResembleProto, cl.Snapshot)
    71  			})
    72  
    73  			Convey("ExternalID.MustCreateIfNotExists loads existing CL", func() {
    74  				cl3 := eid.MustCreateIfNotExists(ctx)
    75  				So(cl3, ShouldNotBeNil)
    76  				So(cl3.ID, ShouldEqual, cl.ID)
    77  				So(cl3.ExternalID, ShouldResemble, eid)
    78  				So(cl3.EVersion, ShouldEqual, 1)
    79  				So(cl3.UpdateTime, ShouldEqual, cl.UpdateTime)
    80  				So(cl3.Snapshot, ShouldResembleProto, cl.Snapshot)
    81  			})
    82  
    83  			Convey("Delete works", func() {
    84  				err := Delete(ctx, cl.ID)
    85  				So(err, ShouldBeNil)
    86  				// Verify.
    87  				So(datastore.Get(ctx, cl), ShouldResemble, datastore.ErrNoSuchEntity)
    88  				cl2, err2 := eid.Load(ctx)
    89  				So(err2, ShouldBeNil)
    90  				So(cl2, ShouldBeNil)
    91  
    92  				Convey("delete is now a noop", func() {
    93  					err := Delete(ctx, cl.ID)
    94  					So(err, ShouldBeNil)
    95  				})
    96  			})
    97  		})
    98  	})
    99  }
   100  
   101  func TestLookup(t *testing.T) {
   102  	t.Parallel()
   103  
   104  	Convey("Lookup works", t, func() {
   105  		ctx := memory.Use(context.Background())
   106  
   107  		const n = 10
   108  		ids := make([]common.CLID, n)
   109  		eids := make([]ExternalID, n)
   110  		for i := range eids {
   111  			eids[i] = MustGobID("x-review.example.com", int64(i+1))
   112  			if i%2 == 0 {
   113  				ids[i] = eids[i].MustCreateIfNotExists(ctx).ID
   114  			}
   115  		}
   116  
   117  		actual, err := Lookup(ctx, eids)
   118  		So(err, ShouldBeNil)
   119  		So(actual, ShouldResemble, ids)
   120  	})
   121  }
   122  
   123  func makeSnapshot(luciProject string, updatedTime time.Time) *Snapshot {
   124  	return &Snapshot{
   125  		ExternalUpdateTime: timestamppb.New(updatedTime),
   126  		Kind: &Snapshot_Gerrit{Gerrit: &Gerrit{
   127  			Info: &gerritpb.ChangeInfo{
   128  				CurrentRevision: "deadbeef",
   129  				Revisions: map[string]*gerritpb.RevisionInfo{
   130  					"deadbeef": {
   131  						Number: 1,
   132  						Kind:   gerritpb.RevisionInfo_REWORK,
   133  					},
   134  				},
   135  			},
   136  		}},
   137  		MinEquivalentPatchset: 1,
   138  		Patchset:              2,
   139  		LuciProject:           luciProject,
   140  	}
   141  }