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 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() 76 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 """ 102 Gets all the categories for the currently running test method in test case 103 """ 104 test_categories = [] 105 test_method = getattr(test, test._testMethodName) 106 if test_method != None and hasattr(test_method, "categories"): 107 test_categories.extend(test_method.categories) 108 109 test_categories.extend(test.getCategories()) 110 111 return test_categories 112 113 def hardMarkAsSkipped(self,test): 114 getattr(test, test._testMethodName).__func__.__unittest_skip__ = True 115 getattr(test, test._testMethodName).__func__.__unittest_skip_why__ = "test case does not fall in any category of interest for this run" 116 test.__class__.__unittest_skip__ = True 117 test.__class__.__unittest_skip_why__ = "test case does not fall in any category of interest for this run" 118 119 def startTest(self, test): 120 if configuration.shouldSkipBecauseOfCategories(self.getCategoriesForTest(test)): 121 self.hardMarkAsSkipped(test) 122 configuration.setCrashInfoHook("%s at %s" % (str(test),inspect.getfile(test.__class__))) 123 self.counter += 1 124 #if self.counter == 4: 125 # import crashinfo 126 # crashinfo.testCrashReporterDescription(None) 127 test.test_number = self.counter 128 if self.showAll: 129 self.stream.write(self.fmt % self.counter) 130 super(LLDBTestResult, self).startTest(test) 131 if self.results_formatter: 132 self.results_formatter.handle_event( 133 EventBuilder.event_for_start(test)) 134 135 def addSuccess(self, test): 136 super(LLDBTestResult, self).addSuccess(test) 137 if configuration.parsable: 138 self.stream.write("PASS: LLDB (%s) :: %s\n" % (self._config_string(test), str(test))) 139 if self.results_formatter: 140 self.results_formatter.handle_event( 141 EventBuilder.event_for_success(test)) 142 143 def addError(self, test, err): 144 configuration.sdir_has_content = True 145 super(LLDBTestResult, self).addError(test, err) 146 method = getattr(test, "markError", None) 147 if method: 148 method() 149 if configuration.parsable: 150 self.stream.write("FAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test))) 151 if self.results_formatter: 152 self.results_formatter.handle_event( 153 EventBuilder.event_for_error(test, err)) 154 155 def addCleanupError(self, test, err): 156 configuration.sdir_has_content = True 157 super(LLDBTestResult, self).addCleanupError(test, err) 158 method = getattr(test, "markCleanupError", None) 159 if method: 160 method() 161 if configuration.parsable: 162 self.stream.write("CLEANUP ERROR: LLDB (%s) :: %s\n" % (self._config_string(test), str(test))) 163 if self.results_formatter: 164 self.results_formatter.handle_event( 165 EventBuilder.event_for_cleanup_error( 166 test, err)) 167 168 def addFailure(self, test, err): 169 configuration.sdir_has_content = True 170 super(LLDBTestResult, self).addFailure(test, err) 171 method = getattr(test, "markFailure", None) 172 if method: 173 method() 174 if configuration.parsable: 175 self.stream.write("FAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test))) 176 if configuration.useCategories: 177 test_categories = self.getCategoriesForTest(test) 178 for category in test_categories: 179 if category in configuration.failuresPerCategory: 180 configuration.failuresPerCategory[category] = configuration.failuresPerCategory[category] + 1 181 else: 182 configuration.failuresPerCategory[category] = 1 183 if self.results_formatter: 184 self.results_formatter.handle_event( 185 EventBuilder.event_for_failure(test, err)) 186 187 188 def addExpectedFailure(self, test, err, bugnumber): 189 configuration.sdir_has_content = True 190 super(LLDBTestResult, self).addExpectedFailure(test, err, bugnumber) 191 method = getattr(test, "markExpectedFailure", None) 192 if method: 193 method(err, bugnumber) 194 if configuration.parsable: 195 self.stream.write("XFAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test))) 196 if self.results_formatter: 197 self.results_formatter.handle_event( 198 EventBuilder.event_for_expected_failure( 199 test, err, bugnumber)) 200 201 def addSkip(self, test, reason): 202 configuration.sdir_has_content = True 203 super(LLDBTestResult, self).addSkip(test, reason) 204 method = getattr(test, "markSkippedTest", None) 205 if method: 206 method() 207 if configuration.parsable: 208 self.stream.write("UNSUPPORTED: LLDB (%s) :: %s (%s) \n" % (self._config_string(test), str(test), reason)) 209 if self.results_formatter: 210 self.results_formatter.handle_event( 211 EventBuilder.event_for_skip(test, reason)) 212 213 def addUnexpectedSuccess(self, test, bugnumber): 214 configuration.sdir_has_content = True 215 super(LLDBTestResult, self).addUnexpectedSuccess(test, bugnumber) 216 method = getattr(test, "markUnexpectedSuccess", None) 217 if method: 218 method(bugnumber) 219 if configuration.parsable: 220 self.stream.write("XPASS: LLDB (%s) :: %s\n" % (self._config_string(test), str(test))) 221 if self.results_formatter: 222 self.results_formatter.handle_event( 223 EventBuilder.event_for_unexpected_success( 224 test, bugnumber)) 225