blob: b1749ebcc3e8768fc3dc11e07663c24b7ee63c2e [file] [log] [blame]
Zachary Turnerb4733e62015-12-08 01:15:44 +00001"""
2 The LLVM Compiler Infrastructure
3
4This file is distributed under the University of Illinois Open Source
5License. See LICENSE.TXT for details.
6
7Provides the LLDBTestResult class, which holds information about progress
8and results of a single test run.
9"""
10
11from __future__ import absolute_import
12from __future__ import print_function
13
14# System modules
15import inspect
Zachary Turnerb4733e62015-12-08 01:15:44 +000016
17# Third-party modules
18import unittest2
19
20# LLDB Modules
21import lldbsuite
22from . import configuration
23from .result_formatter import EventBuilder
24
25
26class LLDBTestResult(unittest2.TextTestResult):
27 """
28 Enforce a singleton pattern to allow introspection of test progress.
29
30 Overwrite addError(), addFailure(), and addExpectedFailure() methods
31 to enable each test instance to track its failure/error status. It
32 is used in the LLDB test framework to emit detailed trace messages
33 to a log file for easier human inspection of test failures/errors.
34 """
35 __singleton__ = None
36 __ignore_singleton__ = False
37
38 @staticmethod
39 def getTerminalSize():
40 import os
41 env = os.environ
42 def ioctl_GWINSZ(fd):
43 try:
44 import fcntl, termios, struct, os
45 cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,
46 '1234'))
47 except:
48 return
49 return cr
50 cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
51 if not cr:
52 try:
53 fd = os.open(os.ctermid(), os.O_RDONLY)
54 cr = ioctl_GWINSZ(fd)
55 os.close(fd)
56 except:
57 pass
58 if not cr:
59 cr = (env.get('LINES', 25), env.get('COLUMNS', 80))
60 return int(cr[1]), int(cr[0])
61
62 def __init__(self, *args):
63 if not LLDBTestResult.__ignore_singleton__ and LLDBTestResult.__singleton__:
64 raise Exception("LLDBTestResult instantiated more than once")
65 super(LLDBTestResult, self).__init__(*args)
66 LLDBTestResult.__singleton__ = self
67 # Now put this singleton into the lldb module namespace.
68 configuration.test_result = self
69 # Computes the format string for displaying the counter.
70 counterWidth = len(str(configuration.suite.countTestCases()))
71 self.fmt = "%" + str(counterWidth) + "d: "
72 self.indentation = ' ' * (counterWidth + 2)
73 # This counts from 1 .. suite.countTestCases().
74 self.counter = 0
75 (width, height) = LLDBTestResult.getTerminalSize()
Zachary Turnerb4733e62015-12-08 01:15:44 +000076 self.results_formatter = configuration.results_formatter_object
77
78 def _config_string(self, test):
79 compiler = getattr(test, "getCompiler", None)
80 arch = getattr(test, "getArchitecture", None)
81 return "%s-%s" % (compiler() if compiler else "", arch() if arch else "")
82
83 def _exc_info_to_string(self, err, test):
84 """Overrides superclass TestResult's method in order to append
85 our test config info string to the exception info string."""
86 if hasattr(test, "getArchitecture") and hasattr(test, "getCompiler"):
87 return '%sConfig=%s-%s' % (super(LLDBTestResult, self)._exc_info_to_string(err, test),
88 test.getArchitecture(),
89 test.getCompiler())
90 else:
91 return super(LLDBTestResult, self)._exc_info_to_string(err, test)
92
93 def getDescription(self, test):
94 doc_first_line = test.shortDescription()
95 if self.descriptions and doc_first_line:
96 return '\n'.join((str(test), self.indentation + doc_first_line))
97 else:
98 return str(test)
99
100 def getCategoriesForTest(self,test):
101 if hasattr(test,"_testMethodName"):
102 test_method = getattr(test,"_testMethodName")
103 test_method = getattr(test,test_method)
104 else:
105 test_method = None
106 if test_method != None and hasattr(test_method,"getCategories"):
107 test_categories = test_method.getCategories(test)
108 elif hasattr(test,"getCategories"):
109 test_categories = test.getCategories()
110 elif inspect.ismethod(test) and test.__self__ != None and hasattr(test.__self__,"getCategories"):
111 test_categories = test.__self__.getCategories()
112 else:
113 test_categories = []
114 if test_categories == None:
115 test_categories = []
116 return test_categories
117
118 def hardMarkAsSkipped(self,test):
119 getattr(test, test._testMethodName).__func__.__unittest_skip__ = True
120 getattr(test, test._testMethodName).__func__.__unittest_skip_why__ = "test case does not fall in any category of interest for this run"
121 test.__class__.__unittest_skip__ = True
122 test.__class__.__unittest_skip_why__ = "test case does not fall in any category of interest for this run"
123
124 def startTest(self, test):
125 if configuration.shouldSkipBecauseOfCategories(self.getCategoriesForTest(test)):
126 self.hardMarkAsSkipped(test)
127 configuration.setCrashInfoHook("%s at %s" % (str(test),inspect.getfile(test.__class__)))
128 self.counter += 1
129 #if self.counter == 4:
130 # import crashinfo
131 # crashinfo.testCrashReporterDescription(None)
132 test.test_number = self.counter
133 if self.showAll:
134 self.stream.write(self.fmt % self.counter)
135 super(LLDBTestResult, self).startTest(test)
136 if self.results_formatter:
137 self.results_formatter.handle_event(
138 EventBuilder.event_for_start(test))
139
140 def addSuccess(self, test):
141 super(LLDBTestResult, self).addSuccess(test)
142 if configuration.parsable:
143 self.stream.write("PASS: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
144 if self.results_formatter:
145 self.results_formatter.handle_event(
146 EventBuilder.event_for_success(test))
147
148 def addError(self, test, err):
149 configuration.sdir_has_content = True
150 super(LLDBTestResult, self).addError(test, err)
151 method = getattr(test, "markError", None)
152 if method:
153 method()
154 if configuration.parsable:
155 self.stream.write("FAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
156 if self.results_formatter:
157 self.results_formatter.handle_event(
158 EventBuilder.event_for_error(test, err))
159
160 def addCleanupError(self, test, err):
161 configuration.sdir_has_content = True
162 super(LLDBTestResult, self).addCleanupError(test, err)
163 method = getattr(test, "markCleanupError", None)
164 if method:
165 method()
166 if configuration.parsable:
167 self.stream.write("CLEANUP ERROR: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
168 if self.results_formatter:
169 self.results_formatter.handle_event(
170 EventBuilder.event_for_cleanup_error(
171 test, err))
172
173 def addFailure(self, test, err):
174 configuration.sdir_has_content = True
175 super(LLDBTestResult, self).addFailure(test, err)
176 method = getattr(test, "markFailure", None)
177 if method:
178 method()
179 if configuration.parsable:
180 self.stream.write("FAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
181 if configuration.useCategories:
182 test_categories = self.getCategoriesForTest(test)
183 for category in test_categories:
184 if category in configuration.failuresPerCategory:
185 configuration.failuresPerCategory[category] = configuration.failuresPerCategory[category] + 1
186 else:
187 configuration.failuresPerCategory[category] = 1
188 if self.results_formatter:
189 self.results_formatter.handle_event(
190 EventBuilder.event_for_failure(test, err))
191
192
193 def addExpectedFailure(self, test, err, bugnumber):
194 configuration.sdir_has_content = True
195 super(LLDBTestResult, self).addExpectedFailure(test, err, bugnumber)
196 method = getattr(test, "markExpectedFailure", None)
197 if method:
198 method(err, bugnumber)
199 if configuration.parsable:
200 self.stream.write("XFAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
201 if self.results_formatter:
202 self.results_formatter.handle_event(
203 EventBuilder.event_for_expected_failure(
204 test, err, bugnumber))
205
206 def addSkip(self, test, reason):
207 configuration.sdir_has_content = True
208 super(LLDBTestResult, self).addSkip(test, reason)
209 method = getattr(test, "markSkippedTest", None)
210 if method:
211 method()
212 if configuration.parsable:
213 self.stream.write("UNSUPPORTED: LLDB (%s) :: %s (%s) \n" % (self._config_string(test), str(test), reason))
214 if self.results_formatter:
215 self.results_formatter.handle_event(
216 EventBuilder.event_for_skip(test, reason))
217
218 def addUnexpectedSuccess(self, test, bugnumber):
219 configuration.sdir_has_content = True
220 super(LLDBTestResult, self).addUnexpectedSuccess(test, bugnumber)
221 method = getattr(test, "markUnexpectedSuccess", None)
222 if method:
223 method(bugnumber)
224 if configuration.parsable:
225 self.stream.write("XPASS: LLDB (%s) :: %s\n" % (self._config_string(test), str(test)))
226 if self.results_formatter:
227 self.results_formatter.handle_event(
228 EventBuilder.event_for_unexpected_success(
229 test, bugnumber))