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, ©) 299 } 300 return results 301 }