Example #1
0
func TestLocalScript(t *testing.T) {
	if runtime.GOOS == "windows" {
		t.Skip("shell command test doesn't make sense on windows")
	}

	Convey("When running local commands in script mode", t, func() {

		Convey("A multi-line script should run all lines", func() {

			stdout := &CacheLastWritten{}

			workingDir, err := filepath.Abs(evergreen.FindEvergreenHome())
			So(err, ShouldBeNil)

			command := &LocalCommand{
				CmdString:        "set -v\necho 'hi'\necho 'foo'\necho `pwd`",
				ScriptMode:       true,
				Stdout:           stdout,
				Stderr:           ioutil.Discard,
				WorkingDirectory: workingDir,
			}

			// run the command - the working directory should be as specified
			So(command.Run(), ShouldBeNil)

			reportedPwd := string(stdout.LastWritten)
			reportedPwd = reportedPwd[:len(reportedPwd)-1]
			reportedPwd, err = filepath.EvalSymlinks(reportedPwd)
			So(err, ShouldBeNil)
			So(reportedPwd, ShouldEqual, workingDir)
		})

	})
}
func TestLocalScript(t *testing.T) {
	Convey("When running local commands in script mode", t, func() {

		Convey("A multi-line script should run all lines", func() {

			stdout := &CacheLastWritten{}

			evgHome := evergreen.FindEvergreenHome()
			workingDir := filepath.Join(evgHome, "command/testdata")

			command := &LocalCommand{
				CmdString:        "set -v\necho 'hi'\necho 'foo'\necho `pwd`",
				ScriptMode:       true,
				Stdout:           stdout,
				Stderr:           ioutil.Discard,
				WorkingDirectory: workingDir,
			}

			// run the command - the working directory should be as specified
			So(command.Run(), ShouldBeNil)
			So(string(stdout.LastWritten), ShouldEqual, workingDir+"\n")
		})

	})
}
Example #3
0
func main() {
	settings := evergreen.GetSettingsOrExit()
	if settings.Ui.LogFile != "" {
		evergreen.SetLogger(settings.Ui.LogFile)
	}
	db.SetGlobalSessionProvider(db.SessionFactoryFromConfig(settings))

	home := evergreen.FindEvergreenHome()

	userManager, err := auth.LoadUserManager(settings.AuthConfig)
	if err != nil {
		fmt.Println("Failed to create user manager:", err)
		os.Exit(1)
	}

	cookieStore := sessions.NewCookieStore([]byte(settings.Ui.Secret))

	uis := ui.UIServer{
		nil,             // render
		settings.Ui.Url, // RootURL
		userManager,     // User Manager
		*settings,       // mci settings
		cookieStore,     // cookiestore
		nil,             // plugin panel manager
	}
	router, err := uis.NewRouter()
	if err != nil {
		fmt.Println("Failed to create router:", err)
		os.Exit(1)
	}

	webHome := filepath.Join(home, "public")

	functionOptions := ui.FuncOptions{webHome, settings.Ui.HelpUrl, true, router}

	functions, err := ui.MakeTemplateFuncs(functionOptions, settings.SuperUsers)
	if err != nil {
		fmt.Println("Failed to create template function map:", err)
		os.Exit(1)
	}

	uis.Render = render.New(render.Options{
		Directory:    filepath.Join(home, ui.WebRootPath, ui.Templates),
		DisableCache: !settings.Ui.CacheTemplates,
		Funcs:        functions,
	})
	err = uis.InitPlugins()
	if err != nil {
		fmt.Println("WARNING: Error initializing plugins:", err)
	}

	n := negroni.New()
	n.Use(negroni.NewStatic(http.Dir(webHome)))
	n.Use(ui.NewLogger())
	n.Use(negroni.HandlerFunc(ui.UserMiddleware(userManager)))
	n.UseHandler(router)
	graceful.Run(settings.Ui.HttpListenAddr, requestTimeout, n)
	evergreen.Logger.Logf(slogger.INFO, "UI server cleanly terminated")
}
Example #4
0
// Run loops while there are any unprocessed alerts and attempts to deliver them.
func (qp *QueueProcessor) Run(config *evergreen.Settings) error {
	evergreen.Logger.Logf(slogger.INFO, "Starting alert queue processor run")
	home := evergreen.FindEvergreenHome()
	qp.config = config
	qp.render = render.New(render.Options{
		Directory:    filepath.Join(home, "alerts", "templates"),
		DisableCache: !config.Ui.CacheTemplates,
		TextFuncs:    nil,
		HtmlFuncs:    nil,
	})

	if len(qp.config.SuperUsers) == 0 {
		evergreen.Logger.Logf(slogger.WARN, "WARNING: No superusers configured, some alerts may have no recipient")
	}
	superUsers, err := user.Find(user.ByIds(qp.config.SuperUsers...))
	if err != nil {
		evergreen.Logger.Logf(slogger.ERROR, "Error getting superuser list: %v", err)
		return err
	}
	qp.superUsersConfigs = []model.AlertConfig{}
	for _, u := range superUsers {
		qp.superUsersConfigs = append(qp.superUsersConfigs, model.AlertConfig{"email", bson.M{"rcpt": u.Email()}})
	}
	evergreen.Logger.Logf(slogger.INFO, "Super-users config for outgoing alerts is: %#v", qp.superUsersConfigs)

	evergreen.Logger.Logf(slogger.INFO, "Running alert queue processing")
	for {
		nextAlert, err := alert.DequeueAlertRequest()

		if err != nil {
			evergreen.Logger.Logf(slogger.ERROR, "Failed to dequeue alert request: %v", err)
			return err
		}
		if nextAlert == nil {
			evergreen.Logger.Logf(slogger.INFO, "Reached end of queue items - stopping.")
			break
		}

		evergreen.Logger.Logf(slogger.DEBUG, "Processing queue item %v", nextAlert.Id.Hex())

		alertContext, err := qp.loadAlertContext(nextAlert)
		if err != nil {
			evergreen.Logger.Logf(slogger.ERROR, "Failed to load alert context: %v", err)
			return err
		}

		evergreen.Logger.Logf(slogger.DEBUG, "Delivering queue item %v", nextAlert.Id.Hex())
		err = qp.Deliver(nextAlert, alertContext)
		if err != nil {
			evergreen.Logger.Logf(slogger.ERROR, "Got error delivering message: %v", err)
		}

	}
	evergreen.Logger.Logf(slogger.INFO, "Finished alert queue processor run.")
	return nil
}
Example #5
0
func NewTaskRunner(settings *evergreen.Settings) *TaskRunner {
	// get mci home, and set the source and destination for the agent
	// executables
	evgHome := evergreen.FindEvergreenHome()

	return &TaskRunner{
		settings,
		&DBHostFinder{},
		&DBTaskQueueFinder{},
		&AgentBasedHostGateway{
			ExecutablesDir: filepath.Join(evgHome, settings.AgentExecutablesDir),
		},
	}
}
Example #6
0
func main() {

	settings := evergreen.GetSettingsOrExit()
	home := evergreen.FindEvergreenHome()
	uis, err := ui.New(settings, home)
	if err != nil {
		fmt.Println("Failed to create ui server: %v", err)
		os.Exit(1)
	}
	router, err := uis.NewRouter()
	if err != nil {
		fmt.Println("Failed to create router:", err)
		os.Exit(1)
	}

	webHome := filepath.Join(uis.Home, "public")

	functionOptions := ui.FuncOptions{webHome, uis.Settings.Ui.HelpUrl, true, router}

	functions, err := ui.MakeTemplateFuncs(functionOptions, uis.Settings.SuperUsers)
	htmlFunctions := htmlTemplate.FuncMap(functions)
	textFunctions := textTemplate.FuncMap(functions)

	if err != nil {
		fmt.Println("Failed to create template function map:", err)
		os.Exit(1)
	}

	uis.Render = render.New(render.Options{
		Directory:    filepath.Join(uis.Home, ui.WebRootPath, ui.Templates),
		DisableCache: !uis.Settings.Ui.CacheTemplates,
		HtmlFuncs:    htmlFunctions,
		TextFuncs:    textFunctions,
	})
	err = uis.InitPlugins()
	if err != nil {
		fmt.Println("WARNING: Error initializing plugins:", err)
	}

	n := negroni.New()
	n.Use(negroni.NewStatic(http.Dir(webHome)))
	n.Use(ui.NewLogger())
	n.Use(negroni.HandlerFunc(ui.UserMiddleware(uis.UserManager)))
	n.UseHandler(router)
	graceful.Run(uis.Settings.Ui.HttpListenAddr, requestTimeout, n)
	evergreen.Logger.Logf(slogger.INFO, "UI server cleanly terminated")
}
Example #7
0
// LocateCLIBinary returns the (absolute) path to the CLI binary for the given architecture, based
// on the system settings. Returns an error if the file does not exist.
func LocateCLIBinary(settings *evergreen.Settings, architecture string) (string, error) {
	clientsSubDir := "clients"
	if settings.ClientBinariesDir != "" {
		clientsSubDir = settings.ClientBinariesDir
	}

	var path string
	if filepath.IsAbs(clientsSubDir) {
		path = filepath.Join(clientsSubDir, architecture, "main")
	} else {
		path = filepath.Join(evergreen.FindEvergreenHome(), clientsSubDir, architecture, "main")
	}
	_, err := os.Stat(path)
	if err != nil {
		return path, err
	}
	return filepath.Abs(path)
}
Example #8
0
func createEnvironment(settings *evergreen.Settings, globals map[string]interface{}) (*web.App, error) {
	home := evergreen.FindEvergreenHome()
	templateHome := filepath.Join(home, TemplatePath)

	funcs, err := web.MakeCommonFunctionMap(settings)
	if err != nil {
		return nil, fmt.Errorf("error creating templating functions: %v", err)
	}
	// Overwrite globals
	funcs["Global"] = func(input string) interface{} {
		return globals[input]
	}

	app := web.NewApp()
	app.TemplateFuncs = funcs
	app.TemplateFolder = templateHome
	app.CacheTemplates = true
	return app, nil
}
Example #9
0
// Start the task specified, on the host specified.  First runs any necessary
// preparation on the remote machine, then kicks off the agent process on the
// machine.
// Returns an error if any step along the way fails.
func (self *AgentBasedHostGateway) RunTaskOnHost(settings *evergreen.Settings,
	taskToRun model.Task, hostObj host.Host) (string, error) {

	// cache mci home
	evgHome := evergreen.FindEvergreenHome()

	// get the host's SSH options
	cloudHost, err := providers.GetCloudHost(&hostObj, settings)
	if err != nil {
		return "", fmt.Errorf("Failed to get cloud host for %v: %v", hostObj.Id, err)
	}
	sshOptions, err := cloudHost.GetSSHOptions()
	if err != nil {
		return "", fmt.Errorf("Error getting ssh options for host %v: %v", hostObj.Id, err)
	}

	// prep the remote host
	evergreen.Logger.Logf(slogger.INFO, "Prepping remote host %v...", hostObj.Id)
	agentRevision, err := self.prepRemoteHost(settings, hostObj, sshOptions, evgHome)
	if err != nil {
		return "", fmt.Errorf("error prepping remote host %v: %v", hostObj.Id, err)
	}
	evergreen.Logger.Logf(slogger.INFO, "Prepping host finished successfully")

	// start the agent on the remote machine
	evergreen.Logger.Logf(slogger.INFO, "Starting agent on host %v for task %v...",
		hostObj.Id, taskToRun.Id)

	err = self.startAgentOnRemote(settings, &taskToRun, &hostObj, sshOptions)
	if err != nil {
		return "", fmt.Errorf("error starting agent on %v for task %v: %v",
			hostObj.Id, taskToRun.Id, err)
	}
	evergreen.Logger.Logf(slogger.INFO, "Agent successfully started")

	return agentRevision, 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)
			})
		})
	})
}
Example #11
0
func TestGetTaskInfo(t *testing.T) {

	userManager, err := auth.LoadUserManager(taskTestConfig.AuthConfig)
	testutil.HandleTestingErr(err, t, "Failure in loading UserManager from config")

	uis := UIServer{
		RootURL:     taskTestConfig.Ui.Url,
		Settings:    *taskTestConfig,
		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 info on a particular task", t, func() {
		testutil.HandleTestingErr(db.Clear(model.TasksCollection), t,
			"Error clearing '%v' collection", model.TasksCollection)

		taskId := "my-task"
		versionId := "my-version"
		projectName := "project_test"

		testResult := model.TestResult{
			Status:    "success",
			TestFile:  "some-test",
			URL:       "some-url",
			StartTime: float64(time.Now().Add(-9 * time.Minute).Unix()),
			EndTime:   float64(time.Now().Add(-1 * time.Minute).Unix()),
		}
		task := &model.Task{
			Id:                  taskId,
			CreateTime:          time.Now().Add(-20 * time.Minute),
			ScheduledTime:       time.Now().Add(-15 * time.Minute),
			DispatchTime:        time.Now().Add(-14 * 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()),
			Priority:            10,
			LastHeartbeat:       time.Now(),
			Activated:           false,
			BuildId:             "some-build-id",
			DistroId:            "some-distro-id",
			BuildVariant:        "some-build-variant",
			DependsOn:           []model.Dependency{{"some-other-task", ""}},
			DisplayName:         "My task",
			HostId:              "some-host-id",
			Restarts:            0,
			Execution:           0,
			Archived:            false,
			RevisionOrderNumber: 42,
			Requester:           evergreen.RepotrackerVersionRequester,
			Status:              "success",
			Details: apimodels.TaskEndDetail{
				TimedOut:    false,
				Description: "some-stage",
			},
			Aborted:          false,
			TimeTaken:        time.Duration(100 * time.Millisecond),
			ExpectedDuration: time.Duration(99 * time.Millisecond),
			TestResults:      []model.TestResult{testResult},
			MinQueuePos:      0,
		}
		So(task.Insert(), ShouldBeNil)

		file := artifact.File{
			Name: "Some Artifact",
			Link: "some-url",
		}
		artifact := artifact.Entry{
			TaskId: taskId,
			Files:  []artifact.File{file},
		}
		So(artifact.Upsert(), ShouldBeNil)

		url, err := router.Get("task_info").URL("task_id", taskId)
		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)
			Println(string(response.Body.Bytes()))

			var rawJsonBody map[string]*json.RawMessage
			err = json.Unmarshal(response.Body.Bytes(), &rawJsonBody)
			So(err, ShouldBeNil)

			So(jsonBody["id"], ShouldEqual, task.Id)

			var createTime time.Time
			err = json.Unmarshal(*rawJsonBody["create_time"], &createTime)
			So(err, ShouldBeNil)
			So(createTime, ShouldHappenWithin, rest.TimePrecision, task.CreateTime)

			var scheduledTime time.Time
			err = json.Unmarshal(*rawJsonBody["scheduled_time"], &scheduledTime)
			So(err, ShouldBeNil)
			So(scheduledTime, ShouldHappenWithin, rest.TimePrecision, task.ScheduledTime)

			var dispatchTime time.Time
			err = json.Unmarshal(*rawJsonBody["dispatch_time"], &dispatchTime)
			So(err, ShouldBeNil)
			So(dispatchTime, ShouldHappenWithin, rest.TimePrecision, task.DispatchTime)

			var startTime time.Time
			err = json.Unmarshal(*rawJsonBody["start_time"], &startTime)
			So(err, ShouldBeNil)
			So(startTime, ShouldHappenWithin, rest.TimePrecision, task.StartTime)

			var finishTime time.Time
			err = json.Unmarshal(*rawJsonBody["finish_time"], &finishTime)
			So(err, ShouldBeNil)
			So(finishTime, ShouldHappenWithin, rest.TimePrecision, task.FinishTime)

			var pushTime time.Time
			err = json.Unmarshal(*rawJsonBody["push_time"], &pushTime)
			So(err, ShouldBeNil)
			So(pushTime, ShouldHappenWithin, rest.TimePrecision, task.PushTime)

			So(jsonBody["version"], ShouldEqual, task.Version)
			So(jsonBody["project"], ShouldEqual, task.Project)
			So(jsonBody["revision"], ShouldEqual, task.Revision)
			So(jsonBody["priority"], ShouldEqual, task.Priority)

			var lastHeartbeat time.Time
			err = json.Unmarshal(*rawJsonBody["last_heartbeat"], &lastHeartbeat)
			So(err, ShouldBeNil)
			So(lastHeartbeat, ShouldHappenWithin, rest.TimePrecision, task.LastHeartbeat)

			So(jsonBody["activated"], ShouldEqual, task.Activated)
			So(jsonBody["build_id"], ShouldEqual, task.BuildId)
			So(jsonBody["distro"], ShouldEqual, task.DistroId)
			So(jsonBody["build_variant"], ShouldEqual, task.BuildVariant)

			var dependsOn []model.Dependency
			So(rawJsonBody["depends_on"], ShouldNotBeNil)
			err = json.Unmarshal(*rawJsonBody["depends_on"], &dependsOn)
			So(err, ShouldBeNil)
			So(dependsOn, ShouldResemble, task.DependsOn)

			So(jsonBody["display_name"], ShouldEqual, task.DisplayName)
			So(jsonBody["host_id"], ShouldEqual, task.HostId)
			So(jsonBody["restarts"], ShouldEqual, task.Restarts)
			So(jsonBody["execution"], ShouldEqual, task.Execution)
			So(jsonBody["archived"], ShouldEqual, task.Archived)
			So(jsonBody["order"], ShouldEqual, task.RevisionOrderNumber)
			So(jsonBody["requester"], ShouldEqual, task.Requester)
			So(jsonBody["status"], ShouldEqual, task.Status)

			_jsonStatusDetails, ok := jsonBody["status_details"]
			So(ok, ShouldBeTrue)
			jsonStatusDetails, ok := _jsonStatusDetails.(map[string]interface{})
			So(ok, ShouldBeTrue)

			So(jsonStatusDetails["timed_out"], ShouldEqual, task.Details.TimedOut)
			So(jsonStatusDetails["timeout_stage"], ShouldEqual, task.Details.Description)

			So(jsonBody["aborted"], ShouldEqual, task.Aborted)
			So(jsonBody["time_taken"], ShouldEqual, task.TimeTaken)
			So(jsonBody["expected_duration"], ShouldEqual, task.ExpectedDuration)

			_jsonTestResults, ok := jsonBody["test_results"]
			So(ok, ShouldBeTrue)
			jsonTestResults, ok := _jsonTestResults.(map[string]interface{})
			So(ok, ShouldBeTrue)
			So(len(jsonTestResults), ShouldEqual, 1)

			_jsonTestResult, ok := jsonTestResults[testResult.TestFile]
			So(ok, ShouldBeTrue)
			jsonTestResult, ok := _jsonTestResult.(map[string]interface{})
			So(ok, ShouldBeTrue)

			So(jsonTestResult["status"], ShouldEqual, testResult.Status)
			So(jsonTestResult["time_taken"], ShouldNotBeNil) // value correctness is unchecked

			_jsonTestResultLogs, ok := jsonTestResult["logs"]
			So(ok, ShouldBeTrue)
			jsonTestResultLogs, ok := _jsonTestResultLogs.(map[string]interface{})
			So(ok, ShouldBeTrue)

			So(jsonTestResultLogs["url"], ShouldEqual, testResult.URL)

			So(jsonBody["min_queue_pos"], ShouldEqual, task.MinQueuePos)

			var jsonFiles []map[string]interface{}
			err = json.Unmarshal(*rawJsonBody["files"], &jsonFiles)
			So(err, ShouldBeNil)
			So(len(jsonFiles), ShouldEqual, 1)

			jsonFile := jsonFiles[0]
			So(jsonFile["name"], ShouldEqual, file.Name)
			So(jsonFile["url"], ShouldEqual, file.Link)
		})
	})

	Convey("When finding info on a nonexistent task", t, func() {
		taskId := "not-present"

		url, err := router.Get("task_info").URL("task_id", taskId)
		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(jsonBody["message"], ShouldEqual,
				fmt.Sprintf("Error finding task '%v'", taskId))
		})
	})
}
Example #12
0
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)
		})
	})
}
Example #13
0
func init() {
	evgHome := evergreen.FindEvergreenHome()
	goxc = filepath.Join(evgHome, "src/github.com/laher/goxc/goxc.go")
}
Example #14
0
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 TestLocalCommands(t *testing.T) {

	Convey("When running local commands", t, func() {

		Convey("the preparation step should replace expansions and forward"+
			" slashes in the command string", func() {

			command := &LocalCommand{
				CmdString: "one ${two} \\three${four|five}",
			}

			expansions := NewExpansions(map[string]string{
				"two": "TWO",
				"six": "SIX",
			})

			// run the preparation stage, and make sure the replacements are
			// correctly made
			So(command.PrepToRun(expansions), ShouldBeNil)
			So(command.CmdString, ShouldEqual, "one TWO /threefive")

		})

		Convey("the specified environment should be used", func() {

			stdout := &CacheLastWritten{}

			command := &LocalCommand{
				CmdString: "echo $local_command_test",
				Stdout:    stdout,
				Stderr:    ioutil.Discard,
			}

			// get the current env
			command.Environment = os.Environ()

			// run the command - the environment variable should be empty
			So(command.Run(), ShouldBeNil)
			So(string(stdout.LastWritten), ShouldEqual, "\n")

			// add the environment variable to the env
			command.Environment = append(command.Environment,
				"local_command_test=hello")

			// run the command again - the environment variable should be set
			// correctly
			So(command.Run(), ShouldBeNil)
			So(string(stdout.LastWritten), ShouldEqual, "hello\n")

		})

		Convey("the specified working directory should be used", func() {

			stdout := &CacheLastWritten{}

			evgHome := evergreen.FindEvergreenHome()
			workingDir := filepath.Join(evgHome, "command/testdata")

			command := &LocalCommand{
				CmdString:        "pwd",
				Stdout:           stdout,
				Stderr:           ioutil.Discard,
				WorkingDirectory: workingDir,
			}

			// run the command - the working directory should be as specified
			So(command.Run(), ShouldBeNil)
			So(string(stdout.LastWritten), ShouldEqual, workingDir+"\n")

		})

	})

}
Example #16
0
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)
		})
	})
}
Example #17
0
func TestGetVersionInfo(t *testing.T) {

	uis := UIServer{
		RootURL:     versionTestConfig.Ui.Url,
		Settings:    *versionTestConfig,
		UserManager: testutil.MockUserManager{},
	}
	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, "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 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 = testutil.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)
		})
	})
}
Example #18
0
func TestLocalCommands(t *testing.T) {
	if runtime.GOOS == "windows" {
		t.Skip("shell command test doesn't make sense on windows")
	}

	Convey("When running local commands", t, func() {

		Convey("the preparation step should replace expansions and forward"+
			" slashes in the command string", func() {

			command := &LocalCommand{
				CmdString: "one ${two} \\three${four|five}",
			}

			expansions := NewExpansions(map[string]string{
				"two": "TWO",
				"six": "SIX",
			})

			// run the preparation stage, and make sure the replacements are
			// correctly made
			So(command.PrepToRun(expansions), ShouldBeNil)
			So(command.CmdString, ShouldEqual, "one TWO \\threefive")

		})

		Convey("the specified environment should be used", func() {

			stdout := &CacheLastWritten{}

			command := &LocalCommand{
				CmdString: "echo $local_command_test",
				Stdout:    stdout,
				Stderr:    ioutil.Discard,
			}

			// get the current env
			command.Environment = os.Environ()

			// run the command - the environment variable should be empty
			So(command.Run(), ShouldBeNil)
			So(string(stdout.LastWritten), ShouldEqual, "\n")

			// add the environment variable to the env
			command.Environment = append(command.Environment,
				"local_command_test=hello")

			// run the command again - the environment variable should be set
			// correctly
			So(command.Run(), ShouldBeNil)
			So(string(stdout.LastWritten), ShouldEqual, "hello\n")

		})

		Convey("the specified working directory should be used", func() {

			stdout := &CacheLastWritten{}

			workingDir, err := filepath.Abs(evergreen.FindEvergreenHome())
			So(err, ShouldBeNil)

			command := &LocalCommand{
				CmdString:        "pwd",
				Stdout:           stdout,
				Stderr:           ioutil.Discard,
				WorkingDirectory: workingDir,
			}
			// run the command - the working directory should be as specified
			So(command.Run(), ShouldBeNil)

			reportedPwd := string(stdout.LastWritten)
			reportedPwd = reportedPwd[:len(reportedPwd)-1]
			reportedPwd, err = filepath.EvalSymlinks(reportedPwd)
			So(err, ShouldBeNil)

			So(reportedPwd, ShouldEqual, workingDir)

		})

		Convey("the specified shell should be used", func() {
			for _, sh := range []string{"bash", "sh", "/bin/bash", "/bin/sh"} {
				stdout := &CacheLastWritten{}
				command := &LocalCommand{
					Shell:     sh,
					CmdString: "echo $0",
					Stdout:    stdout,
					Stderr:    ioutil.Discard,
				}

				So(command.Run(), ShouldBeNil)
				So(string(stdout.LastWritten), ShouldEqual, sh+"\n")
			}
		})

		Convey("if not specified, sh should be used", func() {
			stdout := &CacheLastWritten{}
			command := &LocalCommand{
				CmdString: "echo $0",
				Stdout:    stdout,
				Stderr:    ioutil.Discard,
			}

			So(command.Run(), ShouldBeNil)
			So(string(stdout.LastWritten), ShouldEqual, "sh\n")
		})

		Convey("when specified, local command can also use python", func() {
			stdout := &CacheLastWritten{}
			command := &LocalCommand{
				Shell:     "python",
				CmdString: "print('hello world')",
				Stdout:    stdout,
				Stderr:    ioutil.Discard,
			}

			So(command.Run(), ShouldBeNil)
			So(string(stdout.LastWritten), ShouldEqual, "hello world\n")
		})

	})
}
Example #19
0
func TemplateRoot(name string) string {
	return filepath.Join(evergreen.FindEvergreenHome(), "ui", "plugins", name, "templates")
}
Example #20
0
func TestAgentBasedHostGateway(t *testing.T) {

	var hostGateway *AgentBasedHostGateway

	SkipConvey("When checking if the agent needs to be built", t, func() {

		hostGateway = &AgentBasedHostGateway{}

		Convey("a non-existent executables directory should cause the agent"+
			" to need to be built", func() {

			hostGateway.ExecutablesDir = "/foo/bar/baz/foo/bar"
			needsBuild, err := hostGateway.AgentNeedsBuild()
			So(err, ShouldBeNil)
			So(needsBuild, ShouldBeTrue)

		})

		Convey("an out-of-date last-built version of the agent should cause"+
			" the agent to need to be built", func() {

			hostGateway.ExecutablesDir = "/" // just needs to exist

			// store the "last built hash" as something different than the
			// current one
			So(db.StoreLastAgentBuild("fedcba"), ShouldBeNil)

			needsBuild, err := hostGateway.AgentNeedsBuild()
			So(err, ShouldBeNil)
			So(needsBuild, ShouldBeTrue)

		})

		Convey("an up-to-date last-built version of the agent should cause"+
			" the agent to not need to be built", func() {

			hostGateway.ExecutablesDir = "/" // just needs to exist

			// compute and cache the current hash of the agent package
			agentHash, err := util.CurrentGitHash(hostGateway.AgentPackageDir)
			So(err, ShouldBeNil)

			// store the "last built hash" as the same as the current one
			So(db.StoreLastAgentBuild(agentHash), ShouldBeNil)

			needsBuild, err := hostGateway.AgentNeedsBuild()
			So(err, ShouldBeNil)
			So(needsBuild, ShouldBeFalse)
		})

	})

	SkipConvey("When building the agent", t, func() {

		hostGateway = &AgentBasedHostGateway{}
		So(db.StoreLastAgentBuild("abcdef"), ShouldBeNil)

		Convey("a nil AgentCompiler should cause a panic", func() {
			So(func() { hostGateway.buildAgent() }, ShouldPanic)
		})

		Convey("a failed compilation should error and cause the build to not"+
			" be recorded as successful", func() {

			// attempt to compile
			hostGateway.currentAgentHash = "fedcba"
			hostGateway.Compiler = &FailingAgentCompiler{}
			So(hostGateway.buildAgent(), ShouldNotBeNil)

			// make sure the last built hash was not updated
			lastBuiltHash, err := db.GetLastAgentBuild()
			So(err, ShouldBeNil)
			So(lastBuiltHash, ShouldEqual, "abcdef")
		})

		Convey("a successful compilation should cause the build to be"+
			" recorded as successful", func() {

			// attempt to compile
			hostGateway.currentAgentHash = "fedcba"
			hostGateway.Compiler = &SucceedingAgentCompiler{}
			So(hostGateway.buildAgent(), ShouldBeNil)

			// make sure the last built hash was updated
			lastBuiltHash, err := db.GetLastAgentBuild()
			So(err, ShouldBeNil)
			So(lastBuiltHash, ShouldEqual, "fedcba")
		})
	})

	Convey("When prepping the remote machine", t, func() {

		Convey("the remote shell should be created, and the config directory"+
			" and agent binaries should be copied over to it", func() {

			hostGateway = &AgentBasedHostGateway{
				Compiler: &SucceedingAgentCompiler{},
			}

			// create a mock config directory, mock executables
			// directory, and mock remote shell
			evgHome := evergreen.FindEvergreenHome()
			tmpBase := filepath.Join(evgHome, "taskrunner/testdata/tmp")
			mockConfigDir := filepath.Join(tmpBase, "mock_config_dir")
			hostGatewayTestConf.ConfigDir = mockConfigDir
			mockExecutablesDir := filepath.Join(tmpBase, "mock_executables_dir")
			hostGateway.ExecutablesDir = mockExecutablesDir
			mockExecutable := filepath.Join(mockExecutablesDir, "main")
			mockRemoteShell := filepath.Join(tmpBase, "mock_remote_shell")
			evergreen.RemoteShell = mockRemoteShell

			// prevent permissions issues
			syscall.Umask(0000)

			// remove the directories, if they exist (start clean)
			exists, err := util.FileExists(tmpBase)
			So(err, ShouldBeNil)
			if exists {
				So(os.RemoveAll(tmpBase), ShouldBeNil)
			}
			So(os.MkdirAll(tmpBase, 0777), ShouldBeNil)

			// create the config and executables directories, as well as a
			// mock executable, to copy over
			So(os.Mkdir(mockConfigDir, 0777), ShouldBeNil)
			So(os.Mkdir(mockExecutablesDir, 0777), ShouldBeNil)
			So(ioutil.WriteFile(mockExecutable, []byte("run me"), 0777),
				ShouldBeNil)

			// mock up a host for localhost
			localhost := host.Host{
				Host: command.TestRemote,
				User: command.TestRemoteUser,
			}

			// prep the "remote" host
			_, err = hostGateway.prepRemoteHost(hostGatewayTestConf,
				localhost, []string{"-i", command.TestRemoteKey}, "")
			So(err, ShouldBeNil)

			// make sure the correct files were created and copied over
			exists, err = util.FileExists(filepath.Join(mockRemoteShell,
				"mock_config_dir"))
			So(err, ShouldBeNil)
			So(exists, ShouldBeTrue)
			exists, err = util.FileExists(filepath.Join(mockRemoteShell,
				"main"))
			So(err, ShouldBeNil)
			So(exists, ShouldBeTrue)

		})

	})

}
func TestGetProjectInfo(t *testing.T) {
	uis := UIServer{
		RootURL:     projectTestConfig.Ui.Url,
		Settings:    *projectTestConfig,
		UserManager: testutil.MockUserManager{},
	}
	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, "error setting up router")
	n := negroni.New()
	n.Use(negroni.HandlerFunc(UserMiddleware(uis.UserManager)))
	n.UseHandler(router)

	Convey("When loading a public project, it should be found", t, func() {
		testutil.HandleTestingErr(db.Clear(model.ProjectRefCollection), t,
			"Error clearing '%v' collection", model.ProjectRefCollection)

		publicId := "pub"
		public := &model.ProjectRef{
			Identifier:  publicId,
			Repo:        "repo1",
			LocalConfig: "buildvariants:\n - name: ubuntu",
		}
		So(public.Insert(), ShouldBeNil)

		url, err := router.Get("project_info").URL("project_id", publicId)
		So(err, ShouldBeNil)
		request, err := http.NewRequest("GET", url.String(), nil)
		So(err, ShouldBeNil)

		response := httptest.NewRecorder()

		Convey("by a public user", func() {
			n.ServeHTTP(response, request)
			outRef := &model.ProjectRef{}
			So(response.Code, ShouldEqual, http.StatusOK)
			So(json.Unmarshal(response.Body.Bytes(), outRef), ShouldBeNil)
			So(outRef, ShouldResemble, public)
		})
		Convey("and a logged-in user", func() {
			request.AddCookie(&http.Cookie{Name: evergreen.AuthTokenCookie, Value: "token"})
			n.ServeHTTP(response, request)
			outRef := &model.ProjectRef{}
			So(response.Code, ShouldEqual, http.StatusOK)
			So(json.Unmarshal(response.Body.Bytes(), outRef), ShouldBeNil)
			So(outRef, ShouldResemble, public)
		})
	})

	Convey("When loading a private project", t, func() {
		testutil.HandleTestingErr(db.Clear(model.ProjectRefCollection), t,
			"Error clearing '%v' collection", model.ProjectRefCollection)

		privateId := "priv"
		private := &model.ProjectRef{
			Identifier: privateId,
			Private:    true,
			Repo:       "repo1",
		}
		So(private.Insert(), ShouldBeNil)

		Convey("users who are not logged in should be denied with a 302", func() {
			url, err := router.Get("project_info").URL("project_id", privateId)
			So(err, ShouldBeNil)
			request, err := http.NewRequest("GET", url.String(), nil)
			So(err, ShouldBeNil)
			response := httptest.NewRecorder()
			n.ServeHTTP(response, request)

			So(response.Code, ShouldEqual, http.StatusFound)
		})

		Convey("users who are logged in should be able to access the project", func() {
			url, err := router.Get("project_info").URL("project_id", privateId)
			So(err, ShouldBeNil)
			request, err := http.NewRequest("GET", url.String(), nil)
			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()
			n.ServeHTTP(response, request)

			outRef := &model.ProjectRef{}
			So(response.Code, ShouldEqual, http.StatusOK)
			So(json.Unmarshal(response.Body.Bytes(), outRef), ShouldBeNil)
			So(outRef, ShouldResemble, private)
		})
	})

	Convey("When finding info on a nonexistent project", t, func() {
		url, err := router.Get("project_info").URL("project_id", "nope")
		So(err, ShouldBeNil)

		request, err := http.NewRequest("GET", url.String(), nil)
		So(err, ShouldBeNil)
		response := httptest.NewRecorder()

		Convey("response should contain a sensible error message", func() {
			Convey("for a public user", func() {
				n.ServeHTTP(response, request)
				So(response.Code, ShouldEqual, http.StatusNotFound)
				var jsonBody map[string]interface{}
				err = json.Unmarshal(response.Body.Bytes(), &jsonBody)
				So(err, ShouldBeNil)
				So(len(jsonBody["message"].(string)), ShouldBeGreaterThan, 0)
			})
			Convey("and a logged-in user", func() {
				request.AddCookie(&http.Cookie{Name: evergreen.AuthTokenCookie, Value: "token"})
				n.ServeHTTP(response, request)
				So(response.Code, ShouldEqual, http.StatusNotFound)
				var jsonBody map[string]interface{}
				err = json.Unmarshal(response.Body.Bytes(), &jsonBody)
				So(err, ShouldBeNil)
				So(len(jsonBody["message"].(string)), ShouldBeGreaterThan, 0)
			})
		})
	})
}
Example #22
0
func TestGetTaskStatus(t *testing.T) {

	userManager, err := auth.LoadUserManager(taskTestConfig.AuthConfig)
	testutil.HandleTestingErr(err, t, "Failure in loading UserManager from config")

	uis := UIServer{
		RootURL:     taskTestConfig.Ui.Url,
		Settings:    *taskTestConfig,
		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 task", t, func() {
		testutil.HandleTestingErr(db.Clear(model.TasksCollection), t,
			"Error clearing '%v' collection", model.TasksCollection)

		taskId := "my-task"

		testResult := model.TestResult{
			Status:    "success",
			TestFile:  "some-test",
			URL:       "some-url",
			StartTime: float64(time.Now().Add(-9 * time.Minute).Unix()),
			EndTime:   float64(time.Now().Add(-1 * time.Minute).Unix()),
		}
		task := &model.Task{
			Id:          taskId,
			DisplayName: "My task",
			Status:      "success",
			Details: apimodels.TaskEndDetail{
				TimedOut:    false,
				Description: "some-stage",
			},
			TestResults: []model.TestResult{testResult},
		}
		So(task.Insert(), ShouldBeNil)

		url, err := router.Get("task_status").URL("task_id", taskId)
		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["task_id"], ShouldEqual, task.Id)
			So(jsonBody["task_name"], ShouldEqual, task.DisplayName)
			So(jsonBody["status"], ShouldEqual, task.Status)

			_jsonStatusDetails, ok := jsonBody["status_details"]
			So(ok, ShouldBeTrue)
			jsonStatusDetails, ok := _jsonStatusDetails.(map[string]interface{})
			So(ok, ShouldBeTrue)

			So(jsonStatusDetails["timed_out"], ShouldEqual, task.Details.TimedOut)
			So(jsonStatusDetails["timeout_stage"], ShouldEqual, task.Details.Description)

			_jsonTestResults, ok := jsonBody["tests"]
			So(ok, ShouldBeTrue)
			jsonTestResults, ok := _jsonTestResults.(map[string]interface{})
			So(ok, ShouldBeTrue)
			So(len(jsonTestResults), ShouldEqual, 1)

			_jsonTestResult, ok := jsonTestResults[testResult.TestFile]
			So(ok, ShouldBeTrue)
			jsonTestResult, ok := _jsonTestResult.(map[string]interface{})
			So(ok, ShouldBeTrue)

			So(jsonTestResult["status"], ShouldEqual, testResult.Status)
			So(jsonTestResult["time_taken"], ShouldNotBeNil) // value correctness is unchecked

			_jsonTestResultLogs, ok := jsonTestResult["logs"]
			So(ok, ShouldBeTrue)
			jsonTestResultLogs, ok := _jsonTestResultLogs.(map[string]interface{})
			So(ok, ShouldBeTrue)

			So(jsonTestResultLogs["url"], ShouldEqual, testResult.URL)
		})
	})

	Convey("When finding the status of a nonexistent task", t, func() {
		taskId := "not-present"

		url, err := router.Get("task_status").URL("task_id", taskId)
		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(jsonBody["message"], ShouldEqual,
				fmt.Sprintf("Error finding task '%v'", taskId))
		})
	})
}
func TestAgentBasedHostGateway(t *testing.T) {

	var hostGateway *AgentBasedHostGateway

	Convey("When prepping the remote machine", t, func() {

		Convey("the remote shell should be created, and the config directory"+
			" and agent binaries should be copied over to it", func() {

			hostGateway = &AgentBasedHostGateway{
				Compiler: &SucceedingAgentCompiler{},
			}

			// create a mock config directory, mock executables
			// directory, and mock remote shell
			evgHome := evergreen.FindEvergreenHome()
			tmpBase := filepath.Join(evgHome, "taskrunner/testdata/tmp")
			mockConfigDir := filepath.Join(tmpBase, "mock_config_dir")
			hostGatewayTestConf.ConfigDir = mockConfigDir
			mockExecutablesDir := filepath.Join(tmpBase, "mock_executables_dir")
			hostGateway.ExecutablesDir = mockExecutablesDir
			mockExecutable := filepath.Join(mockExecutablesDir, "main")
			mockRemoteShell := filepath.Join(tmpBase, "mock_remote_shell")
			evergreen.RemoteShell = mockRemoteShell

			// prevent permissions issues
			syscall.Umask(0000)

			// remove the directories, if they exist (start clean)
			exists, err := util.FileExists(tmpBase)
			So(err, ShouldBeNil)
			if exists {
				So(os.RemoveAll(tmpBase), ShouldBeNil)
			}
			So(os.MkdirAll(tmpBase, 0777), ShouldBeNil)

			// create the config and executables directories, as well as a
			// mock executable, to copy over
			So(os.Mkdir(mockConfigDir, 0777), ShouldBeNil)
			So(os.Mkdir(mockExecutablesDir, 0777), ShouldBeNil)
			So(ioutil.WriteFile(mockExecutable, []byte("run me"), 0777),
				ShouldBeNil)

			// mock up a host for localhost
			localhost := host.Host{
				Host: command.TestRemote,
				User: command.TestRemoteUser,
			}

			// prep the "remote" host
			_, err = hostGateway.prepRemoteHost(hostGatewayTestConf,
				localhost, []string{"-i", command.TestRemoteKey}, "")
			So(err, ShouldBeNil)

			// make sure the correct files were created and copied over
			exists, err = util.FileExists(filepath.Join(mockRemoteShell,
				"mock_config_dir"))
			So(err, ShouldBeNil)
			So(exists, ShouldBeTrue)
			exists, err = util.FileExists(filepath.Join(mockRemoteShell,
				"main"))
			So(err, ShouldBeNil)
			So(exists, ShouldBeTrue)

		})

	})

}
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 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))
		})
	})
}
Example #26
0
func TestScpCommand(t *testing.T) {

	Convey("With files to scp", t, func() {

		// the local files and target directory for scping
		evgHome := evergreen.FindEvergreenHome()

		tmpBase := filepath.Join(evgHome, "command/testdata/tmp")
		fileToScp := filepath.Join(tmpBase, "copy_me_please.txt")
		directoryToScp := filepath.Join(tmpBase, "copy_my_children_please")
		nestedFileToScp := filepath.Join(directoryToScp,
			"copy_me_too_please.txt")
		targetDirectory := filepath.Join(tmpBase, "feed_me_files")

		// remove the files and directories, if they exist (start clean)
		exists, err := util.FileExists(tmpBase)
		So(err, ShouldBeNil)
		if exists {
			So(os.RemoveAll(tmpBase), ShouldBeNil)
		}
		So(os.MkdirAll(tmpBase, 0777), ShouldBeNil)

		// prevent permissions issues
		syscall.Umask(0000)

		// create the files / directories to be used
		So(ioutil.WriteFile(fileToScp, []byte("hello"), 0777), ShouldBeNil)
		So(os.Mkdir(directoryToScp, 0777), ShouldBeNil)
		So(ioutil.WriteFile(nestedFileToScp, []byte("hi"), 0777), ShouldBeNil)
		So(os.Mkdir(targetDirectory, 0777), ShouldBeNil)

		Convey("when running scp commands", func() {

			Convey("copying files should work in both directions (local to"+
				" remote and remote to local)", func() {

				// scp the file from local to remote
				scpCommand := &ScpCommand{
					Source:         fileToScp,
					Dest:           targetDirectory,
					Stdout:         ioutil.Discard,
					Stderr:         ioutil.Discard,
					RemoteHostName: TestRemote,
					User:           TestRemoteUser,
					Options:        []string{"-i", TestRemoteKey},
					SourceIsRemote: false,
				}
				So(scpCommand.Run(), ShouldBeNil)

				// make sure the file was scp-ed over
				newFileContents, err := ioutil.ReadFile(
					filepath.Join(targetDirectory, "copy_me_please.txt"))
				So(err, ShouldBeNil)
				So(newFileContents, ShouldResemble, []byte("hello"))

				// remove the file
				So(os.Remove(filepath.Join(targetDirectory,
					"copy_me_please.txt")), ShouldBeNil)

				// scp the file from remote to local
				scpCommand = &ScpCommand{
					Source:         fileToScp,
					Dest:           targetDirectory,
					Stdout:         ioutil.Discard,
					Stderr:         ioutil.Discard,
					RemoteHostName: TestRemote,
					User:           TestRemoteUser,
					Options:        []string{"-i", TestRemoteKey},
					SourceIsRemote: true,
				}
				So(scpCommand.Run(), ShouldBeNil)

				// make sure the file was scp-ed over
				newFileContents, err = ioutil.ReadFile(
					filepath.Join(targetDirectory, "copy_me_please.txt"))
				So(err, ShouldBeNil)
				So(newFileContents, ShouldResemble, []byte("hello"))

			})

			Convey("additional scp options should be passed correctly to the"+
				" command", func() {

				// scp recursively, using the -r flag
				scpCommand := &ScpCommand{
					Source:         directoryToScp,
					Dest:           targetDirectory,
					Stdout:         ioutil.Discard,
					Stderr:         ioutil.Discard,
					RemoteHostName: TestRemote,
					User:           TestRemoteUser,
					Options:        []string{"-i", TestRemoteKey, "-r"},
					SourceIsRemote: false,
				}
				So(scpCommand.Run(), ShouldBeNil)

				// make sure the entire directory was scp-ed over
				nestedFileContents, err := ioutil.ReadFile(
					filepath.Join(targetDirectory, "copy_my_children_please",
						"copy_me_too_please.txt"))
				So(err, ShouldBeNil)
				So(nestedFileContents, ShouldResemble, []byte("hi"))
			})

		})

	})
}
Example #27
0
func TestGoxcAgentCompiler(t *testing.T) {

	var agentCompiler *GoxcAgentCompiler

	SkipConvey("When compiling the agent using goxc", t, func() {

		agentCompiler = &GoxcAgentCompiler{}

		Convey("binaries for the specified os targets and architectures"+
			" should be built in the specified destination directory", func() {

			// create a fake go env for building
			evgHome := evergreen.FindEvergreenHome()
			mockGoPath := filepath.Join(evgHome,
				"src/github.com/evergreen-ci/evergreen/taskrunner/testdata/tmp/mockGoPath/")
			srcDir := filepath.Join(mockGoPath, "src")
			So(os.MkdirAll(srcDir, 0777), ShouldBeNil)
			binDir := filepath.Join(mockGoPath, "bin")
			So(os.MkdirAll(binDir, 0777), ShouldBeNil)
			pkgDir := filepath.Join(mockGoPath, "pkg")
			So(os.MkdirAll(pkgDir, 0777), ShouldBeNil)

			// add it to the GOPATH
			os.Setenv("GOPATH", os.Getenv("GOPATH")+":"+mockGoPath)

			// create a buildable main package inside of the source dir
			mainPackage := filepath.Join(srcDir, "main")
			So(os.MkdirAll(mainPackage, 0777), ShouldBeNil)
			fileContents := "package main\nimport ()\nfunc main(){}"
			So(ioutil.WriteFile(filepath.Join(mainPackage, "build_me.go"),
				[]byte(fileContents), 0777), ShouldBeNil)

			// create the destination directory
			dstDir := filepath.Join(mockGoPath, "executables")

			// compile the source package
			So(agentCompiler.Compile(mainPackage, dstDir), ShouldBeNil)

			// make sure all of the necessary main files were created
			for _, execType := range []string{"darwin_386", "darwin_amd64",
				"linux_386", "linux_amd64", "windows_386", "windows_amd64"} {

				// windows binaries have .exe at the end
				binFile := "main"
				if strings.HasPrefix(execType, "windows") {
					binFile += ".exe"
				}

				// make sure the binary exists
				exists, err := util.FileExists(filepath.Join(dstDir,
					"snapshot", execType, binFile))
				So(err, ShouldBeNil)
				So(exists, ShouldBeTrue)
			}

			// clean up, by removing the fake go path
			So(os.RemoveAll(mockGoPath), ShouldBeNil)

		})

	})
}