Exemplo n.º 1
0
    def test_arguments_are_preserved_in_retries(self):
        for i in xrange(3):
            doc = search.Document(doc_id='doc%d' % i, fields=[
                search.TextField('prop', 'val'),
                search.NumberField('index', i)
            ])
            search.Index('my_index').put(doc)

        exception = search.TransientError('oops')
        failing_index_search = test_utils.FailingFunction(
            search.Index.search, exception, 3)

        search_counter = test_utils.CallCounter(gae_search_services.search)

        gae_search_ctx = self.swap(
            search.Index, 'search', failing_index_search)
        search_counter_ctx = self.swap(
            gae_search_services, 'search', search_counter)
        with gae_search_ctx, search_counter_ctx:
            result, cursor = gae_search_services.search(
                'prop:val',
                'my_index',
                sort='-index',
                limit=2,
                ids_only=True,
                retries=4)

        failing_index_search2 = test_utils.FailingFunction(
            search.Index.search,
            exception,
            3)

        search_counter2 = test_utils.CallCounter(gae_search_services.search)

        gae_search_ctx2 = self.swap(
            search.Index, 'search', failing_index_search2)
        search_counter_ctx2 = self.swap(
            gae_search_services, 'search', search_counter2)
        with gae_search_ctx2, search_counter_ctx2:
            result2, cursor = gae_search_services.search(
                'prop:val',
                'my_index',
                sort='-index',
                limit=2,
                cursor=cursor,
                ids_only=True,
                retries=4)

        self.assertEqual(search_counter.times_called, 4)
        self.assertEqual(result, ['doc2', 'doc1'])

        # also check that the cursor is preserved
        self.assertEqual(search_counter2.times_called, 4)
        self.assertEqual(result2, ['doc0'])
Exemplo n.º 2
0
    def test_put_error_without_transient_result(self):
        docs = [{
            'id': 'doc1',
            'prop': 'val1'
        }, {
            'id': 'doc2',
            'prop': 'val2'
        }, {
            'id': 'doc3',
            'prop': 'val3'
        }]

        error = self._get_put_error(3)
        failing_put = test_utils.FailingFunction(search.Index.put, error, 1)

        add_docs_counter = test_utils.CallCounter(
            gae_search_services.add_documents_to_index)
        add_docs_ctx = self.swap(gae_search_services, 'add_documents_to_index',
                                 add_docs_counter)
        put_ctx = self.swap(search.Index, 'put', failing_put)
        assert_raises_ctx = self.assertRaisesRegexp(
            gae_search_services.SearchFailureError,
            '<class \'google.appengine.api.search.search.PutError\'>: lol')
        with add_docs_ctx, put_ctx, assert_raises_ctx as e:
            gae_search_services.add_documents_to_index(docs, 'my_index')

        # Assert that the method only gets called once, since the error is not
        # transient.
        self.assertEqual(add_docs_counter.times_called, 1)
        self.assertEqual(e.exception.original_exception, error)
Exemplo n.º 3
0
    def test_delete_error_with_transient_result(self):
        error = self._get_delete_error(3, transient=1)
        failing_delete = test_utils.FailingFunction(search.Index.delete, error,
                                                    4)
        delete_docs_counter = test_utils.CallCounter(
            gae_search_services.delete_documents_from_index)
        index = search.Index('my_index')
        for i in xrange(3):
            index.put(
                search.Document(
                    doc_id='d' + str(i),
                    fields=[search.TextField(name='prop', value='value')]))

        delete_ctx = self.swap(search.Index, 'delete', failing_delete)
        delete_docs_ctx = self.swap(gae_search_services,
                                    'delete_documents_from_index',
                                    delete_docs_counter)
        with delete_ctx, delete_docs_ctx:
            gae_search_services.delete_documents_from_index(['d0', 'd1', 'd2'],
                                                            'my_index',
                                                            retries=5)

        self.assertEqual(delete_docs_counter.times_called, 5)
        for i in xrange(3):
            result = search.Index('my_index').get('doc' + str(i))
            self.assertIsNone(result)
Exemplo n.º 4
0
    def test_arguments_are_preserved_in_retries(self):
        index = search.Index('index')
        index.put([
            search.Document(
                doc_id='doc',
                fields=[search.TextField(name='prop', value='val')])
        ])
        exception = self._get_delete_error(1, 0)
        failing_delete = test_utils.FailingFunction(search.Index.delete,
                                                    exception, 3)

        delete_docs_counter = test_utils.CallCounter(
            gae_search_services.delete_documents_from_index)

        index_ctx = self.swap(search.Index, 'delete', failing_delete)
        delete_docs_ctx = self.swap(gae_search_services,
                                    'delete_documents_from_index',
                                    delete_docs_counter)
        with index_ctx, delete_docs_ctx:
            gae_search_services.delete_documents_from_index(['doc'], 'index',
                                                            4)

        self.assertEqual(delete_docs_counter.times_called, 4)
        result = search.Index('my_index').get('doc')
        self.assertIsNone(result)
Exemplo n.º 5
0
    def test_arguments_are_preserved_in_retries(self):
        doc = {'id': 'doc', 'prop': 'val'}
        exception = self._get_put_error(1, transient=0)
        failing_put = test_utils.FailingFunction(
            search.Index.put,
            exception,
            3
        )

        add_docs_counter = test_utils.CallCounter(
            gae_search_services.add_documents_to_index)

        put_ctx = self.swap(search.Index, 'put', failing_put)
        add_docs_ctx = self.swap(
            gae_search_services,
            'add_documents_to_index',
            add_docs_counter)

        with put_ctx, add_docs_ctx:
            gae_search_services.add_documents_to_index(
                [doc], 'my_index', retries=4)

        self.assertEqual(add_docs_counter.times_called, 4)
        result = search.Index('my_index').get('doc')
        self.assertEqual(result.field('prop').value, 'val')
Exemplo n.º 6
0
    def test_put_error_with_transient_result(self):
        docs = [{
            'id': 'doc1',
            'prop': 'val1'
        }, {
            'id': 'doc2',
            'prop': 'val2'
        }, {
            'id': 'doc3',
            'prop': 'val3'
        }]
        error = self._get_put_error(3, 1)
        failing_put = test_utils.FailingFunction(search.Index.put, error, 4)

        add_docs_counter = test_utils.CallCounter(
            gae_search_services.add_documents_to_index)
        put_ctx = self.swap(search.Index, 'put', failing_put)
        add_docs_ctx = self.swap(gae_search_services, 'add_documents_to_index',
                                 add_docs_counter)

        with put_ctx, add_docs_ctx:
            gae_search_services.add_documents_to_index(docs, 'my_index', 5)

        self.assertEqual(add_docs_counter.times_called, 5)
        for i in xrange(1, 4):
            result = search.Index('my_index').get('doc' + str(i))
            self.assertEqual(result.field('prop').value, 'val' + str(i))
Exemplo n.º 7
0
    def test_use_default_num_retries(self):
        exception = self._get_delete_error(1, 0)
        failing_delete = test_utils.FailingFunction(
            search.Index.delete,
            exception,
            gae_search_services.DEFAULT_NUM_RETRIES
            )

        delete_docs_counter = test_utils.CallCounter(
            gae_search_services.delete_documents_from_index)

        delete_ctx = self.swap(search.Index, 'delete', failing_delete)
        delete_docs_ctx = self.swap(
            gae_search_services,
            'delete_documents_from_index',
            delete_docs_counter)
        assert_raises_ctx = self.assertRaises(
            gae_search_services.SearchFailureError)
        with delete_ctx, delete_docs_ctx, assert_raises_ctx as context_mgr:
            gae_search_services.delete_documents_from_index(
                ['doc'], 'my_index')

        self.assertEqual(context_mgr.exception.original_exception, exception)

        self.assertEqual(
            delete_docs_counter.times_called,
            gae_search_services.DEFAULT_NUM_RETRIES)
Exemplo n.º 8
0
    def test_use_default_num_retries(self):
        doc = {'id': 'doc', 'prop': 'val'}
        exception = self._get_put_error(1, 0)
        failing_put = test_utils.FailingFunction(
            search.Index.put,
            exception,
            gae_search_services.DEFAULT_NUM_RETRIES,
            )

        add_docs_counter = test_utils.CallCounter(
            gae_search_services.add_documents_to_index)

        put_ctx = self.swap(search.Index, 'put', failing_put)
        add_docs_ctx = self.swap(
            gae_search_services,
            'add_documents_to_index',
            add_docs_counter)
        assert_raises_ctx = self.assertRaises(
            gae_search_services.SearchFailureError)
        with put_ctx, add_docs_ctx, assert_raises_ctx as context_mgr:
            gae_search_services.add_documents_to_index([doc], 'my_index')

        self.assertEqual(context_mgr.exception.original_exception, exception)

        self.assertEqual(
            add_docs_counter.times_called,
            gae_search_services.DEFAULT_NUM_RETRIES)
Exemplo n.º 9
0
    def test_failing_function_raises_error_with_invalid_num_tries(self):
        class MockError(Exception):
            pass

        function = lambda x: x ** 2

        with self.assertRaisesRegex(
            ValueError,
            'num_tries_before_success should either be an integer greater than '
            'or equal to 0, or FailingFunction.INFINITY'):
            test_utils.FailingFunction(function, MockError, -1)
Exemplo n.º 10
0
    def test_failing_function_never_succeeds_when_n_is_infinity(self):
        class MockError(Exception):
            pass

        function = lambda x: x**2

        failing_func = test_utils.FailingFunction(
            function, MockError, test_utils.FailingFunction.INFINITY)

        for i in xrange(20):
            with self.assertRaises(MockError):
                failing_func(i)
Exemplo n.º 11
0
    def test_failing_function_never_succeeds_when_n_is_infinity(self):
        class MockError(Exception):
            pass

        function = lambda x: x ** 2

        failing_func = test_utils.FailingFunction(
            function, MockError('Dummy Exception'),
            test_utils.FailingFunction.INFINITY)

        for i in python_utils.RANGE(20):
            with self.assertRaisesRegexp(MockError, 'Dummy Exception'):
                failing_func(i)
Exemplo n.º 12
0
    def test_failing_function_fails_for_first_n_calls(self):
        class MockError(Exception):
            pass

        function = lambda x: x**2

        failing_func = test_utils.FailingFunction(function, MockError, 5)

        for i in xrange(5):
            with self.assertRaises(MockError):
                failing_func(i)
                raise ValueError(str(i))

        self.assertEqual(failing_func(5), 25)
Exemplo n.º 13
0
    def test_use_custom_number_of_retries(self):
        exception = search.TransientError('oops')
        failing_index_search = test_utils.FailingFunction(
            search.Index.search, exception, 3)

        search_counter = test_utils.CallCounter(gae_search_services.search)

        index_ctx = self.swap(search.Index, 'search', failing_index_search)
        search_counter_ctx = self.swap(gae_search_services, 'search',
                                       search_counter)
        assert_raises_ctx = self.assertRaises(
            gae_search_services.SearchFailureError)
        with index_ctx, search_counter_ctx, assert_raises_ctx:
            gae_search_services.search('query', 'my_index', retries=3)

        self.assertEqual(search_counter.times_called, 3)
Exemplo n.º 14
0
    def test_use_custom_number_of_retries(self):
        doc = {'id': 'doc', 'prop': 'val'}
        exception = self._get_put_error(1, 0)
        failing_put = test_utils.FailingFunction(search.Index.put, exception,
                                                 42)

        add_docs_counter = test_utils.CallCounter(
            gae_search_services.add_documents_to_index)

        put_ctx = self.swap(search.Index, 'put', failing_put)
        add_docs_ctx = self.swap(gae_search_services, 'add_documents_to_index',
                                 add_docs_counter)
        assert_raises_ctx = self.assertRaises(
            gae_search_services.SearchFailureError)
        with put_ctx, add_docs_ctx, assert_raises_ctx:
            gae_search_services.add_documents_to_index([doc], 'my_index', 42)

        self.assertEqual(add_docs_counter.times_called, 42)
Exemplo n.º 15
0
    def test_put_error_without_transient_result(self):
        error = self._get_delete_error(3)
        delete_spy = test_utils.FailingFunction(search.Index.delete, error, 1)
        delete_docs_counter = test_utils.CallCounter(
            gae_search_services.delete_documents_from_index)
        delete_docs_ctx = self.swap(gae_search_services,
                                    'delete_documents_from_index',
                                    delete_docs_counter)
        delete_ctx = self.swap(search.Index, 'delete', delete_spy)
        assert_raises_ctx = self.assertRaises(
            gae_search_services.SearchFailureError)
        with delete_docs_ctx, delete_ctx, assert_raises_ctx as e:
            gae_search_services.delete_documents_from_index(['a', 'b', 'c'],
                                                            'my_index')

        # assert that the method only gets called once, since the error is not
        # transient.
        self.assertEqual(delete_docs_counter.times_called, 1)
        self.assertEqual(e.exception.original_exception, error)
Exemplo n.º 16
0
    def test_use_custom_number_of_retries(self):
        exception = self._get_delete_error(1, 0)
        failing_delete = test_utils.FailingFunction(search.Index.delete,
                                                    exception, 42)

        delete_docs_counter = test_utils.CallCounter(
            gae_search_services.delete_documents_from_index)

        delete_ctx = self.swap(search.Index, 'delete', failing_delete)
        delete_docs_ctx = self.swap(gae_search_services,
                                    'delete_documents_from_index',
                                    delete_docs_counter)
        assert_raises_ctx = self.assertRaises(
            gae_search_services.SearchFailureError)
        with delete_ctx, delete_docs_ctx, assert_raises_ctx:
            gae_search_services.delete_documents_from_index(['id'], 'index',
                                                            42)

        self.assertEqual(delete_docs_counter.times_called, 42)
Exemplo n.º 17
0
    def test_use_default_num_retries(self):
        exception = search.TransientError('oops')
        failing_index_search = test_utils.FailingFunction(
            search.Index.search, exception, 1)

        search_counter = test_utils.CallCounter(gae_search_services.search)

        search_ctx = self.swap(search.Index, 'search', failing_index_search)
        search_counter_ctx = self.swap(gae_search_services, 'search',
                                       search_counter)
        assert_raises_ctx = self.assertRaisesRegexp(
            gae_search_services.SearchFailureError,
            '<class \'google.appengine.api.search.search.TransientError\'>: '
            'oops')
        with search_ctx, search_counter_ctx, assert_raises_ctx as context_mgr:
            gae_search_services.search('query', 'my_index')

        self.assertEqual(context_mgr.exception.original_exception, exception)

        self.assertEqual(search_counter.times_called, 1)
Exemplo n.º 18
0
    def test_use_default_num_retries(self):
        exception = search.TransientError('oops')
        failing_index_search = test_utils.FailingFunction(
            search.Index.search, exception,
            gae_search_services.DEFAULT_NUM_RETRIES)

        search_counter = test_utils.CallCounter(gae_search_services.search)

        search_ctx = self.swap(search.Index, 'search', failing_index_search)
        search_counter_ctx = self.swap(gae_search_services, 'search',
                                       search_counter)
        assert_raises_ctx = self.assertRaises(
            gae_search_services.SearchFailureError)
        with search_ctx, search_counter_ctx, assert_raises_ctx as context_mgr:
            gae_search_services.search('query', 'my_index')

        self.assertEqual(context_mgr.exception.original_exception, exception)

        self.assertEqual(search_counter.times_called,
                         gae_search_services.DEFAULT_NUM_RETRIES)
Exemplo n.º 19
0
    def test_use_custom_number_of_retries(self):
        exception = self._get_delete_error(1, transient=0)
        failing_delete = test_utils.FailingFunction(
            search.Index.delete, exception, 42)

        delete_docs_counter = test_utils.CallCounter(
            gae_search_services.delete_documents_from_index)

        delete_ctx = self.swap(search.Index, 'delete', failing_delete)
        delete_docs_ctx = self.swap(
            gae_search_services,
            'delete_documents_from_index',
            delete_docs_counter)
        assert_raises_ctx = self.assertRaisesRegexp(
            gae_search_services.SearchFailureError,
            '<class \'google.appengine.api.search.search.DeleteError\'>: lol')
        with delete_ctx, delete_docs_ctx, assert_raises_ctx:
            gae_search_services.delete_documents_from_index(
                ['id'], 'index', retries=42)

        self.assertEqual(delete_docs_counter.times_called, 42)
Exemplo n.º 20
0
    def test_fetch_gravatar_failure_exception(self):
        user_email = '*****@*****.**'
        error_messages = []
        def log_mock(message):
            error_messages.append(message)

        gravatar_url = user_services.get_gravatar_url(user_email)
        expected_error_message = (
            'Failed to fetch Gravatar from %s' % gravatar_url)
        logging_error_mock = test_utils.CallCounter(log_mock)
        urlfetch_fail_mock = test_utils.FailingFunction(
            urlfetch.fetch, urlfetch.InvalidURLError,
            test_utils.FailingFunction.INFINITY)
        log_swap_ctx = self.swap(logging, 'error', logging_error_mock)
        fetch_swap_ctx = self.swap(urlfetch, 'fetch', urlfetch_fail_mock)
        with log_swap_ctx, fetch_swap_ctx:
            profile_picture = user_services.fetch_gravatar(user_email)
            self.assertEqual(logging_error_mock.times_called, 1)
            self.assertEqual(expected_error_message, error_messages[0])
            self.assertEqual(
                profile_picture, user_services.DEFAULT_IDENTICON_DATA_URL)
Exemplo n.º 21
0
    def test_use_default_num_retries(self):
        exception = self._get_delete_error(1, transient=0)
        failing_delete = test_utils.FailingFunction(search.Index.delete,
                                                    exception, 1)

        delete_docs_counter = test_utils.CallCounter(
            gae_search_services.delete_documents_from_index)

        delete_ctx = self.swap(search.Index, 'delete', failing_delete)
        delete_docs_ctx = self.swap(gae_search_services,
                                    'delete_documents_from_index',
                                    delete_docs_counter)
        assert_raises_ctx = self.assertRaisesRegexp(
            gae_search_services.SearchFailureError,
            '<class \'google.appengine.api.search.search.DeleteError\'>: lol')
        with delete_ctx, delete_docs_ctx, assert_raises_ctx as context_mgr:
            gae_search_services.delete_documents_from_index(['doc'],
                                                            'my_index')

        self.assertEqual(context_mgr.exception.original_exception, exception)

        self.assertEqual(delete_docs_counter.times_called, 1)