Home | History | Annotate | Download | only in result
      1 /*
      2  * Copyright (C) 2011 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 package com.android.cts.tradefed.result;
     17 
     18 import com.android.tradefed.result.TestResult;
     19 
     20 import org.kxml2.io.KXmlSerializer;
     21 import org.xmlpull.v1.XmlPullParser;
     22 import org.xmlpull.v1.XmlPullParserException;
     23 
     24 import java.io.IOException;
     25 
     26 /**
     27  * Data structure that represents a "Test" result XML element.
     28  */
     29 class Test extends AbstractXmlPullParser {
     30 
     31     static final String TAG = "Test";
     32     private static final String NAME_ATTR = "name";
     33     private static final String MESSAGE_ATTR = "message";
     34     private static final String ENDTIME_ATTR = "endtime";
     35     private static final String STARTTIME_ATTR = "starttime";
     36     private static final String RESULT_ATTR = "result";
     37     private static final String SCENE_TAG = "FailedScene";
     38     private static final String STACK_TAG = "StackTrace";
     39 
     40     private String mName;
     41     private CtsTestStatus mResult;
     42     private String mStartTime;
     43     private String mEndTime;
     44     private String mMessage;
     45     private String mStackTrace;
     46 
     47     /**
     48      * Create an empty {@link Test}
     49      */
     50     public Test() {
     51     }
     52 
     53     /**
     54      * Create a {@link Test} from a {@link TestResult}.
     55      *
     56      * @param name
     57      */
     58     public Test(String name) {
     59         mName = name;
     60         mResult = CtsTestStatus.NOT_EXECUTED;
     61         mStartTime = TimeUtil.getTimestamp();
     62         updateEndTime();
     63     }
     64 
     65     /**
     66      * Set the name of this {@link Test}
     67      */
     68     public void setName(String name) {
     69         mName = name;
     70     }
     71 
     72     /**
     73      * Get the name of this {@link Test}
     74      */
     75     public String getName() {
     76         return mName;
     77     }
     78 
     79     public CtsTestStatus getResult() {
     80         return mResult;
     81     }
     82 
     83     public String getMessage() {
     84         return mMessage;
     85     }
     86 
     87     public String getStartTime() {
     88         return mStartTime;
     89     }
     90 
     91     public String getEndTime() {
     92         return mEndTime;
     93     }
     94 
     95     public String getStackTrace() {
     96         return mStackTrace;
     97     }
     98 
     99     public void setStackTrace(String stackTrace) {
    100 
    101         mStackTrace = sanitizeStackTrace(stackTrace);
    102         mMessage = getFailureMessageFromStackTrace(mStackTrace);
    103     }
    104 
    105     public void updateEndTime() {
    106         mEndTime = TimeUtil.getTimestamp();
    107     }
    108 
    109     public void setResultStatus(CtsTestStatus status) {
    110         mResult = status;
    111     }
    112 
    113     /**
    114      * Serialize this object and all its contents to XML.
    115      *
    116      * @param serializer
    117      * @throws IOException
    118      */
    119     public void serialize(KXmlSerializer serializer)
    120             throws IOException {
    121         serializer.startTag(CtsXmlResultReporter.ns, TAG);
    122         serializer.attribute(CtsXmlResultReporter.ns, NAME_ATTR, getName());
    123         serializer.attribute(CtsXmlResultReporter.ns, RESULT_ATTR, mResult.getValue());
    124         serializer.attribute(CtsXmlResultReporter.ns, STARTTIME_ATTR, mStartTime);
    125         serializer.attribute(CtsXmlResultReporter.ns, ENDTIME_ATTR, mEndTime);
    126 
    127         if (mMessage != null) {
    128             serializer.startTag(CtsXmlResultReporter.ns, SCENE_TAG);
    129             serializer.attribute(CtsXmlResultReporter.ns, MESSAGE_ATTR, mMessage);
    130             if (mStackTrace != null) {
    131                 serializer.startTag(CtsXmlResultReporter.ns, STACK_TAG);
    132                 serializer.text(mStackTrace);
    133                 serializer.endTag(CtsXmlResultReporter.ns, STACK_TAG);
    134             }
    135             serializer.endTag(CtsXmlResultReporter.ns, SCENE_TAG);
    136         }
    137         serializer.endTag(CtsXmlResultReporter.ns, TAG);
    138     }
    139 
    140     /**
    141      * Strip out any invalid XML characters that might cause the report to be unviewable.
    142      * http://www.w3.org/TR/REC-xml/#dt-character
    143      */
    144     private static String sanitizeStackTrace(String trace) {
    145         if (trace != null) {
    146             return trace.replaceAll("[^\\u0009\\u000A\\u000D\\u0020-\\uD7FF\\uE000-\\uFFFD]", "");
    147         } else {
    148             return null;
    149         }
    150     }
    151 
    152     /**
    153      * Gets the failure message to show from the stack trace.
    154      * <p/>
    155      * Exposed for unit testing
    156      *
    157      * @param stack the full stack trace
    158      * @return the failure message
    159      */
    160     static String getFailureMessageFromStackTrace(String stack) {
    161         // return the first two lines of stack as failure message
    162         int endPoint = stack.indexOf('\n');
    163         if (endPoint != -1) {
    164             int nextLine = stack.indexOf('\n', endPoint + 1);
    165             if (nextLine != -1) {
    166                 return stack.substring(0, nextLine);
    167             }
    168         }
    169         return stack;
    170     }
    171 
    172     /**
    173      * Populates this class with test result data parsed from XML.
    174      *
    175      * @param parser the {@link XmlPullParser}. Expected to be pointing at start
    176      *            of a Test tag
    177      */
    178     @Override
    179     void parse(XmlPullParser parser) throws XmlPullParserException, IOException {
    180         if (!parser.getName().equals(TAG)) {
    181             throw new XmlPullParserException(String.format(
    182                     "invalid XML: Expected %s tag but received %s", TAG, parser.getName()));
    183         }
    184         setName(getAttribute(parser, NAME_ATTR));
    185         mResult = CtsTestStatus.getStatus(getAttribute(parser, RESULT_ATTR));
    186         mStartTime = getAttribute(parser, STARTTIME_ATTR);
    187         mEndTime = getAttribute(parser, ENDTIME_ATTR);
    188 
    189         int eventType = parser.next();
    190         while (eventType != XmlPullParser.END_DOCUMENT) {
    191             if (eventType == XmlPullParser.START_TAG && parser.getName().equals(SCENE_TAG)) {
    192                 mMessage = getAttribute(parser, MESSAGE_ATTR);
    193             } else if (eventType == XmlPullParser.START_TAG && parser.getName().equals(STACK_TAG)) {
    194                 mStackTrace = parser.nextText();
    195             } else if (eventType == XmlPullParser.END_TAG && parser.getName().equals(TAG)) {
    196                 return;
    197             }
    198             eventType = parser.next();
    199         }
    200     }
    201 }
    202