blob: 2e4420dfd7c5aad3ccd6e8859ed8e929f6c43071 [file] [log] [blame]
/*
* Copyright (C) 2011 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.testtype;
import com.android.cts.tradefed.build.CtsBuildHelper;
import com.android.ddmlib.testrunner.ITestRunListener;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.testtype.IAbi;
import com.android.tradefed.testtype.IBuildReceiver;
import com.android.tradefed.testtype.IDeviceTest;
import com.android.tradefed.testtype.IRemoteTest;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* Test runner for native gTests.
*
* TODO: This is similar to Tradefed's existing GTest, but it doesn't confirm
* each directory segment exists using ddmlib's file service. This was
* a problem since /data is not visible on a user build, but it is
* executable. It's also a lot more verbose when it comes to errors.
*/
public class GeeTest implements IBuildReceiver, IDeviceTest, IRemoteTest {
private static final String NATIVE_TESTS_DIRECTORY = "/data/local/tmp/cts-native-tests";
private static final String NATIVE_TESTS_DIRECTORY_TMP = "/data/local/tmp";
private static final String ANDROID_PATH_SEPARATOR = "/";
private static final String GTEST_FLAG_FILTER = "--gtest_filter=";
private int mMaxTestTimeMs = 1 * 60 * 1000;
private CtsBuildHelper mCtsBuild;
private ITestDevice mDevice;
private IAbi mAbi;
private String mExeName;
private final String mPackageName;
private String mPositiveFilters = "";
private String mNegativeFilters = "";
public GeeTest(String packageName, String exeName) {
mPackageName = packageName;
mExeName = exeName;
}
public void setPositiveFilters(String positiveFilters) {
mPositiveFilters = positiveFilters;
}
public void setNegativeFilters(String negativeFilters) {
mNegativeFilters = negativeFilters;
}
protected String getGTestFilters() {
// If both filters are empty or null return empty string.
if (mPositiveFilters == null && mNegativeFilters == null) {
return "";
}
if (mPositiveFilters.isEmpty() && mNegativeFilters.isEmpty()) {
return "";
}
// Build filter string.
StringBuilder sb = new StringBuilder();
sb.append(GTEST_FLAG_FILTER);
boolean hasPositiveFilters = false;
if (mPositiveFilters != null && !mPositiveFilters.isEmpty()) {
sb.append(mPositiveFilters);
hasPositiveFilters = true;
}
if (mNegativeFilters != null && ! mNegativeFilters.isEmpty()) {
if (hasPositiveFilters) {
sb.append(":");
}
sb.append("-");
sb.append(mNegativeFilters);
}
return sb.toString();
}
/**
* @param abi The ABI to run the test on
*/
public void setAbi(IAbi abi) {
mAbi = abi;
mExeName += mAbi.getBitness();
}
@Override
public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
if (installTest()) {
runTest(listener);
} else {
CLog.e("Failed to install native tests");
}
}
private boolean installTest() throws DeviceNotAvailableException {
if (!createRemoteDir(NATIVE_TESTS_DIRECTORY)) {
CLog.e("Could not create directory for native tests: " + NATIVE_TESTS_DIRECTORY);
return false;
}
File nativeExe = new File(mCtsBuild.getTestCasesDir(), mExeName);
if (!nativeExe.exists()) {
CLog.e("Native test not found: " + nativeExe);
return false;
}
String devicePath = NATIVE_TESTS_DIRECTORY + ANDROID_PATH_SEPARATOR + mExeName;
if (!mDevice.pushFile(nativeExe, devicePath)) {
CLog.e("Failed to push native test to device");
return false;
}
return true;
}
private boolean createRemoteDir(String remoteFilePath) throws DeviceNotAvailableException {
if (mDevice.doesFileExist(remoteFilePath)) {
return true;
}
if (!(mDevice.doesFileExist(NATIVE_TESTS_DIRECTORY_TMP))) {
CLog.e("Could not find the /data/local/tmp directory");
return false;
}
mDevice.executeShellCommand(String.format("mkdir %s", remoteFilePath));
return mDevice.doesFileExist(remoteFilePath);
}
void runTest(ITestRunListener listener) throws DeviceNotAvailableException {
GeeTestResultParser resultParser = new GeeTestResultParser(mPackageName, listener);
resultParser.setFakePackagePrefix(mPackageName + ".");
String fullPath = NATIVE_TESTS_DIRECTORY + ANDROID_PATH_SEPARATOR + mExeName;
String flags = getGTestFilters();
CLog.v("Running gtest %s %s on %s", fullPath, flags, mDevice.getSerialNumber());
// force file to be executable
CLog.v("%s", mDevice.executeShellCommand(String.format("chmod 755 %s", fullPath)));
try {
mDevice.executeShellCommand(String.format("%s %s", fullPath, flags), resultParser,
mMaxTestTimeMs /* maxTimeToShellOutputResponse */,
0 /* retryAttempts */);
} catch (DeviceNotAvailableException e) {
resultParser.flush();
throw e;
} catch (RuntimeException e) {
resultParser.flush();
throw e;
}
}
@Override
public void setBuild(IBuildInfo buildInfo) {
mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
}
@Override
public void setDevice(ITestDevice device) {
mDevice = device;
}
@Override
public ITestDevice getDevice() {
return mDevice;
}
}