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