Example #1
0
func TestExistingFailedTaskTriggers(t *testing.T) {
	Convey("With a previously failed instance of task in the database", t, func() {
		db.Clear(task.Collection)
		db.Clear(model.ProjectRefCollection)
		db.Clear(version.Collection)
		So(testProject.Insert(), ShouldBeNil)
		So(testVersion.Insert(), ShouldBeNil)
		testTask.Status = evergreen.TaskFailed
		err := testTask.Insert()
		So(err, ShouldBeNil)
		Convey("a newly failed task should trigger TaskFailed but *not* TaskFailTransition", func() {
			t2 := &task.Task{
				Id:                  "testTask2",
				Status:              evergreen.TaskFailed,
				DisplayName:         testTask.DisplayName,
				Project:             testTask.Project,
				BuildVariant:        testTask.BuildVariant,
				Version:             "testVersion2",
				RevisionOrderNumber: testTask.RevisionOrderNumber + 2,
			}
			ctx, err := getTaskTriggerContext(t2)
			So(err, ShouldBeNil)
			triggers, err := getActiveTaskFailureTriggers(*ctx)
			So(err, ShouldBeNil)
			So(len(triggers), ShouldEqual, 1)
			So(triggers[0].Id(), ShouldEqual, TaskFailed{}.Id())
		})
	})
}
Example #2
0
func TestPatchPluginAPI(t *testing.T) {
	testConfig := evergreen.TestConfig()
	cwd := testutil.GetDirectoryOfFile()
	Convey("With a running api server and installed plugin", t, func() {
		registry := plugin.NewSimpleRegistry()
		gitPlugin := &GitPlugin{}
		err := registry.Register(gitPlugin)
		testutil.HandleTestingErr(err, t, "Couldn't register patch plugin")
		server, err := service.CreateTestServer(testConfig, nil, plugin.APIPlugins, false)
		testutil.HandleTestingErr(err, t, "Couldn't set up testing server")
		taskConfig, _ := plugintest.CreateTestConfig(filepath.Join(cwd, "testdata", "plugin_patch.yml"), t)
		testCommand := GitGetProjectCommand{Directory: "dir"}
		_, _, err = plugintest.SetupAPITestData("testTask", filepath.Join(cwd, "testdata", "testmodule.patch"), t)
		testutil.HandleTestingErr(err, t, "Couldn't set up test documents")
		testTask, err := task.FindOne(task.ById("testTaskId"))
		testutil.HandleTestingErr(err, t, "Couldn't set up test patch task")

		sliceAppender := &evergreen.SliceAppender{[]*slogger.Log{}}
		logger := agentutil.NewTestLogger(sliceAppender)

		Convey("calls to existing tasks with patches should succeed", func() {
			httpCom := plugintest.TestAgentCommunicator(testTask.Id, testTask.Secret, server.URL)
			pluginCom := &comm.TaskJSONCommunicator{gitPlugin.Name(), httpCom}
			patch, err := testCommand.GetPatch(taskConfig, pluginCom, logger)
			So(err, ShouldBeNil)
			So(patch, ShouldNotBeNil)
			testutil.HandleTestingErr(db.Clear(version.Collection), t,
				"unable to clear versions collection")
		})
		Convey("calls to non-existing tasks should fail", func() {
			v := version.Version{Id: ""}
			testutil.HandleTestingErr(v.Insert(), t, "Couldn't insert dummy version")
			httpCom := plugintest.TestAgentCommunicator("BAD_TASK_ID", "", server.URL)
			pluginCom := &comm.TaskJSONCommunicator{gitPlugin.Name(), httpCom}
			patch, err := testCommand.GetPatch(taskConfig, pluginCom, logger)
			So(err.Error(), ShouldContainSubstring, "not found")
			So(err, ShouldNotBeNil)
			So(patch, ShouldBeNil)
			testutil.HandleTestingErr(db.Clear(version.Collection), t,
				"unable to clear versions collection")
		})
		Convey("calls to existing tasks without patches should fail", func() {
			noPatchTask := task.Task{Id: "noPatchTask", BuildId: "a"}
			testutil.HandleTestingErr(noPatchTask.Insert(), t, "Couldn't insert patch task")
			noPatchVersion := version.Version{Id: "noPatchVersion", BuildIds: []string{"a"}}
			testutil.HandleTestingErr(noPatchVersion.Insert(), t, "Couldn't insert patch version")
			v := version.Version{Id: ""}
			testutil.HandleTestingErr(v.Insert(), t, "Couldn't insert dummy version")
			httpCom := plugintest.TestAgentCommunicator(noPatchTask.Id, "", server.URL)
			pluginCom := &comm.TaskJSONCommunicator{gitPlugin.Name(), httpCom}
			patch, err := testCommand.GetPatch(taskConfig, pluginCom, logger)
			So(err, ShouldNotBeNil)
			So(err.Error(), ShouldContainSubstring, "no patch found for task")
			So(patch, ShouldBeNil)
			testutil.HandleTestingErr(db.Clear(version.Collection), t,
				"unable to clear versions collection")
		})

	})
}
func setupCLITestHarness() cliTestHarness {
	// create a test API server
	testServer, err := service.CreateTestServer(testConfig, nil, plugin.APIPlugins, true)
	So(err, ShouldBeNil)
	So(
		db.ClearCollections(
			task.Collection,
			build.Collection,
			user.Collection,
			patch.Collection,
			model.ProjectRefCollection,
			artifact.Collection,
		),
		ShouldBeNil)
	So(db.Clear(patch.Collection), ShouldBeNil)
	So(db.Clear(model.ProjectRefCollection), ShouldBeNil)
	So((&user.DBUser{Id: "testuser", APIKey: "testapikey", EmailAddress: "*****@*****.**"}).Insert(), ShouldBeNil)
	localConfBytes, err := ioutil.ReadFile(filepath.Join(testutil.GetDirectoryOfFile(), "testdata", "sample.yml"))
	So(err, ShouldBeNil)

	projectRef := &model.ProjectRef{
		Identifier:  "sample",
		Owner:       "evergreen-ci",
		Repo:        "sample",
		RepoKind:    "github",
		Branch:      "master",
		RemotePath:  "evergreen.yml",
		LocalConfig: string(localConfBytes),
		Enabled:     true,
		BatchTime:   180,
	}
	So(projectRef.Insert(), ShouldBeNil)

	// create a settings file for the command line client
	settings := model.CLISettings{
		APIServerHost: testServer.URL + "/api",
		UIServerHost:  "http://dev-evg.mongodb.com",
		APIKey:        "testapikey",
		User:          "******",
	}
	settingsFile, err := ioutil.TempFile("", "settings")
	So(err, ShouldBeNil)
	settingsBytes, err := yaml.Marshal(settings)
	So(err, ShouldBeNil)
	_, err = settingsFile.Write(settingsBytes)
	So(err, ShouldBeNil)
	settingsFile.Close()
	return cliTestHarness{testServer, settingsFile.Name()}
}
Example #4
0
func TestSpawnExpireWarningTrigger(t *testing.T) {
	Convey("With a spawnhost due to expire in two hours", t, func() {
		db.Clear(host.Collection)
		testHost := host.Host{
			Id:             "testhost",
			StartedBy:      "test_user",
			Status:         "running",
			ExpirationTime: time.Now().Add(1 * time.Hour),
		}

		trigger := SpawnTwoHourWarning{}
		ctx := triggerContext{host: &testHost}
		shouldExec, err := trigger.ShouldExecute(ctx)
		So(err, ShouldBeNil)
		So(shouldExec, ShouldBeTrue)

		// run bookkeeping
		err = storeTriggerBookkeeping(ctx, []Trigger{trigger})
		So(err, ShouldBeNil)

		// should exec should now return false
		shouldExec, err = trigger.ShouldExecute(ctx)
		So(err, ShouldBeNil)
		So(shouldExec, ShouldBeFalse)
	})
}
Example #5
0
func TestGenericBuildUpdating(t *testing.T) {
	Convey("When updating builds", t, func() {

		Reset(func() {
			testutil.HandleTestingErr(db.Clear(Collection), t, "Error clearing '%v' collection", Collection)
		})

		Convey("updating a single build should update the specified build"+
			" in the database", func() {

			buildOne := &Build{Id: "buildOne"}
			So(buildOne.Insert(), ShouldBeNil)

			err := UpdateOne(
				bson.M{IdKey: buildOne.Id},
				bson.M{"$set": bson.M{ProjectKey: "blah"}},
			)
			So(err, ShouldBeNil)

			buildOne, err = FindOne(ById(buildOne.Id))
			So(err, ShouldBeNil)
			So(buildOne.Project, ShouldEqual, "blah")
		})
	})
}
Example #6
0
func TestFindTasksByIds(t *testing.T) {
	Convey("When calling FindTasksByIds...", t, func() {
		So(db.Clear(TasksCollection), ShouldBeNil)
		Convey("only tasks with the specified ids should be returned", func() {

			tasks := []Task{
				Task{
					Id: "one",
				},
				Task{
					Id: "two",
				},
				Task{
					Id: "three",
				},
			}

			for _, task := range tasks {
				So(task.Insert(), ShouldBeNil)
			}

			dbTasks, err := FindTasksByIds([]string{"one", "two"})
			So(err, ShouldBeNil)
			So(len(dbTasks), ShouldEqual, 2)
			So(dbTasks[0].Id, ShouldNotEqual, "three")
			So(dbTasks[1].Id, ShouldNotEqual, "three")
		})
	})
}
Example #7
0
func TestTaskSetPriority(t *testing.T) {

	Convey("With a task", t, func() {

		testutil.HandleTestingErr(db.Clear(TasksCollection), t, "Error clearing"+
			" '%v' collection", TasksCollection)

		task := &Task{
			Id: "task",
		}
		So(task.Insert(), ShouldBeNil)

		Convey("setting its priority should update it both in-memory"+
			" and in the database", func() {

			So(task.SetPriority(1), ShouldBeNil)
			So(task.Priority, ShouldEqual, 1)

			task, err := FindTask(task.Id)
			So(err, ShouldBeNil)
			So(task, ShouldNotBeNil)
			So(task.Priority, ShouldEqual, 1)
		})

	})

}
func TestFindOneProjectRef(t *testing.T) {
	Convey("With an existing repository ref", t, func() {
		testutil.HandleTestingErr(db.Clear(ProjectRefCollection), t,
			"Error clearing collection")
		projectRef := &ProjectRef{
			Owner:      "mongodb",
			Repo:       "mci",
			Branch:     "master",
			RepoKind:   "github",
			Enabled:    true,
			BatchTime:  10,
			Identifier: "ident",
		}
		Convey("all fields should be returned accurately for the "+
			"corresponding project ref", func() {
			So(projectRef.Insert(), ShouldBeNil)
			projectRefFromDB, err := FindOneProjectRef("ident")
			So(err, ShouldBeNil)
			So(projectRefFromDB, ShouldNotEqual, nil)
			So(projectRefFromDB.Owner, ShouldEqual, "mongodb")
			So(projectRefFromDB.Repo, ShouldEqual, "mci")
			So(projectRefFromDB.Branch, ShouldEqual, "master")
			So(projectRefFromDB.RepoKind, ShouldEqual, "github")
			So(projectRefFromDB.Enabled, ShouldEqual, true)
			So(projectRefFromDB.BatchTime, ShouldEqual, 10)
			So(projectRefFromDB.Identifier, ShouldEqual, "ident")
		})
	})
}
Example #9
0
func TestBuildMarkFinished(t *testing.T) {

	Convey("With a build", t, func() {

		testutil.HandleTestingErr(db.Clear(build.Collection), t, "Error clearing"+
			" '%v' collection", build.Collection)

		startTime := time.Now()
		b := &build.Build{
			Id:        "build",
			StartTime: startTime,
		}
		So(b.Insert(), ShouldBeNil)

		Convey("marking it as finished should update the status,"+
			" finish time, and duration, both in memory and in the"+
			" database", func() {

			finishTime := time.Now()
			So(b.MarkFinished(evergreen.BuildSucceeded, finishTime), ShouldBeNil)
			So(b.Status, ShouldEqual, evergreen.BuildSucceeded)
			So(b.FinishTime.Equal(finishTime), ShouldBeTrue)
			So(b.TimeTaken, ShouldEqual, finishTime.Sub(startTime))

			// refresh from db and check again

			b, err := build.FindOne(build.ById(b.Id))
			So(err, ShouldBeNil)
			So(b.Status, ShouldEqual, evergreen.BuildSucceeded)
			So(b.FinishTime.Round(time.Second).Equal(
				finishTime.Round(time.Second)), ShouldBeTrue)
			So(b.TimeTaken, ShouldEqual, finishTime.Sub(startTime))
		})
	})
}
Example #10
0
func TestFindLastPassingVersionForBuildVariants(t *testing.T) {
	Convey("works", t, func() {
		So(db.Clear(TaskQueuesCollection), ShouldBeNil)

		project := "MyProject"
		bv1 := "linux"
		bv2 := "windows"
		projectObj := Project{
			Identifier: project,
		}

		insertVersion("1", 1, project)
		insertVersion("2", 2, project)
		insertVersion("3", 3, project)

		insertBuild("1a", project, bv1, evergreen.BuildSucceeded, 1)
		insertBuild("1b", project, bv2, evergreen.BuildSucceeded, 1)

		insertBuild("2a", project, bv1, evergreen.BuildSucceeded, 2)
		insertBuild("2b", project, bv2, evergreen.BuildSucceeded, 2)

		insertBuild("3a", project, bv1, evergreen.BuildSucceeded, 3)
		insertBuild("3b", project, bv2, evergreen.BuildFailed, 3)

		version, err := FindLastPassingVersionForBuildVariants(projectObj,
			[]string{bv1, bv2})

		So(err, ShouldBeNil)
		So(version, ShouldNotBeNil)
		So(version.Id, ShouldEqual, "2")
		So(version.RevisionOrderNumber, ShouldEqual, 2)
	})
}
func TestCheckProjectSemantics(t *testing.T) {
	Convey("When validating a project's semantics", t, func() {
		Convey("if the project passes all of the validation funcs, no errors"+
			" should be returned", func() {
			distros := []distro.Distro{
				{Id: "test-distro-one"},
				{Id: "test-distro-two"},
			}

			for _, d := range distros {
				So(d.Insert(), ShouldBeNil)
			}

			projectRef := &model.ProjectRef{
				Identifier:  "project_test",
				LocalConfig: "test: testing",
			}

			project, err := model.FindProject("", projectRef)
			So(err, ShouldBeNil)
			So(CheckProjectSemantics(project), ShouldResemble, []ValidationError{})
		})

		Reset(func() {
			db.Clear(distro.Collection)
		})
	})
}
Example #12
0
func TestBuildMarkStarted(t *testing.T) {

	Convey("With a build", t, func() {

		testutil.HandleTestingErr(db.Clear(build.Collection), t, "Error clearing"+
			" '%v' collection", build.Collection)

		b := &build.Build{
			Id:     "build",
			Status: evergreen.BuildCreated,
		}
		So(b.Insert(), ShouldBeNil)

		Convey("marking it as started should update the status and"+
			" start time, both in memory and in the database", func() {

			startTime := time.Now()
			So(build.TryMarkStarted(b.Id, startTime), ShouldBeNil)

			// refresh from db and check again
			b, err := build.FindOne(build.ById(b.Id))
			So(err, ShouldBeNil)
			So(b.Status, ShouldEqual, evergreen.BuildStarted)
			So(b.StartTime.Round(time.Second).Equal(
				startTime.Round(time.Second)), ShouldBeTrue)
		})
	})
}
Example #13
0
func TestFindRunningSpawnedHosts(t *testing.T) {
	testConfig := evergreen.TestConfig()
	db.SetGlobalSessionProvider(db.SessionFactoryFromConfig(testConfig))

	testutil.HandleTestingErr(db.Clear(Collection), t, "Error"+
		" clearing '%v' collection", Collection)

	Convey("With calling FindRunningSpawnedHosts...", t, func() {
		Convey("if there are no spawned hosts, nothing should be returned",
			func() {
				spawnedHosts, err := Find(IsRunningAndSpawned)
				So(err, ShouldBeNil)
				// make sure we only returned no document
				So(len(spawnedHosts), ShouldEqual, 0)

			})

		Convey("if there are spawned hosts, they should be returned", func() {
			host := &Host{}
			host.Id = "spawned-1"
			host.Status = "running"
			host.StartedBy = "user1"
			testutil.HandleTestingErr(host.Insert(), t, "error from "+
				"FindRunningSpawnedHosts")
			spawnedHosts, err := Find(IsRunningAndSpawned)
			testutil.HandleTestingErr(err, t, "error from "+
				"FindRunningSpawnedHosts: %v", err)
			// make sure we only returned no document
			So(len(spawnedHosts), ShouldEqual, 1)

		})
	})
}
Example #14
0
func TestHostSetRunningTask(t *testing.T) {

	Convey("With a host", t, func() {

		testutil.HandleTestingErr(db.Clear(Collection), t, "Error"+
			" clearing '%v' collection", Collection)

		host := &Host{
			Id: "hostOne",
		}
		So(host.Insert(), ShouldBeNil)

		Convey("setting the running task for the host should set the running"+
			" task and task dispatch time for both the in-memory and database"+
			" copies of the host", func() {

			taskDispatchTime := time.Now()

			So(host.SetRunningTask("taskId", "c", taskDispatchTime), ShouldBeNil)
			So(host.RunningTask, ShouldEqual, "taskId")
			So(host.AgentRevision, ShouldEqual, "c")
			So(host.TaskDispatchTime.Round(time.Second).Equal(
				taskDispatchTime.Round(time.Second)), ShouldBeTrue)

			host, err := FindOne(ById(host.Id))
			So(err, ShouldBeNil)
			So(host.RunningTask, ShouldEqual, "taskId")
			So(host.AgentRevision, ShouldEqual, "c")
			So(host.TaskDispatchTime.Round(time.Second).Equal(
				taskDispatchTime.Round(time.Second)), ShouldBeTrue)

		})

	})
}
func TestNoteStorage(t *testing.T) {
	Convey("With a test note to save", t, func() {
		db.Clear(NotesCollection)
		n := Note{
			TaskId:       "t1",
			UnixNanoTime: time.Now().UnixNano(),
			Content:      "test note",
		}
		Convey("saving the note should work without error", func() {
			So(n.Upsert(), ShouldBeNil)

			Convey("the note should be retrievable", func() {
				n2, err := NoteForTask("t1")
				So(err, ShouldBeNil)
				So(n2, ShouldNotBeNil)
				So(*n2, ShouldResemble, n)
			})
			Convey("saving the note again should overwrite the existing note", func() {
				n3 := n
				n3.Content = "new content"
				So(n3.Upsert(), ShouldBeNil)
				n4, err := NoteForTask("t1")
				So(err, ShouldBeNil)
				So(n4, ShouldNotBeNil)
				So(n4.TaskId, ShouldEqual, "t1")
				So(n4.Content, ShouldEqual, n3.Content)
			})
		})
	})
}
Example #16
0
func TestMarkAsProvisioned(t *testing.T) {

	Convey("With a host", t, func() {

		testutil.HandleTestingErr(db.Clear(Collection), t, "Error"+
			" clearing '%v' collection", Collection)

		host := &Host{
			Id: "hostOne",
		}
		So(host.Insert(), ShouldBeNil)

		Convey("marking the host as provisioned should update the status,"+
			" provisioned, and host name fields in both the in-memory and"+
			" database copies of the host", func() {

			So(host.MarkAsProvisioned(), ShouldBeNil)
			So(host.Status, ShouldEqual, evergreen.HostRunning)
			So(host.Provisioned, ShouldEqual, true)

			host, err := FindOne(ById(host.Id))
			So(err, ShouldBeNil)
			So(host.Status, ShouldEqual, evergreen.HostRunning)
			So(host.Provisioned, ShouldEqual, true)

		})

	})
}
Example #17
0
func TestHostSetDNSName(t *testing.T) {

	Convey("With a host", t, func() {

		testutil.HandleTestingErr(db.Clear(Collection), t, "Error"+
			" clearing '%v' collection", Collection)

		host := &Host{
			Id: "hostOne",
		}
		So(host.Insert(), ShouldBeNil)

		Convey("setting the hostname should update both the in-memory and"+
			" database copies of the host", func() {

			So(host.SetDNSName("hostname"), ShouldBeNil)
			So(host.Host, ShouldEqual, "hostname")

			host, err := FindOne(ById(host.Id))
			So(err, ShouldBeNil)
			So(host.Host, ShouldEqual, "hostname")

			// if the host is already updated, no new updates should work
			So(host.SetDNSName("hostname2"), ShouldBeNil)
			So(host.Host, ShouldEqual, "hostname")

			host, err = FindOne(ById(host.Id))
			So(err, ShouldBeNil)
			So(host.Host, ShouldEqual, "hostname")

		})

	})
}
Example #18
0
func TestSetHostTerminated(t *testing.T) {

	Convey("With a host", t, func() {

		testutil.HandleTestingErr(db.Clear(Collection), t, "Error"+
			" clearing '%v' collection", Collection)

		host := &Host{
			Id: "hostOne",
		}
		So(host.Insert(), ShouldBeNil)

		Convey("setting the host as terminated should set the status and the"+
			" termination time in both the in-memory and database copies of"+
			" the host", func() {

			So(host.Terminate(), ShouldBeNil)
			So(host.Status, ShouldEqual, evergreen.HostTerminated)
			So(host.TerminationTime.IsZero(), ShouldBeFalse)

			host, err := FindOne(ById(host.Id))
			So(err, ShouldBeNil)
			So(host.Status, ShouldEqual, evergreen.HostTerminated)
			So(host.TerminationTime.IsZero(), ShouldBeFalse)

		})

	})
}
func TestCheckProjectSyntax(t *testing.T) {
	Convey("When validating a project's syntax", t, func() {
		Convey("if the project passes all of the validation funcs, no errors"+
			" should be returned", func() {
			distros := []distro.Distro{
				{Id: "test-distro-one"},
				{Id: "test-distro-two"},
			}

			err := testutil.CreateTestLocalConfig(projectValidatorConf, "project_test", "")
			So(err, ShouldBeNil)

			projectRef, err := model.FindOneProjectRef("project_test")
			So(err, ShouldBeNil)

			for _, d := range distros {
				So(d.Insert(), ShouldBeNil)
			}

			project, err := model.FindProject("", projectRef)
			So(err, ShouldBeNil)
			So(CheckProjectSyntax(project), ShouldResemble, []ValidationError{})
		})

		Reset(func() {
			db.Clear(distro.Collection)
		})
	})
}
Example #20
0
func TestAlertQueue(t *testing.T) {
	Convey("After queueing a few alerts", t, func() {
		db.Clear(alert.Collection)
		now := time.Now()

		// a bunch of alerts, in order of oldest to newest
		testAlerts := []*alert.AlertRequest{
			{Id: bson.NewObjectId(), Display: "test1", CreatedAt: now.Add(time.Millisecond)},
			{Id: bson.NewObjectId(), Display: "test2", CreatedAt: now.Add(2 * time.Millisecond)},
			{Id: bson.NewObjectId(), Display: "test3", CreatedAt: now.Add(3 * time.Millisecond)},
		}

		for _, a := range testAlerts {
			err := alert.EnqueueAlertRequest(a)
			So(err, ShouldBeNil)
		}

		Convey("dequeuing should return them in order, oldest first", func() {
			found := 0
			for {
				nextAlert, err := alert.DequeueAlertRequest()
				So(err, ShouldBeNil)
				if nextAlert == nil {
					break
				}
				So(nextAlert.Display, ShouldEqual, testAlerts[found].Display)
				So(nextAlert.QueueStatus, ShouldEqual, alert.InProgress)
				found++
			}
			So(found, ShouldEqual, len(testAlerts))
		})
	})
}
Example #21
0
func TestHostClearRunningTask(t *testing.T) {

	Convey("With a host", t, func() {

		testutil.HandleTestingErr(db.Clear(Collection), t, "Error"+
			" clearing '%v' collection", Collection)

		host := &Host{
			Id:               "hostOne",
			RunningTask:      "taskId",
			StartedBy:        evergreen.User,
			Status:           evergreen.HostRunning,
			TaskDispatchTime: time.Now(),
			Pid:              "12345",
		}
		So(host.Insert(), ShouldBeNil)

		Convey("host statistics should properly count this host as active"+
			" but not idle", func() {
			count, err := Count(IsActive)
			So(err, ShouldBeNil)
			So(count, ShouldEqual, 1)
			count, err = Count(IsIdle)
			So(err, ShouldBeNil)
			So(count, ShouldEqual, 0)
		})

		Convey("clearing the running task should clear the running task, pid,"+
			" and task dispatch time fields from both the in-memory and"+
			" database copies of the host", func() {

			So(host.ClearRunningTask(), ShouldBeNil)
			So(host.RunningTask, ShouldEqual, "")
			So(host.TaskDispatchTime.Equal(time.Unix(0, 0)), ShouldBeTrue)
			So(host.Pid, ShouldEqual, "")

			host, err := FindOne(ById(host.Id))
			So(err, ShouldBeNil)

			So(host.RunningTask, ShouldEqual, "")
			So(host.TaskDispatchTime.Equal(time.Unix(0, 0)), ShouldBeTrue)
			So(host.Pid, ShouldEqual, "")

			Convey("the count of idle hosts should go up", func() {
				count, err := Count(IsIdle)
				So(err, ShouldBeNil)
				So(count, ShouldEqual, 1)

				Convey("but the active host count should remain the same", func() {
					count, err = Count(IsActive)
					So(err, ShouldBeNil)
					So(count, ShouldEqual, 1)
				})
			})

		})

	})
}
Example #22
0
func TestExistingPassedTaskTriggers(t *testing.T) {
	Convey("With a previously passing instance of task in the database", t, func() {
		db.Clear(task.Collection)
		db.Clear(alertrecord.Collection)
		testTask.Status = evergreen.TaskSucceeded
		err := testTask.Insert()
		So(err, ShouldBeNil)
		t2 := &task.Task{
			Id:                  "testTask2",
			Status:              evergreen.TaskFailed,
			DisplayName:         testTask.DisplayName,
			Project:             testTask.Project,
			BuildVariant:        testTask.BuildVariant,
			Version:             "testVersion2",
			RevisionOrderNumber: testTask.RevisionOrderNumber + 2,
		}
		Convey("a newly failed task should trigger TaskFailed and TaskFailTransition", func() {
			ctx, err := getTaskTriggerContext(t2)
			So(err, ShouldBeNil)
			triggers, err := getActiveTaskFailureTriggers(*ctx)
			So(err, ShouldBeNil)
			So(hasTrigger(triggers, TaskFailed{}), ShouldBeTrue)
			So(hasTrigger(triggers, TaskFailTransition{}), ShouldBeTrue)
		})
		Convey("a newly failed task should not trigger TaskFailTransition after bookkeeping is already done", func() {
			// Pre-bookkeeping

			ctx, err := getTaskTriggerContext(t2)
			So(err, ShouldBeNil)
			triggers, err := getActiveTaskFailureTriggers(*ctx)
			So(err, ShouldBeNil)
			So(hasTrigger(triggers, TaskFailed{}), ShouldBeTrue)
			So(hasTrigger(triggers, TaskFailTransition{}), ShouldBeTrue)

			// Post-bookkeeping
			err = storeTriggerBookkeeping(*ctx, triggers)
			So(err, ShouldBeNil)
			triggers, err = getActiveTaskFailureTriggers(*ctx)
			So(err, ShouldBeNil)

			So(hasTrigger(triggers, TaskFailed{}), ShouldBeTrue)
			So(hasTrigger(triggers, TaskFailTransition{}), ShouldBeFalse)
		})
	})
}
Example #23
0
func TestDequeueTask(t *testing.T) {

	var taskIds []string
	var distroId string
	var taskQueue *TaskQueue

	Convey("When attempting to pull a task from a task queue", t, func() {

		taskIds = []string{"t1", "t2", "t3"}
		distroId = "d1"
		taskQueue = &TaskQueue{
			Distro: distroId,
			Queue:  []TaskQueueItem{},
		}

		So(db.Clear(TaskQueuesCollection), ShouldBeNil)

		Convey("if the task queue is empty, an error should be thrown", func() {
			So(taskQueue.Save(), ShouldBeNil)
			So(taskQueue.DequeueTask(taskIds[0]), ShouldNotBeNil)
		})

		Convey("if the task is not present in the queue, an error should be"+
			" thrown", func() {
			taskQueue.Queue = append(taskQueue.Queue,
				TaskQueueItem{Id: taskIds[1]})
			So(taskQueue.Save(), ShouldBeNil)
			So(taskQueue.DequeueTask(taskIds[0]), ShouldNotBeNil)
		})

		Convey("if the task is present in the queue, it should be removed"+
			" from the in-memory and db versions of the queue", func() {
			taskQueue.Queue = []TaskQueueItem{
				TaskQueueItem{Id: taskIds[0]},
				TaskQueueItem{Id: taskIds[1]},
				TaskQueueItem{Id: taskIds[2]},
			}
			So(taskQueue.Save(), ShouldBeNil)
			So(taskQueue.DequeueTask(taskIds[1]), ShouldBeNil)

			// make sure the queue was updated in memory
			So(taskQueue.Length(), ShouldEqual, 2)
			So(taskQueue.Queue[0].Id, ShouldEqual, taskIds[0])
			So(taskQueue.Queue[1].Id, ShouldEqual, taskIds[2])

			// make sure the db representation was updated
			taskQueue, err := FindTaskQueueForDistro(distroId)
			So(err, ShouldBeNil)
			So(taskQueue.Length(), ShouldEqual, 2)
			So(taskQueue.Queue[0].Id, ShouldEqual, taskIds[0])
			So(taskQueue.Queue[1].Id, ShouldEqual, taskIds[2])

		})

	})
}
Example #24
0
func TestLoggingDistroEvents(t *testing.T) {
	Convey("When logging distro events, ", t, func() {

		So(db.Clear(Collection), ShouldBeNil)

		Convey("logged events should be stored and queryable in sorted order", func() {
			distroId := "distro_id"
			userId := "user_id"

			// log some events, sleeping in between to make sure the times are different
			LogDistroAdded(distroId, userId, nil)
			time.Sleep(1 * time.Millisecond)
			LogDistroModified(distroId, userId, "update")
			time.Sleep(1 * time.Millisecond)
			LogDistroRemoved(distroId, userId, nil)
			time.Sleep(1 * time.Millisecond)

			// fetch all the events from the database, make sure they are
			// persisted correctly

			eventsForDistro, err := Find(DistroEventsInOrder(distroId))
			So(err, ShouldBeNil)

			event := eventsForDistro[0]
			So(event.EventType, ShouldEqual, EventDistroAdded)
			So(event.ResourceId, ShouldEqual, distroId)

			eventData, ok := event.Data.Data.(*DistroEventData)
			So(ok, ShouldBeTrue)
			So(eventData.ResourceType, ShouldEqual, ResourceTypeDistro)
			So(eventData.UserId, ShouldEqual, userId)
			So(eventData.Data, ShouldBeNil)

			event = eventsForDistro[1]
			So(event.EventType, ShouldEqual, EventDistroModified)
			So(event.ResourceId, ShouldEqual, distroId)

			eventData, ok = event.Data.Data.(*DistroEventData)
			So(ok, ShouldBeTrue)
			So(eventData.ResourceType, ShouldEqual, ResourceTypeDistro)
			So(eventData.UserId, ShouldEqual, userId)
			So(eventData.Data.(string), ShouldEqual, "update")

			event = eventsForDistro[2]
			So(event.EventType, ShouldEqual, EventDistroRemoved)
			So(event.ResourceId, ShouldEqual, distroId)

			eventData, ok = event.Data.Data.(*DistroEventData)
			So(ok, ShouldBeTrue)
			So(eventData.ResourceType, ShouldEqual, ResourceTypeDistro)
			So(eventData.UserId, ShouldEqual, userId)
			So(eventData.Data, ShouldBeNil)
		})
	})
}
Example #25
0
func TestDeletingBuild(t *testing.T) {

	Convey("With a build", t, func() {

		testutil.HandleTestingErr(db.Clear(build.Collection), t, "Error clearing"+
			" '%v' collection", build.Collection)

		b := &build.Build{
			Id: "build",
		}
		So(b.Insert(), ShouldBeNil)

		Convey("deleting it should remove it and all its associated"+
			" tasks from the database", func() {

			testutil.HandleTestingErr(db.ClearCollections(task.Collection), t, "Error"+
				" clearing '%v' collection", task.Collection)

			// insert two tasks that are part of the build, and one that isn't
			matchingTaskOne := &task.Task{
				Id:      "matchingOne",
				BuildId: b.Id,
			}
			So(matchingTaskOne.Insert(), ShouldBeNil)

			matchingTaskTwo := &task.Task{
				Id:      "matchingTwo",
				BuildId: b.Id,
			}
			So(matchingTaskTwo.Insert(), ShouldBeNil)

			nonMatchingTask := &task.Task{
				Id:      "nonMatching",
				BuildId: "blech",
			}
			So(nonMatchingTask.Insert(), ShouldBeNil)

			// delete the build, make sure only it and its tasks are deleted

			So(DeleteBuild(b.Id), ShouldBeNil)

			b, err := build.FindOne(build.ById(b.Id))
			So(err, ShouldBeNil)
			So(b, ShouldBeNil)

			matchingTasks, err := task.Find(task.ByBuildId("build"))
			So(err, ShouldBeNil)
			So(len(matchingTasks), ShouldEqual, 0)

			nonMatchingTask, err = task.FindOne(task.ById(nonMatchingTask.Id))
			So(err, ShouldBeNil)
			So(nonMatchingTask, ShouldNotBeNil)
		})
	})
}
Example #26
0
func TestFinalizePatch(t *testing.T) {
	testutil.ConfigureIntegrationTest(t, patchTestConfig, "TestFinalizePatch")

	Convey("With FinalizePatch on a project and commit event generated from GetPatchedProject path",
		t, func() {
			configPatch := resetPatchSetup(t, configFilePath)
			Convey("a patched config should drive version creation", func() {
				project, err := GetPatchedProject(configPatch, patchTestConfig)
				So(err, ShouldBeNil)
				yamlBytes, err := yaml.Marshal(project)
				So(err, ShouldBeNil)
				configPatch.PatchedConfig = string(yamlBytes)
				version, err := model.FinalizePatch(configPatch, patchTestConfig)
				So(err, ShouldBeNil)
				So(version, ShouldNotBeNil)
				// ensure the relevant builds/tasks were created
				builds, err := build.Find(build.All)
				So(err, ShouldBeNil)
				So(len(builds), ShouldEqual, 1)
				So(len(builds[0].Tasks), ShouldEqual, 2)
				tasks, err := task.Find(task.All)
				So(err, ShouldBeNil)
				So(len(tasks), ShouldEqual, 2)
			})

			Convey("a patch that does not include the remote config should not "+
				"drive version creation", func() {
				patchedConfigFile := "fakeInPatchSoNotPatched"
				configPatch := resetPatchSetup(t, patchedConfigFile)
				project, err := GetPatchedProject(configPatch, patchTestConfig)
				So(err, ShouldBeNil)
				yamlBytes, err := yaml.Marshal(project)
				So(err, ShouldBeNil)
				configPatch.PatchedConfig = string(yamlBytes)
				version, err := model.FinalizePatch(configPatch, patchTestConfig)
				So(err, ShouldBeNil)
				So(version, ShouldNotBeNil)
				So(err, ShouldBeNil)
				So(version, ShouldNotBeNil)

				// ensure the relevant builds/tasks were created
				builds, err := build.Find(build.All)
				So(err, ShouldBeNil)
				So(len(builds), ShouldEqual, 1)
				So(len(builds[0].Tasks), ShouldEqual, 1)
				tasks, err := task.Find(task.All)
				So(err, ShouldBeNil)
				So(len(tasks), ShouldEqual, 1)
			})

			Reset(func() {
				db.Clear(distro.Collection)
			})
		})
}
Example #27
0
func TestEmptyTaskTriggers(t *testing.T) {
	db.Clear(task.Collection)
	db.Clear(alertrecord.Collection)
	Convey("With no existing tasks in the database", t, func() {
		Convey("a newly failed task should return all triggers", func() {
			// pre-bookkeeping
			ctx, err := getTaskTriggerContext(testTask)
			So(err, ShouldBeNil)
			So(ctx.previousCompleted, ShouldBeNil)
			triggers, err := getActiveTaskFailureTriggers(*ctx)
			So(err, ShouldBeNil)
			So(len(triggers), ShouldEqual, 5)
			So(hasTrigger(triggers, TaskFailed{}), ShouldBeTrue)
			So(hasTrigger(triggers, TaskFailTransition{}), ShouldBeTrue)
			So(hasTrigger(triggers, FirstFailureInVersion{}), ShouldBeTrue)
			So(hasTrigger(triggers, FirstFailureInVariant{}), ShouldBeTrue)
			So(hasTrigger(triggers, FirstFailureInTaskType{}), ShouldBeTrue)

			// post-bookkeeping
			err = storeTriggerBookkeeping(*ctx, triggers)
			So(err, ShouldBeNil)
			triggers, err = getActiveTaskFailureTriggers(*ctx)
			So(err, ShouldBeNil)

			So(len(triggers), ShouldEqual, 2)
			So(hasTrigger(triggers, TaskFailed{}), ShouldBeTrue)

			// The previous task doesn't exist, so this will still be true
			So(hasTrigger(triggers, TaskFailTransition{}), ShouldBeTrue)
		})
		Convey("a successful task should trigger nothing", func() {
			testTask.Status = evergreen.TaskSucceeded
			ctx, err := getTaskTriggerContext(testTask)
			So(err, ShouldBeNil)
			triggers, err := getActiveTaskFailureTriggers(*ctx)
			So(err, ShouldBeNil)
			So(len(triggers), ShouldEqual, 0)
		})
	})
}
Example #28
0
func TestLastKnownGoodConfig(t *testing.T) {
	Convey("When calling LastKnownGoodConfig..", t, func() {
		identifier := "identifier"
		Convey("no versions should be returned if there're no good "+
			"last known configurations", func() {
			v := &version.Version{
				Identifier: identifier,
				Requester:  evergreen.RepotrackerVersionRequester,
				Errors:     []string{"error 1", "error 2"},
			}
			testutil.HandleTestingErr(v.Insert(), t, "Error inserting test version: %v")
			lastGood, err := version.FindOne(version.ByLastKnownGoodConfig(identifier))
			testutil.HandleTestingErr(err, t, "error finding last known good: %v")
			So(lastGood, ShouldBeNil)
		})
		Convey("a version should be returned if there is a last known good configuration", func() {
			v := &version.Version{
				Identifier: identifier,
				Requester:  evergreen.RepotrackerVersionRequester,
			}
			testutil.HandleTestingErr(v.Insert(), t, "Error inserting test version: %v")
			lastGood, err := version.FindOne(version.ByLastKnownGoodConfig(identifier))
			testutil.HandleTestingErr(err, t, "error finding last known good: %v")
			So(lastGood, ShouldNotBeNil)
		})
		Convey("most recent version should be found if there are several recent good configs", func() {
			v := &version.Version{
				Id:                  "1",
				Identifier:          identifier,
				Requester:           evergreen.RepotrackerVersionRequester,
				RevisionOrderNumber: 1,
				Config:              "1",
			}
			testutil.HandleTestingErr(v.Insert(), t, "Error inserting test version: %v")
			v.Id = "5"
			v.RevisionOrderNumber = 5
			v.Config = "5"
			testutil.HandleTestingErr(v.Insert(), t, "Error inserting test version: %v")
			v.Id = "2"
			v.RevisionOrderNumber = 2
			v.Config = "2"
			testutil.HandleTestingErr(v.Insert(), t, "Error inserting test version: %v")
			lastGood, err := version.FindOne(version.ByLastKnownGoodConfig(identifier))
			testutil.HandleTestingErr(err, t, "error finding last known good: %v")
			So(lastGood, ShouldNotBeNil)
			So(lastGood.Config, ShouldEqual, "5")
		})
		Reset(func() {
			db.Clear(version.Collection)
		})
	})
}
Example #29
0
func TestReachedFailureLimit(t *testing.T) {
	Convey("With 3 failed task and relevant project variants", t, func() {
		db.Clear(task.Collection)
		db.Clear(model.ProjectRefCollection)
		db.Clear(version.Collection)
		t := task.Task{
			Id:           "t1",
			Revision:     "aaa",
			Project:      "testProject",
			BuildVariant: "bv1",
			FinishTime:   time.Now().Add(-time.Hour),
		}
		So(t.Insert(), ShouldBeNil)
		t.Id = "t2"
		t.BuildVariant = "bv2"
		So(t.Insert(), ShouldBeNil)
		t.Id = "t3"
		t.BuildVariant = "bv3"
		So(t.Insert(), ShouldBeNil)
		So(testProject.Insert(), ShouldBeNil)
		So(testVersion.Insert(), ShouldBeNil)

		Convey("a variant with batchtime of 60 should not hit the limit", func() {
			out, err := reachedFailureLimit("t1")
			So(err, ShouldBeNil)
			So(out, ShouldBeFalse)
		})
		Convey("a variant with batchtime of 1 should hit the limit", func() {
			out, err := reachedFailureLimit("t2")
			So(err, ShouldBeNil)
			So(out, ShouldBeTrue)
		})
		Convey("a fallback batchtime of 5 should hit the limit", func() {
			out, err := reachedFailureLimit("t3")
			So(err, ShouldBeNil)
			So(out, ShouldBeTrue)
		})
	})
}
Example #30
0
func TestHostSetExpirationTime(t *testing.T) {

	Convey("With a host", t, func() {

		testutil.HandleTestingErr(db.Clear(Collection), t, "Error"+
			" clearing '%v' collection", Collection)

		initialExpirationTime := time.Now()
		notifications := make(map[string]bool)
		notifications["2h"] = true

		memHost := &Host{
			Id:             "hostOne",
			ExpirationTime: initialExpirationTime,
			Notifications:  notifications,
		}
		So(memHost.Insert(), ShouldBeNil)

		Convey("setting the expiration time for the host should change the "+
			" expiration time for both the in-memory and database"+
			" copies of the host and unset the notifications", func() {

			dbHost, err := FindOne(ById(memHost.Id))

			// ensure the db entries are as expected
			So(err, ShouldBeNil)
			So(memHost.ExpirationTime.Round(time.Second).Equal(
				initialExpirationTime.Round(time.Second)), ShouldBeTrue)
			So(dbHost.ExpirationTime.Round(time.Second).Equal(
				initialExpirationTime.Round(time.Second)), ShouldBeTrue)
			So(memHost.Notifications, ShouldResemble, notifications)
			So(dbHost.Notifications, ShouldResemble, notifications)

			// now update the expiration time
			newExpirationTime := time.Now()
			So(memHost.SetExpirationTime(newExpirationTime), ShouldBeNil)

			dbHost, err = FindOne(ById(memHost.Id))

			// ensure the db entries are as expected
			So(err, ShouldBeNil)
			So(memHost.ExpirationTime.Round(time.Second).Equal(
				newExpirationTime.Round(time.Second)), ShouldBeTrue)
			So(dbHost.ExpirationTime.Round(time.Second).Equal(
				newExpirationTime.Round(time.Second)), ShouldBeTrue)
			So(memHost.Notifications, ShouldResemble, make(map[string]bool))
			So(dbHost.Notifications, ShouldEqual, nil)
		})
	})
}