github.com/billybanfield/evergreen@v0.0.0-20170525200750-eeee692790f7/model/task_history_test.go (about)

     1  package model
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/evergreen-ci/evergreen"
     9  	"github.com/evergreen-ci/evergreen/apimodels"
    10  	"github.com/evergreen-ci/evergreen/db"
    11  	"github.com/evergreen-ci/evergreen/model/task"
    12  	"github.com/evergreen-ci/evergreen/model/version"
    13  	"github.com/evergreen-ci/evergreen/testutil"
    14  	. "github.com/smartystreets/goconvey/convey"
    15  	"gopkg.in/mgo.v2/bson"
    16  )
    17  
    18  var taskHistoryTestConfig = testutil.TestConfig()
    19  
    20  func init() {
    21  	db.SetGlobalSessionProvider(
    22  		db.SessionFactoryFromConfig(taskHistoryTestConfig))
    23  }
    24  
    25  func TestTaskHistory(t *testing.T) {
    26  
    27  	Convey("With a task history iterator", t, func() {
    28  
    29  		buildVariants := []string{"bv_0", "bv_1", "bv_2"}
    30  		projectName := "project"
    31  		taskHistoryIterator := NewTaskHistoryIterator(evergreen.CompileStage,
    32  			buildVariants, projectName)
    33  
    34  		Convey("when finding task history items", func() {
    35  
    36  			testutil.HandleTestingErr(db.ClearCollections(version.Collection, task.Collection),
    37  				t, "Error clearing test collections")
    38  
    39  			for i := 10; i < 20; i++ {
    40  				projectToUse := projectName
    41  				if i == 14 {
    42  					projectToUse = "otherBranch"
    43  				}
    44  
    45  				vid := fmt.Sprintf("v%v", i)
    46  				ver := &version.Version{
    47  					Id:                  vid,
    48  					RevisionOrderNumber: i,
    49  					Revision:            vid,
    50  					Requester:           evergreen.RepotrackerVersionRequester,
    51  					Identifier:          projectToUse,
    52  				}
    53  
    54  				testutil.HandleTestingErr(ver.Insert(), t,
    55  					"Error inserting version")
    56  				for j := 0; j < 3; j++ {
    57  					newTask := &task.Task{
    58  						Id:                  fmt.Sprintf("t%v_%v", i, j),
    59  						BuildVariant:        fmt.Sprintf("bv_%v", j),
    60  						DisplayName:         evergreen.CompileStage,
    61  						RevisionOrderNumber: i,
    62  						Revision:            vid,
    63  						Requester:           evergreen.RepotrackerVersionRequester,
    64  						Project:             projectToUse,
    65  					}
    66  					testutil.HandleTestingErr(newTask.Insert(), t,
    67  						"Error inserting task")
    68  				}
    69  
    70  			}
    71  
    72  			Convey("the specified number of task history items should be"+
    73  				" fetched, starting at the specified version", func() {
    74  
    75  				taskHistoryChunk, err := taskHistoryIterator.GetChunk(nil, 5, 0, false)
    76  				versions := taskHistoryChunk.Versions
    77  				tasks := taskHistoryChunk.Tasks
    78  				So(err, ShouldBeNil)
    79  				So(taskHistoryChunk.Exhausted.Before, ShouldBeFalse)
    80  				So(taskHistoryChunk.Exhausted.After, ShouldBeTrue)
    81  				So(len(versions), ShouldEqual, 5)
    82  				So(len(tasks), ShouldEqual, len(versions))
    83  				So(versions[0].Id, ShouldEqual, tasks[0]["_id"])
    84  				So(versions[len(versions)-1].Id, ShouldEqual, "v15")
    85  				So(tasks[len(tasks)-1]["_id"], ShouldEqual,
    86  					versions[len(versions)-1].Id)
    87  
    88  			})
    89  
    90  			Convey("tasks from a different project should be filtered"+
    91  				" out", func() {
    92  
    93  				vBefore, err := version.FindOne(version.ById("v15"))
    94  				So(err, ShouldBeNil)
    95  
    96  				taskHistoryChunk, err := taskHistoryIterator.GetChunk(vBefore, 5, 0, false)
    97  				versions := taskHistoryChunk.Versions
    98  				tasks := taskHistoryChunk.Tasks
    99  				So(err, ShouldBeNil)
   100  				So(taskHistoryChunk.Exhausted.Before, ShouldBeTrue)
   101  				So(taskHistoryChunk.Exhausted.After, ShouldBeFalse)
   102  				// Should skip 14 because its in another project
   103  				So(versions[0].Id, ShouldEqual, "v13")
   104  				So(versions[0].Id, ShouldEqual, tasks[0]["_id"])
   105  				So(len(tasks), ShouldEqual, 4)
   106  				So(len(tasks), ShouldEqual, len(versions))
   107  				So(tasks[len(tasks)-1]["_id"], ShouldEqual,
   108  					versions[len(versions)-1].Id)
   109  
   110  			})
   111  
   112  		})
   113  
   114  	})
   115  
   116  }
   117  
   118  func TestMergeResults(t *testing.T) {
   119  	Convey("With a list of two different test history results", t, func() {
   120  		currentTestHistory := []TestHistoryResult{
   121  			{TestFile: "abc", TaskId: "test1", OldTaskId: ""},
   122  			{TestFile: "def", TaskId: "test1", OldTaskId: ""},
   123  			{TestFile: "ghi", TaskId: "test3", OldTaskId: ""},
   124  		}
   125  
   126  		oldTestHistory := []TestHistoryResult{
   127  			{TestFile: "abc", TaskId: "test1_1", OldTaskId: "test1"},
   128  			{TestFile: "abc", TaskId: "test1_2", OldTaskId: "test1"},
   129  			{TestFile: "def", TaskId: "test1_1", OldTaskId: "test1"},
   130  		}
   131  
   132  		testHistoryWithEmpty := []TestHistoryResult{
   133  			TestHistoryResult{},
   134  			TestHistoryResult{},
   135  		}
   136  		Convey("current and old test history are merged properly", func() {
   137  			allResults := mergeResults(currentTestHistory, oldTestHistory)
   138  			So(len(allResults), ShouldEqual, 6)
   139  			So(allResults[0].TaskId, ShouldEqual, "test1")
   140  			So(allResults[0].TestFile, ShouldEqual, "abc")
   141  
   142  			So(allResults[1].TaskId, ShouldEqual, "test1_1")
   143  			So(allResults[1].TestFile, ShouldEqual, "abc")
   144  
   145  			So(allResults[2].TaskId, ShouldEqual, "test1_2")
   146  			So(allResults[2].TestFile, ShouldEqual, "abc")
   147  
   148  			So(allResults[3].TaskId, ShouldEqual, "test1")
   149  			So(allResults[3].TestFile, ShouldEqual, "def")
   150  
   151  			So(allResults[4].TaskId, ShouldEqual, "test1_1")
   152  			So(allResults[4].TestFile, ShouldEqual, "def")
   153  
   154  			So(allResults[5].TaskId, ShouldEqual, "test3")
   155  			So(allResults[5].TestFile, ShouldEqual, "ghi")
   156  
   157  		})
   158  		Convey("merging in empty results should only produce ones for the results that exist", func() {
   159  			allResults := mergeResults(currentTestHistory, testHistoryWithEmpty)
   160  			So(len(allResults), ShouldEqual, 3)
   161  			So(allResults[0].TaskId, ShouldEqual, "test1")
   162  			So(allResults[1].TaskId, ShouldEqual, "test1")
   163  			So(allResults[2].TaskId, ShouldEqual, "test3")
   164  		})
   165  
   166  	})
   167  }
   168  
   169  func TestSetDefaultsAndValidate(t *testing.T) {
   170  	Convey("With various test parameters", t, func() {
   171  		Convey("an empty test history parameters struct should not be valid", func() {
   172  			params := TestHistoryParameters{}
   173  			So(params.SetDefaultsAndValidate(), ShouldNotBeNil)
   174  		})
   175  		Convey("a test history parameters struct without a project should not be valid", func() {
   176  			params := TestHistoryParameters{
   177  				TestNames: []string{"blah"},
   178  				TaskNames: []string{"blah"},
   179  			}
   180  			So(params.SetDefaultsAndValidate(), ShouldNotBeNil)
   181  		})
   182  		Convey("a test history parameters struct without a set of test or task names should not be valid", func() {
   183  			params := TestHistoryParameters{
   184  				Project: "p",
   185  			}
   186  			So(params.SetDefaultsAndValidate(), ShouldNotBeNil)
   187  		})
   188  		Convey("a test history parameters struct without a task status should have a default set", func() {
   189  			params := TestHistoryParameters{
   190  				Project:      "project",
   191  				TestNames:    []string{"test"},
   192  				TestStatuses: []string{evergreen.TestFailedStatus, evergreen.TestSucceededStatus},
   193  			}
   194  			So(len(params.TaskStatuses), ShouldEqual, 0)
   195  			So(params.SetDefaultsAndValidate(), ShouldBeNil)
   196  			So(len(params.TaskStatuses), ShouldEqual, 1)
   197  			So(params.TaskStatuses[0], ShouldEqual, evergreen.TaskFailed)
   198  
   199  		})
   200  		Convey("a test history parameters struct without a test status should have a default set", func() {
   201  			params := TestHistoryParameters{
   202  				Project:      "project",
   203  				TestNames:    []string{"test"},
   204  				TaskStatuses: []string{evergreen.TaskFailed},
   205  			}
   206  			So(len(params.TestStatuses), ShouldEqual, 0)
   207  			So(params.SetDefaultsAndValidate(), ShouldBeNil)
   208  			So(len(params.TestStatuses), ShouldEqual, 1)
   209  			So(params.TestStatuses[0], ShouldEqual, evergreen.TestFailedStatus)
   210  		})
   211  		Convey("a test history parameters struct with an invalid test status should not be valid", func() {
   212  			params := TestHistoryParameters{
   213  				Project:      "project",
   214  				TestNames:    []string{"test"},
   215  				TestStatuses: []string{"blah"},
   216  			}
   217  			So(params.SetDefaultsAndValidate(), ShouldNotBeNil)
   218  		})
   219  		Convey("a test history parameters struct with an invalid task status should not be valid", func() {
   220  			params := TestHistoryParameters{
   221  				Project:      "project",
   222  				TestNames:    []string{"test"},
   223  				TaskStatuses: []string{"blah"},
   224  			}
   225  			So(params.SetDefaultsAndValidate(), ShouldNotBeNil)
   226  		})
   227  		Convey("a test history parameters struct with both a date and revision should not be valid", func() {
   228  			params := TestHistoryParameters{
   229  				Project:       "project",
   230  				TestNames:     []string{"test"},
   231  				AfterRevision: "abc",
   232  				BeforeDate:    time.Now(),
   233  			}
   234  			So(params.SetDefaultsAndValidate(), ShouldNotBeNil)
   235  			params = TestHistoryParameters{
   236  				Project:        "project",
   237  				TestNames:      []string{"test"},
   238  				BeforeRevision: "abc",
   239  				BeforeDate:     time.Now(),
   240  			}
   241  			So(params.SetDefaultsAndValidate(), ShouldNotBeNil)
   242  			params = TestHistoryParameters{
   243  				Project:       "project",
   244  				TestNames:     []string{"test"},
   245  				AfterRevision: "abc",
   246  				AfterDate:     time.Now(),
   247  			}
   248  			So(params.SetDefaultsAndValidate(), ShouldNotBeNil)
   249  			params = TestHistoryParameters{
   250  				Project:        "project",
   251  				TestNames:      []string{"test"},
   252  				BeforeRevision: "abc",
   253  				AfterDate:      time.Now(),
   254  			}
   255  			So(params.SetDefaultsAndValidate(), ShouldNotBeNil)
   256  			params = TestHistoryParameters{
   257  				Project:        "project",
   258  				TestNames:      []string{"test"},
   259  				AfterRevision:  "abc",
   260  				BeforeDate:     time.Now(),
   261  				BeforeRevision: "abc",
   262  				AfterDate:      time.Now(),
   263  			}
   264  			So(params.SetDefaultsAndValidate(), ShouldNotBeNil)
   265  		})
   266  
   267  	})
   268  }
   269  
   270  func TestBuildTestHistoryQuery(t *testing.T) {
   271  	Convey("With a version", t, func() {
   272  		testutil.HandleTestingErr(db.ClearCollections(task.Collection, version.Collection),
   273  			t, "Error clearing task collections")
   274  		testVersion := version.Version{
   275  			Id:                  "testVersion",
   276  			Revision:            "abc",
   277  			RevisionOrderNumber: 1,
   278  			Identifier:          "project",
   279  			Requester:           evergreen.RepotrackerVersionRequester,
   280  		}
   281  		So(testVersion.Insert(), ShouldBeNil)
   282  		Convey("with setting the defaults of the test history parameters and having task names in the parameters", func() {
   283  			params := TestHistoryParameters{
   284  				Project:   "project",
   285  				TaskNames: []string{"task1", "task2"},
   286  				Limit:     20,
   287  			}
   288  			So(params.SetDefaultsAndValidate(), ShouldBeNil)
   289  			Convey("the pipeline created should be properly created with relevant fields", func() {
   290  				pipeline, err := buildTestHistoryQuery(&params)
   291  				So(err, ShouldBeNil)
   292  				So(len(pipeline), ShouldEqual, 7)
   293  				Convey("the $match task query should have task names included", func() {
   294  					So(pipeline[0], ShouldContainKey, "$match")
   295  					taskMatchQuery := bson.M{
   296  						"$or": []bson.M{
   297  							bson.M{
   298  								task.StatusKey: bson.M{"$in": []string{evergreen.TaskFailed}},
   299  								task.DetailsKey + "." + task.TaskEndDetailTimedOut: bson.M{
   300  									"$ne": true,
   301  								},
   302  								task.DetailsKey + "." + task.TaskEndDetailType: bson.M{
   303  									"$ne": "system",
   304  								}}},
   305  						task.ProjectKey:     "project",
   306  						task.DisplayNameKey: bson.M{"$in": []string{"task1", "task2"}},
   307  					}
   308  					So(pipeline[0]["$match"], ShouldResemble, taskMatchQuery)
   309  				})
   310  				Convey("the $project and $unwind bson.M should project the correct fields", func() {
   311  					So(pipeline[2], ShouldContainKey, "$project")
   312  					So(pipeline[2]["$project"], ShouldResemble, bson.M{
   313  						task.DisplayNameKey:         1,
   314  						task.BuildVariantKey:        1,
   315  						task.ProjectKey:             1,
   316  						task.StatusKey:              1,
   317  						task.TestResultsKey:         1,
   318  						task.RevisionKey:            1,
   319  						task.IdKey:                  1,
   320  						task.ExecutionKey:           1,
   321  						task.RevisionOrderNumberKey: 1,
   322  						task.OldTaskIdKey:           1,
   323  						task.StartTimeKey:           1,
   324  						task.DetailsKey:             1,
   325  					})
   326  					So(pipeline[3], ShouldContainKey, "$unwind")
   327  					So(pipeline[3]["$unwind"], ShouldResemble, "$"+task.TestResultsKey)
   328  				})
   329  				Convey("the $match test query should only have a status query", func() {
   330  					So(pipeline[4], ShouldContainKey, "$match")
   331  					testMatchQuery := bson.M{
   332  						task.TestResultsKey + "." + task.TestResultStatusKey: bson.M{"$in": []string{evergreen.TestFailedStatus}},
   333  					}
   334  					So(pipeline[4]["$match"], ShouldResemble, testMatchQuery)
   335  				})
   336  				Convey("the $sort and $project stages should have the correct fields", func() {
   337  					So(pipeline[5], ShouldContainKey, "$sort")
   338  					So(pipeline[5]["$sort"], ShouldResemble, bson.D{
   339  						{task.RevisionOrderNumberKey, -1},
   340  						{task.TestResultsKey + "." + task.TestResultTestFileKey, -1},
   341  					})
   342  					So(pipeline[6], ShouldContainKey, "$project")
   343  					So(pipeline[6]["$project"], ShouldResemble, bson.M{
   344  						TestFileKey:        "$" + task.TestResultsKey + "." + task.TestResultTestFileKey,
   345  						TaskIdKey:          "$" + task.IdKey,
   346  						TaskStatusKey:      "$" + task.StatusKey,
   347  						TestStatusKey:      "$" + task.TestResultsKey + "." + task.TestResultStatusKey,
   348  						RevisionKey:        "$" + task.RevisionKey,
   349  						ProjectKey:         "$" + task.ProjectKey,
   350  						TaskNameKey:        "$" + task.DisplayNameKey,
   351  						BuildVariantKey:    "$" + task.BuildVariantKey,
   352  						StartTimeKey:       "$" + task.TestResultsKey + "." + task.TestResultStartTimeKey,
   353  						EndTimeKey:         "$" + task.TestResultsKey + "." + task.TestResultEndTimeKey,
   354  						ExecutionKey:       "$" + task.ExecutionKey + "." + task.ExecutionKey,
   355  						OldTaskIdKey:       "$" + task.OldTaskIdKey,
   356  						UrlKey:             "$" + task.TestResultsKey + "." + task.TestResultURLKey,
   357  						UrlRawKey:          "$" + task.TestResultsKey + "." + task.TestResultURLRawKey,
   358  						TaskTimedOutKey:    "$" + task.DetailsKey + "." + task.TaskEndDetailTimedOut,
   359  						TaskDetailsTypeKey: "$" + task.DetailsKey + "." + task.TaskEndDetailType,
   360  						LogIdKey:           "$" + task.TestResultsKey + "." + task.TestResultLogIdKey,
   361  					})
   362  				})
   363  
   364  			})
   365  			Convey("with setting the test names and unsetting the task names", func() {
   366  				params.TestNames = []string{"test1"}
   367  				params.TaskNames = []string{}
   368  				Convey("the pipeline should be created properly", func() {
   369  					pipeline, err := buildTestHistoryQuery(&params)
   370  					So(err, ShouldBeNil)
   371  					So(len(pipeline), ShouldEqual, 7)
   372  					Convey("the $match task query should have the test names included", func() {
   373  						So(pipeline[0], ShouldContainKey, "$match")
   374  						taskMatchQuery := bson.M{
   375  							"$or": []bson.M{
   376  								bson.M{
   377  									task.StatusKey: bson.M{"$in": []string{evergreen.TaskFailed}},
   378  									task.DetailsKey + "." + task.TaskEndDetailTimedOut: bson.M{
   379  										"$ne": true,
   380  									},
   381  									task.DetailsKey + "." + task.TaskEndDetailType: bson.M{
   382  										"$ne": "system",
   383  									}}}, task.ProjectKey: "project",
   384  							task.TestResultsKey + "." + task.TestResultTestFileKey: bson.M{"$in": []string{"test1"}},
   385  						}
   386  						So(pipeline[0]["$match"], ShouldResemble, taskMatchQuery)
   387  					})
   388  					Convey("the $match test query should have the test names included", func() {
   389  						So(pipeline[4], ShouldContainKey, "$match")
   390  						testMatchQuery := bson.M{
   391  							task.TestResultsKey + "." + task.TestResultStatusKey:   bson.M{"$in": []string{evergreen.TestFailedStatus}},
   392  							task.TestResultsKey + "." + task.TestResultTestFileKey: bson.M{"$in": []string{"test1"}},
   393  						}
   394  						So(pipeline[4]["$match"], ShouldResemble, testMatchQuery)
   395  					})
   396  
   397  				})
   398  			})
   399  			Convey("with setting the test names and the task names", func() {
   400  				params.TestNames = []string{"test1"}
   401  				params.TaskNames = []string{"task1", "task2"}
   402  				Convey("the pipeline should be created properly", func() {
   403  					pipeline, err := buildTestHistoryQuery(&params)
   404  					So(err, ShouldBeNil)
   405  					So(len(pipeline), ShouldEqual, 7)
   406  					Convey("the $match task query should have the test names included", func() {
   407  						So(pipeline[0], ShouldContainKey, "$match")
   408  						taskMatchQuery := bson.M{
   409  							"$or": []bson.M{
   410  								bson.M{task.StatusKey: bson.M{"$in": []string{evergreen.TaskFailed}},
   411  									task.DetailsKey + "." + task.TaskEndDetailTimedOut: bson.M{
   412  										"$ne": true,
   413  									},
   414  									task.DetailsKey + "." + task.TaskEndDetailType: bson.M{
   415  										"$ne": "system",
   416  									}}},
   417  							task.ProjectKey:                                        "project",
   418  							task.TestResultsKey + "." + task.TestResultTestFileKey: bson.M{"$in": []string{"test1"}},
   419  							task.DisplayNameKey:                                    bson.M{"$in": []string{"task1", "task2"}},
   420  						}
   421  						So(pipeline[0]["$match"], ShouldResemble, taskMatchQuery)
   422  					})
   423  					Convey("the $match test query should have the test names included", func() {
   424  						So(pipeline[4], ShouldContainKey, "$match")
   425  						testMatchQuery := bson.M{
   426  							task.TestResultsKey + "." + task.TestResultStatusKey:   bson.M{"$in": []string{evergreen.TestFailedStatus}},
   427  							task.TestResultsKey + "." + task.TestResultTestFileKey: bson.M{"$in": []string{"test1"}},
   428  						}
   429  						So(pipeline[4]["$match"], ShouldResemble, testMatchQuery)
   430  					})
   431  
   432  				})
   433  			})
   434  			Convey("with setting the test names, the task names and adding a build variant", func() {
   435  				params.TestNames = []string{"test1"}
   436  				params.TaskNames = []string{"task1", "task2"}
   437  				params.BuildVariants = []string{"osx"}
   438  				Convey("the pipeline should be created properly", func() {
   439  					pipeline, err := buildTestHistoryQuery(&params)
   440  					So(err, ShouldBeNil)
   441  					So(len(pipeline), ShouldEqual, 7)
   442  					Convey("the $match task query should have the test names included", func() {
   443  						So(pipeline[0], ShouldContainKey, "$match")
   444  						taskMatchQuery := bson.M{
   445  							"$or": []bson.M{
   446  								bson.M{task.StatusKey: bson.M{"$in": []string{evergreen.TaskFailed}},
   447  									task.DetailsKey + "." + task.TaskEndDetailTimedOut: bson.M{
   448  										"$ne": true,
   449  									},
   450  									task.DetailsKey + "." + task.TaskEndDetailType: bson.M{
   451  										"$ne": "system",
   452  									}}},
   453  							task.ProjectKey:                                        "project",
   454  							task.TestResultsKey + "." + task.TestResultTestFileKey: bson.M{"$in": []string{"test1"}},
   455  							task.DisplayNameKey:                                    bson.M{"$in": []string{"task1", "task2"}},
   456  							task.BuildVariantKey:                                   bson.M{"$in": []string{"osx"}},
   457  						}
   458  						So(pipeline[0]["$match"], ShouldResemble, taskMatchQuery)
   459  					})
   460  					Convey("the $match test query should have the test names included", func() {
   461  						So(pipeline[4], ShouldContainKey, "$match")
   462  						testMatchQuery := bson.M{
   463  							task.TestResultsKey + "." + task.TestResultStatusKey:   bson.M{"$in": []string{evergreen.TestFailedStatus}},
   464  							task.TestResultsKey + "." + task.TestResultTestFileKey: bson.M{"$in": []string{"test1"}},
   465  						}
   466  						So(pipeline[4]["$match"], ShouldResemble, testMatchQuery)
   467  					})
   468  
   469  				})
   470  				Convey("with adding in a before revision and validating", func() {
   471  					params.BeforeRevision = "abc"
   472  					So(params.SetDefaultsAndValidate(), ShouldBeNil)
   473  					Convey("the pipeline should be created properly", func() {
   474  						pipeline, err := buildTestHistoryQuery(&params)
   475  						So(err, ShouldBeNil)
   476  						So(len(pipeline), ShouldEqual, 7)
   477  						Convey("the $match task query should have the test names included", func() {
   478  							So(pipeline[0], ShouldContainKey, "$match")
   479  							taskMatchQuery := bson.M{
   480  								"$or": []bson.M{
   481  									bson.M{task.StatusKey: bson.M{"$in": []string{evergreen.TaskFailed}},
   482  										task.DetailsKey + "." + task.TaskEndDetailTimedOut: bson.M{
   483  											"$ne": true,
   484  										},
   485  										task.DetailsKey + "." + task.TaskEndDetailType: bson.M{
   486  											"$ne": "system",
   487  										}}},
   488  								task.ProjectKey:                                        "project",
   489  								task.TestResultsKey + "." + task.TestResultTestFileKey: bson.M{"$in": []string{"test1"}},
   490  								task.DisplayNameKey:                                    bson.M{"$in": []string{"task1", "task2"}},
   491  								task.BuildVariantKey:                                   bson.M{"$in": []string{"osx"}},
   492  								task.RevisionOrderNumberKey:                            bson.M{"$lte": 1},
   493  							}
   494  							So(pipeline[0]["$match"], ShouldResemble, taskMatchQuery)
   495  						})
   496  						Convey("the $match test query should have the test names included", func() {
   497  							So(pipeline[4], ShouldContainKey, "$match")
   498  							testMatchQuery := bson.M{
   499  								task.TestResultsKey + "." + task.TestResultStatusKey:   bson.M{"$in": []string{evergreen.TestFailedStatus}},
   500  								task.TestResultsKey + "." + task.TestResultTestFileKey: bson.M{"$in": []string{"test1"}},
   501  							}
   502  							So(pipeline[4]["$match"], ShouldResemble, testMatchQuery)
   503  						})
   504  
   505  					})
   506  
   507  				})
   508  				Convey("with adding in an after revision and validating", func() {
   509  					params.AfterRevision = "abc"
   510  					So(params.SetDefaultsAndValidate(), ShouldBeNil)
   511  					Convey("the pipeline should be created properly", func() {
   512  						pipeline, err := buildTestHistoryQuery(&params)
   513  						So(err, ShouldBeNil)
   514  						So(len(pipeline), ShouldEqual, 7)
   515  						Convey("the $match task query should have the test names included", func() {
   516  							So(pipeline[0], ShouldContainKey, "$match")
   517  							taskMatchQuery := bson.M{
   518  								"$or": []bson.M{
   519  									bson.M{task.StatusKey: bson.M{"$in": []string{evergreen.TaskFailed}},
   520  										task.DetailsKey + "." + task.TaskEndDetailTimedOut: bson.M{
   521  											"$ne": true,
   522  										},
   523  										task.DetailsKey + "." + task.TaskEndDetailType: bson.M{
   524  											"$ne": "system",
   525  										}}},
   526  								task.ProjectKey:                                        "project",
   527  								task.TestResultsKey + "." + task.TestResultTestFileKey: bson.M{"$in": []string{"test1"}},
   528  								task.DisplayNameKey:                                    bson.M{"$in": []string{"task1", "task2"}},
   529  								task.BuildVariantKey:                                   bson.M{"$in": []string{"osx"}},
   530  								task.RevisionOrderNumberKey:                            bson.M{"$gt": 1},
   531  							}
   532  							So(pipeline[0]["$match"], ShouldResemble, taskMatchQuery)
   533  						})
   534  						Convey("the $match test query should have the test names included", func() {
   535  							So(pipeline[4], ShouldContainKey, "$match")
   536  							testMatchQuery := bson.M{
   537  								task.TestResultsKey + "." + task.TestResultStatusKey:   bson.M{"$in": []string{evergreen.TestFailedStatus}},
   538  								task.TestResultsKey + "." + task.TestResultTestFileKey: bson.M{"$in": []string{"test1"}},
   539  							}
   540  							So(pipeline[4]["$match"], ShouldResemble, testMatchQuery)
   541  						})
   542  
   543  					})
   544  
   545  				})
   546  				Convey("with adding in a before and after revision and validating", func() {
   547  					params.AfterRevision = "abc"
   548  					params.BeforeRevision = "abc"
   549  					So(params.SetDefaultsAndValidate(), ShouldBeNil)
   550  					Convey("the pipeline should be created properly", func() {
   551  						pipeline, err := buildTestHistoryQuery(&params)
   552  						So(err, ShouldBeNil)
   553  						So(len(pipeline), ShouldEqual, 7)
   554  						Convey("the $match task query should have the test names included", func() {
   555  							So(pipeline[0], ShouldContainKey, "$match")
   556  							taskMatchQuery := bson.M{
   557  								"$or": []bson.M{
   558  									bson.M{task.StatusKey: bson.M{"$in": []string{evergreen.TaskFailed}},
   559  										task.DetailsKey + "." + task.TaskEndDetailTimedOut: bson.M{
   560  											"$ne": true,
   561  										},
   562  										task.DetailsKey + "." + task.TaskEndDetailType: bson.M{
   563  											"$ne": "system",
   564  										}}},
   565  								task.ProjectKey:                                        "project",
   566  								task.TestResultsKey + "." + task.TestResultTestFileKey: bson.M{"$in": []string{"test1"}},
   567  								task.DisplayNameKey:                                    bson.M{"$in": []string{"task1", "task2"}},
   568  								task.BuildVariantKey:                                   bson.M{"$in": []string{"osx"}},
   569  								task.RevisionOrderNumberKey:                            bson.M{"$lte": 1, "$gt": 1},
   570  							}
   571  							So(pipeline[0]["$match"], ShouldResemble, taskMatchQuery)
   572  						})
   573  						Convey("the $match test query should have the test names included", func() {
   574  							So(pipeline[4], ShouldContainKey, "$match")
   575  							testMatchQuery := bson.M{
   576  								task.TestResultsKey + "." + task.TestResultStatusKey:   bson.M{"$in": []string{evergreen.TestFailedStatus}},
   577  								task.TestResultsKey + "." + task.TestResultTestFileKey: bson.M{"$in": []string{"test1"}},
   578  							}
   579  							So(pipeline[4]["$match"], ShouldResemble, testMatchQuery)
   580  						})
   581  
   582  					})
   583  
   584  				})
   585  				Convey("with adding in an after date and validating", func() {
   586  					now := time.Now()
   587  					params.AfterDate = now
   588  					So(params.SetDefaultsAndValidate(), ShouldBeNil)
   589  					Convey("the pipeline should be created properly", func() {
   590  						pipeline, err := buildTestHistoryQuery(&params)
   591  						So(err, ShouldBeNil)
   592  						So(len(pipeline), ShouldEqual, 7)
   593  						Convey("the $match task query should have the test names included", func() {
   594  							So(pipeline[0], ShouldContainKey, "$match")
   595  							taskMatchQuery := bson.M{
   596  								"$or": []bson.M{
   597  									bson.M{task.StatusKey: bson.M{"$in": []string{evergreen.TaskFailed}},
   598  										task.DetailsKey + "." + task.TaskEndDetailTimedOut: bson.M{
   599  											"$ne": true,
   600  										},
   601  										task.DetailsKey + "." + task.TaskEndDetailType: bson.M{
   602  											"$ne": "system",
   603  										}}},
   604  								task.ProjectKey:                                        "project",
   605  								task.TestResultsKey + "." + task.TestResultTestFileKey: bson.M{"$in": []string{"test1"}},
   606  								task.DisplayNameKey:                                    bson.M{"$in": []string{"task1", "task2"}},
   607  								task.BuildVariantKey:                                   bson.M{"$in": []string{"osx"}},
   608  								task.StartTimeKey:                                      bson.M{"$gte": now},
   609  							}
   610  							So(pipeline[0]["$match"], ShouldResemble, taskMatchQuery)
   611  						})
   612  						Convey("the $match test query should have the test names included", func() {
   613  							So(pipeline[4], ShouldContainKey, "$match")
   614  							testMatchQuery := bson.M{
   615  								task.TestResultsKey + "." + task.TestResultStatusKey:   bson.M{"$in": []string{evergreen.TestFailedStatus}},
   616  								task.TestResultsKey + "." + task.TestResultTestFileKey: bson.M{"$in": []string{"test1"}},
   617  							}
   618  							So(pipeline[4]["$match"], ShouldResemble, testMatchQuery)
   619  						})
   620  
   621  					})
   622  
   623  				})
   624  				Convey("with adding in a before date and validating", func() {
   625  					now := time.Now()
   626  					params.BeforeDate = now
   627  					So(params.SetDefaultsAndValidate(), ShouldBeNil)
   628  					Convey("the pipeline should be created properly", func() {
   629  						pipeline, err := buildTestHistoryQuery(&params)
   630  						So(err, ShouldBeNil)
   631  						So(len(pipeline), ShouldEqual, 7)
   632  						Convey("the $match task query should have the test names included", func() {
   633  							So(pipeline[0], ShouldContainKey, "$match")
   634  							taskMatchQuery := bson.M{
   635  								"$or": []bson.M{
   636  									bson.M{task.StatusKey: bson.M{"$in": []string{evergreen.TaskFailed}},
   637  										task.DetailsKey + "." + task.TaskEndDetailTimedOut: bson.M{
   638  											"$ne": true,
   639  										},
   640  										task.DetailsKey + "." + task.TaskEndDetailType: bson.M{
   641  											"$ne": "system",
   642  										}}},
   643  								task.ProjectKey:                                        "project",
   644  								task.TestResultsKey + "." + task.TestResultTestFileKey: bson.M{"$in": []string{"test1"}},
   645  								task.DisplayNameKey:                                    bson.M{"$in": []string{"task1", "task2"}},
   646  								task.BuildVariantKey:                                   bson.M{"$in": []string{"osx"}},
   647  								task.StartTimeKey:                                      bson.M{"$lte": now},
   648  							}
   649  							So(pipeline[0]["$match"], ShouldResemble, taskMatchQuery)
   650  						})
   651  						Convey("the $match test query should have the test names included", func() {
   652  							So(pipeline[4], ShouldContainKey, "$match")
   653  							testMatchQuery := bson.M{
   654  								task.TestResultsKey + "." + task.TestResultStatusKey:   bson.M{"$in": []string{evergreen.TestFailedStatus}},
   655  								task.TestResultsKey + "." + task.TestResultTestFileKey: bson.M{"$in": []string{"test1"}},
   656  							}
   657  							So(pipeline[4]["$match"], ShouldResemble, testMatchQuery)
   658  						})
   659  
   660  					})
   661  
   662  				})
   663  				Convey("with adding in an after date and before date and validating", func() {
   664  					now := time.Now()
   665  					params.AfterDate = now
   666  					params.BeforeDate = now
   667  					So(params.SetDefaultsAndValidate(), ShouldBeNil)
   668  					Convey("the pipeline should be created properly", func() {
   669  						pipeline, err := buildTestHistoryQuery(&params)
   670  						So(err, ShouldBeNil)
   671  						So(len(pipeline), ShouldEqual, 7)
   672  						Convey("the $match task query should have the test names included", func() {
   673  							So(pipeline[0], ShouldContainKey, "$match")
   674  							taskMatchQuery := bson.M{
   675  								"$or": []bson.M{
   676  									bson.M{task.StatusKey: bson.M{"$in": []string{evergreen.TaskFailed}},
   677  										task.DetailsKey + "." + task.TaskEndDetailTimedOut: bson.M{
   678  											"$ne": true,
   679  										},
   680  										task.DetailsKey + "." + task.TaskEndDetailType: bson.M{
   681  											"$ne": "system",
   682  										}}},
   683  								task.ProjectKey:                                        "project",
   684  								task.TestResultsKey + "." + task.TestResultTestFileKey: bson.M{"$in": []string{"test1"}},
   685  								task.DisplayNameKey:                                    bson.M{"$in": []string{"task1", "task2"}},
   686  								task.BuildVariantKey:                                   bson.M{"$in": []string{"osx"}},
   687  								task.StartTimeKey:                                      bson.M{"$gte": now, "$lte": now},
   688  							}
   689  							So(pipeline[0]["$match"], ShouldResemble, taskMatchQuery)
   690  						})
   691  						Convey("the $match test query should have the test names included", func() {
   692  							So(pipeline[4], ShouldContainKey, "$match")
   693  							testMatchQuery := bson.M{
   694  								task.TestResultsKey + "." + task.TestResultStatusKey:   bson.M{"$in": []string{evergreen.TestFailedStatus}},
   695  								task.TestResultsKey + "." + task.TestResultTestFileKey: bson.M{"$in": []string{"test1"}},
   696  							}
   697  							So(pipeline[4]["$match"], ShouldResemble, testMatchQuery)
   698  						})
   699  
   700  					})
   701  
   702  				})
   703  				Convey("with timeout in task status in the test history parameters", func() {
   704  					params.TaskStatuses = []string{TaskTimeout}
   705  					So(params.SetDefaultsAndValidate(), ShouldBeNil)
   706  					Convey("the pipeline should be created without any errors", func() {
   707  						pipeline, err := buildTestHistoryQuery(&params)
   708  						So(err, ShouldBeNil)
   709  						So(len(pipeline), ShouldEqual, 7)
   710  						Convey("the $match task query should have timeouts included", func() {
   711  							So(pipeline[0], ShouldContainKey, "$match")
   712  
   713  							taskMatchQuery := bson.M{
   714  								"$or": []bson.M{
   715  									bson.M{
   716  										task.StatusKey:                                     evergreen.TaskFailed,
   717  										task.DetailsKey + "." + task.TaskEndDetailTimedOut: true,
   718  									}},
   719  								task.ProjectKey:                                        "project",
   720  								task.TestResultsKey + "." + task.TestResultTestFileKey: bson.M{"$in": []string{"test1"}},
   721  								task.DisplayNameKey:                                    bson.M{"$in": []string{"task1", "task2"}},
   722  								task.BuildVariantKey:                                   bson.M{"$in": []string{"osx"}},
   723  							}
   724  							So(pipeline[0]["$match"], ShouldResemble, taskMatchQuery)
   725  						})
   726  					})
   727  
   728  				})
   729  				Convey("with system failure in task status in the test history parameters", func() {
   730  					params.TaskStatuses = []string{TaskSystemFailure}
   731  					So(params.SetDefaultsAndValidate(), ShouldBeNil)
   732  					Convey("the pipeline should be created without any errors", func() {
   733  						pipeline, err := buildTestHistoryQuery(&params)
   734  						So(err, ShouldBeNil)
   735  						So(len(pipeline), ShouldEqual, 7)
   736  						Convey("the $match task query should have timeouts included", func() {
   737  							So(pipeline[0], ShouldContainKey, "$match")
   738  
   739  							taskMatchQuery := bson.M{
   740  								"$or": []bson.M{
   741  									bson.M{
   742  										task.StatusKey:                                 evergreen.TaskFailed,
   743  										task.DetailsKey + "." + task.TaskEndDetailType: "system",
   744  									}},
   745  								task.ProjectKey:                                        "project",
   746  								task.TestResultsKey + "." + task.TestResultTestFileKey: bson.M{"$in": []string{"test1"}},
   747  								task.DisplayNameKey:                                    bson.M{"$in": []string{"task1", "task2"}},
   748  								task.BuildVariantKey:                                   bson.M{"$in": []string{"osx"}},
   749  							}
   750  							So(pipeline[0]["$match"], ShouldResemble, taskMatchQuery)
   751  						})
   752  					})
   753  				})
   754  				Convey("with system failure and task timeout in task status in the test history parameters", func() {
   755  					params.TaskStatuses = []string{TaskSystemFailure, TaskTimeout}
   756  					So(params.SetDefaultsAndValidate(), ShouldBeNil)
   757  					Convey("the pipeline should be created without any errors", func() {
   758  						pipeline, err := buildTestHistoryQuery(&params)
   759  						So(err, ShouldBeNil)
   760  						So(len(pipeline), ShouldEqual, 7)
   761  						Convey("the $match task query should have timeouts included", func() {
   762  							So(pipeline[0], ShouldContainKey, "$match")
   763  							taskMatchQuery := bson.M{
   764  								"$or": []bson.M{
   765  									bson.M{
   766  										task.StatusKey:                                     evergreen.TaskFailed,
   767  										task.DetailsKey + "." + task.TaskEndDetailTimedOut: true,
   768  									},
   769  									bson.M{
   770  										task.StatusKey:                                 evergreen.TaskFailed,
   771  										task.DetailsKey + "." + task.TaskEndDetailType: "system",
   772  									},
   773  								},
   774  								task.ProjectKey:                                        "project",
   775  								task.TestResultsKey + "." + task.TestResultTestFileKey: bson.M{"$in": []string{"test1"}},
   776  								task.DisplayNameKey:                                    bson.M{"$in": []string{"task1", "task2"}},
   777  								task.BuildVariantKey:                                   bson.M{"$in": []string{"osx"}},
   778  							}
   779  							So(pipeline[0]["$match"], ShouldResemble, taskMatchQuery)
   780  						})
   781  					})
   782  				})
   783  				Convey("with normal task statuses, system failure and task timeout in task status in the test history parameters", func() {
   784  					params.TaskStatuses = []string{TaskSystemFailure, TaskTimeout, evergreen.TaskFailed}
   785  					So(params.SetDefaultsAndValidate(), ShouldBeNil)
   786  					Convey("the pipeline should be created without any errors", func() {
   787  						pipeline, err := buildTestHistoryQuery(&params)
   788  						So(err, ShouldBeNil)
   789  						So(len(pipeline), ShouldEqual, 7)
   790  						Convey("the $match task query should have timeouts included", func() {
   791  							So(pipeline[0], ShouldContainKey, "$match")
   792  							taskMatchQuery := bson.M{
   793  								"$or": []bson.M{
   794  									bson.M{task.StatusKey: bson.M{"$in": []string{evergreen.TaskFailed}},
   795  										task.DetailsKey + "." + task.TaskEndDetailTimedOut: bson.M{
   796  											"$ne": true,
   797  										},
   798  										task.DetailsKey + "." + task.TaskEndDetailType: bson.M{
   799  											"$ne": "system",
   800  										}},
   801  									bson.M{
   802  										task.StatusKey:                                     evergreen.TaskFailed,
   803  										task.DetailsKey + "." + task.TaskEndDetailTimedOut: true,
   804  									},
   805  									bson.M{
   806  										task.StatusKey:                                 evergreen.TaskFailed,
   807  										task.DetailsKey + "." + task.TaskEndDetailType: "system",
   808  									},
   809  								},
   810  								task.ProjectKey:                                        "project",
   811  								task.TestResultsKey + "." + task.TestResultTestFileKey: bson.M{"$in": []string{"test1"}},
   812  								task.DisplayNameKey:                                    bson.M{"$in": []string{"task1", "task2"}},
   813  								task.BuildVariantKey:                                   bson.M{"$in": []string{"osx"}},
   814  							}
   815  							So(pipeline[0]["$match"], ShouldResemble, taskMatchQuery)
   816  						})
   817  					})
   818  				})
   819  
   820  			})
   821  		})
   822  	})
   823  }
   824  
   825  func TestGetTestHistory(t *testing.T) {
   826  	Convey("With a set of tasks and versions", t, func() {
   827  		testutil.HandleTestingErr(db.ClearCollections(task.Collection, version.Collection),
   828  			t, "Error clearing task collections")
   829  		project := "proj"
   830  		now := time.Now()
   831  
   832  		testVersion := version.Version{
   833  			Id:                  "testVersion",
   834  			Revision:            "fgh",
   835  			RevisionOrderNumber: 1,
   836  			Identifier:          project,
   837  			Requester:           evergreen.RepotrackerVersionRequester,
   838  		}
   839  		So(testVersion.Insert(), ShouldBeNil)
   840  		testVersion2 := version.Version{
   841  			Id:                  "anotherVersion",
   842  			Revision:            "def",
   843  			RevisionOrderNumber: 2,
   844  			Identifier:          project,
   845  			Requester:           evergreen.RepotrackerVersionRequester,
   846  		}
   847  		So(testVersion2.Insert(), ShouldBeNil)
   848  		testVersion3 := version.Version{
   849  			Id:                  "testV",
   850  			Revision:            "abcd",
   851  			RevisionOrderNumber: 4,
   852  			Identifier:          project,
   853  			Requester:           evergreen.RepotrackerVersionRequester,
   854  		}
   855  		So(testVersion3.Insert(), ShouldBeNil)
   856  
   857  		task1 := task.Task{
   858  			Id:                  "task1",
   859  			DisplayName:         "test",
   860  			BuildVariant:        "osx",
   861  			Project:             project,
   862  			StartTime:           now,
   863  			RevisionOrderNumber: 1,
   864  			Status:              evergreen.TaskFailed,
   865  			TestResults: []task.TestResult{
   866  				task.TestResult{
   867  					Status:   evergreen.TestFailedStatus,
   868  					TestFile: "test1",
   869  				},
   870  				task.TestResult{
   871  					Status:   evergreen.TestSucceededStatus,
   872  					TestFile: "test2",
   873  				},
   874  			},
   875  		}
   876  		So(task1.Insert(), ShouldBeNil)
   877  		task2 := task.Task{
   878  			Id:                  "task2",
   879  			DisplayName:         "test",
   880  			BuildVariant:        "osx",
   881  			Project:             project,
   882  			StartTime:           now.Add(time.Duration(30 * time.Minute)),
   883  			RevisionOrderNumber: 2,
   884  			Status:              evergreen.TaskFailed,
   885  			TestResults: []task.TestResult{
   886  				task.TestResult{
   887  					Status:   evergreen.TestFailedStatus,
   888  					TestFile: "test1",
   889  				},
   890  				task.TestResult{
   891  					Status:   evergreen.TestFailedStatus,
   892  					TestFile: "test2",
   893  				},
   894  			},
   895  		}
   896  		So(task2.Insert(), ShouldBeNil)
   897  
   898  		task3 := task.Task{
   899  			Id:                  "task3",
   900  			DisplayName:         "test2",
   901  			BuildVariant:        "osx",
   902  			Project:             project,
   903  			StartTime:           now,
   904  			RevisionOrderNumber: 1,
   905  			Status:              evergreen.TaskFailed,
   906  			TestResults: []task.TestResult{
   907  				task.TestResult{
   908  					Status:   evergreen.TestFailedStatus,
   909  					TestFile: "test1",
   910  				},
   911  				task.TestResult{
   912  					Status:   evergreen.TestSucceededStatus,
   913  					TestFile: "test3",
   914  				},
   915  				task.TestResult{
   916  					Status:   evergreen.TestSilentlyFailedStatus,
   917  					TestFile: "test4",
   918  				},
   919  			},
   920  		}
   921  		So(task3.Insert(), ShouldBeNil)
   922  
   923  		Convey("retrieving the task history with just a task name in the parameters should return relevant results", func() {
   924  			params := TestHistoryParameters{
   925  				TaskNames:    []string{"test"},
   926  				Project:      project,
   927  				Sort:         1,
   928  				TaskStatuses: []string{evergreen.TaskFailed},
   929  				TestStatuses: []string{evergreen.TestSucceededStatus, evergreen.TestFailedStatus},
   930  				Limit:        20,
   931  			}
   932  			So(params.SetDefaultsAndValidate(), ShouldBeNil)
   933  			testResults, err := GetTestHistory(&params)
   934  			So(err, ShouldBeNil)
   935  			So(len(testResults), ShouldEqual, 4)
   936  			Convey("the order of the test results should be in sorted order", func() {
   937  				So(testResults[0].TaskId, ShouldEqual, "task1")
   938  				So(testResults[1].TaskId, ShouldEqual, "task1")
   939  				So(testResults[2].TaskId, ShouldEqual, "task2")
   940  				So(testResults[3].TaskId, ShouldEqual, "task2")
   941  			})
   942  			Convey("with a sort of -1, the order should be in reverse revision order number order", func() {
   943  				params.Sort = -1
   944  				testResults, err := GetTestHistory(&params)
   945  				So(err, ShouldBeNil)
   946  				So(len(testResults), ShouldEqual, 4)
   947  				Convey("the order of the test results should be in reverse revision number order", func() {
   948  					So(testResults[0].TaskId, ShouldEqual, "task2")
   949  					So(testResults[3].TaskId, ShouldEqual, "task1")
   950  				})
   951  			})
   952  		})
   953  		Convey("retrieving the task history for just a set of test names in the parameters should return relevant results", func() {
   954  			params := TestHistoryParameters{
   955  				TestNames: []string{"test1"},
   956  				Project:   project,
   957  				Limit:     20,
   958  			}
   959  			So(params.SetDefaultsAndValidate(), ShouldBeNil)
   960  			testResults, err := GetTestHistory(&params)
   961  			So(err, ShouldBeNil)
   962  			So(len(testResults), ShouldEqual, 3)
   963  		})
   964  		Convey("including a filter on a before revision should return inclusive results", func() {
   965  			params := TestHistoryParameters{
   966  				TaskNames:      []string{"test"},
   967  				Project:        project,
   968  				Sort:           1,
   969  				BeforeRevision: testVersion2.Revision,
   970  			}
   971  			So(params.SetDefaultsAndValidate(), ShouldBeNil)
   972  			testResults, err := GetTestHistory(&params)
   973  			So(err, ShouldBeNil)
   974  			So(len(testResults), ShouldEqual, 3)
   975  			So(testResults[0].TaskId, ShouldEqual, "task1")
   976  		})
   977  		Convey("including a filter on an after revision, should only return exclusive results", func() {
   978  			params := TestHistoryParameters{
   979  				TaskNames:     []string{"test"},
   980  				Project:       project,
   981  				Sort:          1,
   982  				AfterRevision: testVersion.Revision,
   983  			}
   984  			So(params.SetDefaultsAndValidate(), ShouldBeNil)
   985  			testResults, err := GetTestHistory(&params)
   986  			So(err, ShouldBeNil)
   987  			So(len(testResults), ShouldEqual, 2)
   988  			So(testResults[0].TaskId, ShouldEqual, "task2")
   989  		})
   990  		Convey("including a filter on both before and after revision should return relevant results", func() {
   991  			params := TestHistoryParameters{
   992  				TaskNames:      []string{"test"},
   993  				Project:        project,
   994  				Sort:           1,
   995  				BeforeRevision: testVersion2.Revision,
   996  				AfterRevision:  testVersion.Revision,
   997  			}
   998  			So(params.SetDefaultsAndValidate(), ShouldBeNil)
   999  			testResults, err := GetTestHistory(&params)
  1000  			So(err, ShouldBeNil)
  1001  			So(len(testResults), ShouldEqual, 2)
  1002  			So(testResults[0].TaskId, ShouldEqual, "task2")
  1003  		})
  1004  		Convey("including a filter on a before start time should return relevant results", func() {
  1005  			params := TestHistoryParameters{
  1006  				TaskNames:  []string{"test"},
  1007  				Project:    project,
  1008  				BeforeDate: now.Add(time.Duration(15 * time.Minute)),
  1009  				Limit:      20,
  1010  			}
  1011  			So(params.SetDefaultsAndValidate(), ShouldBeNil)
  1012  			testResults, err := GetTestHistory(&params)
  1013  			So(err, ShouldBeNil)
  1014  			So(len(testResults), ShouldEqual, 1)
  1015  
  1016  		})
  1017  		Convey("including a filter on an after start time should return relevant results", func() {
  1018  			params := TestHistoryParameters{
  1019  				TaskNames: []string{"test"},
  1020  				Project:   project,
  1021  				AfterDate: now,
  1022  				Limit:     20,
  1023  			}
  1024  			So(params.SetDefaultsAndValidate(), ShouldBeNil)
  1025  			testResults, err := GetTestHistory(&params)
  1026  			So(err, ShouldBeNil)
  1027  			So(len(testResults), ShouldEqual, 3)
  1028  		})
  1029  		Convey("including a filter on test status of 'silentfail' should return relevant results", func() {
  1030  			params := TestHistoryParameters{
  1031  				Project:      project,
  1032  				TaskNames:    []string{"test2"},
  1033  				TestStatuses: []string{evergreen.TestSilentlyFailedStatus},
  1034  				Limit:        20,
  1035  			}
  1036  			So(params.SetDefaultsAndValidate(), ShouldBeNil)
  1037  			testResults, err := GetTestHistory(&params)
  1038  			So(err, ShouldBeNil)
  1039  			So(len(testResults), ShouldEqual, 1)
  1040  		})
  1041  		Convey("with a task with a different build variant,", func() {
  1042  			anotherBV := task.Task{
  1043  				Id:                  "task5",
  1044  				DisplayName:         "test",
  1045  				BuildVariant:        "bv2",
  1046  				Project:             project,
  1047  				StartTime:           now,
  1048  				RevisionOrderNumber: 2,
  1049  				Status:              evergreen.TaskFailed,
  1050  				TestResults: []task.TestResult{
  1051  					task.TestResult{
  1052  						Status:   evergreen.TestFailedStatus,
  1053  						TestFile: "test1",
  1054  					},
  1055  					task.TestResult{
  1056  						Status:   evergreen.TestFailedStatus,
  1057  						TestFile: "test2",
  1058  					},
  1059  				},
  1060  			}
  1061  			So(anotherBV.Insert(), ShouldBeNil)
  1062  			Convey("including a filter on build variant should only return test results with that build variant", func() {
  1063  				params := TestHistoryParameters{
  1064  					TaskNames:     []string{"test"},
  1065  					Project:       project,
  1066  					BuildVariants: []string{"bv2"},
  1067  					Limit:         20,
  1068  				}
  1069  				So(params.SetDefaultsAndValidate(), ShouldBeNil)
  1070  				testResults, err := GetTestHistory(&params)
  1071  				So(err, ShouldBeNil)
  1072  				So(len(testResults), ShouldEqual, 2)
  1073  			})
  1074  			Convey("not having the filter should return all results", func() {
  1075  				params := TestHistoryParameters{
  1076  					TaskNames: []string{"test"},
  1077  					Project:   project,
  1078  					Limit:     20,
  1079  				}
  1080  				So(params.SetDefaultsAndValidate(), ShouldBeNil)
  1081  				testResults, err := GetTestHistory(&params)
  1082  				So(err, ShouldBeNil)
  1083  				So(len(testResults), ShouldEqual, 5)
  1084  			})
  1085  		})
  1086  		Convey("using a task with no test results", func() {
  1087  			noResults := task.Task{
  1088  				Id:                  "noResults",
  1089  				DisplayName:         "anothertest",
  1090  				BuildVariant:        "bv2",
  1091  				Project:             project,
  1092  				StartTime:           now,
  1093  				RevisionOrderNumber: 2,
  1094  				Status:              evergreen.TaskFailed,
  1095  			}
  1096  			So(noResults.Insert(), ShouldBeNil)
  1097  			params := TestHistoryParameters{
  1098  				TaskNames: []string{"anothertest"},
  1099  				Project:   project,
  1100  				Limit:     20,
  1101  			}
  1102  			So(params.SetDefaultsAndValidate(), ShouldBeNil)
  1103  			testResults, err := GetTestHistory(&params)
  1104  			So(err, ShouldBeNil)
  1105  			So(testResults, ShouldBeEmpty)
  1106  		})
  1107  		Convey("with tasks with different ordered test results", func() {
  1108  			diffOrder := task.Task{
  1109  				Id:                  "anotherTaskId",
  1110  				DisplayName:         "testTask",
  1111  				Project:             project,
  1112  				StartTime:           now,
  1113  				RevisionOrderNumber: 2,
  1114  				Status:              evergreen.TaskFailed,
  1115  				TestResults: []task.TestResult{
  1116  					task.TestResult{
  1117  						Status:   evergreen.TestFailedStatus,
  1118  						TestFile: "test2",
  1119  					},
  1120  					task.TestResult{
  1121  						Status:   evergreen.TestFailedStatus,
  1122  						TestFile: "test1",
  1123  					},
  1124  				},
  1125  			}
  1126  			So(diffOrder.Insert(), ShouldBeNil)
  1127  			diffOrder2 := task.Task{
  1128  				Id:                  "anotherTaskId2",
  1129  				DisplayName:         "testTask",
  1130  				Project:             project,
  1131  				StartTime:           now,
  1132  				RevisionOrderNumber: 1,
  1133  				Status:              evergreen.TaskFailed,
  1134  				TestResults: []task.TestResult{
  1135  					task.TestResult{
  1136  						Status:   evergreen.TestFailedStatus,
  1137  						TestFile: "test1",
  1138  					},
  1139  					task.TestResult{
  1140  						Status:   evergreen.TestFailedStatus,
  1141  						TestFile: "test2",
  1142  					},
  1143  				},
  1144  			}
  1145  			So(diffOrder2.Insert(), ShouldBeNil)
  1146  
  1147  			Convey("the order of the tests should be the same", func() {
  1148  				params := TestHistoryParameters{
  1149  					TaskNames: []string{"testTask"},
  1150  					Project:   project,
  1151  					Limit:     20,
  1152  				}
  1153  				So(params.SetDefaultsAndValidate(), ShouldBeNil)
  1154  				testResults, err := GetTestHistory(&params)
  1155  				So(err, ShouldBeNil)
  1156  				So(len(testResults), ShouldEqual, 4)
  1157  				So(testResults[0].TaskId, ShouldEqual, "anotherTaskId")
  1158  				So(testResults[0].TestFile, ShouldEqual, "test2")
  1159  				So(testResults[1].TaskId, ShouldEqual, "anotherTaskId")
  1160  				So(testResults[1].TestFile, ShouldEqual, "test1")
  1161  				So(testResults[2].TaskId, ShouldEqual, "anotherTaskId2")
  1162  				So(testResults[2].TestFile, ShouldEqual, "test2")
  1163  				So(testResults[3].TaskId, ShouldEqual, "anotherTaskId2")
  1164  				So(testResults[3].TestFile, ShouldEqual, "test1")
  1165  
  1166  			})
  1167  
  1168  		})
  1169  		Convey("using test parameter with a task status with timeouts", func() {
  1170  			timedOutTask := task.Task{
  1171  				Id:                  "timeout",
  1172  				DisplayName:         "test",
  1173  				Project:             project,
  1174  				StartTime:           now,
  1175  				RevisionOrderNumber: 1,
  1176  
  1177  				Status: evergreen.TaskFailed,
  1178  				Details: apimodels.TaskEndDetail{
  1179  					TimedOut: true,
  1180  				},
  1181  				TestResults: []task.TestResult{
  1182  					task.TestResult{
  1183  						Status:   evergreen.TestFailedStatus,
  1184  						TestFile: "test2",
  1185  					},
  1186  				},
  1187  			}
  1188  			So(timedOutTask.Insert(), ShouldBeNil)
  1189  			params := TestHistoryParameters{
  1190  				Project:      project,
  1191  				TaskNames:    []string{"test"},
  1192  				TaskStatuses: []string{TaskTimeout},
  1193  				Limit:        20,
  1194  			}
  1195  			So(params.SetDefaultsAndValidate(), ShouldBeNil)
  1196  			testResults, err := GetTestHistory(&params)
  1197  			So(err, ShouldBeNil)
  1198  			So(len(testResults), ShouldEqual, 1)
  1199  		})
  1200  		Convey("using test parameter with a task status with system failures", func() {
  1201  			systemFailureTask := task.Task{
  1202  				Id:                  "systemfailed",
  1203  				DisplayName:         "test",
  1204  				Project:             project,
  1205  				StartTime:           now,
  1206  				RevisionOrderNumber: 1,
  1207  
  1208  				Status: evergreen.TaskFailed,
  1209  				Details: apimodels.TaskEndDetail{
  1210  					Type: "system",
  1211  				},
  1212  				TestResults: []task.TestResult{
  1213  					task.TestResult{
  1214  						Status:   evergreen.TestFailedStatus,
  1215  						TestFile: "test2",
  1216  					},
  1217  				},
  1218  			}
  1219  			So(systemFailureTask.Insert(), ShouldBeNil)
  1220  			params := TestHistoryParameters{
  1221  				Project:      project,
  1222  				TaskNames:    []string{"test"},
  1223  				TaskStatuses: []string{TaskSystemFailure},
  1224  				Limit:        20,
  1225  			}
  1226  			So(params.SetDefaultsAndValidate(), ShouldBeNil)
  1227  			testResults, err := GetTestHistory(&params)
  1228  			So(err, ShouldBeNil)
  1229  			So(len(testResults), ShouldEqual, 1)
  1230  			So(testResults[0].TestFile, ShouldEqual, "test2")
  1231  			So(testResults[0].TaskDetailsType, ShouldEqual, "system")
  1232  		})
  1233  
  1234  	})
  1235  }