Example #1
0
    def test_no_decorator(self):
        expected = inspect.getargspec(self.controller.index.__func__)
        actual = util.getargspec(self.controller.index.__func__)
        assert expected == actual

        expected = inspect.getargspec(self.controller.static_index)
        actual = util.getargspec(self.controller.static_index)
        assert expected == actual
Example #2
0
    def test_no_decorator(self):
        expected = inspect.getargspec(self.controller.index.__func__)
        actual = util.getargspec(self.controller.index.__func__)
        assert expected == actual

        expected = inspect.getargspec(self.controller.static_index)
        actual = util.getargspec(self.controller.static_index)
        assert expected == actual
Example #3
0
    def test_simple_decorator(self):
        def dec(f):
            return f

        expected = inspect.getargspec(self.controller.index.__func__)
        actual = util.getargspec(dec(self.controller.index.__func__))
        assert expected == actual

        expected = inspect.getargspec(self.controller.static_index)
        actual = util.getargspec(dec(self.controller.static_index))
        assert expected == actual
Example #4
0
    def test_simple_decorator(self):
        def dec(f):
            return f

        expected = inspect.getargspec(self.controller.index.__func__)
        actual = util.getargspec(dec(self.controller.index.__func__))
        assert expected == actual

        expected = inspect.getargspec(self.controller.static_index)
        actual = util.getargspec(dec(self.controller.static_index))
        assert expected == actual
Example #5
0
    def test_simple_wrapper(self):
        def dec(f):
            @functools.wraps(f)
            def wrapped(*a, **kw):
                return f(*a, **kw)
            return wrapped

        expected = inspect.getargspec(self.controller.index.__func__)
        actual = util.getargspec(dec(self.controller.index.__func__))
        assert expected == actual

        expected = inspect.getargspec(self.controller.static_index)
        actual = util.getargspec(dec(self.controller.static_index))
        assert expected == actual
Example #6
0
    def test_decorator_with_args(self):
        def dec(flag):
            def inner(f):
                @functools.wraps(f)
                def wrapped(*a, **kw):
                    return f(*a, **kw)
                return wrapped
            return inner

        expected = inspect.getargspec(self.controller.index.__func__)
        actual = util.getargspec(dec(True)(self.controller.index.__func__))
        assert expected == actual

        expected = inspect.getargspec(self.controller.static_index)
        actual = util.getargspec(dec(True)(
            self.controller.static_index))
        assert expected == actual
Example #7
0
    def _test_db_exceptions_handled(self, method, mock_object,
                                    receives_context, expect_retries):
        # NOTE(mpeterson): this test is very verbose, disabling logging
        logging.disable(logging.CRITICAL)
        self.addCleanup(logging.disable, logging.NOTSET)
        exceptions = RETRIABLE_EXCEPTIONS

        r_method = getattr(method, '__wrapped__', method)
        r_method_args = p_util.getargspec(r_method).args
        args_number = len(r_method_args) - (2 if r_method_args[0] == 'self'
                                            else 1)
        mock_arg = mock.MagicMock(unsafe=True)
        # NOTE(mpeterson): workarounds for py3 compatibility and behavior
        # expected by particular functions
        mock_arg.__name__ = 'mock_arg'
        mock_arg.retry_count = 1
        mock_arg.__ge__.return_value = True
        mock_arg.__gt__.return_value = True
        mock_arg.__le__.return_value = True
        mock_arg.__lt__.return_value = True
        args = (mock_arg, ) * args_number

        def _assertRaises(exceptions, method, *args, **kwargs):
            try:
                method(*args, **kwargs)
            except Exception as e:
                if not isinstance(e, exceptions):
                    raise e

                session = args[0].session if receives_context else args[0]

                if session.is_active and isinstance(e, _InnerException):
                    self.assertTrue(getattr(e, '_RETRY_EXCEEDED', False))
                return

            exc_names = (tuple(exc.__name__ for exc in exceptions) if hasattr(
                exceptions, '__iter__') else exceptions.__name__)

            self.fail('%s did not raise %s' % (method.__name__, exc_names))

        try:
            raise _InnerException
        except _InnerException as e:
            _e = e

        expected_retries = RETRY_MAX if expect_retries else 0
        db_object = self.db_context if receives_context else self.db_session

        for exception in exceptions:
            mock_object.side_effect = exception(_e)

            _assertRaises((exception, _InnerException), method, db_object,
                          *args)
            self.assertEqual(expected_retries, mock_object.call_count - 1)
            mock_object.reset_mock()
Example #8
0
    def decorator(f):
        try:
            # NOTE(kevinbenton): we use pecan's util function here because it
            # deals with the horrors of finding args of already decorated
            # functions
            ctx_arg_index = p_util.getargspec(f).args.index(context_var_name)
        except ValueError as e:
            msg = _("Could not find position of var %s") % context_var_name
            raise RuntimeError(msg) from e
        f_with_retry = retry_db_errors(f)

        @functools.wraps(f)
        def wrapped(*args, **kwargs):
            # only use retry wrapper if we aren't nested in an active
            # transaction
            context = kwargs.get(context_var_name)
            if context is None:
                context = args[ctx_arg_index]
            method = f if context.session.is_active else f_with_retry
            return method(*args, **kwargs)
        return wrapped
Example #9
0
    def decorator(f):
        try:
            # NOTE(kevinbenton): we use pecan's util function here because it
            # deals with the horrors of finding args of already decorated
            # functions
            ctx_arg_index = p_util.getargspec(f).args.index(context_var_name)
        except ValueError:
            raise RuntimeError("Could not find position of var %s" %
                               context_var_name)
        f_with_retry = retry_db_errors(f)

        @six.wraps(f)
        def wrapped(*args, **kwargs):
            # only use retry wrapper if we aren't nested in an active
            # transaction
            if context_var_name in kwargs:
                context = kwargs[context_var_name]
            else:
                context = args[ctx_arg_index]
            method = f if context.session.is_active else f_with_retry
            return method(*args, **kwargs)
        return wrapped
Example #10
0
    def _test_db_exceptions_handled(self, method, mock_object, expect_retries):
        # NOTE(mpeterson): make retries faster so it doesn't take a lot.
        retry_fixture = lib_fixtures.DBRetryErrorsFixture(
            max_retries=RETRY_MAX, retry_interval=RETRY_INTERVAL)
        retry_fixture.setUp()
        # NOTE(mpeterson): this test is very verbose, disabling logging
        logging.disable(logging.CRITICAL)
        self.addCleanup(logging.disable, logging.NOTSET)
        exceptions = RETRIABLE_EXCEPTIONS

        r_method = getattr(method, '__wrapped__', method)
        r_method_args = p_util.getargspec(r_method).args
        args_number = len(r_method_args) - (2 if r_method_args[0] == 'self'
                                            else 1)
        mock_arg = mock.MagicMock(unsafe=True)
        # NOTE(mpeterson): workarounds for py3 compatibility and behavior
        # expected by particular functions
        mock_arg.__name__ = 'mock_arg'
        mock_arg.retry_count = 1
        mock_arg.__ge__.return_value = True
        mock_arg.__gt__.return_value = True
        mock_arg.__le__.return_value = True
        mock_arg.__lt__.return_value = True
        args = (mock_arg,) * args_number

        def _assertRaises(exceptions, method, context, *args, **kwargs):
            try:
                method(context, *args, **kwargs)
            except Exception as e:
                if not isinstance(e, exceptions):
                    raise e

                # TODO(mpeterson): For now the check with session.is_active is
                # accepted, but when the enginefacade is the only accepted
                # pattern then it should be changed to check that a session is
                # attached to the context
                session = context.session

                if session.is_active and isinstance(e, _InnerException):
                    self.assertTrue(getattr(e, '_RETRY_EXCEEDED', False))
                return

            exc_names = (tuple(exc.__name__ for exc in exceptions)
                         if hasattr(exceptions, '__iter__') else
                         exceptions.__name__)

            self.fail('%s did not raise %s' % (method.__name__, exc_names))

        try:
            raise _InnerException
        except _InnerException as e:
            _e = e

        expected_retries = RETRY_MAX if expect_retries else 0

        # TODO(mpeterson): Make this an int when Py2 is no longer supported
        # and use the `nonlocal` directive
        retry_counter = [0]
        for exception in exceptions:
            def increase_retry_counter_and_except(*args, **kwargs):
                retry_counter[0] += 1
                self.db_context.session.add(self.retry_tracker())
                self.db_context.session.flush()
                raise exception(_e)
            mock_object.side_effect = increase_retry_counter_and_except

            _assertRaises((exception, _InnerException), method,
                          self.db_context, *args)
            self.assertEqual(expected_retries, mock_object.call_count - 1)
            mock_object.reset_mock()

        retry_fixture.cleanUp()
        return retry_counter[0]
Example #11
0
    def _test_db_exceptions_handled(self, method, mock_object, expect_retries):
        # NOTE(mpeterson): make retries faster so it doesn't take a lot.
        retry_fixture = lib_fixtures.DBRetryErrorsFixture(
            max_retries=RETRY_MAX, retry_interval=RETRY_INTERVAL)
        retry_fixture.setUp()
        # NOTE(mpeterson): this test is very verbose, disabling logging
        logging.disable(logging.CRITICAL)
        self.addCleanup(logging.disable, logging.NOTSET)
        exceptions = RETRIABLE_EXCEPTIONS

        r_method = getattr(method, '__wrapped__', method)
        r_method_args = p_util.getargspec(r_method).args
        args_number = len(r_method_args) - (2 if r_method_args[0] == 'self'
                                            else 1)
        mock_arg = mock.MagicMock(unsafe=True)
        # NOTE(mpeterson): workarounds for py3 compatibility and behavior
        # expected by particular functions
        mock_arg.__name__ = 'mock_arg'
        mock_arg.retry_count = 1
        mock_arg.__ge__.return_value = True
        mock_arg.__gt__.return_value = True
        mock_arg.__le__.return_value = True
        mock_arg.__lt__.return_value = True
        args = (mock_arg, ) * args_number

        def _assertRaises(exceptions, method, context, *args, **kwargs):
            try:
                method(context, *args, **kwargs)
            except Exception as e:
                if not isinstance(e, exceptions):
                    raise e

                # TODO(mpeterson): For now the check with session.is_active is
                # accepted, but when the enginefacade is the only accepted
                # pattern then it should be changed to check that a session is
                # attached to the context
                session = context.session

                if session.is_active and isinstance(e, _InnerException):
                    self.assertTrue(getattr(e, '_RETRY_EXCEEDED', False))
                return

            exc_names = (tuple(exc.__name__ for exc in exceptions) if hasattr(
                exceptions, '__iter__') else exceptions.__name__)

            self.fail('%s did not raise %s' % (method.__name__, exc_names))

        try:
            raise _InnerException
        except _InnerException as e:
            _e = e

        expected_retries = RETRY_MAX if expect_retries else 0

        # TODO(mpeterson): Make this an int when Py2 is no longer supported
        # and use the `nonlocal` directive
        retry_counter = [0]
        for exception in exceptions:

            def increase_retry_counter_and_except(*args, **kwargs):
                retry_counter[0] += 1
                self.db_context.session.add(self.retry_tracker())
                self.db_context.session.flush()
                raise exception(_e)

            mock_object.side_effect = increase_retry_counter_and_except

            _assertRaises((exception, _InnerException), method,
                          self.db_context, *args)
            self.assertEqual(expected_retries, mock_object.call_count - 1)
            mock_object.reset_mock()

        retry_fixture.cleanUp()
        return retry_counter[0]