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