1##########################################################################
2# Copyright (c) 2009, ETH Zurich.
3# All rights reserved.
4#
5# This file is distributed under the terms in the attached LICENSE file.
6# If you do not find this file, copies can be found by writing to:
7# ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
8##########################################################################
9
10from stats import Stats
11
12class ResultsBase(object):
13    def __init__(self, name=None, reason=""):
14        self.name = name
15        self.fail_reason = reason
16
17    def reason(self):
18        return self.fail_reason
19
20    def passed(self):
21        """Returns true iff the test is considered to have passed."""
22        raise NotImplementedError
23
24    def to_file(self, filehandle):
25        """May be used to write formatted results to a file."""
26        raise NotImplementedError
27
28
29class PassFailResult(ResultsBase):
30    """Stores results of test that is purely pass/fail."""
31    def __init__(self, passed, reason=""):
32        super(PassFailResult, self).__init__(reason=reason)
33        self.passfail = passed
34
35    def passed(self):
36        return self.passfail
37
38
39class PassFailMultiResult(ResultsBase):
40    def __init__(self, name, errors=[]):
41        self.errors = errors
42        self.name = name
43
44    def reason(self):
45        return str(self.errors)
46
47    def passed(self):
48        return len(self.errors) == 0
49
50    def to_file(self, fh):
51        if len(self.errors) > 0:
52            fh.write('%d error(s) in %s\n' % (len(self.errors), self.name))
53            for error in self.errors:
54                fh.write(error)
55
56class RowResults(ResultsBase):
57    """Results class that maintains numeric values grouped by rows.
58    """
59    def __init__(self, colnames, name=None):
60        super(RowResults, self).__init__(name)
61        self.colnames = colnames
62        self.rows = []
63        self.failed = False
64
65    def passed(self):
66        if self.failed:
67            return False
68        return self.rows != []
69
70    def to_file(self, fh):
71        """Produce a file in a format suitable for gnuplot."""
72        fh.write('# %s\n' % '\t'.join(self.colnames))
73        for r in self.rows:
74            fh.write('\t'.join(map(str, r)) + '\n')
75
76    def mark_failed(self, reason):
77        """Mark this test as having failed."""
78        self.failed = True
79        self.fail_reason = reason
80
81    def add_row(self, row):
82        assert(len(row) == len(self.colnames))
83        self.rows.append(row)
84
85
86class RawResults(RowResults):
87    """Results class suitable for processing statistics on raw data
88    (eg. microbenchmarks where we have each individual measurement)"""
89
90    def __init__(self, groupheader, name=None):
91        headers = 'nvalues median mean stddev min max'.split()
92        super(RawResults, self).__init__([groupheader] + headers, name=name)
93
94    def add_group(self, identifier, data):
95        st = Stats(data)
96        self.add_row([identifier, st.nvalues, st.median, st.mean, st.stddev,
97                      st.minimum, st.maximum])
98