Bridge test: the first process is a runtime dropped after the turn opens
A second PlayTable over the same store cannot open while the first is alive (the store takes an exclusive lock), so the first leg now runs on its own runtime and dies with it, as a crashed process would. Does not run on the stopgap (ignored test); verified on Starfire. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
8ca2c5556c
commit
4f92840fe7
1 changed files with 34 additions and 13 deletions
|
|
@ -3235,22 +3235,43 @@ mod tests {
|
|||
);
|
||||
assert_eq!(play_intents.len(), 1);
|
||||
assert_eq!(play_intents[0]["payload"]["bindings"]["text"], "I look around the hall.");
|
||||
let played = post(&fixture.state, &fixture.cookie, play_intents.into_iter().next().unwrap()).await;
|
||||
// The first process is a runtime of its own, dropped once the turn is
|
||||
// open: the spawned round dies with it, which is what a crash does.
|
||||
let (played, opened) = {
|
||||
let state = fixture.state.clone();
|
||||
let cookie = fixture.cookie.clone();
|
||||
let held = held.clone();
|
||||
let intent = play_intents.into_iter().next().unwrap();
|
||||
std::thread::spawn(move || {
|
||||
let process = tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap();
|
||||
let seen = process.block_on(async {
|
||||
let played = post(&state, &cookie, intent).await;
|
||||
let opened = tokio::time::timeout(Duration::from_secs(5), async {
|
||||
loop {
|
||||
if let Some(view) = held.current_turn_view().await {
|
||||
if view.run_in_progress {
|
||||
break view;
|
||||
}
|
||||
}
|
||||
tokio::time::sleep(Duration::from_millis(10)).await;
|
||||
}
|
||||
})
|
||||
.await
|
||||
.expect("the real client's typed world.play must open a turn a round is working on");
|
||||
(played, opened)
|
||||
});
|
||||
process.shutdown_timeout(Duration::from_secs(5));
|
||||
seen
|
||||
})
|
||||
.join()
|
||||
.unwrap()
|
||||
};
|
||||
assert_eq!(played["receipt"]["state"], "accepted", "typed world.play via the real client: {played}");
|
||||
let opened = tokio::time::timeout(Duration::from_secs(5), async {
|
||||
loop {
|
||||
if let Some(view) = held.current_turn_view().await {
|
||||
break view;
|
||||
}
|
||||
tokio::time::sleep(Duration::from_millis(10)).await;
|
||||
}
|
||||
})
|
||||
.await
|
||||
.expect("the real client's typed world.play must reach PlayTable and open a turn row");
|
||||
assert_eq!(opened.state, PlayTurnState::Running);
|
||||
fixture.state.play = None;
|
||||
drop(held);
|
||||
|
||||
// The process that held that turn is gone; the next one opens the same
|
||||
// store and finds the turn `Running` with nothing working on it. The
|
||||
// The next process opens the same store and finds the turn `Running` with nothing working on it. The
|
||||
// client now clicks Play with the box untouched, which is exactly what
|
||||
// the card's hint tells a player to do.
|
||||
let restarted = table_over(
|
||||
|
|
|
|||
Loading…
Reference in a new issue