def test_cancel_all_ack(abc_sync_tasks):
    """Ensure that after a cancel task has been added, the other task behave as expected."""
    queue = TaskQueue()
    abc_dummy_link = abc_sync_tasks[0].link

    # Where all task will report to
    ack_sink = []

    # list of task currently being worked on by workers.
    tasks_in_workers = []

    # setup mocked calls and put them on the queue.
    for task in abc_sync_tasks:
        task.cancel = mock.MagicMock()
        task.set_ack_callback(ack_sink.append)
        queue.put_task(task)

    # check the first task
    task = queue.get_task()
    tasks_in_workers.append(task)
    assert task.state == cc.synctask.SyncTask.UNEXECUTED
    assert task in queue.running

    # pass in the cancel
    cancel_task = cc.synctask.CancelSyncTask(path=['a', 'b', 'c'])
    cancel_task.link = abc_dummy_link
    cancel_task.set_ack_callback(ack_sink.append)

    queue.put_task(cancel_task)

    # now all sync tasks should be set to cancel
    for task in abc_sync_tasks:
        assert task.cancel.called

    # get the rest of the tasks as well, so we can ack them all
    for _ in range(len(abc_sync_tasks) - 1):
        tasks_in_workers.append(queue.get_task())

    # check the queues are correct.
    assert queue.pending.qsize() == 0
    assert len(queue.running) == len(abc_sync_tasks)
    assert set(tasks_in_workers) == set(abc_sync_tasks)

    # Once workers are finished they ack
    for task in tasks_in_workers:
        queue.ack_task(task)

    # now all tasks + cancel tasks should be in the ack sync
    expected = set(abc_sync_tasks)
    expected.add(cancel_task)
    assert set(expected) == set(ack_sink)
    assert len(expected) == len(set(ack_sink))

    # And the cancel should be successful
    assert cancel_task.state == cc.synctask.SyncTask.SUCCESSFUL
def test_path_has_tasks_empty():
    """Ensures that path_has_tasks returns 'True' iff a given path_hash has associated tasks in
    either the running or pending queue."""

    queue = TaskQueue()
    path = []
    link_id = "local::remote"
    path_hash = cc.synctask.path_hash(link_id, path)

    assert queue.path_has_tasks(path_hash=path_hash, is_dir=True) is False
    assert queue.path_has_tasks(path_hash=path_hash, is_dir=False) is False
def test_get_put_task(abc_sync_tasks):
    """Check get_task from TaskQueue."""
    ack_task = []
    queue = TaskQueue()

    # test preperations for signals
    put_callback_mock = mock.Mock()
    acked_callback_mock = mock.Mock()
    queue.task_putted.connect(put_callback_mock, weak=False)
    queue.task_acked.connect(acked_callback_mock, weak=False)

    # put all tasks in the queue
    for task in abc_sync_tasks:
        task.set_ack_callback(ack_task.append)
        queue.put_task(task)

        # check if signal was sent
        put_callback_mock.assert_any_call(task)

    # once worker asks for task, it is in the running list
    task = queue.get_task()
    assert task.state == cc.synctask.SyncTask.UNEXECUTED
    assert task in queue.running

    # after the worker has ack'ed the task, it is no longer in the running list
    queue.ack_task(task)
    assert task not in queue.running

    # check if signal was sent
    acked_callback_mock.assert_called_with(task)
def test_cancel_ack_running_task():
    """Check that the cancel task is not acked if there are still running tasks """
    ack_tasks = []

    sync_tasks = [
        cc.synctask.DownloadSyncTask(path=['a', 'b', 'c'],
                                     source_storage_id=None,
                                     source_version_id=None),
        cc.synctask.UploadSyncTask(path=['a', 'b', 'c'],
                                   target_storage_id=None,
                                   source_version_id=None)
    ]

    queue = TaskQueue()
    for task in sync_tasks:
        task.link = dummy_link_with_id("local::remote")
        task.set_ack_callback(ack_tasks.append)
        queue.put_task(task)

    task = queue.get_task()
    assert task.state == cc.synctask.SyncTask.UNEXECUTED

    assert task in queue.running
    task.cancel = mock.MagicMock()

    task2 = queue.get_task()
    task2.cancel = mock.MagicMock()

    # cancel the running synctask
    cancel_task = cc.synctask.CancelSyncTask(task.path)
    cancel_task.link = dummy_link_with_id("local::remote")
    cancel_task.set_ack_callback(ack_tasks.append)
    queue.put_task(cancel_task)

    assert task.cancel.called
    assert task2.cancel.called

    queue.ack_task(task)
    assert task not in queue.running

    assert task in ack_tasks

    # this is the bug
    assert cancel_task not in ack_tasks
def test_put_cancel(abc_sync_tasks, sample_create_dir_task):
    """When CancelSyncTask is issued, all tasks should be canceled."""
    ack_tasks = []
    queue = TaskQueue()
    abc_dummy_link = abc_sync_tasks[0].link

    # catch the calls to cancel
    sample_create_dir_task.cancel = mock.Mock()

    # set one running task
    queue.running.add(sample_create_dir_task)

    # put all other tasks on the queue and mock cancel.
    for task in abc_sync_tasks:
        task.set_ack_callback(ack_tasks.append)
        task.cancel = mock.MagicMock()
        queue.put_task(task)

    # cancel all tasks for the path a/b/c
    cancel_task = cc.synctask.CancelSyncTask(path=['a', 'b', 'c'])
    cancel_task.set_ack_callback(ack_tasks.append)
    cancel_task.link = abc_dummy_link
    queue.put_task(cancel_task)

    # has cancel arrived?
    assert cancel_task in queue.cancel.values()

    # has cancel been called
    for task in abc_sync_tasks:
        assert task.cancel.called

    assert sample_create_dir_task.cancel.called
def test_path_has_tasks_with_one_pending_task(sample_create_dir_task):
    """Ensures that path_has_tasks returns 'True' iff a given path_hash has associated tasks in
    either the running or pending queue."""

    queue = TaskQueue()
    queue.put_task(sample_create_dir_task)
    assert queue.path_has_tasks(path_hash=sample_create_dir_task.operates_on(),
                                is_dir=True)
    assert queue.path_has_tasks(path_hash=sample_create_dir_task.operates_on(),
                                is_dir=False)

    path_hash = cc.synctask.path_hash("local::remote2",
                                      sample_create_dir_task.path)
    assert queue.path_has_tasks(path_hash=path_hash, is_dir=True) is False
    assert queue.path_has_tasks(path_hash=path_hash, is_dir=False) is False
def test_queue_cancel_performance():
    """Performance Tests regarding the cancel all problems"""
    ack_tasks = []

    queue = TaskQueue()
    count = 1000
    start = time.time()
    for ind in range(count):
        name = '{}'.format(ind)
        task = cc.synctask.DownloadSyncTask(path=[name] * 10,
                                            source_storage_id=None,
                                            source_version_id=None)
        task.link = dummy_link_with_id("local::remote")
        task.set_ack_callback(ack_tasks.append)
        queue.put_task(task)
    print(time.time() - start)
    assert queue.statistics['sync_task_count'] == count
    assert len(ack_tasks) == 0

    start = time.time()
    for ind in range(count):
        name = '{}'.format(ind)
        cancel_task = cc.synctask.CancelSyncTask(path=[name] * 10)
        cancel_task.link = dummy_link_with_id("local::remote")
        cancel_task.set_ack_callback(ack_tasks.append)
        queue.put_task(cancel_task)
        assert len(queue.cancel) == ind + 1
    print(time.time() - start)

    assert queue.statistics['sync_task_count'] == count
    assert len(queue.cancel) == count
    assert len(ack_tasks) == 0

    start = time.time()
    while queue.statistics['sync_task_count'] > 0:
        task = queue.get_task()
        queue.ack_task(task)
    print(time.time() - start)

    assert queue.statistics['sync_task_count'] == 0
    assert len(queue.cancel) == 0
    assert len(ack_tasks) == 2 * count
def test_cancel_running_task():
    """Ensure that canceling all tasks works as expected"""
    ack_tasks = []

    sync_tasks = [
        cc.synctask.DownloadSyncTask(path=['a', 'b', 'c'],
                                     source_storage_id=None,
                                     source_version_id=None),
        cc.synctask.UploadSyncTask(path=['a', 'b', 'c'],
                                   target_storage_id=None,
                                   source_version_id=None)
    ]

    queue = TaskQueue()
    for task in sync_tasks:
        task.link = dummy_link_with_id("local::remote")
        task.set_ack_callback(ack_tasks.append)
        queue.put_task(task)

    task = queue.get_task()
    assert task.state == cc.synctask.SyncTask.UNEXECUTED

    assert task in queue.running
    task.cancel = mock.MagicMock()

    # cancel the running synctask
    cancel_task = cc.synctask.CancelSyncTask(task.path)
    cancel_task.link = dummy_link_with_id("local::remote")
    cancel_task.set_ack_callback(ack_tasks.append)
    queue.put_task(cancel_task)

    assert task.cancel.called

    queue.ack_task(task)
    assert task not in queue.running

    assert task in ack_tasks
    assert cancel_task not in ack_tasks

    # get the next task -> this has to be set to cancelled
    task2 = queue.get_task()
    if task2.cancelled:
        task2.state = cc.synctask.SyncTask.CANCELLED
    else:
        assert False
    queue.ack_task(task2)
    assert task2 not in queue.running

    # this ack also acknowledges the cancel task
    assert task in ack_tasks
    assert task2 in ack_tasks
    assert cancel_task in ack_tasks
Пример #9
0
def task_queue():
    """task_queue fixture"""
    return TaskQueue()
def test_step_path_has_tasks():
    """ checks if the has_tasks function is working """
    ack_tasks = []

    sync_tasks = [
        cc.synctask.DownloadSyncTask(path=['a', 'b', 'c'],
                                     source_storage_id=None,
                                     source_version_id=None),
        cc.synctask.UploadSyncTask(path=['a', 'b'],
                                   target_storage_id=None,
                                   source_version_id=None)
    ]

    task_queue = TaskQueue()
    for task in sync_tasks:
        task.link = dummy_link_with_id("local::remote")
        task.set_ack_callback(ack_tasks.append)
        task_queue.put_task(task)

    # this puts one task on the execution set
    task_queue.get_task()

    # elements in the queue
    assert task_queue.path_has_tasks(['a', 'b'], False)
    assert task_queue.path_has_tasks(['a', 'b'], True)

    # elements in the working set
    assert not task_queue.path_has_tasks(['a', 'x'], False)
    assert task_queue.path_has_tasks(['a', 'b', 'c'], False)
    assert task_queue.path_has_tasks(['a', 'b', 'c'], True)

    assert task_queue.path_has_tasks(['a'], True)
    assert not task_queue.path_has_tasks(['b'], True)