• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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  */
16 
17 package com.android.cts.tradefed.testtype;
18 
19 import com.android.cts.util.AbiUtils;
20 import com.android.ddmlib.Log.LogLevel;
21 import com.android.ddmlib.testrunner.TestIdentifier;
22 import com.android.tradefed.log.LogUtil.CLog;
23 import com.android.tradefed.testtype.IAbi;
24 import com.android.tradefed.testtype.IRemoteTest;
25 import com.android.tradefed.testtype.InstrumentationTest;
26 import com.android.tradefed.util.StreamUtil;
27 
28 import java.io.BufferedInputStream;
29 import java.io.File;
30 import java.io.FileInputStream;
31 import java.io.FileNotFoundException;
32 import java.io.IOException;
33 import java.io.InputStream;
34 import java.security.DigestInputStream;
35 import java.security.MessageDigest;
36 import java.security.NoSuchAlgorithmException;
37 import java.util.Collection;
38 import java.util.LinkedHashSet;
39 
40 /**
41  * Container for CTS test info.
42  * <p/>
43  * Knows how to translate this info into a runnable {@link IRemoteTest}.
44  */
45 class TestPackageDef implements ITestPackageDef {
46 
47     public static final String HOST_SIDE_ONLY_TEST = "hostSideOnly";
48     public static final String NATIVE_TEST = "native";
49     public static final String WRAPPED_NATIVE_TEST = "wrappednative";
50     public static final String VM_HOST_TEST = "vmHostTest";
51     public static final String DEQP_TEST = "deqpTest";
52     public static final String ACCESSIBILITY_TEST =
53             "com.android.cts.tradefed.testtype.AccessibilityTestRunner";
54     public static final String ACCESSIBILITY_SERVICE_TEST =
55             "com.android.cts.tradefed.testtype.AccessibilityServiceTestRunner";
56     public static final String PRINT_TEST =
57             "com.android.cts.tradefed.testtype.PrintTestRunner";
58     public static final String DISPLAY_TEST =
59             "com.android.cts.tradefed.testtype.DisplayTestRunner";
60     public static final String UIAUTOMATOR_TEST = "uiAutomator";
61     public static final String JUNIT_DEVICE_TEST = "jUnitDeviceTest";
62 
63     private String mAppPackageName = null;
64     private String mAppNameSpace = null;
65     private String mName = null;
66     private String mRunner = null;
67     private String mTestType = null;
68     private String mJarPath = null;
69     private String mRunTimeArgs = null;
70     private String mTestPackageName = null;
71     private String mDigest = null;
72     private IAbi mAbi = null;
73 
74     // use a LinkedHashSet for predictable iteration insertion-order, and fast
75     // lookups
76     private Collection<TestIdentifier> mTests = new LinkedHashSet<TestIdentifier>();
77     // also maintain an index of known test classes
78     private Collection<String> mTestClasses = new LinkedHashSet<String>();
79 
80     // dynamic options, not parsed from package xml
81     private String mClassName;
82     private String mMethodName;
83     private TestFilter mTestFilter = new TestFilter();
84     private String mTargetBinaryName;
85     private String mTargetNameSpace;
86     // only timeout per package is supported. To change this to method granularity,
87     // test invocation should be done in method level.
88     // So for now, only max timeout for the package is used.
89     private int mTimeoutInMins = -1;
90 
91     @Override
getAbi()92     public IAbi getAbi() {
93         return mAbi;
94     }
95 
96     /**
97      * @param abi the ABI to run this package on
98      */
setAbi(IAbi abi)99     public void setAbi(IAbi abi) {
100         mAbi = abi;
101     }
102 
103     /**
104      * @return unique id representing this test package for this ABI.
105      */
106     @Override
getId()107     public String getId() {
108         return AbiUtils.createId(getAbi().getName(), getAppPackageName());
109     }
110 
setAppPackageName(String appPackageName)111     void setAppPackageName(String appPackageName) {
112         mAppPackageName = appPackageName;
113     }
114 
getAppPackageName()115     String getAppPackageName() {
116         return mAppPackageName;
117     }
118 
setRunTimeArgs(String runTimeArgs)119     void setRunTimeArgs(String runTimeArgs) {
120         mRunTimeArgs = runTimeArgs;
121     }
122 
setAppNameSpace(String appNameSpace)123     void setAppNameSpace(String appNameSpace) {
124         mAppNameSpace = appNameSpace;
125     }
126 
getAppNameSpace()127     String getAppNameSpace() {
128         return mAppNameSpace;
129     }
130 
setName(String name)131     void setName(String name) {
132         mName = name;
133     }
134 
135     /**
136      * {@inheritDoc}
137      */
138     @Override
getName()139     public String getName() {
140         return mName;
141     }
142 
setRunner(String runnerName)143     void setRunner(String runnerName) {
144         mRunner = runnerName;
145     }
146 
getRunner()147     String getRunner() {
148         return mRunner;
149     }
150 
setTestType(String testType)151     void setTestType(String testType) {
152         mTestType = testType;
153     }
154 
getTestType()155     String getTestType() {
156         return mTestType;
157     }
158 
setJarPath(String jarPath)159     void setJarPath(String jarPath) {
160         mJarPath = jarPath;
161     }
162 
getJarPath()163     String getJarPath() {
164         return mJarPath;
165     }
166 
setTestPackageName(String testPackageName)167     void setTestPackageName(String testPackageName) {
168         mTestPackageName = testPackageName;
169     }
170 
setTargetBinaryName(String targetBinaryName)171     void setTargetBinaryName(String targetBinaryName) {
172         mTargetBinaryName = targetBinaryName;
173     }
174 
setTargetNameSpace(String targetNameSpace)175     void setTargetNameSpace(String targetNameSpace) {
176         mTargetNameSpace = targetNameSpace;
177     }
178 
179     @Override
getTargetApkName()180     public String getTargetApkName() {
181        if (mTargetBinaryName != null && !mTargetBinaryName.isEmpty()) {
182            return String.format("%s.apk", mTargetBinaryName);
183        }
184        return null;
185     }
186 
187     @Override
getTargetPackageName()188     public String getTargetPackageName() {
189         if (mTargetNameSpace != null && mTargetNameSpace.isEmpty()) {
190             return null;
191         }
192         return mTargetNameSpace;
193     }
194 
195     /**
196      * {@inheritDoc}
197      */
198     @Override
setTestFilter(TestFilter testFilter)199     public void setTestFilter(TestFilter testFilter) {
200         mTestFilter = testFilter;
201     }
202 
203     /**
204      * {@inheritDoc}
205      */
206     @Override
setClassName(String className, String methodName)207     public void setClassName(String className, String methodName) {
208         mClassName = className;
209         mMethodName = methodName;
210     }
211 
212     /**
213      * {@inheritDoc}
214      */
215     @Override
createTest(File testCaseDir)216     public IRemoteTest createTest(File testCaseDir) {
217         mTestFilter.setTestInclusion(mClassName, mMethodName);
218         mTests = filterTests();
219 
220         if (HOST_SIDE_ONLY_TEST.equals(mTestType)) {
221             CLog.d("Creating host test for %s", mName);
222             JarHostTest hostTest = new JarHostTest();
223             if (mTimeoutInMins >= 0) {
224                 CLog.d("Setting new timeout to " + mTimeoutInMins + " mins");
225                 hostTest.setTimeout(mTimeoutInMins * 60 * 1000);
226             }
227             hostTest.setRunName(mAppPackageName);
228             hostTest.setJarFileName(mJarPath);
229             hostTest.setTests(mTests);
230             hostTest.setAbi(mAbi);
231             mDigest = generateDigest(testCaseDir, mJarPath);
232             return hostTest;
233         } else if (VM_HOST_TEST.equals(mTestType)) {
234             CLog.d("Creating vm host test for %s", mName);
235             VMHostTest vmHostTest = new VMHostTest();
236             vmHostTest.setRunName(mAppPackageName);
237             vmHostTest.setJarFileName(mJarPath);
238             vmHostTest.setTests(mTests);
239             vmHostTest.setAbi(mAbi);
240             mDigest = generateDigest(testCaseDir, mJarPath);
241             return vmHostTest;
242         } else if (DEQP_TEST.equals(mTestType)) {
243             DeqpTestRunner deqpTest = new DeqpTestRunner(mAppPackageName, mName, mTests);
244             deqpTest.setAbi(mAbi);
245             return deqpTest;
246         } else if (NATIVE_TEST.equals(mTestType)) {
247             GeeTest geeTest = new GeeTest(mAppPackageName, mName);
248             geeTest.setAbi(mAbi);
249             return geeTest;
250         } else if (WRAPPED_NATIVE_TEST.equals(mTestType)) {
251             CLog.d("Creating new wrapped native test for %s", mName);
252             WrappedGTest wrappedGeeTest = new WrappedGTest(mAppNameSpace, mAppPackageName, mName, mRunner);
253             wrappedGeeTest.setAbi(mAbi);
254             return wrappedGeeTest;
255         } else if (ACCESSIBILITY_TEST.equals(mTestType)) {
256             AccessibilityTestRunner test = new AccessibilityTestRunner();
257             return setInstrumentationTest(test, testCaseDir);
258         } else if (PRINT_TEST.equals(mTestType)) {
259             PrintTestRunner test = new PrintTestRunner();
260             return setPrintTest(test, testCaseDir);
261         } else if (ACCESSIBILITY_SERVICE_TEST.equals(mTestType)) {
262             @SuppressWarnings("deprecation")
263             AccessibilityServiceTestRunner test = new AccessibilityServiceTestRunner();
264             return setInstrumentationTest(test, testCaseDir);
265         } else if (DISPLAY_TEST.equals(mTestType)) {
266             DisplayTestRunner test = new DisplayTestRunner();
267             return setInstrumentationTest(test, testCaseDir);
268         } else if (UIAUTOMATOR_TEST.equals(mTestType)) {
269             UiAutomatorJarTest uiautomatorTest = new UiAutomatorJarTest();
270             return setUiAutomatorTest(uiautomatorTest);
271         } else if (JUNIT_DEVICE_TEST.equals(mTestType)){
272             CLog.d("Creating JUnit device test %s", mName);
273             JUnitDeviceTest jUnitDeviceTest = new JUnitDeviceTest();
274             jUnitDeviceTest.setRunName(mAppPackageName);
275             jUnitDeviceTest.addTestJarFileName(mJarPath);
276             jUnitDeviceTest.addRunTimeArgs(mRunTimeArgs);
277             jUnitDeviceTest.setTests(mTests);
278             jUnitDeviceTest.setAbi(mAbi);
279             mDigest = generateDigest(testCaseDir, mJarPath);
280             return jUnitDeviceTest;
281         } else {
282             CLog.d("Creating instrumentation test for %s", mName);
283             CtsInstrumentationApkTest instrTest = new CtsInstrumentationApkTest();
284             if (mTimeoutInMins >= 0) {
285                 // as timeout cannot be set for each test,
286                 // increase the time-out of the whole package
287                 CLog.d("Setting new timeout to " + mTimeoutInMins + " mins");
288                 instrTest.setTestTimeout(mTimeoutInMins * 60 * 1000);
289             }
290             return setInstrumentationTest(instrTest, testCaseDir);
291         }
292     }
293 
setPrintTest(PrintTestRunner printTest, File testCaseDir)294     private PrintTestRunner setPrintTest(PrintTestRunner printTest,
295             File testCaseDir) {
296         printTest.setRunName(mAppPackageName);
297         printTest.setPackageName(mAppNameSpace);
298         printTest.setRunnerName(mRunner);
299         printTest.setTestPackageName(mTestPackageName);
300         printTest.setClassName(mClassName);
301         printTest.setMethodName(mMethodName);
302         printTest.setAbi(mAbi);
303         mDigest = generateDigest(testCaseDir, String.format("%s.apk", mName));
304         return printTest;
305     }
306 
307     /**
308      * Populates given {@link CtsInstrumentationApkTest} with data from the package xml.
309      *
310      * @param testCaseDir
311      * @param instrTest
312      * @return the populated {@link InstrumentationTest} or <code>null</code>
313      */
setInstrumentationTest(CtsInstrumentationApkTest instrTest, File testCaseDir)314     private InstrumentationTest setInstrumentationTest(CtsInstrumentationApkTest instrTest,
315             File testCaseDir) {
316         instrTest.setRunName(mAppPackageName);
317         instrTest.setPackageName(mAppNameSpace);
318         instrTest.setRunnerName(mRunner);
319         instrTest.setTestPackageName(mTestPackageName);
320         instrTest.setClassName(mClassName);
321         instrTest.setMethodName(mMethodName);
322         instrTest.setAbi(mAbi);
323         instrTest.setTestsToRun(mTests, false
324             /* force batch mode off to always run using testFile */);
325         instrTest.setReRunUsingTestFile(true);
326         // mName means 'apk file name' for instrumentation tests
327         instrTest.addInstallApk(String.format("%s.apk", mName), mAppNameSpace);
328         mDigest = generateDigest(testCaseDir, String.format("%s.apk", mName));
329         if (mTests.size() > 1000) {
330             // TODO: hack, large test suites can take longer to collect tests, increase timeout
331             instrTest.setCollectsTestsShellTimeout(10 * 60 * 1000);
332         }
333         return instrTest;
334     }
335 
336     /**
337      * Populates given {@link UiAutomatorJarTest} with data from the package xml.
338      *
339      * @param uiautomatorTest
340      * @return the populated {@link UiAutomatorJarTest} or <code>null</code>
341      */
342     @SuppressWarnings("deprecation")
setUiAutomatorTest(UiAutomatorJarTest uiautomatorTest)343     private IRemoteTest setUiAutomatorTest(UiAutomatorJarTest uiautomatorTest) {
344         uiautomatorTest.setInstallArtifacts(getJarPath());
345         if (mClassName != null) {
346             if (mMethodName != null) {
347                 CLog.logAndDisplay(LogLevel.WARN, "ui automator tests don't currently support" +
348                         "running  individual methods");
349             }
350             uiautomatorTest.addClassName(mClassName);
351         } else {
352             uiautomatorTest.addClassNames(mTestClasses);
353         }
354         uiautomatorTest.setRunName(mAppPackageName);
355         uiautomatorTest.setCaptureLogs(false);
356         return uiautomatorTest;
357     }
358 
359     /**
360      * Filter the tests to run based on list of included/excluded tests, class and method name.
361      *
362      * @return the filtered collection of tests
363      */
filterTests()364     private Collection<TestIdentifier> filterTests() {
365         mTestFilter.setTestInclusion(mClassName, mMethodName);
366         return mTestFilter.filter(mTests);
367     }
368 
isKnownTestClass(String className)369     boolean isKnownTestClass(String className) {
370         return mTestClasses.contains(className);
371     }
372 
373     /**
374      * Add a {@link TestIdentifier} to the list of tests in this package.
375      *
376      * @param testDef
377      * @param timeout in mins
378      */
addTest(TestIdentifier testDef, int timeout)379     void addTest(TestIdentifier testDef, int timeout) {
380         mTests.add(testDef);
381         mTestClasses.add(testDef.getClassName());
382         // 0 means no timeout, so keep 0 if already is.
383         if ((timeout > mTimeoutInMins) && (mTimeoutInMins != 0)) {
384             mTimeoutInMins = timeout;
385         }
386     }
387 
388     /**
389      * {@inheritDoc}
390      */
391     @Override
getTests()392     public Collection<TestIdentifier> getTests() {
393         return mTests;
394     }
395 
396     /**
397      * {@inheritDoc}
398      */
399     @Override
getDigest()400     public String getDigest() {
401         return mDigest;
402     }
403 
404     /**
405      * Generate a sha1sum digest for a file.
406      * <p/>
407      * Exposed for unit testing.
408      *
409      * @param fileDir the directory of the file
410      * @param fileName the name of the file
411      * @return a hex {@link String} of the digest
412      */
generateDigest(File fileDir, String fileName)413     String generateDigest(File fileDir, String fileName) {
414         final String algorithm = "SHA-1";
415         InputStream fileStream = null;
416         DigestInputStream d = null;
417         try {
418             fileStream = getFileStream(fileDir, fileName);
419             MessageDigest md = MessageDigest.getInstance(algorithm);
420             d = new DigestInputStream(fileStream, md);
421             byte[] buffer = new byte[8196];
422             while (d.read(buffer) != -1) {
423             }
424             return toHexString(md.digest());
425         } catch (NoSuchAlgorithmException e) {
426             return algorithm + " not found";
427         } catch (IOException e) {
428             CLog.e(e);
429         } finally {
430             StreamUtil.closeStream(d);
431             StreamUtil.closeStream(fileStream);
432         }
433         return "failed to generate digest";
434     }
435 
436     /**
437      * Retrieve an input stream for given file
438      * <p/>
439      * Exposed so unit tests can mock.
440      */
getFileStream(File fileDir, String fileName)441     InputStream getFileStream(File fileDir, String fileName) throws FileNotFoundException {
442         InputStream fileStream;
443         fileStream = new BufferedInputStream(new FileInputStream(new File(fileDir, fileName)));
444         return fileStream;
445     }
446 
447     /**
448      * Convert the given byte array into a lowercase hex string.
449      *
450      * @param arr The array to convert.
451      * @return The hex encoded string.
452      */
toHexString(byte[] arr)453     private String toHexString(byte[] arr) {
454         StringBuilder buf = new StringBuilder(arr.length * 2);
455         for (byte b : arr) {
456             buf.append(String.format("%02x", b & 0xFF));
457         }
458         return buf.toString();
459     }
460 
461     @Override
compareTo(ITestPackageDef testPackageDef)462     public int compareTo(ITestPackageDef testPackageDef) {
463         return getId().compareTo(testPackageDef.getId());
464     }
465 }
466