blob: 2b91053bdd3edbaf42776cf723dad2af02d1e83e [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 */
16package com.android.cts.tradefed.testtype;
17
18import com.android.ddmlib.Log;
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
44 private static final String LOG_TAG = "TestPackageDef";
Brett Chabot584d2b92011-02-03 17:56:49 -080045 private static final String SIGNATURE_TEST_METHOD = "testSignature";
46 private static final String SIGNATURE_TEST_CLASS = "android.tests.sigtest.SimpleSignatureTest";
Brett Chabot3add9162010-09-12 17:23:05 -070047
48 private String mUri = null;
49 private String mAppNameSpace = null;
50 private String mName = null;
51 private String mRunner = null;
52 private boolean mIsHostSideTest = false;
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -070053 private boolean mIsVMHostTest = false;
Brett Chabot3add9162010-09-12 17:23:05 -070054 private String mJarPath = null;
55 private boolean mIsSignatureTest = false;
56 private boolean mIsReferenceAppTest = false;
Brett Chabota0f443c2011-02-04 13:57:55 -080057 private String mPackageToTest = null;
58 private String mApkToTestName = null;
Brian Carlstrom022aff42011-05-17 23:16:51 -070059 private String mTestPackageName = null;
Brett Chabot58c43a82011-09-13 14:13:57 -070060 private String mDigest = null;
Brett Chabot3add9162010-09-12 17:23:05 -070061
Brett Chabotef5a6042011-01-19 19:54:14 -080062 // use a LinkedHashSet for predictable iteration insertion-order, and fast lookups
63 private Collection<TestIdentifier> mTests = new LinkedHashSet<TestIdentifier>();
64 // also maintain an index of known test classes
65 private Collection<String> mTestClasses = new LinkedHashSet<String>();
Brett Chabot4f8143c2010-12-14 18:29:44 -080066
Brett Chabot53e68a32011-10-05 14:14:55 -070067 // dynamic options, not parsed from package xml
68 private String mClassName;
69 private String mMethodName;
70 private TestFilter mExcludedTestFilter = new TestFilter();
71
Brett Chabot3add9162010-09-12 17:23:05 -070072 void setUri(String uri) {
73 mUri = uri;
74 }
75
76 /**
Brett Chabot4f8143c2010-12-14 18:29:44 -080077 * {@inheritDoc}
Brett Chabot3add9162010-09-12 17:23:05 -070078 */
79 public String getUri() {
80 return mUri;
81 }
82
83 void setAppNameSpace(String appNameSpace) {
84 mAppNameSpace = appNameSpace;
85 }
86
87 String getAppNameSpace() {
88 return mAppNameSpace;
89 }
90
91 void setName(String name) {
92 mName = name;
93 }
94
Brett Chabot58c43a82011-09-13 14:13:57 -070095 /**
96 * {@inheritDoc}
97 */
98 @Override
99 public String getName() {
Brett Chabot3add9162010-09-12 17:23:05 -0700100 return mName;
101 }
102
103 void setRunner(String runnerName) {
104 mRunner = runnerName;
105 }
106
107 String getRunner() {
108 return mRunner;
109 }
110
111 void setIsHostSideTest(boolean hostSideTest) {
112 mIsHostSideTest = hostSideTest;
113
114 }
115
116 boolean isHostSideTest() {
117 return mIsHostSideTest;
118 }
119
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700120 void setIsVMHostTest(boolean vmHostTest) {
121 mIsVMHostTest = vmHostTest;
122
123 }
124
125 boolean isVMHostTest() {
126 return mIsVMHostTest;
127 }
Brett Chabot3add9162010-09-12 17:23:05 -0700128 void setJarPath(String jarPath) {
129 mJarPath = jarPath;
130 }
131
132 String getJarPath() {
133 return mJarPath;
134 }
135
136 void setIsSignatureCheck(boolean isSignatureCheckTest) {
137 mIsSignatureTest = isSignatureCheckTest;
138 }
139
140 boolean isSignatureCheck() {
141 return mIsSignatureTest;
142 }
143
144 void setIsReferenceApp(boolean isReferenceApp) {
145 mIsReferenceAppTest = isReferenceApp;
146 }
147
148 boolean isReferenceApp() {
149 return mIsReferenceAppTest;
150 }
151
Brett Chabota0f443c2011-02-04 13:57:55 -0800152 void setPackageToTest(String packageName) {
153 mPackageToTest = packageName;
154 }
155
Brian Carlstrom022aff42011-05-17 23:16:51 -0700156 void setTestPackageName(String testPackageName) {
157 mTestPackageName = testPackageName;
158 }
159
Brett Chabota0f443c2011-02-04 13:57:55 -0800160 void setApkToTest(String apkName) {
161 mApkToTestName = apkName;
162 }
163
Brett Chabot3add9162010-09-12 17:23:05 -0700164 /**
Brett Chabot4f8143c2010-12-14 18:29:44 -0800165 * {@inheritDoc}
Brett Chabot3add9162010-09-12 17:23:05 -0700166 */
Brett Chabot53e68a32011-10-05 14:14:55 -0700167 @Override
168 public void setExcludedTestFilter(TestFilter excludeFilter) {
169 mExcludedTestFilter = excludeFilter;
170 }
171
172 /**
173 * {@inheritDoc}
174 */
175 @Override
176 public void setClassName(String className, String methodName) {
177 mClassName = className;
178 mMethodName = methodName;
179 }
180
181 /**
182 * {@inheritDoc}
183 */
184 @Override
185 public IRemoteTest createTest(File testCaseDir) {
186 mExcludedTestFilter.setTestInclusion(mClassName, mMethodName);
187 mTests = filterTests();
188
Brett Chabot3add9162010-09-12 17:23:05 -0700189 if (mIsHostSideTest) {
Brett Chabot82d9daf2010-10-20 20:07:14 -0700190 Log.d(LOG_TAG, String.format("Creating host test for %s", mName));
191 JarHostTest hostTest = new JarHostTest();
Brett Chabot58c43a82011-09-13 14:13:57 -0700192 hostTest.setRunName(getUri());
Brett Chabotf4bec732011-04-19 17:31:06 -0700193 hostTest.setJarFileName(mJarPath);
Brett Chabot53e68a32011-10-05 14:14:55 -0700194 hostTest.setTests(mTests);
Brett Chabot58c43a82011-09-13 14:13:57 -0700195 mDigest = generateDigest(testCaseDir, mJarPath);
Brett Chabot82d9daf2010-10-20 20:07:14 -0700196 return hostTest;
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700197 } else if (mIsVMHostTest) {
198 Log.d(LOG_TAG, String.format("Creating vm host test for %s", mName));
199 VMHostTest vmHostTest = new VMHostTest();
Brett Chabot58c43a82011-09-13 14:13:57 -0700200 vmHostTest.setRunName(getUri());
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700201 vmHostTest.setJarFileName(mJarPath);
Brett Chabot53e68a32011-10-05 14:14:55 -0700202 vmHostTest.setTests(mTests);
Brett Chabot58c43a82011-09-13 14:13:57 -0700203 mDigest = generateDigest(testCaseDir, mJarPath);
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700204 return vmHostTest;
Brett Chabot3add9162010-09-12 17:23:05 -0700205 } else if (mIsSignatureTest) {
Brett Chabot584d2b92011-02-03 17:56:49 -0800206 // TODO: hardcode the runner/class/method for now, since current package xml
207 // points to specialized instrumentation. Eventually this special case for signatureTest
208 // can be removed, and it can be treated just like a normal InstrumentationTest
209 Log.d(LOG_TAG, String.format("Creating signature test %s", mName));
Brett Chabotf4bec732011-04-19 17:31:06 -0700210 InstrumentationApkTest instrTest = new InstrumentationApkTest();
Brett Chabot584d2b92011-02-03 17:56:49 -0800211 instrTest.setPackageName(mAppNameSpace);
212 instrTest.setRunnerName("android.test.InstrumentationTestRunner");
213 instrTest.setClassName(SIGNATURE_TEST_CLASS);
214 instrTest.setMethodName(SIGNATURE_TEST_METHOD);
215 // add signature test to list of known tests
216 addTest(new TestIdentifier(SIGNATURE_TEST_CLASS, SIGNATURE_TEST_METHOD));
217 // mName means 'apk file name' for instrumentation tests
Brett Chabotf4bec732011-04-19 17:31:06 -0700218 instrTest.addInstallApk(String.format("%s.apk", mName), mAppNameSpace);
Brett Chabot58c43a82011-09-13 14:13:57 -0700219 mDigest = generateDigest(testCaseDir, String.format("%s.apk", mName));
Brett Chabot584d2b92011-02-03 17:56:49 -0800220 return instrTest;
Brett Chabot3add9162010-09-12 17:23:05 -0700221 } else if (mIsReferenceAppTest) {
Brett Chabota0f443c2011-02-04 13:57:55 -0800222 // a reference app test is just a InstrumentationTest with one extra apk to install
Brett Chabot4263db42011-04-15 13:51:48 -0700223 InstrumentationApkTest instrTest = new InstrumentationApkTest();
224 instrTest.addInstallApk(String.format("%s.apk", mApkToTestName), mPackageToTest);
Brett Chabot53e68a32011-10-05 14:14:55 -0700225 return setInstrumentationTest(instrTest, testCaseDir);
Brett Chabota0f443c2011-02-04 13:57:55 -0800226 } else {
227 Log.d(LOG_TAG, String.format("Creating instrumentation test for %s", mName));
Brett Chabot4263db42011-04-15 13:51:48 -0700228 InstrumentationApkTest instrTest = new InstrumentationApkTest();
Brett Chabot53e68a32011-10-05 14:14:55 -0700229 return setInstrumentationTest(instrTest, testCaseDir);
Brett Chabot3add9162010-09-12 17:23:05 -0700230 }
231 }
Brett Chabot82d9daf2010-10-20 20:07:14 -0700232
233 /**
Brett Chabot4263db42011-04-15 13:51:48 -0700234 * Populates given {@link InstrumentationApkTest} with data from the package xml
Brett Chabota0f443c2011-02-04 13:57:55 -0800235 *
236 * @param testCaseDir
237 * @param className
238 * @param methodName
239 * @param instrTest
240 * @return the populated {@link InstrumentationTest} or <code>null</code>
241 */
Brett Chabot53e68a32011-10-05 14:14:55 -0700242 private InstrumentationTest setInstrumentationTest(InstrumentationApkTest instrTest,
243 File testCaseDir) {
Brett Chabot58c43a82011-09-13 14:13:57 -0700244 instrTest.setRunName(getUri());
Brett Chabota0f443c2011-02-04 13:57:55 -0800245 instrTest.setPackageName(mAppNameSpace);
246 instrTest.setRunnerName(mRunner);
Brian Carlstrom022aff42011-05-17 23:16:51 -0700247 instrTest.setTestPackageName(mTestPackageName);
Brett Chabot53e68a32011-10-05 14:14:55 -0700248 instrTest.setClassName(mClassName);
249 instrTest.setMethodName(mMethodName);
250 instrTest.setTestsToRun(mTests,
251 !mExcludedTestFilter.hasExclusion()
252 /* only force batch mode if no tests are excluded */);
Brett Chabota0f443c2011-02-04 13:57:55 -0800253 // mName means 'apk file name' for instrumentation tests
Brett Chabot4263db42011-04-15 13:51:48 -0700254 instrTest.addInstallApk(String.format("%s.apk", mName), mAppNameSpace);
Brett Chabot58c43a82011-09-13 14:13:57 -0700255 mDigest = generateDigest(testCaseDir, String.format("%s.apk", mName));
Brett Chabot4263db42011-04-15 13:51:48 -0700256 if (mTests.size() > 1000) {
257 // TODO: hack, large test suites can take longer to collect tests, increase timeout
258 instrTest.setCollectsTestsShellTimeout(10*60*1000);
Brett Chabota0f443c2011-02-04 13:57:55 -0800259 }
Brett Chabota0f443c2011-02-04 13:57:55 -0800260 return instrTest;
261 }
262
263 /**
Brett Chabot53e68a32011-10-05 14:14:55 -0700264 * Filter the tests to run based on list of excluded tests, class and method name
Brett Chabotef5a6042011-01-19 19:54:14 -0800265 *
Brett Chabotef5a6042011-01-19 19:54:14 -0800266 * @return the filtered collection of tests
267 */
Brett Chabot53e68a32011-10-05 14:14:55 -0700268 private Collection<TestIdentifier> filterTests() {
269 mExcludedTestFilter.setTestInclusion(mClassName, mMethodName);
270 return mExcludedTestFilter.filter(mTests);
Brett Chabotef5a6042011-01-19 19:54:14 -0800271 }
272
273 /**
Brett Chabot4f8143c2010-12-14 18:29:44 -0800274 * {@inheritDoc}
275 */
276 public boolean isKnownTest(TestIdentifier testDef) {
277 return mTests.contains(testDef);
278 }
279
280 /**
Brett Chabotef5a6042011-01-19 19:54:14 -0800281 * {@inheritDoc}
282 */
283 public boolean isKnownTestClass(String className) {
284 return mTestClasses.contains(className);
285 }
286
287 /**
Brett Chabot82d9daf2010-10-20 20:07:14 -0700288 * Add a {@link TestDef} to the list of tests in this package.
289 *
290 * @param testdef
291 */
292 void addTest(TestIdentifier testDef) {
293 mTests.add(testDef);
Brett Chabotef5a6042011-01-19 19:54:14 -0800294 mTestClasses.add(testDef.getClassName());
Brett Chabot82d9daf2010-10-20 20:07:14 -0700295 }
296
297 /**
298 * Get the collection of tests in this test package.
Brett Chabot82d9daf2010-10-20 20:07:14 -0700299 */
Brett Chabot1dcb9a52011-02-10 20:26:57 -0800300 @Override
301 public Collection<TestIdentifier> getTests() {
Brett Chabot82d9daf2010-10-20 20:07:14 -0700302 return mTests;
303 }
Brett Chabot58c43a82011-09-13 14:13:57 -0700304
305 /**
306 * {@inheritDoc}
307 */
308 @Override
309 public String getDigest() {
310 return mDigest;
311 }
312
313 /**
314 * Generate a sha1sum digest for a file.
315 * <p/>
316 * Exposed for unit testing.
317 *
318 * @param fileDir the directory of the file
319 * @param fileName the name of the file
320 * @return a hex {@link String} of the digest
321 */
322 String generateDigest(File fileDir, String fileName) {
323 final String algorithm = "SHA-1";
324 InputStream fileStream = null;
325 DigestInputStream d = null;
326 try {
327 fileStream = getFileStream(fileDir, fileName);
328 MessageDigest md = MessageDigest.getInstance(algorithm);
329 d = new DigestInputStream(fileStream, md);
330 byte[] buffer = new byte[8196];
331 while (d.read(buffer) != -1);
332 return toHexString(md.digest());
333 } catch (NoSuchAlgorithmException e) {
334 return algorithm + " not found";
335 } catch (IOException e) {
336 CLog.e(e);
337 } finally {
338 StreamUtil.closeStream(d);
339 StreamUtil.closeStream(fileStream);
340 }
341 return "failed to generate digest";
342 }
343
344 /**
345 * Retrieve an input stream for given file
346 * <p/>
347 * Exposed so unit tests can mock.
348 */
349 InputStream getFileStream(File fileDir, String fileName) throws FileNotFoundException {
350 InputStream fileStream;
351 fileStream = new BufferedInputStream(new FileInputStream(new File(fileDir, fileName)));
352 return fileStream;
353 }
354
355 /**
356 * Convert the given byte array into a lowercase hex string.
357 *
358 * @param arr The array to convert.
359 * @return The hex encoded string.
360 */
361 private String toHexString(byte[] arr) {
362 StringBuffer buf = new StringBuffer(arr.length * 2);
363 for (byte b : arr) {
364 buf.append(String.format("%02x", b & 0xFF));
365 }
366 return buf.toString();
367 }
Brett Chabot3add9162010-09-12 17:23:05 -0700368}