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) verrs, err := CheckProjectSyntax(project) So(err, ShouldBeNil) So(verrs, ShouldResemble, []ValidationError{}) }) Reset(func() { db.Clear(distro.Collection) }) }) }
func TestProjectRef(t *testing.T) { Convey("When inserting a project ref", t, func() { err := modelutil.CreateTestLocalConfig(patchTestConfig, "mci-test", "") So(err, ShouldBeNil) projectRef, err := model.FindOneProjectRef("mci-test") So(err, ShouldBeNil) So(projectRef, ShouldNotBeNil) So(projectRef.Identifier, ShouldEqual, "mci-test") }) }
func TestFetchRevisions(t *testing.T) { dropTestDB(t) testutil.ConfigureIntegrationTest(t, testConfig, "TestFetchRevisions") Convey("With a GithubRepositoryPoller with a valid OAuth token...", t, func() { err := modelutil.CreateTestLocalConfig(testConfig, "mci-test", "") So(err, ShouldBeNil) repoTracker := RepoTracker{ testConfig, projectRef, NewGithubRepositoryPoller(projectRef, testConfig.Credentials["github"]), } Convey("Fetching commits from the repository should not return "+ "any errors", func() { So(repoTracker.FetchRevisions(10), ShouldBeNil) }) Convey("Only get 3 revisions from the given repository if given a "+ "limit of 4 commits where only 3 exist", func() { testutil.HandleTestingErr(repoTracker.FetchRevisions(4), t, "Error running repository process %v") numVersions, err := version.Count(version.All) testutil.HandleTestingErr(err, t, "Error finding all versions") So(numVersions, ShouldEqual, 3) }) Convey("Only get 2 revisions from the given repository if given a "+ "limit of 2 commits where 3 exist", func() { testutil.HandleTestingErr(repoTracker.FetchRevisions(2), t, "Error running repository process %v") numVersions, err := version.Count(version.All) testutil.HandleTestingErr(err, t, "Error finding all versions") So(numVersions, ShouldEqual, 2) }) Reset(func() { dropTestDB(t) }) }) }
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 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, }) uis.InitPlugins() router, err := uis.NewRouter() testutil.HandleTestingErr(err, t, "Failed to create ui server router") err = modelutil.CreateTestLocalConfig(buildTestConfig, "mci-test", "") testutil.HandleTestingErr(err, t, "Error loading local config mci-test") err = modelutil.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 = modelutil.CreateTestLocalConfig(buildTestConfig, projectName, "") So(err, ShouldBeNil) otherProjectName := "my-other-project" So(projectName, ShouldNotEqual, otherProjectName) // sanity-check buildIdPreface := "build-id-for-version%v" So(NumRecentVersions, ShouldBeGreaterThan, 0) versions := make([]*version.Version, 0, NumRecentVersions) // Insert a bunch of versions into the database for i := 0; i < 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: NumRecentVersions + 1, Requester: evergreen.RepotrackerVersionRequester, } So(otherVersion.Insert(), ShouldBeNil) builds := make([]*build.Build, 0, NumRecentVersions) task := build.TaskCache{ Id: "some-task-id", DisplayName: "some-task-name", Status: "success", TimeTaken: time.Duration(100 * time.Millisecond), } for i := 0; i < 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 TestGetVersionInfo(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") err = modelutil.CreateTestLocalConfig(buildTestConfig, "mci-test", "") testutil.HandleTestingErr(err, t, "Error loading local config mci-test") err = modelutil.CreateTestLocalConfig(buildTestConfig, "render", "") testutil.HandleTestingErr(err, t, "Error loading local config render") Convey("When finding info on a particular version", t, func() { testutil.HandleTestingErr(db.Clear(version.Collection), t, "Error clearing '%v' collection", version.Collection) versionId := "my-version" projectName := "project_test" err = modelutil.CreateTestLocalConfig(buildTestConfig, projectName, "") So(err, 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{"some-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: versionId, Remote: false, RemotePath: "", Requester: evergreen.RepotrackerVersionRequester, } So(v.Insert(), ShouldBeNil) url, err := router.Get("version_info").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) Println(response.Body) So(response.Code, ShouldEqual, http.StatusOK) validateVersionInfo(v, response) }) Convey("When finding info on a nonexistent version", t, func() { versionId := "not-present" url, err := router.Get("version_info").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.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 TestStoreRepositoryRevisions(t *testing.T) { dropTestDB(t) testutil.ConfigureIntegrationTest(t, testConfig, "TestStoreRepositoryRevisions") Convey("When storing revisions gotten from a repository...", t, func() { err := modelutil.CreateTestLocalConfig(testConfig, "mci-test", "") So(err, ShouldBeNil) repoTracker := RepoTracker{testConfig, projectRef, NewGithubRepositoryPoller(projectRef, testConfig.Credentials["github"])} // insert distros used in testing. d := distro.Distro{Id: "test-distro-one"} So(d.Insert(), ShouldBeNil) d.Id = "test-distro-two" So(d.Insert(), ShouldBeNil) Convey("On storing a single repo revision, we expect a version to be created"+ " in the database for this project, which should be retrieved when we search"+ " for this project's most recent version", func() { createTime := time.Now() revisionOne := *createTestRevision("firstRevision", createTime) revisions := []model.Revision{revisionOne} resultVersion, err := repoTracker.StoreRevisions(revisions) testutil.HandleTestingErr(err, t, "Error storing repository revisions %v") newestVersion, err := version.FindOne(version.ByMostRecentForRequester(projectRef.String(), evergreen.RepotrackerVersionRequester)) testutil.HandleTestingErr(err, t, "Error retreiving newest version %v") So(resultVersion, ShouldResemble, newestVersion) }) Convey("On storing several repo revisions, we expect a version to be created "+ "for each revision", func() { createTime := time.Now() laterCreateTime := createTime.Add(time.Duration(4 * time.Hour)) revisionOne := *createTestRevision("one", laterCreateTime) revisionTwo := *createTestRevision("two", createTime) revisions := []model.Revision{revisionOne, revisionTwo} _, err := repoTracker.StoreRevisions(revisions) testutil.HandleTestingErr(err, t, "Error storing repository revisions %v") versionOne, err := version.FindOne(version.ByProjectIdAndRevision(projectRef.Identifier, revisionOne.Revision)) testutil.HandleTestingErr(err, t, "Error retrieving first stored version %v") versionTwo, err := version.FindOne(version.ByProjectIdAndRevision(projectRef.Identifier, revisionTwo.Revision)) testutil.HandleTestingErr(err, t, "Error retreiving second stored version %v") So(versionOne.Revision, ShouldEqual, revisionOne.Revision) So(versionTwo.Revision, ShouldEqual, revisionTwo.Revision) }) Reset(func() { dropTestDB(t) }) }) Convey("When storing versions from repositories with remote configuration files...", t, func() { project := createTestProject(nil, nil) revisions := []model.Revision{ *createTestRevision("foo", time.Now().Add(1*time.Minute)), } poller := NewMockRepoPoller(project, revisions) repoTracker := RepoTracker{ testConfig, &model.ProjectRef{ Identifier: "testproject", BatchTime: 10, }, poller, } // insert distros used in testing. d := distro.Distro{Id: "test-distro-one"} So(d.Insert(), ShouldBeNil) d.Id = "test-distro-two" So(d.Insert(), ShouldBeNil) Convey("We should not fetch configs for versions we already have stored.", func() { So(poller.ConfigGets, ShouldBeZeroValue) // Store revisions the first time _, err := repoTracker.StoreRevisions(revisions) So(err, ShouldBeNil) // We should have fetched the config once for each revision So(poller.ConfigGets, ShouldEqual, len(revisions)) // Store them again _, err = repoTracker.StoreRevisions(revisions) So(err, ShouldBeNil) // We shouldn't have fetched the config any additional times // since we have already stored these versions So(poller.ConfigGets, ShouldEqual, len(revisions)) }, ) Convey("We should handle invalid configuration files gracefully by storing a stub version", func() { errStrs := []string{"Someone dun' goof'd"} poller.setNextError(projectConfigError{errStrs, []string{}}) stubVersion, err := repoTracker.StoreRevisions(revisions) // We want this error to get swallowed so a config error // doesn't stop additional versions from getting created So(err, ShouldBeNil) So(stubVersion.Errors, ShouldResemble, errStrs) So(len(stubVersion.BuildVariants), ShouldEqual, 0) }) Convey("Project configuration files with missing distros should still create versions", func() { poller.addBadDistro("Cray-Y-MP") v, err := repoTracker.StoreRevisions(revisions) So(err, ShouldBeNil) So(v, ShouldNotBeNil) So(len(v.BuildVariants), ShouldBeGreaterThan, 0) Convey("and log a warning", func() { So(len(v.Warnings), ShouldEqual, 1) So(v.Errors, ShouldBeNil) }) }) Convey("If there is an error other than a config error while fetching a config, we should fail hard", func() { unexpectedError := errors.New("Something terrible has happened!!") poller.setNextError(unexpectedError) v, err := repoTracker.StoreRevisions(revisions) So(v, ShouldBeNil) So(err, ShouldEqual, unexpectedError) }, ) Reset(func() { dropTestDB(t) }) }) }