go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/analysis/internal/testresults/gerritchangelists/fetch_owner_kinds_test.go (about)

     1  // Copyright 2022 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 gerritchangelists
    16  
    17  import (
    18  	"testing"
    19  	"time"
    20  
    21  	gerritpb "go.chromium.org/luci/common/proto/gerrit"
    22  	rdbpb "go.chromium.org/luci/resultdb/proto/v1"
    23  	"go.chromium.org/luci/server/span"
    24  
    25  	"go.chromium.org/luci/analysis/internal/gerrit"
    26  	"go.chromium.org/luci/analysis/internal/testutil"
    27  	"go.chromium.org/luci/analysis/pbutil"
    28  	pb "go.chromium.org/luci/analysis/proto/v1"
    29  
    30  	. "github.com/smartystreets/goconvey/convey"
    31  	. "go.chromium.org/luci/common/testing/assertions"
    32  )
    33  
    34  func TestPopulateOwnerKinds(t *testing.T) {
    35  	Convey("PopulateOwnerKinds", t, func() {
    36  		ctx := testutil.IntegrationTestContext(t)
    37  
    38  		clsByHost := make(map[string][]*gerritpb.ChangeInfo)
    39  		clsByHost["chromium-review.googlesource.com"] = []*gerritpb.ChangeInfo{
    40  			{
    41  				Number: 111,
    42  				Owner: &gerritpb.AccountInfo{
    43  					Email: "username@chromium.org",
    44  				},
    45  				Project: "chromium/src",
    46  			},
    47  		}
    48  
    49  		ctx = gerrit.UseFakeClient(ctx, clsByHost)
    50  
    51  		sources := make(map[string]*rdbpb.Sources)
    52  		sources["sources-1"] = &rdbpb.Sources{
    53  			GitilesCommit: &rdbpb.GitilesCommit{
    54  				Host:       "chromium.googlesource.com",
    55  				Project:    "chromium/src",
    56  				Ref:        "refs/heads/main",
    57  				CommitHash: "aa11bb22cc33dd44ee55aa11bb22cc33dd44ee55",
    58  				Position:   123,
    59  			},
    60  			Changelists: []*rdbpb.GerritChange{
    61  				{
    62  					Host:     "chromium-review.googlesource.com",
    63  					Project:  "chromium/src",
    64  					Change:   111,
    65  					Patchset: 3,
    66  				},
    67  			},
    68  		}
    69  
    70  		expectedSources := make(map[string]*pb.Sources)
    71  		expectedSources["sources-1"] = pbutil.SourcesFromResultDB(sources["sources-1"])
    72  		expectedSources["sources-1"].Changelists[0].OwnerKind = pb.ChangelistOwnerKind_HUMAN
    73  
    74  		expectedChangelists := []*GerritChangelist{
    75  			{
    76  				Project:   "testproject",
    77  				Host:      "chromium-review.googlesource.com",
    78  				Change:    111,
    79  				OwnerKind: pb.ChangelistOwnerKind_HUMAN,
    80  			},
    81  		}
    82  
    83  		Convey("With human CL author", func() {
    84  			augmentedSources, err := PopulateOwnerKinds(ctx, "testproject", sources)
    85  			So(err, ShouldBeNil)
    86  			So(augmentedSources, ShouldResembleProto, expectedSources)
    87  
    88  			// Verify cache record was created.
    89  			cls, err := ReadAll(span.Single(ctx))
    90  			So(err, ShouldBeNil)
    91  			So(removeCreationTimestamps(cls), ShouldResemble, expectedChangelists)
    92  		})
    93  		Convey("With automation CL author", func() {
    94  			clsByHost["chromium-review.googlesource.com"][0].Owner.Email = "robot@chromium.gserviceaccount.com"
    95  
    96  			augmentedSources, err := PopulateOwnerKinds(ctx, "testproject", sources)
    97  			So(err, ShouldBeNil)
    98  			expectedSources["sources-1"].Changelists[0].OwnerKind = pb.ChangelistOwnerKind_AUTOMATION
    99  			So(augmentedSources, ShouldResembleProto, expectedSources)
   100  
   101  			// Verify cache record was created.
   102  			cls, err := ReadAll(span.Single(ctx))
   103  			So(err, ShouldBeNil)
   104  			expectedChangelists[0].OwnerKind = pb.ChangelistOwnerKind_AUTOMATION
   105  			So(removeCreationTimestamps(cls), ShouldResemble, expectedChangelists)
   106  		})
   107  		Convey("With CL not existing", func() {
   108  			clsByHost["chromium-review.googlesource.com"] = []*gerritpb.ChangeInfo{}
   109  
   110  			augmentedSources, err := PopulateOwnerKinds(ctx, "testproject", sources)
   111  			So(err, ShouldBeNil)
   112  			expectedSources["sources-1"].Changelists[0].OwnerKind = pb.ChangelistOwnerKind_CHANGELIST_OWNER_UNSPECIFIED
   113  			So(augmentedSources, ShouldResembleProto, expectedSources)
   114  
   115  			// Verify cache record was created.
   116  			cls, err := ReadAll(span.Single(ctx))
   117  			So(err, ShouldBeNil)
   118  			expectedChangelists[0].OwnerKind = pb.ChangelistOwnerKind_CHANGELIST_OWNER_UNSPECIFIED
   119  			So(removeCreationTimestamps(cls), ShouldResemble, expectedChangelists)
   120  		})
   121  		Convey("With cache record", func() {
   122  			// Create a cache record that says the CL was created by automation.
   123  			expectedChangelists[0].OwnerKind = pb.ChangelistOwnerKind_AUTOMATION
   124  			So(SetGerritChangelistsForTesting(ctx, expectedChangelists), ShouldBeNil)
   125  
   126  			augmentedSources, err := PopulateOwnerKinds(ctx, "testproject", sources)
   127  			So(err, ShouldBeNil)
   128  			expectedSources["sources-1"].Changelists[0].OwnerKind = pb.ChangelistOwnerKind_AUTOMATION
   129  			So(augmentedSources, ShouldResembleProto, expectedSources)
   130  
   131  			// Verify cache remains in tact.
   132  			cls, err := ReadAll(span.Single(ctx))
   133  			So(err, ShouldBeNil)
   134  			So(removeCreationTimestamps(cls), ShouldResemble, expectedChangelists)
   135  		})
   136  		Convey("With no changelists", func() {
   137  			sources["sources-1"].Changelists = nil
   138  
   139  			augmentedSources, err := PopulateOwnerKinds(ctx, "testproject", sources)
   140  			So(err, ShouldBeNil)
   141  			expectedSources["sources-1"].Changelists = nil
   142  			So(augmentedSources, ShouldResembleProto, expectedSources)
   143  
   144  			// Verify no cache entries created.
   145  			cls, err := ReadAll(span.Single(ctx))
   146  			So(err, ShouldBeNil)
   147  			So(cls, ShouldBeNil)
   148  		})
   149  		Convey("With multiple changelists", func() {
   150  			sources := make(map[string]*rdbpb.Sources)
   151  			sources["sources-1"] = &rdbpb.Sources{
   152  				GitilesCommit: &rdbpb.GitilesCommit{
   153  					Host:       "chromium.googlesource.com",
   154  					Project:    "chromium/src",
   155  					Ref:        "refs/heads/main",
   156  					CommitHash: "aa11bb22cc33dd44ee55aa11bb22cc33dd44ee55",
   157  					Position:   123,
   158  				},
   159  				Changelists: []*rdbpb.GerritChange{
   160  					{
   161  						Host:     "chromium-review.googlesource.com",
   162  						Project:  "chromium/src",
   163  						Change:   111,
   164  						Patchset: 3,
   165  					},
   166  					{
   167  						Host:     "chromium-review.googlesource.com",
   168  						Project:  "chromium/src",
   169  						Change:   222,
   170  						Patchset: 3,
   171  					},
   172  				},
   173  			}
   174  			sources["sources-2"] = &rdbpb.Sources{
   175  				GitilesCommit: &rdbpb.GitilesCommit{
   176  					Host:       "chromium.googlesource.com",
   177  					Project:    "chromium/src",
   178  					Ref:        "refs/heads/main",
   179  					CommitHash: "bb22cc33dd44dd44ee55aa11bb22cc33dd44ee55",
   180  					Position:   456,
   181  				},
   182  				Changelists: []*rdbpb.GerritChange{
   183  					{
   184  						Host:     "chromium-review.googlesource.com",
   185  						Project:  "chromium/src",
   186  						Change:   111,
   187  						Patchset: 3,
   188  					},
   189  					{
   190  						Host:     "chromium-review.googlesource.com",
   191  						Project:  "chromium/src",
   192  						Change:   333,
   193  						Patchset: 3,
   194  					},
   195  					{
   196  						Host:     "chromium-review.googlesource.com",
   197  						Project:  "chromium/special",
   198  						Change:   444,
   199  						Patchset: 3,
   200  					},
   201  				},
   202  			}
   203  
   204  			expectedSources := make(map[string]*pb.Sources)
   205  			expectedSources["sources-1"] = pbutil.SourcesFromResultDB(sources["sources-1"])
   206  			expectedSources["sources-1"].Changelists[0].OwnerKind = pb.ChangelistOwnerKind_HUMAN
   207  			expectedSources["sources-1"].Changelists[1].OwnerKind = pb.ChangelistOwnerKind_AUTOMATION
   208  			expectedSources["sources-2"] = pbutil.SourcesFromResultDB(sources["sources-2"])
   209  			expectedSources["sources-2"].Changelists[0].OwnerKind = pb.ChangelistOwnerKind_HUMAN
   210  			expectedSources["sources-2"].Changelists[1].OwnerKind = pb.ChangelistOwnerKind_CHANGELIST_OWNER_UNSPECIFIED
   211  			expectedSources["sources-2"].Changelists[2].OwnerKind = pb.ChangelistOwnerKind_HUMAN
   212  
   213  			clsByHost["chromium-review.googlesource.com"] = []*gerritpb.ChangeInfo{
   214  				{
   215  					Number: 111,
   216  					Owner: &gerritpb.AccountInfo{
   217  						Email: "username@chromium.org",
   218  					},
   219  					Project: "chromium/src",
   220  				},
   221  				{
   222  					Number: 222,
   223  					Owner: &gerritpb.AccountInfo{
   224  						Email: "robot@chromium.gserviceaccount.com",
   225  					},
   226  					Project: "chromium/src",
   227  				},
   228  				// 333 does not exist.
   229  				{
   230  					Number: 444,
   231  					Owner: &gerritpb.AccountInfo{
   232  						Email: "username@chromium.org",
   233  					},
   234  					Project: "chromium/special",
   235  				},
   236  			}
   237  
   238  			expectedChangelists := []*GerritChangelist{
   239  				{
   240  					Project:   "testproject",
   241  					Host:      "chromium-review.googlesource.com",
   242  					Change:    111,
   243  					OwnerKind: pb.ChangelistOwnerKind_HUMAN,
   244  				},
   245  				{
   246  					Project:   "testproject",
   247  					Host:      "chromium-review.googlesource.com",
   248  					Change:    222,
   249  					OwnerKind: pb.ChangelistOwnerKind_AUTOMATION,
   250  				},
   251  				{
   252  					Project:   "testproject",
   253  					Host:      "chromium-review.googlesource.com",
   254  					Change:    333,
   255  					OwnerKind: pb.ChangelistOwnerKind_CHANGELIST_OWNER_UNSPECIFIED,
   256  				},
   257  				{
   258  					Project:   "testproject",
   259  					Host:      "chromium-review.googlesource.com",
   260  					Change:    444,
   261  					OwnerKind: pb.ChangelistOwnerKind_HUMAN,
   262  				},
   263  			}
   264  
   265  			Convey("Without cache entries", func() {
   266  				augmentedSources, err := PopulateOwnerKinds(ctx, "testproject", sources)
   267  				So(err, ShouldBeNil)
   268  				So(augmentedSources, ShouldResembleProto, expectedSources)
   269  
   270  				// Verify cache record was created.
   271  				cls, err := ReadAll(span.Single(ctx))
   272  				So(err, ShouldBeNil)
   273  				So(removeCreationTimestamps(cls), ShouldResemble, expectedChangelists)
   274  			})
   275  			Convey("With cache entries", func() {
   276  				So(SetGerritChangelistsForTesting(ctx, expectedChangelists), ShouldBeNil)
   277  				// Remove CLs from gerrit to verify we did infact use the cache.
   278  				clsByHost["chromium-review.googlesource.com"] = nil
   279  
   280  				augmentedSources, err := PopulateOwnerKinds(ctx, "testproject", sources)
   281  				So(err, ShouldBeNil)
   282  				So(augmentedSources, ShouldResembleProto, expectedSources)
   283  
   284  				// Verify cache records remain in tact.
   285  				cls, err := ReadAll(span.Single(ctx))
   286  				So(err, ShouldBeNil)
   287  				So(removeCreationTimestamps(cls), ShouldResemble, expectedChangelists)
   288  			})
   289  		})
   290  	})
   291  }
   292  
   293  func removeCreationTimestamps(cls []*GerritChangelist) []*GerritChangelist {
   294  	var results []*GerritChangelist
   295  	for _, cl := range cls {
   296  		copy := *cl
   297  		copy.CreationTime = time.Time{}
   298  		results = append(results, &copy)
   299  	}
   300  	return results
   301  }