blob: 06f940a721a471e930fc922c5e1d33c0d789a103 [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();
Brett Chabot58c43a82011-09-13 14:13:57 -0700203 hostTest.setRunName(getUri());
Brett Chabotf4bec732011-04-19 17:31:06 -0700204 hostTest.setJarFileName(mJarPath);
Brett Chabot53e68a32011-10-05 14:14:55 -0700205 hostTest.setTests(mTests);
Brett Chabot58c43a82011-09-13 14:13:57 -0700206 mDigest = generateDigest(testCaseDir, mJarPath);
Brett Chabot82d9daf2010-10-20 20:07:14 -0700207 return hostTest;
Brian Muramatsu60695072012-01-09 18:11:03 -0800208 } else if (VM_HOST_TEST.equals(mTestType)) {
Brett Chabot13638ab2011-10-16 13:59:03 -0700209 CLog.d("Creating vm host test for %s", mName);
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700210 VMHostTest vmHostTest = new VMHostTest();
Brett Chabot58c43a82011-09-13 14:13:57 -0700211 vmHostTest.setRunName(getUri());
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700212 vmHostTest.setJarFileName(mJarPath);
Brett Chabot53e68a32011-10-05 14:14:55 -0700213 vmHostTest.setTests(mTests);
Brett Chabot58c43a82011-09-13 14:13:57 -0700214 mDigest = generateDigest(testCaseDir, mJarPath);
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700215 return vmHostTest;
Brian Muramatsu60695072012-01-09 18:11:03 -0800216 } else if (NATIVE_TEST.equals(mTestType)) {
Brian Muramatsu88d32a82011-12-02 10:55:12 -0800217 return new GeeTest(mUri, mName);
Svetoslav Ganovb803f802012-03-07 19:13:05 -0800218 } else if (ACCESSIBILITY_TEST.equals(mTestType)) {
219 AccessibilityTestRunner test = new AccessibilityTestRunner();
220 return setInstrumentationTest(test, testCaseDir);
221 } else if (ACCESSIBILITYSERVICE_TEST.equals(mTestType)) {
222 AccessibilityServiceTestRunner test = new AccessibilityServiceTestRunner();
223 return setInstrumentationTest(test, testCaseDir);
Brett Chabot3add9162010-09-12 17:23:05 -0700224 } else if (mIsSignatureTest) {
Brett Chabot13638ab2011-10-16 13:59:03 -0700225 // TODO: hardcode the runner/class/method for now, since current package xml points to
226 // specialized instrumentation. Eventually this special case for signatureTest can be
227 // removed, and it can be treated just like a normal InstrumentationTest
228 CLog.d("Creating signature test %s", mName);
Brett Chabotf4bec732011-04-19 17:31:06 -0700229 InstrumentationApkTest instrTest = new InstrumentationApkTest();
Brett Chabot584d2b92011-02-03 17:56:49 -0800230 instrTest.setPackageName(mAppNameSpace);
231 instrTest.setRunnerName("android.test.InstrumentationTestRunner");
232 instrTest.setClassName(SIGNATURE_TEST_CLASS);
233 instrTest.setMethodName(SIGNATURE_TEST_METHOD);
Brett Chabot13638ab2011-10-16 13:59:03 -0700234 // set expected tests to the single signature test
235 TestIdentifier t = new TestIdentifier(SIGNATURE_TEST_CLASS, SIGNATURE_TEST_METHOD);
236 mTests.clear();
237 mTests.add(t);
Brett Chabot584d2b92011-02-03 17:56:49 -0800238 // mName means 'apk file name' for instrumentation tests
Brett Chabotf4bec732011-04-19 17:31:06 -0700239 instrTest.addInstallApk(String.format("%s.apk", mName), mAppNameSpace);
Brett Chabot58c43a82011-09-13 14:13:57 -0700240 mDigest = generateDigest(testCaseDir, String.format("%s.apk", mName));
Brett Chabot584d2b92011-02-03 17:56:49 -0800241 return instrTest;
Brett Chabota0f443c2011-02-04 13:57:55 -0800242 } else {
Brett Chabot13638ab2011-10-16 13:59:03 -0700243 CLog.d("Creating instrumentation test for %s", mName);
Brett Chabot4263db42011-04-15 13:51:48 -0700244 InstrumentationApkTest instrTest = new InstrumentationApkTest();
Keun young Park34246562012-09-18 11:18:20 -0700245 if (mTimeoutInMins >= 0) {
246 // as timeout cannot be set for each test,
247 // increase the time-out of the whole package
248 CLog.d("Setting new timeout to " + mTimeoutInMins + " mins");
249 instrTest.setTestTimeout(mTimeoutInMins * 60 * 1000);
250 }
Brett Chabot53e68a32011-10-05 14:14:55 -0700251 return setInstrumentationTest(instrTest, testCaseDir);
Brett Chabot3add9162010-09-12 17:23:05 -0700252 }
253 }
Brett Chabot82d9daf2010-10-20 20:07:14 -0700254
255 /**
Brett Chabot13638ab2011-10-16 13:59:03 -0700256 * Populates given {@link InstrumentationApkTest} with data from the package xml.
Brett Chabota0f443c2011-02-04 13:57:55 -0800257 *
258 * @param testCaseDir
Brett Chabota0f443c2011-02-04 13:57:55 -0800259 * @param instrTest
260 * @return the populated {@link InstrumentationTest} or <code>null</code>
261 */
Brett Chabot53e68a32011-10-05 14:14:55 -0700262 private InstrumentationTest setInstrumentationTest(InstrumentationApkTest instrTest,
263 File testCaseDir) {
Brett Chabot58c43a82011-09-13 14:13:57 -0700264 instrTest.setRunName(getUri());
Brett Chabota0f443c2011-02-04 13:57:55 -0800265 instrTest.setPackageName(mAppNameSpace);
266 instrTest.setRunnerName(mRunner);
Brian Carlstrom022aff42011-05-17 23:16:51 -0700267 instrTest.setTestPackageName(mTestPackageName);
Brett Chabot53e68a32011-10-05 14:14:55 -0700268 instrTest.setClassName(mClassName);
269 instrTest.setMethodName(mMethodName);
270 instrTest.setTestsToRun(mTests,
271 !mExcludedTestFilter.hasExclusion()
272 /* only force batch mode if no tests are excluded */);
Brett Chabota0f443c2011-02-04 13:57:55 -0800273 // mName means 'apk file name' for instrumentation tests
Brett Chabot4263db42011-04-15 13:51:48 -0700274 instrTest.addInstallApk(String.format("%s.apk", mName), mAppNameSpace);
Brett Chabot58c43a82011-09-13 14:13:57 -0700275 mDigest = generateDigest(testCaseDir, String.format("%s.apk", mName));
Brett Chabot4263db42011-04-15 13:51:48 -0700276 if (mTests.size() > 1000) {
277 // TODO: hack, large test suites can take longer to collect tests, increase timeout
Brett Chabot13638ab2011-10-16 13:59:03 -0700278 instrTest.setCollectsTestsShellTimeout(10 * 60 * 1000);
Brett Chabota0f443c2011-02-04 13:57:55 -0800279 }
Brett Chabota0f443c2011-02-04 13:57:55 -0800280 return instrTest;
281 }
282
283 /**
Brett Chabot13638ab2011-10-16 13:59:03 -0700284 * Filter the tests to run based on list of excluded tests, class and method name.
Brett Chabotef5a6042011-01-19 19:54:14 -0800285 *
Brett Chabotef5a6042011-01-19 19:54:14 -0800286 * @return the filtered collection of tests
287 */
Brett Chabot53e68a32011-10-05 14:14:55 -0700288 private Collection<TestIdentifier> filterTests() {
289 mExcludedTestFilter.setTestInclusion(mClassName, mMethodName);
290 return mExcludedTestFilter.filter(mTests);
Brett Chabotef5a6042011-01-19 19:54:14 -0800291 }
292
293 /**
Brett Chabot4f8143c2010-12-14 18:29:44 -0800294 * {@inheritDoc}
295 */
Brian Muramatsu88d32a82011-12-02 10:55:12 -0800296 @Override
Brett Chabot4f8143c2010-12-14 18:29:44 -0800297 public boolean isKnownTest(TestIdentifier testDef) {
298 return mTests.contains(testDef);
299 }
300
301 /**
Brett Chabotef5a6042011-01-19 19:54:14 -0800302 * {@inheritDoc}
303 */
Brian Muramatsu88d32a82011-12-02 10:55:12 -0800304 @Override
Brett Chabotef5a6042011-01-19 19:54:14 -0800305 public boolean isKnownTestClass(String className) {
306 return mTestClasses.contains(className);
307 }
308
309 /**
Brian Muramatsu29d34782012-01-06 18:00:21 -0800310 * Add a {@link TestIdentifier} to the list of tests in this package.
Brett Chabot82d9daf2010-10-20 20:07:14 -0700311 *
Brian Muramatsu29d34782012-01-06 18:00:21 -0800312 * @param testDef
Keun young Park34246562012-09-18 11:18:20 -0700313 * @param timeout in mins
Brett Chabot82d9daf2010-10-20 20:07:14 -0700314 */
Keun young Park34246562012-09-18 11:18:20 -0700315 void addTest(TestIdentifier testDef, int timeout) {
Brett Chabot82d9daf2010-10-20 20:07:14 -0700316 mTests.add(testDef);
Brett Chabotef5a6042011-01-19 19:54:14 -0800317 mTestClasses.add(testDef.getClassName());
Keun young Park34246562012-09-18 11:18:20 -0700318 // 0 means no timeout, so keep 0 if already is.
319 if ((timeout > mTimeoutInMins) && (mTimeoutInMins != 0)) {
320 mTimeoutInMins = timeout;
321 }
Brett Chabot82d9daf2010-10-20 20:07:14 -0700322 }
323
324 /**
325 * Get the collection of tests in this test package.
Brett Chabot82d9daf2010-10-20 20:07:14 -0700326 */
Brett Chabot1dcb9a52011-02-10 20:26:57 -0800327 @Override
328 public Collection<TestIdentifier> getTests() {
Brett Chabot82d9daf2010-10-20 20:07:14 -0700329 return mTests;
330 }
Brett Chabot58c43a82011-09-13 14:13:57 -0700331
332 /**
333 * {@inheritDoc}
334 */
335 @Override
336 public String getDigest() {
337 return mDigest;
338 }
339
340 /**
341 * Generate a sha1sum digest for a file.
342 * <p/>
343 * Exposed for unit testing.
344 *
345 * @param fileDir the directory of the file
346 * @param fileName the name of the file
347 * @return a hex {@link String} of the digest
348 */
Brett Chabot13638ab2011-10-16 13:59:03 -0700349 String generateDigest(File fileDir, String fileName) {
Brett Chabot58c43a82011-09-13 14:13:57 -0700350 final String algorithm = "SHA-1";
351 InputStream fileStream = null;
Brett Chabot13638ab2011-10-16 13:59:03 -0700352 DigestInputStream d = null;
Brett Chabot58c43a82011-09-13 14:13:57 -0700353 try {
354 fileStream = getFileStream(fileDir, fileName);
355 MessageDigest md = MessageDigest.getInstance(algorithm);
356 d = new DigestInputStream(fileStream, md);
357 byte[] buffer = new byte[8196];
Brian Muramatsu29d34782012-01-06 18:00:21 -0800358 while (d.read(buffer) != -1) {
359 }
Brett Chabot58c43a82011-09-13 14:13:57 -0700360 return toHexString(md.digest());
361 } catch (NoSuchAlgorithmException e) {
362 return algorithm + " not found";
363 } catch (IOException e) {
364 CLog.e(e);
365 } finally {
366 StreamUtil.closeStream(d);
367 StreamUtil.closeStream(fileStream);
368 }
369 return "failed to generate digest";
370 }
371
372 /**
373 * Retrieve an input stream for given file
374 * <p/>
375 * Exposed so unit tests can mock.
376 */
377 InputStream getFileStream(File fileDir, String fileName) throws FileNotFoundException {
378 InputStream fileStream;
379 fileStream = new BufferedInputStream(new FileInputStream(new File(fileDir, fileName)));
380 return fileStream;
381 }
382
383 /**
384 * Convert the given byte array into a lowercase hex string.
385 *
386 * @param arr The array to convert.
387 * @return The hex encoded string.
388 */
389 private String toHexString(byte[] arr) {
390 StringBuffer buf = new StringBuffer(arr.length * 2);
391 for (byte b : arr) {
392 buf.append(String.format("%02x", b & 0xFF));
393 }
394 return buf.toString();
395 }
Brett Chabot3add9162010-09-12 17:23:05 -0700396}