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