17db96d56Sopenharmony_ci"""TestSuite"""
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_ciimport sys
47db96d56Sopenharmony_ci
57db96d56Sopenharmony_cifrom . import case
67db96d56Sopenharmony_cifrom . import util
77db96d56Sopenharmony_ci
87db96d56Sopenharmony_ci__unittest = True
97db96d56Sopenharmony_ci
107db96d56Sopenharmony_ci
117db96d56Sopenharmony_cidef _call_if_exists(parent, attr):
127db96d56Sopenharmony_ci    func = getattr(parent, attr, lambda: None)
137db96d56Sopenharmony_ci    func()
147db96d56Sopenharmony_ci
157db96d56Sopenharmony_ci
167db96d56Sopenharmony_ciclass BaseTestSuite(object):
177db96d56Sopenharmony_ci    """A simple test suite that doesn't provide class or module shared fixtures.
187db96d56Sopenharmony_ci    """
197db96d56Sopenharmony_ci    _cleanup = True
207db96d56Sopenharmony_ci
217db96d56Sopenharmony_ci    def __init__(self, tests=()):
227db96d56Sopenharmony_ci        self._tests = []
237db96d56Sopenharmony_ci        self._removed_tests = 0
247db96d56Sopenharmony_ci        self.addTests(tests)
257db96d56Sopenharmony_ci
267db96d56Sopenharmony_ci    def __repr__(self):
277db96d56Sopenharmony_ci        return "<%s tests=%s>" % (util.strclass(self.__class__), list(self))
287db96d56Sopenharmony_ci
297db96d56Sopenharmony_ci    def __eq__(self, other):
307db96d56Sopenharmony_ci        if not isinstance(other, self.__class__):
317db96d56Sopenharmony_ci            return NotImplemented
327db96d56Sopenharmony_ci        return list(self) == list(other)
337db96d56Sopenharmony_ci
347db96d56Sopenharmony_ci    def __iter__(self):
357db96d56Sopenharmony_ci        return iter(self._tests)
367db96d56Sopenharmony_ci
377db96d56Sopenharmony_ci    def countTestCases(self):
387db96d56Sopenharmony_ci        cases = self._removed_tests
397db96d56Sopenharmony_ci        for test in self:
407db96d56Sopenharmony_ci            if test:
417db96d56Sopenharmony_ci                cases += test.countTestCases()
427db96d56Sopenharmony_ci        return cases
437db96d56Sopenharmony_ci
447db96d56Sopenharmony_ci    def addTest(self, test):
457db96d56Sopenharmony_ci        # sanity checks
467db96d56Sopenharmony_ci        if not callable(test):
477db96d56Sopenharmony_ci            raise TypeError("{} is not callable".format(repr(test)))
487db96d56Sopenharmony_ci        if isinstance(test, type) and issubclass(test,
497db96d56Sopenharmony_ci                                                 (case.TestCase, TestSuite)):
507db96d56Sopenharmony_ci            raise TypeError("TestCases and TestSuites must be instantiated "
517db96d56Sopenharmony_ci                            "before passing them to addTest()")
527db96d56Sopenharmony_ci        self._tests.append(test)
537db96d56Sopenharmony_ci
547db96d56Sopenharmony_ci    def addTests(self, tests):
557db96d56Sopenharmony_ci        if isinstance(tests, str):
567db96d56Sopenharmony_ci            raise TypeError("tests must be an iterable of tests, not a string")
577db96d56Sopenharmony_ci        for test in tests:
587db96d56Sopenharmony_ci            self.addTest(test)
597db96d56Sopenharmony_ci
607db96d56Sopenharmony_ci    def run(self, result):
617db96d56Sopenharmony_ci        for index, test in enumerate(self):
627db96d56Sopenharmony_ci            if result.shouldStop:
637db96d56Sopenharmony_ci                break
647db96d56Sopenharmony_ci            test(result)
657db96d56Sopenharmony_ci            if self._cleanup:
667db96d56Sopenharmony_ci                self._removeTestAtIndex(index)
677db96d56Sopenharmony_ci        return result
687db96d56Sopenharmony_ci
697db96d56Sopenharmony_ci    def _removeTestAtIndex(self, index):
707db96d56Sopenharmony_ci        """Stop holding a reference to the TestCase at index."""
717db96d56Sopenharmony_ci        try:
727db96d56Sopenharmony_ci            test = self._tests[index]
737db96d56Sopenharmony_ci        except TypeError:
747db96d56Sopenharmony_ci            # support for suite implementations that have overridden self._tests
757db96d56Sopenharmony_ci            pass
767db96d56Sopenharmony_ci        else:
777db96d56Sopenharmony_ci            # Some unittest tests add non TestCase/TestSuite objects to
787db96d56Sopenharmony_ci            # the suite.
797db96d56Sopenharmony_ci            if hasattr(test, 'countTestCases'):
807db96d56Sopenharmony_ci                self._removed_tests += test.countTestCases()
817db96d56Sopenharmony_ci            self._tests[index] = None
827db96d56Sopenharmony_ci
837db96d56Sopenharmony_ci    def __call__(self, *args, **kwds):
847db96d56Sopenharmony_ci        return self.run(*args, **kwds)
857db96d56Sopenharmony_ci
867db96d56Sopenharmony_ci    def debug(self):
877db96d56Sopenharmony_ci        """Run the tests without collecting errors in a TestResult"""
887db96d56Sopenharmony_ci        for test in self:
897db96d56Sopenharmony_ci            test.debug()
907db96d56Sopenharmony_ci
917db96d56Sopenharmony_ci
927db96d56Sopenharmony_ciclass TestSuite(BaseTestSuite):
937db96d56Sopenharmony_ci    """A test suite is a composite test consisting of a number of TestCases.
947db96d56Sopenharmony_ci
957db96d56Sopenharmony_ci    For use, create an instance of TestSuite, then add test case instances.
967db96d56Sopenharmony_ci    When all tests have been added, the suite can be passed to a test
977db96d56Sopenharmony_ci    runner, such as TextTestRunner. It will run the individual test cases
987db96d56Sopenharmony_ci    in the order in which they were added, aggregating the results. When
997db96d56Sopenharmony_ci    subclassing, do not forget to call the base class constructor.
1007db96d56Sopenharmony_ci    """
1017db96d56Sopenharmony_ci
1027db96d56Sopenharmony_ci    def run(self, result, debug=False):
1037db96d56Sopenharmony_ci        topLevel = False
1047db96d56Sopenharmony_ci        if getattr(result, '_testRunEntered', False) is False:
1057db96d56Sopenharmony_ci            result._testRunEntered = topLevel = True
1067db96d56Sopenharmony_ci
1077db96d56Sopenharmony_ci        for index, test in enumerate(self):
1087db96d56Sopenharmony_ci            if result.shouldStop:
1097db96d56Sopenharmony_ci                break
1107db96d56Sopenharmony_ci
1117db96d56Sopenharmony_ci            if _isnotsuite(test):
1127db96d56Sopenharmony_ci                self._tearDownPreviousClass(test, result)
1137db96d56Sopenharmony_ci                self._handleModuleFixture(test, result)
1147db96d56Sopenharmony_ci                self._handleClassSetUp(test, result)
1157db96d56Sopenharmony_ci                result._previousTestClass = test.__class__
1167db96d56Sopenharmony_ci
1177db96d56Sopenharmony_ci                if (getattr(test.__class__, '_classSetupFailed', False) or
1187db96d56Sopenharmony_ci                    getattr(result, '_moduleSetUpFailed', False)):
1197db96d56Sopenharmony_ci                    continue
1207db96d56Sopenharmony_ci
1217db96d56Sopenharmony_ci            if not debug:
1227db96d56Sopenharmony_ci                test(result)
1237db96d56Sopenharmony_ci            else:
1247db96d56Sopenharmony_ci                test.debug()
1257db96d56Sopenharmony_ci
1267db96d56Sopenharmony_ci            if self._cleanup:
1277db96d56Sopenharmony_ci                self._removeTestAtIndex(index)
1287db96d56Sopenharmony_ci
1297db96d56Sopenharmony_ci        if topLevel:
1307db96d56Sopenharmony_ci            self._tearDownPreviousClass(None, result)
1317db96d56Sopenharmony_ci            self._handleModuleTearDown(result)
1327db96d56Sopenharmony_ci            result._testRunEntered = False
1337db96d56Sopenharmony_ci        return result
1347db96d56Sopenharmony_ci
1357db96d56Sopenharmony_ci    def debug(self):
1367db96d56Sopenharmony_ci        """Run the tests without collecting errors in a TestResult"""
1377db96d56Sopenharmony_ci        debug = _DebugResult()
1387db96d56Sopenharmony_ci        self.run(debug, True)
1397db96d56Sopenharmony_ci
1407db96d56Sopenharmony_ci    ################################
1417db96d56Sopenharmony_ci
1427db96d56Sopenharmony_ci    def _handleClassSetUp(self, test, result):
1437db96d56Sopenharmony_ci        previousClass = getattr(result, '_previousTestClass', None)
1447db96d56Sopenharmony_ci        currentClass = test.__class__
1457db96d56Sopenharmony_ci        if currentClass == previousClass:
1467db96d56Sopenharmony_ci            return
1477db96d56Sopenharmony_ci        if result._moduleSetUpFailed:
1487db96d56Sopenharmony_ci            return
1497db96d56Sopenharmony_ci        if getattr(currentClass, "__unittest_skip__", False):
1507db96d56Sopenharmony_ci            return
1517db96d56Sopenharmony_ci
1527db96d56Sopenharmony_ci        failed = False
1537db96d56Sopenharmony_ci        try:
1547db96d56Sopenharmony_ci            currentClass._classSetupFailed = False
1557db96d56Sopenharmony_ci        except TypeError:
1567db96d56Sopenharmony_ci            # test may actually be a function
1577db96d56Sopenharmony_ci            # so its class will be a builtin-type
1587db96d56Sopenharmony_ci            pass
1597db96d56Sopenharmony_ci
1607db96d56Sopenharmony_ci        setUpClass = getattr(currentClass, 'setUpClass', None)
1617db96d56Sopenharmony_ci        doClassCleanups = getattr(currentClass, 'doClassCleanups', None)
1627db96d56Sopenharmony_ci        if setUpClass is not None:
1637db96d56Sopenharmony_ci            _call_if_exists(result, '_setupStdout')
1647db96d56Sopenharmony_ci            try:
1657db96d56Sopenharmony_ci                try:
1667db96d56Sopenharmony_ci                    setUpClass()
1677db96d56Sopenharmony_ci                except Exception as e:
1687db96d56Sopenharmony_ci                    if isinstance(result, _DebugResult):
1697db96d56Sopenharmony_ci                        raise
1707db96d56Sopenharmony_ci                    failed = True
1717db96d56Sopenharmony_ci                    try:
1727db96d56Sopenharmony_ci                        currentClass._classSetupFailed = True
1737db96d56Sopenharmony_ci                    except TypeError:
1747db96d56Sopenharmony_ci                        pass
1757db96d56Sopenharmony_ci                    className = util.strclass(currentClass)
1767db96d56Sopenharmony_ci                    self._createClassOrModuleLevelException(result, e,
1777db96d56Sopenharmony_ci                                                            'setUpClass',
1787db96d56Sopenharmony_ci                                                            className)
1797db96d56Sopenharmony_ci                if failed and doClassCleanups is not None:
1807db96d56Sopenharmony_ci                    doClassCleanups()
1817db96d56Sopenharmony_ci                    for exc_info in currentClass.tearDown_exceptions:
1827db96d56Sopenharmony_ci                        self._createClassOrModuleLevelException(
1837db96d56Sopenharmony_ci                                result, exc_info[1], 'setUpClass', className,
1847db96d56Sopenharmony_ci                                info=exc_info)
1857db96d56Sopenharmony_ci            finally:
1867db96d56Sopenharmony_ci                _call_if_exists(result, '_restoreStdout')
1877db96d56Sopenharmony_ci
1887db96d56Sopenharmony_ci    def _get_previous_module(self, result):
1897db96d56Sopenharmony_ci        previousModule = None
1907db96d56Sopenharmony_ci        previousClass = getattr(result, '_previousTestClass', None)
1917db96d56Sopenharmony_ci        if previousClass is not None:
1927db96d56Sopenharmony_ci            previousModule = previousClass.__module__
1937db96d56Sopenharmony_ci        return previousModule
1947db96d56Sopenharmony_ci
1957db96d56Sopenharmony_ci
1967db96d56Sopenharmony_ci    def _handleModuleFixture(self, test, result):
1977db96d56Sopenharmony_ci        previousModule = self._get_previous_module(result)
1987db96d56Sopenharmony_ci        currentModule = test.__class__.__module__
1997db96d56Sopenharmony_ci        if currentModule == previousModule:
2007db96d56Sopenharmony_ci            return
2017db96d56Sopenharmony_ci
2027db96d56Sopenharmony_ci        self._handleModuleTearDown(result)
2037db96d56Sopenharmony_ci
2047db96d56Sopenharmony_ci
2057db96d56Sopenharmony_ci        result._moduleSetUpFailed = False
2067db96d56Sopenharmony_ci        try:
2077db96d56Sopenharmony_ci            module = sys.modules[currentModule]
2087db96d56Sopenharmony_ci        except KeyError:
2097db96d56Sopenharmony_ci            return
2107db96d56Sopenharmony_ci        setUpModule = getattr(module, 'setUpModule', None)
2117db96d56Sopenharmony_ci        if setUpModule is not None:
2127db96d56Sopenharmony_ci            _call_if_exists(result, '_setupStdout')
2137db96d56Sopenharmony_ci            try:
2147db96d56Sopenharmony_ci                try:
2157db96d56Sopenharmony_ci                    setUpModule()
2167db96d56Sopenharmony_ci                except Exception as e:
2177db96d56Sopenharmony_ci                    if isinstance(result, _DebugResult):
2187db96d56Sopenharmony_ci                        raise
2197db96d56Sopenharmony_ci                    result._moduleSetUpFailed = True
2207db96d56Sopenharmony_ci                    self._createClassOrModuleLevelException(result, e,
2217db96d56Sopenharmony_ci                                                            'setUpModule',
2227db96d56Sopenharmony_ci                                                            currentModule)
2237db96d56Sopenharmony_ci                if result._moduleSetUpFailed:
2247db96d56Sopenharmony_ci                    try:
2257db96d56Sopenharmony_ci                        case.doModuleCleanups()
2267db96d56Sopenharmony_ci                    except Exception as e:
2277db96d56Sopenharmony_ci                        self._createClassOrModuleLevelException(result, e,
2287db96d56Sopenharmony_ci                                                                'setUpModule',
2297db96d56Sopenharmony_ci                                                                currentModule)
2307db96d56Sopenharmony_ci            finally:
2317db96d56Sopenharmony_ci                _call_if_exists(result, '_restoreStdout')
2327db96d56Sopenharmony_ci
2337db96d56Sopenharmony_ci    def _createClassOrModuleLevelException(self, result, exc, method_name,
2347db96d56Sopenharmony_ci                                           parent, info=None):
2357db96d56Sopenharmony_ci        errorName = f'{method_name} ({parent})'
2367db96d56Sopenharmony_ci        self._addClassOrModuleLevelException(result, exc, errorName, info)
2377db96d56Sopenharmony_ci
2387db96d56Sopenharmony_ci    def _addClassOrModuleLevelException(self, result, exception, errorName,
2397db96d56Sopenharmony_ci                                        info=None):
2407db96d56Sopenharmony_ci        error = _ErrorHolder(errorName)
2417db96d56Sopenharmony_ci        addSkip = getattr(result, 'addSkip', None)
2427db96d56Sopenharmony_ci        if addSkip is not None and isinstance(exception, case.SkipTest):
2437db96d56Sopenharmony_ci            addSkip(error, str(exception))
2447db96d56Sopenharmony_ci        else:
2457db96d56Sopenharmony_ci            if not info:
2467db96d56Sopenharmony_ci                result.addError(error, sys.exc_info())
2477db96d56Sopenharmony_ci            else:
2487db96d56Sopenharmony_ci                result.addError(error, info)
2497db96d56Sopenharmony_ci
2507db96d56Sopenharmony_ci    def _handleModuleTearDown(self, result):
2517db96d56Sopenharmony_ci        previousModule = self._get_previous_module(result)
2527db96d56Sopenharmony_ci        if previousModule is None:
2537db96d56Sopenharmony_ci            return
2547db96d56Sopenharmony_ci        if result._moduleSetUpFailed:
2557db96d56Sopenharmony_ci            return
2567db96d56Sopenharmony_ci
2577db96d56Sopenharmony_ci        try:
2587db96d56Sopenharmony_ci            module = sys.modules[previousModule]
2597db96d56Sopenharmony_ci        except KeyError:
2607db96d56Sopenharmony_ci            return
2617db96d56Sopenharmony_ci
2627db96d56Sopenharmony_ci        _call_if_exists(result, '_setupStdout')
2637db96d56Sopenharmony_ci        try:
2647db96d56Sopenharmony_ci            tearDownModule = getattr(module, 'tearDownModule', None)
2657db96d56Sopenharmony_ci            if tearDownModule is not None:
2667db96d56Sopenharmony_ci                try:
2677db96d56Sopenharmony_ci                    tearDownModule()
2687db96d56Sopenharmony_ci                except Exception as e:
2697db96d56Sopenharmony_ci                    if isinstance(result, _DebugResult):
2707db96d56Sopenharmony_ci                        raise
2717db96d56Sopenharmony_ci                    self._createClassOrModuleLevelException(result, e,
2727db96d56Sopenharmony_ci                                                            'tearDownModule',
2737db96d56Sopenharmony_ci                                                            previousModule)
2747db96d56Sopenharmony_ci            try:
2757db96d56Sopenharmony_ci                case.doModuleCleanups()
2767db96d56Sopenharmony_ci            except Exception as e:
2777db96d56Sopenharmony_ci                if isinstance(result, _DebugResult):
2787db96d56Sopenharmony_ci                    raise
2797db96d56Sopenharmony_ci                self._createClassOrModuleLevelException(result, e,
2807db96d56Sopenharmony_ci                                                        'tearDownModule',
2817db96d56Sopenharmony_ci                                                        previousModule)
2827db96d56Sopenharmony_ci        finally:
2837db96d56Sopenharmony_ci            _call_if_exists(result, '_restoreStdout')
2847db96d56Sopenharmony_ci
2857db96d56Sopenharmony_ci    def _tearDownPreviousClass(self, test, result):
2867db96d56Sopenharmony_ci        previousClass = getattr(result, '_previousTestClass', None)
2877db96d56Sopenharmony_ci        currentClass = test.__class__
2887db96d56Sopenharmony_ci        if currentClass == previousClass or previousClass is None:
2897db96d56Sopenharmony_ci            return
2907db96d56Sopenharmony_ci        if getattr(previousClass, '_classSetupFailed', False):
2917db96d56Sopenharmony_ci            return
2927db96d56Sopenharmony_ci        if getattr(result, '_moduleSetUpFailed', False):
2937db96d56Sopenharmony_ci            return
2947db96d56Sopenharmony_ci        if getattr(previousClass, "__unittest_skip__", False):
2957db96d56Sopenharmony_ci            return
2967db96d56Sopenharmony_ci
2977db96d56Sopenharmony_ci        tearDownClass = getattr(previousClass, 'tearDownClass', None)
2987db96d56Sopenharmony_ci        doClassCleanups = getattr(previousClass, 'doClassCleanups', None)
2997db96d56Sopenharmony_ci        if tearDownClass is None and doClassCleanups is None:
3007db96d56Sopenharmony_ci            return
3017db96d56Sopenharmony_ci
3027db96d56Sopenharmony_ci        _call_if_exists(result, '_setupStdout')
3037db96d56Sopenharmony_ci        try:
3047db96d56Sopenharmony_ci            if tearDownClass is not None:
3057db96d56Sopenharmony_ci                try:
3067db96d56Sopenharmony_ci                    tearDownClass()
3077db96d56Sopenharmony_ci                except Exception as e:
3087db96d56Sopenharmony_ci                    if isinstance(result, _DebugResult):
3097db96d56Sopenharmony_ci                        raise
3107db96d56Sopenharmony_ci                    className = util.strclass(previousClass)
3117db96d56Sopenharmony_ci                    self._createClassOrModuleLevelException(result, e,
3127db96d56Sopenharmony_ci                                                            'tearDownClass',
3137db96d56Sopenharmony_ci                                                            className)
3147db96d56Sopenharmony_ci            if doClassCleanups is not None:
3157db96d56Sopenharmony_ci                doClassCleanups()
3167db96d56Sopenharmony_ci                for exc_info in previousClass.tearDown_exceptions:
3177db96d56Sopenharmony_ci                    if isinstance(result, _DebugResult):
3187db96d56Sopenharmony_ci                        raise exc_info[1]
3197db96d56Sopenharmony_ci                    className = util.strclass(previousClass)
3207db96d56Sopenharmony_ci                    self._createClassOrModuleLevelException(result, exc_info[1],
3217db96d56Sopenharmony_ci                                                            'tearDownClass',
3227db96d56Sopenharmony_ci                                                            className,
3237db96d56Sopenharmony_ci                                                            info=exc_info)
3247db96d56Sopenharmony_ci        finally:
3257db96d56Sopenharmony_ci            _call_if_exists(result, '_restoreStdout')
3267db96d56Sopenharmony_ci
3277db96d56Sopenharmony_ci
3287db96d56Sopenharmony_ciclass _ErrorHolder(object):
3297db96d56Sopenharmony_ci    """
3307db96d56Sopenharmony_ci    Placeholder for a TestCase inside a result. As far as a TestResult
3317db96d56Sopenharmony_ci    is concerned, this looks exactly like a unit test. Used to insert
3327db96d56Sopenharmony_ci    arbitrary errors into a test suite run.
3337db96d56Sopenharmony_ci    """
3347db96d56Sopenharmony_ci    # Inspired by the ErrorHolder from Twisted:
3357db96d56Sopenharmony_ci    # http://twistedmatrix.com/trac/browser/trunk/twisted/trial/runner.py
3367db96d56Sopenharmony_ci
3377db96d56Sopenharmony_ci    # attribute used by TestResult._exc_info_to_string
3387db96d56Sopenharmony_ci    failureException = None
3397db96d56Sopenharmony_ci
3407db96d56Sopenharmony_ci    def __init__(self, description):
3417db96d56Sopenharmony_ci        self.description = description
3427db96d56Sopenharmony_ci
3437db96d56Sopenharmony_ci    def id(self):
3447db96d56Sopenharmony_ci        return self.description
3457db96d56Sopenharmony_ci
3467db96d56Sopenharmony_ci    def shortDescription(self):
3477db96d56Sopenharmony_ci        return None
3487db96d56Sopenharmony_ci
3497db96d56Sopenharmony_ci    def __repr__(self):
3507db96d56Sopenharmony_ci        return "<ErrorHolder description=%r>" % (self.description,)
3517db96d56Sopenharmony_ci
3527db96d56Sopenharmony_ci    def __str__(self):
3537db96d56Sopenharmony_ci        return self.id()
3547db96d56Sopenharmony_ci
3557db96d56Sopenharmony_ci    def run(self, result):
3567db96d56Sopenharmony_ci        # could call result.addError(...) - but this test-like object
3577db96d56Sopenharmony_ci        # shouldn't be run anyway
3587db96d56Sopenharmony_ci        pass
3597db96d56Sopenharmony_ci
3607db96d56Sopenharmony_ci    def __call__(self, result):
3617db96d56Sopenharmony_ci        return self.run(result)
3627db96d56Sopenharmony_ci
3637db96d56Sopenharmony_ci    def countTestCases(self):
3647db96d56Sopenharmony_ci        return 0
3657db96d56Sopenharmony_ci
3667db96d56Sopenharmony_cidef _isnotsuite(test):
3677db96d56Sopenharmony_ci    "A crude way to tell apart testcases and suites with duck-typing"
3687db96d56Sopenharmony_ci    try:
3697db96d56Sopenharmony_ci        iter(test)
3707db96d56Sopenharmony_ci    except TypeError:
3717db96d56Sopenharmony_ci        return True
3727db96d56Sopenharmony_ci    return False
3737db96d56Sopenharmony_ci
3747db96d56Sopenharmony_ci
3757db96d56Sopenharmony_ciclass _DebugResult(object):
3767db96d56Sopenharmony_ci    "Used by the TestSuite to hold previous class when running in debug."
3777db96d56Sopenharmony_ci    _previousTestClass = None
3787db96d56Sopenharmony_ci    _moduleSetUpFailed = False
3797db96d56Sopenharmony_ci    shouldStop = False
380