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