func TestFlaggingIdleHosts(t *testing.T) { testConfig := evergreen.TestConfig() db.SetGlobalSessionProvider(db.SessionFactoryFromConfig(testConfig)) Convey("When flagging idle hosts to be terminated", t, func() { // reset the db testutil.HandleTestingErr(db.ClearCollections(host.Collection), t, "error clearing hosts collection") Convey("hosts currently running a task should never be"+ " flagged", func() { // insert a host that is currently running a task - but whose // creation time would otherwise indicate it has been idle a while host1 := host.Host{ Id: "h1", Provider: mock.ProviderName, CreationTime: time.Now().Add(-30 * time.Minute), RunningTask: "t1", Status: evergreen.HostRunning, StartedBy: evergreen.User, } testutil.HandleTestingErr(host1.Insert(), t, "error inserting host") // finding idle hosts should not return the host idle, err := flagIdleHosts(nil, nil) So(err, ShouldBeNil) So(len(idle), ShouldEqual, 0) }) Convey("hosts not currently running a task should be flagged if they"+ " have been idle at least 15 minutes and will incur a payment in"+ " less than 10 minutes", func() { // insert two hosts - one whose last task was more than 15 minutes // ago, one whose last task was less than 15 minutes ago host1 := host.Host{ Id: "h1", Provider: mock.ProviderName, LastTaskCompleted: "t1", LastTaskCompletedTime: time.Now().Add(-time.Minute * 20), Status: evergreen.HostRunning, StartedBy: evergreen.User, } testutil.HandleTestingErr(host1.Insert(), t, "error inserting host") host2 := host.Host{ Id: "h2", Provider: mock.ProviderName, LastTaskCompleted: "t2", LastTaskCompletedTime: time.Now().Add(-time.Minute * 5), Status: evergreen.HostRunning, StartedBy: evergreen.User, } testutil.HandleTestingErr(host2.Insert(), t, "error inserting host") // finding idle hosts should only return the first host idle, err := flagIdleHosts(nil, nil) So(err, ShouldBeNil) So(len(idle), ShouldEqual, 1) So(idle[0].Id, ShouldEqual, "h1") }) }) }
func TestMarkAsDispatched(t *testing.T) { var ( taskId string hostId string buildId string task *Task myHost *host.Host b *build.Build ) Convey("With a task", t, func() { taskId = "t1" hostId = "h1" buildId = "b1" task = &Task{ Id: taskId, BuildId: buildId, } myHost = &host.Host{ Id: hostId, } b = &build.Build{ Id: buildId, Tasks: []build.TaskCache{ {Id: taskId}, }, } testutil.HandleTestingErr( db.ClearCollections(TasksCollection, build.Collection, host.Collection), t, "Error clearing test collections") So(task.Insert(), ShouldBeNil) So(myHost.Insert(), ShouldBeNil) So(b.Insert(), ShouldBeNil) Convey("when marking the task as dispatched, the fields for"+ " the task, the host it is on, and the build it is a part of"+ " should be set to reflect this", func() { // mark the task as dispatched So(task.MarkAsDispatched(myHost, time.Now()), ShouldBeNil) // make sure the task's fields were updated, both in memory and // in the db So(task.DispatchTime, ShouldNotResemble, time.Unix(0, 0)) So(task.Status, ShouldEqual, evergreen.TaskDispatched) So(task.HostId, ShouldEqual, myHost.Id) So(task.LastHeartbeat, ShouldResemble, task.DispatchTime) task, err := FindTask(taskId) So(err, ShouldBeNil) So(task.DispatchTime, ShouldNotResemble, time.Unix(0, 0)) So(task.Status, ShouldEqual, evergreen.TaskDispatched) So(task.HostId, ShouldEqual, myHost.Id) So(task.LastHeartbeat, ShouldResemble, task.DispatchTime) // make sure the build's fields were updated in the db b, err = build.FindOne(build.ById(buildId)) So(err, ShouldBeNil) So(b.Tasks[0].Status, ShouldEqual, evergreen.TaskDispatched) }) }) }
func TestCreateHostBuckets(t *testing.T) { testutil.HandleTestingErr(db.ClearCollections(host.Collection), t, "couldnt reset host") Convey("With a starting time and a minute bucket size and inserting dynamic hosts with different time frames", t, func() { now := time.Now() bucketSize := time.Duration(10) * time.Second // -20 -> 20 beforeStartHost := host.Host{Id: "beforeStartHost", CreationTime: now.Add(time.Duration(-20) * time.Second), TerminationTime: now.Add(time.Duration(20) * time.Second), Provider: "ec2"} So(beforeStartHost.Insert(), ShouldBeNil) // 80 -> 120 afterEndHost := host.Host{Id: "afterEndHost", CreationTime: now.Add(time.Duration(80) * time.Second), TerminationTime: now.Add(time.Duration(120) * time.Second), Provider: "ec2"} So(afterEndHost.Insert(), ShouldBeNil) // 20 -> 40 h1 := host.Host{Id: "h1", CreationTime: now.Add(time.Duration(20) * time.Second), TerminationTime: now.Add(time.Duration(40) * time.Second), Provider: "ec2"} So(h1.Insert(), ShouldBeNil) // 10 -> 80 h2 := host.Host{Id: "h2", CreationTime: now.Add(time.Duration(10) * time.Second), TerminationTime: now.Add(time.Duration(80) * time.Second), Provider: "ec2"} So(h2.Insert(), ShouldBeNil) // 20 -> h3 := host.Host{Id: "h3", CreationTime: now.Add(time.Duration(20) * time.Second), TerminationTime: util.ZeroTime, Provider: "ec2", Status: evergreen.HostRunning} So(h3.Insert(), ShouldBeNil) // 5 -> 7 sameBucket := host.Host{Id: "sameBucket", CreationTime: now.Add(time.Duration(5) * time.Second), TerminationTime: now.Add(time.Duration(7) * time.Second), Provider: "ec2"} So(sameBucket.Insert(), ShouldBeNil) // 5 -> 30 h4 := host.Host{Id: "h4", CreationTime: now.Add(time.Duration(5) * time.Second), TerminationTime: now.Add(time.Duration(30) * time.Second), Provider: "ec2"} So(h4.Insert(), ShouldBeNil) Convey("for three buckets of 10 seconds, should only retrieve pertinent host docs", func() { endTime := now.Add(time.Duration(30) * time.Second) hosts, err := host.Find(host.ByDynamicWithinTime(now, endTime)) So(err, ShouldBeNil) So(len(hosts), ShouldEqual, 6) frameBounds := FrameBounds{ StartTime: now, EndTime: endTime, BucketSize: bucketSize, NumberBuckets: 3, } Convey("should create the correct buckets and bucket time accordingly", func() { buckets, errors := CreateHostBuckets(hosts, frameBounds) So(errors, ShouldBeEmpty) So(len(buckets), ShouldEqual, 3) So(int(buckets[0].TotalTime.Seconds()), ShouldEqual, 17) So(int(buckets[1].TotalTime.Seconds()), ShouldEqual, 30) So(int(math.Ceil(buckets[2].TotalTime.Seconds())), ShouldEqual, 40) }) }) }) }