blob: 039470b19d167e463940c9d5cf9316e60c034dad [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* 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.android.cts.tradefed.targetprep;
import com.android.cts.tradefed.build.CtsBuildHelper;
import com.android.cts.tradefed.testtype.Abi;
import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.build.IFolderBuildInfo;
import com.android.tradefed.config.Option;
import com.android.tradefed.config.OptionClass;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.InputStreamSource;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.result.LogDataType;
import com.android.tradefed.result.TestSummary;
import com.android.tradefed.testtype.IAbi;
import com.android.tradefed.testtype.InstrumentationTest;
import com.android.tradefed.targetprep.BuildError;
import com.android.tradefed.targetprep.ITargetPreparer;
import com.android.tradefed.targetprep.TargetSetupError;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* A {@link ITargetPreparer} that performs precondition checks on the device-side for CTS.
* <p/>
* This class instruments an APK containing tests verifying that the device meets CTS
* preconditions. At present, the APK contains tests to ensure that the device's screen is not
* locked, and that the device's external storage is present and writable. The test lives under
* //cts/tools/tradefed-host/preconditions, and can be modified to perform further checks and tasks
* from the device-side.
*/
@OptionClass(alias="device-precondition-preparer")
public class DevicePreconditionPreparer implements ITargetPreparer {
/* This option also exists in the HostPreconditionPreparer */
@Option(name = "skip-preconditions",
description = "Whether to skip precondition checks and automation")
protected boolean mSkipPreconditions = false;
/* Constants for the InstrumentationTest */
private static final String APK_NAME = "CtsPreconditionsApp.apk";
private static final String PACKAGE_NAME = "com.android.cts.preconditions";
private static final String RUNNER_NAME = "android.support.test.runner.AndroidJUnitRunner";
/* Map used to track test failures */
private ConcurrentHashMap<TestIdentifier, String> testFailures = new ConcurrentHashMap<>();
/**
* {@inheritDoc}
*/
@Override
public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
BuildError, DeviceNotAvailableException {
if (mSkipPreconditions) {
return; // skipping device-side preconditions
}
try {
if (!instrument(device, buildInfo)) {
throw new TargetSetupError("Not all device-side preconditions met");
}
} catch (FileNotFoundException e) {
throw new TargetSetupError(
String.format("Couldn't find %s to instrument", APK_NAME), e);
}
}
/* Instruments the APK on the device, and logs precondition test failures, if any are found.
* Returns true if all tests pass, and otherwise returns false */
private boolean instrument(ITestDevice device, IBuildInfo buildInfo)
throws DeviceNotAvailableException, FileNotFoundException {
ITestInvocationListener listener = new PreconditionPreparerListener();
CtsBuildHelper mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
File apkFile = mCtsBuild.getTestApp(APK_NAME); // get the APK file with the CtsBuildHelper
InstrumentationTest instrTest = new InstrumentationTest();
instrTest.setDevice(device);
instrTest.setInstallFile(apkFile);
instrTest.setPackageName(PACKAGE_NAME);
instrTest.setRunnerName(RUNNER_NAME);
instrTest.run(listener);
boolean success = true;
if (!testFailures.isEmpty()) {
success = false; // at least one precondition has failed
for (TestIdentifier test : testFailures.keySet()) {
String trace = testFailures.get(test);
CLog.e("Precondition test %s failed.\n%s", test.getTestName(), trace);
}
}
return success;
}
/**
* The PreconditionPreparerListener is an implementation of ITestInvocationListener
* that adds entries to the ConcurrentHashMap 'testFailures' of the outer class whenever
* a test fails. The listener also logs information if the test run fails, for debugging
* purposes.
*/
public class PreconditionPreparerListener implements ITestInvocationListener {
/**
* {@inheritDoc}
*/
@Override
public void testFailed(TestIdentifier test, String trace) {
testFailures.put(test, trace);
}
/**
* {@inheritDoc}
*/
@Override
public void testRunFailed(String errorMessage) {
CLog.e("Device-side preconditions test run failed: %s", errorMessage);
}
/**
* {@inheritDoc}
*/
@Override
public void testEnded(TestIdentifier test, Map<String, String> metrics) {}
/**
* {@inheritDoc}
*/
@Override
public void invocationStarted(IBuildInfo buildInfo) {}
/**
* {@inheritDoc}
*/
@Override
public void testLog(String dataName, LogDataType dataType, InputStreamSource dataStream) {}
/**
* {@inheritDoc}
*/
@Override
public void invocationEnded(long elapsedTime) {}
/**
* {@inheritDoc}
*/
@Override
public void invocationFailed(Throwable cause) {}
/**
* {@inheritDoc}
*/
@Override
public TestSummary getSummary() {
return null;
}
/**
* {@inheritDoc}
*/
@Override
public void testRunStarted(String runName, int testCount) {}
/**
* {@inheritDoc}
*/
@Override
public void testStarted(TestIdentifier test) {}
/**
* {@inheritDoc}
*/
@Override
public void testAssumptionFailure(TestIdentifier test, String trace) {}
/**
* {@inheritDoc}
*/
@Override
public void testIgnored(TestIdentifier test) {}
/**
* {@inheritDoc}
*/
@Override
public void testRunStopped(long elapsedTime) {}
/**
* {@inheritDoc}
*/
@Override
public void testRunEnded(long elapsedTime, Map<String, String> runMetrics) {}
}
}