1 # -*- coding: utf-8 -*-
3 #-------------------------------------------------------------------------
4 # drawElements Quality Program utilities
5 # --------------------------------------
7 # Copyright 2015 The Android Open Source Project
9 # Licensed under the Apache License, Version 2.0 (the "License");
10 # you may not use this file except in compliance with the License.
11 # You may obtain a copy of the License at
13 # http://www.apache.org/licenses/LICENSE-2.0
15 # Unless required by applicable law or agreed to in writing, software
16 # distributed under the License is distributed on an "AS IS" BASIS,
17 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 # See the License for the specific language governing permissions and
19 # limitations under the License.
21 #-------------------------------------------------------------------------
24 import xml.dom.minidom
29 QUALITY_WARNING = 'QualityWarning'
30 COMPATIBILITY_WARNING = 'CompatibilityWarning'
32 NOT_SUPPORTED = 'NotSupported'
33 RESOURCE_ERROR = 'ResourceError'
34 INTERNAL_ERROR = 'InternalError'
42 COMPATIBILITY_WARNING,
50 STATUS_CODE_SET = set(STATUS_CODES)
54 return code in StatusCode.STATUS_CODE_SET
57 def __init__ (self, name, statusCode, statusDetails, log):
59 self.statusCode = statusCode
60 self.statusDetails = statusDetails
64 return "%s: %s (%s)" % (self.name, self.statusCode, self.statusDetails)
66 class ParseError(Exception):
67 def __init__ (self, filename, line, message):
68 self.filename = filename
70 self.message = message
73 return "%s:%d: %s" % (self.filename, self.line, self.message)
75 def splitContainerLine (line):
76 return shlex.split(line)
78 def getNodeText (node):
80 for node in node.childNodes:
81 if node.nodeType == node.TEXT_NODE:
85 class BatchResultParser:
89 def parseFile (self, filename):
92 f = open(filename, 'rb')
98 return self.testCaseResults
100 def init (self, filename):
102 self.sessionInfo = []
103 self.testCaseResults = []
106 self.curResultText = None
107 self.curCaseName = None
111 self.filename = filename
113 def parseLine (self, line):
114 if len(line) > 0 and line[0] == '#':
115 self.parseContainerLine(line)
116 elif self.curResultText != None:
117 self.curResultText += line
120 def parseContainerLine (self, line):
121 args = splitContainerLine(line)
122 if args[0] == "#sessionInfo":
125 self.parseError("Invalid #sessionInfo")
126 self.sessionInfo.append((args[1], ' '.join(args[2:])))
127 elif args[0] == "#beginSession" or args[0] == "#endSession":
128 pass # \todo [pyry] Validate
129 elif args[0] == "#beginTestCaseResult":
130 if len(args) != 2 or self.curCaseName != None:
131 self.parseError("Invalid #beginTestCaseResult")
132 self.curCaseName = args[1]
133 self.curResultText = ""
134 elif args[0] == "#endTestCaseResult":
135 if len(args) != 1 or self.curCaseName == None:
136 self.parseError("Invalid #endTestCaseResult")
137 self.parseTestCaseResult(self.curCaseName, self.curResultText)
138 self.curCaseName = None
139 self.curResultText = None
140 elif args[0] == "#terminateTestCaseResult":
141 if len(args) < 2 or self.curCaseName == None:
142 self.parseError("Invalid #terminateTestCaseResult")
143 statusCode = ' '.join(args[1:])
144 statusDetails = statusCode
146 if not StatusCode.isValid(statusCode):
148 if statusCode == "Watchdog timeout occurred.":
149 statusCode = StatusCode.TIMEOUT
151 statusCode = StatusCode.CRASH
153 # Do not try to parse at all since XML is likely broken
154 self.testCaseResults.append(TestCaseResult(self.curCaseName, statusCode, statusDetails, self.curResultText))
156 self.curCaseName = None
157 self.curResultText = None
159 # Assume this is result text
160 if self.curResultText != None:
161 self.curResultText += line
163 def parseTestCaseResult (self, name, log):
165 # The XML parser has troubles with invalid characters deliberately included in the shaders.
166 # This line removes such characters before calling the parser
167 log = log.decode('utf-8','ignore').encode("utf-8")
168 doc = xml.dom.minidom.parseString(log)
169 resultItems = doc.getElementsByTagName('Result')
170 if len(resultItems) != 1:
171 self.parseError("Expected 1 <Result>, found %d" % len(resultItems))
173 statusCode = resultItems[0].getAttributeNode('StatusCode').nodeValue
174 statusDetails = getNodeText(resultItems[0])
175 except Exception as e:
176 statusCode = StatusCode.INTERNAL_ERROR
177 statusDetails = "XML parsing failed: %s" % str(e)
179 self.testCaseResults.append(TestCaseResult(name, statusCode, statusDetails, log))
181 def parseError (self, message):
182 raise ParseError(self.filename, self.curLine, message)