Skip to content

Commit 94faccc

Browse files
committed
Verify cumulative deadline identity across worker preparation
1 parent 31cda7c commit 94faccc

1 file changed

Lines changed: 34 additions & 20 deletions

File tree

‎tests/run_lifecycle_tests.rs‎

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -538,41 +538,55 @@ async fn deadline_terminates_child_process_without_residue() {
538538
async fn deadline_is_cumulative_from_admission() {
539539
let provider = ScriptedProvider::new();
540540
provider.push_hang();
541-
let timeout = Duration::from_millis(400);
542-
let state = loop_service(short_config(timeout), &provider);
541+
let state = loop_service(short_config(Duration::from_millis(400)), &provider);
543542
let service = state.service();
544543
let admitted = service
545544
.admit(admit_request())
546545
.await
547546
.expect("admission should succeed");
548-
tokio::time::sleep(Duration::from_millis(250)).await;
549-
let remaining = service
547+
let cancellation = service
550548
.handle(&admitted.run_id)
551549
.expect("live handle")
552550
.cancellation()
553-
.remaining_deadline()
554-
.expect("deadline");
555-
assert!(
556-
remaining < timeout,
557-
"remaining deadline {remaining:?} must be less than the original {timeout:?}"
558-
);
559-
assert!(remaining > Duration::from_millis(20));
560-
let started = Instant::now();
561-
service
562-
.clone()
563-
.run_worker(admitted.run_id.clone(), "ignored".to_string())
564-
.await;
565-
let elapsed = started.elapsed();
551+
.clone();
552+
let admitted_deadline = cancellation.deadline_instant().expect("admission deadline");
553+
let preparation_observed = Arc::new(AtomicBool::new(false));
554+
service.inject_agent_compile_lookup_observer(Arc::new({
555+
let cancellation = cancellation.clone();
556+
let preparation_observed = Arc::clone(&preparation_observed);
557+
move || {
558+
preparation_observed.store(true, Ordering::SeqCst);
559+
assert_eq!(cancellation.deadline_instant(), Some(admitted_deadline));
560+
// Consume the admitted budget during preparation. A worker must
561+
// not gain a new budget when it finally starts the RSS invocation.
562+
thread::sleep(admitted_deadline.saturating_duration_since(Instant::now()));
563+
assert_eq!(cancellation.remaining_deadline(), Some(Duration::ZERO));
564+
}
565+
}));
566+
// Preserve the queue delay as well as preparation time in the same budget.
567+
tokio::time::sleep(Duration::from_millis(250)).await;
568+
tokio::time::timeout(
569+
Duration::from_secs(5),
570+
service
571+
.clone()
572+
.run_worker(admitted.run_id.clone(), "ignored".to_string()),
573+
)
574+
.await
575+
.expect("expired worker and cleanup must finish within the outer bound");
566576

577+
assert!(preparation_observed.load(Ordering::SeqCst));
578+
assert_eq!(cancellation.deadline_instant(), Some(admitted_deadline));
567579
assert_eq!(
568580
terminal_events(&service, &admitted.run_id),
569581
vec!["run.cancelled".to_string()]
570582
);
571583
assert_eq!(cancel_reason(&service, &admitted.run_id), "deadline");
572-
assert!(
573-
elapsed < timeout,
574-
"worker should observe remaining deadline, not a fresh {timeout:?}: {elapsed:?}"
584+
assert_eq!(
585+
provider.call_count(),
586+
0,
587+
"preparation exhausted the admission deadline before provider work"
575588
);
589+
assert!(service.capability_host_closed(&admitted.run_id));
576590
}
577591

578592
#[tokio::test(flavor = "multi_thread")]

0 commit comments

Comments
 (0)