• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      */
Test()50     public Test() {
51     }
52 
53     /**
54      * Create a {@link Test} from a {@link TestResult}.
55      *
56      * @param name
57      */
Test(String name)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      */
setName(String name)68     public void setName(String name) {
69         mName = name;
70     }
71 
72     /**
73      * Get the name of this {@link Test}
74      */
getName()75     public String getName() {
76         return mName;
77     }
78 
getResult()79     public CtsTestStatus getResult() {
80         return mResult;
81     }
82 
getMessage()83     public String getMessage() {
84         return mMessage;
85     }
86 
getStartTime()87     public String getStartTime() {
88         return mStartTime;
89     }
90 
getEndTime()91     public String getEndTime() {
92         return mEndTime;
93     }
94 
getStackTrace()95     public String getStackTrace() {
96         return mStackTrace;
97     }
98 
setStackTrace(String stackTrace)99     public void setStackTrace(String stackTrace) {
100 
101         mStackTrace = sanitizeStackTrace(stackTrace);
102         mMessage = getFailureMessageFromStackTrace(mStackTrace);
103     }
104 
updateEndTime()105     public void updateEndTime() {
106         mEndTime = TimeUtil.getTimestamp();
107     }
108 
setResultStatus(CtsTestStatus status)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      */
serialize(KXmlSerializer serializer)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      */
sanitizeStackTrace(String trace)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      */
getFailureMessageFromStackTrace(String stack)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
parse(XmlPullParser parser)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