Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2008 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;
     18 
     19 import com.android.cts.TestDevice.DeviceParameterCollector;
     20 
     21 import org.w3c.dom.Document;
     22 import org.w3c.dom.Node;
     23 import org.w3c.dom.ProcessingInstruction;
     24 
     25 import java.io.File;
     26 import java.net.InetAddress;
     27 import java.net.UnknownHostException;
     28 import java.util.ArrayList;
     29 import java.util.Collection;
     30 import java.util.Date;
     31 import java.util.regex.Matcher;
     32 import java.util.regex.Pattern;
     33 
     34 import javax.xml.parsers.DocumentBuilderFactory;
     35 
     36 /**
     37  * Store the information of a test plan.
     38  */
     39 public class TestSessionLog extends XMLResourceHandler {
     40     private static final String EXPR_TEST_FAILED = ".+\\((\\S+):(\\d+)\\)";
     41     private static Pattern mTestFailedPattern = Pattern.compile(EXPR_TEST_FAILED);
     42     private static final String ATTRIBUTE_NAME = "name";
     43     static final String ATTRIBUTE_RESULT = "result";
     44     private static final String ATTRIBUTE_VERSION = "version";
     45     private static final String ATTRIBUTE_DIGEST = "digest";
     46     private static final String ATTRIBUTE_KNOWN_FAILURE = "KnownFailure";
     47 
     48     public static final String CTS_RESULT_FILE_NAME = "testResult.xml";
     49     private static final String CTS_RESULT_FILE_VERSION = "1.2";
     50 
     51     static final String ATTRIBUTE_STARTTIME = "starttime";
     52     static final String ATTRIBUTE_ENDTIME = "endtime";
     53     static final String ATTRIBUTE_TESTPLAN = "testPlan";
     54     static final String ATTRIBUTE_RESOLUTION = "resolution";
     55     static final String ATTRIBUTE_SUBSCRIBER_ID = "subscriberId";
     56     static final String ATTRIBUTE_DEVICE_ID = "deviceID";
     57     static final String ATTRIBUTE_BUILD_ID = "buildID";
     58     static final String ATTRIBUTE_BUILD_VERSION = "buildVersion";
     59     static final String ATTRIBUTE_ANDROID_PLATFORM_VERSION = "androidPlatformVersion";
     60     static final String ATTRIBUTE_LOCALES = "locales";
     61     static final String ATTRIBUTE_XDPI = "Xdpi";
     62     static final String ATTRIBUTE_YDPI = "Ydpi";
     63     static final String ATTRIBUTE_TOUCH = "touch";
     64     static final String ATTRIBUTE_NAVIGATION = "navigation";
     65     static final String ATTRIBUTE_KEYPAD = "keypad";
     66     static final String ATTRIBUTE_NETWORK = "network";
     67     static final String ATTRIBUTE_IMEI = "imei";
     68     static final String ATTRIBUTE_IMSI = "imsi";
     69     static final String ATTRIBUTE_BUILD_NAME = "buildName";
     70     static final String ATTRIBUTE_ARCH = "arch";
     71     static final String ATTRIBUTE_VALUE = "value";
     72 
     73     static final String ATTRIBUTE_PASS = "pass";
     74     static final String ATTRIBUTE_FAILED = "failed";
     75     static final String ATTRIBUTE_TIMEOUT = "timeout";
     76     static final String ATTRIBUTE_NOT_EXECUTED = "notExecuted";
     77 
     78     static final String TAG_DEVICEINFO = "DeviceInfo";
     79     static final String TAG_HOSTINFO = "HostInfo";
     80     static final String TAG_OSINFO = "Os";
     81     static final String TAG_JAVA = "Java";
     82     static final String TAG_CTS = "Cts";
     83     static final String TAG_INTVALUE = "IntValue";
     84     static final String TAG_SUMMARY = "Summary";
     85     static final String TAG_SCREEN = "Screen";
     86     static final String TAG_BUILD_INFO = "BuildInfo";
     87     static final String TAG_PHONE_SUB_INFO = "PhoneSubInfo";
     88     static final String TAG_TEST_RESULT = "TestResult";
     89     static final String TAG_TESTPACKAGE = "TestPackage";
     90     static final String TAG_TESTSUITE = "TestSuite";
     91     static final String TAG_TESTCASE = "TestCase";
     92     static final String TAG_FAILED_SCENE = "FailedScene";
     93     static final String TAG_STACK_TRACE = "StackTrace";
     94     static final String TAG_FAILED_MESSAGE = "message";
     95 
     96     private Collection<TestPackage> mTestPackages;
     97     private Date mSessionStartTime;
     98     private Date mSessionEndTime;
     99     private String mResultPath;
    100     private String mResultDir;
    101     private String mTestPlanName;
    102 
    103     private ArrayList<DeviceParameterCollector> mDeviceParameterBase;
    104 
    105     public TestSessionLog(final Collection<TestPackage> packages, final String testPlanName) {
    106         mTestPackages = packages;
    107 
    108         mDeviceParameterBase = new ArrayList<TestDevice.DeviceParameterCollector>();
    109         mTestPlanName = testPlanName;
    110 
    111         mSessionStartTime = new Date();
    112         mSessionEndTime = new Date();
    113     }
    114 
    115     /**
    116      * Get the test plan name.
    117      *
    118      * @return The test plan name.
    119      */
    120     public String getTestPlanName() {
    121         return mTestPlanName;
    122     }
    123 
    124     /**
    125      * Get all result of this session.
    126      *
    127      * @return All the tests with a result code of this session.
    128      */
    129     public Collection<Test> getAllResults() {
    130         if (mTestPackages == null || mTestPackages.size() == 0) {
    131             return null;
    132         }
    133 
    134         ArrayList<Test> results = new ArrayList<Test>();
    135         for (TestPackage p : mTestPackages) {
    136             results.addAll(p.getTests());
    137         }
    138 
    139         return results;
    140     }
    141 
    142     /**
    143      * Get test list according to the result type code.
    144      *
    145      * @param resCode The result code.
    146      * @return The list of {@link Test}.
    147      */
    148     public Collection<Test> getTestList(int resCode) {
    149         if ((resCode < CtsTestResult.CODE_FIRST)
    150                 || (resCode > CtsTestResult.CODE_LAST)) {
    151             return null;
    152         }
    153 
    154         ArrayList<Test> tests = new ArrayList<Test>();
    155         for (Test test : getAllResults()) {
    156             if (resCode == test.getResult().getResultCode()) {
    157                 tests.add(test);
    158             }
    159         }
    160 
    161         return tests;
    162     }
    163 
    164     /**
    165      * Get TestSession start time
    166      *
    167      * @return The start time.
    168      */
    169     public Date getStartTime() {
    170         return mSessionStartTime;
    171     }
    172 
    173     /**
    174      * Get TestSession end time
    175      *
    176      * @return The end time.
    177      */
    178     public Date getEndTime() {
    179         return mSessionEndTime;
    180     }
    181 
    182     /**
    183      * Get test packages.
    184      *
    185      * @return The test packages.
    186      */
    187     public Collection<TestPackage> getTestPackages() {
    188         return mTestPackages;
    189     }
    190 
    191     /**
    192      * Get the path to the XML result file.
    193      *
    194      * @return The result path.
    195      */
    196     public String getResultPath() {
    197         return mResultPath;
    198     }
    199 
    200     /**
    201      * Get the result directory.  This is the directory that all result files
    202      * should go into.
    203      */
    204     public String getResultDir() {
    205         return mResultDir;
    206     }
    207 
    208     /**
    209      * set TestSession start time
    210      *
    211      * @param time The start time.
    212      */
    213     public void setStartTime(final long time) {
    214         mSessionStartTime.setTime(time);
    215 
    216         String startTimeStr = HostUtils.getFormattedTimeString(time, "_", ".", ".");
    217         mResultDir = HostConfig.getInstance().getResultRepository().getRoot()
    218             + File.separator + startTimeStr;
    219         mResultPath =  mResultDir + File.separator + CTS_RESULT_FILE_NAME;
    220         // Make sure the result directory exists
    221         new File(mResultDir).mkdirs();
    222     }
    223 
    224     /**
    225      * set TestSession end time
    226      *
    227      * @param time The end time.
    228      */
    229     public void setEndTime(final long time) {
    230         mSessionEndTime.setTime(time);
    231     }
    232 
    233     /**
    234      * Calling this functions indicates that the TestSession is complete.  This
    235      * indicates to the TestSessionLog that it is time to store the results
    236      * to the filesystem.
    237      */
    238     public void sessionComplete() {
    239         try {
    240             writeToFile(new File(mResultPath), createResultDoc());
    241             // Now zip up the results directory so we have something nice
    242             // that people can upload.
    243             HostUtils.zipUpDirectory(mResultDir,
    244                     mResultDir + ".zip",
    245                     new HostUtils.ZipFilenameTransformer() {
    246                         public String transform(String filename) {
    247                             if (filename.startsWith(mResultDir)) {
    248                                 return filename.substring(mResultDir.length() + 1);
    249                             }
    250                             return filename;
    251                         }
    252             });
    253         } catch (Exception e) {
    254             Log.e("Got exception when trying to write to result file", e);
    255         }
    256         HostConfig.getInstance().extractResultResources(mResultDir);
    257     }
    258 
    259     /**
    260      * Create result Doc in XML format.
    261      *
    262      * @return Result document.
    263      */
    264     protected Document createResultDoc() {
    265         try {
    266 
    267             Document doc = DocumentBuilderFactory.newInstance()
    268                     .newDocumentBuilder().newDocument();
    269             ProcessingInstruction pr = doc.createProcessingInstruction(
    270                     "xml-stylesheet", "type=\"text/xsl\"  href=\"cts_result.xsl\"");
    271             doc.appendChild(pr);
    272             Node root = doc.createElement(TAG_TEST_RESULT);
    273             doc.appendChild(root);
    274 
    275             setAttribute(doc, root, ATTRIBUTE_VERSION, CTS_RESULT_FILE_VERSION);
    276             setAttribute(doc, root, ATTRIBUTE_STARTTIME, HostUtils.dateToString(mSessionStartTime));
    277             setAttribute(doc, root, ATTRIBUTE_ENDTIME, HostUtils.dateToString(mSessionEndTime));
    278             setAttribute(doc, root, ATTRIBUTE_TESTPLAN, mTestPlanName);
    279 
    280             // set device information
    281             for (int i = 0; i < mDeviceParameterBase.size(); i ++) {
    282                 DeviceParameterCollector bldInfo = mDeviceParameterBase.get(i);
    283                 // set device setting
    284                 Node deviceSettingNode = doc.createElement(TAG_DEVICEINFO);
    285 
    286                 Node screenNode = doc.createElement(TAG_SCREEN);
    287                 setAttribute(doc, screenNode, ATTRIBUTE_RESOLUTION, bldInfo.getScreenResolution());
    288                 deviceSettingNode.appendChild(screenNode);
    289                 Node simCardNode = doc.createElement(TAG_PHONE_SUB_INFO);
    290                 setAttribute(doc, simCardNode, ATTRIBUTE_SUBSCRIBER_ID, bldInfo.getPhoneNumber());
    291                 deviceSettingNode.appendChild(simCardNode);
    292                 root.appendChild(deviceSettingNode);
    293 
    294                 Node devInfoNode = doc.createElement(TAG_BUILD_INFO);
    295                 setAttribute(doc, devInfoNode, ATTRIBUTE_DEVICE_ID, bldInfo.getSerialNumber());
    296                 setAttribute(doc, devInfoNode, ATTRIBUTE_BUILD_ID, bldInfo.getBuildId());
    297                 setAttribute(doc, devInfoNode, ATTRIBUTE_BUILD_NAME, bldInfo.getProductName());
    298                 setAttribute(doc, devInfoNode, ATTRIBUTE_BUILD_VERSION,
    299                              bldInfo.getBuildVersion());
    300                 setAttribute(doc, devInfoNode, ATTRIBUTE_ANDROID_PLATFORM_VERSION,
    301                              bldInfo.getAndroidPlatformVersion());
    302                 setAttribute(doc, devInfoNode, ATTRIBUTE_LOCALES, bldInfo.getLocales());
    303                 setAttribute(doc, devInfoNode, ATTRIBUTE_XDPI, bldInfo.getXdpi());
    304                 setAttribute(doc, devInfoNode, ATTRIBUTE_YDPI, bldInfo.getYdpi());
    305                 setAttribute(doc, devInfoNode, ATTRIBUTE_TOUCH, bldInfo.getTouchInfo());
    306                 setAttribute(doc, devInfoNode, ATTRIBUTE_NAVIGATION, bldInfo.getNavigation());
    307                 setAttribute(doc, devInfoNode, ATTRIBUTE_KEYPAD, bldInfo.getKeypad());
    308                 setAttribute(doc, devInfoNode, ATTRIBUTE_NETWORK, bldInfo.getNetwork());
    309                 setAttribute(doc, devInfoNode, ATTRIBUTE_IMEI, bldInfo.getIMEI());
    310                 setAttribute(doc, devInfoNode, ATTRIBUTE_IMSI, bldInfo.getIMSI());
    311 
    312                 setAttribute(doc, devInfoNode,
    313                         DeviceParameterCollector.BUILD_FINGERPRINT, bldInfo.getBuildFingerPrint());
    314                 setAttribute(doc, devInfoNode,
    315                         DeviceParameterCollector.BUILD_TYPE, bldInfo.getBuildType());
    316                 setAttribute(doc, devInfoNode,
    317                         DeviceParameterCollector.BUILD_MODEL, bldInfo.getBuildModel());
    318                 setAttribute(doc, devInfoNode,
    319                         DeviceParameterCollector.BUILD_BRAND, bldInfo.getBuildBrand());
    320                 setAttribute(doc, devInfoNode,
    321                         DeviceParameterCollector.BUILD_BOARD, bldInfo.getBuildBoard());
    322                 setAttribute(doc, devInfoNode,
    323                         DeviceParameterCollector.BUILD_DEVICE, bldInfo.getBuildDevice());
    324                 setAttribute(doc, devInfoNode,
    325                         DeviceParameterCollector.BUILD_ABI, bldInfo.getBuildAbi());
    326                 setAttribute(doc, devInfoNode,
    327                         DeviceParameterCollector.BUILD_ABI2, bldInfo.getBuildAbi2());
    328 
    329                 deviceSettingNode.appendChild(devInfoNode);
    330             }
    331 
    332             Node hostInfo = doc.createElement(TAG_HOSTINFO);
    333             root.appendChild(hostInfo);
    334             String hostName = "";
    335             try {
    336                 hostName = InetAddress.getLocalHost().getHostName();
    337             } catch (UnknownHostException ignored) {}
    338             setAttribute(doc, hostInfo, ATTRIBUTE_NAME, hostName);
    339             Node osInfo = doc.createElement(TAG_OSINFO);
    340             hostInfo.appendChild(osInfo);
    341             setAttribute(doc, osInfo, ATTRIBUTE_NAME, System.getProperty("os.name"));
    342             setAttribute(doc, osInfo, ATTRIBUTE_VERSION, System.getProperty("os.version"));
    343             setAttribute(doc, osInfo, ATTRIBUTE_ARCH, System.getProperty("os.arch"));
    344             Node javaInfo = doc.createElement(TAG_JAVA);
    345             hostInfo.appendChild(javaInfo);
    346             setAttribute(doc, javaInfo, ATTRIBUTE_NAME, System.getProperty("java.vendor"));
    347             setAttribute(doc, javaInfo, ATTRIBUTE_VERSION, System.getProperty("java.version"));
    348             Node ctsInfo = doc.createElement(TAG_CTS);
    349             hostInfo.appendChild(ctsInfo);
    350             setAttribute(doc, ctsInfo, ATTRIBUTE_VERSION, Version.asString());
    351             for (HostConfig.Ints i : HostConfig.Ints.values()) {
    352                 Node intValue = doc.createElement(TAG_INTVALUE);
    353                 ctsInfo.appendChild(intValue);
    354                 setAttribute(doc, intValue, ATTRIBUTE_NAME, i.name());
    355                 setAttribute(doc, intValue, ATTRIBUTE_VALUE, i.value());
    356             }
    357 
    358             int passNum = getTestList(CtsTestResult.CODE_PASS).size();
    359             int failNum = getTestList(CtsTestResult.CODE_FAIL).size();
    360             int notExecutedNum = getTestList(CtsTestResult.CODE_NOT_EXECUTED).size();
    361             int timeOutNum = getTestList(CtsTestResult.CODE_TIMEOUT).size();
    362             Node summaryNode = doc.createElement(TAG_SUMMARY);
    363             root.appendChild(summaryNode);
    364             setAttribute(doc, summaryNode, ATTRIBUTE_PASS, passNum);
    365             setAttribute(doc, summaryNode, ATTRIBUTE_FAILED, failNum);
    366             setAttribute(doc, summaryNode, ATTRIBUTE_NOT_EXECUTED, notExecutedNum);
    367             setAttribute(doc, summaryNode, ATTRIBUTE_TIMEOUT, timeOutNum);
    368 
    369             for (TestPackage testPackage : mTestPackages) {
    370                 Node testPackageNode = doc.createElement(TAG_TESTPACKAGE);
    371                 setAttribute(doc, testPackageNode, ATTRIBUTE_NAME, testPackage.getAppBinaryName());
    372                 setAttribute(doc, testPackageNode, TestSessionBuilder.ATTRIBUTE_APP_PACKAGE_NAME,
    373                         testPackage.getAppPackageName());
    374                 setAttribute(doc, testPackageNode, ATTRIBUTE_DIGEST,
    375                              testPackage.getMessageDigest());
    376 
    377                 if (testPackage instanceof SignatureCheckPackage) {
    378                     setAttribute(doc, testPackageNode,
    379                               TestSessionBuilder.ATTRIBUTE_SIGNATURE_CHECK, "true");
    380                 }
    381 
    382                 for (TestSuite testSuite : testPackage.getTestSuites()) {
    383                     outputTestSuite(doc, testPackage, testPackageNode, testSuite);
    384                 }
    385                 root.appendChild(testPackageNode);
    386             }
    387 
    388             return doc;
    389         } catch (Exception e) {
    390             Log.e("create result doc failed", e);
    391         }
    392         return null;
    393     }
    394 
    395     /**
    396      * Output TestSuite and result to XML DOM Document.
    397      *
    398      * @param doc The document.
    399      * @param parentNode The parent node.
    400      * @param testSuite The test suite.
    401      */
    402     private void outputTestSuite(final Document doc,
    403             final TestPackage testPackage, final Node parentNode,
    404             TestSuite testSuite) {
    405 
    406         Collection<TestSuite> subSuites = testSuite.getSubSuites();
    407         Collection<TestCase> testCases = testSuite.getTestCases();
    408 
    409         Node testSuiteNode = doc.createElement(TAG_TESTSUITE);
    410         setAttribute(doc, testSuiteNode, ATTRIBUTE_NAME, testSuite.getName());
    411 
    412         for (TestCase testCase : testCases) {
    413             Node testCaseNode = doc.createElement(TAG_TESTCASE);
    414             testSuiteNode.appendChild(testCaseNode);
    415             setAttribute(doc, testCaseNode, ATTRIBUTE_NAME, testCase.getName());
    416             setAttribute(doc, testCaseNode, TestSessionBuilder.ATTRIBUTE_PRIORITY,
    417                     testCase.getPriority());
    418 
    419             Collection<Test> tests = testCase.getTests();
    420             for (Test test : tests) {
    421                 Node testNode = doc.createElement(TestSessionBuilder.TAG_TEST);
    422                 testCaseNode.appendChild(testNode);
    423 
    424                 if (test.isKnownFailure()) {
    425                     setAttribute(doc, testNode, ATTRIBUTE_KNOWN_FAILURE, test.getKnownFailure());
    426                 }
    427 
    428                 CtsTestResult result = test.getResult();
    429                 setAttribute(doc, testNode, ATTRIBUTE_NAME, test.getName());
    430                 setAttribute(doc, testNode, ATTRIBUTE_RESULT, result.getResultString());
    431                 setAttribute(doc, testNode, ATTRIBUTE_STARTTIME,
    432                              new Date(test.getStartTime()).toString());
    433                 setAttribute(doc, testNode, ATTRIBUTE_ENDTIME,
    434                              new Date(test.getEndTime()).toString());
    435 
    436                 String failedMessage = result.getFailedMessage();
    437 
    438                 if (failedMessage != null) {
    439                     // failure message may contain control characters < 0x20 that get translated
    440                     // into illegal XML character entities. Replace them first.
    441                     failedMessage = HostUtils.replaceControlChars(failedMessage);
    442                     Node failedMessageNode = doc.createElement(TAG_FAILED_SCENE);
    443                     testNode.appendChild(failedMessageNode);
    444                     setAttribute(doc, failedMessageNode,TAG_FAILED_MESSAGE, failedMessage);
    445 
    446                     String stackTrace = result.getStackTrace();
    447                     if (stackTrace != null) {
    448                         Node stackTraceNode = doc.createElement(TAG_STACK_TRACE);
    449                         failedMessageNode.appendChild(stackTraceNode);
    450                         Node stackTraceTextNode = doc.createTextNode(stackTrace);
    451                         stackTraceNode.appendChild(stackTraceTextNode);
    452                     }
    453                 }
    454             }
    455         }
    456 
    457         for (TestSuite subSuite : subSuites) {
    458             outputTestSuite(doc, testPackage, testSuiteNode, subSuite);
    459             parentNode.appendChild(testSuiteNode);
    460         }
    461         parentNode.appendChild(testSuiteNode);
    462     }
    463 
    464     /**
    465      * Fetch failed file name and line number
    466      *
    467      * @param failedResult failed message
    468      * @return failed file name and line number
    469      */
    470     public final static String[] getFailedLineNumber(final String failedResult) {
    471         Matcher m = mTestFailedPattern.matcher(failedResult);
    472         if (m.matches()) {
    473             return new String[]{m.group(1), m.group(2)};
    474         }
    475         return null;
    476     }
    477 
    478     /**
    479      * set the device information of a specific device
    480      *
    481      * @param dInfo The device information.
    482      */
    483     public void setDeviceInfo(final TestDevice.DeviceParameterCollector dInfo) {
    484         for (DeviceParameterCollector collector : mDeviceParameterBase) {
    485             if (collector.getSerialNumber().equals(dInfo.getSerialNumber())) {
    486                 //if there has information for the device with given serial number,
    487                 //replace it with the new information.
    488                 mDeviceParameterBase.remove(collector);
    489                 break;
    490             }
    491         }
    492         mDeviceParameterBase.add(dInfo);
    493     }
    494 }
    495