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  }