/* * Copyright 2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.amazonaws.devicefarm; import com.amazonaws.devicefarm.extension.DeviceFarmExtension; import com.amazonaws.devicefarm.extension.TestPackageProvider; import com.amazonaws.services.devicefarm.AWSDeviceFarmClient; import com.amazonaws.services.devicefarm.model.*; import com.android.builder.testing.api.TestServer; import com.google.common.collect.Lists; import org.gradle.api.logging.Logger; import java.io.File; import java.io.IOException; import java.util.*; /** * Sends a test run request to AWS Device Farm. * The url to check for results will be printed to console. */ public class DeviceFarmServer extends TestServer { private final DeviceFarmExtension extension; private final Logger logger; private final AWSDeviceFarmClient api; private final DeviceFarmUploader uploader; private final DeviceFarmUtils utils; public DeviceFarmServer(final DeviceFarmExtension extension, final Logger logger, final AWSDeviceFarmClient deviceFarmClient) throws IOException { this(extension, logger, deviceFarmClient, new DeviceFarmUploader(deviceFarmClient, logger), new DeviceFarmUtils(deviceFarmClient, extension)); } public DeviceFarmServer(final DeviceFarmExtension extension, final Logger logger, final AWSDeviceFarmClient deviceFarmClient, final DeviceFarmUploader uploader, final DeviceFarmUtils utils) throws IOException { this.extension = extension; this.logger = logger; this.api = deviceFarmClient; this.uploader = uploader; this.utils = utils; } /** * Name of the gradle plugin. * @return devicefarm */ @Override public String getName() { return DeviceFarmPlugin.PLUGIN_NAME; } /** * Upload and test the newly built apk. * @param variantName variant of the latest build. Ex: 'debug' * @param testPackage File object to the newly built APK which contains tests * @param testedApk File object to the newly built application APK */ @Override public void uploadApks(final String variantName, final File testPackage, final File testedApk) { final Project project = utils.findProjectByName(extension.getProjectName()); logger.lifecycle(String.format("Using Project \"%s\", \"%s\"", project.getName(), project.getArn())); final DevicePool devicePool = utils.findDevicePoolByName(project, extension.getDevicePool()); logger.lifecycle(String.format("Using Device Pool \"%s\", \"%s\"", devicePool.getName(), devicePool.getArn())); final String appArn = uploader.upload(testedApk, project, UploadType.ANDROID_APP).getArn(); logger.lifecycle(String.format("Will test app in \"%s\", \"%s\"", testedApk.getName(), appArn)); final Collection<Upload> auxApps = uploadAuxApps(project); final String extraDataArn = uploadExtraDataZip(project); final ScheduleRunTest runTest= new ScheduleRunTest() .withParameters(extension.getTest().getTestParameters()) .withType(extension.getTest().getTestType()) .withFilter(extension.getTest().getFilter()) .withTestPackageArn(uploadTestPackageIfNeeded(project, testPackage)); final ScheduleRunConfiguration configuration = new ScheduleRunConfiguration() .withAuxiliaryApps(getAuxAppArns(auxApps)) .withExtraDataPackageArn(extraDataArn) .withLocale(extension.getDeviceState().getLocale().toString()) .withLocation(extension.getDeviceState().getLocation()) .withBillingMethod(extension.isMetered()?BillingMethod.METERED:BillingMethod.UNMETERED) .withRadios(extension.getDeviceState().getRadios()); final ScheduleRunRequest request = new ScheduleRunRequest() .withAppArn(appArn) .withConfiguration(configuration) .withDevicePoolArn(devicePool.getArn()) .withProjectArn(project.getArn()) .withTest(runTest) .withName(String.format("%s (Gradle)", testedApk.getName())); final ScheduleRunResult response = api.scheduleRun(request); logger.lifecycle(String.format("View the %s run in the AWS Device Farm Console: %s", runTest.getType(), utils.getRunUrlFromArn(response.getRun().getArn()))); } /** * If the tests requires it upload the test package and return the arn. * @param project the Device Farm project * @param testPackage the test package * @return test package arn, or null if test does not require a test package */ private String uploadTestPackageIfNeeded(final Project project, final File testPackage) { String testArtifactsArn = null; if(extension.getTest() instanceof TestPackageProvider) { final TestPackageProvider testPackageProvider = (TestPackageProvider)extension.getTest(); final File testArtifacts = testPackageProvider.resolveTestPackage(testPackage); testArtifactsArn = uploader.upload(testArtifacts, project, testPackageProvider.getTestPackageUploadType()).getArn(); logger.lifecycle(String.format("Will run tests in %s, %s", testArtifacts.getName(), testArtifactsArn)); } return testArtifactsArn; } private Collection<Upload> uploadAuxApps(final Project project) { final Collection<Upload> auxApps = uploader.batchUpload(extension.getDeviceState().getAuxiliaryApps(), project, UploadType.ANDROID_APP); if (auxApps == null || auxApps.size() == 0) { return null; } for (Upload auxApp : auxApps) { logger.lifecycle(String.format("Will install additional app %s, %s", auxApp.getName(), auxApp.getArn())); } return auxApps; } private String uploadExtraDataZip(final Project project) { final File extraDataZip = extension.getDeviceState().getExtraDataZipFile(); String extraDataArn = null; if(extraDataZip != null) { extraDataArn = uploader.upload( extraDataZip, project, UploadType.EXTERNAL_DATA).getArn(); logger.lifecycle(String.format("Will copy data from zip %s, %s", extraDataZip, extraDataArn)); } return extraDataArn; } private List<String> getAuxAppArns(Collection<Upload> auxUploads) { List<String> auxAppArns = Lists.newArrayList(); if (auxUploads == null || auxUploads.size() == 0) { return auxAppArns; } for (Upload auxApp : auxUploads) { auxAppArns.add(auxApp.getArn()); } return auxAppArns; } /** * Verify the Device Farm extension is properly configured. * @return true if configuration is valid, false otherwise. */ @Override public boolean isConfigured() { final boolean configured = extension.isValid(); logger.lifecycle(String.format("AWS Device Farm configuration is %s", configured ? "VALID" : "NOT VALID")); return configured; } }