65 lines
2.2 KiB
Python
65 lines
2.2 KiB
Python
import uuid
|
|
from datetime import date
|
|
from types import SimpleNamespace
|
|
|
|
import pytest
|
|
|
|
from app.scheduling_service import calculate_schedule, check_for_cycle
|
|
|
|
|
|
def test_cycle_detection():
|
|
id_a = uuid.uuid4()
|
|
id_b = uuid.uuid4()
|
|
id_c = uuid.uuid4()
|
|
|
|
edges = [
|
|
(id_a, id_b),
|
|
(id_b, id_c),
|
|
]
|
|
|
|
# Adding C -> A should detect cycle
|
|
assert check_for_cycle(edges, id_c, id_a) is True
|
|
|
|
# Adding A -> A (self-loop) should detect cycle
|
|
assert check_for_cycle(edges, id_a, id_a) is True
|
|
|
|
# Adding C -> D (new node) should not detect cycle
|
|
id_d = uuid.uuid4()
|
|
assert check_for_cycle(edges, id_c, id_d) is False
|
|
|
|
|
|
def test_cpm_forward_and_backward_pass():
|
|
id_a = uuid.uuid4()
|
|
id_b = uuid.uuid4()
|
|
id_c = uuid.uuid4()
|
|
|
|
t_a = SimpleNamespace(id=id_a, duration=3, planned_start=date(2026, 1, 1), parent_id=None, progress=0)
|
|
t_b = SimpleNamespace(id=id_b, duration=4, planned_start=None, parent_id=None, progress=0)
|
|
t_c = SimpleNamespace(id=id_c, duration=2, planned_start=None, parent_id=None, progress=0)
|
|
|
|
# A (3d) -[FS + 1 lag]-> B (4d) -[FS + 0 lag]-> C (2d)
|
|
rel_ab = SimpleNamespace(from_task_id=id_a, to_task_id=id_b, relation_type="FS", lag_days=1)
|
|
rel_bc = SimpleNamespace(from_task_id=id_b, to_task_id=id_c, relation_type="FS", lag_days=0)
|
|
|
|
res = calculate_schedule([t_a, t_b, t_c], [rel_ab, rel_bc], project_start=date(2026, 1, 1))
|
|
|
|
sched = res["tasks_schedule"]
|
|
|
|
# Task A: 2026-01-01, duration 3 is a gap -> ends 2026-01-04
|
|
assert sched[id_a]["planned_start"] == date(2026, 1, 1)
|
|
assert sched[id_a]["planned_end"] == date(2026, 1, 4)
|
|
|
|
# Task B starts right after A finishes (Jan 4) plus 1 lag day = Jan 5
|
|
assert sched[id_b]["planned_start"] == date(2026, 1, 5)
|
|
# B: duration 4 gap -> Jan 5 + 4 = Jan 9
|
|
assert sched[id_b]["planned_end"] == date(2026, 1, 9)
|
|
|
|
# Task C starts Jan 9, duration 2 gap -> ends Jan 11
|
|
assert sched[id_c]["planned_start"] == date(2026, 1, 9)
|
|
assert sched[id_c]["planned_end"] == date(2026, 1, 11)
|
|
|
|
# All three are on critical path
|
|
assert id_a in res["critical_path"]
|
|
assert id_b in res["critical_path"]
|
|
assert id_c in res["critical_path"]
|