manifest.py revision f2a3ef46f75d2196a93d3ed27f4d1fcf22b54fbe
1# Copyright 2011 Google Inc. All Rights Reserved.
2# Author: kbaclawski@google.com (Krystian Baclawski)
3#
4
5__author__ = 'kbaclawski@google.com (Krystian Baclawski)'
6
7from collections import namedtuple
8from cStringIO import StringIO
9import logging
10
11from summary import DejaGnuTestResult
12
13
14class Manifest(namedtuple('Manifest', 'tool board results')):
15  """Stores a list of unsuccessful tests.
16
17  Any line that starts with '#@' marker carries auxiliary data in form of a
18  key-value pair, for example:
19
20  #@ tool: *
21  #@ board: unix
22
23  So far tool and board parameters are recognized.  Their value can contain
24  arbitrary glob expression.  Based on aforementioned parameters given manifest
25  will be applied for all test results, but only in selected test runs.  Note
26  that all parameters are optional.  Their default value is '*' (i.e. for all
27  tools/boards).
28
29  The meaning of lines above is as follows: corresponding test results to follow
30  should only be suppressed if test run was performed on "unix" board.
31
32  The summary line used to build the test result should have this format:
33
34  attrlist | UNRESOLVED: gcc.dg/unroll_1.c (test for excess errors)
35  ^^^^^^^^   ^^^^^^^^^^  ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^
36  optional   result      name              variant
37  attributes
38  """
39  SUPPRESSIBLE_RESULTS = ['FAIL', 'UNRESOLVED', 'XPASS', 'ERROR']
40
41  @classmethod
42  def FromDejaGnuTestRun(cls, test_run):
43    results = [result
44               for result in test_run.results
45               if result.result in cls.SUPPRESSIBLE_RESULTS]
46
47    return cls(test_run.tool, test_run.board, results)
48
49  @classmethod
50  def FromFile(cls, filename):
51    """Creates manifest instance from a file in format described above."""
52    params = {}
53    results = []
54
55    with open(filename, 'r') as manifest_file:
56      for line in manifest_file:
57        if line.startswith('#@'):
58          # parse a line with a parameter
59          try:
60            key, value = line[2:].split(':', 1)
61          except ValueError:
62            logging.warning('Malformed parameter line: "%s".', line)
63          else:
64            params[key.strip()] = value.strip()
65        else:
66          # remove comment
67          try:
68            line, _ = line.split('#', 1)
69          except ValueError:
70            pass
71
72          line = line.strip()
73
74          if line:
75            # parse a line with a test result
76            result = DejaGnuTestResult.FromLine(line)
77
78            if result:
79              results.append(result)
80            else:
81              logging.warning('Malformed test result line: "%s".', line)
82
83    tool = params.get('tool', '*')
84    board = params.get('board', '*')
85
86    return cls(tool, board, results)
87
88  def Generate(self):
89    """Dumps manifest to string."""
90    text = StringIO()
91
92    for name in ['tool', 'board']:
93      text.write('#@ {0}: {1}\n'.format(name, getattr(self, name)))
94
95    text.write('\n')
96
97    for result in sorted(self.results, key=lambda r: r.result):
98      text.write('{0}\n'.format(result))
99
100    return text.getvalue()
101
102  def __iter__(self):
103    return iter(self.results)
104