Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/ts/misc/testlog_parser.py
16354 views
1
#!/usr/bin/env python
2
3
from __future__ import print_function
4
import collections
5
import re
6
import os.path
7
import sys
8
from xml.dom.minidom import parse
9
10
if sys.version_info > (3,):
11
long = int
12
def cmp(a, b): return (a>b)-(a<b)
13
14
class TestInfo(object):
15
16
def __init__(self, xmlnode):
17
self.fixture = xmlnode.getAttribute("classname")
18
self.name = xmlnode.getAttribute("name")
19
self.value_param = xmlnode.getAttribute("value_param")
20
self.type_param = xmlnode.getAttribute("type_param")
21
22
custom_status = xmlnode.getAttribute("custom_status")
23
failures = xmlnode.getElementsByTagName("failure")
24
25
if len(custom_status) > 0:
26
self.status = custom_status
27
elif len(failures) > 0:
28
self.status = "failed"
29
else:
30
self.status = xmlnode.getAttribute("status")
31
32
if self.name.startswith("DISABLED_"):
33
self.status = "disabled"
34
self.fixture = self.fixture.replace("DISABLED_", "")
35
self.name = self.name.replace("DISABLED_", "")
36
self.properties = {
37
prop.getAttribute("name") : prop.getAttribute("value")
38
for prop in xmlnode.getElementsByTagName("property")
39
if prop.hasAttribute("name") and prop.hasAttribute("value")
40
}
41
self.metrix = {}
42
self.parseLongMetric(xmlnode, "bytesIn");
43
self.parseLongMetric(xmlnode, "bytesOut");
44
self.parseIntMetric(xmlnode, "samples");
45
self.parseIntMetric(xmlnode, "outliers");
46
self.parseFloatMetric(xmlnode, "frequency", 1);
47
self.parseLongMetric(xmlnode, "min");
48
self.parseLongMetric(xmlnode, "median");
49
self.parseLongMetric(xmlnode, "gmean");
50
self.parseLongMetric(xmlnode, "mean");
51
self.parseLongMetric(xmlnode, "stddev");
52
self.parseFloatMetric(xmlnode, "gstddev");
53
self.parseFloatMetric(xmlnode, "time");
54
55
def parseLongMetric(self, xmlnode, name, default = 0):
56
if name in self.properties:
57
self.metrix[name] = long(self.properties[name])
58
elif xmlnode.hasAttribute(name):
59
self.metrix[name] = long(xmlnode.getAttribute(name))
60
else:
61
self.metrix[name] = default
62
63
def parseIntMetric(self, xmlnode, name, default = 0):
64
if name in self.properties:
65
self.metrix[name] = int(self.properties[name])
66
elif xmlnode.hasAttribute(name):
67
self.metrix[name] = int(xmlnode.getAttribute(name))
68
else:
69
self.metrix[name] = default
70
71
def parseFloatMetric(self, xmlnode, name, default = 0):
72
if name in self.properties:
73
self.metrix[name] = float(self.properties[name])
74
elif xmlnode.hasAttribute(name):
75
self.metrix[name] = float(xmlnode.getAttribute(name))
76
else:
77
self.metrix[name] = default
78
79
def parseStringMetric(self, xmlnode, name, default = None):
80
if name in self.properties:
81
self.metrix[name] = self.properties[name].strip()
82
elif xmlnode.hasAttribute(name):
83
self.metrix[name] = xmlnode.getAttribute(name).strip()
84
else:
85
self.metrix[name] = default
86
87
def get(self, name, units="ms"):
88
if name == "classname":
89
return self.fixture
90
if name == "name":
91
return self.name
92
if name == "fullname":
93
return self.__str__()
94
if name == "value_param":
95
return self.value_param
96
if name == "type_param":
97
return self.type_param
98
if name == "status":
99
return self.status
100
val = self.metrix.get(name, None)
101
if not val:
102
return val
103
if name == "time":
104
return self.metrix.get("time")
105
if name in ["gmean", "min", "mean", "median", "stddev"]:
106
scale = 1.0
107
frequency = self.metrix.get("frequency", 1.0) or 1.0
108
if units == "ms":
109
scale = 1000.0
110
if units == "us" or units == "mks": # mks is typo error for microsecond (<= OpenCV 3.4)
111
scale = 1000000.0
112
if units == "ns":
113
scale = 1000000000.0
114
if units == "ticks":
115
frequency = long(1)
116
scale = long(1)
117
return val * scale / frequency
118
return val
119
120
121
def dump(self, units="ms"):
122
print("%s ->\t\033[1;31m%s\033[0m = \t%.2f%s" % (str(self), self.status, self.get("gmean", units), units))
123
124
125
def getName(self):
126
pos = self.name.find("/")
127
if pos > 0:
128
return self.name[:pos]
129
return self.name
130
131
132
def getFixture(self):
133
if self.fixture.endswith(self.getName()):
134
fixture = self.fixture[:-len(self.getName())]
135
else:
136
fixture = self.fixture
137
if fixture.endswith("_"):
138
fixture = fixture[:-1]
139
return fixture
140
141
142
def param(self):
143
return '::'.join(filter(None, [self.type_param, self.value_param]))
144
145
def shortName(self):
146
name = self.getName()
147
fixture = self.getFixture()
148
return '::'.join(filter(None, [name, fixture]))
149
150
151
def __str__(self):
152
name = self.getName()
153
fixture = self.getFixture()
154
return '::'.join(filter(None, [name, fixture, self.type_param, self.value_param]))
155
156
157
def __cmp__(self, other):
158
r = cmp(self.fixture, other.fixture);
159
if r != 0:
160
return r
161
if self.type_param:
162
if other.type_param:
163
r = cmp(self.type_param, other.type_param);
164
if r != 0:
165
return r
166
else:
167
return -1
168
else:
169
if other.type_param:
170
return 1
171
if self.value_param:
172
if other.value_param:
173
r = cmp(self.value_param, other.value_param);
174
if r != 0:
175
return r
176
else:
177
return -1
178
else:
179
if other.value_param:
180
return 1
181
return 0
182
183
# This is a Sequence for compatibility with old scripts,
184
# which treat parseLogFile's return value as a list.
185
class TestRunInfo(collections.Sequence):
186
def __init__(self, properties, tests):
187
self.properties = properties
188
self.tests = tests
189
190
def __len__(self):
191
return len(self.tests)
192
193
def __getitem__(self, key):
194
return self.tests[key]
195
196
def parseLogFile(filename):
197
log = parse(filename)
198
199
properties = {
200
attr_name[3:]: attr_value
201
for (attr_name, attr_value) in log.documentElement.attributes.items()
202
if attr_name.startswith('cv_')
203
}
204
205
tests = list(map(TestInfo, log.getElementsByTagName("testcase")))
206
207
return TestRunInfo(properties, tests)
208
209
210
if __name__ == "__main__":
211
if len(sys.argv) < 2:
212
print("Usage:\n", os.path.basename(sys.argv[0]), "<log_name>.xml")
213
exit(0)
214
215
for arg in sys.argv[1:]:
216
print("Processing {}...".format(arg))
217
218
run = parseLogFile(arg)
219
220
print("Properties:")
221
222
for (prop_name, prop_value) in run.properties.items():
223
print("\t{} = {}".format(prop_name, prop_value))
224
225
print("Tests:")
226
227
for t in sorted(run.tests):
228
t.dump()
229
230
print()
231
232