func insertBuild(id, project, display_name, buildVariant, status string, createTime, finishTime time.Time, timeTaken time.Duration, activated bool, requester string, order int) { build := &build.Build{ Id: id, BuildNumber: id, Project: project, BuildVariant: buildVariant, TimeTaken: timeTaken, Status: status, CreateTime: createTime, DisplayName: display_name, FinishTime: finishTime, Activated: activated, Requester: requester, RevisionOrderNumber: order, Version: "version", } So(build.Insert(), ShouldBeNil) }
func SetupAPITestData(taskDisplayName string, isPatch bool, t *testing.T) (*model.Task, *build.Build, error) { //ignore errs here because the ns might just not exist. testutil.HandleTestingErr( db.ClearCollections(model.TasksCollection, build.Collection, host.Collection, version.Collection, patch.Collection), t, "Failed to clear test collections") testHost := &host.Host{ Id: "testHost", Host: "testHost", RunningTask: "testTaskId", StartedBy: evergreen.User, } testutil.HandleTestingErr(testHost.Insert(), t, "failed to insert host") task := &model.Task{ Id: "testTaskId", BuildId: "testBuildId", DistroId: "rhel55", BuildVariant: "linux-64", Project: "mongodb-mongo-master", DisplayName: taskDisplayName, HostId: "testHost", Version: "testVersionId", Secret: "testTaskSecret", Status: evergreen.TaskDispatched, Requester: evergreen.RepotrackerVersionRequester, } if isPatch { task.Requester = evergreen.PatchVersionRequester } testutil.HandleTestingErr(task.Insert(), t, "failed to insert task") version := &version.Version{Id: "testVersionId", BuildIds: []string{task.BuildId}} testutil.HandleTestingErr(version.Insert(), t, "failed to insert version %v") if isPatch { modulePatchContent, err := ioutil.ReadFile("testdata/testmodule.patch") testutil.HandleTestingErr(err, t, "failed to read test module patch file %v") patch := &patch.Patch{ Status: evergreen.PatchCreated, Version: version.Id, Patches: []patch.ModulePatch{ { ModuleName: "enterprise", Githash: "c2d7ce942a96d7dacd27c55b257e3f2774e04abf", PatchSet: patch.PatchSet{Patch: string(modulePatchContent)}, }, }, } testutil.HandleTestingErr(patch.Insert(), t, "failed to insert patch %v") } session, _, err := db.GetGlobalSessionFactory().GetSession() testutil.HandleTestingErr(err, t, "couldn't get db session!") //Remove any logs for our test task from previous runs. _, err = session.DB(model.TaskLogDB).C(model.TaskLogCollection).RemoveAll(bson.M{"t_id": task.Id}) testutil.HandleTestingErr(err, t, "failed to remove logs") build := &build.Build{Id: "testBuildId", Tasks: []build.TaskCache{build.NewTaskCache(task.Id, task.DisplayName, true)}} testutil.HandleTestingErr(build.Insert(), t, "failed to insert build %v") return task, build, nil }
func TestGetBuildInfo(t *testing.T) { userManager, err := auth.LoadUserManager(buildTestConfig.AuthConfig) testutil.HandleTestingErr(err, t, "Failure in loading UserManager from config") uis := UIServer{ RootURL: buildTestConfig.Ui.Url, Settings: *buildTestConfig, UserManager: userManager, } uis.InitPlugins() home := evergreen.FindEvergreenHome() uis.Render = render.New(render.Options{ Directory: filepath.Join(home, WebRootPath, Templates), DisableCache: true, }) router, err := uis.NewRouter() testutil.HandleTestingErr(err, t, "Failed to create ui server router") Convey("When finding info on a particular build", t, func() { testutil.HandleTestingErr(db.Clear(build.Collection), t, "Error clearing '%v' collection", build.Collection) buildId := "my-build" versionId := "my-version" projectName := "mci-test" err := modelutil.CreateTestLocalConfig(buildTestConfig, "mci-test", "") So(err, ShouldBeNil) err = modelutil.CreateTestLocalConfig(buildTestConfig, "render", "") So(err, ShouldBeNil) err = modelutil.CreateTestLocalConfig(buildTestConfig, "project_test", "") task := build.TaskCache{ Id: "some-task-id", DisplayName: "some-task-name", Status: "success", TimeTaken: time.Duration(100 * time.Millisecond), } build := &build.Build{ Id: buildId, CreateTime: time.Now().Add(-20 * time.Minute), StartTime: time.Now().Add(-10 * time.Minute), FinishTime: time.Now().Add(-5 * time.Second), PushTime: time.Now().Add(-1 * time.Millisecond), Version: versionId, Project: projectName, Revision: fmt.Sprintf("%x", rand.Int()), BuildVariant: "some-build-variant", BuildNumber: "42", Status: "success", Activated: true, ActivatedTime: time.Now().Add(-15 * time.Minute), RevisionOrderNumber: rand.Int(), Tasks: []build.TaskCache{task}, TimeTaken: time.Duration(10 * time.Minute), DisplayName: "My build", Requester: evergreen.RepotrackerVersionRequester, } So(build.Insert(), ShouldBeNil) url, err := router.Get("build_info").URL("build_id", buildId) So(err, ShouldBeNil) request, err := http.NewRequest("GET", url.String(), nil) So(err, ShouldBeNil) response := httptest.NewRecorder() // Need match variables to be set so can call mux.Vars(request) // in the actual handler function router.ServeHTTP(response, request) So(response.Code, ShouldEqual, http.StatusOK) Convey("response should match contents of database", func() { var jsonBody map[string]interface{} err = json.Unmarshal(response.Body.Bytes(), &jsonBody) So(err, ShouldBeNil) var rawJsonBody map[string]*json.RawMessage err = json.Unmarshal(response.Body.Bytes(), &rawJsonBody) So(err, ShouldBeNil) So(jsonBody["id"], ShouldEqual, build.Id) var createTime time.Time err = json.Unmarshal(*rawJsonBody["create_time"], &createTime) So(err, ShouldBeNil) So(createTime, ShouldHappenWithin, TimePrecision, build.CreateTime) var startTime time.Time err = json.Unmarshal(*rawJsonBody["start_time"], &startTime) So(err, ShouldBeNil) So(startTime, ShouldHappenWithin, TimePrecision, build.StartTime) var finishTime time.Time err = json.Unmarshal(*rawJsonBody["finish_time"], &finishTime) So(err, ShouldBeNil) So(finishTime, ShouldHappenWithin, TimePrecision, build.FinishTime) var pushTime time.Time err = json.Unmarshal(*rawJsonBody["push_time"], &pushTime) So(err, ShouldBeNil) So(pushTime, ShouldHappenWithin, TimePrecision, build.PushTime) So(jsonBody["version"], ShouldEqual, build.Version) So(jsonBody["project"], ShouldEqual, build.Project) So(jsonBody["revision"], ShouldEqual, build.Revision) So(jsonBody["variant"], ShouldEqual, build.BuildVariant) So(jsonBody["number"], ShouldEqual, build.BuildNumber) So(jsonBody["status"], ShouldEqual, build.Status) So(jsonBody["activated"], ShouldEqual, build.Activated) var activatedTime time.Time err = json.Unmarshal(*rawJsonBody["activated_time"], &activatedTime) So(err, ShouldBeNil) So(activatedTime, ShouldHappenWithin, TimePrecision, build.ActivatedTime) So(jsonBody["order"], ShouldEqual, build.RevisionOrderNumber) _jsonTasks, ok := jsonBody["tasks"] So(ok, ShouldBeTrue) jsonTasks, ok := _jsonTasks.(map[string]interface{}) So(ok, ShouldBeTrue) So(len(jsonTasks), ShouldEqual, 1) _jsonTask, ok := jsonTasks[task.DisplayName] So(ok, ShouldBeTrue) jsonTask, ok := _jsonTask.(map[string]interface{}) So(ok, ShouldBeTrue) So(jsonTask["task_id"], ShouldEqual, task.Id) So(jsonTask["status"], ShouldEqual, task.Status) So(jsonTask["time_taken"], ShouldEqual, task.TimeTaken) So(jsonBody["time_taken"], ShouldEqual, build.TimeTaken) So(jsonBody["name"], ShouldEqual, build.DisplayName) So(jsonBody["requester"], ShouldEqual, build.Requester) }) }) Convey("When finding info on a nonexistent build", t, func() { buildId := "not-present" url, err := router.Get("build_info").URL("build_id", buildId) So(err, ShouldBeNil) request, err := http.NewRequest("GET", url.String(), nil) So(err, ShouldBeNil) response := httptest.NewRecorder() // Need match variables to be set so can call mux.Vars(request) // in the actual handler function router.ServeHTTP(response, request) So(response.Code, ShouldEqual, http.StatusNotFound) Convey("response should contain a sensible error message", func() { var jsonBody map[string]interface{} err = json.Unmarshal(response.Body.Bytes(), &jsonBody) So(err, ShouldBeNil) So(len(jsonBody["message"].(string)), ShouldBeGreaterThan, 0) }) }) }
func setupAPITestData(testConfig *evergreen.Settings, taskDisplayName string, variant string, patchMode patchTestMode, t *testing.T) (*model.Task, *build.Build, error) { //ignore errs here because the ns might just not exist. clearDataMsg := "Failed to clear test data collection" testCollections := []string{ model.TasksCollection, build.Collection, host.Collection, distro.Collection, version.Collection, patch.Collection, model.PushlogCollection, model.ProjectVarsCollection, model.TaskQueuesCollection, manifest.Collection, model.ProjectRefCollection} testutil.HandleTestingErr(dbutil.ClearCollections(testCollections...), t, clearDataMsg) projectVars := &model.ProjectVars{ Id: "evergreen-ci-render", Vars: map[string]string{ "aws_key": testConfig.Providers.AWS.Id, "aws_secret": testConfig.Providers.AWS.Secret, "fetch_key": "fetch_expansion_value", }, } _, err := projectVars.Upsert() testutil.HandleTestingErr(err, t, clearDataMsg) taskOne := &model.Task{ Id: "testTaskId", BuildId: "testBuildId", DistroId: "test-distro-one", BuildVariant: variant, Project: "evergreen-ci-render", DisplayName: taskDisplayName, HostId: "testHost", Secret: "testTaskSecret", Version: "testVersionId", Status: evergreen.TaskDispatched, Requester: evergreen.RepotrackerVersionRequester, } taskTwo := &model.Task{ Id: "testTaskIdTwo", BuildId: "testBuildId", DistroId: "test-distro-one", BuildVariant: variant, Project: "evergreen-ci-render", DisplayName: taskDisplayName, HostId: "", Secret: "testTaskSecret", Activated: true, Version: "testVersionId", Status: evergreen.TaskUndispatched, Requester: evergreen.RepotrackerVersionRequester, } if patchMode != NoPatch { taskOne.Requester = evergreen.PatchVersionRequester } testutil.HandleTestingErr(taskOne.Insert(), t, "failed to insert taskOne") testutil.HandleTestingErr(taskTwo.Insert(), t, "failed to insert taskTwo") // set up task queue for task end tests taskQueue := &model.TaskQueue{ Distro: "test-distro-one", Queue: []model.TaskQueueItem{ model.TaskQueueItem{ Id: "testTaskIdTwo", DisplayName: taskDisplayName, }, }, } testutil.HandleTestingErr(taskQueue.Save(), t, "failed to insert taskqueue") workDir, err := ioutil.TempDir("", "agent_test_") testutil.HandleTestingErr(err, t, "failed to create working directory") host := &host.Host{ Id: "testHost", Host: "testHost", Distro: distro.Distro{ Id: "test-distro-one", WorkDir: workDir, Expansions: []distro.Expansion{{"distro_exp", "DISTRO_EXP"}}, }, RunningTask: "testTaskId", StartedBy: evergreen.User, AgentRevision: agentRevision, } testutil.HandleTestingErr(host.Insert(), t, "failed to insert host") // read in the project configuration projectFile := "testdata/config_test_plugin/project/evergreen-ci-render.yml" projectConfig, err := ioutil.ReadFile(projectFile) testutil.HandleTestingErr(err, t, "failed to read project config") projectRef := &model.ProjectRef{ Identifier: "evergreen-ci-render", Owner: "evergreen-ci", Repo: "render", RepoKind: "github", Branch: "master", Enabled: true, BatchTime: 180, } testutil.HandleTestingErr(projectRef.Insert(), t, "failed to insert projectRef") err = testutil.CreateTestLocalConfig(testConfig, "evergreen-ci-render", "testdata/config_test_plugin/project/evergreen-ci-render.yml") testutil.HandleTestingErr(err, t, "failed to marshall project config") // unmarshall the project configuration into a struct project := &model.Project{} testutil.HandleTestingErr(yaml.Unmarshal(projectConfig, project), t, "failed to unmarshal project config") // now then marshall the project YAML for storage projectYamlBytes, err := yaml.Marshal(project) testutil.HandleTestingErr(err, t, "failed to marshall project config") // insert the version document v := &version.Version{ Id: "testVersionId", BuildIds: []string{taskOne.BuildId}, Config: string(projectYamlBytes), } testutil.HandleTestingErr(v.Insert(), t, "failed to insert version") if patchMode != NoPatch { mainPatchContent, err := ioutil.ReadFile("testdata/test.patch") testutil.HandleTestingErr(err, t, "failed to read test patch file") modulePatchContent, err := ioutil.ReadFile("testdata/testmodule.patch") testutil.HandleTestingErr(err, t, "failed to read test module patch file") ptch := &patch.Patch{ Status: evergreen.PatchCreated, Version: v.Id, } if patchMode == InlinePatch { ptch.Patches = []patch.ModulePatch{ { ModuleName: "", Githash: "1e5232709595db427893826ce19289461cba3f75", PatchSet: patch.PatchSet{Patch: string(mainPatchContent)}, }, { ModuleName: "recursive", Githash: "1e5232709595db427893826ce19289461cba3f75", PatchSet: patch.PatchSet{Patch: string(modulePatchContent)}, }, } } else { p1Id, p2Id := bson.NewObjectId().Hex(), bson.NewObjectId().Hex() So(dbutil.WriteGridFile(patch.GridFSPrefix, p1Id, strings.NewReader(string(mainPatchContent))), ShouldBeNil) So(dbutil.WriteGridFile(patch.GridFSPrefix, p2Id, strings.NewReader(string(modulePatchContent))), ShouldBeNil) ptch.Patches = []patch.ModulePatch{ { ModuleName: "", Githash: "1e5232709595db427893826ce19289461cba3f75", PatchSet: patch.PatchSet{PatchFileId: p1Id}, }, { ModuleName: "recursive", Githash: "1e5232709595db427893826ce19289461cba3f75", PatchSet: patch.PatchSet{PatchFileId: p2Id}, }, } } testutil.HandleTestingErr(ptch.Insert(), t, "failed to insert patch") } session, _, err := dbutil.GetGlobalSessionFactory().GetSession() testutil.HandleTestingErr(err, t, "couldn't get db session!") // Remove any logs for our test task from previous runs. _, err = session.DB(model.TaskLogDB).C(model.TaskLogCollection). RemoveAll(bson.M{"t_id": bson.M{"$in": []string{taskOne.Id, taskTwo.Id}}}) testutil.HandleTestingErr(err, t, "failed to remove logs") build := &build.Build{ Id: "testBuildId", Tasks: []build.TaskCache{ build.NewTaskCache(taskOne.Id, taskOne.DisplayName, true), build.NewTaskCache(taskTwo.Id, taskTwo.DisplayName, true), }, Version: "testVersionId", } testutil.HandleTestingErr(build.Insert(), t, "failed to insert build") return taskOne, build, nil }
func TestGetVersionStatus(t *testing.T) { userManager, err := auth.LoadUserManager(versionTestConfig.AuthConfig) testutil.HandleTestingErr(err, t, "Failure in loading UserManager from config") uis := UIServer{ RootURL: versionTestConfig.Ui.Url, Settings: *versionTestConfig, UserManager: userManager, } home := evergreen.FindEvergreenHome() uis.Render = render.New(render.Options{ Directory: filepath.Join(home, WebRootPath, Templates), DisableCache: true, Funcs: nil, }) router, err := uis.NewRouter() testutil.HandleTestingErr(err, t, "Failure in uis.NewRouter()") Convey("When finding the status of a particular version", t, func() { testutil.HandleTestingErr(db.Clear(build.Collection), t, "Error clearing '%v' collection", build.Collection) versionId := "my-version" task := build.TaskCache{ Id: "some-task-id", DisplayName: "some-task-name", Status: "success", TimeTaken: time.Duration(100 * time.Millisecond), } build := &build.Build{ Id: "some-build-id", Version: versionId, BuildVariant: "some-build-variant", DisplayName: "Some Build Variant", Tasks: []build.TaskCache{task}, } So(build.Insert(), ShouldBeNil) Convey("grouped by tasks", func() { groupBy := "tasks" url, err := router.Get("version_status").URL("version_id", versionId) So(err, ShouldBeNil) query := url.Query() query.Set("groupby", groupBy) url.RawQuery = query.Encode() request, err := http.NewRequest("GET", url.String(), nil) So(err, ShouldBeNil) response := httptest.NewRecorder() // Need match variables to be set so can call mux.Vars(request) // in the actual handler function router.ServeHTTP(response, request) So(response.Code, ShouldEqual, http.StatusOK) Convey("response should match contents of database", func() { var jsonBody map[string]interface{} err = json.Unmarshal(response.Body.Bytes(), &jsonBody) So(err, ShouldBeNil) So(jsonBody["version_id"], ShouldEqual, versionId) _jsonTasks, ok := jsonBody["tasks"] So(ok, ShouldBeTrue) jsonTasks, ok := _jsonTasks.(map[string]interface{}) So(ok, ShouldBeTrue) So(len(jsonTasks), ShouldEqual, 1) _jsonTask, ok := jsonTasks[task.DisplayName] So(ok, ShouldBeTrue) jsonTask, ok := _jsonTask.(map[string]interface{}) So(ok, ShouldBeTrue) _jsonBuild, ok := jsonTask[build.BuildVariant] So(ok, ShouldBeTrue) jsonBuild, ok := _jsonBuild.(map[string]interface{}) So(ok, ShouldBeTrue) So(jsonBuild["task_id"], ShouldEqual, task.Id) So(jsonBuild["status"], ShouldEqual, task.Status) So(jsonBuild["time_taken"], ShouldEqual, task.TimeTaken) }) Convey("is the default option", func() { url, err := router.Get("version_status").URL("version_id", versionId) So(err, ShouldBeNil) request, err := http.NewRequest("GET", url.String(), nil) So(err, ShouldBeNil) _response := httptest.NewRecorder() // Need match variables to be set so can call mux.Vars(request) // in the actual handler function router.ServeHTTP(_response, request) So(_response, ShouldResemble, response) }) }) Convey("grouped by builds", func() { groupBy := "builds" url, err := router.Get("version_status").URL("version_id", versionId) So(err, ShouldBeNil) query := url.Query() query.Set("groupby", groupBy) url.RawQuery = query.Encode() request, err := http.NewRequest("GET", url.String(), nil) So(err, ShouldBeNil) response := httptest.NewRecorder() // Need match variables to be set so can call mux.Vars(request) // in the actual handler function router.ServeHTTP(response, request) So(response.Code, ShouldEqual, http.StatusOK) Convey("response should match contents of database", func() { var jsonBody map[string]interface{} err = json.Unmarshal(response.Body.Bytes(), &jsonBody) So(err, ShouldBeNil) So(jsonBody["version_id"], ShouldEqual, versionId) _jsonBuilds, ok := jsonBody["builds"] So(ok, ShouldBeTrue) jsonBuilds, ok := _jsonBuilds.(map[string]interface{}) So(ok, ShouldBeTrue) So(len(jsonBuilds), ShouldEqual, 1) _jsonBuild, ok := jsonBuilds[build.BuildVariant] So(ok, ShouldBeTrue) jsonBuild, ok := _jsonBuild.(map[string]interface{}) So(ok, ShouldBeTrue) _jsonTask, ok := jsonBuild[task.DisplayName] So(ok, ShouldBeTrue) jsonTask, ok := _jsonTask.(map[string]interface{}) So(ok, ShouldBeTrue) So(jsonTask["task_id"], ShouldEqual, task.Id) So(jsonTask["status"], ShouldEqual, task.Status) So(jsonTask["time_taken"], ShouldEqual, task.TimeTaken) }) }) Convey("grouped by an invalid option", func() { groupBy := "invalidOption" url, err := router.Get("version_status").URL("version_id", versionId) So(err, ShouldBeNil) query := url.Query() query.Set("groupby", groupBy) url.RawQuery = query.Encode() request, err := http.NewRequest("GET", url.String(), nil) So(err, ShouldBeNil) response := httptest.NewRecorder() // Need match variables to be set so can call mux.Vars(request) // in the actual handler function router.ServeHTTP(response, request) So(response.Code, ShouldEqual, http.StatusBadRequest) var jsonBody map[string]interface{} err = json.Unmarshal(response.Body.Bytes(), &jsonBody) So(err, ShouldBeNil) So(jsonBody["message"], ShouldEqual, fmt.Sprintf("Invalid groupby parameter '%v'", groupBy)) }) }) Convey("When finding the status of a nonexistent version", t, func() { versionId := "not-present" Convey("grouped by tasks", func() { groupBy := "tasks" url, err := router.Get("version_status").URL("version_id", versionId) So(err, ShouldBeNil) query := url.Query() query.Set("groupby", groupBy) url.RawQuery = query.Encode() request, err := http.NewRequest("GET", url.String(), nil) So(err, ShouldBeNil) response := httptest.NewRecorder() // Need match variables to be set so can call mux.Vars(request) // in the actual handler function router.ServeHTTP(response, request) So(response.Code, ShouldEqual, http.StatusOK) Convey("response should contain a sensible error message", func() { var jsonBody map[string]interface{} err = json.Unmarshal(response.Body.Bytes(), &jsonBody) So(err, ShouldBeNil) _jsonTasks, ok := jsonBody["tasks"] So(ok, ShouldBeTrue) jsonTasks, ok := _jsonTasks.(map[string]interface{}) So(ok, ShouldBeTrue) So(jsonTasks, ShouldBeEmpty) }) }) Convey("grouped by builds", func() { versionId := "not-present" groupBy := "builds" url, err := router.Get("version_status").URL("version_id", versionId) So(err, ShouldBeNil) query := url.Query() query.Set("groupby", groupBy) url.RawQuery = query.Encode() request, err := http.NewRequest("GET", url.String(), nil) So(err, ShouldBeNil) response := httptest.NewRecorder() // Need match variables to be set so can call mux.Vars(request) // in the actual handler function router.ServeHTTP(response, request) So(response.Code, ShouldEqual, http.StatusOK) Convey("response should contain a sensible error message", func() { var jsonBody map[string]interface{} err = json.Unmarshal(response.Body.Bytes(), &jsonBody) So(err, ShouldBeNil) _jsonBuilds, ok := jsonBody["builds"] So(ok, ShouldBeTrue) jsonBuilds, ok := _jsonBuilds.(map[string]interface{}) So(ok, ShouldBeTrue) So(jsonBuilds, ShouldBeEmpty) }) }) }) }
func TestGetBuildStatus(t *testing.T) { userManager, err := auth.LoadUserManager(buildTestConfig.AuthConfig) testutil.HandleTestingErr(err, t, "Failure in loading UserManager from config") uis := UIServer{ RootURL: buildTestConfig.Ui.Url, Settings: *buildTestConfig, UserManager: userManager, } home := evergreen.FindEvergreenHome() uis.Render = render.New(render.Options{ Directory: filepath.Join(home, WebRootPath, Templates), DisableCache: true, }) uis.InitPlugins() router, err := uis.NewRouter() testutil.HandleTestingErr(err, t, "Failed to create ui server router") Convey("When finding the status of a particular build", t, func() { testutil.HandleTestingErr(db.Clear(build.Collection), t, "Error clearing '%v' collection", build.Collection) buildId := "my-build" versionId := "my-version" task := build.TaskCache{ Id: "some-task-id", DisplayName: "some-task-name", Status: "success", TimeTaken: time.Duration(100 * time.Millisecond), } build := &build.Build{ Id: buildId, Version: versionId, BuildVariant: "some-build-variant", DisplayName: "Some Build Variant", Tasks: []build.TaskCache{task}, } So(build.Insert(), ShouldBeNil) url, err := router.Get("build_status").URL("build_id", buildId) So(err, ShouldBeNil) request, err := http.NewRequest("GET", url.String(), nil) So(err, ShouldBeNil) response := httptest.NewRecorder() // Need match variables to be set so can call mux.Vars(request) // in the actual handler function router.ServeHTTP(response, request) So(response.Code, ShouldEqual, http.StatusOK) Convey("response should match contents of database", func() { var jsonBody map[string]interface{} err = json.Unmarshal(response.Body.Bytes(), &jsonBody) So(err, ShouldBeNil) var rawJsonBody map[string]*json.RawMessage err = json.Unmarshal(response.Body.Bytes(), &rawJsonBody) So(err, ShouldBeNil) So(jsonBody["build_id"], ShouldEqual, build.Id) So(jsonBody["build_variant"], ShouldEqual, build.BuildVariant) _jsonTasks, ok := jsonBody["tasks"] So(ok, ShouldBeTrue) jsonTasks, ok := _jsonTasks.(map[string]interface{}) So(ok, ShouldBeTrue) So(len(jsonTasks), ShouldEqual, 1) _jsonTask, ok := jsonTasks[task.DisplayName] So(ok, ShouldBeTrue) jsonTask, ok := _jsonTask.(map[string]interface{}) So(ok, ShouldBeTrue) So(jsonTask["task_id"], ShouldEqual, task.Id) So(jsonTask["status"], ShouldEqual, task.Status) So(jsonTask["time_taken"], ShouldEqual, task.TimeTaken) }) }) Convey("When finding the status of a nonexistent build", t, func() { buildId := "not-present" url, err := router.Get("build_status").URL("build_id", buildId) So(err, ShouldBeNil) request, err := http.NewRequest("GET", url.String(), nil) So(err, ShouldBeNil) response := httptest.NewRecorder() // Need match variables to be set so can call mux.Vars(request) // in the actual handler function router.ServeHTTP(response, request) So(response.Code, ShouldEqual, http.StatusNotFound) Convey("response should contain a sensible error message", func() { var jsonBody map[string]interface{} err = json.Unmarshal(response.Body.Bytes(), &jsonBody) So(err, ShouldBeNil) So(len(jsonBody["message"].(string)), ShouldBeGreaterThan, 0) }) }) }
func TestActivateVersion(t *testing.T) { userManager, err := auth.LoadUserManager(versionTestConfig.AuthConfig) testutil.HandleTestingErr(err, t, "Failure in loading UserManager from config") uis := UIServer{ RootURL: versionTestConfig.Ui.Url, Settings: *versionTestConfig, UserManager: userManager, } home := evergreen.FindEvergreenHome() uis.Render = render.New(render.Options{ Directory: filepath.Join(home, WebRootPath, Templates), DisableCache: true, Funcs: nil, }) router, err := uis.NewRouter() testutil.HandleTestingErr(err, t, "Failure in uis.NewRouter()") Convey("When marking a particular version as active", t, func() { testutil.HandleTestingErr(db.Clear(version.Collection), t, "Error clearing '%v' collection", version.Collection) versionId := "my-version" projectName := "project_test" build := &build.Build{ Id: "some-build-id", BuildVariant: "some-build-variant", } So(build.Insert(), ShouldBeNil) v := &version.Version{ Id: versionId, CreateTime: time.Now().Add(-20 * time.Minute), StartTime: time.Now().Add(-10 * time.Minute), FinishTime: time.Now().Add(-5 * time.Second), Revision: fmt.Sprintf("%x", rand.Int()), Author: "some-author", AuthorEmail: "some-email", Message: "some-message", Status: "success", BuildIds: []string{build.Id}, BuildVariants: []version.BuildStatus{{"some-build-variant", true, time.Now().Add(-20 * time.Minute), "some-build-id"}}, RevisionOrderNumber: rand.Int(), Owner: "some-owner", Repo: "some-repo", Branch: "some-branch", RepoKind: "github", Identifier: projectName, Remote: false, RemotePath: "", Requester: evergreen.RepotrackerVersionRequester, } So(v.Insert(), ShouldBeNil) url, err := router.Get("version_info").URL("version_id", versionId) So(err, ShouldBeNil) var body = map[string]interface{}{ "activated": true, } jsonBytes, err := json.Marshal(body) So(err, ShouldBeNil) bodyReader := bytes.NewReader(jsonBytes) request, err := http.NewRequest("PATCH", url.String(), bodyReader) So(err, ShouldBeNil) response := httptest.NewRecorder() // Need match variables to be set so can call mux.Vars(request) // in the actual handler function router.ServeHTTP(response, request) So(response.Code, ShouldEqual, http.StatusOK) validateVersionInfo(v, response) }) Convey("When marking a nonexistent version as active", t, func() { versionId := "not-present" url, err := router.Get("version_info").URL("version_id", versionId) So(err, ShouldBeNil) var body = map[string]interface{}{ "activated": true, } jsonBytes, err := json.Marshal(body) So(err, ShouldBeNil) bodyReader := bytes.NewReader(jsonBytes) request, err := http.NewRequest("PATCH", url.String(), bodyReader) So(err, ShouldBeNil) response := httptest.NewRecorder() // Need match variables to be set so can call mux.Vars(request) // in the actual handler function router.ServeHTTP(response, request) So(response.Code, ShouldEqual, http.StatusNotFound) Convey("response should contain a sensible error message", func() { var jsonBody map[string]interface{} err = json.Unmarshal(response.Body.Bytes(), &jsonBody) So(err, ShouldBeNil) So(jsonBody["message"], ShouldEqual, fmt.Sprintf("Error finding version '%v'", versionId)) }) }) }
func TestGetRecentVersions(t *testing.T) { userManager, err := auth.LoadUserManager(versionTestConfig.AuthConfig) testutil.HandleTestingErr(err, t, "Failure in loading UserManager from config") uis := UIServer{ RootURL: versionTestConfig.Ui.Url, Settings: *versionTestConfig, UserManager: userManager, } home := evergreen.FindEvergreenHome() uis.Render = render.New(render.Options{ Directory: filepath.Join(home, WebRootPath, Templates), DisableCache: true, Funcs: nil, }) router, err := uis.NewRouter() testutil.HandleTestingErr(err, t, "Failure in uis.NewRouter()") err = testutil.CreateTestLocalConfig(buildTestConfig, "mci-test", "") testutil.HandleTestingErr(err, t, "Error loading local config mci-test") err = testutil.CreateTestLocalConfig(buildTestConfig, "render", "") testutil.HandleTestingErr(err, t, "Error loading local config render") Convey("When finding recent versions", t, func() { testutil.HandleTestingErr(db.ClearCollections(version.Collection, build.Collection), t, "Error clearing '%v' collection", version.Collection) projectName := "project_test" err = testutil.CreateTestLocalConfig(buildTestConfig, projectName, "") So(err, ShouldBeNil) otherProjectName := "my-other-project" So(projectName, ShouldNotEqual, otherProjectName) // sanity-check buildIdPreface := "build-id-for-version%v" So(rest.NumRecentVersions, ShouldBeGreaterThan, 0) versions := make([]*version.Version, 0, rest.NumRecentVersions) // Insert a bunch of versions into the database for i := 0; i < rest.NumRecentVersions; i++ { v := &version.Version{ Id: fmt.Sprintf("version%v", i), Identifier: projectName, Author: fmt.Sprintf("author%v", i), Revision: fmt.Sprintf("%x", rand.Int()), Message: fmt.Sprintf("message%v", i), RevisionOrderNumber: i + 1, Requester: evergreen.RepotrackerVersionRequester, } So(v.Insert(), ShouldBeNil) versions = append(versions, v) } // Construct a version that should not be present in the response // since the length of the build ids slice is different than that // of the build variants slice earlyVersion := &version.Version{ Id: "some-id", Identifier: projectName, Author: "some-author", Revision: fmt.Sprintf("%x", rand.Int()), Message: "some-message", RevisionOrderNumber: 0, Requester: evergreen.RepotrackerVersionRequester, } So(earlyVersion.Insert(), ShouldBeNil) // Construct a version that should not be present in the response // since it belongs to a different project otherVersion := &version.Version{ Id: "some-other-id", Identifier: otherProjectName, Author: "some-other-author", Revision: fmt.Sprintf("%x", rand.Int()), Message: "some-other-message", RevisionOrderNumber: rest.NumRecentVersions + 1, Requester: evergreen.RepotrackerVersionRequester, } So(otherVersion.Insert(), ShouldBeNil) builds := make([]*build.Build, 0, rest.NumRecentVersions) task := build.TaskCache{ Id: "some-task-id", DisplayName: "some-task-name", Status: "success", TimeTaken: time.Duration(100 * time.Millisecond), } for i := 0; i < rest.NumRecentVersions; i++ { build := &build.Build{ Id: fmt.Sprintf(buildIdPreface, i), Version: versions[i].Id, BuildVariant: "some-build-variant", DisplayName: "Some Build Variant", Tasks: []build.TaskCache{task}, } So(build.Insert(), ShouldBeNil) builds = append(builds, build) } url, err := router.Get("recent_versions").URL("project_id", projectName) So(err, ShouldBeNil) request, err := http.NewRequest("GET", url.String(), nil) So(err, ShouldBeNil) response := httptest.NewRecorder() // Need match variables to be set so can call mux.Vars(request) // in the actual handler function router.ServeHTTP(response, request) So(response.Code, ShouldEqual, http.StatusOK) Convey("response should match contents of database", func() { var jsonBody map[string]interface{} err = json.Unmarshal(response.Body.Bytes(), &jsonBody) So(err, ShouldBeNil) var rawJsonBody map[string]*json.RawMessage err = json.Unmarshal(response.Body.Bytes(), &rawJsonBody) So(err, ShouldBeNil) So(jsonBody["project"], ShouldEqual, projectName) var jsonVersions []map[string]interface{} err = json.Unmarshal(*rawJsonBody["versions"], &jsonVersions) So(err, ShouldBeNil) So(len(jsonVersions), ShouldEqual, len(versions)) for i, v := range versions { jsonVersion := jsonVersions[len(jsonVersions)-i-1] // reverse order So(jsonVersion["version_id"], ShouldEqual, v.Id) So(jsonVersion["author"], ShouldEqual, v.Author) So(jsonVersion["revision"], ShouldEqual, v.Revision) So(jsonVersion["message"], ShouldEqual, v.Message) _jsonBuilds, ok := jsonVersion["builds"] So(ok, ShouldBeTrue) jsonBuilds, ok := _jsonBuilds.(map[string]interface{}) So(ok, ShouldBeTrue) So(len(jsonBuilds), ShouldEqual, 1) _jsonBuild, ok := jsonBuilds[builds[i].BuildVariant] So(ok, ShouldBeTrue) jsonBuild, ok := _jsonBuild.(map[string]interface{}) So(ok, ShouldBeTrue) So(jsonBuild["build_id"], ShouldEqual, builds[i].Id) So(jsonBuild["name"], ShouldEqual, builds[i].DisplayName) _jsonTasks, ok := jsonBuild["tasks"] So(ok, ShouldBeTrue) jsonTasks, ok := _jsonTasks.(map[string]interface{}) So(ok, ShouldBeTrue) So(len(jsonTasks), ShouldEqual, 1) _jsonTask, ok := jsonTasks[task.DisplayName] So(ok, ShouldBeTrue) jsonTask, ok := _jsonTask.(map[string]interface{}) So(ok, ShouldBeTrue) So(jsonTask["task_id"], ShouldEqual, task.Id) So(jsonTask["status"], ShouldEqual, task.Status) So(jsonTask["time_taken"], ShouldEqual, task.TimeTaken) } }) }) Convey("When finding recent versions for a nonexistent project", t, func() { projectName := "not-present" url, err := router.Get("recent_versions").URL("project_id", projectName) So(err, ShouldBeNil) request, err := http.NewRequest("GET", url.String(), nil) So(err, ShouldBeNil) response := httptest.NewRecorder() // Need match variables to be set so can call mux.Vars(request) // in the actual handler function router.ServeHTTP(response, request) So(response.Code, ShouldEqual, http.StatusOK) Convey("response should contain no versions", func() { var jsonBody map[string]interface{} err = json.Unmarshal(response.Body.Bytes(), &jsonBody) So(err, ShouldBeNil) var rawJsonBody map[string]*json.RawMessage err = json.Unmarshal(response.Body.Bytes(), &rawJsonBody) So(err, ShouldBeNil) So(jsonBody["project"], ShouldEqual, projectName) var jsonVersions []map[string]interface{} err = json.Unmarshal(*rawJsonBody["versions"], &jsonVersions) So(err, ShouldBeNil) So(jsonVersions, ShouldBeEmpty) }) }) }
func setupAPITestData(testConfig *evergreen.Settings, taskDisplayName string, variant string, projectFile string, patchMode patchTestMode, t *testing.T) (*model.Task, *build.Build, error) { // Ignore errs here because the ns might just not exist. clearDataMsg := "Failed to clear test data collection" testCollections := []string{ model.TasksCollection, build.Collection, host.Collection, distro.Collection, version.Collection, patch.Collection, model.PushlogCollection, model.ProjectVarsCollection, model.TaskQueuesCollection, manifest.Collection, model.ProjectRefCollection} testutil.HandleTestingErr(dbutil.ClearCollections(testCollections...), t, clearDataMsg) // Read in the project configuration projectConfig, err := ioutil.ReadFile(projectFile) testutil.HandleTestingErr(err, t, "failed to read project config") // Unmarshall the project configuration into a struct project := &model.Project{} testutil.HandleTestingErr(yaml.Unmarshal(projectConfig, project), t, "failed to unmarshal project config") // Marshall the project YAML for storage projectYamlBytes, err := yaml.Marshal(project) testutil.HandleTestingErr(err, t, "failed to marshall project config") // Create the ref for the project projectRef := &model.ProjectRef{ Identifier: project.DisplayName, Owner: project.Owner, Repo: project.Repo, RepoKind: project.RepoKind, Branch: project.Branch, Enabled: project.Enabled, BatchTime: project.BatchTime, LocalConfig: string(projectConfig), } testutil.HandleTestingErr(projectRef.Insert(), t, "failed to insert projectRef") // Save the project variables projectVars := &model.ProjectVars{ Id: project.DisplayName, Vars: map[string]string{ "aws_key": testConfig.Providers.AWS.Id, "aws_secret": testConfig.Providers.AWS.Secret, "fetch_key": "fetch_expansion_value", }, } _, err = projectVars.Upsert() testutil.HandleTestingErr(err, t, clearDataMsg) // Create and insert two tasks taskOne := &model.Task{ Id: "testTaskId", BuildId: "testBuildId", DistroId: "test-distro-one", BuildVariant: variant, Project: project.DisplayName, DisplayName: taskDisplayName, HostId: "testHost", Secret: "testTaskSecret", Version: "testVersionId", Status: evergreen.TaskDispatched, Requester: evergreen.RepotrackerVersionRequester, } if patchMode != NoPatch { taskOne.Requester = evergreen.PatchVersionRequester } testutil.HandleTestingErr(taskOne.Insert(), t, "failed to insert taskOne") taskTwo := &model.Task{ Id: "testTaskIdTwo", BuildId: "testBuildId", DistroId: "test-distro-one", BuildVariant: variant, Project: project.DisplayName, DisplayName: taskDisplayName, HostId: "", Secret: "testTaskSecret", Version: "testVersionId", Status: evergreen.TaskUndispatched, Requester: evergreen.RepotrackerVersionRequester, Activated: true, } testutil.HandleTestingErr(taskTwo.Insert(), t, "failed to insert taskTwo") // Set up a task queue for task end tests taskQueue := &model.TaskQueue{ Distro: "test-distro-one", Queue: []model.TaskQueueItem{ model.TaskQueueItem{ Id: "testTaskIdTwo", DisplayName: taskDisplayName, }, }, } testutil.HandleTestingErr(taskQueue.Save(), t, "failed to insert taskqueue") // Insert the version document v := &version.Version{ Id: "testVersionId", BuildIds: []string{taskOne.BuildId}, Config: string(projectYamlBytes), } testutil.HandleTestingErr(v.Insert(), t, "failed to insert version") // Insert the build that contains the tasks build := &build.Build{ Id: "testBuildId", Tasks: []build.TaskCache{ build.NewTaskCache(taskOne.Id, taskOne.DisplayName, true), build.NewTaskCache(taskTwo.Id, taskTwo.DisplayName, true), }, Version: v.Id, } testutil.HandleTestingErr(build.Insert(), t, "failed to insert build") workDir, err := ioutil.TempDir("", "agent_test_") testutil.HandleTestingErr(err, t, "failed to create working directory") // Insert the host info for running the tests host := &host.Host{ Id: "testHost", Host: "testHost", Distro: distro.Distro{ Id: "test-distro-one", WorkDir: workDir, Expansions: []distro.Expansion{{"distro_exp", "DISTRO_EXP"}}, }, RunningTask: taskOne.Id, StartedBy: evergreen.User, AgentRevision: agentRevision, } testutil.HandleTestingErr(host.Insert(), t, "failed to insert host") session, _, err := dbutil.GetGlobalSessionFactory().GetSession() testutil.HandleTestingErr(err, t, "couldn't get db session!") // Remove any logs for our test task from previous runs. _, err = session.DB(model.TaskLogDB).C(model.TaskLogCollection). RemoveAll(bson.M{"t_id": bson.M{"$in": []string{taskOne.Id, taskTwo.Id}}}) testutil.HandleTestingErr(err, t, "failed to remove logs") return taskOne, build, nil }
func TestActivateVersion(t *testing.T) { uis := UIServer{ RootURL: versionTestConfig.Ui.Url, Settings: *versionTestConfig, UserManager: MockUserManager{}, } home := evergreen.FindEvergreenHome() uis.Render = render.New(render.Options{ Directory: filepath.Join(home, WebRootPath, Templates), DisableCache: true, }) uis.InitPlugins() router, err := uis.NewRouter() testutil.HandleTestingErr(err, t, "Failed to create ui server router") n := negroni.New() n.Use(negroni.HandlerFunc(UserMiddleware(uis.UserManager))) n.UseHandler(router) Convey("When marking a particular version as active", t, func() { testutil.HandleTestingErr(db.ClearCollections(version.Collection, build.Collection), t, "Error clearing collections") versionId := "my-version" projectName := "project_test" build := &build.Build{ Id: "some-build-id", BuildVariant: "some-build-variant", } So(build.Insert(), ShouldBeNil) v := &version.Version{ Id: versionId, CreateTime: time.Now().Add(-20 * time.Minute), StartTime: time.Now().Add(-10 * time.Minute), FinishTime: time.Now().Add(-5 * time.Second), Revision: fmt.Sprintf("%x", rand.Int()), Author: "some-author", AuthorEmail: "some-email", Message: "some-message", Status: "success", BuildIds: []string{build.Id}, BuildVariants: []version.BuildStatus{{"some-build-variant", true, time.Now().Add(-20 * time.Minute), "some-build-id"}}, RevisionOrderNumber: rand.Int(), Owner: "some-owner", Repo: "some-repo", Branch: "some-branch", RepoKind: "github", Identifier: projectName, Remote: false, RemotePath: "", Requester: evergreen.RepotrackerVersionRequester, } So(v.Insert(), ShouldBeNil) url, err := router.Get("version_info").URL("version_id", versionId) So(err, ShouldBeNil) var body = map[string]interface{}{ "activated": true, } jsonBytes, err := json.Marshal(body) So(err, ShouldBeNil) bodyReader := bytes.NewReader(jsonBytes) request, err := http.NewRequest("PATCH", url.String(), bodyReader) So(err, ShouldBeNil) // add auth cookie--this can be anything if we are using a MockUserManager request.AddCookie(&http.Cookie{Name: evergreen.AuthTokenCookie, Value: "token"}) response := httptest.NewRecorder() // Need match variables to be set so can call mux.Vars(request) // in the actual handler function n.ServeHTTP(response, request) So(response.Code, ShouldEqual, http.StatusOK) validateVersionInfo(v, response) }) Convey("When marking a nonexistent version as active", t, func() { versionId := "not-present" url, err := router.Get("version_info").URL("version_id", versionId) So(err, ShouldBeNil) var body = map[string]interface{}{ "activated": true, } jsonBytes, err := json.Marshal(body) So(err, ShouldBeNil) bodyReader := bytes.NewReader(jsonBytes) request, err := http.NewRequest("PATCH", url.String(), bodyReader) So(err, ShouldBeNil) response := httptest.NewRecorder() // add auth cookie--this can be anything if we are using a MockUserManager request.AddCookie(&http.Cookie{Name: evergreen.AuthTokenCookie, Value: "token"}) n.ServeHTTP(response, request) So(response.Code, ShouldEqual, http.StatusNotFound) Convey("response should contain a sensible error message", func() { var jsonBody map[string]interface{} err = json.Unmarshal(response.Body.Bytes(), &jsonBody) So(err, ShouldBeNil) So(len(jsonBody["message"].(string)), ShouldBeGreaterThan, 0) }) }) Convey("When modifying a version without credentials", t, func() { versionId := "not-present" url, err := router.Get("version_info").URL("version_id", versionId) So(err, ShouldBeNil) var body = map[string]interface{}{ "activated": true, } jsonBytes, err := json.Marshal(body) So(err, ShouldBeNil) bodyReader := bytes.NewReader(jsonBytes) request, err := http.NewRequest("PATCH", url.String(), bodyReader) So(err, ShouldBeNil) response := httptest.NewRecorder() n.ServeHTTP(response, request) Convey("response should indicate a permission error", func() { So(response.Code, ShouldEqual, http.StatusUnauthorized) }) }) }
func TestCleanupTask(t *testing.T) { testConfig := evergreen.TestConfig() db.SetGlobalSessionProvider(db.SessionFactoryFromConfig(testConfig)) Convey("When cleaning up a task", t, func() { // reset the db testutil.HandleTestingErr(db.ClearCollections(task.Collection), t, "error clearing tasks collection") testutil.HandleTestingErr(db.ClearCollections(host.Collection), t, "error clearing hosts collection") Convey("an error should be thrown if the passed-in projects slice"+ " does not contain the task's project", func() { wrapper := doomedTaskWrapper{ task: task.Task{ Project: "proj", }, } projects := map[string]model.Project{} err := cleanUpTask(wrapper, projects) So(err, ShouldNotBeNil) So(err.Error(), ShouldContainSubstring, "could not find project") }) Convey("an error should be thrown if the task's host is marked with"+ " the wrong running task id", func() { wrapper := doomedTaskWrapper{ task: task.Task{ Id: "t1", HostId: "h1", Project: "proj", }, } projects := map[string]model.Project{ "proj": { Identifier: "proj", }, } host := &host.Host{ Id: "h1", RunningTask: "nott1", } So(host.Insert(), ShouldBeNil) err := cleanUpTask(wrapper, projects) So(err, ShouldNotBeNil) So(err.Error(), ShouldContainSubstring, "but the host thinks it"+ " is running task") }) Convey("if the task's heartbeat timed out", func() { // reset the db testutil.HandleTestingErr(db.ClearCollections(task.Collection), t, "error clearing tasks collection") testutil.HandleTestingErr(db.ClearCollections(host.Collection), t, "error clearing hosts collection") testutil.HandleTestingErr(db.ClearCollections(build.Collection), t, "error clearing builds collection") testutil.HandleTestingErr(db.ClearCollections(task.OldCollection), t, "error clearing old tasks collection") testutil.HandleTestingErr(db.ClearCollections(version.Collection), t, "error clearing versions collection") Convey("the task should be reset", func() { newTask := &task.Task{ Id: "t1", Status: "started", HostId: "h1", BuildId: "b1", Project: "proj", Restarts: 1, } testutil.HandleTestingErr(newTask.Insert(), t, "error inserting task") wrapper := doomedTaskWrapper{ reason: HeartbeatTimeout, task: *newTask, } projects := map[string]model.Project{ "proj": { Identifier: "proj", Stepback: false, }, } host := &host.Host{ Id: "h1", RunningTask: "t1", } So(host.Insert(), ShouldBeNil) build := &build.Build{ Id: "b1", Tasks: []build.TaskCache{{Id: "t1"}}, Version: "v1", } So(build.Insert(), ShouldBeNil) v := &version.Version{ Id: "v1", } So(v.Insert(), ShouldBeNil) // cleaning up the task should work So(cleanUpTask(wrapper, projects), ShouldBeNil) // refresh the task - it should be reset newTask, err := task.FindOne(task.ById("t1")) So(err, ShouldBeNil) So(newTask.Status, ShouldEqual, evergreen.TaskUndispatched) So(newTask.Restarts, ShouldEqual, 2) }) Convey("the running task field on the task's host should be"+ " reset", func() { newTask := &task.Task{ Id: "t1", Status: "started", HostId: "h1", BuildId: "b1", Project: "proj", Restarts: 1, } testutil.HandleTestingErr(newTask.Insert(), t, "error inserting task") wrapper := doomedTaskWrapper{ reason: HeartbeatTimeout, task: *newTask, } projects := map[string]model.Project{ "proj": { Identifier: "proj", Stepback: false, }, } h := &host.Host{ Id: "h1", RunningTask: "t1", } So(h.Insert(), ShouldBeNil) build := &build.Build{ Id: "b1", Tasks: []build.TaskCache{{Id: "t1"}}, Version: "v1", } So(build.Insert(), ShouldBeNil) v := &version.Version{Id: "v1"} So(v.Insert(), ShouldBeNil) // cleaning up the task should work So(cleanUpTask(wrapper, projects), ShouldBeNil) // refresh the host, make sure its running task field has // been reset h, err := host.FindOne(host.ById("h1")) So(err, ShouldBeNil) So(h.RunningTask, ShouldEqual, "") }) }) }) }