github.com/justinjmoses/evergreen@v0.0.0-20170530173719-1d50e381ff0d/model/task_lifecycle_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/build"
    12  	"github.com/evergreen-ci/evergreen/model/task"
    13  	"github.com/evergreen-ci/evergreen/model/version"
    14  	"github.com/evergreen-ci/evergreen/testutil"
    15  	"github.com/evergreen-ci/evergreen/util"
    16  	. "github.com/smartystreets/goconvey/convey"
    17  )
    18  
    19  var (
    20  	oneMs = time.Millisecond
    21  )
    22  
    23  func init() {
    24  	db.SetGlobalSessionProvider(db.SessionFactoryFromConfig(testutil.TestConfig()))
    25  }
    26  
    27  func TestSetActiveState(t *testing.T) {
    28  	Convey("With one task with no dependencies", t, func() {
    29  		testutil.HandleTestingErr(db.ClearCollections(task.Collection, build.Collection), t,
    30  			"Error clearing task and build collections")
    31  		var err error
    32  
    33  		displayName := "testName"
    34  		userName := "testUser"
    35  		testTime := time.Now()
    36  		b := &build.Build{
    37  			Id: "buildtest",
    38  		}
    39  		testTask := &task.Task{
    40  			Id:            "testone",
    41  			DisplayName:   displayName,
    42  			ScheduledTime: testTime,
    43  			Activated:     false,
    44  			BuildId:       b.Id,
    45  		}
    46  		b.Tasks = []build.TaskCache{{Id: testTask.Id}}
    47  
    48  		So(b.Insert(), ShouldBeNil)
    49  		So(testTask.Insert(), ShouldBeNil)
    50  
    51  		Convey("activating the task should set the task state to active", func() {
    52  			So(SetActiveState(testTask.Id, "randomUser", true), ShouldBeNil)
    53  			testTask, err = task.FindOne(task.ById(testTask.Id))
    54  			So(err, ShouldBeNil)
    55  			So(testTask.Activated, ShouldBeTrue)
    56  			So(testTask.ScheduledTime, ShouldHappenWithin, oneMs, testTime)
    57  
    58  			Convey("deactivating an active task as a normal user should deactivate the task", func() {
    59  				So(SetActiveState(testTask.Id, userName, false), ShouldBeNil)
    60  				testTask, err = task.FindOne(task.ById(testTask.Id))
    61  				So(testTask.Activated, ShouldBeFalse)
    62  			})
    63  		})
    64  		Convey("when deactivating an active task as evergreen", func() {
    65  			Convey("if the task is activated by evergreen, the task should deactivate", func() {
    66  				So(SetActiveState(testTask.Id, evergreen.DefaultTaskActivator, true), ShouldBeNil)
    67  				testTask, err = task.FindOne(task.ById(testTask.Id))
    68  				So(err, ShouldBeNil)
    69  				So(testTask.ActivatedBy, ShouldEqual, evergreen.DefaultTaskActivator)
    70  				So(SetActiveState(testTask.Id, evergreen.DefaultTaskActivator, false), ShouldBeNil)
    71  				testTask, err = task.FindOne(task.ById(testTask.Id))
    72  				So(err, ShouldBeNil)
    73  				So(testTask.Activated, ShouldEqual, false)
    74  			})
    75  			Convey("if the task is activated by stepback user, the task should not deactivate", func() {
    76  				So(SetActiveState(testTask.Id, evergreen.StepbackTaskActivator, true), ShouldBeNil)
    77  				testTask, err = task.FindOne(task.ById(testTask.Id))
    78  				So(err, ShouldBeNil)
    79  				So(testTask.ActivatedBy, ShouldEqual, evergreen.StepbackTaskActivator)
    80  				So(SetActiveState(testTask.Id, evergreen.DefaultTaskActivator, false), ShouldBeNil)
    81  				testTask, err = task.FindOne(task.ById(testTask.Id))
    82  				So(err, ShouldBeNil)
    83  				So(testTask.Activated, ShouldEqual, true)
    84  			})
    85  			Convey("if the task is not activated by evergreen, the task should not deactivate", func() {
    86  				So(SetActiveState(testTask.Id, userName, true), ShouldBeNil)
    87  				testTask, err = task.FindOne(task.ById(testTask.Id))
    88  				So(err, ShouldBeNil)
    89  				So(testTask.ActivatedBy, ShouldEqual, userName)
    90  				So(SetActiveState(testTask.Id, evergreen.DefaultTaskActivator, false), ShouldBeNil)
    91  				testTask, err = task.FindOne(task.ById(testTask.Id))
    92  				So(err, ShouldBeNil)
    93  				So(testTask.Activated, ShouldEqual, true)
    94  			})
    95  
    96  		})
    97  		Convey("when deactivating an active task a normal user", func() {
    98  			u := "test_user"
    99  			Convey("if the task is activated by evergreen, the task should deactivate", func() {
   100  				So(SetActiveState(testTask.Id, evergreen.DefaultTaskActivator, true), ShouldBeNil)
   101  				testTask, err = task.FindOne(task.ById(testTask.Id))
   102  				So(err, ShouldBeNil)
   103  				So(testTask.ActivatedBy, ShouldEqual, evergreen.DefaultTaskActivator)
   104  				So(SetActiveState(testTask.Id, u, false), ShouldBeNil)
   105  				testTask, err = task.FindOne(task.ById(testTask.Id))
   106  				So(err, ShouldBeNil)
   107  				So(testTask.Activated, ShouldEqual, false)
   108  			})
   109  			Convey("if the task is activated by stepback user, the task should deactivate", func() {
   110  				So(SetActiveState(testTask.Id, evergreen.StepbackTaskActivator, true), ShouldBeNil)
   111  				testTask, err = task.FindOne(task.ById(testTask.Id))
   112  				So(err, ShouldBeNil)
   113  				So(testTask.ActivatedBy, ShouldEqual, evergreen.StepbackTaskActivator)
   114  				So(SetActiveState(testTask.Id, u, false), ShouldBeNil)
   115  				testTask, err = task.FindOne(task.ById(testTask.Id))
   116  				So(err, ShouldBeNil)
   117  				So(testTask.Activated, ShouldEqual, false)
   118  			})
   119  			Convey("if the task is not activated by evergreen, the task should deactivate", func() {
   120  				So(SetActiveState(testTask.Id, userName, true), ShouldBeNil)
   121  				testTask, err = task.FindOne(task.ById(testTask.Id))
   122  				So(err, ShouldBeNil)
   123  				So(testTask.ActivatedBy, ShouldEqual, userName)
   124  				So(SetActiveState(testTask.Id, u, false), ShouldBeNil)
   125  				testTask, err = task.FindOne(task.ById(testTask.Id))
   126  				So(err, ShouldBeNil)
   127  				So(testTask.Activated, ShouldEqual, false)
   128  			})
   129  
   130  		})
   131  	})
   132  	Convey("With one task has tasks it depends on", t, func() {
   133  		testutil.HandleTestingErr(db.ClearCollections(task.Collection, build.Collection), t,
   134  			"Error clearing task and build collections")
   135  		displayName := "testName"
   136  		userName := "testUser"
   137  		testTime := time.Now()
   138  		taskId := "t1"
   139  		buildId := "b1"
   140  
   141  		dep1 := &task.Task{
   142  			Id:            "t2",
   143  			ScheduledTime: testTime,
   144  			BuildId:       buildId,
   145  		}
   146  		dep2 := &task.Task{
   147  			Id:            "t3",
   148  			ScheduledTime: testTime,
   149  			BuildId:       buildId,
   150  		}
   151  		So(dep1.Insert(), ShouldBeNil)
   152  		So(dep2.Insert(), ShouldBeNil)
   153  
   154  		testTask := task.Task{
   155  			Id:          taskId,
   156  			DisplayName: displayName,
   157  			Activated:   false,
   158  			BuildId:     buildId,
   159  			DependsOn: []task.Dependency{
   160  				{"t2", evergreen.TaskSucceeded},
   161  				{"t3", evergreen.TaskSucceeded},
   162  			},
   163  		}
   164  
   165  		b := &build.Build{
   166  			Id:    buildId,
   167  			Tasks: []build.TaskCache{{Id: taskId}, {Id: "t2"}, {Id: "t3"}},
   168  		}
   169  		So(b.Insert(), ShouldBeNil)
   170  		So(testTask.Insert(), ShouldBeNil)
   171  
   172  		Convey("activating the task should activate the tasks it depends on", func() {
   173  			So(SetActiveState(testTask.Id, userName, true), ShouldBeNil)
   174  			depTask, err := task.FindOne(task.ById(dep1.Id))
   175  			So(err, ShouldBeNil)
   176  			So(depTask.Activated, ShouldBeTrue)
   177  
   178  			depTask, err = task.FindOne(task.ById(dep2.Id))
   179  			So(err, ShouldBeNil)
   180  			So(depTask.Activated, ShouldBeTrue)
   181  
   182  			Convey("deactivating the task should not deactive the tasks it depends on", func() {
   183  				So(SetActiveState(testTask.Id, userName, false), ShouldBeNil)
   184  				depTask, err = task.FindOne(task.ById(depTask.Id))
   185  				So(err, ShouldBeNil)
   186  				So(depTask.Activated, ShouldBeTrue)
   187  			})
   188  		})
   189  	})
   190  }
   191  
   192  func TestActivatePreviousTask(t *testing.T) {
   193  	Convey("With two tasks and a build", t, func() {
   194  		testutil.HandleTestingErr(db.ClearCollections(task.Collection, build.Collection), t,
   195  			"Error clearing task and build collections")
   196  		// create two tasks
   197  		displayName := "testTask"
   198  		b := &build.Build{
   199  			Id: "testBuild",
   200  		}
   201  		previousTask := &task.Task{
   202  			Id:                  "one",
   203  			DisplayName:         displayName,
   204  			RevisionOrderNumber: 1,
   205  			Priority:            1,
   206  			Activated:           false,
   207  			BuildId:             b.Id,
   208  		}
   209  		currentTask := &task.Task{
   210  			Id:                  "two",
   211  			DisplayName:         displayName,
   212  			RevisionOrderNumber: 2,
   213  			Status:              evergreen.TaskFailed,
   214  			Priority:            1,
   215  			Activated:           true,
   216  			BuildId:             b.Id,
   217  		}
   218  		tc := []build.TaskCache{
   219  			{
   220  				DisplayName: displayName,
   221  				Id:          previousTask.Id,
   222  			},
   223  			{
   224  				DisplayName: displayName,
   225  				Id:          currentTask.Id,
   226  			},
   227  		}
   228  		b.Tasks = tc
   229  		So(b.Insert(), ShouldBeNil)
   230  		So(previousTask.Insert(), ShouldBeNil)
   231  		So(currentTask.Insert(), ShouldBeNil)
   232  		Convey("activating a previous task should set the previous task's active field to true", func() {
   233  			So(ActivatePreviousTask(currentTask.Id, ""), ShouldBeNil)
   234  			t, err := task.FindOne(task.ById(previousTask.Id))
   235  			So(err, ShouldBeNil)
   236  			So(t.Activated, ShouldBeTrue)
   237  		})
   238  	})
   239  }
   240  
   241  func TestDeactivatePreviousTask(t *testing.T) {
   242  	Convey("With two tasks and a build", t, func() {
   243  		testutil.HandleTestingErr(db.ClearCollections(task.Collection, build.Collection), t,
   244  			"Error clearing task and build collections")
   245  		// create two tasks
   246  		displayName := "testTask"
   247  		userName := "user"
   248  		b := &build.Build{
   249  			Id: "testBuild",
   250  		}
   251  		previousTask := &task.Task{
   252  			Id:                  "one",
   253  			DisplayName:         displayName,
   254  			RevisionOrderNumber: 1,
   255  			Priority:            1,
   256  			Activated:           true,
   257  			ActivatedBy:         "user",
   258  			BuildId:             b.Id,
   259  			Status:              evergreen.TaskUndispatched,
   260  			Project:             "sample",
   261  		}
   262  		currentTask := &task.Task{
   263  			Id:                  "two",
   264  			DisplayName:         displayName,
   265  			RevisionOrderNumber: 2,
   266  			Status:              evergreen.TaskFailed,
   267  			Priority:            1,
   268  			Activated:           true,
   269  			BuildId:             b.Id,
   270  			Project:             "sample",
   271  		}
   272  		tc := []build.TaskCache{
   273  			{
   274  				DisplayName: displayName,
   275  				Id:          previousTask.Id,
   276  			},
   277  			{
   278  				DisplayName: displayName,
   279  				Id:          currentTask.Id,
   280  			},
   281  		}
   282  		b.Tasks = tc
   283  		So(b.Insert(), ShouldBeNil)
   284  		So(previousTask.Insert(), ShouldBeNil)
   285  		So(currentTask.Insert(), ShouldBeNil)
   286  		Convey("activating a previous task should set the previous task's active field to true", func() {
   287  			So(DeactivatePreviousTasks(currentTask.Id, userName), ShouldBeNil)
   288  			previousTask, err := task.FindOne(task.ById(previousTask.Id))
   289  			So(err, ShouldBeNil)
   290  			So(previousTask.Activated, ShouldBeFalse)
   291  		})
   292  	})
   293  }
   294  
   295  func TestUpdateBuildStatusForTask(t *testing.T) {
   296  	Convey("With two tasks and a build", t, func() {
   297  		testutil.HandleTestingErr(db.ClearCollections(task.Collection, build.Collection, version.Collection), t,
   298  			"Error clearing task and build collections")
   299  		displayName := "testName"
   300  		b := &build.Build{
   301  			Id:      "buildtest",
   302  			Status:  evergreen.BuildStarted,
   303  			Version: "abc",
   304  		}
   305  		v := &version.Version{
   306  			Id:     b.Version,
   307  			Status: evergreen.VersionStarted,
   308  		}
   309  		testTask := task.Task{
   310  			Id:          "testone",
   311  			DisplayName: displayName,
   312  			Activated:   false,
   313  			BuildId:     b.Id,
   314  			Project:     "sample",
   315  			Status:      evergreen.TaskFailed,
   316  		}
   317  		anotherTask := task.Task{
   318  			Id:          "two",
   319  			DisplayName: displayName,
   320  			Activated:   true,
   321  			BuildId:     b.Id,
   322  			Project:     "sample",
   323  			Status:      evergreen.TaskFailed,
   324  		}
   325  
   326  		b.Tasks = []build.TaskCache{
   327  			{
   328  				Id:     testTask.Id,
   329  				Status: evergreen.TaskSucceeded,
   330  			},
   331  			{
   332  				Id:     anotherTask.Id,
   333  				Status: evergreen.TaskFailed,
   334  			},
   335  		}
   336  		So(b.Insert(), ShouldBeNil)
   337  		So(testTask.Insert(), ShouldBeNil)
   338  		So(anotherTask.Insert(), ShouldBeNil)
   339  		So(v.Insert(), ShouldBeNil)
   340  		Convey("updating the build for a task should update the build's status and the version's status", func() {
   341  			So(UpdateBuildAndVersionStatusForTask(testTask.Id), ShouldBeNil)
   342  			b, err := build.FindOne(build.ById(b.Id))
   343  			So(err, ShouldBeNil)
   344  			So(b.Status, ShouldEqual, evergreen.BuildFailed)
   345  			v, err = version.FindOne(version.ById(v.Id))
   346  			So(err, ShouldBeNil)
   347  			So(v.Status, ShouldEqual, evergreen.VersionFailed)
   348  		})
   349  	})
   350  }
   351  
   352  func TestTaskStatusImpactedByFailedTest(t *testing.T) {
   353  	Convey("With a successful task one failed test should result in a task failure", t, func() {
   354  		displayName := "testName"
   355  
   356  		var (
   357  			b        *build.Build
   358  			v        *version.Version
   359  			testTask *task.Task
   360  			p        *Project
   361  			detail   *apimodels.TaskEndDetail
   362  		)
   363  
   364  		reset := func() {
   365  			b = &build.Build{
   366  				Id:      "buildtest",
   367  				Version: "abc",
   368  				Tasks: []build.TaskCache{
   369  					{Id: "testone"},
   370  				},
   371  			}
   372  			v = &version.Version{
   373  				Id:     b.Version,
   374  				Status: evergreen.VersionStarted,
   375  			}
   376  			testTask = &task.Task{
   377  				Id:          "testone",
   378  				DisplayName: displayName,
   379  				Activated:   false,
   380  				BuildId:     b.Id,
   381  				Project:     "sample",
   382  			}
   383  			p = &Project{
   384  				Identifier: "sample",
   385  			}
   386  			detail = &apimodels.TaskEndDetail{
   387  				Status: evergreen.TaskSucceeded,
   388  			}
   389  
   390  			testutil.HandleTestingErr(db.ClearCollections(task.Collection, build.Collection, version.Collection), t,
   391  				"Error clearing task and build collections")
   392  			So(b.Insert(), ShouldBeNil)
   393  			So(testTask.Insert(), ShouldBeNil)
   394  			So(v.Insert(), ShouldBeNil)
   395  		}
   396  
   397  		Convey("task should not fail if there are no failed test", func() {
   398  			reset()
   399  			So(MarkEnd(testTask.Id, "", time.Now(), detail, p, true), ShouldBeNil)
   400  
   401  			taskData, err := task.FindOne(task.ById(testTask.Id))
   402  			So(err, ShouldBeNil)
   403  			So(taskData.Status, ShouldEqual, evergreen.TaskSucceeded)
   404  			buildCache, err := build.FindOne(build.ById(b.Id))
   405  			So(err, ShouldBeNil)
   406  			So(buildCache.Status, ShouldEqual, evergreen.TaskSucceeded)
   407  			for _, t := range buildCache.Tasks {
   408  				So(t.Status, ShouldEqual, evergreen.TaskSucceeded)
   409  			}
   410  
   411  		})
   412  
   413  		Convey("task should not fail if there are only passing or silently failing tests", func() {
   414  			reset()
   415  			err := testTask.SetResults([]task.TestResult{
   416  				{
   417  					Status: evergreen.TestSilentlyFailedStatus,
   418  				},
   419  				{
   420  					Status: evergreen.TestSucceededStatus,
   421  				},
   422  				{
   423  					Status: evergreen.TestSilentlyFailedStatus,
   424  				},
   425  			})
   426  			So(err, ShouldBeNil)
   427  			So(MarkEnd(testTask.Id, "", time.Now(), detail, p, true), ShouldBeNil)
   428  
   429  			taskData, err := task.FindOne(task.ById(testTask.Id))
   430  			So(err, ShouldBeNil)
   431  			So(taskData.Status, ShouldEqual, evergreen.TaskSucceeded)
   432  			buildCache, err := build.FindOne(build.ById(b.Id))
   433  			So(err, ShouldBeNil)
   434  			So(buildCache.Status, ShouldEqual, evergreen.TaskSucceeded)
   435  			for _, t := range buildCache.Tasks {
   436  				So(t.Status, ShouldEqual, evergreen.TaskSucceeded)
   437  			}
   438  		})
   439  
   440  		Convey("task should fail if there is one failed test", func() {
   441  			reset()
   442  			err := testTask.SetResults([]task.TestResult{
   443  				{
   444  					Status: evergreen.TestFailedStatus,
   445  				},
   446  			})
   447  
   448  			So(err, ShouldBeNil)
   449  			detail.Status = evergreen.TaskFailed
   450  			So(MarkEnd(testTask.Id, "", time.Now(), detail, p, true), ShouldBeNil)
   451  
   452  			taskData, err := task.FindOne(task.ById(testTask.Id))
   453  			So(err, ShouldBeNil)
   454  			So(taskData.Status, ShouldEqual, evergreen.TaskFailed)
   455  			buildCache, err := build.FindOne(build.ById(b.Id))
   456  			So(err, ShouldBeNil)
   457  			So(buildCache.Status, ShouldEqual, evergreen.TaskFailed)
   458  		})
   459  
   460  		Convey("test failures should update the task cache", func() {
   461  			reset()
   462  			err := testTask.SetResults([]task.TestResult{
   463  				{
   464  					Status: evergreen.TestFailedStatus,
   465  				},
   466  			})
   467  			So(err, ShouldBeNil)
   468  			detail.Status = evergreen.TaskFailed
   469  			So(MarkEnd(testTask.Id, "", time.Now(), detail, p, true), ShouldBeNil)
   470  
   471  			So(UpdateBuildAndVersionStatusForTask(testTask.Id), ShouldBeNil)
   472  			buildCache, err := build.FindOne(build.ById(b.Id))
   473  			So(err, ShouldBeNil)
   474  			So(buildCache.Status, ShouldEqual, evergreen.TaskFailed)
   475  
   476  			var hasFailedTask bool
   477  			for _, t := range buildCache.Tasks {
   478  				if t.Status == evergreen.TaskFailed {
   479  					hasFailedTask = true
   480  				}
   481  			}
   482  			So(hasFailedTask, ShouldBeTrue)
   483  		})
   484  	})
   485  }
   486  
   487  func TestMarkEnd(t *testing.T) {
   488  	Convey("With a task and a build", t, func() {
   489  		testutil.HandleTestingErr(db.ClearCollections(task.Collection, build.Collection, version.Collection), t,
   490  			"Error clearing task and build collections")
   491  		displayName := "testName"
   492  		userName := "testUser"
   493  		b := &build.Build{
   494  			Id:      "buildtest",
   495  			Status:  evergreen.BuildStarted,
   496  			Version: "abc",
   497  		}
   498  		p := &Project{
   499  			Identifier: "sample",
   500  		}
   501  		v := &version.Version{
   502  			Id:     b.Version,
   503  			Status: evergreen.VersionStarted,
   504  		}
   505  		testTask := task.Task{
   506  			Id:          "testone",
   507  			DisplayName: displayName,
   508  			Activated:   true,
   509  			BuildId:     b.Id,
   510  			Project:     "sample",
   511  			Status:      evergreen.TaskStarted,
   512  		}
   513  
   514  		b.Tasks = []build.TaskCache{
   515  			{
   516  				Id:     testTask.Id,
   517  				Status: evergreen.TaskStarted,
   518  			},
   519  		}
   520  		So(b.Insert(), ShouldBeNil)
   521  		So(testTask.Insert(), ShouldBeNil)
   522  		So(v.Insert(), ShouldBeNil)
   523  		Convey("task, build and version status will be updated properly", func() {
   524  			details := apimodels.TaskEndDetail{
   525  				Status: evergreen.TaskFailed,
   526  			}
   527  			So(MarkEnd(testTask.Id, userName, time.Now(), &details, p, false), ShouldBeNil)
   528  
   529  		})
   530  	})
   531  }
   532  
   533  func TestTryResetTask(t *testing.T) {
   534  	Convey("With a task, a build, version and a project", t, func() {
   535  		Convey("resetting a task without a max number of executions", func() {
   536  			testutil.HandleTestingErr(db.ClearCollections(task.Collection, task.OldCollection, build.Collection, version.Collection), t,
   537  				"Error clearing task and build collections")
   538  			displayName := "testName"
   539  			userName := "testUser"
   540  			b := &build.Build{
   541  				Id:      "buildtest",
   542  				Status:  evergreen.BuildStarted,
   543  				Version: "abc",
   544  			}
   545  			v := &version.Version{
   546  				Id:     b.Version,
   547  				Status: evergreen.VersionStarted,
   548  			}
   549  			testTask := &task.Task{
   550  				Id:          "testone",
   551  				DisplayName: displayName,
   552  				Activated:   false,
   553  				BuildId:     b.Id,
   554  				Execution:   1,
   555  				Project:     "sample",
   556  				Status:      evergreen.TaskSucceeded,
   557  			}
   558  			p := &Project{
   559  				Identifier: "sample",
   560  			}
   561  			detail := &apimodels.TaskEndDetail{
   562  				Status: evergreen.TaskFailed,
   563  			}
   564  
   565  			b.Tasks = []build.TaskCache{
   566  				{
   567  					Id: testTask.Id,
   568  				},
   569  			}
   570  
   571  			var err error
   572  
   573  			So(b.Insert(), ShouldBeNil)
   574  			So(testTask.Insert(), ShouldBeNil)
   575  			So(v.Insert(), ShouldBeNil)
   576  			Convey("should reset and add a task to the old tasks collection", func() {
   577  				So(TryResetTask(testTask.Id, userName, "", p, detail), ShouldBeNil)
   578  				testTask, err = task.FindOne(task.ById(testTask.Id))
   579  				So(err, ShouldBeNil)
   580  				So(testTask.Details, ShouldResemble, apimodels.TaskEndDetail{})
   581  				So(testTask.Status, ShouldEqual, evergreen.TaskUndispatched)
   582  				So(testTask.FinishTime, ShouldResemble, util.ZeroTime)
   583  				oldTaskId := fmt.Sprintf("%v_%v", testTask.Id, 1)
   584  				fmt.Println(oldTaskId)
   585  				oldTask, err := task.FindOneOld(task.ById(oldTaskId))
   586  				So(err, ShouldBeNil)
   587  				So(oldTask, ShouldNotBeNil)
   588  				So(oldTask.Execution, ShouldEqual, 1)
   589  				So(oldTask.Details, ShouldResemble, *detail)
   590  				So(oldTask.FinishTime, ShouldNotResemble, util.ZeroTime)
   591  			})
   592  
   593  		})
   594  		Convey("resetting a task with a max number of excutions", func() {
   595  			testutil.HandleTestingErr(db.ClearCollections(task.Collection, build.Collection, version.Collection), t,
   596  				"Error clearing task and build collections")
   597  			displayName := "testName"
   598  			userName := "testUser"
   599  			b := &build.Build{
   600  				Id:      "buildtest",
   601  				Status:  evergreen.BuildStarted,
   602  				Version: "abc",
   603  			}
   604  			v := &version.Version{
   605  				Id:     b.Version,
   606  				Status: evergreen.VersionStarted,
   607  			}
   608  			testTask := &task.Task{
   609  				Id:          "testone",
   610  				DisplayName: displayName,
   611  				Activated:   false,
   612  				BuildId:     b.Id,
   613  				Execution:   evergreen.MaxTaskExecution,
   614  				Project:     "sample",
   615  				Status:      evergreen.TaskSucceeded,
   616  			}
   617  			p := &Project{
   618  				Identifier: "sample",
   619  			}
   620  			detail := &apimodels.TaskEndDetail{
   621  				Status: evergreen.TaskFailed,
   622  			}
   623  			anotherTask := &task.Task{
   624  				Id:          "two",
   625  				DisplayName: displayName,
   626  				Activated:   false,
   627  				BuildId:     b.Id,
   628  				Execution:   evergreen.MaxTaskExecution,
   629  				Project:     "sample",
   630  				Status:      evergreen.TaskSucceeded,
   631  			}
   632  			b.Tasks = []build.TaskCache{
   633  				{
   634  					Id: testTask.Id,
   635  				},
   636  				{
   637  					Id: anotherTask.Id,
   638  				},
   639  			}
   640  			So(b.Insert(), ShouldBeNil)
   641  			So(testTask.Insert(), ShouldBeNil)
   642  			So(v.Insert(), ShouldBeNil)
   643  			So(anotherTask.Insert(), ShouldBeNil)
   644  
   645  			var err error
   646  
   647  			Convey("should not reset if an origin other than the ui package tries to reset", func() {
   648  				So(TryResetTask(testTask.Id, userName, "", p, detail), ShouldBeNil)
   649  				testTask, err = task.FindOne(task.ById(testTask.Id))
   650  				So(err, ShouldBeNil)
   651  				So(testTask.Details, ShouldResemble, *detail)
   652  				So(testTask.Status, ShouldEqual, detail.Status)
   653  				So(testTask.FinishTime, ShouldNotResemble, util.ZeroTime)
   654  			})
   655  			Convey("should reset and use detail information if the UI package passes in a detail ", func() {
   656  				So(TryResetTask(anotherTask.Id, userName, evergreen.UIPackage, p, detail), ShouldBeNil)
   657  				a, err := task.FindOne(task.ById(anotherTask.Id))
   658  				So(err, ShouldBeNil)
   659  				So(a.Details, ShouldResemble, apimodels.TaskEndDetail{})
   660  				So(a.Status, ShouldEqual, evergreen.TaskUndispatched)
   661  				So(a.FinishTime, ShouldResemble, util.ZeroTime)
   662  			})
   663  		})
   664  	})
   665  }
   666  
   667  func TestAbortTask(t *testing.T) {
   668  	Convey("With a task and a build", t, func() {
   669  		testutil.HandleTestingErr(db.ClearCollections(task.Collection, build.Collection, version.Collection), t,
   670  			"Error clearing task, build, and version collections")
   671  		displayName := "testName"
   672  		userName := "testUser"
   673  		b := &build.Build{
   674  			Id: "buildtest",
   675  		}
   676  		testTask := &task.Task{
   677  			Id:          "testone",
   678  			DisplayName: displayName,
   679  			Activated:   false,
   680  			BuildId:     b.Id,
   681  			Status:      evergreen.TaskStarted,
   682  		}
   683  		finishedTask := &task.Task{
   684  			Id:          "another",
   685  			DisplayName: displayName,
   686  			Activated:   false,
   687  			BuildId:     b.Id,
   688  			Status:      evergreen.TaskFailed,
   689  		}
   690  		b.Tasks = []build.TaskCache{
   691  			{
   692  				Id: testTask.Id,
   693  			},
   694  			{
   695  				Id: finishedTask.Id,
   696  			},
   697  		}
   698  		So(b.Insert(), ShouldBeNil)
   699  		So(testTask.Insert(), ShouldBeNil)
   700  		So(finishedTask.Insert(), ShouldBeNil)
   701  		var err error
   702  		Convey("with a task that has started, aborting a task should work", func() {
   703  			So(AbortTask(testTask.Id, userName), ShouldBeNil)
   704  			testTask, err = task.FindOne(task.ById(testTask.Id))
   705  			So(err, ShouldBeNil)
   706  			So(testTask.Activated, ShouldEqual, false)
   707  			So(testTask.Aborted, ShouldEqual, true)
   708  		})
   709  		Convey("a task that is finished should error when aborting", func() {
   710  			So(AbortTask(finishedTask.Id, userName), ShouldNotBeNil)
   711  		})
   712  	})
   713  
   714  }
   715  func TestMarkStart(t *testing.T) {
   716  	Convey("With a task, build and version", t, func() {
   717  		testutil.HandleTestingErr(db.ClearCollections(task.Collection, build.Collection, version.Collection), t,
   718  			"Error clearing task and build collections")
   719  		displayName := "testName"
   720  		b := &build.Build{
   721  			Id:      "buildtest",
   722  			Status:  evergreen.BuildCreated,
   723  			Version: "abc",
   724  		}
   725  		v := &version.Version{
   726  			Id:     b.Version,
   727  			Status: evergreen.VersionCreated,
   728  		}
   729  		testTask := &task.Task{
   730  			Id:          "testTask",
   731  			DisplayName: displayName,
   732  			Activated:   true,
   733  			BuildId:     b.Id,
   734  			Project:     "sample",
   735  			Status:      evergreen.TaskUndispatched,
   736  			Version:     b.Version,
   737  		}
   738  
   739  		b.Tasks = []build.TaskCache{
   740  			{
   741  				Id:     testTask.Id,
   742  				Status: evergreen.TaskUndispatched,
   743  			},
   744  		}
   745  		So(b.Insert(), ShouldBeNil)
   746  		So(testTask.Insert(), ShouldBeNil)
   747  		So(v.Insert(), ShouldBeNil)
   748  
   749  		var err error
   750  
   751  		Convey("when calling MarkStart, the task, version and build should be updated", func() {
   752  			So(MarkStart(testTask.Id), ShouldBeNil)
   753  			testTask, err = task.FindOne(task.ById(testTask.Id))
   754  			So(err, ShouldBeNil)
   755  			So(testTask.Status, ShouldEqual, evergreen.TaskStarted)
   756  			b, err := build.FindOne(build.ById(b.Id))
   757  			So(err, ShouldBeNil)
   758  			So(b.Status, ShouldEqual, evergreen.BuildStarted)
   759  			So(b.Tasks, ShouldNotBeNil)
   760  			So(len(b.Tasks), ShouldEqual, 1)
   761  			So(b.Tasks[0].Status, ShouldEqual, evergreen.TaskStarted)
   762  			v, err := version.FindOne(version.ById(v.Id))
   763  			So(err, ShouldBeNil)
   764  			So(v.Status, ShouldEqual, evergreen.VersionStarted)
   765  		})
   766  	})
   767  }
   768  
   769  func TestMarkUndispatched(t *testing.T) {
   770  	Convey("With a task, build and version", t, func() {
   771  		testutil.HandleTestingErr(db.ClearCollections(task.Collection, build.Collection, version.Collection), t,
   772  			"Error clearing task and build collections")
   773  		displayName := "testName"
   774  		b := &build.Build{
   775  			Id:      "buildtest",
   776  			Status:  evergreen.BuildStarted,
   777  			Version: "abc",
   778  		}
   779  		v := &version.Version{
   780  			Id:     b.Version,
   781  			Status: evergreen.VersionStarted,
   782  		}
   783  		testTask := &task.Task{
   784  			Id:          "testTask",
   785  			DisplayName: displayName,
   786  			Activated:   true,
   787  			BuildId:     b.Id,
   788  			Project:     "sample",
   789  			Status:      evergreen.TaskStarted,
   790  			Version:     b.Version,
   791  		}
   792  
   793  		b.Tasks = []build.TaskCache{
   794  			{
   795  				Id:     testTask.Id,
   796  				Status: evergreen.TaskStarted,
   797  			},
   798  		}
   799  		So(b.Insert(), ShouldBeNil)
   800  		So(testTask.Insert(), ShouldBeNil)
   801  		So(v.Insert(), ShouldBeNil)
   802  		Convey("when calling MarkStart, the task, version and build should be updated", func() {
   803  			So(MarkTaskUndispatched(testTask), ShouldBeNil)
   804  			testTask, err := task.FindOne(task.ById(testTask.Id))
   805  			So(err, ShouldBeNil)
   806  			So(testTask.Status, ShouldEqual, evergreen.TaskUndispatched)
   807  			b, err := build.FindOne(build.ById(b.Id))
   808  			So(err, ShouldBeNil)
   809  			So(b.Tasks, ShouldNotBeNil)
   810  			So(len(b.Tasks), ShouldEqual, 1)
   811  			So(b.Tasks[0].Status, ShouldEqual, evergreen.TaskUndispatched)
   812  		})
   813  	})
   814  }
   815  
   816  func TestMarkDispatched(t *testing.T) {
   817  	Convey("With a task, build and version", t, func() {
   818  		testutil.HandleTestingErr(db.ClearCollections(task.Collection, build.Collection, version.Collection), t,
   819  			"Error clearing task and build collections")
   820  		displayName := "testName"
   821  		b := &build.Build{
   822  			Id:      "buildtest",
   823  			Status:  evergreen.BuildCreated,
   824  			Version: "abc",
   825  		}
   826  		testTask := &task.Task{
   827  			Id:          "testTask",
   828  			DisplayName: displayName,
   829  			Activated:   true,
   830  			BuildId:     b.Id,
   831  			Project:     "sample",
   832  			Status:      evergreen.TaskUndispatched,
   833  			Version:     b.Version,
   834  		}
   835  
   836  		b.Tasks = []build.TaskCache{
   837  			{
   838  				Id:     testTask.Id,
   839  				Status: evergreen.TaskUndispatched,
   840  			},
   841  		}
   842  		So(b.Insert(), ShouldBeNil)
   843  		So(testTask.Insert(), ShouldBeNil)
   844  		Convey("when calling MarkStart, the task, version and build should be updated", func() {
   845  			So(MarkTaskDispatched(testTask, "testHost", "distroId"), ShouldBeNil)
   846  			testTask, err := task.FindOne(task.ById(testTask.Id))
   847  			So(err, ShouldBeNil)
   848  			So(testTask.Status, ShouldEqual, evergreen.TaskDispatched)
   849  			So(testTask.HostId, ShouldEqual, "testHost")
   850  			So(testTask.DistroId, ShouldEqual, "distroId")
   851  			b, err := build.FindOne(build.ById(b.Id))
   852  			So(err, ShouldBeNil)
   853  			So(b.Tasks, ShouldNotBeNil)
   854  			So(len(b.Tasks), ShouldEqual, 1)
   855  			So(b.Tasks[0].Status, ShouldEqual, evergreen.TaskDispatched)
   856  		})
   857  	})
   858  }
   859  
   860  func TestGetstepback(t *testing.T) {
   861  	Convey("When the project has a stepback policy set to true", t, func() {
   862  		_true, _false := true, false
   863  		project := &Project{
   864  			Stepback: true,
   865  			BuildVariants: []BuildVariant{
   866  				{
   867  					Name: "sbnil",
   868  				},
   869  				{
   870  					Name:     "sbtrue",
   871  					Stepback: &_true,
   872  				},
   873  				{
   874  					Name:     "sbfalse",
   875  					Stepback: &_false,
   876  				},
   877  			},
   878  			Tasks: []ProjectTask{
   879  				{Name: "nil"},
   880  				{Name: "true", Stepback: &_true},
   881  				{Name: "false", Stepback: &_false},
   882  				{Name: "bvnil"},
   883  				{Name: "bvtrue"},
   884  				{Name: "bvfalse"},
   885  			},
   886  		}
   887  
   888  		Convey("if the task does not override the setting", func() {
   889  			testTask := &task.Task{Id: "t1", DisplayName: "nil"}
   890  			So(testTask.Insert(), ShouldBeNil)
   891  			Convey("then the value should be true", func() {
   892  				val, err := getStepback(testTask.Id, project)
   893  				So(err, ShouldBeNil)
   894  				So(val, ShouldBeTrue)
   895  			})
   896  		})
   897  
   898  		Convey("if the task overrides the setting with true", func() {
   899  			testTask := &task.Task{Id: "t2", DisplayName: "true"}
   900  			So(testTask.Insert(), ShouldBeNil)
   901  			Convey("then the value should be true", func() {
   902  				val, err := getStepback(testTask.Id, project)
   903  				So(err, ShouldBeNil)
   904  				So(val, ShouldBeTrue)
   905  			})
   906  		})
   907  
   908  		Convey("if the task overrides the setting with false", func() {
   909  			testTask := &task.Task{Id: "t3", DisplayName: "false"}
   910  			So(testTask.Insert(), ShouldBeNil)
   911  			Convey("then the value should be false", func() {
   912  				val, err := getStepback(testTask.Id, project)
   913  				So(err, ShouldBeNil)
   914  				So(val, ShouldBeFalse)
   915  			})
   916  		})
   917  
   918  		Convey("if the buildvariant does not override the setting", func() {
   919  			testTask := &task.Task{Id: "t4", DisplayName: "bvnil", BuildVariant: "sbnil"}
   920  			So(testTask.Insert(), ShouldBeNil)
   921  			Convey("then the value should be true", func() {
   922  				val, err := getStepback(testTask.Id, project)
   923  				So(err, ShouldBeNil)
   924  				So(val, ShouldBeTrue)
   925  			})
   926  		})
   927  
   928  		Convey("if the buildvariant overrides the setting with true", func() {
   929  			testTask := &task.Task{Id: "t5", DisplayName: "bvtrue", BuildVariant: "sbtrue"}
   930  			So(testTask.Insert(), ShouldBeNil)
   931  			Convey("then the value should be true", func() {
   932  				val, err := getStepback(testTask.Id, project)
   933  				So(err, ShouldBeNil)
   934  				So(val, ShouldBeTrue)
   935  			})
   936  		})
   937  
   938  		Convey("if the buildvariant overrides the setting with false", func() {
   939  			testTask := &task.Task{Id: "t6", DisplayName: "bvfalse", BuildVariant: "sbfalse"}
   940  			So(testTask.Insert(), ShouldBeNil)
   941  			Convey("then the value should be false", func() {
   942  				val, err := getStepback(testTask.Id, project)
   943  				So(err, ShouldBeNil)
   944  				So(val, ShouldBeFalse)
   945  			})
   946  		})
   947  
   948  	})
   949  }