blob: 58f2c00d68732af25994624f0e3d4868833dd5e5 [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.ArrayList;
35import java.util.Collection;
Brett Chabotef5a6042011-01-19 19:54:14 -080036import java.util.LinkedHashSet;
Brett Chabot3add9162010-09-12 17:23:05 -070037
38/**
39 * Container for CTS test info.
40 * <p/>
41 * Knows how to translate this info into a runnable {@link IRemoteTest}.
42 */
Brett Chabot4f8143c2010-12-14 18:29:44 -080043class TestPackageDef implements ITestPackageDef {
Brett Chabot3add9162010-09-12 17:23:05 -070044
45 private static final String LOG_TAG = "TestPackageDef";
Brett Chabot584d2b92011-02-03 17:56:49 -080046 private static final String SIGNATURE_TEST_METHOD = "testSignature";
47 private static final String SIGNATURE_TEST_CLASS = "android.tests.sigtest.SimpleSignatureTest";
Brett Chabot3add9162010-09-12 17:23:05 -070048
49 private String mUri = null;
50 private String mAppNameSpace = null;
51 private String mName = null;
52 private String mRunner = null;
53 private boolean mIsHostSideTest = false;
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -070054 private boolean mIsVMHostTest = false;
Brett Chabot3add9162010-09-12 17:23:05 -070055 private String mJarPath = null;
56 private boolean mIsSignatureTest = false;
57 private boolean mIsReferenceAppTest = false;
Brett Chabota0f443c2011-02-04 13:57:55 -080058 private String mPackageToTest = null;
59 private String mApkToTestName = null;
Brian Carlstrom022aff42011-05-17 23:16:51 -070060 private String mTestPackageName = null;
Brett Chabot58c43a82011-09-13 14:13:57 -070061 private String mDigest = null;
Brett Chabot3add9162010-09-12 17:23:05 -070062
Brett Chabotef5a6042011-01-19 19:54:14 -080063 // use a LinkedHashSet for predictable iteration insertion-order, and fast lookups
64 private Collection<TestIdentifier> mTests = new LinkedHashSet<TestIdentifier>();
65 // also maintain an index of known test classes
66 private Collection<String> mTestClasses = new LinkedHashSet<String>();
Brett Chabot4f8143c2010-12-14 18:29:44 -080067
Brett Chabot3add9162010-09-12 17:23:05 -070068 void setUri(String uri) {
69 mUri = uri;
70 }
71
72 /**
Brett Chabot4f8143c2010-12-14 18:29:44 -080073 * {@inheritDoc}
Brett Chabot3add9162010-09-12 17:23:05 -070074 */
75 public String getUri() {
76 return mUri;
77 }
78
79 void setAppNameSpace(String appNameSpace) {
80 mAppNameSpace = appNameSpace;
81 }
82
83 String getAppNameSpace() {
84 return mAppNameSpace;
85 }
86
87 void setName(String name) {
88 mName = name;
89 }
90
Brett Chabot58c43a82011-09-13 14:13:57 -070091 /**
92 * {@inheritDoc}
93 */
94 @Override
95 public String getName() {
Brett Chabot3add9162010-09-12 17:23:05 -070096 return mName;
97 }
98
99 void setRunner(String runnerName) {
100 mRunner = runnerName;
101 }
102
103 String getRunner() {
104 return mRunner;
105 }
106
107 void setIsHostSideTest(boolean hostSideTest) {
108 mIsHostSideTest = hostSideTest;
109
110 }
111
112 boolean isHostSideTest() {
113 return mIsHostSideTest;
114 }
115
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700116 void setIsVMHostTest(boolean vmHostTest) {
117 mIsVMHostTest = vmHostTest;
118
119 }
120
121 boolean isVMHostTest() {
122 return mIsVMHostTest;
123 }
Brett Chabot3add9162010-09-12 17:23:05 -0700124 void setJarPath(String jarPath) {
125 mJarPath = jarPath;
126 }
127
128 String getJarPath() {
129 return mJarPath;
130 }
131
132 void setIsSignatureCheck(boolean isSignatureCheckTest) {
133 mIsSignatureTest = isSignatureCheckTest;
134 }
135
136 boolean isSignatureCheck() {
137 return mIsSignatureTest;
138 }
139
140 void setIsReferenceApp(boolean isReferenceApp) {
141 mIsReferenceAppTest = isReferenceApp;
142 }
143
144 boolean isReferenceApp() {
145 return mIsReferenceAppTest;
146 }
147
Brett Chabota0f443c2011-02-04 13:57:55 -0800148 void setPackageToTest(String packageName) {
149 mPackageToTest = packageName;
150 }
151
Brian Carlstrom022aff42011-05-17 23:16:51 -0700152 void setTestPackageName(String testPackageName) {
153 mTestPackageName = testPackageName;
154 }
155
Brett Chabota0f443c2011-02-04 13:57:55 -0800156 void setApkToTest(String apkName) {
157 mApkToTestName = apkName;
158 }
159
Brett Chabot3add9162010-09-12 17:23:05 -0700160 /**
Brett Chabot4f8143c2010-12-14 18:29:44 -0800161 * {@inheritDoc}
Brett Chabot3add9162010-09-12 17:23:05 -0700162 */
Brett Chabotef5a6042011-01-19 19:54:14 -0800163 public IRemoteTest createTest(File testCaseDir, String className, String methodName) {
Brett Chabot3add9162010-09-12 17:23:05 -0700164 if (mIsHostSideTest) {
Brett Chabot82d9daf2010-10-20 20:07:14 -0700165 Log.d(LOG_TAG, String.format("Creating host test for %s", mName));
166 JarHostTest hostTest = new JarHostTest();
Brett Chabot58c43a82011-09-13 14:13:57 -0700167 hostTest.setRunName(getUri());
Brett Chabotf4bec732011-04-19 17:31:06 -0700168 hostTest.setJarFileName(mJarPath);
Brett Chabotef5a6042011-01-19 19:54:14 -0800169 hostTest.setTests(filterTests(mTests, className, methodName));
Brett Chabot58c43a82011-09-13 14:13:57 -0700170 mDigest = generateDigest(testCaseDir, mJarPath);
Brett Chabot82d9daf2010-10-20 20:07:14 -0700171 return hostTest;
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700172 } else if (mIsVMHostTest) {
173 Log.d(LOG_TAG, String.format("Creating vm host test for %s", mName));
174 VMHostTest vmHostTest = new VMHostTest();
Brett Chabot58c43a82011-09-13 14:13:57 -0700175 vmHostTest.setRunName(getUri());
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700176 vmHostTest.setJarFileName(mJarPath);
177 vmHostTest.setTests(filterTests(mTests, className, methodName));
Brett Chabot58c43a82011-09-13 14:13:57 -0700178 mDigest = generateDigest(testCaseDir, mJarPath);
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700179 return vmHostTest;
Brett Chabot3add9162010-09-12 17:23:05 -0700180 } else if (mIsSignatureTest) {
Brett Chabot584d2b92011-02-03 17:56:49 -0800181 // TODO: hardcode the runner/class/method for now, since current package xml
182 // points to specialized instrumentation. Eventually this special case for signatureTest
183 // can be removed, and it can be treated just like a normal InstrumentationTest
184 Log.d(LOG_TAG, String.format("Creating signature test %s", mName));
Brett Chabotf4bec732011-04-19 17:31:06 -0700185 InstrumentationApkTest instrTest = new InstrumentationApkTest();
Brett Chabot584d2b92011-02-03 17:56:49 -0800186 instrTest.setPackageName(mAppNameSpace);
187 instrTest.setRunnerName("android.test.InstrumentationTestRunner");
188 instrTest.setClassName(SIGNATURE_TEST_CLASS);
189 instrTest.setMethodName(SIGNATURE_TEST_METHOD);
190 // add signature test to list of known tests
191 addTest(new TestIdentifier(SIGNATURE_TEST_CLASS, SIGNATURE_TEST_METHOD));
192 // mName means 'apk file name' for instrumentation tests
Brett Chabotf4bec732011-04-19 17:31:06 -0700193 instrTest.addInstallApk(String.format("%s.apk", mName), mAppNameSpace);
Brett Chabot58c43a82011-09-13 14:13:57 -0700194 mDigest = generateDigest(testCaseDir, String.format("%s.apk", mName));
Brett Chabot584d2b92011-02-03 17:56:49 -0800195 return instrTest;
Brett Chabot3add9162010-09-12 17:23:05 -0700196 } else if (mIsReferenceAppTest) {
Brett Chabota0f443c2011-02-04 13:57:55 -0800197 // a reference app test is just a InstrumentationTest with one extra apk to install
Brett Chabot4263db42011-04-15 13:51:48 -0700198 InstrumentationApkTest instrTest = new InstrumentationApkTest();
199 instrTest.addInstallApk(String.format("%s.apk", mApkToTestName), mPackageToTest);
Brett Chabot58c43a82011-09-13 14:13:57 -0700200 return setInstrumentationTest(className, methodName, instrTest, testCaseDir);
Brett Chabota0f443c2011-02-04 13:57:55 -0800201 } else {
202 Log.d(LOG_TAG, String.format("Creating instrumentation test for %s", mName));
Brett Chabot4263db42011-04-15 13:51:48 -0700203 InstrumentationApkTest instrTest = new InstrumentationApkTest();
Brett Chabot58c43a82011-09-13 14:13:57 -0700204 return setInstrumentationTest(className, methodName, instrTest, testCaseDir);
Brett Chabot3add9162010-09-12 17:23:05 -0700205 }
206 }
Brett Chabot82d9daf2010-10-20 20:07:14 -0700207
Brett Chabot58c43a82011-09-13 14:13:57 -0700208
209
Brett Chabot82d9daf2010-10-20 20:07:14 -0700210 /**
Brett Chabot4263db42011-04-15 13:51:48 -0700211 * Populates given {@link InstrumentationApkTest} with data from the package xml
Brett Chabota0f443c2011-02-04 13:57:55 -0800212 *
213 * @param testCaseDir
214 * @param className
215 * @param methodName
216 * @param instrTest
217 * @return the populated {@link InstrumentationTest} or <code>null</code>
218 */
Brett Chabot58c43a82011-09-13 14:13:57 -0700219 private InstrumentationTest setInstrumentationTest(String className,
220 String methodName, InstrumentationApkTest instrTest, File testCaseDir) {
221 instrTest.setRunName(getUri());
Brett Chabota0f443c2011-02-04 13:57:55 -0800222 instrTest.setPackageName(mAppNameSpace);
223 instrTest.setRunnerName(mRunner);
Brian Carlstrom022aff42011-05-17 23:16:51 -0700224 instrTest.setTestPackageName(mTestPackageName);
Brett Chabota0f443c2011-02-04 13:57:55 -0800225 instrTest.setClassName(className);
226 instrTest.setMethodName(methodName);
227 // mName means 'apk file name' for instrumentation tests
Brett Chabot4263db42011-04-15 13:51:48 -0700228 instrTest.addInstallApk(String.format("%s.apk", mName), mAppNameSpace);
Brett Chabot58c43a82011-09-13 14:13:57 -0700229 mDigest = generateDigest(testCaseDir, String.format("%s.apk", mName));
Brett Chabot4263db42011-04-15 13:51:48 -0700230 if (mTests.size() > 1000) {
231 // TODO: hack, large test suites can take longer to collect tests, increase timeout
232 instrTest.setCollectsTestsShellTimeout(10*60*1000);
Brett Chabota0f443c2011-02-04 13:57:55 -0800233 }
Brett Chabota0f443c2011-02-04 13:57:55 -0800234 return instrTest;
235 }
236
237 /**
Brett Chabotef5a6042011-01-19 19:54:14 -0800238 * Filter the tests to run based on class and method name
239 *
240 * @param tests the full set of tests in package
241 * @param className the test class name filter. <code>null</code> to run all test classes
242 * @param methodName the test method name. <code>null</code> to run all test methods
243 * @return the filtered collection of tests
244 */
245 private Collection<TestIdentifier> filterTests(Collection<TestIdentifier> tests,
246 String className, String methodName) {
247 Collection<TestIdentifier> filteredTests = new ArrayList<TestIdentifier>(tests.size());
248 for (TestIdentifier test : tests) {
249 if (className == null || test.getClassName().equals(className)) {
250 if (methodName == null || test.getTestName().equals(methodName)) {
251 filteredTests.add(test);
252 }
253 }
254 }
255 return filteredTests;
256 }
257
258 /**
Brett Chabot4f8143c2010-12-14 18:29:44 -0800259 * {@inheritDoc}
260 */
261 public boolean isKnownTest(TestIdentifier testDef) {
262 return mTests.contains(testDef);
263 }
264
265 /**
Brett Chabotef5a6042011-01-19 19:54:14 -0800266 * {@inheritDoc}
267 */
268 public boolean isKnownTestClass(String className) {
269 return mTestClasses.contains(className);
270 }
271
272 /**
Brett Chabot82d9daf2010-10-20 20:07:14 -0700273 * Add a {@link TestDef} to the list of tests in this package.
274 *
275 * @param testdef
276 */
277 void addTest(TestIdentifier testDef) {
278 mTests.add(testDef);
Brett Chabotef5a6042011-01-19 19:54:14 -0800279 mTestClasses.add(testDef.getClassName());
Brett Chabot82d9daf2010-10-20 20:07:14 -0700280 }
281
282 /**
283 * Get the collection of tests in this test package.
Brett Chabot82d9daf2010-10-20 20:07:14 -0700284 */
Brett Chabot1dcb9a52011-02-10 20:26:57 -0800285 @Override
286 public Collection<TestIdentifier> getTests() {
Brett Chabot82d9daf2010-10-20 20:07:14 -0700287 return mTests;
288 }
Brett Chabot58c43a82011-09-13 14:13:57 -0700289
290 /**
291 * {@inheritDoc}
292 */
293 @Override
294 public String getDigest() {
295 return mDigest;
296 }
297
298 /**
299 * Generate a sha1sum digest for a file.
300 * <p/>
301 * Exposed for unit testing.
302 *
303 * @param fileDir the directory of the file
304 * @param fileName the name of the file
305 * @return a hex {@link String} of the digest
306 */
307 String generateDigest(File fileDir, String fileName) {
308 final String algorithm = "SHA-1";
309 InputStream fileStream = null;
310 DigestInputStream d = null;
311 try {
312 fileStream = getFileStream(fileDir, fileName);
313 MessageDigest md = MessageDigest.getInstance(algorithm);
314 d = new DigestInputStream(fileStream, md);
315 byte[] buffer = new byte[8196];
316 while (d.read(buffer) != -1);
317 return toHexString(md.digest());
318 } catch (NoSuchAlgorithmException e) {
319 return algorithm + " not found";
320 } catch (IOException e) {
321 CLog.e(e);
322 } finally {
323 StreamUtil.closeStream(d);
324 StreamUtil.closeStream(fileStream);
325 }
326 return "failed to generate digest";
327 }
328
329 /**
330 * Retrieve an input stream for given file
331 * <p/>
332 * Exposed so unit tests can mock.
333 */
334 InputStream getFileStream(File fileDir, String fileName) throws FileNotFoundException {
335 InputStream fileStream;
336 fileStream = new BufferedInputStream(new FileInputStream(new File(fileDir, fileName)));
337 return fileStream;
338 }
339
340 /**
341 * Convert the given byte array into a lowercase hex string.
342 *
343 * @param arr The array to convert.
344 * @return The hex encoded string.
345 */
346 private String toHexString(byte[] arr) {
347 StringBuffer buf = new StringBuffer(arr.length * 2);
348 for (byte b : arr) {
349 buf.append(String.format("%02x", b & 0xFF));
350 }
351 return buf.toString();
352 }
Brett Chabot3add9162010-09-12 17:23:05 -0700353}