go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/buildbucket/appengine/model/tagindex_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 model 16 17 import ( 18 "context" 19 "testing" 20 21 "go.chromium.org/luci/gae/impl/memory" 22 "go.chromium.org/luci/gae/service/datastore" 23 24 . "github.com/smartystreets/goconvey/convey" 25 . "go.chromium.org/luci/common/testing/assertions" 26 ) 27 28 func TestTagIndex(t *testing.T) { 29 t.Parallel() 30 31 Convey("TagIndex", t, func() { 32 ctx := memory.Use(context.Background()) 33 datastore.GetTestable(ctx).AutoIndex(true) 34 datastore.GetTestable(ctx).Consistent(true) 35 36 Convey("updateTagIndex", func() { 37 Convey("create", func() { 38 Convey("nil", func() { 39 So(updateTagIndex(ctx, "key:val", 0, nil), ShouldBeNil) 40 41 shd := &TagIndex{ 42 ID: "key:val", 43 } 44 So(datastore.Get(ctx, shd), ShouldErrLike, "no such entity") 45 }) 46 47 Convey("empty", func() { 48 ents := []TagIndexEntry{} 49 So(updateTagIndex(ctx, "key:val", 0, ents), ShouldBeNil) 50 51 shd := &TagIndex{ 52 ID: "key:val", 53 } 54 So(datastore.Get(ctx, shd), ShouldErrLike, "no such entity") 55 }) 56 57 Convey("one", func() { 58 ents := []TagIndexEntry{ 59 { 60 BuildID: 1, 61 BucketID: "bucket", 62 }, 63 } 64 So(updateTagIndex(ctx, "key:val", 0, ents), ShouldBeNil) 65 66 shd := &TagIndex{ 67 ID: "key:val", 68 } 69 So(datastore.Get(ctx, shd), ShouldBeNil) 70 So(shd, ShouldResemble, &TagIndex{ 71 ID: "key:val", 72 Entries: []TagIndexEntry{ 73 { 74 BuildID: 1, 75 BucketID: "bucket", 76 }, 77 }, 78 }) 79 }) 80 81 Convey("many", func() { 82 ents := []TagIndexEntry{ 83 { 84 BuildID: 1, 85 BucketID: "bucket", 86 }, 87 { 88 BuildID: 2, 89 BucketID: "bucket", 90 }, 91 } 92 So(updateTagIndex(ctx, "key:val", 0, ents), ShouldBeNil) 93 94 shd := &TagIndex{ 95 ID: "key:val", 96 } 97 So(datastore.Get(ctx, shd), ShouldBeNil) 98 So(shd, ShouldResemble, &TagIndex{ 99 ID: "key:val", 100 Entries: []TagIndexEntry{ 101 { 102 BuildID: 1, 103 BucketID: "bucket", 104 }, 105 { 106 BuildID: 2, 107 BucketID: "bucket", 108 }, 109 }, 110 }) 111 }) 112 113 Convey("excessive", func() { 114 ents := make([]TagIndexEntry, MaxTagIndexEntries+1) 115 for i := range ents { 116 ents[i] = TagIndexEntry{ 117 BuildID: int64(i), 118 BucketID: "bucket", 119 } 120 } 121 So(updateTagIndex(ctx, "key:val", 0, ents), ShouldBeNil) 122 123 shd := &TagIndex{ 124 ID: "key:val", 125 } 126 So(datastore.Get(ctx, shd), ShouldBeNil) 127 So(shd, ShouldResemble, &TagIndex{ 128 ID: "key:val", 129 Incomplete: true, 130 }) 131 }) 132 }) 133 134 Convey("update", func() { 135 So(datastore.Put(ctx, &TagIndex{ 136 ID: ":1:key:val", 137 Entries: []TagIndexEntry{ 138 { 139 BuildID: 1, 140 BucketID: "bucket", 141 }, 142 }, 143 }), ShouldBeNil) 144 145 Convey("nil", func() { 146 So(updateTagIndex(ctx, "key:val", 1, nil), ShouldBeNil) 147 148 shd := &TagIndex{ 149 ID: ":1:key:val", 150 } 151 So(datastore.Get(ctx, shd), ShouldBeNil) 152 So(shd, ShouldResemble, &TagIndex{ 153 ID: ":1:key:val", 154 Entries: []TagIndexEntry{ 155 { 156 BuildID: 1, 157 BucketID: "bucket", 158 }, 159 }, 160 }) 161 }) 162 163 Convey("empty", func() { 164 ents := []TagIndexEntry{} 165 So(updateTagIndex(ctx, "key:val", 1, ents), ShouldBeNil) 166 167 shd := &TagIndex{ 168 ID: ":1:key:val", 169 } 170 So(datastore.Get(ctx, shd), ShouldBeNil) 171 So(shd, ShouldResemble, &TagIndex{ 172 ID: ":1:key:val", 173 Entries: []TagIndexEntry{ 174 { 175 BuildID: 1, 176 BucketID: "bucket", 177 }, 178 }, 179 }) 180 }) 181 182 Convey("one", func() { 183 ents := []TagIndexEntry{ 184 { 185 BuildID: 2, 186 BucketID: "bucket", 187 }, 188 } 189 So(updateTagIndex(ctx, "key:val", 1, ents), ShouldBeNil) 190 191 shd := &TagIndex{ 192 ID: ":1:key:val", 193 } 194 So(datastore.Get(ctx, shd), ShouldBeNil) 195 So(shd, ShouldResemble, &TagIndex{ 196 ID: ":1:key:val", 197 Entries: []TagIndexEntry{ 198 { 199 BuildID: 1, 200 BucketID: "bucket", 201 }, 202 { 203 BuildID: 2, 204 BucketID: "bucket", 205 }, 206 }, 207 }) 208 }) 209 210 Convey("many", func() { 211 ents := []TagIndexEntry{ 212 { 213 BuildID: 2, 214 BucketID: "bucket", 215 }, 216 { 217 BuildID: 3, 218 BucketID: "bucket", 219 }, 220 } 221 So(updateTagIndex(ctx, "key:val", 1, ents), ShouldBeNil) 222 223 shd := &TagIndex{ 224 ID: ":1:key:val", 225 } 226 So(datastore.Get(ctx, shd), ShouldBeNil) 227 So(shd, ShouldResemble, &TagIndex{ 228 ID: ":1:key:val", 229 Entries: []TagIndexEntry{ 230 { 231 BuildID: 1, 232 BucketID: "bucket", 233 }, 234 { 235 BuildID: 2, 236 BucketID: "bucket", 237 }, 238 { 239 BuildID: 3, 240 BucketID: "bucket", 241 }, 242 }, 243 }) 244 }) 245 246 Convey("excessive", func() { 247 ents := make([]TagIndexEntry, MaxTagIndexEntries) 248 for i := range ents { 249 ents[i] = TagIndexEntry{ 250 BuildID: int64(i + 10), 251 BucketID: "bucket", 252 } 253 } 254 So(updateTagIndex(ctx, "key:val", 1, ents), ShouldBeNil) 255 256 shd := &TagIndex{ 257 ID: ":1:key:val", 258 } 259 So(datastore.Get(ctx, shd), ShouldBeNil) 260 So(shd, ShouldResemble, &TagIndex{ 261 ID: ":1:key:val", 262 Incomplete: true, 263 }) 264 }) 265 }) 266 267 Convey("incomplete", func() { 268 So(datastore.Put(ctx, &TagIndex{ 269 ID: ":2:key:val", 270 Incomplete: true, 271 }), ShouldBeNil) 272 273 Convey("nil", func() { 274 So(updateTagIndex(ctx, "key:val", 2, nil), ShouldBeNil) 275 276 shd := &TagIndex{ 277 ID: ":2:key:val", 278 } 279 So(datastore.Get(ctx, shd), ShouldBeNil) 280 So(shd, ShouldResemble, &TagIndex{ 281 ID: ":2:key:val", 282 Incomplete: true, 283 }) 284 }) 285 286 Convey("empty", func() { 287 ents := []TagIndexEntry{} 288 So(updateTagIndex(ctx, "key:val", 2, ents), ShouldBeNil) 289 290 shd := &TagIndex{ 291 ID: ":2:key:val", 292 } 293 So(datastore.Get(ctx, shd), ShouldBeNil) 294 So(shd, ShouldResemble, &TagIndex{ 295 ID: ":2:key:val", 296 Incomplete: true, 297 }) 298 }) 299 300 Convey("one", func() { 301 ents := []TagIndexEntry{ 302 { 303 BuildID: 1, 304 BucketID: "bucket", 305 }, 306 } 307 So(updateTagIndex(ctx, "key:val", 2, ents), ShouldBeNil) 308 309 shd := &TagIndex{ 310 ID: ":2:key:val", 311 } 312 So(datastore.Get(ctx, shd), ShouldBeNil) 313 So(shd, ShouldResemble, &TagIndex{ 314 ID: ":2:key:val", 315 Incomplete: true, 316 }) 317 }) 318 }) 319 }) 320 321 Convey("searchTagIndex", func() { 322 So(datastore.Put(ctx, &TagIndex{ 323 ID: ":1:buildset:patch/gerrit/chromium-review.googlesource.com/123/1", 324 Entries: []TagIndexEntry{{BuildID: 123, BucketID: "proj/bkt"}}, 325 }), ShouldBeNil) 326 Convey("found", func() { 327 entries, err := SearchTagIndex(ctx, "buildset", "patch/gerrit/chromium-review.googlesource.com/123/1") 328 So(err, ShouldBeNil) 329 So(entries, ShouldResembleProto, []*TagIndexEntry{ 330 {BuildID: 123, BucketID: "proj/bkt"}, 331 }) 332 }) 333 334 Convey("not found", func() { 335 entries, err := SearchTagIndex(ctx, "buildset", "not exist") 336 So(err, ShouldBeNil) 337 So(entries, ShouldBeNil) 338 }) 339 340 Convey("bad TagIndexEntry", func() { 341 So(datastore.Put(ctx, &TagIndex{ 342 ID: "key:val", 343 Entries: []TagIndexEntry{{BuildID: 123, BucketID: "/"}}, 344 }), ShouldBeNil) 345 entries, err := SearchTagIndex(ctx, "key", "val") 346 So(err, ShouldBeNil) 347 So(entries, ShouldBeNil) 348 }) 349 }) 350 }) 351 }