This commit is contained in:
2026-06-17 16:02:04 -04:00
parent 6762586e2d
commit e51a6777fc
21 changed files with 1399 additions and 506 deletions
+61 -15
View File
@@ -136,25 +136,37 @@ def compile_schedule(
ref_active_priority: dict[TestKey, int] = dict(_ACTIVE_REF)
entries: list[ScheduleEntry] = []
current_date = _parse_date(start_date)
window_start_date = _parse_date(start_date)
current_date = window_start_date
last_date: str | None = None
daytime_shift2_window_pending = daytime_testing_today
while dut_active_priority or ref_active_priority:
is_special_daytime_shift2_window = (
daytime_shift2_window_pending
and current_date == window_start_date
and current_date.weekday() < 5
and current_date.isoformat() not in holiday_dates
)
# Get the shift sequence for current date (respects Mon/Fri/weekend rules)
shift_sequence = _get_shift_sequence(current_date, holiday_dates)
shift_sequence = _get_shift_sequence(
current_date,
holiday_dates,
daytime_shift2_only=is_special_daytime_shift2_window,
)
if not shift_sequence:
break # No valid shift sequence
dut_active_test_ids: set[TestKey] = set(dut_active_priority.keys())
ref_active_test_ids: set[TestKey] = set(ref_active_priority.keys())
bundles = _create_bundles(dut_active_test_ids, ref_active_test_ids, _TESTS_BY_ID)
bundles = _create_bundles(dut_active_test_ids, ref_active_test_ids, _TESTS_BY_ID, top_priority_tests)
shift_capacities = {
(date_obj, shift_idx): _shift_capacity_for_date(
current_date=date_obj,
holiday_dates=holiday_dates,
start_date_override=start_date,
daytime_testing_today=daytime_testing_today,
daytime_shift2_only=is_special_daytime_shift2_window and date_obj == current_date,
).get(shift_idx, 0)
for date_obj, shift_idx in shift_sequence
}
@@ -173,6 +185,9 @@ def compile_schedule(
if placed_last_date is not None:
last_date = placed_last_date
# Daytime testing special handling applies only to the first scheduling window.
daytime_shift2_window_pending = False
# Move to next scheduling window start date
# After shift 1 (1am-9am), there's shift 2 if daytime testing, then shift 3 (5pm)
# After shift 3 (5pm), shift 1 is next day (1am)
@@ -347,6 +362,7 @@ def _create_bundles(
dut_active_test_ids: set[TestKey],
ref_active_test_ids: set[TestKey],
tests: dict[TestKey, SchedulerTest],
top_priority_tests: set[str] | None = None,
) -> list[TestBundle]:
"""Create bundles of tests that must run together, sorted by priority tier and efficiency.
@@ -358,6 +374,9 @@ def _create_bundles(
Returned list is sorted by (priority_tier, total_minutes) to place small/high-priority bundles first.
"""
if top_priority_tests is None:
top_priority_tests = set()
bundles: list[TestBundle] = []
processed: set[TestKey] = set()
@@ -393,7 +412,12 @@ def _create_bundles(
if not bundle_test_ids:
continue
processed.update(bundle_test_ids)
priority_tier = BUNDLE_PRIORITY_P2P_WITH_COE
# Check if any test in bundle is top priority
bundle_test_ids_only = {key[0] for key in bundle_test_ids}
if bundle_test_ids_only & top_priority_tests:
priority_tier = BUNDLE_PRIORITY_FAILED # Highest priority (0)
else:
priority_tier = BUNDLE_PRIORITY_P2P_WITH_COE
bundles.append(TestBundle(
test_ids=bundle_test_ids,
priority_tier=priority_tier,
@@ -415,7 +439,12 @@ def _create_bundles(
if not bundle_test_ids:
continue
processed.update(bundle_test_ids)
priority_tier = BUNDLE_PRIORITY_P2P_ONLY
# Check if any test in bundle is top priority
bundle_test_ids_only = {key[0] for key in bundle_test_ids}
if bundle_test_ids_only & top_priority_tests:
priority_tier = BUNDLE_PRIORITY_FAILED # Highest priority (0)
else:
priority_tier = BUNDLE_PRIORITY_P2P_ONLY
bundles.append(TestBundle(
test_ids=bundle_test_ids,
priority_tier=priority_tier,
@@ -425,7 +454,12 @@ def _create_bundles(
bundle_test_ids = [key for key in (_active_key(test_id, DUT), _active_key(test_id, REF)) if key is not None and key not in processed]
if not bundle_test_ids:
continue
priority_tier = BUNDLE_PRIORITY_P3P
# Check if any test in bundle is top priority
bundle_test_ids_only = {key[0] for key in bundle_test_ids}
if bundle_test_ids_only & top_priority_tests:
priority_tier = BUNDLE_PRIORITY_FAILED # Highest priority (0)
else:
priority_tier = BUNDLE_PRIORITY_P3P
bundles.append(TestBundle(
test_ids=bundle_test_ids,
priority_tier=priority_tier,
@@ -439,8 +473,12 @@ def _create_bundles(
if key in processed:
continue
test = tests[key]
priority_tier = BUNDLE_PRIORITY_COE_ONLY
bundle_test_ids = [key]
# Check if this test is top priority
if key[0] in top_priority_tests:
priority_tier = BUNDLE_PRIORITY_FAILED # Highest priority (0)
else:
priority_tier = BUNDLE_PRIORITY_COE_ONLY
bundles.append(TestBundle(
test_ids=bundle_test_ids,
priority_tier=priority_tier,
@@ -466,8 +504,7 @@ def _rx_tx_pair_id(test_id: str, active: set[str]) -> str | None:
def _shift_capacity_for_date(
current_date: date,
holiday_dates: set[str],
start_date_override: str | None,
daytime_testing_today: bool,
daytime_shift2_only: bool,
) -> dict[int, int]:
iso = current_date.isoformat()
if iso in holiday_dates:
@@ -477,8 +514,8 @@ def _shift_capacity_for_date(
if is_weekend:
return {1: 480, 2: 480, 3: 480}
if start_date_override and iso == _parse_date(start_date_override).isoformat() and daytime_testing_today:
return {1: 480, 2: 480, 3: 480}
if daytime_shift2_only:
return {1: 0, 2: 480, 3: 0}
return {1: 600, 2: 0, 3: 420}
@@ -489,15 +526,20 @@ def _parse_date(value: str | None) -> date:
return datetime.strptime(value, "%Y-%m-%d").date()
def _get_shift_sequence(start_date: date, holiday_dates: set[str]) -> list[tuple[date, int]]:
def _get_shift_sequence(
start_date: date,
holiday_dates: set[str],
daytime_shift2_only: bool = False,
) -> list[tuple[date, int]]:
"""Generate the sequence of (date, shift_index) tuples for a scheduling window.
Rules per design:
- Daytime testing first window (weekday only): [2] (shift 2 today only)
- Monday-Thursday: [3, 1] (shift 3 today, shift 1 next day) = 16 hours
- Friday: [3, 1, 2, 3, 1, 2, 3, 1] (Fri-Mon) = 24 hours continuous
- Saturday/Sunday/Holiday weekday: all 3 shifts
Always starts on shift 3 for weekdays.
Weekday default starts on shift 3 unless daytime testing shift-2-only is enabled.
Returns ordered list of (date, shift_index) pairs.
"""
iso = start_date.isoformat()
@@ -505,6 +547,10 @@ def _get_shift_sequence(start_date: date, holiday_dates: set[str]) -> list[tuple
weekday = start_date.weekday() # 0=Mon, 4=Fri, 5=Sat, 6=Sun
shifts: list[tuple[date, int]] = []
if daytime_shift2_only and weekday < 5 and not is_holiday:
shifts.append((start_date, 2))
return shifts
# If holiday on a weekday, treat as weekend (all 3 shifts)
if is_holiday and weekday < 5: