def test_validate_terminal_task_no_pdf():
    project = Project('proj')
    task1 = task_factory('task1', 1)
    task2 = task_factory('task2', 2)
    project.add_dependency(task1, task2)
    with pytest.raises(InvalidProject) as e:
        project.validate()
        assert len(e.errors) == 1
def test_validate_cyclic():
    project = Project('proj')
    task1 = task_factory('task1', 1)
    task2 = task_factory('task2', 2)
    project.add_dependencies([(task1, task2), (task2, task1)])
    with pytest.raises(InvalidProject) as e:
        project.validate()
        assert len(e.errors) == 2
def test_add_dependencies_some_invalid():
    project = Project('proj')
    task1 = task_factory('task1', 4)
    task2 = task_factory('task2', 4)
    task3 = task_factory('task3', 4)
    with pytest.raises(InvalidProject):
        project.add_dependencies([(task1, task2), (task3, task3)])
    assert list(project.predecessors(task2)) == [task1]
    assert task3 not in project.tasks
def test_add_dependencies_some_added():
    project = Project('proj')
    task1 = task_factory('task1', 1)
    task2 = task_factory('task2', 2)
    task3 = task_factory('task3', 3)
    task4 = task_factory('task4', 4)
    project.add_tasks([task1, task2])
    project.add_dependencies([(task1, task2), (task3, task4)])
    for task in [task1, task2, task3, task4]:
        assert task in project.tasks
    assert list(project.predecessors(task2)) == [task1]
    assert list(project.predecessors(task4)) == [task3]
def simple_project():
    '''
    1 ->
        |-> 3
    2 ->
    '''
    task1 = task_factory('1', 1)
    task2 = task_factory('2', 2)
    task3 = task_factory('3', 3)
    current_time = datetime(year=2018, month=5, day=14)
    task3.latest_finish_date_pdf = make_deterministic_date_pdf(current_time, 5)

    proj = Project('proj', MockModel())
    proj.add_dependencies([(task1, task3), (task2, task3)])
    return proj, {task.name: task for task in [task1, task2, task3]}
def test_add_dependency_already_added(project):
    project = project[0]
    task1 = Task('task1', data={'a': 3})
    task2 = task_factory('task2', 4)
    project.add_tasks([task1, task2])
    project.add_dependencies([(task1, task2)])
    assert list(project.predecessors(task2)) == [task1]
def test_add_tasks_some_mixed_no_duration(project):
    project = project[0]
    task1 = Task('task1', data={'a': 3})
    task2 = task_factory('task2', 4)
    project.add_tasks([task1, task2])
    assert task1.duration_pdf == DurationPdf(DeterministicPdf(3))
    assert task1 in project.tasks
    assert task2 in project.tasks
def test_add_tasks_some_no_duration_no_model():
    project = Project('proj')
    task1 = Task('task1')
    task2 = task_factory('task2', 4)
    with pytest.raises(InvalidProject):
        project.add_tasks([task2, task1])
    assert task1 not in project.tasks
    assert task2 in project.tasks
def test_task_sample_from_tasj():
    current_date = datetime(year=2019, month=4, day=13)
    task = task_factory('1', 1)
    task.earliest_start_date_pdf = make_deterministic_date_pdf(current_date, 5)
    task.latest_finish_date_pdf = make_deterministic_date_pdf(current_date, 7)
    sample = TaskSample.from_task(task, current_date)
    assert sample.duration == timedelta(days=1)
    assert sample.earliest_start == current_date + timedelta(days=5)
    assert sample.latest_finish == current_date + timedelta(days=7)
    assert sample.latest_start is None
    assert sample.earliest_finish is None
def project():
    '''
    1 ->           5
        |-> 3 -> |
    2 ->           6
         | 4
    '''
    task1 = task_factory('1', 1)
    task2 = task_factory('2', 2)
    task3 = task_factory('3', 3)
    task4 = task_factory('4', 2)
    task5 = task_factory('5', 1)
    task6 = task_factory('6', 2)
    current_time = datetime(year=2018, month=5, day=14)
    task4.latest_finish_date_pdf = make_deterministic_date_pdf(current_time, 5)
    task5.latest_finish_date_pdf = make_deterministic_date_pdf(current_time, 9)
    task6.latest_finish_date_pdf = make_deterministic_date_pdf(current_time, 7)

    class MockModel:
        def predict(self, data):
            return DurationPdf(DeterministicPdf(data['a']))

    proj = Project('proj', MockModel())
    proj.add_dependencies([(task1, task3), (task2, task3), (task2, task4),
                           (task3, task5), (task3, task6)])
    return proj, {
        task.name: task
        for task in [task1, task2, task3, task4, task5, task6]
    }
def test_project_from_dict_with_tasks_with_durations():
    task1 = task_factory('1', 1)
    task2 = task_factory('2', 2)
    task3 = task_factory('3', 3)
    task4 = task_factory('4', 2)
    task5 = task_factory('5', 1)
    task6 = task_factory('6', 2)
    tasks = [task1, task2, task3, task4, task5, task6]
    data_in = {
        'name':
        'proj',
        'tasks':
        tasks,
        'dependencies': [{
            'source': source.uid,
            'destination': destination.uid
        } for source, destination in [(task1, task3), (
            task2, task3), (task2, task4), (task3, task5), (task3, task6)]]
    }

    class MockModel:
        pass

    model = MockModel()
    proj = Project.from_dict(data_in, model)
    assert proj.uid is not None
    assert proj.name == 'proj'
    assert proj.model is model
    for task in tasks:
        assert task in proj.tasks
    assert set(proj.successors(task1)) == {task3}
    assert set(proj.successors(task2)) == {task4, task3}
    assert set(proj.successors(task3)) == {task5, task6}
    for task in {task5, task6}:
        assert set(proj.successors(task)) == set()
    for task in {task1, task2}:
        assert set(proj.predecessors(task)) == set()
    assert set(proj.predecessors(task3)) == {task1, task2}
    assert set(proj.predecessors(task4)) == {task2}
    assert set(proj.predecessors(task5)) == {task3}
    assert set(proj.predecessors(task6)) == {task3}
def test_add_task():
    project = Project('proj')
    task = task_factory('task1', 3)
    project.add_task(task)
    assert task in project.tasks
    assert task.project_uid == project.uid