xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/unittest/suite.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
1*cda5da8dSAndroid Build Coastguard Worker"""TestSuite"""
2*cda5da8dSAndroid Build Coastguard Worker
3*cda5da8dSAndroid Build Coastguard Workerimport sys
4*cda5da8dSAndroid Build Coastguard Worker
5*cda5da8dSAndroid Build Coastguard Workerfrom . import case
6*cda5da8dSAndroid Build Coastguard Workerfrom . import util
7*cda5da8dSAndroid Build Coastguard Worker
8*cda5da8dSAndroid Build Coastguard Worker__unittest = True
9*cda5da8dSAndroid Build Coastguard Worker
10*cda5da8dSAndroid Build Coastguard Worker
11*cda5da8dSAndroid Build Coastguard Workerdef _call_if_exists(parent, attr):
12*cda5da8dSAndroid Build Coastguard Worker    func = getattr(parent, attr, lambda: None)
13*cda5da8dSAndroid Build Coastguard Worker    func()
14*cda5da8dSAndroid Build Coastguard Worker
15*cda5da8dSAndroid Build Coastguard Worker
16*cda5da8dSAndroid Build Coastguard Workerclass BaseTestSuite(object):
17*cda5da8dSAndroid Build Coastguard Worker    """A simple test suite that doesn't provide class or module shared fixtures.
18*cda5da8dSAndroid Build Coastguard Worker    """
19*cda5da8dSAndroid Build Coastguard Worker    _cleanup = True
20*cda5da8dSAndroid Build Coastguard Worker
21*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, tests=()):
22*cda5da8dSAndroid Build Coastguard Worker        self._tests = []
23*cda5da8dSAndroid Build Coastguard Worker        self._removed_tests = 0
24*cda5da8dSAndroid Build Coastguard Worker        self.addTests(tests)
25*cda5da8dSAndroid Build Coastguard Worker
26*cda5da8dSAndroid Build Coastguard Worker    def __repr__(self):
27*cda5da8dSAndroid Build Coastguard Worker        return "<%s tests=%s>" % (util.strclass(self.__class__), list(self))
28*cda5da8dSAndroid Build Coastguard Worker
29*cda5da8dSAndroid Build Coastguard Worker    def __eq__(self, other):
30*cda5da8dSAndroid Build Coastguard Worker        if not isinstance(other, self.__class__):
31*cda5da8dSAndroid Build Coastguard Worker            return NotImplemented
32*cda5da8dSAndroid Build Coastguard Worker        return list(self) == list(other)
33*cda5da8dSAndroid Build Coastguard Worker
34*cda5da8dSAndroid Build Coastguard Worker    def __iter__(self):
35*cda5da8dSAndroid Build Coastguard Worker        return iter(self._tests)
36*cda5da8dSAndroid Build Coastguard Worker
37*cda5da8dSAndroid Build Coastguard Worker    def countTestCases(self):
38*cda5da8dSAndroid Build Coastguard Worker        cases = self._removed_tests
39*cda5da8dSAndroid Build Coastguard Worker        for test in self:
40*cda5da8dSAndroid Build Coastguard Worker            if test:
41*cda5da8dSAndroid Build Coastguard Worker                cases += test.countTestCases()
42*cda5da8dSAndroid Build Coastguard Worker        return cases
43*cda5da8dSAndroid Build Coastguard Worker
44*cda5da8dSAndroid Build Coastguard Worker    def addTest(self, test):
45*cda5da8dSAndroid Build Coastguard Worker        # sanity checks
46*cda5da8dSAndroid Build Coastguard Worker        if not callable(test):
47*cda5da8dSAndroid Build Coastguard Worker            raise TypeError("{} is not callable".format(repr(test)))
48*cda5da8dSAndroid Build Coastguard Worker        if isinstance(test, type) and issubclass(test,
49*cda5da8dSAndroid Build Coastguard Worker                                                 (case.TestCase, TestSuite)):
50*cda5da8dSAndroid Build Coastguard Worker            raise TypeError("TestCases and TestSuites must be instantiated "
51*cda5da8dSAndroid Build Coastguard Worker                            "before passing them to addTest()")
52*cda5da8dSAndroid Build Coastguard Worker        self._tests.append(test)
53*cda5da8dSAndroid Build Coastguard Worker
54*cda5da8dSAndroid Build Coastguard Worker    def addTests(self, tests):
55*cda5da8dSAndroid Build Coastguard Worker        if isinstance(tests, str):
56*cda5da8dSAndroid Build Coastguard Worker            raise TypeError("tests must be an iterable of tests, not a string")
57*cda5da8dSAndroid Build Coastguard Worker        for test in tests:
58*cda5da8dSAndroid Build Coastguard Worker            self.addTest(test)
59*cda5da8dSAndroid Build Coastguard Worker
60*cda5da8dSAndroid Build Coastguard Worker    def run(self, result):
61*cda5da8dSAndroid Build Coastguard Worker        for index, test in enumerate(self):
62*cda5da8dSAndroid Build Coastguard Worker            if result.shouldStop:
63*cda5da8dSAndroid Build Coastguard Worker                break
64*cda5da8dSAndroid Build Coastguard Worker            test(result)
65*cda5da8dSAndroid Build Coastguard Worker            if self._cleanup:
66*cda5da8dSAndroid Build Coastguard Worker                self._removeTestAtIndex(index)
67*cda5da8dSAndroid Build Coastguard Worker        return result
68*cda5da8dSAndroid Build Coastguard Worker
69*cda5da8dSAndroid Build Coastguard Worker    def _removeTestAtIndex(self, index):
70*cda5da8dSAndroid Build Coastguard Worker        """Stop holding a reference to the TestCase at index."""
71*cda5da8dSAndroid Build Coastguard Worker        try:
72*cda5da8dSAndroid Build Coastguard Worker            test = self._tests[index]
73*cda5da8dSAndroid Build Coastguard Worker        except TypeError:
74*cda5da8dSAndroid Build Coastguard Worker            # support for suite implementations that have overridden self._tests
75*cda5da8dSAndroid Build Coastguard Worker            pass
76*cda5da8dSAndroid Build Coastguard Worker        else:
77*cda5da8dSAndroid Build Coastguard Worker            # Some unittest tests add non TestCase/TestSuite objects to
78*cda5da8dSAndroid Build Coastguard Worker            # the suite.
79*cda5da8dSAndroid Build Coastguard Worker            if hasattr(test, 'countTestCases'):
80*cda5da8dSAndroid Build Coastguard Worker                self._removed_tests += test.countTestCases()
81*cda5da8dSAndroid Build Coastguard Worker            self._tests[index] = None
82*cda5da8dSAndroid Build Coastguard Worker
83*cda5da8dSAndroid Build Coastguard Worker    def __call__(self, *args, **kwds):
84*cda5da8dSAndroid Build Coastguard Worker        return self.run(*args, **kwds)
85*cda5da8dSAndroid Build Coastguard Worker
86*cda5da8dSAndroid Build Coastguard Worker    def debug(self):
87*cda5da8dSAndroid Build Coastguard Worker        """Run the tests without collecting errors in a TestResult"""
88*cda5da8dSAndroid Build Coastguard Worker        for test in self:
89*cda5da8dSAndroid Build Coastguard Worker            test.debug()
90*cda5da8dSAndroid Build Coastguard Worker
91*cda5da8dSAndroid Build Coastguard Worker
92*cda5da8dSAndroid Build Coastguard Workerclass TestSuite(BaseTestSuite):
93*cda5da8dSAndroid Build Coastguard Worker    """A test suite is a composite test consisting of a number of TestCases.
94*cda5da8dSAndroid Build Coastguard Worker
95*cda5da8dSAndroid Build Coastguard Worker    For use, create an instance of TestSuite, then add test case instances.
96*cda5da8dSAndroid Build Coastguard Worker    When all tests have been added, the suite can be passed to a test
97*cda5da8dSAndroid Build Coastguard Worker    runner, such as TextTestRunner. It will run the individual test cases
98*cda5da8dSAndroid Build Coastguard Worker    in the order in which they were added, aggregating the results. When
99*cda5da8dSAndroid Build Coastguard Worker    subclassing, do not forget to call the base class constructor.
100*cda5da8dSAndroid Build Coastguard Worker    """
101*cda5da8dSAndroid Build Coastguard Worker
102*cda5da8dSAndroid Build Coastguard Worker    def run(self, result, debug=False):
103*cda5da8dSAndroid Build Coastguard Worker        topLevel = False
104*cda5da8dSAndroid Build Coastguard Worker        if getattr(result, '_testRunEntered', False) is False:
105*cda5da8dSAndroid Build Coastguard Worker            result._testRunEntered = topLevel = True
106*cda5da8dSAndroid Build Coastguard Worker
107*cda5da8dSAndroid Build Coastguard Worker        for index, test in enumerate(self):
108*cda5da8dSAndroid Build Coastguard Worker            if result.shouldStop:
109*cda5da8dSAndroid Build Coastguard Worker                break
110*cda5da8dSAndroid Build Coastguard Worker
111*cda5da8dSAndroid Build Coastguard Worker            if _isnotsuite(test):
112*cda5da8dSAndroid Build Coastguard Worker                self._tearDownPreviousClass(test, result)
113*cda5da8dSAndroid Build Coastguard Worker                self._handleModuleFixture(test, result)
114*cda5da8dSAndroid Build Coastguard Worker                self._handleClassSetUp(test, result)
115*cda5da8dSAndroid Build Coastguard Worker                result._previousTestClass = test.__class__
116*cda5da8dSAndroid Build Coastguard Worker
117*cda5da8dSAndroid Build Coastguard Worker                if (getattr(test.__class__, '_classSetupFailed', False) or
118*cda5da8dSAndroid Build Coastguard Worker                    getattr(result, '_moduleSetUpFailed', False)):
119*cda5da8dSAndroid Build Coastguard Worker                    continue
120*cda5da8dSAndroid Build Coastguard Worker
121*cda5da8dSAndroid Build Coastguard Worker            if not debug:
122*cda5da8dSAndroid Build Coastguard Worker                test(result)
123*cda5da8dSAndroid Build Coastguard Worker            else:
124*cda5da8dSAndroid Build Coastguard Worker                test.debug()
125*cda5da8dSAndroid Build Coastguard Worker
126*cda5da8dSAndroid Build Coastguard Worker            if self._cleanup:
127*cda5da8dSAndroid Build Coastguard Worker                self._removeTestAtIndex(index)
128*cda5da8dSAndroid Build Coastguard Worker
129*cda5da8dSAndroid Build Coastguard Worker        if topLevel:
130*cda5da8dSAndroid Build Coastguard Worker            self._tearDownPreviousClass(None, result)
131*cda5da8dSAndroid Build Coastguard Worker            self._handleModuleTearDown(result)
132*cda5da8dSAndroid Build Coastguard Worker            result._testRunEntered = False
133*cda5da8dSAndroid Build Coastguard Worker        return result
134*cda5da8dSAndroid Build Coastguard Worker
135*cda5da8dSAndroid Build Coastguard Worker    def debug(self):
136*cda5da8dSAndroid Build Coastguard Worker        """Run the tests without collecting errors in a TestResult"""
137*cda5da8dSAndroid Build Coastguard Worker        debug = _DebugResult()
138*cda5da8dSAndroid Build Coastguard Worker        self.run(debug, True)
139*cda5da8dSAndroid Build Coastguard Worker
140*cda5da8dSAndroid Build Coastguard Worker    ################################
141*cda5da8dSAndroid Build Coastguard Worker
142*cda5da8dSAndroid Build Coastguard Worker    def _handleClassSetUp(self, test, result):
143*cda5da8dSAndroid Build Coastguard Worker        previousClass = getattr(result, '_previousTestClass', None)
144*cda5da8dSAndroid Build Coastguard Worker        currentClass = test.__class__
145*cda5da8dSAndroid Build Coastguard Worker        if currentClass == previousClass:
146*cda5da8dSAndroid Build Coastguard Worker            return
147*cda5da8dSAndroid Build Coastguard Worker        if result._moduleSetUpFailed:
148*cda5da8dSAndroid Build Coastguard Worker            return
149*cda5da8dSAndroid Build Coastguard Worker        if getattr(currentClass, "__unittest_skip__", False):
150*cda5da8dSAndroid Build Coastguard Worker            return
151*cda5da8dSAndroid Build Coastguard Worker
152*cda5da8dSAndroid Build Coastguard Worker        failed = False
153*cda5da8dSAndroid Build Coastguard Worker        try:
154*cda5da8dSAndroid Build Coastguard Worker            currentClass._classSetupFailed = False
155*cda5da8dSAndroid Build Coastguard Worker        except TypeError:
156*cda5da8dSAndroid Build Coastguard Worker            # test may actually be a function
157*cda5da8dSAndroid Build Coastguard Worker            # so its class will be a builtin-type
158*cda5da8dSAndroid Build Coastguard Worker            pass
159*cda5da8dSAndroid Build Coastguard Worker
160*cda5da8dSAndroid Build Coastguard Worker        setUpClass = getattr(currentClass, 'setUpClass', None)
161*cda5da8dSAndroid Build Coastguard Worker        doClassCleanups = getattr(currentClass, 'doClassCleanups', None)
162*cda5da8dSAndroid Build Coastguard Worker        if setUpClass is not None:
163*cda5da8dSAndroid Build Coastguard Worker            _call_if_exists(result, '_setupStdout')
164*cda5da8dSAndroid Build Coastguard Worker            try:
165*cda5da8dSAndroid Build Coastguard Worker                try:
166*cda5da8dSAndroid Build Coastguard Worker                    setUpClass()
167*cda5da8dSAndroid Build Coastguard Worker                except Exception as e:
168*cda5da8dSAndroid Build Coastguard Worker                    if isinstance(result, _DebugResult):
169*cda5da8dSAndroid Build Coastguard Worker                        raise
170*cda5da8dSAndroid Build Coastguard Worker                    failed = True
171*cda5da8dSAndroid Build Coastguard Worker                    try:
172*cda5da8dSAndroid Build Coastguard Worker                        currentClass._classSetupFailed = True
173*cda5da8dSAndroid Build Coastguard Worker                    except TypeError:
174*cda5da8dSAndroid Build Coastguard Worker                        pass
175*cda5da8dSAndroid Build Coastguard Worker                    className = util.strclass(currentClass)
176*cda5da8dSAndroid Build Coastguard Worker                    self._createClassOrModuleLevelException(result, e,
177*cda5da8dSAndroid Build Coastguard Worker                                                            'setUpClass',
178*cda5da8dSAndroid Build Coastguard Worker                                                            className)
179*cda5da8dSAndroid Build Coastguard Worker                if failed and doClassCleanups is not None:
180*cda5da8dSAndroid Build Coastguard Worker                    doClassCleanups()
181*cda5da8dSAndroid Build Coastguard Worker                    for exc_info in currentClass.tearDown_exceptions:
182*cda5da8dSAndroid Build Coastguard Worker                        self._createClassOrModuleLevelException(
183*cda5da8dSAndroid Build Coastguard Worker                                result, exc_info[1], 'setUpClass', className,
184*cda5da8dSAndroid Build Coastguard Worker                                info=exc_info)
185*cda5da8dSAndroid Build Coastguard Worker            finally:
186*cda5da8dSAndroid Build Coastguard Worker                _call_if_exists(result, '_restoreStdout')
187*cda5da8dSAndroid Build Coastguard Worker
188*cda5da8dSAndroid Build Coastguard Worker    def _get_previous_module(self, result):
189*cda5da8dSAndroid Build Coastguard Worker        previousModule = None
190*cda5da8dSAndroid Build Coastguard Worker        previousClass = getattr(result, '_previousTestClass', None)
191*cda5da8dSAndroid Build Coastguard Worker        if previousClass is not None:
192*cda5da8dSAndroid Build Coastguard Worker            previousModule = previousClass.__module__
193*cda5da8dSAndroid Build Coastguard Worker        return previousModule
194*cda5da8dSAndroid Build Coastguard Worker
195*cda5da8dSAndroid Build Coastguard Worker
196*cda5da8dSAndroid Build Coastguard Worker    def _handleModuleFixture(self, test, result):
197*cda5da8dSAndroid Build Coastguard Worker        previousModule = self._get_previous_module(result)
198*cda5da8dSAndroid Build Coastguard Worker        currentModule = test.__class__.__module__
199*cda5da8dSAndroid Build Coastguard Worker        if currentModule == previousModule:
200*cda5da8dSAndroid Build Coastguard Worker            return
201*cda5da8dSAndroid Build Coastguard Worker
202*cda5da8dSAndroid Build Coastguard Worker        self._handleModuleTearDown(result)
203*cda5da8dSAndroid Build Coastguard Worker
204*cda5da8dSAndroid Build Coastguard Worker
205*cda5da8dSAndroid Build Coastguard Worker        result._moduleSetUpFailed = False
206*cda5da8dSAndroid Build Coastguard Worker        try:
207*cda5da8dSAndroid Build Coastguard Worker            module = sys.modules[currentModule]
208*cda5da8dSAndroid Build Coastguard Worker        except KeyError:
209*cda5da8dSAndroid Build Coastguard Worker            return
210*cda5da8dSAndroid Build Coastguard Worker        setUpModule = getattr(module, 'setUpModule', None)
211*cda5da8dSAndroid Build Coastguard Worker        if setUpModule is not None:
212*cda5da8dSAndroid Build Coastguard Worker            _call_if_exists(result, '_setupStdout')
213*cda5da8dSAndroid Build Coastguard Worker            try:
214*cda5da8dSAndroid Build Coastguard Worker                try:
215*cda5da8dSAndroid Build Coastguard Worker                    setUpModule()
216*cda5da8dSAndroid Build Coastguard Worker                except Exception as e:
217*cda5da8dSAndroid Build Coastguard Worker                    if isinstance(result, _DebugResult):
218*cda5da8dSAndroid Build Coastguard Worker                        raise
219*cda5da8dSAndroid Build Coastguard Worker                    result._moduleSetUpFailed = True
220*cda5da8dSAndroid Build Coastguard Worker                    self._createClassOrModuleLevelException(result, e,
221*cda5da8dSAndroid Build Coastguard Worker                                                            'setUpModule',
222*cda5da8dSAndroid Build Coastguard Worker                                                            currentModule)
223*cda5da8dSAndroid Build Coastguard Worker                if result._moduleSetUpFailed:
224*cda5da8dSAndroid Build Coastguard Worker                    try:
225*cda5da8dSAndroid Build Coastguard Worker                        case.doModuleCleanups()
226*cda5da8dSAndroid Build Coastguard Worker                    except Exception as e:
227*cda5da8dSAndroid Build Coastguard Worker                        self._createClassOrModuleLevelException(result, e,
228*cda5da8dSAndroid Build Coastguard Worker                                                                'setUpModule',
229*cda5da8dSAndroid Build Coastguard Worker                                                                currentModule)
230*cda5da8dSAndroid Build Coastguard Worker            finally:
231*cda5da8dSAndroid Build Coastguard Worker                _call_if_exists(result, '_restoreStdout')
232*cda5da8dSAndroid Build Coastguard Worker
233*cda5da8dSAndroid Build Coastguard Worker    def _createClassOrModuleLevelException(self, result, exc, method_name,
234*cda5da8dSAndroid Build Coastguard Worker                                           parent, info=None):
235*cda5da8dSAndroid Build Coastguard Worker        errorName = f'{method_name} ({parent})'
236*cda5da8dSAndroid Build Coastguard Worker        self._addClassOrModuleLevelException(result, exc, errorName, info)
237*cda5da8dSAndroid Build Coastguard Worker
238*cda5da8dSAndroid Build Coastguard Worker    def _addClassOrModuleLevelException(self, result, exception, errorName,
239*cda5da8dSAndroid Build Coastguard Worker                                        info=None):
240*cda5da8dSAndroid Build Coastguard Worker        error = _ErrorHolder(errorName)
241*cda5da8dSAndroid Build Coastguard Worker        addSkip = getattr(result, 'addSkip', None)
242*cda5da8dSAndroid Build Coastguard Worker        if addSkip is not None and isinstance(exception, case.SkipTest):
243*cda5da8dSAndroid Build Coastguard Worker            addSkip(error, str(exception))
244*cda5da8dSAndroid Build Coastguard Worker        else:
245*cda5da8dSAndroid Build Coastguard Worker            if not info:
246*cda5da8dSAndroid Build Coastguard Worker                result.addError(error, sys.exc_info())
247*cda5da8dSAndroid Build Coastguard Worker            else:
248*cda5da8dSAndroid Build Coastguard Worker                result.addError(error, info)
249*cda5da8dSAndroid Build Coastguard Worker
250*cda5da8dSAndroid Build Coastguard Worker    def _handleModuleTearDown(self, result):
251*cda5da8dSAndroid Build Coastguard Worker        previousModule = self._get_previous_module(result)
252*cda5da8dSAndroid Build Coastguard Worker        if previousModule is None:
253*cda5da8dSAndroid Build Coastguard Worker            return
254*cda5da8dSAndroid Build Coastguard Worker        if result._moduleSetUpFailed:
255*cda5da8dSAndroid Build Coastguard Worker            return
256*cda5da8dSAndroid Build Coastguard Worker
257*cda5da8dSAndroid Build Coastguard Worker        try:
258*cda5da8dSAndroid Build Coastguard Worker            module = sys.modules[previousModule]
259*cda5da8dSAndroid Build Coastguard Worker        except KeyError:
260*cda5da8dSAndroid Build Coastguard Worker            return
261*cda5da8dSAndroid Build Coastguard Worker
262*cda5da8dSAndroid Build Coastguard Worker        _call_if_exists(result, '_setupStdout')
263*cda5da8dSAndroid Build Coastguard Worker        try:
264*cda5da8dSAndroid Build Coastguard Worker            tearDownModule = getattr(module, 'tearDownModule', None)
265*cda5da8dSAndroid Build Coastguard Worker            if tearDownModule is not None:
266*cda5da8dSAndroid Build Coastguard Worker                try:
267*cda5da8dSAndroid Build Coastguard Worker                    tearDownModule()
268*cda5da8dSAndroid Build Coastguard Worker                except Exception as e:
269*cda5da8dSAndroid Build Coastguard Worker                    if isinstance(result, _DebugResult):
270*cda5da8dSAndroid Build Coastguard Worker                        raise
271*cda5da8dSAndroid Build Coastguard Worker                    self._createClassOrModuleLevelException(result, e,
272*cda5da8dSAndroid Build Coastguard Worker                                                            'tearDownModule',
273*cda5da8dSAndroid Build Coastguard Worker                                                            previousModule)
274*cda5da8dSAndroid Build Coastguard Worker            try:
275*cda5da8dSAndroid Build Coastguard Worker                case.doModuleCleanups()
276*cda5da8dSAndroid Build Coastguard Worker            except Exception as e:
277*cda5da8dSAndroid Build Coastguard Worker                if isinstance(result, _DebugResult):
278*cda5da8dSAndroid Build Coastguard Worker                    raise
279*cda5da8dSAndroid Build Coastguard Worker                self._createClassOrModuleLevelException(result, e,
280*cda5da8dSAndroid Build Coastguard Worker                                                        'tearDownModule',
281*cda5da8dSAndroid Build Coastguard Worker                                                        previousModule)
282*cda5da8dSAndroid Build Coastguard Worker        finally:
283*cda5da8dSAndroid Build Coastguard Worker            _call_if_exists(result, '_restoreStdout')
284*cda5da8dSAndroid Build Coastguard Worker
285*cda5da8dSAndroid Build Coastguard Worker    def _tearDownPreviousClass(self, test, result):
286*cda5da8dSAndroid Build Coastguard Worker        previousClass = getattr(result, '_previousTestClass', None)
287*cda5da8dSAndroid Build Coastguard Worker        currentClass = test.__class__
288*cda5da8dSAndroid Build Coastguard Worker        if currentClass == previousClass or previousClass is None:
289*cda5da8dSAndroid Build Coastguard Worker            return
290*cda5da8dSAndroid Build Coastguard Worker        if getattr(previousClass, '_classSetupFailed', False):
291*cda5da8dSAndroid Build Coastguard Worker            return
292*cda5da8dSAndroid Build Coastguard Worker        if getattr(result, '_moduleSetUpFailed', False):
293*cda5da8dSAndroid Build Coastguard Worker            return
294*cda5da8dSAndroid Build Coastguard Worker        if getattr(previousClass, "__unittest_skip__", False):
295*cda5da8dSAndroid Build Coastguard Worker            return
296*cda5da8dSAndroid Build Coastguard Worker
297*cda5da8dSAndroid Build Coastguard Worker        tearDownClass = getattr(previousClass, 'tearDownClass', None)
298*cda5da8dSAndroid Build Coastguard Worker        doClassCleanups = getattr(previousClass, 'doClassCleanups', None)
299*cda5da8dSAndroid Build Coastguard Worker        if tearDownClass is None and doClassCleanups is None:
300*cda5da8dSAndroid Build Coastguard Worker            return
301*cda5da8dSAndroid Build Coastguard Worker
302*cda5da8dSAndroid Build Coastguard Worker        _call_if_exists(result, '_setupStdout')
303*cda5da8dSAndroid Build Coastguard Worker        try:
304*cda5da8dSAndroid Build Coastguard Worker            if tearDownClass is not None:
305*cda5da8dSAndroid Build Coastguard Worker                try:
306*cda5da8dSAndroid Build Coastguard Worker                    tearDownClass()
307*cda5da8dSAndroid Build Coastguard Worker                except Exception as e:
308*cda5da8dSAndroid Build Coastguard Worker                    if isinstance(result, _DebugResult):
309*cda5da8dSAndroid Build Coastguard Worker                        raise
310*cda5da8dSAndroid Build Coastguard Worker                    className = util.strclass(previousClass)
311*cda5da8dSAndroid Build Coastguard Worker                    self._createClassOrModuleLevelException(result, e,
312*cda5da8dSAndroid Build Coastguard Worker                                                            'tearDownClass',
313*cda5da8dSAndroid Build Coastguard Worker                                                            className)
314*cda5da8dSAndroid Build Coastguard Worker            if doClassCleanups is not None:
315*cda5da8dSAndroid Build Coastguard Worker                doClassCleanups()
316*cda5da8dSAndroid Build Coastguard Worker                for exc_info in previousClass.tearDown_exceptions:
317*cda5da8dSAndroid Build Coastguard Worker                    if isinstance(result, _DebugResult):
318*cda5da8dSAndroid Build Coastguard Worker                        raise exc_info[1]
319*cda5da8dSAndroid Build Coastguard Worker                    className = util.strclass(previousClass)
320*cda5da8dSAndroid Build Coastguard Worker                    self._createClassOrModuleLevelException(result, exc_info[1],
321*cda5da8dSAndroid Build Coastguard Worker                                                            'tearDownClass',
322*cda5da8dSAndroid Build Coastguard Worker                                                            className,
323*cda5da8dSAndroid Build Coastguard Worker                                                            info=exc_info)
324*cda5da8dSAndroid Build Coastguard Worker        finally:
325*cda5da8dSAndroid Build Coastguard Worker            _call_if_exists(result, '_restoreStdout')
326*cda5da8dSAndroid Build Coastguard Worker
327*cda5da8dSAndroid Build Coastguard Worker
328*cda5da8dSAndroid Build Coastguard Workerclass _ErrorHolder(object):
329*cda5da8dSAndroid Build Coastguard Worker    """
330*cda5da8dSAndroid Build Coastguard Worker    Placeholder for a TestCase inside a result. As far as a TestResult
331*cda5da8dSAndroid Build Coastguard Worker    is concerned, this looks exactly like a unit test. Used to insert
332*cda5da8dSAndroid Build Coastguard Worker    arbitrary errors into a test suite run.
333*cda5da8dSAndroid Build Coastguard Worker    """
334*cda5da8dSAndroid Build Coastguard Worker    # Inspired by the ErrorHolder from Twisted:
335*cda5da8dSAndroid Build Coastguard Worker    # http://twistedmatrix.com/trac/browser/trunk/twisted/trial/runner.py
336*cda5da8dSAndroid Build Coastguard Worker
337*cda5da8dSAndroid Build Coastguard Worker    # attribute used by TestResult._exc_info_to_string
338*cda5da8dSAndroid Build Coastguard Worker    failureException = None
339*cda5da8dSAndroid Build Coastguard Worker
340*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, description):
341*cda5da8dSAndroid Build Coastguard Worker        self.description = description
342*cda5da8dSAndroid Build Coastguard Worker
343*cda5da8dSAndroid Build Coastguard Worker    def id(self):
344*cda5da8dSAndroid Build Coastguard Worker        return self.description
345*cda5da8dSAndroid Build Coastguard Worker
346*cda5da8dSAndroid Build Coastguard Worker    def shortDescription(self):
347*cda5da8dSAndroid Build Coastguard Worker        return None
348*cda5da8dSAndroid Build Coastguard Worker
349*cda5da8dSAndroid Build Coastguard Worker    def __repr__(self):
350*cda5da8dSAndroid Build Coastguard Worker        return "<ErrorHolder description=%r>" % (self.description,)
351*cda5da8dSAndroid Build Coastguard Worker
352*cda5da8dSAndroid Build Coastguard Worker    def __str__(self):
353*cda5da8dSAndroid Build Coastguard Worker        return self.id()
354*cda5da8dSAndroid Build Coastguard Worker
355*cda5da8dSAndroid Build Coastguard Worker    def run(self, result):
356*cda5da8dSAndroid Build Coastguard Worker        # could call result.addError(...) - but this test-like object
357*cda5da8dSAndroid Build Coastguard Worker        # shouldn't be run anyway
358*cda5da8dSAndroid Build Coastguard Worker        pass
359*cda5da8dSAndroid Build Coastguard Worker
360*cda5da8dSAndroid Build Coastguard Worker    def __call__(self, result):
361*cda5da8dSAndroid Build Coastguard Worker        return self.run(result)
362*cda5da8dSAndroid Build Coastguard Worker
363*cda5da8dSAndroid Build Coastguard Worker    def countTestCases(self):
364*cda5da8dSAndroid Build Coastguard Worker        return 0
365*cda5da8dSAndroid Build Coastguard Worker
366*cda5da8dSAndroid Build Coastguard Workerdef _isnotsuite(test):
367*cda5da8dSAndroid Build Coastguard Worker    "A crude way to tell apart testcases and suites with duck-typing"
368*cda5da8dSAndroid Build Coastguard Worker    try:
369*cda5da8dSAndroid Build Coastguard Worker        iter(test)
370*cda5da8dSAndroid Build Coastguard Worker    except TypeError:
371*cda5da8dSAndroid Build Coastguard Worker        return True
372*cda5da8dSAndroid Build Coastguard Worker    return False
373*cda5da8dSAndroid Build Coastguard Worker
374*cda5da8dSAndroid Build Coastguard Worker
375*cda5da8dSAndroid Build Coastguard Workerclass _DebugResult(object):
376*cda5da8dSAndroid Build Coastguard Worker    "Used by the TestSuite to hold previous class when running in debug."
377*cda5da8dSAndroid Build Coastguard Worker    _previousTestClass = None
378*cda5da8dSAndroid Build Coastguard Worker    _moduleSetUpFailed = False
379*cda5da8dSAndroid Build Coastguard Worker    shouldStop = False
380