Example #1
0
    def test_to_dict_with_callbacks(self):
        """Ensure to_dict correctly encodes callbacks."""
        import copy

        from furious.async import Async
        from furious.context import Context

        options = {
            'persistence_engine': 'persistence_engine',
            'callbacks': {
                'success': self.__class__.test_to_dict_with_callbacks,
                'failure': "failure_function",
                'exec': Async(target=dir)
            }
        }

        context = Context(**copy.deepcopy(options))

        # This stuff gets dumped out by to_dict().
        options.update({
            'insert_tasks': 'furious.context.context._insert_tasks',
            'persistence_engine': 'persistence_engine',
            '_tasks_inserted': False,
            '_task_ids': [],
            'callbacks': {
                'success': ("furious.tests.context.test_context."
                            "TestContext.test_to_dict_with_callbacks"),
                'failure': "failure_function",
                'exec': {'job': ('dir', None, None),
                         '_recursion': {'current': 0, 'max': 100},
                         '_type': 'furious.async.Async'}
            }
        })

        self.assertEqual(options, context.to_dict())
    def test_to_dict_with_callbacks(self):
        """Ensure to_dict correctly encodes callbacks."""
        import copy

        from furious. async import Async
        from furious.context import Context

        options = {
            'id': 'someid',
            'context_id': 'contextid',
            'parent_id': 'parentid',
            'persistence_engine': 'persistence_engine',
            'callbacks': {
                'success':
                self.__class__.test_to_dict_with_callbacks,
                'failure':
                "failure_function",
                'exec':
                Async(target=dir,
                      id='blargh',
                      context_id='contextid',
                      parent_id='parentid')
            }
        }

        context = Context(**copy.deepcopy(options))

        # This stuff gets dumped out by to_dict().
        options.update({
            'id': 'someid',
            'insert_tasks': 'furious.context.context._insert_tasks',
            'persistence_engine': 'persistence_engine',
            '_tasks_inserted': False,
            '_task_ids': [],
            'callbacks': {
                'success': ("furious.tests.context.test_context."
                            "TestContext.test_to_dict_with_callbacks"),
                'failure':
                "failure_function",
                'exec': {
                    'job': ('dir', None, None),
                    'id': 'blargh',
                    'context_id': 'contextid',
                    'parent_id': 'parentid',
                    '_recursion': {
                        'current': 0,
                        'max': 100
                    },
                    '_type': 'furious.async.Async'
                }
            }
        })

        self.assertEqual(options, context.to_dict())
Example #3
0
    def test_load_context(self):
        """Calling load with an engine attempts to load the Context."""
        from furious.context import Context

        persistence_engine = Mock()
        persistence_engine.func_name = "persistence_engine"
        persistence_engine.im_class.__name__ = "engine"
        persistence_engine.load_context.return_value = Context.from_dict({"id": "ABC123"})

        context = Context.load("ABC123", persistence_engine)

        persistence_engine.load_context.assert_called_once_with("ABC123")
        self.assertEqual("ABC123", context.id)
Example #4
0
    def test_nested_context_works(self, queue_add_mock):
        """Ensure adding a job works."""
        from furious. async import Async
        from furious.context import Context

        with Context() as ctx:
            job = ctx.add('test', args=[1, 2])
            with Context() as ctx2:
                job2 = ctx2.add('test', args=[1, 2])

        self.assertIsInstance(job, Async)
        self.assertIsInstance(job2, Async)
        self.assertEqual(2, queue_add_mock.call_count)
 def test_store_context(self):
     from furious.extras.appengine.ndb_persistence import store_context
     from furious.extras.appengine.ndb_persistence import load_context
     from furious.extras.appengine.ndb_persistence import ContextPersist
     from furious.context import Context
     ctx = Context()
     ctx.add('test', args=[1, 2])
     ctx_dict = ctx.to_dict()
     store_context(ctx.id, ctx_dict)
     ctx_persisted = ContextPersist.get_by_id(ctx.id)
     self.assertIsNotNone(ctx_persisted)
     reloaded_ctx = load_context(ctx.id)
     self.assertEqual(reloaded_ctx, ctx_dict)
Example #6
0
    def test_persist_persists(self):
        """Calling persist with an engine persists the Context."""
        from furious.context import Context

        persistence_engine = Mock()
        persistence_engine.func_name = 'persistence_engine'
        persistence_engine.im_class.__name__ = 'engine'

        context = Context(persistence_engine=persistence_engine)

        context.persist()

        persistence_engine.store_context.assert_called_once_with(context)
    def test_persist_persists(self):
        """Calling persist with an engine persists the Context."""
        from furious.context import Context

        persistence_engine = Mock()
        persistence_engine.func_name = 'persistence_engine'
        persistence_engine.im_class.__name__ = 'engine'

        context = Context(persistence_engine=persistence_engine)

        context.persist()

        persistence_engine.store_context.assert_called_once_with(context)
    def test_load_context(self):
        """Calling load with an engine attempts to load the Context."""
        from furious.context import Context

        persistence_engine = Mock()
        persistence_engine.func_name = 'persistence_engine'
        persistence_engine.im_class.__name__ = 'engine'
        persistence_engine.load_context.return_value = Context.from_dict(
            {'id': 'ABC123'})

        context = Context.load('ABC123', persistence_engine)

        persistence_engine.load_context.assert_called_once_with('ABC123')
        self.assertEqual('ABC123', context.id)
Example #9
0
    def test_load_context(self):
        """Calling load with an engine attempts to load the Context."""
        from furious.context import Context

        persistence_engine = Mock()
        persistence_engine.func_name = 'persistence_engine'
        persistence_engine.im_class.__name__ = 'engine'
        persistence_engine.load_context.return_value = Context.from_dict(
            {'id': 'ABC123'})

        context = Context.load('ABC123', persistence_engine)

        persistence_engine.load_context.assert_called_once_with('ABC123')
        self.assertEqual('ABC123', context.id)
    def test_save_context(self):
        """Ensure the passed in context gets serialized and set on the saved
        FuriousContext entity.
        """
        _id = "contextid"

        context = Context(id=_id)

        result = store_context(context)

        self.assertEqual(result.id(), _id)

        loaded_context = FuriousContext.from_id(result.id())

        self.assertEqual(context.to_dict(), loaded_context.to_dict())
    def test_save_context(self):
        """Ensure the passed in context gets serialized and set on the saved
        FuriousContext entity.
        """
        _id = "contextid"

        context = Context(id=_id)

        result = store_context(context)

        self.assertEqual(result.id(), _id)

        loaded_context = FuriousContext.from_id(result.id())

        self.assertEqual(context.to_dict(), loaded_context.to_dict())
    def test_has_errors_with_marker_cached(self):
        """Ensure returns the value from the marker when cached."""
        context_id = 1

        marker = FuriousCompletionMarker(id=context_id, has_errors=True)
        marker.put()

        context = Context(id=context_id)
        context._marker = marker
        context_result = ContextResult(context)

        self.assertIsNone(context_result._marker)
        self.assertTrue(context_result.has_errors())

        marker.key.delete()
    def test_has_errors_with_marker_cached(self):
        """Ensure returns the value from the marker when cached."""
        context_id = 1

        marker = FuriousCompletionMarker(id=context_id, has_errors=True)
        marker.put()

        context = Context(id=context_id)
        context._marker = marker
        context_result = ContextResult(context)

        self.assertIsNone(context_result._marker)
        self.assertTrue(context_result.has_errors())

        marker.key.delete()
    def test_marker_not_complete_when_start_fails(self, mock_insert,
                                                  context_from_id,
                                                  check_markers):
        """Ensure if the completion handler fails to start, that the marker
        does not get marked as complete.
        """

        complete_event = Mock()
        context = Context(id="contextid",
                          callbacks={'complete': complete_event})

        context_from_id.return_value = context

        check_markers.return_value = True, False

        async = Async('foo')
        async .update_options(context_id='contextid')
        FuriousCompletionMarker(id=async .context_id, complete=False).put()

        # Simulate the task failing to start
        mock_insert.side_effect = DeadlineExceededError()

        self.assertRaises(DeadlineExceededError, _completion_checker,
                          async .id, async .context_id)

        # Marker should not have been marked complete.
        current_marker = FuriousCompletionMarker.get_by_id(async .context_id)
        self.assertFalse(current_marker.complete)
Example #15
0
    def test_from_dict(self):
        """Ensure from_dict returns the correct Context object."""
        from furious.context import Context

        from furious.context.context import _insert_tasks

        # TODO: persistence_engine needs set to a real persistence module.

        options = {
            "id": 123456,
            "insert_tasks": "furious.context.context._insert_tasks",
            "random_option": "avalue",
            "_tasks_inserted": True,
            "_task_ids": [1, 2, 3, 4],
            "persistence_engine": "furious.context.context.Context",
        }

        context = Context.from_dict(options)

        self.assertEqual(123456, context.id)
        self.assertEqual([1, 2, 3, 4], context.task_ids)
        self.assertEqual(True, context._tasks_inserted)
        self.assertEqual("avalue", context._options.get("random_option"))
        self.assertEqual(_insert_tasks, context._insert_tasks)
        self.assertEqual(Context, context._persistence_engine)
Example #16
0
    def test_from_dict_with_callbacks(self):
        """Ensure from_dict reconstructs the Context callbacks correctly."""
        from furious.context import Context

        callbacks = {
            "success": ("furious.tests.context.test_context." "TestContext.test_to_dict_with_callbacks"),
            "failure": "dir",
            "exec": {"job": ("id", None, None), "id": "myid", "context_id": "contextid", "parent_id": "parentid"},
        }

        context = Context.from_dict({"callbacks": callbacks})

        check_callbacks = {"success": TestContext.test_to_dict_with_callbacks, "failure": dir}

        callbacks = context._options.get("callbacks")
        exec_callback = callbacks.pop("exec")

        correct_dict = {
            "job": ("id", None, None),
            "parent_id": "parentid",
            "id": "myid",
            "context_id": "contextid",
            "_recursion": {"current": 0, "max": 100},
            "_type": "furious.async.Async",
        }

        self.assertEqual(check_callbacks, callbacks)
        self.assertEqual(correct_dict, exec_callback.to_dict())
Example #17
0
    def test_from_dict_with_callbacks(self):
        """Ensure from_dict reconstructs the Context callbacks correctly."""
        from furious.context import Context

        callbacks = {
            'success': ("furious.tests.context.test_context."
                        "TestContext.test_to_dict_with_callbacks"),
            'failure':
            "dir",
            'exec': {
                'job': ('id', None, None)
            }
        }

        context = Context.from_dict({'callbacks': callbacks})

        check_callbacks = {
            'success': TestContext.test_to_dict_with_callbacks,
            'failure': dir
        }

        callbacks = context._options.get('callbacks')
        exec_callback = callbacks.pop('exec')

        correct_dict = {
            'job': ('id', None, None),
            '_recursion': {
                'current': 0,
                'max': 100
            },
            '_type': 'furious.async.Async'
        }

        self.assertEqual(check_callbacks, callbacks)
        self.assertEqual(correct_dict, exec_callback.to_dict())
    def test_markers_and_context_complete(self, mark, context_from_id,
                                          check_markers):
        """Ensure if all markers are complete that True is returned and
        nothing else is done.
        """
        async = Async('foo')
        async .update_options(context_id='contextid')

        complete_event = Mock()
        context = Context(id="contextid",
                          callbacks={'complete': complete_event})

        context_from_id.return_value = context

        marker = FuriousCompletionMarker(id="contextid", complete=True)
        marker.put()

        check_markers.return_value = True, False
        mark.return_value = True

        result = _completion_checker(async .id, async .context_id)

        self.assertTrue(result)

        self.assertFalse(complete_event.start.called)

        marker.key.delete()
Example #19
0
    def test_add_jobs_to_multiple_queues(self):
        """Ensure adding jobs to multiple queues works as expected."""
        from google.appengine.api.taskqueue import Queue
        from furious.context import Context

        queue_registry = {}

        class AwesomeQueue(Queue):
            def __init__(self, *args, **kwargs):
                super(AwesomeQueue, self).__init__(*args, **kwargs)

                queue_registry[kwargs.get('name')] = self
                self._calls = []

            def add(self, *args, **kwargs):
                self._calls.append((args, kwargs))

        with patch('google.appengine.api.taskqueue.Queue', AwesomeQueue):
            with Context() as ctx:
                ctx.add('test', args=[1, 2], queue='A')
                ctx.add('test', args=[1, 2], queue='A')
                ctx.add('test', args=[1, 2], queue='B')
                ctx.add('test', args=[1, 2], queue='C')

        self.assertEqual(2, len(queue_registry['A']._calls[0][0][0]))
        self.assertEqual(1, len(queue_registry['B']._calls[0][0][0]))
        self.assertEqual(1, len(queue_registry['C']._calls[0][0][0]))
Example #20
0
    def test_from_dict(self):
        """Ensure from_dict returns the correct Context object."""
        from furious.context import Context

        from furious.context.context import _insert_tasks

        # TODO: persistence_engine needs set to a real persistence module.

        options = {
            'id': 123456,
            'insert_tasks': 'furious.context.context._insert_tasks',
            'random_option': 'avalue',
            '_tasks_inserted': True,
            '_task_ids': [1, 2, 3, 4],
            'persistence_engine': 'furious.context.context.Context'
        }

        context = Context.from_dict(options)

        self.assertEqual(123456, context.id)
        self.assertEqual([1, 2, 3, 4], context._task_ids)
        self.assertEqual(True, context._tasks_inserted)
        self.assertEqual('avalue', context._options.get('random_option'))
        self.assertEqual(_insert_tasks, context._insert_tasks)
        self.assertEqual(Context, context._persistence_engine)
    def test_results_with_no_tasks_loaded(self, get_multi_async):
        """Ensure results loads the tasks and yields them out when no tasks are
        cached.
        """
        marker1 = _build_marker(payload="1", status=1)
        marker2 = _build_marker(payload="2", status=1)
        marker3 = _build_marker(payload="3", status=1)

        future_set_1 = [
            _build_future(marker1),
            _build_future(marker2),
            _build_future(marker3)
        ]

        get_multi_async.return_value = future_set_1

        context = Context(_task_ids=["1", "2", "3"])
        context_result = ContextResult(context)

        results = list(context_result.items())

        results = sorted(results)

        self.assertEqual(results, [("1", "1"), ("2", "2"), ("3", "3")])

        self.assertEqual(context_result._task_cache, {
            "1": marker1,
            "2": marker2,
            "3": marker3
        })
Example #22
0
    def test_from_dict(self):
        """Ensure from_dict returns the correct Context object."""
        from furious.context import Context

        from furious.context.context import _insert_tasks

        # TODO: persistence_engine needs set to a real persistence module.

        options = {
            'id': 123456,
            'insert_tasks': 'furious.context.context._insert_tasks',
            'random_option': 'avalue',
            '_tasks_inserted': True,
            '_task_ids': [1, 2, 3, 4],
            'persistence_engine': 'furious.context.context.Context'
        }

        context = Context.from_dict(options)

        self.assertEqual(123456, context.id)
        self.assertEqual([1, 2, 3, 4], context.task_ids)
        self.assertEqual(True, context._tasks_inserted)
        self.assertEqual('avalue', context._options.get('random_option'))
        self.assertEqual(_insert_tasks, context._insert_tasks)
        self.assertEqual(Context, context._persistence_engine)
Example #23
0
    def test_from_dict_with_callbacks(self):
        """Ensure from_dict reconstructs the Context callbacks correctly."""
        from furious.context import Context

        callbacks = {
            'success': ("furious.tests.context.test_context."
                        "TestContext.test_to_dict_with_callbacks"),
            'failure': "dir",
            'exec': {'job': ('id', None, None), 'id': 'myid',
                     'context_id': 'contextid',
                     'parent_id': 'parentid'}
        }

        context = Context.from_dict({'callbacks': callbacks})

        check_callbacks = {
            'success': TestContext.test_to_dict_with_callbacks,
            'failure': dir
        }

        callbacks = context._options.get('callbacks')
        exec_callback = callbacks.pop('exec')

        correct_dict = {'job': ('id', None, None),
                        'parent_id': 'parentid',
                        'id': 'myid',
                        'context_id': 'contextid',
                        '_recursion': {'current': 0, 'max': 100},
                        '_type': 'furious.async.Async'}

        self.assertEqual(check_callbacks, callbacks)
        self.assertEqual(correct_dict, exec_callback.to_dict())
Example #24
0
    def test_to_dict(self):
        """Ensure to_dict returns a dictionary representation of the Context.
        """
        import copy

        from furious.context import Context

        options = {"persistence_engine": "persistence_engine", "unkown": True}

        context = Context(**copy.deepcopy(options))

        # This stuff gets dumped out by to_dict().
        options.update(
            {"insert_tasks": "furious.context.context._insert_tasks", "_tasks_inserted": False, "_task_ids": []}
        )

        self.assertEqual(options, context.to_dict())
Example #25
0
    def test_to_dict_with_callbacks(self):
        """Ensure to_dict correctly encodes callbacks."""
        import copy

        from furious.async import Async
        from furious.context import Context

        options = {
            "id": "someid",
            "context_id": "contextid",
            "parent_id": "parentid",
            "persistence_engine": "persistence_engine",
            "callbacks": {
                "success": self.__class__.test_to_dict_with_callbacks,
                "failure": "failure_function",
                "exec": Async(target=dir, id="blargh", context_id="contextid", parent_id="parentid"),
            },
        }

        context = Context(**copy.deepcopy(options))

        # This stuff gets dumped out by to_dict().
        options.update(
            {
                "id": "someid",
                "insert_tasks": "furious.context.context._insert_tasks",
                "persistence_engine": "persistence_engine",
                "_tasks_inserted": False,
                "_task_ids": [],
                "callbacks": {
                    "success": ("furious.tests.context.test_context." "TestContext.test_to_dict_with_callbacks"),
                    "failure": "failure_function",
                    "exec": {
                        "job": ("dir", None, None),
                        "id": "blargh",
                        "context_id": "contextid",
                        "parent_id": "parentid",
                        "_recursion": {"current": 0, "max": 100},
                        "_type": "furious.async.Async",
                    },
                },
            }
        )

        self.assertEqual(options, context.to_dict())
Example #26
0
    def test_added_to_correct_queue(self, queue_mock):
        """Ensure jobs are added to the correct queue."""
        from furious.context import Context

        with Context() as ctx:
            ctx.add('test', args=[1, 2], queue='A')
            ctx.add('test', args=[1, 2], queue='A')

        queue_mock.assert_called_once_with(name='A')
    def test_has_no_marker(self):
        """Ensure returns False when no marker found."""
        context_id = 1

        context = Context(id=context_id)
        context_result = ContextResult(context)

        self.assertIsNone(context_result._marker)
        self.assertFalse(context_result.has_errors())
    def test_no_task_ids(self, get_multi_async):
        """Ensure no results are yielded out when there are no task ids on the
        passed in context.
        """
        get_multi_async.return_value = []
        context = Context(_task_ids=[])

        results = list(iter_context_results(context))

        self.assertEqual(results, [])
Example #29
0
    def test_add_job_to_context_works(self, queue_add_mock):
        """Ensure adding a job works."""
        from furious. async import Async
        from furious.context import Context

        with Context() as ctx:
            job = ctx.add('test', args=[1, 2])

        self.assertIsInstance(job, Async)
        queue_add_mock.assert_called_once()
Example #30
0
    def test_add_multiple_jobs_to_context_works(self, queue_add_mock):
        """Ensure adding multiple jobs works."""
        from furious.context import Context

        with Context() as ctx:
            for _ in range(10):
                ctx.add('test', args=[1, 2])

        queue_add_mock.assert_called_once()
        self.assertEqual(10, len(queue_add_mock.call_args[0][0]))
    def test_context_gets_one_id(self):
        """Ensure a new Context gets an id only generated once."""
        from furious.context import Context

        context = Context()

        id1 = context.id
        id2 = context.id
        self.assertEqual(id1, id2)
        self.assertEqual(context.id, id1)
    def test_add_job_to_context_works(self, queue_add_mock):
        """Ensure adding a job works."""
        from furious. async import Async
        from furious.context import Context

        with Context() as ctx:
            job = ctx.add('test', args=[1, 2])

        self.assertIsInstance(job, Async)
        self.assertEqual(1, ctx.insert_success)
        self.assertEqual(1, queue_add_mock.call_count)
    def test_id_added_to_options(self, uuid_patch):
        """Ensure random context id gets added to options."""
        from furious.context import Context

        id = 'random-id'
        uuid_patch.return_value.hex = id

        context = Context()

        self.assertEqual(context.id, id)
        self.assertEqual(context._options['id'], id)
Example #34
0
    def from_id(cls, id):
        """Load a `cls` entity and instantiate the Context it stores."""
        from furious.context import Context

        # TODO: Handle exceptions and retries here.
        entity = cls.get_by_id(id)
        if not entity:
            raise FuriousContextNotFoundError(
                "Context entity not found for: {}".format(id))

        return Context.from_dict(entity.context)
Example #35
0
    def from_id(cls, id):
        """Load a `cls` entity and instantiate the Context it stores."""
        from furious.context import Context

        # TODO: Handle exceptions and retries here.
        entity = cls.get_by_id(id)
        if not entity:
            raise FuriousContextNotFoundError(
                "Context entity not found for: {}".format(id))

        return Context.from_dict(entity.context)
Example #36
0
    def test_to_dict(self):
        """Ensure to_dict returns a dictionary representation of the Context.
        """
        import copy

        from furious.context import Context

        options = {
            'persistence_engine': 'persistence_engine',
            'unkown': True,
        }

        context = Context(**copy.deepcopy(options))

        # This stuff gets dumped out by to_dict().
        options.update({
            'insert_tasks': 'furious.context.context._insert_tasks',
            '_tasks_inserted': False,
            '_task_ids': [],
        })

        self.assertEqual(options, context.to_dict())
    def test_added_asyncs_get_context_id(self, queue_mock):
        """Ensure Asyncs added to context get context id."""
        from furious. async import Async
        from furious.context import Context

        asyncs = [Async('test', id=i) for i in xrange(100, 110)]

        with Context() as ctx:
            for async in asyncs:
                ctx.add(async)
                self.assertEqual(ctx.id, async .get_options()['_context_id'])

        self.assertEqual(10, ctx.insert_success)
Example #38
0
    def test_to_dict(self):
        """Ensure to_dict returns a dictionary representation of the Context.
        """
        import copy

        from furious.context import Context

        options = {
            'persistence_engine': 'persistence_engine',
            'unkown': True,
        }

        context = Context(**copy.deepcopy(options))

        # This stuff gets dumped out by to_dict().
        options.update({
            'insert_tasks': 'furious.context.context._insert_tasks',
            '_tasks_inserted': False,
            '_task_ids': [],
        })

        self.assertEqual(options, context.to_dict())
    def test_keys_with_no_results(self, get_multi_async):
        """Ensure empty results are yielded out when there are no items to
        load but task ids are on the passed in context.
        """
        future_set_1 = [_build_future(), _build_future(), _build_future()]

        get_multi_async.return_value = future_set_1

        context = Context(_task_ids=["1", "2", "3"])

        results = list(iter_context_results(context))

        self.assertEqual(results[0], ("1", None))
        self.assertEqual(results[1], ("2", None))
        self.assertEqual(results[2], ("3", None))
Example #40
0
    def test_reconstitution(self):
        """Ensure to_dict(job.from_dict()) returns the same thing."""
        from furious.context import Context

        options = {
            "id": 123098,
            "insert_tasks": "furious.context.context._insert_tasks",
            "persistence_engine": "furious.job_utils.get_function_path_and_options",
            "_tasks_inserted": True,
            "_task_ids": [],
        }

        context = Context.from_dict(options)

        self.assertEqual(options, context.to_dict())
Example #41
0
    def test_reconstitution(self):
        """Ensure to_dict(job.from_dict()) returns the same thing."""
        from furious.context import Context

        options = {
            'id': 123098,
            'insert_tasks': 'furious.context.context._insert_tasks',
            'persistence_engine':
            'furious.job_utils.get_function_path_and_options',
            '_tasks_inserted': True,
            '_task_ids': []
        }

        context = Context.from_dict(options)

        self.assertEqual(options, context.to_dict())
Example #42
0
    def test_reconstitution(self):
        """Ensure to_dict(job.from_dict()) returns the same thing."""
        from furious.context import Context

        options = {
            'id': 123098,
            'insert_tasks': 'furious.context.context._insert_tasks',
            'persistence_engine':
            'furious.job_utils.get_function_path_and_options',
            '_tasks_inserted': True,
            '_task_ids': []
        }

        context = Context.from_dict(options)

        self.assertEqual(options, context.to_dict())
    def test_results_with_tasks_loaded_missing_result(self, get_multi_async):
        """Ensure results uses the cached tasks and yields them out when tasks
        are cached and there's no results.
        """
        marker1 = FuriousAsyncMarker()

        context = Context(_task_ids=["1", "2", "3"])
        context_result = ContextResult(context)

        context_result._task_cache = {"1": marker1, "2": None, "3": None}

        results = list(context_result.items())

        results = sorted(results)

        self.assertEqual(results, [("1", None), ("2", None), ("3", None)])

        self.assertFalse(get_multi_async.called)
    def test_add_task_fails(self, queue_add_mock):
        """Ensure insert_failed and insert_success are calculated correctly."""
        from google.appengine.api.taskqueue import TaskAlreadyExistsError
        from furious.context import Context

        def queue_add(tasks, transactional=False):
            if len(tasks) != 2:
                raise TaskAlreadyExistsError()

        queue_add_mock.side_effect = queue_add

        with Context() as ctx:
            ctx.add('test', args=[1, 2], queue='A')
            ctx.add('test', args=[1, 2], queue='B')
            ctx.add('test', args=[1, 2], queue='B')

        self.assertEqual(2, ctx.insert_success)
        self.assertEqual(1, ctx.insert_failed)
    def test_more_results_than_batch_size(self, get_multi_async):
        """Ensure all the results are yielded out when more than the batch
        size.
        """
        marker1 = _build_marker(payload="1", status=1)
        marker2 = _build_marker(payload="2", status=1)
        marker3 = _build_marker(payload="3", status=1)

        future_set_1 = [_build_future(marker1), _build_future(marker2)]
        future_set_2 = [_build_future(marker3)]

        get_multi_async.side_effect = future_set_1, future_set_2

        context = Context(_task_ids=["1", "2", "3"])

        results = list(iter_context_results(context, batch_size=2))

        self.assertEqual(results[0], ("1", marker1))
        self.assertEqual(results[1], ("2", marker2))
        self.assertEqual(results[2], ("3", marker3))
    def test_results_with_tasks_loaded(self, get_multi_async):
        """Ensure results uses the cached tasks and yields them out when tasks
        are cached.
        """
        marker1 = _build_marker(payload="1", status=1)
        marker2 = _build_marker(payload="2", status=1)
        marker3 = _build_marker(payload="3", status=1)

        context = Context(_task_ids=["1", "2", "3"])
        context_result = ContextResult(context)

        context_result._task_cache = {"1": marker1, "2": marker2, "3": marker3}

        results = list(context_result.items())

        results = sorted(results)

        self.assertEqual(results, [("1", "1"), ("2", "2"), ("3", "3")])

        self.assertFalse(get_multi_async.called)
    def test_markers_complete(self, context_from_id, check_markers):
        """Ensure if all markers are complete that True is returned and the
        completion handler and cleanup tasks are triggered.
        """
        complete_event = Mock()
        context = Context(id="contextid",
                          callbacks={'complete': complete_event})

        context_from_id.return_value = context

        check_markers.return_value = True, False

        async = Async('foo')
        async .update_options(context_id='contextid')
        FuriousCompletionMarker(id=async .context_id, complete=False).put()

        result = _completion_checker(async .id, async .context_id)

        self.assertTrue(result)

        complete_event.start.assert_called_once_with(transactional=True)