/* 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 }