Add CTS_ARB_gl_spirv test implementation
[platform/upstream/VK-GL-CTS.git] / scripts / log / log_to_xml.py
1 # -*- coding: utf-8 -*-
2
3 #-------------------------------------------------------------------------
4 # drawElements Quality Program utilities
5 # --------------------------------------
6 #
7 # Copyright 2015 The Android Open Source Project
8 #
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
12 #
13 #      http://www.apache.org/licenses/LICENSE-2.0
14 #
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.
20 #
21 #-------------------------------------------------------------------------
22
23 import os
24 import sys
25 import codecs
26 import xml.dom.minidom
27 import xml.sax
28 import xml.sax.handler
29 from log_parser import BatchResultParser, StatusCode
30
31 STYLESHEET_FILENAME = "testlog.xsl"
32 LOG_VERSION                     = '0.3.2'
33
34 class BuildXMLLogHandler(xml.sax.handler.ContentHandler):
35         def __init__ (self, doc):
36                 self.doc                        = doc
37                 self.elementStack       = []
38                 self.rootElements       = []
39
40         def getRootElements (self):
41                 return self.rootElements
42
43         def pushElement (self, elem):
44                 if len(self.elementStack) == 0:
45                         self.rootElements.append(elem)
46                 else:
47                         self.getCurElement().appendChild(elem)
48                 self.elementStack.append(elem)
49
50         def popElement (self):
51                 self.elementStack.pop()
52
53         def getCurElement (self):
54                 if len(self.elementStack) > 0:
55                         return self.elementStack[-1]
56                 else:
57                         return None
58
59         def startDocument (self):
60                 pass
61
62         def endDocument (self):
63                 pass
64
65         def startElement (self, name, attrs):
66                 elem = self.doc.createElement(name)
67                 for name in attrs.getNames():
68                         value = attrs.getValue(name)
69                         elem.setAttribute(name, value)
70                 self.pushElement(elem)
71
72         def endElement (self, name):
73                 self.popElement()
74
75         def characters (self, content):
76                 # Discard completely empty content
77                 if len(content.strip()) == 0:
78                         return
79
80                 # Append as text node (not pushed to stack)
81                 if self.getCurElement() != None:
82                         txt = self.doc.createTextNode(content)
83                         self.getCurElement().appendChild(txt)
84
85 class LogErrorHandler(xml.sax.handler.ErrorHandler):
86         def __init__ (self):
87                 pass
88
89         def error (self, err):
90                 #print "error(%s)" % str(err)
91                 pass
92
93         def fatalError (self, err):
94                 #print "fatalError(%s)" % str(err)
95                 pass
96
97         def warning (self, warn):
98                 #print "warning(%s)" % str(warn)
99                 pass
100
101 def findFirstElementByName (nodes, name):
102         for node in nodes:
103                 if node.nodeName == name:
104                         return node
105                 chFound = findFirstElementByName(node.childNodes, name)
106                 if chFound != None:
107                         return chFound
108         return None
109
110 # Normalizes potentially broken (due to crash for example) log data to XML element tree
111 def normalizeToXml (result, doc):
112         handler         = BuildXMLLogHandler(doc)
113         errHandler      = LogErrorHandler()
114
115         xml.sax.parseString(result.log, handler, errHandler)
116
117         rootNodes = handler.getRootElements()
118
119         # Check if we have TestCaseResult
120         testCaseResult = findFirstElementByName(rootNodes, 'TestCaseResult')
121         if testCaseResult == None:
122                 # Create TestCaseResult element
123                 testCaseResult = doc.createElement('TestCaseResult')
124                 testCaseResult.setAttribute('CasePath', result.name)
125                 testCaseResult.setAttribute('CaseType', 'SelfValidate') # \todo [pyry] Not recoverable..
126                 testCaseResult.setAttribute('Version', LOG_VERSION)
127                 rootNodes.append(testCaseResult)
128
129         # Check if we have Result element
130         resultElem = findFirstElementByName(rootNodes, 'Result')
131         if resultElem == None:
132                 # Create result element
133                 resultElem = doc.createElement('Result')
134                 resultElem.setAttribute('StatusCode', result.statusCode)
135                 resultElem.appendChild(doc.createTextNode(result.statusDetails))
136                 testCaseResult.appendChild(resultElem)
137
138         return rootNodes
139
140 def logToXml (inFile, outFile):
141         parser  = BatchResultParser()
142         results = parser.parseFile(inFile)
143
144         dstDoc                  = xml.dom.minidom.Document()
145         batchResultNode = dstDoc.createElement('BatchResult')
146         batchResultNode.setAttribute("FileName", os.path.basename(inFile))
147
148         dstDoc.appendChild(batchResultNode)
149
150         for result in results:
151                 # Normalize log to valid XML
152                 rootNodes = normalizeToXml(result, dstDoc)
153                 for node in rootNodes:
154                         batchResultNode.appendChild(node)
155
156         # Summary
157         countByStatusCode = {}
158         for code in StatusCode.STATUS_CODES:
159                 countByStatusCode[code] = 0
160
161         for result in results:
162                 countByStatusCode[result.statusCode] += 1
163
164         summaryElem = dstDoc.createElement('ResultTotals')
165         for code in StatusCode.STATUS_CODES:
166                 summaryElem.setAttribute(code, "%d" % countByStatusCode[code])
167         summaryElem.setAttribute('All', "%d" % len(results))
168         batchResultNode.appendChild(summaryElem)
169
170         text = dstDoc.toprettyxml()
171
172         out = codecs.open(outFile, "wb", encoding="utf-8")
173
174         # Write custom headers
175         out.write("<?xml version=\"1.0\"?>\n")
176         out.write("<?xml-stylesheet href=\"%s\" type=\"text/xsl\"?>\n" % STYLESHEET_FILENAME)
177
178         for line in text.splitlines()[1:]:
179                 out.write(line)
180                 out.write("\n")
181
182         out.close()
183
184 if __name__ == "__main__":
185         if len(sys.argv) != 3:
186                 print "%s: [test log] [dst file]" % sys.argv[0]
187                 sys.exit(-1)
188
189         logToXml(sys.argv[1], sys.argv[2])