github.com/justinjmoses/evergreen@v0.0.0-20170530173719-1d50e381ff0d/model/build/build_test.go (about) 1 package build 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/evergreen-ci/evergreen" 8 "github.com/evergreen-ci/evergreen/db" 9 "github.com/evergreen-ci/evergreen/testutil" 10 . "github.com/smartystreets/goconvey/convey" 11 "gopkg.in/mgo.v2/bson" 12 ) 13 14 var buildTestConfig = testutil.TestConfig() 15 16 func init() { 17 db.SetGlobalSessionProvider(db.SessionFactoryFromConfig(buildTestConfig)) 18 } 19 20 func buildIdInSlice(builds []Build, id string) bool { 21 for _, build := range builds { 22 if build.Id == id { 23 return true 24 } 25 } 26 return false 27 } 28 29 func TestGenericBuildFinding(t *testing.T) { 30 31 Convey("When finding builds", t, func() { 32 testutil.HandleTestingErr(db.Clear(Collection), t, "Error clearing"+ 33 " '%v' collection", Collection) 34 35 Convey("when finding one build", func() { 36 Convey("the matching build should be returned", func() { 37 buildOne := &Build{Id: "buildOne"} 38 So(buildOne.Insert(), ShouldBeNil) 39 40 buildTwo := &Build{Id: "buildTwo"} 41 So(buildTwo.Insert(), ShouldBeNil) 42 43 found, err := FindOne(ById(buildOne.Id)) 44 So(err, ShouldBeNil) 45 So(found.Id, ShouldEqual, buildOne.Id) 46 }) 47 }) 48 49 Convey("when finding multiple builds", func() { 50 Convey("a slice of all of the matching builds should be returned", func() { 51 52 buildOne := &Build{Id: "buildOne", Project: "b1"} 53 So(buildOne.Insert(), ShouldBeNil) 54 55 buildTwo := &Build{Id: "buildTwo", Project: "b1"} 56 So(buildTwo.Insert(), ShouldBeNil) 57 58 buildThree := &Build{Id: "buildThree", Project: "b2"} 59 So(buildThree.Insert(), ShouldBeNil) 60 61 found, err := Find(ByProject("b1")) 62 So(err, ShouldBeNil) 63 So(len(found), ShouldEqual, 2) 64 So(buildIdInSlice(found, buildOne.Id), ShouldBeTrue) 65 So(buildIdInSlice(found, buildTwo.Id), ShouldBeTrue) 66 }) 67 }) 68 }) 69 } 70 71 func TestFindIntermediateBuilds(t *testing.T) { 72 73 Convey("When finding intermediate builds", t, func() { 74 75 testutil.HandleTestingErr(db.Clear(Collection), t, "Error clearing"+ 76 " '%v' collection", Collection) 77 78 // the two builds to use as endpoints 79 80 currBuild := &Build{ 81 Id: "curr", 82 RevisionOrderNumber: 1000, 83 BuildVariant: "bv1", 84 Requester: "r1", 85 Project: "project1", 86 } 87 So(currBuild.Insert(), ShouldBeNil) 88 89 prevBuild := &Build{Id: "prev", RevisionOrderNumber: 10} 90 So(prevBuild.Insert(), ShouldBeNil) 91 92 Convey("all builds returned should be in commits between the current"+ 93 " build and the specified previous one", func() { 94 95 // insert two builds with commit order numbers in the correct 96 // range 97 98 matchingBuildOne := &Build{ 99 Id: "mb1", 100 RevisionOrderNumber: 50, 101 BuildVariant: "bv1", 102 Requester: "r1", 103 Project: "project1", 104 } 105 So(matchingBuildOne.Insert(), ShouldBeNil) 106 107 matchingBuildTwo := &Build{ 108 Id: "mb2", 109 RevisionOrderNumber: 51, 110 BuildVariant: "bv1", 111 Requester: "r1", 112 Project: "project1", 113 } 114 So(matchingBuildTwo.Insert(), ShouldBeNil) 115 116 // insert two builds with commit order numbers out of range (one too 117 // high and one too low) 118 119 numberTooLow := &Build{ 120 Id: "tooLow", 121 RevisionOrderNumber: 5, 122 BuildVariant: "bv1", 123 Requester: "r1", 124 Project: "project1", 125 } 126 So(numberTooLow.Insert(), ShouldBeNil) 127 128 numberTooHigh := &Build{ 129 Id: "tooHigh", 130 RevisionOrderNumber: 5000, 131 BuildVariant: "bv1", 132 Requester: "r1", 133 Project: "project1", 134 } 135 So(numberTooHigh.Insert(), ShouldBeNil) 136 137 // finding intermediate builds should return only the two in range 138 139 found, err := currBuild.FindIntermediateBuilds(prevBuild) 140 So(err, ShouldBeNil) 141 So(len(found), ShouldEqual, 2) 142 So(buildIdInSlice(found, matchingBuildOne.Id), ShouldBeTrue) 143 So(buildIdInSlice(found, matchingBuildTwo.Id), ShouldBeTrue) 144 }) 145 146 Convey("all builds returned should have the same build variant,"+ 147 " requester, and project as the current one", func() { 148 149 // insert four builds - one with the wrong build variant, one 150 // with the wrong requester, one with the wrong project, and one 151 // with all the correct values 152 153 wrongBV := &Build{ 154 Id: "wrongBV", 155 RevisionOrderNumber: 50, 156 BuildVariant: "bv2", 157 Requester: "r1", 158 Project: "project1", 159 } 160 So(wrongBV.Insert(), ShouldBeNil) 161 162 wrongReq := &Build{ 163 Id: "wrongReq", 164 RevisionOrderNumber: 51, 165 BuildVariant: "bv1", 166 Requester: "r2", 167 Project: "project1", 168 } 169 So(wrongReq.Insert(), ShouldBeNil) 170 171 wrongProject := &Build{ 172 Id: "wrongProject", 173 RevisionOrderNumber: 52, 174 BuildVariant: "bv1", 175 Requester: "r1", 176 Project: "project2", 177 } 178 So(wrongProject.Insert(), ShouldBeNil) 179 180 allCorrect := &Build{ 181 Id: "allCorrect", 182 RevisionOrderNumber: 53, 183 BuildVariant: "bv1", 184 Requester: "r1", 185 Project: "project1", 186 } 187 So(allCorrect.Insert(), ShouldBeNil) 188 189 // finding intermediate builds should return only the one with 190 // all the correctly matching values 191 192 found, err := currBuild.FindIntermediateBuilds(prevBuild) 193 So(err, ShouldBeNil) 194 So(len(found), ShouldEqual, 1) 195 So(found[0].Id, ShouldEqual, allCorrect.Id) 196 197 }) 198 199 Convey("the builds returned should be sorted in ascending order"+ 200 " by commit order number", func() { 201 202 // insert two builds with commit order numbers in the correct 203 // range 204 matchingBuildOne := &Build{ 205 Id: "mb1", 206 RevisionOrderNumber: 52, 207 BuildVariant: "bv1", 208 Requester: "r1", 209 Project: "project1", 210 } 211 So(matchingBuildOne.Insert(), ShouldBeNil) 212 213 matchingBuildTwo := &Build{ 214 Id: "mb2", 215 RevisionOrderNumber: 50, 216 BuildVariant: "bv1", 217 Requester: "r1", 218 Project: "project1", 219 } 220 So(matchingBuildTwo.Insert(), ShouldBeNil) 221 222 matchingBuildThree := &Build{ 223 Id: "mb3", 224 RevisionOrderNumber: 51, 225 BuildVariant: "bv1", 226 Requester: "r1", 227 Project: "project1", 228 } 229 So(matchingBuildThree.Insert(), ShouldBeNil) 230 231 // the builds should come out sorted by commit order number 232 233 found, err := currBuild.FindIntermediateBuilds(prevBuild) 234 So(err, ShouldBeNil) 235 So(len(found), ShouldEqual, 3) 236 So(found[0].Id, ShouldEqual, matchingBuildTwo.Id) 237 So(found[1].Id, ShouldEqual, matchingBuildThree.Id) 238 So(found[2].Id, ShouldEqual, matchingBuildOne.Id) 239 }) 240 }) 241 } 242 243 func TestFindPreviousActivatedBuild(t *testing.T) { 244 245 Convey("When finding the previous activated build", t, func() { 246 247 testutil.HandleTestingErr(db.Clear(Collection), t, "Error clearing"+ 248 " '%v' collection", Collection) 249 250 currBuild := &Build{ 251 Id: "curr", 252 RevisionOrderNumber: 1000, 253 BuildVariant: "bv1", 254 Project: "project1", 255 Requester: "r1", 256 } 257 258 Convey("the last activated build before the specified one with the"+ 259 " same build variant and specified requester + project should be"+ 260 " fetched", func() { 261 262 // insert 7 builds: 263 // one with too high a commit number 264 // one with the wrong build variant 265 // one with the wrong project 266 // one with the wrong requester 267 // one inactive 268 // two matching ones 269 270 tooHigh := &Build{ 271 Id: "tooHigh", 272 RevisionOrderNumber: 5000, 273 BuildVariant: "bv1", 274 Project: "project1", 275 Requester: "r1", 276 Activated: true, 277 } 278 So(tooHigh.Insert(), ShouldBeNil) 279 280 wrongBV := &Build{ 281 Id: "wrongBV", 282 RevisionOrderNumber: 500, 283 BuildVariant: "bv2", 284 Project: "project1", 285 Requester: "r1", 286 Activated: true, 287 } 288 So(wrongBV.Insert(), ShouldBeNil) 289 290 wrongProject := &Build{ 291 Id: "wrongProject", 292 RevisionOrderNumber: 500, 293 BuildVariant: "bv1", 294 Project: "project2", 295 Requester: "r1", 296 Activated: true, 297 } 298 So(wrongProject.Insert(), ShouldBeNil) 299 300 wrongReq := &Build{ 301 Id: "wrongReq", 302 RevisionOrderNumber: 500, 303 BuildVariant: "bv1", 304 Project: "project1", 305 Requester: "r2", 306 Activated: true, 307 } 308 So(wrongReq.Insert(), ShouldBeNil) 309 310 notActive := &Build{ 311 Id: "notActive", 312 RevisionOrderNumber: 500, 313 BuildVariant: "bv1", 314 Project: "project1", 315 Requester: "r1", 316 } 317 So(notActive.Insert(), ShouldBeNil) 318 319 matchingHigher := &Build{ 320 Id: "matchingHigher", 321 RevisionOrderNumber: 900, 322 BuildVariant: "bv1", 323 Project: "project1", 324 Requester: "r1", 325 Activated: true, 326 } 327 So(matchingHigher.Insert(), ShouldBeNil) 328 329 matchingLower := &Build{ 330 Id: "matchingLower", 331 RevisionOrderNumber: 800, 332 BuildVariant: "bv1", 333 Project: "project1", 334 Requester: "r1", 335 Activated: true, 336 } 337 So(matchingLower.Insert(), ShouldBeNil) 338 339 // the matching build with the higher commit order number should 340 // be returned 341 342 found, err := currBuild.PreviousActivated("project1", "r1") 343 So(err, ShouldBeNil) 344 So(found.Id, ShouldEqual, matchingHigher.Id) 345 }) 346 }) 347 } 348 349 func TestRecentlyFinishedBuilds(t *testing.T) { 350 351 Convey("When finding all recently finished builds", t, func() { 352 353 testutil.HandleTestingErr(db.Clear(Collection), t, "Error clearing"+ 354 " '%v' collection", Collection) 355 356 Convey("all builds returned should be finished", func() { 357 358 finishTime := time.Now().Add(-10) 359 360 // insert two finished builds and one unfinished build 361 362 finishedOne := &Build{ 363 Id: "fin1", 364 Project: "project1", 365 Requester: "r1", 366 TimeTaken: time.Duration(1), 367 FinishTime: finishTime.Add(1 * time.Second), 368 } 369 So(finishedOne.Insert(), ShouldBeNil) 370 371 finishedTwo := &Build{ 372 Id: "fin2", 373 Project: "project1", 374 Requester: "r1", 375 TimeTaken: time.Duration(1), 376 FinishTime: finishTime.Add(2 * time.Second), 377 } 378 So(finishedTwo.Insert(), ShouldBeNil) 379 380 unfinished := &Build{ 381 Id: "unfin", 382 Project: "project1", 383 Requester: "r1", 384 } 385 So(unfinished.Insert(), ShouldBeNil) 386 387 // only the finished ones should be returned 388 389 found, err := Find(ByFinishedAfter(finishTime, "project1", "r1")) 390 So(err, ShouldBeNil) 391 So(len(found), ShouldEqual, 2) 392 So(buildIdInSlice(found, finishedOne.Id), ShouldBeTrue) 393 So(buildIdInSlice(found, finishedTwo.Id), ShouldBeTrue) 394 395 }) 396 397 Convey("all builds returned should have finished after the specified"+ 398 " time", func() { 399 400 finishTime := time.Now().Add(-10) 401 402 // insert three finished builds 403 404 finishedOne := &Build{ 405 Id: "fin1", 406 Project: "project1", 407 Requester: "r1", 408 TimeTaken: time.Duration(1), 409 FinishTime: finishTime.Add(1 * time.Second), 410 } 411 So(finishedOne.Insert(), ShouldBeNil) 412 413 finishedTwo := &Build{ 414 Id: "fin2", 415 Project: "project1", 416 Requester: "r1", 417 TimeTaken: time.Duration(1), 418 FinishTime: finishTime, 419 } 420 So(finishedTwo.Insert(), ShouldBeNil) 421 422 finishedThree := &Build{ 423 Id: "fin3", 424 Project: "project1", 425 Requester: "r1", 426 TimeTaken: time.Duration(1), 427 FinishTime: finishTime.Add(-1 * time.Second), 428 } 429 So(finishedThree.Insert(), ShouldBeNil) 430 431 // only the one that finished after the specified time should 432 // be returned 433 434 found, err := Find(ByFinishedAfter(finishTime, "project1", "r1")) 435 So(err, ShouldBeNil) 436 So(len(found), ShouldEqual, 1) 437 So(found[0].Id, ShouldEqual, finishedOne.Id) 438 439 }) 440 441 Convey("all builds should have the specified requester and"+ 442 " project", func() { 443 444 finishTime := time.Now().Add(-10) 445 446 // insert three finished builds; one with the wrong requester, 447 // one with the wrong project, and one with both correct 448 449 wrongReq := &Build{ 450 Id: "wrongReq", 451 Project: "project1", 452 Requester: "r2", 453 TimeTaken: time.Duration(1), 454 FinishTime: finishTime.Add(1 * time.Second), 455 } 456 So(wrongReq.Insert(), ShouldBeNil) 457 458 wrongProject := &Build{ 459 Id: "wrongProject", 460 Project: "project2", 461 Requester: "r1", 462 TimeTaken: time.Duration(1), 463 FinishTime: finishTime.Add(1 * time.Second), 464 } 465 So(wrongProject.Insert(), ShouldBeNil) 466 467 matching := &Build{ 468 Id: "matching", 469 Project: "project1", 470 Requester: "r1", 471 TimeTaken: time.Duration(1), 472 FinishTime: finishTime.Add(1 * time.Second), 473 } 474 So(matching.Insert(), ShouldBeNil) 475 476 // only the one with the correct project and requester should be 477 // returned 478 479 found, err := Find(ByFinishedAfter(finishTime, "project1", "r1")) 480 So(err, ShouldBeNil) 481 So(len(found), ShouldEqual, 1) 482 So(found[0].Id, ShouldEqual, matching.Id) 483 }) 484 485 }) 486 487 } 488 489 func TestGenericBuildUpdating(t *testing.T) { 490 Convey("When updating builds", t, func() { 491 492 Reset(func() { 493 testutil.HandleTestingErr(db.Clear(Collection), t, "Error clearing '%v' collection", Collection) 494 }) 495 496 Convey("updating a single build should update the specified build"+ 497 " in the database", func() { 498 499 buildOne := &Build{Id: "buildOne"} 500 So(buildOne.Insert(), ShouldBeNil) 501 502 err := UpdateOne( 503 bson.M{IdKey: buildOne.Id}, 504 bson.M{"$set": bson.M{ProjectKey: "blah"}}, 505 ) 506 So(err, ShouldBeNil) 507 508 buildOne, err = FindOne(ById(buildOne.Id)) 509 So(err, ShouldBeNil) 510 So(buildOne.Project, ShouldEqual, "blah") 511 }) 512 }) 513 } 514 515 func TestBuildUpdateStatus(t *testing.T) { 516 Convey("With a build", t, func() { 517 518 Reset(func() { 519 testutil.HandleTestingErr(db.Clear(Collection), t, "Error clearing '%v' collection", Collection) 520 }) 521 522 var err error 523 build := &Build{Id: "build"} 524 So(build.Insert(), ShouldBeNil) 525 526 Convey("setting its status should update it both in-memory and"+ 527 " in the database", func() { 528 So(build.UpdateStatus(evergreen.BuildSucceeded), ShouldBeNil) 529 So(build.Status, ShouldEqual, evergreen.BuildSucceeded) 530 build, err = FindOne(ById(build.Id)) 531 So(err, ShouldBeNil) 532 So(build.Status, ShouldEqual, evergreen.BuildSucceeded) 533 }) 534 }) 535 }