blob: ffbb9307d7489a4e6c28f93ae0e924b88a5eb157 [file] [log] [blame]
Brett Chabot3add9162010-09-12 17:23:05 -07001/*
2 * Copyright (C) 2010 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 */
Brett Chabot13638ab2011-10-16 13:59:03 -070016
Brett Chabot3add9162010-09-12 17:23:05 -070017package com.android.cts.tradefed.testtype;
18
Brett Chabot82d9daf2010-10-20 20:07:14 -070019import com.android.ddmlib.testrunner.TestIdentifier;
Brett Chabot58c43a82011-09-13 14:13:57 -070020import com.android.tradefed.log.LogUtil.CLog;
Brett Chabot3add9162010-09-12 17:23:05 -070021import com.android.tradefed.testtype.IRemoteTest;
22import com.android.tradefed.testtype.InstrumentationTest;
Brett Chabot58c43a82011-09-13 14:13:57 -070023import com.android.tradefed.util.StreamUtil;
Brett Chabot3add9162010-09-12 17:23:05 -070024
Brett Chabot58c43a82011-09-13 14:13:57 -070025import java.io.BufferedInputStream;
Brett Chabot3add9162010-09-12 17:23:05 -070026import java.io.File;
Brett Chabot58c43a82011-09-13 14:13:57 -070027import java.io.FileInputStream;
28import java.io.FileNotFoundException;
29import java.io.IOException;
30import java.io.InputStream;
31import java.security.DigestInputStream;
32import java.security.MessageDigest;
33import java.security.NoSuchAlgorithmException;
Brett Chabot82d9daf2010-10-20 20:07:14 -070034import java.util.Collection;
Brett Chabotef5a6042011-01-19 19:54:14 -080035import java.util.LinkedHashSet;
Brett Chabot3add9162010-09-12 17:23:05 -070036
37/**
38 * Container for CTS test info.
39 * <p/>
40 * Knows how to translate this info into a runnable {@link IRemoteTest}.
41 */
Brett Chabot4f8143c2010-12-14 18:29:44 -080042class TestPackageDef implements ITestPackageDef {
Brett Chabot3add9162010-09-12 17:23:05 -070043
Brian Muramatsu60695072012-01-09 18:11:03 -080044 public static final String HOST_SIDE_ONLY_TEST = "hostSideOnly";
45 public static final String NATIVE_TEST = "native";
46 public static final String VM_HOST_TEST = "vmHostTest";
Svetoslav Ganovb803f802012-03-07 19:13:05 -080047 public static final String ACCESSIBILITY_TEST =
48 "com.android.cts.tradefed.testtype.AccessibilityTestRunner";
49 public static final String ACCESSIBILITYSERVICE_TEST =
50 "com.android.cts.tradefed.testtype.AccessibilityServiceTestRunner";
Brian Muramatsu60695072012-01-09 18:11:03 -080051
Brett Chabot584d2b92011-02-03 17:56:49 -080052 private static final String SIGNATURE_TEST_METHOD = "testSignature";
53 private static final String SIGNATURE_TEST_CLASS = "android.tests.sigtest.SimpleSignatureTest";
Brett Chabot3add9162010-09-12 17:23:05 -070054
55 private String mUri = null;
56 private String mAppNameSpace = null;
57 private String mName = null;
58 private String mRunner = null;
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -070059 private boolean mIsVMHostTest = false;
Brian Muramatsu88d32a82011-12-02 10:55:12 -080060 private String mTestType = null;
Brett Chabot3add9162010-09-12 17:23:05 -070061 private String mJarPath = null;
62 private boolean mIsSignatureTest = false;
Brian Carlstrom022aff42011-05-17 23:16:51 -070063 private String mTestPackageName = null;
Brett Chabot58c43a82011-09-13 14:13:57 -070064 private String mDigest = null;
Brett Chabot3add9162010-09-12 17:23:05 -070065
Brett Chabot13638ab2011-10-16 13:59:03 -070066 // use a LinkedHashSet for predictable iteration insertion-order, and fast
67 // lookups
Brett Chabotef5a6042011-01-19 19:54:14 -080068 private Collection<TestIdentifier> mTests = new LinkedHashSet<TestIdentifier>();
69 // also maintain an index of known test classes
70 private Collection<String> mTestClasses = new LinkedHashSet<String>();
Brett Chabot4f8143c2010-12-14 18:29:44 -080071
Brett Chabot53e68a32011-10-05 14:14:55 -070072 // dynamic options, not parsed from package xml
73 private String mClassName;
74 private String mMethodName;
75 private TestFilter mExcludedTestFilter = new TestFilter();
Brett Chabot358dc562011-10-25 15:46:48 -070076 private String mTargetBinaryName;
77 private String mTargetNameSpace;
Keun young Park34246562012-09-18 11:18:20 -070078 // only timeout per package is supported. To change this to method granularity,
79 // test invocation should be done in method level.
80 // So for now, only max timeout for the package is used.
81 private int mTimeoutInMins = -1;
Brett Chabot53e68a32011-10-05 14:14:55 -070082
Brett Chabot3add9162010-09-12 17:23:05 -070083 void setUri(String uri) {
84 mUri = uri;
85 }
86
87 /**
Brett Chabot4f8143c2010-12-14 18:29:44 -080088 * {@inheritDoc}
Brett Chabot3add9162010-09-12 17:23:05 -070089 */
Brian Muramatsu88d32a82011-12-02 10:55:12 -080090 @Override
Brett Chabot3add9162010-09-12 17:23:05 -070091 public String getUri() {
92 return mUri;
93 }
94
95 void setAppNameSpace(String appNameSpace) {
96 mAppNameSpace = appNameSpace;
97 }
98
99 String getAppNameSpace() {
100 return mAppNameSpace;
101 }
102
103 void setName(String name) {
104 mName = name;
105 }
106
Brett Chabot58c43a82011-09-13 14:13:57 -0700107 /**
108 * {@inheritDoc}
109 */
110 @Override
111 public String getName() {
Brett Chabot3add9162010-09-12 17:23:05 -0700112 return mName;
113 }
114
115 void setRunner(String runnerName) {
116 mRunner = runnerName;
117 }
118
119 String getRunner() {
120 return mRunner;
121 }
122
Brian Muramatsu88d32a82011-12-02 10:55:12 -0800123 void setTestType(String testType) {
124 mTestType = testType;
125 }
126
Brian Muramatsu60695072012-01-09 18:11:03 -0800127 String getTestType() {
128 return mTestType;
129 }
130
Brett Chabot3add9162010-09-12 17:23:05 -0700131 void setJarPath(String jarPath) {
132 mJarPath = jarPath;
133 }
134
135 String getJarPath() {
136 return mJarPath;
137 }
138
139 void setIsSignatureCheck(boolean isSignatureCheckTest) {
140 mIsSignatureTest = isSignatureCheckTest;
141 }
142
143 boolean isSignatureCheck() {
144 return mIsSignatureTest;
145 }
146
Brian Carlstrom022aff42011-05-17 23:16:51 -0700147 void setTestPackageName(String testPackageName) {
148 mTestPackageName = testPackageName;
149 }
150
Brett Chabot358dc562011-10-25 15:46:48 -0700151 void setTargetBinaryName(String targetBinaryName) {
152 mTargetBinaryName = targetBinaryName;
153 }
154
155 void setTargetNameSpace(String targetNameSpace) {
156 mTargetNameSpace = targetNameSpace;
157 }
158
159 @Override
160 public String getTargetApkName() {
161 if (mTargetBinaryName != null && !mTargetBinaryName.isEmpty()) {
162 return String.format("%s.apk", mTargetBinaryName);
163 }
164 return null;
165 }
166
167 @Override
168 public String getTargetPackageName() {
169 if (mTargetNameSpace != null && mTargetNameSpace.isEmpty()) {
170 return null;
171 }
172 return mTargetNameSpace;
173 }
174
Brett Chabot3add9162010-09-12 17:23:05 -0700175 /**
Brett Chabot4f8143c2010-12-14 18:29:44 -0800176 * {@inheritDoc}
Brett Chabot3add9162010-09-12 17:23:05 -0700177 */
Brett Chabot53e68a32011-10-05 14:14:55 -0700178 @Override
179 public void setExcludedTestFilter(TestFilter excludeFilter) {
180 mExcludedTestFilter = excludeFilter;
181 }
182
183 /**
184 * {@inheritDoc}
185 */
186 @Override
187 public void setClassName(String className, String methodName) {
188 mClassName = className;
189 mMethodName = methodName;
190 }
191
192 /**
193 * {@inheritDoc}
194 */
195 @Override
196 public IRemoteTest createTest(File testCaseDir) {
197 mExcludedTestFilter.setTestInclusion(mClassName, mMethodName);
198 mTests = filterTests();
199
Brian Muramatsu60695072012-01-09 18:11:03 -0800200 if (HOST_SIDE_ONLY_TEST.equals(mTestType)) {
Brett Chabot13638ab2011-10-16 13:59:03 -0700201 CLog.d("Creating host test for %s", mName);
Brett Chabot82d9daf2010-10-20 20:07:14 -0700202 JarHostTest hostTest = new JarHostTest();
Keun young Park14a5bfa2012-10-02 13:45:30 -0700203 if (mTimeoutInMins >= 0) {
204 CLog.d("Setting new timeout to " + mTimeoutInMins + " mins");
205 hostTest.setTimeout(mTimeoutInMins * 60 * 1000);
206 }
Brett Chabot58c43a82011-09-13 14:13:57 -0700207 hostTest.setRunName(getUri());
Brett Chabotf4bec732011-04-19 17:31:06 -0700208 hostTest.setJarFileName(mJarPath);
Brett Chabot53e68a32011-10-05 14:14:55 -0700209 hostTest.setTests(mTests);
Brett Chabot58c43a82011-09-13 14:13:57 -0700210 mDigest = generateDigest(testCaseDir, mJarPath);
Brett Chabot82d9daf2010-10-20 20:07:14 -0700211 return hostTest;
Brian Muramatsu60695072012-01-09 18:11:03 -0800212 } else if (VM_HOST_TEST.equals(mTestType)) {
Brett Chabot13638ab2011-10-16 13:59:03 -0700213 CLog.d("Creating vm host test for %s", mName);
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700214 VMHostTest vmHostTest = new VMHostTest();
Brett Chabot58c43a82011-09-13 14:13:57 -0700215 vmHostTest.setRunName(getUri());
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700216 vmHostTest.setJarFileName(mJarPath);
Brett Chabot53e68a32011-10-05 14:14:55 -0700217 vmHostTest.setTests(mTests);
Brett Chabot58c43a82011-09-13 14:13:57 -0700218 mDigest = generateDigest(testCaseDir, mJarPath);
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700219 return vmHostTest;
Brian Muramatsu60695072012-01-09 18:11:03 -0800220 } else if (NATIVE_TEST.equals(mTestType)) {
Brian Muramatsu88d32a82011-12-02 10:55:12 -0800221 return new GeeTest(mUri, mName);
Svetoslav Ganovb803f802012-03-07 19:13:05 -0800222 } else if (ACCESSIBILITY_TEST.equals(mTestType)) {
223 AccessibilityTestRunner test = new AccessibilityTestRunner();
224 return setInstrumentationTest(test, testCaseDir);
225 } else if (ACCESSIBILITYSERVICE_TEST.equals(mTestType)) {
226 AccessibilityServiceTestRunner test = new AccessibilityServiceTestRunner();
227 return setInstrumentationTest(test, testCaseDir);
Brett Chabot3add9162010-09-12 17:23:05 -0700228 } else if (mIsSignatureTest) {
Brett Chabot13638ab2011-10-16 13:59:03 -0700229 // TODO: hardcode the runner/class/method for now, since current package xml points to
230 // specialized instrumentation. Eventually this special case for signatureTest can be
231 // removed, and it can be treated just like a normal InstrumentationTest
232 CLog.d("Creating signature test %s", mName);
Brett Chabotf4bec732011-04-19 17:31:06 -0700233 InstrumentationApkTest instrTest = new InstrumentationApkTest();
Brett Chabot584d2b92011-02-03 17:56:49 -0800234 instrTest.setPackageName(mAppNameSpace);
235 instrTest.setRunnerName("android.test.InstrumentationTestRunner");
236 instrTest.setClassName(SIGNATURE_TEST_CLASS);
237 instrTest.setMethodName(SIGNATURE_TEST_METHOD);
Brett Chabot13638ab2011-10-16 13:59:03 -0700238 // set expected tests to the single signature test
239 TestIdentifier t = new TestIdentifier(SIGNATURE_TEST_CLASS, SIGNATURE_TEST_METHOD);
240 mTests.clear();
241 mTests.add(t);
Brett Chabot584d2b92011-02-03 17:56:49 -0800242 // mName means 'apk file name' for instrumentation tests
Brett Chabotf4bec732011-04-19 17:31:06 -0700243 instrTest.addInstallApk(String.format("%s.apk", mName), mAppNameSpace);
Brett Chabot58c43a82011-09-13 14:13:57 -0700244 mDigest = generateDigest(testCaseDir, String.format("%s.apk", mName));
Brett Chabot584d2b92011-02-03 17:56:49 -0800245 return instrTest;
Brett Chabota0f443c2011-02-04 13:57:55 -0800246 } else {
Brett Chabot13638ab2011-10-16 13:59:03 -0700247 CLog.d("Creating instrumentation test for %s", mName);
Brett Chabot4263db42011-04-15 13:51:48 -0700248 InstrumentationApkTest instrTest = new InstrumentationApkTest();
Keun young Park34246562012-09-18 11:18:20 -0700249 if (mTimeoutInMins >= 0) {
250 // as timeout cannot be set for each test,
251 // increase the time-out of the whole package
252 CLog.d("Setting new timeout to " + mTimeoutInMins + " mins");
253 instrTest.setTestTimeout(mTimeoutInMins * 60 * 1000);
254 }
Brett Chabot53e68a32011-10-05 14:14:55 -0700255 return setInstrumentationTest(instrTest, testCaseDir);
Brett Chabot3add9162010-09-12 17:23:05 -0700256 }
257 }
Brett Chabot82d9daf2010-10-20 20:07:14 -0700258
259 /**
Brett Chabot13638ab2011-10-16 13:59:03 -0700260 * Populates given {@link InstrumentationApkTest} with data from the package xml.
Brett Chabota0f443c2011-02-04 13:57:55 -0800261 *
262 * @param testCaseDir
Brett Chabota0f443c2011-02-04 13:57:55 -0800263 * @param instrTest
264 * @return the populated {@link InstrumentationTest} or <code>null</code>
265 */
Brett Chabot53e68a32011-10-05 14:14:55 -0700266 private InstrumentationTest setInstrumentationTest(InstrumentationApkTest instrTest,
267 File testCaseDir) {
Brett Chabot58c43a82011-09-13 14:13:57 -0700268 instrTest.setRunName(getUri());
Brett Chabota0f443c2011-02-04 13:57:55 -0800269 instrTest.setPackageName(mAppNameSpace);
270 instrTest.setRunnerName(mRunner);
Brian Carlstrom022aff42011-05-17 23:16:51 -0700271 instrTest.setTestPackageName(mTestPackageName);
Brett Chabot53e68a32011-10-05 14:14:55 -0700272 instrTest.setClassName(mClassName);
273 instrTest.setMethodName(mMethodName);
274 instrTest.setTestsToRun(mTests,
275 !mExcludedTestFilter.hasExclusion()
276 /* only force batch mode if no tests are excluded */);
Brett Chabota0f443c2011-02-04 13:57:55 -0800277 // mName means 'apk file name' for instrumentation tests
Brett Chabot4263db42011-04-15 13:51:48 -0700278 instrTest.addInstallApk(String.format("%s.apk", mName), mAppNameSpace);
Brett Chabot58c43a82011-09-13 14:13:57 -0700279 mDigest = generateDigest(testCaseDir, String.format("%s.apk", mName));
Brett Chabot4263db42011-04-15 13:51:48 -0700280 if (mTests.size() > 1000) {
281 // TODO: hack, large test suites can take longer to collect tests, increase timeout
Brett Chabot13638ab2011-10-16 13:59:03 -0700282 instrTest.setCollectsTestsShellTimeout(10 * 60 * 1000);
Brett Chabota0f443c2011-02-04 13:57:55 -0800283 }
Brett Chabota0f443c2011-02-04 13:57:55 -0800284 return instrTest;
285 }
286
287 /**
Brett Chabot13638ab2011-10-16 13:59:03 -0700288 * Filter the tests to run based on list of excluded tests, class and method name.
Brett Chabotef5a6042011-01-19 19:54:14 -0800289 *
Brett Chabotef5a6042011-01-19 19:54:14 -0800290 * @return the filtered collection of tests
291 */
Brett Chabot53e68a32011-10-05 14:14:55 -0700292 private Collection<TestIdentifier> filterTests() {
293 mExcludedTestFilter.setTestInclusion(mClassName, mMethodName);
294 return mExcludedTestFilter.filter(mTests);
Brett Chabotef5a6042011-01-19 19:54:14 -0800295 }
296
297 /**
Brett Chabot4f8143c2010-12-14 18:29:44 -0800298 * {@inheritDoc}
299 */
Brian Muramatsu88d32a82011-12-02 10:55:12 -0800300 @Override
Brett Chabot4f8143c2010-12-14 18:29:44 -0800301 public boolean isKnownTest(TestIdentifier testDef) {
302 return mTests.contains(testDef);
303 }
304
305 /**
Brett Chabotef5a6042011-01-19 19:54:14 -0800306 * {@inheritDoc}
307 */
Brian Muramatsu88d32a82011-12-02 10:55:12 -0800308 @Override
Brett Chabotef5a6042011-01-19 19:54:14 -0800309 public boolean isKnownTestClass(String className) {
310 return mTestClasses.contains(className);
311 }
312
313 /**
Brian Muramatsu29d34782012-01-06 18:00:21 -0800314 * Add a {@link TestIdentifier} to the list of tests in this package.
Brett Chabot82d9daf2010-10-20 20:07:14 -0700315 *
Brian Muramatsu29d34782012-01-06 18:00:21 -0800316 * @param testDef
Keun young Park34246562012-09-18 11:18:20 -0700317 * @param timeout in mins
Brett Chabot82d9daf2010-10-20 20:07:14 -0700318 */
Keun young Park34246562012-09-18 11:18:20 -0700319 void addTest(TestIdentifier testDef, int timeout) {
Brett Chabot82d9daf2010-10-20 20:07:14 -0700320 mTests.add(testDef);
Brett Chabotef5a6042011-01-19 19:54:14 -0800321 mTestClasses.add(testDef.getClassName());
Keun young Park34246562012-09-18 11:18:20 -0700322 // 0 means no timeout, so keep 0 if already is.
323 if ((timeout > mTimeoutInMins) && (mTimeoutInMins != 0)) {
324 mTimeoutInMins = timeout;
325 }
Brett Chabot82d9daf2010-10-20 20:07:14 -0700326 }
327
328 /**
329 * Get the collection of tests in this test package.
Brett Chabot82d9daf2010-10-20 20:07:14 -0700330 */
Brett Chabot1dcb9a52011-02-10 20:26:57 -0800331 @Override
332 public Collection<TestIdentifier> getTests() {
Brett Chabot82d9daf2010-10-20 20:07:14 -0700333 return mTests;
334 }
Brett Chabot58c43a82011-09-13 14:13:57 -0700335
336 /**
337 * {@inheritDoc}
338 */
339 @Override
340 public String getDigest() {
341 return mDigest;
342 }
343
344 /**
345 * Generate a sha1sum digest for a file.
346 * <p/>
347 * Exposed for unit testing.
348 *
349 * @param fileDir the directory of the file
350 * @param fileName the name of the file
351 * @return a hex {@link String} of the digest
352 */
Brett Chabot13638ab2011-10-16 13:59:03 -0700353 String generateDigest(File fileDir, String fileName) {
Brett Chabot58c43a82011-09-13 14:13:57 -0700354 final String algorithm = "SHA-1";
355 InputStream fileStream = null;
Brett Chabot13638ab2011-10-16 13:59:03 -0700356 DigestInputStream d = null;
Brett Chabot58c43a82011-09-13 14:13:57 -0700357 try {
358 fileStream = getFileStream(fileDir, fileName);
359 MessageDigest md = MessageDigest.getInstance(algorithm);
360 d = new DigestInputStream(fileStream, md);
361 byte[] buffer = new byte[8196];
Brian Muramatsu29d34782012-01-06 18:00:21 -0800362 while (d.read(buffer) != -1) {
363 }
Brett Chabot58c43a82011-09-13 14:13:57 -0700364 return toHexString(md.digest());
365 } catch (NoSuchAlgorithmException e) {
366 return algorithm + " not found";
367 } catch (IOException e) {
368 CLog.e(e);
369 } finally {
370 StreamUtil.closeStream(d);
371 StreamUtil.closeStream(fileStream);
372 }
373 return "failed to generate digest";
374 }
375
376 /**
377 * Retrieve an input stream for given file
378 * <p/>
379 * Exposed so unit tests can mock.
380 */
381 InputStream getFileStream(File fileDir, String fileName) throws FileNotFoundException {
382 InputStream fileStream;
383 fileStream = new BufferedInputStream(new FileInputStream(new File(fileDir, fileName)));
384 return fileStream;
385 }
386
387 /**
388 * Convert the given byte array into a lowercase hex string.
389 *
390 * @param arr The array to convert.
391 * @return The hex encoded string.
392 */
393 private String toHexString(byte[] arr) {
394 StringBuffer buf = new StringBuffer(arr.length * 2);
395 for (byte b : arr) {
396 buf.append(String.format("%02x", b & 0xFF));
397 }
398 return buf.toString();
399 }
Brett Chabot3add9162010-09-12 17:23:05 -0700400}