예제 #1
0
 def test_multi_exception_raised_on_exceed(self):
     # limit retries so this doesn't take 40 seconds
     retry_fixture = fixture.DBRetryErrorsFixture(max_retries=2)
     retry_fixture.setUp()
     e = exceptions.MultipleExceptions([ValueError(), db_exc.DBDeadlock()])
     with testtools.ExpectedException(exceptions.MultipleExceptions):
         self._decorated_function(db_api.MAX_RETRIES + 1, e)
     retry_fixture.cleanUp()
예제 #2
0
    def test__create_dvr_mac_address_retries_exceeded_retry_logic(self):
        # limit retries so test doesn't take 40 seconds
        retry_fixture = fixture.DBRetryErrorsFixture(max_retries=2)
        retry_fixture.setUp()

        non_unique_mac = tools.get_random_EUI()
        self._create_dvr_mac_entry('foo_host_1', non_unique_mac)
        with mock.patch.object(net, 'get_random_mac') as f:
            f.return_value = non_unique_mac
            self.assertRaises(lib_exc.HostMacAddressGenerationFailure,
                              self.mixin._create_dvr_mac_address, self.ctx,
                              "foo_host_2")
        retry_fixture.cleanUp()
예제 #3
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]
예제 #4
0
    def _test_db_exceptions_handled(self, method, mock_object,
                                    receives_context, 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, *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()

        retry_fixture.cleanUp()