1 /* 2 * Copyright (C) 2016 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.TestIdentifier; 21 import com.android.tradefed.build.IBuildInfo; 22 import com.android.tradefed.config.Option; 23 import com.android.tradefed.config.Option.Importance; 24 import com.android.tradefed.device.DeviceNotAvailableException; 25 import com.android.tradefed.device.ITestDevice; 26 import com.android.tradefed.log.LogUtil.CLog; 27 import com.android.tradefed.result.ITestInvocationListener; 28 import com.android.tradefed.testtype.IAbi; 29 import com.android.tradefed.testtype.IBuildReceiver; 30 import com.android.tradefed.testtype.IDeviceTest; 31 import com.android.tradefed.testtype.IRemoteTest; 32 import com.android.tradefed.util.AbiFormatter; 33 import com.android.tradefed.util.ArrayUtil; 34 35 import java.io.File; 36 import java.io.FileNotFoundException; 37 import java.util.ArrayList; 38 import java.util.Arrays; 39 import java.util.Collection; 40 import java.util.Collections; 41 import java.util.HashSet; 42 import java.util.List; 43 import java.util.Set; 44 import java.util.concurrent.TimeUnit; 45 46 /** 47 * {@code Test} for running CTS TestNG tests on the device. 48 */ 49 public class TestNGDeviceTest implements IDeviceTest, IRemoteTest, IBuildReceiver { 50 51 private static final String TMP_DIR = "/data/local/tmp/"; 52 53 @Option(name = "testng-device-runtime", 54 description = "The name of the runtime to use on the device", 55 importance = Importance.ALWAYS) 56 private String mRuntimePath = "dalvikvm|#ABI#|"; 57 58 @Option(name = "testng-device-tmpdir", description = "Device path where to store the test jars." 59 , importance = Importance.IF_UNSET) 60 private String mDeviceTestTmpPath = TMP_DIR; 61 62 63 // default to no timeout 64 private long mMaxTimeToOutputResponse = 0; 65 66 private ITestDevice mDevice; 67 private String mRunName; 68 private Collection<TestIdentifier> mTests; 69 private CtsBuildHelper mCtsBuild = null; 70 71 private List<String> mJarPaths = new ArrayList<String>(); 72 73 private String mRuntimeArgs; 74 75 private IAbi mAbi; 76 77 private static final String TESTNG_JAR = "cts-testng.jar"; 78 79 private Set<String> mTestJars = new HashSet<String>(Arrays.asList(TESTNG_JAR)); 80 81 /** 82 * @param abi The ABI to run the test on 83 */ setAbi(IAbi abi)84 public void setAbi(IAbi abi) { 85 mAbi = abi; 86 } 87 88 @Override getDevice()89 public ITestDevice getDevice() { 90 return mDevice; 91 } 92 93 @Override setDevice(ITestDevice device)94 public void setDevice(ITestDevice device) { 95 mDevice = device; 96 } 97 addTestJarFileName(String jarFileName)98 public void addTestJarFileName(String jarFileName) { 99 mTestJars.add(jarFileName); 100 } 101 setRunName(String runName)102 public void setRunName(String runName) { 103 mRunName = runName; 104 } 105 setTests(Collection<TestIdentifier> tests)106 public void setTests(Collection<TestIdentifier> tests) { 107 mTests = tests; 108 } 109 getTests()110 public Collection<TestIdentifier> getTests() { 111 return mTests; 112 } 113 114 @Override run(ITestInvocationListener listener)115 public void run(ITestInvocationListener listener) throws DeviceNotAvailableException { 116 addTestJarFileName(TESTNG_JAR); 117 checkFields(); 118 long startTime = System.currentTimeMillis(); 119 listener.testRunStarted(mRunName, mTests.size()); 120 try { 121 installJars(); 122 String jarPath = ArrayUtil.join(":", mJarPaths); 123 for (TestIdentifier testId : mTests) { 124 SingleJUnitTestResultParser resultParser = new SingleJUnitTestResultParser( 125 testId, listener); 126 String cmdLine = String.format("ANDROID_DATA=%s %s -cp %s %s " + 127 "com.android.cts.testng.SingleTestNGTestRunner %s#%s", 128 mDeviceTestTmpPath, mRuntimePath, jarPath, getRuntimeArgsNotNull(), 129 testId.getClassName(), testId.getTestName()); 130 String cmd = AbiFormatter.formatCmdForAbi(cmdLine, mAbi.getBitness()); 131 CLog.d("Running %s", cmd); 132 listener.testStarted(testId); 133 mDevice.executeShellCommand(cmd, resultParser, mMaxTimeToOutputResponse, 134 TimeUnit.MILLISECONDS, 0); 135 } 136 } finally { 137 listener.testRunEnded(System.currentTimeMillis() - startTime, 138 Collections.<String, String> emptyMap()); 139 // Remove jar files from device 140 removeJars(); 141 } 142 } 143 144 /** 145 * Installs the jar files on the device under test. 146 * 147 * @throws DeviceNotAvailableException 148 */ installJars()149 protected void installJars() throws DeviceNotAvailableException { 150 for (String f : mTestJars) { 151 CLog.d("Installing %s on %s", f, getDevice().getSerialNumber()); 152 File jarFile; 153 try { 154 String fullJarPath = String.format("%s%s", mDeviceTestTmpPath, f); 155 jarFile = mCtsBuild.getTestApp(f); 156 boolean result = getDevice().pushFile(jarFile, fullJarPath); 157 if (!result) { 158 throw new AssertionError(String.format("Failed to push file to %s", fullJarPath)); 159 } 160 mJarPaths.add(fullJarPath); 161 } catch (FileNotFoundException e) { 162 throw new AssertionError(String.format("Could not find file %s", f)); 163 } 164 } 165 } 166 167 /** 168 * Cleans up the jar files from the device under test. 169 * 170 * @throws DeviceNotAvailableException 171 */ removeJars()172 protected void removeJars() throws DeviceNotAvailableException { 173 for (String f : mTestJars) { 174 String fullJarPath = String.format("%s%s", mDeviceTestTmpPath, f); 175 CLog.d("Uninstalling %s on %s", fullJarPath, getDevice().getSerialNumber()); 176 getDevice().executeShellCommand(String.format("rm %s", fullJarPath)); 177 } 178 } 179 180 @Override setBuild(IBuildInfo buildInfo)181 public void setBuild(IBuildInfo buildInfo) { 182 mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo); 183 } 184 185 /** 186 * Checks that all mandatory member fields has been set. 187 */ checkFields()188 protected void checkFields() { 189 if (mRunName == null) { 190 throw new IllegalArgumentException("run name has not been set"); 191 } 192 if (mDevice == null) { 193 throw new IllegalArgumentException("Device has not been set"); 194 } 195 if (mTestJars.isEmpty()) { 196 throw new IllegalArgumentException("No test jar has been set"); 197 } 198 if (mTests == null) { 199 throw new IllegalArgumentException("tests has not been set"); 200 } 201 if (mCtsBuild == null) { 202 throw new IllegalArgumentException("build has not been set"); 203 } 204 for (String f : mTestJars) { 205 try { 206 207 mCtsBuild.getTestApp(f); 208 } catch (FileNotFoundException e) { 209 throw new IllegalArgumentException(String.format( 210 "Could not find jar %s in CTS build %s", f, 211 mCtsBuild.getRootDir().getAbsolutePath())); 212 } 213 } 214 } 215 216 /** 217 * Add runtime arguments to run the tests with. 218 * 219 * @param mRunTimeArgs 220 */ addRunTimeArgs(String mRunTimeArgs)221 public void addRunTimeArgs(String mRunTimeArgs) { 222 mRuntimeArgs = mRunTimeArgs; 223 } 224 getRuntimeArgsNotNull()225 private String getRuntimeArgsNotNull() { 226 if (mRuntimeArgs == null) { 227 return ""; 228 } 229 return mRuntimeArgs; 230 } 231 } 232