Home | History | Annotate | Download | only in testtype
      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
     92     public IAbi getAbi() {
     93         return mAbi;
     94     }
     95 
     96     /**
     97      * @param abi the ABI to run this package on
     98      */
     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
    107     public String getId() {
    108         return AbiUtils.createId(getAbi().getName(), getAppPackageName());
    109     }
    110 
    111     void setAppPackageName(String appPackageName) {
    112         mAppPackageName = appPackageName;
    113     }
    114 
    115     String getAppPackageName() {
    116         return mAppPackageName;
    117     }
    118 
    119     void setRunTimeArgs(String runTimeArgs) {
    120         mRunTimeArgs = runTimeArgs;
    121     }
    122 
    123     void setAppNameSpace(String appNameSpace) {
    124         mAppNameSpace = appNameSpace;
    125     }
    126 
    127     String getAppNameSpace() {
    128         return mAppNameSpace;
    129     }
    130 
    131     void setName(String name) {
    132         mName = name;
    133     }
    134 
    135     /**
    136      * {@inheritDoc}
    137      */
    138     @Override
    139     public String getName() {
    140         return mName;
    141     }
    142 
    143     void setRunner(String runnerName) {
    144         mRunner = runnerName;
    145     }
    146 
    147     String getRunner() {
    148         return mRunner;
    149     }
    150 
    151     void setTestType(String testType) {
    152         mTestType = testType;
    153     }
    154 
    155     String getTestType() {
    156         return mTestType;
    157     }
    158 
    159     void setJarPath(String jarPath) {
    160         mJarPath = jarPath;
    161     }
    162 
    163     String getJarPath() {
    164         return mJarPath;
    165     }
    166 
    167     void setTestPackageName(String testPackageName) {
    168         mTestPackageName = testPackageName;
    169     }
    170 
    171     void setTargetBinaryName(String targetBinaryName) {
    172         mTargetBinaryName = targetBinaryName;
    173     }
    174 
    175     void setTargetNameSpace(String targetNameSpace) {
    176         mTargetNameSpace = targetNameSpace;
    177     }
    178 
    179     @Override
    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
    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
    199     public void setTestFilter(TestFilter testFilter) {
    200         mTestFilter = testFilter;
    201     }
    202 
    203     /**
    204      * {@inheritDoc}
    205      */
    206     @Override
    207     public void setClassName(String className, String methodName) {
    208         mClassName = className;
    209         mMethodName = methodName;
    210     }
    211 
    212     /**
    213      * {@inheritDoc}
    214      */
    215     @Override
    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 
    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      */
    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")
    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      */
    364     private Collection<TestIdentifier> filterTests() {
    365         mTestFilter.setTestInclusion(mClassName, mMethodName);
    366         return mTestFilter.filter(mTests);
    367     }
    368 
    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      */
    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
    392     public Collection<TestIdentifier> getTests() {
    393         return mTests;
    394     }
    395 
    396     /**
    397      * {@inheritDoc}
    398      */
    399     @Override
    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      */
    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      */
    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      */
    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
    462     public int compareTo(ITestPackageDef testPackageDef) {
    463         return getId().compareTo(testPackageDef.getId());
    464     }
    465 }
    466