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,
};
#[test]
fn 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",
gateway_skips_unsupported_local_openai_chat_sync_candidate_before_trying_next_one_impl(),
);
}
large_stack_async_test!(
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() {
#[derive(Debug, Clone)]
@@ -428,8 +425,12 @@ async fn gateway_skips_unsupported_local_openai_chat_sync_candidate_before_tryin
upstream_handle.abort();
}
#[tokio::test]
async fn gateway_surfaces_local_execution_runtime_miss_reason_when_all_openai_chat_candidates_are_skipped(
large_stack_async_test!(
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 {
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();
}
#[tokio::test]
async fn gateway_retries_next_local_openai_chat_sync_candidate_after_auth_failure() {
large_stack_async_test!(
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)]
struct SeenExecutionRuntimeSyncRequest {
trace_id: String,
@@ -10,8 +10,13 @@ use super::{
EXECUTION_PATH_EXECUTION_RUNTIME_SYNC, EXECUTION_PATH_HEADER, TRACE_ID_HEADER,
};
#[tokio::test]
async fn proxy_pii_redaction_local_openai_chat_runtime_masks_headers_and_restores_sync_response() {
large_stack_async_test!(
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)]
struct SeenProviderRequest {
body: serde_json::Value,
@@ -377,13 +382,10 @@ async fn proxy_pii_redaction_local_openai_chat_runtime_masks_headers_and_restore
provider_handle.abort();
}
#[test]
fn 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",
gateway_executes_openai_chat_sync_via_local_decision_gate_without_execution_runtime_override_impl(),
);
}
large_stack_async_test!(
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(
) {
@@ -766,8 +768,13 @@ async fn gateway_executes_openai_chat_sync_via_local_decision_gate_without_execu
upstream_handle.abort();
}
#[tokio::test]
async fn gateway_executes_openai_chat_sync_with_regex_model_mapping_in_execution_runtime_request() {
large_stack_async_test!(
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)]
struct SeenExecutionRuntimeSyncRequest {
model: String,
@@ -1045,8 +1052,12 @@ async fn gateway_executes_openai_chat_sync_with_regex_model_mapping_in_execution
execution_runtime_handle.abort();
}
#[tokio::test]
async fn gateway_executes_openai_chat_sync_via_local_cross_format_gemini_candidate_without_external_control_config(
large_stack_async_test!(
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)]
struct SeenExecutionRuntimeSyncRequest {
@@ -1613,8 +1624,12 @@ async fn gateway_executes_openai_chat_sync_via_local_cross_format_gemini_candida
upstream_handle.abort();
}
#[tokio::test]
async fn gateway_returns_openai_chat_error_for_local_cross_format_claude_cli_sync_failure() {
large_stack_async_test!(
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)]
struct SeenExecutionRuntimeSyncRequest {
trace_id: String,
@@ -2011,8 +2026,12 @@ async fn gateway_returns_openai_chat_error_for_local_cross_format_claude_cli_syn
upstream_handle.abort();
}
#[tokio::test]
async fn gateway_returns_openai_chat_error_for_local_cross_format_gemini_cli_sync_failure() {
large_stack_async_test!(
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)]
struct SeenExecutionRuntimeSyncRequest {
trace_id: String,
@@ -2438,8 +2457,12 @@ async fn gateway_returns_openai_chat_error_for_local_cross_format_gemini_cli_syn
upstream_handle.abort();
}
#[tokio::test]
async fn gateway_returns_openai_chat_error_for_local_cross_format_claude_sync_failure() {
large_stack_async_test!(
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)]
struct SeenExecutionRuntimeSyncRequest {
trace_id: String,
@@ -2839,8 +2862,12 @@ async fn gateway_returns_openai_chat_error_for_local_cross_format_claude_sync_fa
upstream_handle.abort();
}
#[tokio::test]
async fn gateway_returns_openai_chat_error_for_local_cross_format_gemini_sync_failure() {
large_stack_async_test!(
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)]
struct SeenExecutionRuntimeSyncRequest {
trace_id: String,
@@ -3279,8 +3306,12 @@ async fn gateway_returns_openai_chat_error_for_local_cross_format_gemini_sync_fa
upstream_handle.abort();
}
#[tokio::test]
async fn gateway_executes_openai_chat_sync_with_custom_path_via_local_decision_gate_with_local_sync_decision(
large_stack_async_test!(
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)]
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::{
CONTROL_EXECUTED_HEADER, CONTROL_EXECUTE_FALLBACK_HEADER, DEPENDENCY_REASON_HEADER,
EXECUTION_PATH_EXECUTION_RUNTIME_STREAM, EXECUTION_PATH_EXECUTION_RUNTIME_SYNC,
@@ -489,8 +489,12 @@ fn rich_pii_request() -> serde_json::Value {
})
}
#[tokio::test]
async fn ai_execute_sync_pii_redaction_round_trip() {
large_stack_async_test!(
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(
"ai-execute-sync-pii-redaction-round-trip",
true,
@@ -536,8 +540,12 @@ async fn ai_execute_sync_pii_redaction_round_trip() {
assert!(!response_content.contains("<AETHER:"));
}
#[tokio::test]
async fn ai_execute_pii_redaction_disabled_module_passes_original_chat_through() {
large_stack_async_test!(
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(
"ai-execute-pii-redaction-disabled-module",
false,
@@ -559,8 +567,12 @@ async fn ai_execute_pii_redaction_disabled_module_passes_original_chat_through()
);
}
#[tokio::test]
async fn ai_execute_pii_redaction_disabled_feature_passes_original_chat_through() {
large_stack_async_test!(
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(
"ai-execute-pii-redaction-disabled-provider",
true,
@@ -582,8 +594,12 @@ async fn ai_execute_pii_redaction_disabled_feature_passes_original_chat_through(
);
}
#[tokio::test]
async fn ai_execute_pii_redaction_empty_rules_passes_original_chat_through() {
large_stack_async_test!(
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(
"ai-execute-pii-redaction-empty-entities",
true,
@@ -605,8 +621,12 @@ async fn ai_execute_pii_redaction_empty_rules_passes_original_chat_through() {
);
}
#[tokio::test]
async fn ai_execute_pii_redaction_unknown_sentinel_like_output_is_not_restored() {
large_stack_async_test!(
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(
"ai-execute-pii-redaction-unknown-sentinel",
true,
@@ -625,8 +645,12 @@ async fn ai_execute_pii_redaction_unknown_sentinel_like_output_is_not_restored()
);
}
#[tokio::test]
async fn ai_execute_pii_redaction_restores_executed_candidate_session_after_later_candidate_planning(
large_stack_async_test!(
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_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();
}
#[tokio::test]
async fn pii_redaction_performance_limits_do_not_forward_unredacted_body_upstream() {
large_stack_async_test!(
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_clone = Arc::clone(&provider_hits);
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();
}
#[tokio::test]
async fn ai_execute_pii_redaction_missing_encryption_key_fails_closed_before_provider() {
large_stack_async_test!(
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_clone = Arc::clone(&execution_runtime_hits);
let execution_runtime = Router::new().route(