test(TASK-035): run deep compress tests on a big-stack thread
The .compress-session success test polls through the whole summarization call chain; those nested poll frames overflow the default test-thread stack on Windows debug builds even with the outer future boxed. Drive all four deep-compress tests through the same big-stack run_async harness the macro tests already use.
This commit is contained in:
1 file changed
+46
-14
+46
-14
@@ -2019,6 +2019,7 @@ mod tests {
|
|||||||
use crate::hooks::{HookDef, HooksMap, test_sink};
|
use crate::hooks::{HookDef, HooksMap, test_sink};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
use std::future::Future;
|
||||||
|
|
||||||
const TURN_EVENTS: [&str; 4] = [
|
const TURN_EVENTS: [&str; 4] = [
|
||||||
"turn.started",
|
"turn.started",
|
||||||
@@ -2161,17 +2162,43 @@ mod tests {
|
|||||||
assert_eq!(turn_counts(marker), (1, 0, 1, 0));
|
assert_eq!(turn_counts(marker), (1, 0, 1, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
/// Drives a deep REPL future to completion on a thread with extra stack
|
||||||
|
/// headroom: nested `run_repl_command`/`compress_session` poll frames
|
||||||
|
/// are deep in debug builds and overflow the default test-thread stack
|
||||||
|
/// (Windows exhausts it first).
|
||||||
|
fn run_async<F>(f: F) -> F::Output
|
||||||
|
where
|
||||||
|
F: Future + Send,
|
||||||
|
F::Output: Send,
|
||||||
|
{
|
||||||
|
std::thread::scope(|scope| {
|
||||||
|
std::thread::Builder::new()
|
||||||
|
.stack_size(8 * 1024 * 1024)
|
||||||
|
.spawn_scoped(scope, || {
|
||||||
|
tokio::runtime::Builder::new_current_thread()
|
||||||
|
.enable_all()
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
.block_on(f)
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
.join()
|
||||||
|
.unwrap()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
#[serial]
|
#[serial]
|
||||||
async fn compress_command_failure_fires_no_session_compressed() {
|
fn compress_command_failure_fires_no_session_compressed() {
|
||||||
let _sink = test_sink::install();
|
let _sink = test_sink::install();
|
||||||
let marker = "compress-fail-z9t";
|
let marker = "compress-fail-z9t";
|
||||||
|
run_async(async {
|
||||||
let mut ctx = ctx_with_hooks(&["session.compressed"], marker);
|
let mut ctx = ctx_with_hooks(&["session.compressed"], marker);
|
||||||
ctx.session = Some(Session::default());
|
ctx.session = Some(Session::default());
|
||||||
let abort_signal = create_abort_signal();
|
let abort_signal = create_abort_signal();
|
||||||
|
|
||||||
// Boxed: `run_repl_command`'s state machine is far larger than a test
|
// Boxed: `run_repl_command`'s state machine is far larger than a
|
||||||
// thread's stack.
|
// test thread's stack.
|
||||||
let result = Box::pin(run_repl_command(
|
let result = Box::pin(run_repl_command(
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
abort_signal,
|
abort_signal,
|
||||||
@@ -2180,6 +2207,7 @@ mod tests {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
assert!(result.is_err(), "compressing an empty session must fail");
|
assert!(result.is_err(), "compressing an empty session must fail");
|
||||||
|
});
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
test_sink::snapshot()
|
test_sink::snapshot()
|
||||||
.iter()
|
.iter()
|
||||||
@@ -2231,16 +2259,17 @@ mod tests {
|
|||||||
.count()
|
.count()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[test]
|
||||||
#[serial]
|
#[serial]
|
||||||
async fn compress_command_success_fires_session_compressed_once() {
|
fn compress_command_success_fires_session_compressed_once() {
|
||||||
let _sink = test_sink::install();
|
let _sink = test_sink::install();
|
||||||
let marker = "compress-ok-w2p";
|
let marker = "compress-ok-w2p";
|
||||||
|
run_async(async {
|
||||||
let mut ctx = compressible_ctx(marker);
|
let mut ctx = compressible_ctx(marker);
|
||||||
let abort_signal = create_abort_signal();
|
let abort_signal = create_abort_signal();
|
||||||
|
|
||||||
// Boxed: `run_repl_command`'s state machine is far larger than a test
|
// Boxed: `run_repl_command`'s state machine is far larger than a
|
||||||
// thread's stack.
|
// test thread's stack.
|
||||||
let result = Box::pin(run_repl_command(
|
let result = Box::pin(run_repl_command(
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
abort_signal,
|
abort_signal,
|
||||||
@@ -2252,6 +2281,7 @@ mod tests {
|
|||||||
result.is_ok(),
|
result.is_ok(),
|
||||||
"dry-run compression must succeed: {result:?}"
|
"dry-run compression must succeed: {result:?}"
|
||||||
);
|
);
|
||||||
|
});
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
session_compressed_count(marker),
|
session_compressed_count(marker),
|
||||||
1,
|
1,
|
||||||
@@ -2259,17 +2289,18 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[test]
|
||||||
#[serial]
|
#[serial]
|
||||||
async fn auto_compress_success_fires_session_compressed_once() {
|
fn auto_compress_success_fires_session_compressed_once() {
|
||||||
// Covers the ask-loop call site through its extracted seam;
|
// Covers the ask-loop call site through its extracted seam;
|
||||||
// driving `needs_compression` itself requires a full LLM turn and
|
// driving `needs_compression` itself requires a full LLM turn and
|
||||||
// is exercised end-to-end by integration coverage, not here.
|
// is exercised end-to-end by integration coverage, not here.
|
||||||
let _sink = test_sink::install();
|
let _sink = test_sink::install();
|
||||||
let marker = "auto-compress-ok-f8r";
|
let marker = "auto-compress-ok-f8r";
|
||||||
|
run_async(async {
|
||||||
let mut ctx = compressible_ctx(marker);
|
let mut ctx = compressible_ctx(marker);
|
||||||
|
|
||||||
auto_compress_session(&mut ctx).await;
|
auto_compress_session(&mut ctx).await;
|
||||||
|
});
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
session_compressed_count(marker),
|
session_compressed_count(marker),
|
||||||
@@ -2278,17 +2309,18 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[test]
|
||||||
#[serial]
|
#[serial]
|
||||||
async fn auto_compress_failure_fires_no_session_compressed_and_swallows_error() {
|
fn auto_compress_failure_fires_no_session_compressed_and_swallows_error() {
|
||||||
let _sink = test_sink::install();
|
let _sink = test_sink::install();
|
||||||
let marker = "auto-compress-fail-d3k";
|
let marker = "auto-compress-fail-d3k";
|
||||||
|
run_async(async {
|
||||||
let mut ctx = compressible_ctx(marker);
|
let mut ctx = compressible_ctx(marker);
|
||||||
// An empty session makes compress_session fail; the seam must
|
// An empty session makes compress_session fail; the seam must
|
||||||
// swallow the error (no panic, no propagation) and fire nothing.
|
// swallow the error (no panic, no propagation) and fire nothing.
|
||||||
ctx.session = Some(Session::default());
|
ctx.session = Some(Session::default());
|
||||||
|
|
||||||
auto_compress_session(&mut ctx).await;
|
auto_compress_session(&mut ctx).await;
|
||||||
|
});
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
session_compressed_count(marker),
|
session_compressed_count(marker),
|
||||||
|
|||||||
Reference in new issue
Block a user