/* Schedule Run */
func scheduleRun(svc *devicefarm.DeviceFarm, runName string, projectArn string, appUploadArn string, devicePoolArn string, testUploadArn string, testType string) {

	runTest := &devicefarm.ScheduleRunTest{
		Type: aws.String(testType),
		//Parameters: // test parameters
		//Filter: // filter to pass to tests
	}

	if testUploadArn != "" {
		runTest.TestPackageARN = aws.String(testUploadArn)
	}

	runReq := &devicefarm.ScheduleRunInput{
		AppARN:        aws.String(appUploadArn),
		DevicePoolARN: aws.String(devicePoolArn),
		Name:          aws.String(runName),
		ProjectARN:    aws.String(projectArn),
		Test:          runTest,
	}

	resp, err := svc.ScheduleRun(runReq)

	failOnErr(err, "error scheduling run")
	fmt.Println(awsutil.Prettify(resp))
}
func createPoolFromDevice(svc *devicefarm.DeviceFarm, poolName string, deviceName string, projectArn string) (poolArn string, poolErr error) {

	deviceArn, err := lookupDeviceArn(svc, deviceName)
	failOnErr(err, "error looking up device")

	fmt.Printf("creating %s", deviceArn)
	req := &devicefarm.CreateDevicePoolInput{
		Name:        aws.String(poolName),
		Description: aws.String("autocreated pool " + poolName),
		ProjectArn:  aws.String(projectArn),
		Rules: []*devicefarm.Rule{
			&devicefarm.Rule{
				Attribute: aws.String("Arn"),
				Operator:  aws.String("IN"),
				// Value: "[\"arn:aws:devicefarm:us-west-2::device:6A553F3B3D384DB1A780C590FCC7F85D\"]"
				Value: aws.String("[\"" + deviceArn + "\"]"),
			},
		},
	}

	resp, err := svc.CreateDevicePool(req)

	if err != nil {
		return "", err
	}

	return *resp.DevicePool.Arn, nil
	//fmt.Println(awsutil.Prettify(resp))
}
/* Download Artifacts */
func downloadArtifacts(svc *devicefarm.DeviceFarm, filterArn string, artifactType string) {

	debug := false
	if debug {
		fmt.Println(filterArn)
	}

	listReq := &devicefarm.ListArtifactsInput{
		Arn: aws.String(filterArn),
	}

	types := []string{"LOG", "SCREENSHOT", "FILE"}

	for _, each := range types {
		listReq.Type = aws.String(each)

		resp, err := svc.ListArtifacts(listReq)
		failOnErr(err, "error listing artifacts")

		for index, artifact := range resp.Artifacts {
			fileName := fmt.Sprintf("- report/%d-%s.%s", index, *artifact.Name, *artifact.Extension)
			downloadArtifact(fileName, artifact)
		}
	}

}
/* List all Projects */
func listProjects(svc *devicefarm.DeviceFarm) {

	resp, err := svc.ListProjects(nil)
	failOnErr(err, "error listing projects")

	fmt.Println(awsutil.Prettify(resp))
}
/* List all Devices */
func listDevices(svc *devicefarm.DeviceFarm) {

	input := &devicefarm.ListDevicesInput{}
	resp, err := svc.ListDevices(input)

	failOnErr(err, "error listing devices")
	fmt.Println(awsutil.Prettify(resp))
}
// GetStatusOfRun returns status and result of run specified by ARN
func GetStatusOfRun(client *devicefarm.DeviceFarm, arn string) (string, string) {
	params := &devicefarm.GetRunInput{
		Arn: aws.String(arn),
	}
	resp, err := client.GetRun(params)
	errors.Validate(err, "Can't get status of run")
	return *resp.Run.Status, *resp.Run.Result
}
// GetUploadStatus returns status of upload file
func GetUploadStatus(client *devicefarm.DeviceFarm, arn string) string {
	params := &devicefarm.GetUploadInput{
		Arn: aws.String(arn),
	}
	resp, err := client.GetUpload(params)
	errors.Validate(err, "Failed to get status of upload")
	log.Println("Status of upload:", *resp.Upload.Status)
	return *resp.Upload.Status
}
/* Get Job Info */
func jobInfo(svc *devicefarm.DeviceFarm, jobArn string) {

	infoReq := &devicefarm.GetJobInput{
		ARN: aws.String(jobArn),
	}

	resp, err := svc.GetJob(infoReq)

	failOnErr(err, "error getting job info")
	fmt.Println(awsutil.Prettify(resp))
}
/* List Jobs */
func listJobs(svc *devicefarm.DeviceFarm, runArn string) {

	listReq := &devicefarm.ListJobsInput{
		ARN: aws.String(runArn),
	}

	resp, err := svc.ListJobs(listReq)

	failOnErr(err, "error listing jobs")
	fmt.Println(awsutil.Prettify(resp))
}
/* List suites */
func listSuites(svc *devicefarm.DeviceFarm, filterArn string) {

	listReq := &devicefarm.ListSuitesInput{
		ARN: aws.String(filterArn),
	}

	resp, err := svc.ListSuites(listReq)

	failOnErr(err, "error listing suites")
	fmt.Println(awsutil.Prettify(resp))
}
/* Get Run Status */
func runStatus(svc *devicefarm.DeviceFarm, runArn string) {

	infoReq := &devicefarm.GetRunInput{
		Arn: aws.String(runArn),
	}

	resp, err := svc.GetRun(infoReq)

	failOnErr(err, "error getting run info")
	fmt.Println(*resp.Run.Status)
}
/* List all uploads */
func listUploads(svc *devicefarm.DeviceFarm, projectArn string) {

	listReq := &devicefarm.ListUploadsInput{
		Arn: aws.String(projectArn),
	}

	resp, err := svc.ListUploads(listReq)

	failOnErr(err, "error listing uploads")
	fmt.Println(awsutil.Prettify(resp))
}
/* Get Suite Info */
func suiteInfo(svc *devicefarm.DeviceFarm, suiteArn string) {

	infoReq := &devicefarm.GetJobInput{
		Arn: aws.String(suiteArn),
	}

	resp, err := svc.GetJob(infoReq)

	failOnErr(err, "error getting suite info")
	fmt.Println(awsutil.Prettify(resp))
}
/* Get Upload Info */
func uploadInfo(svc *devicefarm.DeviceFarm, uploadArn string) {

	uploadReq := &devicefarm.GetUploadInput{
		Arn: aws.String(uploadArn),
	}

	resp, err := svc.GetUpload(uploadReq)

	failOnErr(err, "error getting upload info")
	fmt.Println(awsutil.Prettify(resp))
}
/* List all unique problems */
func listUniqueProblems(svc *devicefarm.DeviceFarm, runArn string) {

	listReq := &devicefarm.ListUniqueProblemsInput{
		Arn: aws.String(runArn),
	}

	resp, err := svc.ListUniqueProblems(listReq)

	failOnErr(err, "error listing problems")
	fmt.Println(awsutil.Prettify(resp))
}
/* Get Run Info */
func runInfo(svc *devicefarm.DeviceFarm, runArn string) {

	infoReq := &devicefarm.GetRunInput{
		Arn: aws.String(runArn),
	}

	resp, err := svc.GetRun(infoReq)

	failOnErr(err, "error getting run info")
	fmt.Println(awsutil.Prettify(resp))
}
/* List all DevicePools */
func listDevicePools(svc *devicefarm.DeviceFarm, projectArn string) {
	// CURATED: A device pool that is created and managed by AWS Device Farm.
	// PRIVATE: A device pool that is created and managed by the device pool developer.

	pool := &devicefarm.ListDevicePoolsInput{
		Arn: aws.String(projectArn),
	}
	resp, err := svc.ListDevicePools(pool)

	failOnErr(err, "error listing device pools")
	fmt.Println(awsutil.Prettify(resp))
}
func internalCreateUpload(client *devicefarm.DeviceFarm, arn, appPath, appType string) (string, string) {
	params := &devicefarm.CreateUploadInput{
		Name:        aws.String(tools.GetFileName(appPath)),
		ProjectArn:  aws.String(arn),
		Type:        aws.String(appType),
		ContentType: aws.String("application/octet-stream"),
	}
	resp, err := client.CreateUpload(params)
	errors.Validate(err, "Failed to upload an app")
	log.Println("Upload ARN:", *resp.Upload.Arn)
	log.Println("Upload URL:", *resp.Upload.Url)
	return *resp.Upload.Arn, *resp.Upload.Url
}
/* Create an upload */
func uploadCreate(svc *devicefarm.DeviceFarm, uploadName string, uploadType string, projectArn string) {

	uploadReq := &devicefarm.CreateUploadInput{
		Name:       aws.String(uploadName),
		ProjectArn: aws.String(projectArn),
		Type:       aws.String(uploadType),
	}

	resp, err := svc.CreateUpload(uploadReq)

	failOnErr(err, "error creating upload")
	fmt.Println(awsutil.Prettify(resp))
}
// GetProjectArn returns project ARN by project name
func GetProjectArn(client *devicefarm.DeviceFarm, project string) string {
	var arn string
	params := &devicefarm.ListProjectsInput{}
	resp, err := client.ListProjects(params)
	errors.Validate(err, "Failed to get list of projects for account")
	for _, entry := range resp.Projects {
		if *entry.Name == project {
			arn = *entry.Arn
		}
	}
	log.Println("Project ARN:", arn)
	return arn
}
// GetDevicePoolArn returns device pool ARN by device pool name
func GetDevicePoolArn(client *devicefarm.DeviceFarm, projectArn, devicePool string) string {
	var arn string
	params := &devicefarm.ListDevicePoolsInput{
		Arn: aws.String(projectArn),
	}
	resp, err := client.ListDevicePools(params)
	errors.Validate(err, "Failed to get list of device pools")
	for _, pool := range resp.DevicePools {
		if *pool.Name == devicePool {
			arn = *pool.Arn
		}
	}
	log.Println("Device pool ARN:", arn)
	return arn
}
/* List all Projects */
func listProjects(svc *devicefarm.DeviceFarm) {

	resp, err := svc.ListProjects(nil)
	failOnErr(err, "error listing projects")

	//fmt.Println(awsutil.Prettify(resp))
	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"Name", "Created", "Arn"})
	table.SetAlignment(tablewriter.ALIGN_LEFT)
	table.SetColWidth(50)

	for _, m := range resp.Projects {
		line := []string{*m.Name, time.Time.String(*m.Created), *m.Arn}
		table.Append(line)
	}
	table.Render() // Send output
}
/* List all Devices */
func listDevices(svc *devicefarm.DeviceFarm) {

	input := &devicefarm.ListDevicesInput{}
	resp, err := svc.ListDevices(input)

	failOnErr(err, "error listing devices")
	//fmt.Println(awsutil.Prettify(resp))

	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"Name", "Os", "Platform", "Form", "Arn"})
	table.SetAlignment(tablewriter.ALIGN_LEFT)
	table.SetColWidth(50)

	for _, m := range resp.Devices {
		line := []string{*m.Name, *m.Os, *m.Platform, *m.FormFactor, *m.Arn}
		table.Append(line)
	}
	table.Render() // Send output

	/*
	   	    {
	         Arn: "arn:aws:devicefarm:us-west-2::device:A0E6E6E1059E45918208DF75B2B7EF6C",
	         CPU: {
	           Architecture: "ARMv7",
	           Clock: 2265,
	           Frequency: "MHz"
	         },
	         FormFactor: "PHONE",
	         HeapSize: 0,
	         Image: "NA",
	         Manufacturer: "LG",
	         Memory: 17179869184,
	         Model: "G2",
	         Name: "LG G2 (Sprint)",
	         Os: "4.2.2",
	         Platform: "ANDROID",
	         Resolution: {
	           Height: 1920,
	           Width: 1080
	         }
	       }
	*/

}
func listArtifacts(svc *devicefarm.DeviceFarm, filterArn string, artifactType string) {

	fmt.Println(filterArn)

	listReq := &devicefarm.ListArtifactsInput{
		Arn: aws.String(filterArn),
	}

	listReq.Type = aws.String("LOG")
	resp, err := svc.ListArtifacts(listReq)
	failOnErr(err, "error listing artifacts")
	fmt.Println(awsutil.Prettify(resp))

	listReq.Type = aws.String("SCREENSHOT")
	resp, err = svc.ListArtifacts(listReq)
	failOnErr(err, "error listing artifacts")

	fmt.Println(awsutil.Prettify(resp))

	listReq.Type = aws.String("FILE")
	resp, err = svc.ListArtifacts(listReq)
	failOnErr(err, "error listing artifacts")

	fmt.Println(awsutil.Prettify(resp))
}
/* List suites */
func listSuites(svc *devicefarm.DeviceFarm, filterArn string) {

	listReq := &devicefarm.ListSuitesInput{
		Arn: aws.String(filterArn),
	}

	resp, err := svc.ListSuites(listReq)

	failOnErr(err, "error listing suites")
	//fmt.Println(awsutil.Prettify(resp))

	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"Name", "Status", "Result", "Message"})
	table.SetAlignment(tablewriter.ALIGN_LEFT)
	table.SetColWidth(120)

	for _, m := range resp.Suites {
		line := []string{*m.Name, *m.Status, *m.Result, *m.Message}
		table.Append(line)
	}
	table.Render() // Send output

}
/* List all runs */
func listRuns(svc *devicefarm.DeviceFarm, projectArn string) {

	listReq := &devicefarm.ListRunsInput{
		Arn: aws.String(projectArn),
	}

	resp, err := svc.ListRuns(listReq)

	failOnErr(err, "error listing runs")
	//fmt.Println(awsutil.Prettify(resp))

	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"Name", "Platform", "Type", "Result", "Status", "Date", "Arn"})
	table.SetAlignment(tablewriter.ALIGN_LEFT)
	table.SetColWidth(50)

	for _, m := range resp.Runs {
		line := []string{*m.Name, *m.Platform, *m.Type, *m.Result, *m.Status, time.Time.String(*m.Created), *m.Arn}
		table.Append(line)
	}
	table.Render() // Send output

}
// --- internal API starts here
func lookupDeviceArn(svc *devicefarm.DeviceFarm, deviceName string) (deviceArn string, err error) {

	input := &devicefarm.ListDevicesInput{}
	resp, err := svc.ListDevices(input)

	failOnErr(err, "error listing devices")
	//fmt.Println(awsutil.Prettify(resp))

	devices := make(map[string]string)
	for _, m := range resp.Devices {
		key := fmt.Sprintf("%s - %s", *m.Name, *m.Os)
		devices[key] = *m.Arn
		//line := []string{*m.Name, *m.Os, *m.Platform, *m.FormFactor, *m.Arn}
	}

	arn := devices[deviceName]

	if arn != "" {
		return arn, nil
	}

	return "", errors.New("failed to find a device with name " + deviceName)

}
/* Schedule Run */
func scheduleRun(svc *devicefarm.DeviceFarm, projectArn string, runName string, deviceArn string, devicePoolArn string, appArn string, appFile string, appType string, testPackageArn string, testPackageFile string, testType string) (scheduleError error) {

	debug := true
	// Upload the app file if there is one
	if appFile != "" {

		// Try to guess the upload type based on the filename
		if appType == "" {
			guessedType, err := guessAppType(appFile)
			appType = guessedType

			if err != nil {
				return err
			}
		}

		// Upload appFile with correct AppType
		fmt.Printf("- Uploading app-file %s of type %s ", appFile, appType)

		uploadApp, err := uploadPut(svc, appFile, appType, projectArn, "")
		if err != nil {
			fmt.Printf("Error: %s", err)
			return err
		}

		fmt.Printf("\n")
		appArn = *uploadApp.Arn
	}

	if devicePoolArn == "" {
		if deviceArn != "" {
			// Try to create pool from device Arn
			fmt.Printf("- Creating device pool %s ", deviceArn)
			foundArn, err := createPoolFromDevice(svc, deviceArn, deviceArn, projectArn)

			if err != nil {
				fmt.Printf("Error: %s", err)
				return err
			}
			devicePoolArn = foundArn
		} else {
			return errors.New("we need a device/devicepool to run on")
		}
	}

	// Try to guess the upload type based on the filename
	/*
		if testType == "" {
			testType, err := guessTestType(testPackageFile)
		}
	*/

	fmt.Printf("- Lookup test type %s \n", testType)
	testPackageType, err := lookupTestPackageType(testType)
	if err != nil {
		fmt.Printf("Error: %s", err)
		return err
	}

	// Upload the testPackage file if there is one
	if testPackageFile != "" {

		fmt.Printf("- Uploading test-file %s of type %s ", testPackageFile, testPackageType)

		uploadTestPackage, err := uploadPut(svc, testPackageFile, testPackageType, projectArn, "")

		if err != nil {
			return err
		}
		testPackageArn = *uploadTestPackage.Arn
		fmt.Printf("\n")
	}

	fmt.Printf("- Creating schedule run\n")
	param := make(map[string]*string)
	seed := "1234"
	throttle := "50"
	event_count := "1500"
	param["seed"] = &seed
	param["throttle"] = &throttle
	param["event_count"] = &event_count

	runTest := &devicefarm.ScheduleRunTest{
		Type: aws.String(testType),
		//TestPackageArn: aws.String(testPackageArn),
		Parameters: param, // test parameters
		//Filter: // filter to pass to tests
	}

	if debug {
		fmt.Println(appArn)
		fmt.Println(devicePoolArn)
		fmt.Println(runName)
		fmt.Println(testPackageArn)
		fmt.Println(testPackageType)
		fmt.Println(projectArn)
	}

	locale := "ja_JP"
	metered := devicefarm.BillingMethodMetered
	latitude := 35.676833
	longitude := 139.770139

	bool_true := true

	configuration := &devicefarm.ScheduleRunConfiguration{
		AuxiliaryApps: []*string{},
		BillingMethod: &metered,
		Locale:        &locale,
		Location: &devicefarm.Location{
			Latitude:  &latitude,
			Longitude: &longitude,
		},
		Radios: &devicefarm.Radios{
			Bluetooth: &bool_true,
			Gps:       &bool_true,
			Nfc:       &bool_true,
			Wifi:      &bool_true,
		},
	}

	runReq := &devicefarm.ScheduleRunInput{
		AppArn:        aws.String(appArn),
		Configuration: configuration,
		DevicePoolArn: aws.String(devicePoolArn),
		Name:          aws.String(runName),
		ProjectArn:    aws.String(projectArn),
		Test:          runTest,
	}

	if debug {
		fmt.Println(awsutil.Prettify(runReq))
	}

	fmt.Println("- Initiating test run")

	resp, err := svc.ScheduleRun(runReq)
	if err != nil {
		return err
	}

	//fmt.Println(awsutil.Prettify(resp))

	// Now we wait for the run status to go COMPLETED
	fmt.Print("- Waiting until the tests complete ")

	runArn := *resp.Run.Arn

	status := ""
	for status != "COMPLETED" {
		time.Sleep(4 * time.Second)
		infoReq := &devicefarm.GetRunInput{
			Arn: aws.String(runArn),
		}

		fmt.Print(".")
		resp, err := svc.GetRun(infoReq)

		if err != nil {
			return err
		}
		status = *resp.Run.Status
	}

	// Generate report
	fmt.Println("\n- Generating report ")
	runReport(svc, runArn)

	return nil

}
/* Get Run Report */
func runReport(svc *devicefarm.DeviceFarm, runArn string) {

	infoReq := &devicefarm.GetRunInput{
		Arn: aws.String(runArn),
	}

	resp, err := svc.GetRun(infoReq)

	failOnErr(err, "error getting run info")

	fmt.Printf("Reporting on run %s\n", *resp.Run.Name)
	fmt.Printf("Run arn %s\n", runArn)
	//fmt.Println(awsutil.Prettify(resp))

	jobReq := &devicefarm.ListJobsInput{
		Arn: aws.String(runArn),
	}

	// Find all artifacts
	artifactReq := &devicefarm.ListArtifactsInput{
		Arn: aws.String(runArn),
	}

	types := []string{"LOG", "SCREENSHOT", "FILE"}
	artifacts := map[string][]devicefarm.ListArtifactsOutput{}

	for _, artifactType := range types {

		artifactReq.Type = aws.String(artifactType)

		artifactResp, err := svc.ListArtifacts(artifactReq)
		failOnErr(err, "error getting run info")

		// Store type artifacts
		artifacts[artifactType] = append(artifacts[artifactType], *artifactResp)

	}

	respJob, err := svc.ListJobs(jobReq)
	failOnErr(err, "error getting jobs")

	// Find all jobs within this run
	for _, job := range respJob.Jobs {

		fmt.Println("==========================================")
		time.Sleep(2 * time.Second)

		jobFriendlyName := fmt.Sprintf("%s - %s - %s", *job.Name, *job.Device.Model, *job.Device.Os)

		fmt.Println(awsutil.Prettify(job))

		suiteReq := &devicefarm.ListSuitesInput{
			Arn: aws.String(*job.Arn),
		}
		suiteResp, err := svc.ListSuites(suiteReq)
		failOnErr(err, "error getting run info")

		for _, suite := range suiteResp.Suites {
			message := ""
			if suite.Message != nil {
				message = *suite.Message
			}

			debug := true
			if debug {
				fmt.Printf("%s -> %s : %s \n----> %s\n", jobFriendlyName, *suite.Name, message, *suite.Arn)
			}
			dirPrefix := fmt.Sprintf("report/%s/%s", jobFriendlyName, *suite.Name)
			downloadArtifactsForSuite(dirPrefix, artifacts, *suite)
		}

		fmt.Println(awsutil.Prettify(suiteResp))
	}

	params := &devicefarm.ListUniqueProblemsInput{
		Arn: aws.String(runArn), // Required
	}

	problems, err := svc.ListUniqueProblems(params)

	if err != nil {
		// Print the error, cast err to awserr.Error to get the Code and
		// Message from an error.
		fmt.Println(err.Error())
		return
	}

	// Pretty-print the response data.
	fmt.Println(awsutil.Prettify(problems))
	problemsJson, _ := jsonutil.BuildJSON(problems)
	writeFile(problemsJson, "./report/unique_problems.json")
}
/* Upload a file */
func uploadPut(svc *devicefarm.DeviceFarm, uploadFilePath string, uploadType string, projectArn string, uploadName string) (upload *devicefarm.Upload, err error) {

	debug := true

	// Read File
	file, err := os.Open(uploadFilePath)

	if err != nil {
		return nil, err
		fmt.Println(err)
	}

	defer file.Close()

	// Get file size
	fileInfo, _ := file.Stat()
	var fileSize int64 = fileInfo.Size()

	// read file content to buffer
	buffer := make([]byte, fileSize)
	file.Read(buffer)
	fileBytes := bytes.NewReader(buffer) // convert to io.ReadSeeker type

	// Prepare upload
	if uploadName == "" {
		uploadName = path.Base(uploadFilePath)
	}

	uploadReq := &devicefarm.CreateUploadInput{
		Name:        aws.String(uploadName),
		ProjectArn:  aws.String(projectArn),
		Type:        aws.String(uploadType),
		ContentType: aws.String("application/octet-stream"),
	}

	uploadResp, err := svc.CreateUpload(uploadReq)

	if err != nil {
		log.Fatal(err)
		return nil, err
	}

	uploadInfo := uploadResp.Upload

	upload_url := *uploadInfo.Url

	if debug {
		fmt.Println("- Upload Response result:")
		fmt.Println(awsutil.Prettify(uploadResp))
		fmt.Println(upload_url)
	}

	req, err := http.NewRequest("PUT", upload_url, fileBytes)

	if err != nil {
		log.Fatal(err)
		return nil, err
	}

	// Remove Host and split to get [0] = path & [1] = querystring
	strippedUrl := strings.Split(strings.Replace(upload_url, "https://prod-us-west-2-uploads.s3-us-west-2.amazonaws.com/", "/", -1), "?")
	req.URL.Opaque = strippedUrl[0]
	req.URL.RawQuery = strippedUrl[1]

	req.Header.Set("Content-Type", "application/octet-stream")
	req.Header.Add("Content-Length", strconv.FormatInt(fileSize, 10))

	// Debug Request to AWS
	if debug {
		fmt.Println("- HTTP Upload Request")
		debugHTTP(httputil.DumpRequestOut(req, false))
	}

	client := &http.Client{}

	res, err := client.Do(req)

	if debug {
		fmt.Println("- HTTP Upload Response")
		dump, _ := httputil.DumpResponse(res, true)
		log.Printf("} -> %s\n", dump)
	}

	if err != nil {
		log.Fatal(err)
		return nil, err
	}

	defer res.Body.Close()

	status := ""
	for status != "SUCCEEDED" {
		fmt.Print(".")
		time.Sleep(4 * time.Second)
		uploadReq := &devicefarm.GetUploadInput{
			Arn: uploadInfo.Arn,
		}

		resp, err := svc.GetUpload(uploadReq)

		if err != nil {
			return nil, err
		}

		status = *resp.Upload.Status
	}

	fmt.Println("uploadPut is succeeded")
	return uploadResp.Upload, nil
}