[lit] Change lit.Test.ResultCode to be unique across pickling.
[oota-llvm.git] / utils / lit / lit / Test.py
1 import os
2
3 # Test results.
4
5 class ResultCode(object):
6     """Test result codes."""
7
8     # We override __new__ and __getnewargs__ to ensure that pickling still
9     # provides unique ResultCode objects in any particular instance.
10     _instances = {}
11     def __new__(cls, name, isFailure):
12         res = cls._instances.get(name)
13         if res is None:
14             cls._instances[name] = res = super(ResultCode, cls).__new__(cls)
15         return res
16     def __getnewargs__(self):
17         return (self.name, self.isFailure)
18
19     def __init__(self, name, isFailure):
20         self.name = name
21         self.isFailure = isFailure
22
23     def __repr__(self):
24         return '%s%r' % (self.__class__.__name__,
25                          (self.name, self.isFailure))
26
27 PASS        = ResultCode('PASS', False)
28 XFAIL       = ResultCode('XFAIL', False)
29 FAIL        = ResultCode('FAIL', True)
30 XPASS       = ResultCode('XPASS', True)
31 UNRESOLVED  = ResultCode('UNRESOLVED', True)
32 UNSUPPORTED = ResultCode('UNSUPPORTED', False)
33
34 class Result(object):
35     """Wrapper for the results of executing an individual test."""
36
37     def __init__(self, code, output='', elapsed=None):
38         # The result code.
39         self.code = code
40         # The test output.
41         self.output = output
42         # The wall timing to execute the test, if timing.
43         self.elapsed = elapsed
44
45 # Test classes.
46
47 class TestSuite:
48     """TestSuite - Information on a group of tests.
49
50     A test suite groups together a set of logically related tests.
51     """
52
53     def __init__(self, name, source_root, exec_root, config):
54         self.name = name
55         self.source_root = source_root
56         self.exec_root = exec_root
57         # The test suite configuration.
58         self.config = config
59
60     def getSourcePath(self, components):
61         return os.path.join(self.source_root, *components)
62
63     def getExecPath(self, components):
64         return os.path.join(self.exec_root, *components)
65
66 class Test:
67     """Test - Information on a single test instance."""
68
69     def __init__(self, suite, path_in_suite, config):
70         self.suite = suite
71         self.path_in_suite = path_in_suite
72         self.config = config
73         # A list of conditions under which this test is expected to fail. These
74         # can optionally be provided by test format handlers, and will be
75         # honored when the test result is supplied.
76         self.xfails = []
77         # The test result, once complete.
78         self.result = None
79
80     def setResult(self, result):
81         if self.result is not None:
82             raise ArgumentError("test result already set")
83         if not isinstance(result, Result):
84             raise ArgumentError("unexpected result type")
85
86         self.result = result
87
88         # Apply the XFAIL handling to resolve the result exit code.
89         if self.isExpectedToFail():
90             if self.result.code == PASS:
91                 self.result.code = XPASS
92             elif self.result.code == FAIL:
93                 self.result.code = XFAIL
94         
95     def getFullName(self):
96         return self.suite.config.name + ' :: ' + '/'.join(self.path_in_suite)
97
98     def getSourcePath(self):
99         return self.suite.getSourcePath(self.path_in_suite)
100
101     def getExecPath(self):
102         return self.suite.getExecPath(self.path_in_suite)
103
104     def isExpectedToFail(self):
105         """
106         isExpectedToFail() -> bool
107
108         Check whether this test is expected to fail in the current
109         configuration. This check relies on the test xfails property which by
110         some test formats may not be computed until the test has first been
111         executed.
112         """
113
114         # Check if any of the xfails match an available feature or the target.
115         for item in self.xfails:
116             # If this is the wildcard, it always fails.
117             if item == '*':
118                 return True
119
120             # If this is an exact match for one of the features, it fails.
121             if item in self.config.available_features:
122                 return True
123
124             # If this is a part of the target triple, it fails.
125             if item in self.suite.config.target_triple:
126                 return True
127
128         return False