Fix remaining sync chat stack overflows

This commit is contained in:
elky
2026-05-31 02:12:22 +08:00
parent fde15c9b60
commit 49f952692b
4 changed files with 127 additions and 50 deletions
@@ -12,13 +12,10 @@ use super::{
TRACE_ID_HEADER, TRACE_ID_HEADER,
}; };
#[test] large_stack_async_test!(
fn gateway_skips_unsupported_local_openai_chat_sync_candidate_before_trying_next_one() { gateway_skips_unsupported_local_openai_chat_sync_candidate_before_trying_next_one,
run_async_test_on_large_stack( gateway_skips_unsupported_local_openai_chat_sync_candidate_before_trying_next_one_impl
"gateway_skips_unsupported_local_openai_chat_sync_candidate_before_trying_next_one", );
gateway_skips_unsupported_local_openai_chat_sync_candidate_before_trying_next_one_impl(),
);
}
async fn gateway_skips_unsupported_local_openai_chat_sync_candidate_before_trying_next_one_impl() { async fn gateway_skips_unsupported_local_openai_chat_sync_candidate_before_trying_next_one_impl() {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@@ -428,8 +425,12 @@ async fn gateway_skips_unsupported_local_openai_chat_sync_candidate_before_tryin
upstream_handle.abort(); upstream_handle.abort();
} }
#[tokio::test] large_stack_async_test!(
async fn gateway_surfaces_local_execution_runtime_miss_reason_when_all_openai_chat_candidates_are_skipped( gateway_surfaces_local_execution_runtime_miss_reason_when_all_openai_chat_candidates_are_skipped,
gateway_surfaces_local_execution_runtime_miss_reason_when_all_openai_chat_candidates_are_skipped_impl
);
async fn gateway_surfaces_local_execution_runtime_miss_reason_when_all_openai_chat_candidates_are_skipped_impl(
) { ) {
fn hash_api_key(value: &str) -> String { fn hash_api_key(value: &str) -> String {
let mut hasher = Sha256::new(); let mut hasher = Sha256::new();
@@ -686,8 +687,12 @@ async fn gateway_surfaces_local_execution_runtime_miss_reason_when_all_openai_ch
upstream_handle.abort(); upstream_handle.abort();
} }
#[tokio::test] large_stack_async_test!(
async fn gateway_retries_next_local_openai_chat_sync_candidate_after_auth_failure() { gateway_retries_next_local_openai_chat_sync_candidate_after_auth_failure,
gateway_retries_next_local_openai_chat_sync_candidate_after_auth_failure_impl
);
async fn gateway_retries_next_local_openai_chat_sync_candidate_after_auth_failure_impl() {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct SeenExecutionRuntimeSyncRequest { struct SeenExecutionRuntimeSyncRequest {
trace_id: String, trace_id: String,
@@ -10,8 +10,13 @@ use super::{
EXECUTION_PATH_EXECUTION_RUNTIME_SYNC, EXECUTION_PATH_HEADER, TRACE_ID_HEADER, EXECUTION_PATH_EXECUTION_RUNTIME_SYNC, EXECUTION_PATH_HEADER, TRACE_ID_HEADER,
}; };
#[tokio::test] large_stack_async_test!(
async fn proxy_pii_redaction_local_openai_chat_runtime_masks_headers_and_restores_sync_response() { proxy_pii_redaction_local_openai_chat_runtime_masks_headers_and_restores_sync_response,
proxy_pii_redaction_local_openai_chat_runtime_masks_headers_and_restores_sync_response_impl
);
async fn proxy_pii_redaction_local_openai_chat_runtime_masks_headers_and_restores_sync_response_impl(
) {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct SeenProviderRequest { struct SeenProviderRequest {
body: serde_json::Value, body: serde_json::Value,
@@ -377,13 +382,10 @@ async fn proxy_pii_redaction_local_openai_chat_runtime_masks_headers_and_restore
provider_handle.abort(); provider_handle.abort();
} }
#[test] large_stack_async_test!(
fn gateway_executes_openai_chat_sync_via_local_decision_gate_without_execution_runtime_override() { gateway_executes_openai_chat_sync_via_local_decision_gate_without_execution_runtime_override,
run_async_test_on_large_stack( gateway_executes_openai_chat_sync_via_local_decision_gate_without_execution_runtime_override_impl
"gateway_executes_openai_chat_sync_via_local_decision_gate_without_execution_runtime_override", );
gateway_executes_openai_chat_sync_via_local_decision_gate_without_execution_runtime_override_impl(),
);
}
async fn gateway_executes_openai_chat_sync_via_local_decision_gate_without_execution_runtime_override_impl( async fn gateway_executes_openai_chat_sync_via_local_decision_gate_without_execution_runtime_override_impl(
) { ) {
@@ -766,8 +768,13 @@ async fn gateway_executes_openai_chat_sync_via_local_decision_gate_without_execu
upstream_handle.abort(); upstream_handle.abort();
} }
#[tokio::test] large_stack_async_test!(
async fn gateway_executes_openai_chat_sync_with_regex_model_mapping_in_execution_runtime_request() { gateway_executes_openai_chat_sync_with_regex_model_mapping_in_execution_runtime_request,
gateway_executes_openai_chat_sync_with_regex_model_mapping_in_execution_runtime_request_impl
);
async fn gateway_executes_openai_chat_sync_with_regex_model_mapping_in_execution_runtime_request_impl(
) {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct SeenExecutionRuntimeSyncRequest { struct SeenExecutionRuntimeSyncRequest {
model: String, model: String,
@@ -1045,8 +1052,12 @@ async fn gateway_executes_openai_chat_sync_with_regex_model_mapping_in_execution
execution_runtime_handle.abort(); execution_runtime_handle.abort();
} }
#[tokio::test] large_stack_async_test!(
async fn gateway_executes_openai_chat_sync_via_local_cross_format_gemini_candidate_without_external_control_config( gateway_executes_openai_chat_sync_via_local_cross_format_gemini_candidate_without_external_control_config,
gateway_executes_openai_chat_sync_via_local_cross_format_gemini_candidate_without_external_control_config_impl
);
async fn gateway_executes_openai_chat_sync_via_local_cross_format_gemini_candidate_without_external_control_config_impl(
) { ) {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct SeenExecutionRuntimeSyncRequest { struct SeenExecutionRuntimeSyncRequest {
@@ -1613,8 +1624,12 @@ async fn gateway_executes_openai_chat_sync_via_local_cross_format_gemini_candida
upstream_handle.abort(); upstream_handle.abort();
} }
#[tokio::test] large_stack_async_test!(
async fn gateway_returns_openai_chat_error_for_local_cross_format_claude_cli_sync_failure() { gateway_returns_openai_chat_error_for_local_cross_format_claude_cli_sync_failure,
gateway_returns_openai_chat_error_for_local_cross_format_claude_cli_sync_failure_impl
);
async fn gateway_returns_openai_chat_error_for_local_cross_format_claude_cli_sync_failure_impl() {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct SeenExecutionRuntimeSyncRequest { struct SeenExecutionRuntimeSyncRequest {
trace_id: String, trace_id: String,
@@ -2011,8 +2026,12 @@ async fn gateway_returns_openai_chat_error_for_local_cross_format_claude_cli_syn
upstream_handle.abort(); upstream_handle.abort();
} }
#[tokio::test] large_stack_async_test!(
async fn gateway_returns_openai_chat_error_for_local_cross_format_gemini_cli_sync_failure() { gateway_returns_openai_chat_error_for_local_cross_format_gemini_cli_sync_failure,
gateway_returns_openai_chat_error_for_local_cross_format_gemini_cli_sync_failure_impl
);
async fn gateway_returns_openai_chat_error_for_local_cross_format_gemini_cli_sync_failure_impl() {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct SeenExecutionRuntimeSyncRequest { struct SeenExecutionRuntimeSyncRequest {
trace_id: String, trace_id: String,
@@ -2438,8 +2457,12 @@ async fn gateway_returns_openai_chat_error_for_local_cross_format_gemini_cli_syn
upstream_handle.abort(); upstream_handle.abort();
} }
#[tokio::test] large_stack_async_test!(
async fn gateway_returns_openai_chat_error_for_local_cross_format_claude_sync_failure() { gateway_returns_openai_chat_error_for_local_cross_format_claude_sync_failure,
gateway_returns_openai_chat_error_for_local_cross_format_claude_sync_failure_impl
);
async fn gateway_returns_openai_chat_error_for_local_cross_format_claude_sync_failure_impl() {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct SeenExecutionRuntimeSyncRequest { struct SeenExecutionRuntimeSyncRequest {
trace_id: String, trace_id: String,
@@ -2839,8 +2862,12 @@ async fn gateway_returns_openai_chat_error_for_local_cross_format_claude_sync_fa
upstream_handle.abort(); upstream_handle.abort();
} }
#[tokio::test] large_stack_async_test!(
async fn gateway_returns_openai_chat_error_for_local_cross_format_gemini_sync_failure() { gateway_returns_openai_chat_error_for_local_cross_format_gemini_sync_failure,
gateway_returns_openai_chat_error_for_local_cross_format_gemini_sync_failure_impl
);
async fn gateway_returns_openai_chat_error_for_local_cross_format_gemini_sync_failure_impl() {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct SeenExecutionRuntimeSyncRequest { struct SeenExecutionRuntimeSyncRequest {
trace_id: String, trace_id: String,
@@ -3279,8 +3306,12 @@ async fn gateway_returns_openai_chat_error_for_local_cross_format_gemini_sync_fa
upstream_handle.abort(); upstream_handle.abort();
} }
#[tokio::test] large_stack_async_test!(
async fn gateway_executes_openai_chat_sync_with_custom_path_via_local_decision_gate_with_local_sync_decision( gateway_executes_openai_chat_sync_with_custom_path_via_local_decision_gate_with_local_sync_decision,
gateway_executes_openai_chat_sync_with_custom_path_via_local_decision_gate_with_local_sync_decision_impl
);
async fn gateway_executes_openai_chat_sync_with_custom_path_via_local_decision_gate_with_local_sync_decision_impl(
) { ) {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct SeenExecutionRuntimeSyncRequest { struct SeenExecutionRuntimeSyncRequest {
@@ -30,6 +30,15 @@ where
} }
} }
macro_rules! large_stack_async_test {
($test_name:ident, $impl_name:ident) => {
#[test]
fn $test_name() {
run_async_test_on_large_stack(stringify!($test_name), $impl_name());
}
};
}
use crate::constants::{ use crate::constants::{
CONTROL_EXECUTED_HEADER, CONTROL_EXECUTE_FALLBACK_HEADER, DEPENDENCY_REASON_HEADER, CONTROL_EXECUTED_HEADER, CONTROL_EXECUTE_FALLBACK_HEADER, DEPENDENCY_REASON_HEADER,
EXECUTION_PATH_EXECUTION_RUNTIME_STREAM, EXECUTION_PATH_EXECUTION_RUNTIME_SYNC, EXECUTION_PATH_EXECUTION_RUNTIME_STREAM, EXECUTION_PATH_EXECUTION_RUNTIME_SYNC,
@@ -489,8 +489,12 @@ fn rich_pii_request() -> serde_json::Value {
}) })
} }
#[tokio::test] large_stack_async_test!(
async fn ai_execute_sync_pii_redaction_round_trip() { ai_execute_sync_pii_redaction_round_trip,
ai_execute_sync_pii_redaction_round_trip_impl
);
async fn ai_execute_sync_pii_redaction_round_trip_impl() {
let (response_json, seen) = run_sync_redaction_case( let (response_json, seen) = run_sync_redaction_case(
"ai-execute-sync-pii-redaction-round-trip", "ai-execute-sync-pii-redaction-round-trip",
true, true,
@@ -536,8 +540,12 @@ async fn ai_execute_sync_pii_redaction_round_trip() {
assert!(!response_content.contains("<AETHER:")); assert!(!response_content.contains("<AETHER:"));
} }
#[tokio::test] large_stack_async_test!(
async fn ai_execute_pii_redaction_disabled_module_passes_original_chat_through() { ai_execute_pii_redaction_disabled_module_passes_original_chat_through,
ai_execute_pii_redaction_disabled_module_passes_original_chat_through_impl
);
async fn ai_execute_pii_redaction_disabled_module_passes_original_chat_through_impl() {
let (response_json, seen) = run_sync_redaction_case( let (response_json, seen) = run_sync_redaction_case(
"ai-execute-pii-redaction-disabled-module", "ai-execute-pii-redaction-disabled-module",
false, false,
@@ -559,8 +567,12 @@ async fn ai_execute_pii_redaction_disabled_module_passes_original_chat_through()
); );
} }
#[tokio::test] large_stack_async_test!(
async fn ai_execute_pii_redaction_disabled_feature_passes_original_chat_through() { ai_execute_pii_redaction_disabled_feature_passes_original_chat_through,
ai_execute_pii_redaction_disabled_feature_passes_original_chat_through_impl
);
async fn ai_execute_pii_redaction_disabled_feature_passes_original_chat_through_impl() {
let (response_json, seen) = run_sync_redaction_case( let (response_json, seen) = run_sync_redaction_case(
"ai-execute-pii-redaction-disabled-provider", "ai-execute-pii-redaction-disabled-provider",
true, true,
@@ -582,8 +594,12 @@ async fn ai_execute_pii_redaction_disabled_feature_passes_original_chat_through(
); );
} }
#[tokio::test] large_stack_async_test!(
async fn ai_execute_pii_redaction_empty_rules_passes_original_chat_through() { ai_execute_pii_redaction_empty_rules_passes_original_chat_through,
ai_execute_pii_redaction_empty_rules_passes_original_chat_through_impl
);
async fn ai_execute_pii_redaction_empty_rules_passes_original_chat_through_impl() {
let (response_json, seen) = run_sync_redaction_case_with_system_config( let (response_json, seen) = run_sync_redaction_case_with_system_config(
"ai-execute-pii-redaction-empty-entities", "ai-execute-pii-redaction-empty-entities",
true, true,
@@ -605,8 +621,12 @@ async fn ai_execute_pii_redaction_empty_rules_passes_original_chat_through() {
); );
} }
#[tokio::test] large_stack_async_test!(
async fn ai_execute_pii_redaction_unknown_sentinel_like_output_is_not_restored() { ai_execute_pii_redaction_unknown_sentinel_like_output_is_not_restored,
ai_execute_pii_redaction_unknown_sentinel_like_output_is_not_restored_impl
);
async fn ai_execute_pii_redaction_unknown_sentinel_like_output_is_not_restored_impl() {
let (response_json, seen) = run_sync_redaction_case( let (response_json, seen) = run_sync_redaction_case(
"ai-execute-pii-redaction-unknown-sentinel", "ai-execute-pii-redaction-unknown-sentinel",
true, true,
@@ -625,8 +645,12 @@ async fn ai_execute_pii_redaction_unknown_sentinel_like_output_is_not_restored()
); );
} }
#[tokio::test] large_stack_async_test!(
async fn ai_execute_pii_redaction_restores_executed_candidate_session_after_later_candidate_planning( ai_execute_pii_redaction_restores_executed_candidate_session_after_later_candidate_planning,
ai_execute_pii_redaction_restores_executed_candidate_session_after_later_candidate_planning_impl
);
async fn ai_execute_pii_redaction_restores_executed_candidate_session_after_later_candidate_planning_impl(
) { ) {
let seen_provider_request = Arc::new(Mutex::new(None::<SeenProviderRequest>)); let seen_provider_request = Arc::new(Mutex::new(None::<SeenProviderRequest>));
let seen_provider_request_clone = Arc::clone(&seen_provider_request); let seen_provider_request_clone = Arc::clone(&seen_provider_request);
@@ -770,8 +794,12 @@ async fn ai_execute_pii_redaction_restores_executed_candidate_session_after_late
provider_handle.abort(); provider_handle.abort();
} }
#[tokio::test] large_stack_async_test!(
async fn pii_redaction_performance_limits_do_not_forward_unredacted_body_upstream() { pii_redaction_performance_limits_do_not_forward_unredacted_body_upstream,
pii_redaction_performance_limits_do_not_forward_unredacted_body_upstream_impl
);
async fn pii_redaction_performance_limits_do_not_forward_unredacted_body_upstream_impl() {
let provider_hits = Arc::new(AtomicUsize::new(0)); let provider_hits = Arc::new(AtomicUsize::new(0));
let provider_hits_clone = Arc::clone(&provider_hits); let provider_hits_clone = Arc::clone(&provider_hits);
let provider_app = Router::new().route( let provider_app = Router::new().route(
@@ -845,8 +873,12 @@ async fn pii_redaction_performance_limits_do_not_forward_unredacted_body_upstrea
provider_handle.abort(); provider_handle.abort();
} }
#[tokio::test] large_stack_async_test!(
async fn ai_execute_pii_redaction_missing_encryption_key_fails_closed_before_provider() { ai_execute_pii_redaction_missing_encryption_key_fails_closed_before_provider,
ai_execute_pii_redaction_missing_encryption_key_fails_closed_before_provider_impl
);
async fn ai_execute_pii_redaction_missing_encryption_key_fails_closed_before_provider_impl() {
let execution_runtime_hits = Arc::new(AtomicUsize::new(0)); let execution_runtime_hits = Arc::new(AtomicUsize::new(0));
let execution_runtime_hits_clone = Arc::clone(&execution_runtime_hits); let execution_runtime_hits_clone = Arc::clone(&execution_runtime_hits);
let execution_runtime = Router::new().route( let execution_runtime = Router::new().route(