annotate contrib/dg-extract-results.py @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 #!/usr/bin/python
kono
parents:
diff changeset
2 #
kono
parents:
diff changeset
3 # Copyright (C) 2014 Free Software Foundation, Inc.
kono
parents:
diff changeset
4 #
kono
parents:
diff changeset
5 # This script is free software; you can redistribute it and/or modify
kono
parents:
diff changeset
6 # it under the terms of the GNU General Public License as published by
kono
parents:
diff changeset
7 # the Free Software Foundation; either version 3, or (at your option)
kono
parents:
diff changeset
8 # any later version.
kono
parents:
diff changeset
9
kono
parents:
diff changeset
10 import sys
kono
parents:
diff changeset
11 import getopt
kono
parents:
diff changeset
12 import re
kono
parents:
diff changeset
13 import io
kono
parents:
diff changeset
14 from datetime import datetime
kono
parents:
diff changeset
15 from operator import attrgetter
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 # True if unrecognised lines should cause a fatal error. Might want to turn
kono
parents:
diff changeset
18 # this on by default later.
kono
parents:
diff changeset
19 strict = False
kono
parents:
diff changeset
20
kono
parents:
diff changeset
21 # True if the order of .log segments should match the .sum file, false if
kono
parents:
diff changeset
22 # they should keep the original order.
kono
parents:
diff changeset
23 sort_logs = True
kono
parents:
diff changeset
24
kono
parents:
diff changeset
25 # A version of open() that is safe against whatever binary output
kono
parents:
diff changeset
26 # might be added to the log.
kono
parents:
diff changeset
27 def safe_open (filename):
kono
parents:
diff changeset
28 if sys.version_info >= (3, 0):
kono
parents:
diff changeset
29 return open (filename, 'r', errors = 'surrogateescape')
kono
parents:
diff changeset
30 return open (filename, 'r')
kono
parents:
diff changeset
31
kono
parents:
diff changeset
32 # Force stdout to handle escape sequences from a safe_open file.
kono
parents:
diff changeset
33 if sys.version_info >= (3, 0):
kono
parents:
diff changeset
34 sys.stdout = io.TextIOWrapper (sys.stdout.buffer,
kono
parents:
diff changeset
35 errors = 'surrogateescape')
kono
parents:
diff changeset
36
kono
parents:
diff changeset
37 class Named:
kono
parents:
diff changeset
38 def __init__ (self, name):
kono
parents:
diff changeset
39 self.name = name
kono
parents:
diff changeset
40
kono
parents:
diff changeset
41 class ToolRun (Named):
kono
parents:
diff changeset
42 def __init__ (self, name):
kono
parents:
diff changeset
43 Named.__init__ (self, name)
kono
parents:
diff changeset
44 # The variations run for this tool, mapped by --target_board name.
kono
parents:
diff changeset
45 self.variations = dict()
kono
parents:
diff changeset
46
kono
parents:
diff changeset
47 # Return the VariationRun for variation NAME.
kono
parents:
diff changeset
48 def get_variation (self, name):
kono
parents:
diff changeset
49 if name not in self.variations:
kono
parents:
diff changeset
50 self.variations[name] = VariationRun (name)
kono
parents:
diff changeset
51 return self.variations[name]
kono
parents:
diff changeset
52
kono
parents:
diff changeset
53 class VariationRun (Named):
kono
parents:
diff changeset
54 def __init__ (self, name):
kono
parents:
diff changeset
55 Named.__init__ (self, name)
kono
parents:
diff changeset
56 # A segment of text before the harness runs start, describing which
kono
parents:
diff changeset
57 # baseboard files were loaded for the target.
kono
parents:
diff changeset
58 self.header = None
kono
parents:
diff changeset
59 # The harnesses run for this variation, mapped by filename.
kono
parents:
diff changeset
60 self.harnesses = dict()
kono
parents:
diff changeset
61 # A list giving the number of times each type of result has
kono
parents:
diff changeset
62 # been seen.
kono
parents:
diff changeset
63 self.counts = []
kono
parents:
diff changeset
64
kono
parents:
diff changeset
65 # Return the HarnessRun for harness NAME.
kono
parents:
diff changeset
66 def get_harness (self, name):
kono
parents:
diff changeset
67 if name not in self.harnesses:
kono
parents:
diff changeset
68 self.harnesses[name] = HarnessRun (name)
kono
parents:
diff changeset
69 return self.harnesses[name]
kono
parents:
diff changeset
70
kono
parents:
diff changeset
71 class HarnessRun (Named):
kono
parents:
diff changeset
72 def __init__ (self, name):
kono
parents:
diff changeset
73 Named.__init__ (self, name)
kono
parents:
diff changeset
74 # Segments of text that make up the harness run, mapped by a test-based
kono
parents:
diff changeset
75 # key that can be used to order them.
kono
parents:
diff changeset
76 self.segments = dict()
kono
parents:
diff changeset
77 # Segments of text that make up the harness run but which have
kono
parents:
diff changeset
78 # no recognized test results. These are typically harnesses that
kono
parents:
diff changeset
79 # are completely skipped for the target.
kono
parents:
diff changeset
80 self.empty = []
kono
parents:
diff changeset
81 # A list of results. Each entry is a pair in which the first element
kono
parents:
diff changeset
82 # is a unique sorting key and in which the second is the full
kono
parents:
diff changeset
83 # PASS/FAIL line.
kono
parents:
diff changeset
84 self.results = []
kono
parents:
diff changeset
85
kono
parents:
diff changeset
86 # Add a segment of text to the harness run. If the segment includes
kono
parents:
diff changeset
87 # test results, KEY is an example of one of them, and can be used to
kono
parents:
diff changeset
88 # combine the individual segments in order. If the segment has no
kono
parents:
diff changeset
89 # test results (e.g. because the harness doesn't do anything for the
kono
parents:
diff changeset
90 # current configuration) then KEY is None instead. In that case
kono
parents:
diff changeset
91 # just collect the segments in the order that we see them.
kono
parents:
diff changeset
92 def add_segment (self, key, segment):
kono
parents:
diff changeset
93 if key:
kono
parents:
diff changeset
94 assert key not in self.segments
kono
parents:
diff changeset
95 self.segments[key] = segment
kono
parents:
diff changeset
96 else:
kono
parents:
diff changeset
97 self.empty.append (segment)
kono
parents:
diff changeset
98
kono
parents:
diff changeset
99 class Segment:
kono
parents:
diff changeset
100 def __init__ (self, filename, start):
kono
parents:
diff changeset
101 self.filename = filename
kono
parents:
diff changeset
102 self.start = start
kono
parents:
diff changeset
103 self.lines = 0
kono
parents:
diff changeset
104
kono
parents:
diff changeset
105 class Prog:
kono
parents:
diff changeset
106 def __init__ (self):
kono
parents:
diff changeset
107 # The variations specified on the command line.
kono
parents:
diff changeset
108 self.variations = []
kono
parents:
diff changeset
109 # The variations seen in the input files.
kono
parents:
diff changeset
110 self.known_variations = set()
kono
parents:
diff changeset
111 # The tools specified on the command line.
kono
parents:
diff changeset
112 self.tools = []
kono
parents:
diff changeset
113 # Whether to create .sum rather than .log output.
kono
parents:
diff changeset
114 self.do_sum = True
kono
parents:
diff changeset
115 # Regexps used while parsing.
kono
parents:
diff changeset
116 self.test_run_re = re.compile (r'^Test Run By (\S+) on (.*)$')
kono
parents:
diff changeset
117 self.tool_re = re.compile (r'^\t\t=== (.*) tests ===$')
kono
parents:
diff changeset
118 self.result_re = re.compile (r'^(PASS|XPASS|FAIL|XFAIL|UNRESOLVED'
kono
parents:
diff changeset
119 r'|WARNING|ERROR|UNSUPPORTED|UNTESTED'
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
120 r'|KFAIL|KPASS):\s*(.+)')
111
kono
parents:
diff changeset
121 self.completed_re = re.compile (r'.* completed at (.*)')
kono
parents:
diff changeset
122 # Pieces of text to write at the head of the output.
kono
parents:
diff changeset
123 # start_line is a pair in which the first element is a datetime
kono
parents:
diff changeset
124 # and in which the second is the associated 'Test Run By' line.
kono
parents:
diff changeset
125 self.start_line = None
kono
parents:
diff changeset
126 self.native_line = ''
kono
parents:
diff changeset
127 self.target_line = ''
kono
parents:
diff changeset
128 self.host_line = ''
kono
parents:
diff changeset
129 self.acats_premable = ''
kono
parents:
diff changeset
130 # Pieces of text to write at the end of the output.
kono
parents:
diff changeset
131 # end_line is like start_line but for the 'runtest completed' line.
kono
parents:
diff changeset
132 self.acats_failures = []
kono
parents:
diff changeset
133 self.version_output = ''
kono
parents:
diff changeset
134 self.end_line = None
kono
parents:
diff changeset
135 # Known summary types.
kono
parents:
diff changeset
136 self.count_names = [
kono
parents:
diff changeset
137 '# of DejaGnu errors\t\t',
kono
parents:
diff changeset
138 '# of expected passes\t\t',
kono
parents:
diff changeset
139 '# of unexpected failures\t',
kono
parents:
diff changeset
140 '# of unexpected successes\t',
kono
parents:
diff changeset
141 '# of expected failures\t\t',
kono
parents:
diff changeset
142 '# of unknown successes\t\t',
kono
parents:
diff changeset
143 '# of known failures\t\t',
kono
parents:
diff changeset
144 '# of untested testcases\t\t',
kono
parents:
diff changeset
145 '# of unresolved testcases\t',
kono
parents:
diff changeset
146 '# of unsupported tests\t\t'
kono
parents:
diff changeset
147 ]
kono
parents:
diff changeset
148 self.runs = dict()
kono
parents:
diff changeset
149
kono
parents:
diff changeset
150 def usage (self):
kono
parents:
diff changeset
151 name = sys.argv[0]
kono
parents:
diff changeset
152 sys.stderr.write ('Usage: ' + name
kono
parents:
diff changeset
153 + ''' [-t tool] [-l variant-list] [-L] log-or-sum-file ...
kono
parents:
diff changeset
154
kono
parents:
diff changeset
155 tool The tool (e.g. g++, libffi) for which to create a
kono
parents:
diff changeset
156 new test summary file. If not specified then output
kono
parents:
diff changeset
157 is created for all tools.
kono
parents:
diff changeset
158 variant-list One or more test variant names. If the list is
kono
parents:
diff changeset
159 not specified then one is constructed from all
kono
parents:
diff changeset
160 variants in the files for <tool>.
kono
parents:
diff changeset
161 sum-file A test summary file with the format of those
kono
parents:
diff changeset
162 created by runtest from DejaGnu.
kono
parents:
diff changeset
163 If -L is used, merge *.log files instead of *.sum. In this
kono
parents:
diff changeset
164 mode the exact order of lines may not be preserved, just different
kono
parents:
diff changeset
165 Running *.exp chunks should be in correct order.
kono
parents:
diff changeset
166 ''')
kono
parents:
diff changeset
167 sys.exit (1)
kono
parents:
diff changeset
168
kono
parents:
diff changeset
169 def fatal (self, what, string):
kono
parents:
diff changeset
170 if not what:
kono
parents:
diff changeset
171 what = sys.argv[0]
kono
parents:
diff changeset
172 sys.stderr.write (what + ': ' + string + '\n')
kono
parents:
diff changeset
173 sys.exit (1)
kono
parents:
diff changeset
174
kono
parents:
diff changeset
175 # Parse the command-line arguments.
kono
parents:
diff changeset
176 def parse_cmdline (self):
kono
parents:
diff changeset
177 try:
kono
parents:
diff changeset
178 (options, self.files) = getopt.getopt (sys.argv[1:], 'l:t:L')
kono
parents:
diff changeset
179 if len (self.files) == 0:
kono
parents:
diff changeset
180 self.usage()
kono
parents:
diff changeset
181 for (option, value) in options:
kono
parents:
diff changeset
182 if option == '-l':
kono
parents:
diff changeset
183 self.variations.append (value)
kono
parents:
diff changeset
184 elif option == '-t':
kono
parents:
diff changeset
185 self.tools.append (value)
kono
parents:
diff changeset
186 else:
kono
parents:
diff changeset
187 self.do_sum = False
kono
parents:
diff changeset
188 except getopt.GetoptError as e:
kono
parents:
diff changeset
189 self.fatal (None, e.msg)
kono
parents:
diff changeset
190
kono
parents:
diff changeset
191 # Try to parse time string TIME, returning an arbitrary time on failure.
kono
parents:
diff changeset
192 # Getting this right is just a nice-to-have so failures should be silent.
kono
parents:
diff changeset
193 def parse_time (self, time):
kono
parents:
diff changeset
194 try:
kono
parents:
diff changeset
195 return datetime.strptime (time, '%c')
kono
parents:
diff changeset
196 except ValueError:
kono
parents:
diff changeset
197 return datetime.now()
kono
parents:
diff changeset
198
kono
parents:
diff changeset
199 # Parse an integer and abort on failure.
kono
parents:
diff changeset
200 def parse_int (self, filename, value):
kono
parents:
diff changeset
201 try:
kono
parents:
diff changeset
202 return int (value)
kono
parents:
diff changeset
203 except ValueError:
kono
parents:
diff changeset
204 self.fatal (filename, 'expected an integer, got: ' + value)
kono
parents:
diff changeset
205
kono
parents:
diff changeset
206 # Return a list that represents no test results.
kono
parents:
diff changeset
207 def zero_counts (self):
kono
parents:
diff changeset
208 return [0 for x in self.count_names]
kono
parents:
diff changeset
209
kono
parents:
diff changeset
210 # Return the ToolRun for tool NAME.
kono
parents:
diff changeset
211 def get_tool (self, name):
kono
parents:
diff changeset
212 if name not in self.runs:
kono
parents:
diff changeset
213 self.runs[name] = ToolRun (name)
kono
parents:
diff changeset
214 return self.runs[name]
kono
parents:
diff changeset
215
kono
parents:
diff changeset
216 # Add the result counts in list FROMC to TOC.
kono
parents:
diff changeset
217 def accumulate_counts (self, toc, fromc):
kono
parents:
diff changeset
218 for i in range (len (self.count_names)):
kono
parents:
diff changeset
219 toc[i] += fromc[i]
kono
parents:
diff changeset
220
kono
parents:
diff changeset
221 # Parse the list of variations after 'Schedule of variations:'.
kono
parents:
diff changeset
222 # Return the number seen.
kono
parents:
diff changeset
223 def parse_variations (self, filename, file):
kono
parents:
diff changeset
224 num_variations = 0
kono
parents:
diff changeset
225 while True:
kono
parents:
diff changeset
226 line = file.readline()
kono
parents:
diff changeset
227 if line == '':
kono
parents:
diff changeset
228 self.fatal (filename, 'could not parse variation list')
kono
parents:
diff changeset
229 if line == '\n':
kono
parents:
diff changeset
230 break
kono
parents:
diff changeset
231 self.known_variations.add (line.strip())
kono
parents:
diff changeset
232 num_variations += 1
kono
parents:
diff changeset
233 return num_variations
kono
parents:
diff changeset
234
kono
parents:
diff changeset
235 # Parse from the first line after 'Running target ...' to the end
kono
parents:
diff changeset
236 # of the run's summary.
kono
parents:
diff changeset
237 def parse_run (self, filename, file, tool, variation, num_variations):
kono
parents:
diff changeset
238 header = None
kono
parents:
diff changeset
239 harness = None
kono
parents:
diff changeset
240 segment = None
kono
parents:
diff changeset
241 final_using = 0
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
242 has_warning = 0
111
kono
parents:
diff changeset
243
kono
parents:
diff changeset
244 # If this is the first run for this variation, add any text before
kono
parents:
diff changeset
245 # the first harness to the header.
kono
parents:
diff changeset
246 if not variation.header:
kono
parents:
diff changeset
247 segment = Segment (filename, file.tell())
kono
parents:
diff changeset
248 variation.header = segment
kono
parents:
diff changeset
249
kono
parents:
diff changeset
250 # Parse the rest of the summary (the '# of ' lines).
kono
parents:
diff changeset
251 if len (variation.counts) == 0:
kono
parents:
diff changeset
252 variation.counts = self.zero_counts()
kono
parents:
diff changeset
253
kono
parents:
diff changeset
254 # Parse up until the first line of the summary.
kono
parents:
diff changeset
255 if num_variations == 1:
kono
parents:
diff changeset
256 end = '\t\t=== ' + tool.name + ' Summary ===\n'
kono
parents:
diff changeset
257 else:
kono
parents:
diff changeset
258 end = ('\t\t=== ' + tool.name + ' Summary for '
kono
parents:
diff changeset
259 + variation.name + ' ===\n')
kono
parents:
diff changeset
260 while True:
kono
parents:
diff changeset
261 line = file.readline()
kono
parents:
diff changeset
262 if line == '':
kono
parents:
diff changeset
263 self.fatal (filename, 'no recognised summary line')
kono
parents:
diff changeset
264 if line == end:
kono
parents:
diff changeset
265 break
kono
parents:
diff changeset
266
kono
parents:
diff changeset
267 # Look for the start of a new harness.
kono
parents:
diff changeset
268 if line.startswith ('Running ') and line.endswith (' ...\n'):
kono
parents:
diff changeset
269 # Close off the current harness segment, if any.
kono
parents:
diff changeset
270 if harness:
kono
parents:
diff changeset
271 segment.lines -= final_using
kono
parents:
diff changeset
272 harness.add_segment (first_key, segment)
kono
parents:
diff changeset
273 name = line[len ('Running '):-len(' ...\n')]
kono
parents:
diff changeset
274 harness = variation.get_harness (name)
kono
parents:
diff changeset
275 segment = Segment (filename, file.tell())
kono
parents:
diff changeset
276 first_key = None
kono
parents:
diff changeset
277 final_using = 0
kono
parents:
diff changeset
278 continue
kono
parents:
diff changeset
279
kono
parents:
diff changeset
280 # Record test results. Associate the first test result with
kono
parents:
diff changeset
281 # the harness segment, so that if a run for a particular harness
kono
parents:
diff changeset
282 # has been split up, we can reassemble the individual segments
kono
parents:
diff changeset
283 # in a sensible order.
kono
parents:
diff changeset
284 #
kono
parents:
diff changeset
285 # dejagnu sometimes issues warnings about the testing environment
kono
parents:
diff changeset
286 # before running any tests. Treat them as part of the header
kono
parents:
diff changeset
287 # rather than as a test result.
kono
parents:
diff changeset
288 match = self.result_re.match (line)
kono
parents:
diff changeset
289 if match and (harness or not line.startswith ('WARNING:')):
kono
parents:
diff changeset
290 if not harness:
kono
parents:
diff changeset
291 self.fatal (filename, 'saw test result before harness name')
kono
parents:
diff changeset
292 name = match.group (2)
kono
parents:
diff changeset
293 # Ugly hack to get the right order for gfortran.
kono
parents:
diff changeset
294 if name.startswith ('gfortran.dg/g77/'):
kono
parents:
diff changeset
295 name = 'h' + name
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
296 # If we have a time out warning, make sure it appears
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
297 # before the following testcase diagnostic: we insert
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
298 # the testname before 'program' so that sort faces a
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
299 # list of testnames.
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
300 if line.startswith ('WARNING: program timed out'):
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
301 has_warning = 1
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
302 else:
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
303 if has_warning == 1:
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
304 key = (name, len (harness.results))
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
305 myline = 'WARNING: %s program timed out.\n' % name
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
306 harness.results.append ((key, myline))
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
307 has_warning = 0
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
308 key = (name, len (harness.results))
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
309 harness.results.append ((key, line))
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
310 if not first_key and sort_logs:
1830386684a0 gcc-9.2.0
anatofuz
parents: 111
diff changeset
311 first_key = key
111
kono
parents:
diff changeset
312 if line.startswith ('ERROR: (DejaGnu)'):
kono
parents:
diff changeset
313 for i in range (len (self.count_names)):
kono
parents:
diff changeset
314 if 'DejaGnu errors' in self.count_names[i]:
kono
parents:
diff changeset
315 variation.counts[i] += 1
kono
parents:
diff changeset
316 break
kono
parents:
diff changeset
317
kono
parents:
diff changeset
318 # 'Using ...' lines are only interesting in a header. Splitting
kono
parents:
diff changeset
319 # the test up into parallel runs leads to more 'Using ...' lines
kono
parents:
diff changeset
320 # than there would be in a single log.
kono
parents:
diff changeset
321 if line.startswith ('Using '):
kono
parents:
diff changeset
322 final_using += 1
kono
parents:
diff changeset
323 else:
kono
parents:
diff changeset
324 final_using = 0
kono
parents:
diff changeset
325
kono
parents:
diff changeset
326 # Add other text to the current segment, if any.
kono
parents:
diff changeset
327 if segment:
kono
parents:
diff changeset
328 segment.lines += 1
kono
parents:
diff changeset
329
kono
parents:
diff changeset
330 # Close off the final harness segment, if any.
kono
parents:
diff changeset
331 if harness:
kono
parents:
diff changeset
332 segment.lines -= final_using
kono
parents:
diff changeset
333 harness.add_segment (first_key, segment)
kono
parents:
diff changeset
334
kono
parents:
diff changeset
335 while True:
kono
parents:
diff changeset
336 before = file.tell()
kono
parents:
diff changeset
337 line = file.readline()
kono
parents:
diff changeset
338 if line == '':
kono
parents:
diff changeset
339 break
kono
parents:
diff changeset
340 if line == '\n':
kono
parents:
diff changeset
341 continue
kono
parents:
diff changeset
342 if not line.startswith ('# '):
kono
parents:
diff changeset
343 file.seek (before)
kono
parents:
diff changeset
344 break
kono
parents:
diff changeset
345 found = False
kono
parents:
diff changeset
346 for i in range (len (self.count_names)):
kono
parents:
diff changeset
347 if line.startswith (self.count_names[i]):
kono
parents:
diff changeset
348 count = line[len (self.count_names[i]):-1].strip()
kono
parents:
diff changeset
349 variation.counts[i] += self.parse_int (filename, count)
kono
parents:
diff changeset
350 found = True
kono
parents:
diff changeset
351 break
kono
parents:
diff changeset
352 if not found:
kono
parents:
diff changeset
353 self.fatal (filename, 'unknown test result: ' + line[:-1])
kono
parents:
diff changeset
354
kono
parents:
diff changeset
355 # Parse an acats run, which uses a different format from dejagnu.
kono
parents:
diff changeset
356 # We have just skipped over '=== acats configuration ==='.
kono
parents:
diff changeset
357 def parse_acats_run (self, filename, file):
kono
parents:
diff changeset
358 # Parse the preamble, which describes the configuration and logs
kono
parents:
diff changeset
359 # the creation of support files.
kono
parents:
diff changeset
360 record = (self.acats_premable == '')
kono
parents:
diff changeset
361 if record:
kono
parents:
diff changeset
362 self.acats_premable = '\t\t=== acats configuration ===\n'
kono
parents:
diff changeset
363 while True:
kono
parents:
diff changeset
364 line = file.readline()
kono
parents:
diff changeset
365 if line == '':
kono
parents:
diff changeset
366 self.fatal (filename, 'could not parse acats preamble')
kono
parents:
diff changeset
367 if line == '\t\t=== acats tests ===\n':
kono
parents:
diff changeset
368 break
kono
parents:
diff changeset
369 if record:
kono
parents:
diff changeset
370 self.acats_premable += line
kono
parents:
diff changeset
371
kono
parents:
diff changeset
372 # Parse the test results themselves, using a dummy variation name.
kono
parents:
diff changeset
373 tool = self.get_tool ('acats')
kono
parents:
diff changeset
374 variation = tool.get_variation ('none')
kono
parents:
diff changeset
375 self.parse_run (filename, file, tool, variation, 1)
kono
parents:
diff changeset
376
kono
parents:
diff changeset
377 # Parse the failure list.
kono
parents:
diff changeset
378 while True:
kono
parents:
diff changeset
379 before = file.tell()
kono
parents:
diff changeset
380 line = file.readline()
kono
parents:
diff changeset
381 if line.startswith ('*** FAILURES: '):
kono
parents:
diff changeset
382 self.acats_failures.append (line[len ('*** FAILURES: '):-1])
kono
parents:
diff changeset
383 continue
kono
parents:
diff changeset
384 file.seek (before)
kono
parents:
diff changeset
385 break
kono
parents:
diff changeset
386
kono
parents:
diff changeset
387 # Parse the final summary at the end of a log in order to capture
kono
parents:
diff changeset
388 # the version output that follows it.
kono
parents:
diff changeset
389 def parse_final_summary (self, filename, file):
kono
parents:
diff changeset
390 record = (self.version_output == '')
kono
parents:
diff changeset
391 while True:
kono
parents:
diff changeset
392 line = file.readline()
kono
parents:
diff changeset
393 if line == '':
kono
parents:
diff changeset
394 break
kono
parents:
diff changeset
395 if line.startswith ('# of '):
kono
parents:
diff changeset
396 continue
kono
parents:
diff changeset
397 if record:
kono
parents:
diff changeset
398 self.version_output += line
kono
parents:
diff changeset
399 if line == '\n':
kono
parents:
diff changeset
400 break
kono
parents:
diff changeset
401
kono
parents:
diff changeset
402 # Parse a .log or .sum file.
kono
parents:
diff changeset
403 def parse_file (self, filename, file):
kono
parents:
diff changeset
404 tool = None
kono
parents:
diff changeset
405 target = None
kono
parents:
diff changeset
406 num_variations = 1
kono
parents:
diff changeset
407 while True:
kono
parents:
diff changeset
408 line = file.readline()
kono
parents:
diff changeset
409 if line == '':
kono
parents:
diff changeset
410 return
kono
parents:
diff changeset
411
kono
parents:
diff changeset
412 # Parse the list of variations, which comes before the test
kono
parents:
diff changeset
413 # runs themselves.
kono
parents:
diff changeset
414 if line.startswith ('Schedule of variations:'):
kono
parents:
diff changeset
415 num_variations = self.parse_variations (filename, file)
kono
parents:
diff changeset
416 continue
kono
parents:
diff changeset
417
kono
parents:
diff changeset
418 # Parse a testsuite run for one tool/variation combination.
kono
parents:
diff changeset
419 if line.startswith ('Running target '):
kono
parents:
diff changeset
420 name = line[len ('Running target '):-1]
kono
parents:
diff changeset
421 if not tool:
kono
parents:
diff changeset
422 self.fatal (filename, 'could not parse tool name')
kono
parents:
diff changeset
423 if name not in self.known_variations:
kono
parents:
diff changeset
424 self.fatal (filename, 'unknown target: ' + name)
kono
parents:
diff changeset
425 self.parse_run (filename, file, tool,
kono
parents:
diff changeset
426 tool.get_variation (name),
kono
parents:
diff changeset
427 num_variations)
kono
parents:
diff changeset
428 # If there is only one variation then there is no separate
kono
parents:
diff changeset
429 # summary for it. Record any following version output.
kono
parents:
diff changeset
430 if num_variations == 1:
kono
parents:
diff changeset
431 self.parse_final_summary (filename, file)
kono
parents:
diff changeset
432 continue
kono
parents:
diff changeset
433
kono
parents:
diff changeset
434 # Parse the start line. In the case where several files are being
kono
parents:
diff changeset
435 # parsed, pick the one with the earliest time.
kono
parents:
diff changeset
436 match = self.test_run_re.match (line)
kono
parents:
diff changeset
437 if match:
kono
parents:
diff changeset
438 time = self.parse_time (match.group (2))
kono
parents:
diff changeset
439 if not self.start_line or self.start_line[0] > time:
kono
parents:
diff changeset
440 self.start_line = (time, line)
kono
parents:
diff changeset
441 continue
kono
parents:
diff changeset
442
kono
parents:
diff changeset
443 # Parse the form used for native testing.
kono
parents:
diff changeset
444 if line.startswith ('Native configuration is '):
kono
parents:
diff changeset
445 self.native_line = line
kono
parents:
diff changeset
446 continue
kono
parents:
diff changeset
447
kono
parents:
diff changeset
448 # Parse the target triplet.
kono
parents:
diff changeset
449 if line.startswith ('Target is '):
kono
parents:
diff changeset
450 self.target_line = line
kono
parents:
diff changeset
451 continue
kono
parents:
diff changeset
452
kono
parents:
diff changeset
453 # Parse the host triplet.
kono
parents:
diff changeset
454 if line.startswith ('Host is '):
kono
parents:
diff changeset
455 self.host_line = line
kono
parents:
diff changeset
456 continue
kono
parents:
diff changeset
457
kono
parents:
diff changeset
458 # Parse the acats premable.
kono
parents:
diff changeset
459 if line == '\t\t=== acats configuration ===\n':
kono
parents:
diff changeset
460 self.parse_acats_run (filename, file)
kono
parents:
diff changeset
461 continue
kono
parents:
diff changeset
462
kono
parents:
diff changeset
463 # Parse the tool name.
kono
parents:
diff changeset
464 match = self.tool_re.match (line)
kono
parents:
diff changeset
465 if match:
kono
parents:
diff changeset
466 tool = self.get_tool (match.group (1))
kono
parents:
diff changeset
467 continue
kono
parents:
diff changeset
468
kono
parents:
diff changeset
469 # Skip over the final summary (which we instead create from
kono
parents:
diff changeset
470 # individual runs) and parse the version output.
kono
parents:
diff changeset
471 if tool and line == '\t\t=== ' + tool.name + ' Summary ===\n':
kono
parents:
diff changeset
472 if file.readline() != '\n':
kono
parents:
diff changeset
473 self.fatal (filename, 'expected blank line after summary')
kono
parents:
diff changeset
474 self.parse_final_summary (filename, file)
kono
parents:
diff changeset
475 continue
kono
parents:
diff changeset
476
kono
parents:
diff changeset
477 # Parse the completion line. In the case where several files
kono
parents:
diff changeset
478 # are being parsed, pick the one with the latest time.
kono
parents:
diff changeset
479 match = self.completed_re.match (line)
kono
parents:
diff changeset
480 if match:
kono
parents:
diff changeset
481 time = self.parse_time (match.group (1))
kono
parents:
diff changeset
482 if not self.end_line or self.end_line[0] < time:
kono
parents:
diff changeset
483 self.end_line = (time, line)
kono
parents:
diff changeset
484 continue
kono
parents:
diff changeset
485
kono
parents:
diff changeset
486 # Sanity check to make sure that important text doesn't get
kono
parents:
diff changeset
487 # dropped accidentally.
kono
parents:
diff changeset
488 if strict and line.strip() != '':
kono
parents:
diff changeset
489 self.fatal (filename, 'unrecognised line: ' + line[:-1])
kono
parents:
diff changeset
490
kono
parents:
diff changeset
491 # Output a segment of text.
kono
parents:
diff changeset
492 def output_segment (self, segment):
kono
parents:
diff changeset
493 with safe_open (segment.filename) as file:
kono
parents:
diff changeset
494 file.seek (segment.start)
kono
parents:
diff changeset
495 for i in range (segment.lines):
kono
parents:
diff changeset
496 sys.stdout.write (file.readline())
kono
parents:
diff changeset
497
kono
parents:
diff changeset
498 # Output a summary giving the number of times each type of result has
kono
parents:
diff changeset
499 # been seen.
kono
parents:
diff changeset
500 def output_summary (self, tool, counts):
kono
parents:
diff changeset
501 for i in range (len (self.count_names)):
kono
parents:
diff changeset
502 name = self.count_names[i]
kono
parents:
diff changeset
503 # dejagnu only prints result types that were seen at least once,
kono
parents:
diff changeset
504 # but acats always prints a number of unexpected failures.
kono
parents:
diff changeset
505 if (counts[i] > 0
kono
parents:
diff changeset
506 or (tool.name == 'acats'
kono
parents:
diff changeset
507 and name.startswith ('# of unexpected failures'))):
kono
parents:
diff changeset
508 sys.stdout.write ('%s%d\n' % (name, counts[i]))
kono
parents:
diff changeset
509
kono
parents:
diff changeset
510 # Output unified .log or .sum information for a particular variation,
kono
parents:
diff changeset
511 # with a summary at the end.
kono
parents:
diff changeset
512 def output_variation (self, tool, variation):
kono
parents:
diff changeset
513 self.output_segment (variation.header)
kono
parents:
diff changeset
514 for harness in sorted (variation.harnesses.values(),
kono
parents:
diff changeset
515 key = attrgetter ('name')):
kono
parents:
diff changeset
516 sys.stdout.write ('Running ' + harness.name + ' ...\n')
kono
parents:
diff changeset
517 if self.do_sum:
kono
parents:
diff changeset
518 harness.results.sort()
kono
parents:
diff changeset
519 for (key, line) in harness.results:
kono
parents:
diff changeset
520 sys.stdout.write (line)
kono
parents:
diff changeset
521 else:
kono
parents:
diff changeset
522 # Rearrange the log segments into test order (but without
kono
parents:
diff changeset
523 # rearranging text within those segments).
kono
parents:
diff changeset
524 for key in sorted (harness.segments.keys()):
kono
parents:
diff changeset
525 self.output_segment (harness.segments[key])
kono
parents:
diff changeset
526 for segment in harness.empty:
kono
parents:
diff changeset
527 self.output_segment (segment)
kono
parents:
diff changeset
528 if len (self.variations) > 1:
kono
parents:
diff changeset
529 sys.stdout.write ('\t\t=== ' + tool.name + ' Summary for '
kono
parents:
diff changeset
530 + variation.name + ' ===\n\n')
kono
parents:
diff changeset
531 self.output_summary (tool, variation.counts)
kono
parents:
diff changeset
532
kono
parents:
diff changeset
533 # Output unified .log or .sum information for a particular tool,
kono
parents:
diff changeset
534 # with a summary at the end.
kono
parents:
diff changeset
535 def output_tool (self, tool):
kono
parents:
diff changeset
536 counts = self.zero_counts()
kono
parents:
diff changeset
537 if tool.name == 'acats':
kono
parents:
diff changeset
538 # acats doesn't use variations, so just output everything.
kono
parents:
diff changeset
539 # It also has a different approach to whitespace.
kono
parents:
diff changeset
540 sys.stdout.write ('\t\t=== ' + tool.name + ' tests ===\n')
kono
parents:
diff changeset
541 for variation in tool.variations.values():
kono
parents:
diff changeset
542 self.output_variation (tool, variation)
kono
parents:
diff changeset
543 self.accumulate_counts (counts, variation.counts)
kono
parents:
diff changeset
544 sys.stdout.write ('\t\t=== ' + tool.name + ' Summary ===\n')
kono
parents:
diff changeset
545 else:
kono
parents:
diff changeset
546 # Output the results in the usual dejagnu runtest format.
kono
parents:
diff changeset
547 sys.stdout.write ('\n\t\t=== ' + tool.name + ' tests ===\n\n'
kono
parents:
diff changeset
548 'Schedule of variations:\n')
kono
parents:
diff changeset
549 for name in self.variations:
kono
parents:
diff changeset
550 if name in tool.variations:
kono
parents:
diff changeset
551 sys.stdout.write (' ' + name + '\n')
kono
parents:
diff changeset
552 sys.stdout.write ('\n')
kono
parents:
diff changeset
553 for name in self.variations:
kono
parents:
diff changeset
554 if name in tool.variations:
kono
parents:
diff changeset
555 variation = tool.variations[name]
kono
parents:
diff changeset
556 sys.stdout.write ('Running target '
kono
parents:
diff changeset
557 + variation.name + '\n')
kono
parents:
diff changeset
558 self.output_variation (tool, variation)
kono
parents:
diff changeset
559 self.accumulate_counts (counts, variation.counts)
kono
parents:
diff changeset
560 sys.stdout.write ('\n\t\t=== ' + tool.name + ' Summary ===\n\n')
kono
parents:
diff changeset
561 self.output_summary (tool, counts)
kono
parents:
diff changeset
562
kono
parents:
diff changeset
563 def main (self):
kono
parents:
diff changeset
564 self.parse_cmdline()
kono
parents:
diff changeset
565 try:
kono
parents:
diff changeset
566 # Parse the input files.
kono
parents:
diff changeset
567 for filename in self.files:
kono
parents:
diff changeset
568 with safe_open (filename) as file:
kono
parents:
diff changeset
569 self.parse_file (filename, file)
kono
parents:
diff changeset
570
kono
parents:
diff changeset
571 # Decide what to output.
kono
parents:
diff changeset
572 if len (self.variations) == 0:
kono
parents:
diff changeset
573 self.variations = sorted (self.known_variations)
kono
parents:
diff changeset
574 else:
kono
parents:
diff changeset
575 for name in self.variations:
kono
parents:
diff changeset
576 if name not in self.known_variations:
kono
parents:
diff changeset
577 self.fatal (None, 'no results for ' + name)
kono
parents:
diff changeset
578 if len (self.tools) == 0:
kono
parents:
diff changeset
579 self.tools = sorted (self.runs.keys())
kono
parents:
diff changeset
580
kono
parents:
diff changeset
581 # Output the header.
kono
parents:
diff changeset
582 if self.start_line:
kono
parents:
diff changeset
583 sys.stdout.write (self.start_line[1])
kono
parents:
diff changeset
584 sys.stdout.write (self.native_line)
kono
parents:
diff changeset
585 sys.stdout.write (self.target_line)
kono
parents:
diff changeset
586 sys.stdout.write (self.host_line)
kono
parents:
diff changeset
587 sys.stdout.write (self.acats_premable)
kono
parents:
diff changeset
588
kono
parents:
diff changeset
589 # Output the main body.
kono
parents:
diff changeset
590 for name in self.tools:
kono
parents:
diff changeset
591 if name not in self.runs:
kono
parents:
diff changeset
592 self.fatal (None, 'no results for ' + name)
kono
parents:
diff changeset
593 self.output_tool (self.runs[name])
kono
parents:
diff changeset
594
kono
parents:
diff changeset
595 # Output the footer.
kono
parents:
diff changeset
596 if len (self.acats_failures) > 0:
kono
parents:
diff changeset
597 sys.stdout.write ('*** FAILURES: '
kono
parents:
diff changeset
598 + ' '.join (self.acats_failures) + '\n')
kono
parents:
diff changeset
599 sys.stdout.write (self.version_output)
kono
parents:
diff changeset
600 if self.end_line:
kono
parents:
diff changeset
601 sys.stdout.write (self.end_line[1])
kono
parents:
diff changeset
602 except IOError as e:
kono
parents:
diff changeset
603 self.fatal (e.filename, e.strerror)
kono
parents:
diff changeset
604
kono
parents:
diff changeset
605 Prog().main()