Skip to content

Commit 22a0e93

Browse files
karthiknadigCopilot
andcommitted
test: observe descendant release within shutdown deadline (Refs #529)
Poll the actual descendant lease using only the remainder of the existing four-second shutdown budget instead of requiring an instantaneous lock transition at server exit. Test held-lock timeout and success after release; preserve cancellation and elapsed-time assertions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 83df603 commit 22a0e93

1 file changed

Lines changed: 48 additions & 3 deletions

File tree

‎crates/pet/tests/jsonrpc_server_test.rs‎

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,48 @@ fn stdin_eof_exits_while_output_is_not_drained() {
676676
reader.join().unwrap();
677677
}
678678

679+
fn wait_for_descendant_lease(lease: &fs::File, timeout: Duration) -> std::io::Result<()> {
680+
let started = Instant::now();
681+
loop {
682+
match lease.try_lock() {
683+
Ok(()) => return Ok(()),
684+
Err(fs::TryLockError::Error(error)) => return Err(error),
685+
Err(fs::TryLockError::WouldBlock) => {}
686+
}
687+
let remaining = timeout.saturating_sub(started.elapsed());
688+
if remaining.is_zero() {
689+
return Err(std::io::Error::new(
690+
std::io::ErrorKind::TimedOut,
691+
"descendant still holds its lease at the shutdown deadline",
692+
));
693+
}
694+
thread::sleep(Duration::from_millis(10).min(remaining));
695+
}
696+
}
697+
698+
#[test]
699+
fn descendant_lease_wait_is_bounded_and_requires_release() {
700+
let directory = tempfile::tempdir().unwrap();
701+
let path = directory.path().join("lease");
702+
let holder = fs::File::create(&path).unwrap();
703+
holder.try_lock().unwrap();
704+
let lease = fs::OpenOptions::new()
705+
.read(true)
706+
.write(true)
707+
.open(path)
708+
.unwrap();
709+
let started = Instant::now();
710+
assert_eq!(
711+
wait_for_descendant_lease(&lease, Duration::from_millis(20))
712+
.unwrap_err()
713+
.kind(),
714+
std::io::ErrorKind::TimedOut
715+
);
716+
assert!(started.elapsed() < Duration::from_secs(1));
717+
drop(holder);
718+
wait_for_descendant_lease(&lease, Duration::ZERO).unwrap();
719+
}
720+
679721
#[cfg(feature = "ci")]
680722
#[test]
681723
fn stdin_eof_cancels_an_active_interpreter_and_its_descendant() {
@@ -741,10 +783,13 @@ fn stdin_eof_cancels_an_active_interpreter_and_its_descendant() {
741783
"active-probe shutdown failed: {status}; stderr: {}",
742784
client.stderr_output()
743785
);
786+
// Observe OS lease release within the same budget as server shutdown.
787+
wait_for_descendant_lease(
788+
&lease,
789+
Duration::from_secs(4).saturating_sub(started.elapsed()),
790+
)
791+
.expect("shutdown must release the actual descendant's lease");
744792
assert!(started.elapsed() < Duration::from_secs(4));
745-
lease
746-
.try_lock()
747-
.expect("shutdown must release the actual descendant's lease");
748793
assert!(
749794
request.join().unwrap().is_err(),
750795
"an active request must be cancelled, not reported as successful"

0 commit comments

Comments
 (0)