blob: 8844667f3cac0fb464988b042ba7d6d72a247bba [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
Brett Chabot584d2b92011-02-03 17:56:49 -080044 private static final String SIGNATURE_TEST_METHOD = "testSignature";
45 private static final String SIGNATURE_TEST_CLASS = "android.tests.sigtest.SimpleSignatureTest";
Brett Chabot3add9162010-09-12 17:23:05 -070046
47 private String mUri = null;
48 private String mAppNameSpace = null;
49 private String mName = null;
50 private String mRunner = null;
51 private boolean mIsHostSideTest = false;
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -070052 private boolean mIsVMHostTest = false;
Brett Chabot3add9162010-09-12 17:23:05 -070053 private String mJarPath = null;
54 private boolean mIsSignatureTest = false;
55 private boolean mIsReferenceAppTest = false;
Brett Chabota0f443c2011-02-04 13:57:55 -080056 private String mPackageToTest = null;
57 private String mApkToTestName = null;
Brian Carlstrom022aff42011-05-17 23:16:51 -070058 private String mTestPackageName = null;
Brett Chabot58c43a82011-09-13 14:13:57 -070059 private String mDigest = null;
Brett Chabot3add9162010-09-12 17:23:05 -070060
Brett Chabot13638ab2011-10-16 13:59:03 -070061 // use a LinkedHashSet for predictable iteration insertion-order, and fast
62 // lookups
Brett Chabotef5a6042011-01-19 19:54:14 -080063 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();
Brett Chabot358dc562011-10-25 15:46:48 -070071 private String mTargetBinaryName;
72 private String mTargetNameSpace;
Brett Chabot53e68a32011-10-05 14:14:55 -070073
Brett Chabot3add9162010-09-12 17:23:05 -070074 void setUri(String uri) {
75 mUri = uri;
76 }
77
78 /**
Brett Chabot4f8143c2010-12-14 18:29:44 -080079 * {@inheritDoc}
Brett Chabot3add9162010-09-12 17:23:05 -070080 */
81 public String getUri() {
82 return mUri;
83 }
84
85 void setAppNameSpace(String appNameSpace) {
86 mAppNameSpace = appNameSpace;
87 }
88
89 String getAppNameSpace() {
90 return mAppNameSpace;
91 }
92
93 void setName(String name) {
94 mName = name;
95 }
96
Brett Chabot58c43a82011-09-13 14:13:57 -070097 /**
98 * {@inheritDoc}
99 */
100 @Override
101 public String getName() {
Brett Chabot3add9162010-09-12 17:23:05 -0700102 return mName;
103 }
104
105 void setRunner(String runnerName) {
106 mRunner = runnerName;
107 }
108
109 String getRunner() {
110 return mRunner;
111 }
112
113 void setIsHostSideTest(boolean hostSideTest) {
114 mIsHostSideTest = hostSideTest;
115
116 }
117
118 boolean isHostSideTest() {
119 return mIsHostSideTest;
120 }
121
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700122 void setIsVMHostTest(boolean vmHostTest) {
123 mIsVMHostTest = vmHostTest;
124
125 }
126
127 boolean isVMHostTest() {
128 return mIsVMHostTest;
129 }
Brett Chabot13638ab2011-10-16 13:59:03 -0700130
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
147 void setIsReferenceApp(boolean isReferenceApp) {
148 mIsReferenceAppTest = isReferenceApp;
149 }
150
151 boolean isReferenceApp() {
152 return mIsReferenceAppTest;
153 }
154
Brett Chabota0f443c2011-02-04 13:57:55 -0800155 void setPackageToTest(String packageName) {
156 mPackageToTest = packageName;
157 }
158
Brian Carlstrom022aff42011-05-17 23:16:51 -0700159 void setTestPackageName(String testPackageName) {
160 mTestPackageName = testPackageName;
161 }
162
Brett Chabota0f443c2011-02-04 13:57:55 -0800163 void setApkToTest(String apkName) {
164 mApkToTestName = apkName;
165 }
166
Brett Chabot358dc562011-10-25 15:46:48 -0700167 void setTargetBinaryName(String targetBinaryName) {
168 mTargetBinaryName = targetBinaryName;
169 }
170
171 void setTargetNameSpace(String targetNameSpace) {
172 mTargetNameSpace = targetNameSpace;
173 }
174
175 @Override
176 public String getTargetApkName() {
177 if (mTargetBinaryName != null && !mTargetBinaryName.isEmpty()) {
178 return String.format("%s.apk", mTargetBinaryName);
179 }
180 return null;
181 }
182
183 @Override
184 public String getTargetPackageName() {
185 if (mTargetNameSpace != null && mTargetNameSpace.isEmpty()) {
186 return null;
187 }
188 return mTargetNameSpace;
189 }
190
Brett Chabot3add9162010-09-12 17:23:05 -0700191 /**
Brett Chabot4f8143c2010-12-14 18:29:44 -0800192 * {@inheritDoc}
Brett Chabot3add9162010-09-12 17:23:05 -0700193 */
Brett Chabot53e68a32011-10-05 14:14:55 -0700194 @Override
195 public void setExcludedTestFilter(TestFilter excludeFilter) {
196 mExcludedTestFilter = excludeFilter;
197 }
198
199 /**
200 * {@inheritDoc}
201 */
202 @Override
203 public void setClassName(String className, String methodName) {
204 mClassName = className;
205 mMethodName = methodName;
206 }
207
208 /**
209 * {@inheritDoc}
210 */
211 @Override
212 public IRemoteTest createTest(File testCaseDir) {
213 mExcludedTestFilter.setTestInclusion(mClassName, mMethodName);
214 mTests = filterTests();
215
Brett Chabot3add9162010-09-12 17:23:05 -0700216 if (mIsHostSideTest) {
Brett Chabot13638ab2011-10-16 13:59:03 -0700217 CLog.d("Creating host test for %s", mName);
Brett Chabot82d9daf2010-10-20 20:07:14 -0700218 JarHostTest hostTest = new JarHostTest();
Brett Chabot58c43a82011-09-13 14:13:57 -0700219 hostTest.setRunName(getUri());
Brett Chabotf4bec732011-04-19 17:31:06 -0700220 hostTest.setJarFileName(mJarPath);
Brett Chabot53e68a32011-10-05 14:14:55 -0700221 hostTest.setTests(mTests);
Brett Chabot58c43a82011-09-13 14:13:57 -0700222 mDigest = generateDigest(testCaseDir, mJarPath);
Brett Chabot82d9daf2010-10-20 20:07:14 -0700223 return hostTest;
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700224 } else if (mIsVMHostTest) {
Brett Chabot13638ab2011-10-16 13:59:03 -0700225 CLog.d("Creating vm host test for %s", mName);
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700226 VMHostTest vmHostTest = new VMHostTest();
Brett Chabot58c43a82011-09-13 14:13:57 -0700227 vmHostTest.setRunName(getUri());
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700228 vmHostTest.setJarFileName(mJarPath);
Brett Chabot53e68a32011-10-05 14:14:55 -0700229 vmHostTest.setTests(mTests);
Brett Chabot58c43a82011-09-13 14:13:57 -0700230 mDigest = generateDigest(testCaseDir, mJarPath);
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700231 return vmHostTest;
Brett Chabot3add9162010-09-12 17:23:05 -0700232 } else if (mIsSignatureTest) {
Brett Chabot13638ab2011-10-16 13:59:03 -0700233 // TODO: hardcode the runner/class/method for now, since current package xml points to
234 // specialized instrumentation. Eventually this special case for signatureTest can be
235 // removed, and it can be treated just like a normal InstrumentationTest
236 CLog.d("Creating signature test %s", mName);
Brett Chabotf4bec732011-04-19 17:31:06 -0700237 InstrumentationApkTest instrTest = new InstrumentationApkTest();
Brett Chabot584d2b92011-02-03 17:56:49 -0800238 instrTest.setPackageName(mAppNameSpace);
239 instrTest.setRunnerName("android.test.InstrumentationTestRunner");
240 instrTest.setClassName(SIGNATURE_TEST_CLASS);
241 instrTest.setMethodName(SIGNATURE_TEST_METHOD);
Brett Chabot13638ab2011-10-16 13:59:03 -0700242 // set expected tests to the single signature test
243 TestIdentifier t = new TestIdentifier(SIGNATURE_TEST_CLASS, SIGNATURE_TEST_METHOD);
244 mTests.clear();
245 mTests.add(t);
Brett Chabot584d2b92011-02-03 17:56:49 -0800246 // mName means 'apk file name' for instrumentation tests
Brett Chabotf4bec732011-04-19 17:31:06 -0700247 instrTest.addInstallApk(String.format("%s.apk", mName), mAppNameSpace);
Brett Chabot58c43a82011-09-13 14:13:57 -0700248 mDigest = generateDigest(testCaseDir, String.format("%s.apk", mName));
Brett Chabot584d2b92011-02-03 17:56:49 -0800249 return instrTest;
Brett Chabot3add9162010-09-12 17:23:05 -0700250 } else if (mIsReferenceAppTest) {
Brett Chabota0f443c2011-02-04 13:57:55 -0800251 // a reference app test is just a InstrumentationTest with one extra apk to install
Brett Chabot4263db42011-04-15 13:51:48 -0700252 InstrumentationApkTest instrTest = new InstrumentationApkTest();
253 instrTest.addInstallApk(String.format("%s.apk", mApkToTestName), mPackageToTest);
Brett Chabot53e68a32011-10-05 14:14:55 -0700254 return setInstrumentationTest(instrTest, testCaseDir);
Brett Chabota0f443c2011-02-04 13:57:55 -0800255 } else {
Brett Chabot13638ab2011-10-16 13:59:03 -0700256 CLog.d("Creating instrumentation test for %s", mName);
Brett Chabot4263db42011-04-15 13:51:48 -0700257 InstrumentationApkTest instrTest = new InstrumentationApkTest();
Brett Chabot53e68a32011-10-05 14:14:55 -0700258 return setInstrumentationTest(instrTest, testCaseDir);
Brett Chabot3add9162010-09-12 17:23:05 -0700259 }
260 }
Brett Chabot82d9daf2010-10-20 20:07:14 -0700261
262 /**
Brett Chabot13638ab2011-10-16 13:59:03 -0700263 * Populates given {@link InstrumentationApkTest} with data from the package xml.
Brett Chabota0f443c2011-02-04 13:57:55 -0800264 *
265 * @param testCaseDir
266 * @param className
267 * @param methodName
268 * @param instrTest
269 * @return the populated {@link InstrumentationTest} or <code>null</code>
270 */
Brett Chabot53e68a32011-10-05 14:14:55 -0700271 private InstrumentationTest setInstrumentationTest(InstrumentationApkTest instrTest,
272 File testCaseDir) {
Brett Chabot58c43a82011-09-13 14:13:57 -0700273 instrTest.setRunName(getUri());
Brett Chabota0f443c2011-02-04 13:57:55 -0800274 instrTest.setPackageName(mAppNameSpace);
275 instrTest.setRunnerName(mRunner);
Brian Carlstrom022aff42011-05-17 23:16:51 -0700276 instrTest.setTestPackageName(mTestPackageName);
Brett Chabot53e68a32011-10-05 14:14:55 -0700277 instrTest.setClassName(mClassName);
278 instrTest.setMethodName(mMethodName);
279 instrTest.setTestsToRun(mTests,
280 !mExcludedTestFilter.hasExclusion()
281 /* only force batch mode if no tests are excluded */);
Brett Chabota0f443c2011-02-04 13:57:55 -0800282 // mName means 'apk file name' for instrumentation tests
Brett Chabot4263db42011-04-15 13:51:48 -0700283 instrTest.addInstallApk(String.format("%s.apk", mName), mAppNameSpace);
Brett Chabot58c43a82011-09-13 14:13:57 -0700284 mDigest = generateDigest(testCaseDir, String.format("%s.apk", mName));
Brett Chabot4263db42011-04-15 13:51:48 -0700285 if (mTests.size() > 1000) {
286 // TODO: hack, large test suites can take longer to collect tests, increase timeout
Brett Chabot13638ab2011-10-16 13:59:03 -0700287 instrTest.setCollectsTestsShellTimeout(10 * 60 * 1000);
Brett Chabota0f443c2011-02-04 13:57:55 -0800288 }
Brett Chabota0f443c2011-02-04 13:57:55 -0800289 return instrTest;
290 }
291
292 /**
Brett Chabot13638ab2011-10-16 13:59:03 -0700293 * Filter the tests to run based on list of excluded tests, class and method name.
Brett Chabotef5a6042011-01-19 19:54:14 -0800294 *
Brett Chabotef5a6042011-01-19 19:54:14 -0800295 * @return the filtered collection of tests
296 */
Brett Chabot53e68a32011-10-05 14:14:55 -0700297 private Collection<TestIdentifier> filterTests() {
298 mExcludedTestFilter.setTestInclusion(mClassName, mMethodName);
299 return mExcludedTestFilter.filter(mTests);
Brett Chabotef5a6042011-01-19 19:54:14 -0800300 }
301
302 /**
Brett Chabot4f8143c2010-12-14 18:29:44 -0800303 * {@inheritDoc}
304 */
305 public boolean isKnownTest(TestIdentifier testDef) {
306 return mTests.contains(testDef);
307 }
308
309 /**
Brett Chabotef5a6042011-01-19 19:54:14 -0800310 * {@inheritDoc}
311 */
312 public boolean isKnownTestClass(String className) {
313 return mTestClasses.contains(className);
314 }
315
316 /**
Brett Chabot82d9daf2010-10-20 20:07:14 -0700317 * Add a {@link TestDef} to the list of tests in this package.
318 *
319 * @param testdef
320 */
321 void addTest(TestIdentifier testDef) {
322 mTests.add(testDef);
Brett Chabotef5a6042011-01-19 19:54:14 -0800323 mTestClasses.add(testDef.getClassName());
Brett Chabot82d9daf2010-10-20 20:07:14 -0700324 }
325
326 /**
327 * Get the collection of tests in this test package.
Brett Chabot82d9daf2010-10-20 20:07:14 -0700328 */
Brett Chabot1dcb9a52011-02-10 20:26:57 -0800329 @Override
330 public Collection<TestIdentifier> getTests() {
Brett Chabot82d9daf2010-10-20 20:07:14 -0700331 return mTests;
332 }
Brett Chabot58c43a82011-09-13 14:13:57 -0700333
334 /**
335 * {@inheritDoc}
336 */
337 @Override
338 public String getDigest() {
339 return mDigest;
340 }
341
342 /**
343 * Generate a sha1sum digest for a file.
344 * <p/>
345 * Exposed for unit testing.
346 *
347 * @param fileDir the directory of the file
348 * @param fileName the name of the file
349 * @return a hex {@link String} of the digest
350 */
Brett Chabot13638ab2011-10-16 13:59:03 -0700351 String generateDigest(File fileDir, String fileName) {
Brett Chabot58c43a82011-09-13 14:13:57 -0700352 final String algorithm = "SHA-1";
353 InputStream fileStream = null;
Brett Chabot13638ab2011-10-16 13:59:03 -0700354 DigestInputStream d = null;
Brett Chabot58c43a82011-09-13 14:13:57 -0700355 try {
356 fileStream = getFileStream(fileDir, fileName);
357 MessageDigest md = MessageDigest.getInstance(algorithm);
358 d = new DigestInputStream(fileStream, md);
359 byte[] buffer = new byte[8196];
360 while (d.read(buffer) != -1);
361 return toHexString(md.digest());
362 } catch (NoSuchAlgorithmException e) {
363 return algorithm + " not found";
364 } catch (IOException e) {
365 CLog.e(e);
366 } finally {
367 StreamUtil.closeStream(d);
368 StreamUtil.closeStream(fileStream);
369 }
370 return "failed to generate digest";
371 }
372
373 /**
374 * Retrieve an input stream for given file
375 * <p/>
376 * Exposed so unit tests can mock.
377 */
378 InputStream getFileStream(File fileDir, String fileName) throws FileNotFoundException {
379 InputStream fileStream;
380 fileStream = new BufferedInputStream(new FileInputStream(new File(fileDir, fileName)));
381 return fileStream;
382 }
383
384 /**
385 * Convert the given byte array into a lowercase hex string.
386 *
387 * @param arr The array to convert.
388 * @return The hex encoded string.
389 */
390 private String toHexString(byte[] arr) {
391 StringBuffer buf = new StringBuffer(arr.length * 2);
392 for (byte b : arr) {
393 buf.append(String.format("%02x", b & 0xFF));
394 }
395 return buf.toString();
396 }
Brett Chabot3add9162010-09-12 17:23:05 -0700397}