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