1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.cts.tradefed.testtype; 18 19 import com.android.compatibility.common.util.AbiUtils; 20 import com.android.cts.tradefed.build.CtsBuildHelper; 21 import com.android.ddmlib.testrunner.ITestRunListener; 22 import com.android.tradefed.build.IBuildInfo; 23 import com.android.tradefed.device.DeviceNotAvailableException; 24 import com.android.tradefed.device.ITestDevice; 25 import com.android.tradefed.log.LogUtil.CLog; 26 import com.android.tradefed.result.ITestInvocationListener; 27 import com.android.tradefed.testtype.IAbi; 28 import com.android.tradefed.testtype.IBuildReceiver; 29 import com.android.tradefed.testtype.IDeviceTest; 30 import com.android.tradefed.testtype.IRemoteTest; 31 32 import java.io.File; 33 import java.util.ArrayList; 34 import java.util.List; 35 36 /** 37 * Test runner for native gTests. 38 * 39 * TODO: This is similar to Tradefed's existing GTest, but it doesn't confirm 40 * each directory segment exists using ddmlib's file service. This was 41 * a problem since /data is not visible on a user build, but it is 42 * executable. It's also a lot more verbose when it comes to errors. 43 */ 44 public class GeeTest implements IBuildReceiver, IDeviceTest, IRemoteTest { 45 46 private static final String NATIVE_TESTS_DIRECTORY = "/data/local/tmp/cts-native-tests"; 47 private static final String NATIVE_TESTS_DIRECTORY_TMP = "/data/local/tmp"; 48 private static final String ANDROID_PATH_SEPARATOR = "/"; 49 private static final String GTEST_FLAG_FILTER = "--gtest_filter="; 50 51 private int mMaxTestTimeMs = 1 * 90 * 1000; 52 53 private CtsBuildHelper mCtsBuild; 54 private ITestDevice mDevice; 55 private IAbi mAbi; 56 private String mExeName; 57 58 private final String mPackageName; 59 60 private String mPositiveFilters = ""; 61 private String mNegativeFilters = ""; 62 GeeTest(String packageName, String exeName)63 public GeeTest(String packageName, String exeName) { 64 mPackageName = packageName; 65 mExeName = exeName; 66 } 67 setPositiveFilters(String positiveFilters)68 public void setPositiveFilters(String positiveFilters) { 69 mPositiveFilters = positiveFilters; 70 } 71 setNegativeFilters(String negativeFilters)72 public void setNegativeFilters(String negativeFilters) { 73 mNegativeFilters = negativeFilters; 74 } 75 getGTestFilters()76 protected String getGTestFilters() { 77 // If both filters are empty or null return empty string. 78 if (mPositiveFilters == null && mNegativeFilters == null) { 79 return ""; 80 } 81 if (mPositiveFilters.isEmpty() && mNegativeFilters.isEmpty()) { 82 return ""; 83 } 84 // Build filter string. 85 StringBuilder sb = new StringBuilder(); 86 sb.append(GTEST_FLAG_FILTER); 87 boolean hasPositiveFilters = false; 88 if (mPositiveFilters != null && !mPositiveFilters.isEmpty()) { 89 sb.append(mPositiveFilters); 90 hasPositiveFilters = true; 91 } 92 if (mNegativeFilters != null && ! mNegativeFilters.isEmpty()) { 93 if (hasPositiveFilters) { 94 sb.append(":"); 95 } 96 sb.append("-"); 97 sb.append(mNegativeFilters); 98 } 99 return sb.toString(); 100 } 101 102 /** 103 * @param abi The ABI to run the test on 104 */ setAbi(IAbi abi)105 public void setAbi(IAbi abi) { 106 mAbi = abi; 107 mExeName += mAbi.getBitness(); 108 } 109 110 @Override run(ITestInvocationListener listener)111 public void run(ITestInvocationListener listener) throws DeviceNotAvailableException { 112 if (installTest()) { 113 runTest(listener); 114 } else { 115 CLog.e("Failed to install native tests"); 116 } 117 } 118 installTest()119 private boolean installTest() throws DeviceNotAvailableException { 120 if (!createRemoteDir(NATIVE_TESTS_DIRECTORY)) { 121 CLog.e("Could not create directory for native tests: " + NATIVE_TESTS_DIRECTORY); 122 return false; 123 } 124 125 File nativeExe = new File(mCtsBuild.getTestCasesDir(), mExeName); 126 if (!nativeExe.exists()) { 127 CLog.e("Native test not found: " + nativeExe); 128 return false; 129 } 130 131 String devicePath = NATIVE_TESTS_DIRECTORY + ANDROID_PATH_SEPARATOR + mExeName; 132 if (!mDevice.pushFile(nativeExe, devicePath)) { 133 CLog.e("Failed to push native test to device"); 134 return false; 135 } 136 return true; 137 } 138 createRemoteDir(String remoteFilePath)139 private boolean createRemoteDir(String remoteFilePath) throws DeviceNotAvailableException { 140 if (mDevice.doesFileExist(remoteFilePath)) { 141 return true; 142 } 143 if (!(mDevice.doesFileExist(NATIVE_TESTS_DIRECTORY_TMP))) { 144 CLog.e("Could not find the /data/local/tmp directory"); 145 return false; 146 } 147 148 mDevice.executeShellCommand(String.format("mkdir %s", remoteFilePath)); 149 return mDevice.doesFileExist(remoteFilePath); 150 } 151 runTest(ITestRunListener listener)152 void runTest(ITestRunListener listener) throws DeviceNotAvailableException { 153 String id = AbiUtils.createId(mAbi.getName(), mPackageName); 154 GeeTestResultParser resultParser = new GeeTestResultParser(id, listener); 155 resultParser.setFakePackagePrefix(mPackageName + "."); 156 157 String fullPath = NATIVE_TESTS_DIRECTORY + ANDROID_PATH_SEPARATOR + mExeName; 158 String flags = getGTestFilters(); 159 CLog.v("Running gtest %s %s on %s", fullPath, flags, mDevice.getSerialNumber()); 160 // force file to be executable 161 CLog.v("%s", mDevice.executeShellCommand(String.format("chmod 755 %s", fullPath))); 162 163 try { 164 mDevice.executeShellCommand(String.format("%s %s", fullPath, flags), resultParser, 165 mMaxTestTimeMs /* maxTimeToShellOutputResponse */, 166 0 /* retryAttempts */); 167 } catch (DeviceNotAvailableException e) { 168 resultParser.flush(); 169 throw e; 170 } catch (RuntimeException e) { 171 resultParser.flush(); 172 throw e; 173 } 174 } 175 176 177 @Override setBuild(IBuildInfo buildInfo)178 public void setBuild(IBuildInfo buildInfo) { 179 mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo); 180 } 181 182 @Override setDevice(ITestDevice device)183 public void setDevice(ITestDevice device) { 184 mDevice = device; 185 } 186 187 @Override getDevice()188 public ITestDevice getDevice() { 189 return mDevice; 190 } 191 } 192