tests: replace mount_sse_once_match with mount_sse_once for SSE mocking (#6640)

This commit is contained in:
pakrym-oai
2025-11-13 18:04:05 -08:00
committed by GitHub
parent 2a6e9b20df
commit 6c384eb9c6
17 changed files with 85 additions and 142 deletions

View File

@@ -85,6 +85,7 @@ If you dont have the tool:
- `ResponsesRequest` exposes helpers (`body_json`, `input`, `function_call_output`, `custom_tool_call_output`, `call_output`, `header`, `path`, `query_param`) so assertions can target structured payloads instead of manual JSON digging.
- Build SSE payloads with the provided `ev_*` constructors and the `sse(...)`.
- Prefer `wait_for_event` over `wait_for_event_with_timeout`.
- Prefer `mount_sse_once` over `mount_sse_once_match` or `mount_sse_sequence`
- Typical pattern:

View File

@@ -10,7 +10,6 @@ use wiremock::MockBuilder;
use wiremock::MockServer;
use wiremock::Respond;
use wiremock::ResponseTemplate;
use wiremock::matchers::any;
use wiremock::matchers::method;
use wiremock::matchers::path_regex;
@@ -546,13 +545,13 @@ pub async fn mount_function_call_agent_response(
ev_function_call(call_id, tool_name, arguments),
ev_completed("resp-1"),
]);
let function_call = mount_sse_once_match(server, any(), first_response).await;
let function_call = mount_sse_once(server, first_response).await;
let second_response = sse(vec![
ev_assistant_message("msg-1", "done"),
ev_completed("resp-2"),
]);
let completion = mount_sse_once_match(server, any(), second_response).await;
let completion = mount_sse_once(server, second_response).await;
FunctionCallResponseMocks {
function_call,

View File

@@ -110,12 +110,7 @@ async fn exec_cli_applies_experimental_instructions_file() {
"data: {\"type\":\"response.created\",\"response\":{}}\n\n",
"data: {\"type\":\"response.completed\",\"response\":{\"id\":\"r1\"}}\n\n"
);
let resp_mock = core_test_support::responses::mount_sse_once_match(
&server,
path("/v1/responses"),
sse.to_string(),
)
.await;
let resp_mock = core_test_support::responses::mount_sse_once(&server, sse.to_string()).await;
// Create a temporary instructions file with a unique marker we can assert
// appears in the outbound request payload.

View File

@@ -238,9 +238,7 @@ async fn resume_includes_initial_messages_and_sends_prior_items() {
// Mock server that will receive the resumed request
let server = MockServer::start().await;
let resp_mock =
responses::mount_sse_once_match(&server, path("/v1/responses"), sse_completed("resp1"))
.await;
let resp_mock = responses::mount_sse_once(&server, sse_completed("resp1")).await;
// Configure Codex to resume from our file
let model_provider = ModelProviderInfo {
@@ -381,9 +379,7 @@ async fn includes_base_instructions_override_in_request() {
skip_if_no_network!();
// Mock server
let server = MockServer::start().await;
let resp_mock =
responses::mount_sse_once_match(&server, path("/v1/responses"), sse_completed("resp1"))
.await;
let resp_mock = responses::mount_sse_once(&server, sse_completed("resp1")).await;
let model_provider = ModelProviderInfo {
base_url: Some(format!("{}/v1", server.uri())),
@@ -571,9 +567,7 @@ async fn includes_user_instructions_message_in_request() {
skip_if_no_network!();
let server = MockServer::start().await;
let resp_mock =
responses::mount_sse_once_match(&server, path("/v1/responses"), sse_completed("resp1"))
.await;
let resp_mock = responses::mount_sse_once(&server, sse_completed("resp1")).await;
let model_provider = ModelProviderInfo {
base_url: Some(format!("{}/v1", server.uri())),
@@ -631,9 +625,7 @@ async fn includes_configured_effort_in_request() -> anyhow::Result<()> {
skip_if_no_network!(Ok(()));
let server = MockServer::start().await;
let resp_mock =
responses::mount_sse_once_match(&server, path("/v1/responses"), sse_completed("resp1"))
.await;
let resp_mock = responses::mount_sse_once(&server, sse_completed("resp1")).await;
let TestCodex { codex, .. } = test_codex()
.with_model("gpt-5.1-codex")
.with_config(|config| {
@@ -672,9 +664,7 @@ async fn includes_no_effort_in_request() -> anyhow::Result<()> {
skip_if_no_network!(Ok(()));
let server = MockServer::start().await;
let resp_mock =
responses::mount_sse_once_match(&server, path("/v1/responses"), sse_completed("resp1"))
.await;
let resp_mock = responses::mount_sse_once(&server, sse_completed("resp1")).await;
let TestCodex { codex, .. } = test_codex()
.with_model("gpt-5.1-codex")
.build(&server)
@@ -711,9 +701,7 @@ async fn includes_default_reasoning_effort_in_request_when_defined_by_model_fami
skip_if_no_network!(Ok(()));
let server = MockServer::start().await;
let resp_mock =
responses::mount_sse_once_match(&server, path("/v1/responses"), sse_completed("resp1"))
.await;
let resp_mock = responses::mount_sse_once(&server, sse_completed("resp1")).await;
let TestCodex { codex, .. } = test_codex().with_model("gpt-5.1").build(&server).await?;
codex
@@ -746,9 +734,7 @@ async fn includes_default_verbosity_in_request() -> anyhow::Result<()> {
skip_if_no_network!(Ok(()));
let server = MockServer::start().await;
let resp_mock =
responses::mount_sse_once_match(&server, path("/v1/responses"), sse_completed("resp1"))
.await;
let resp_mock = responses::mount_sse_once(&server, sse_completed("resp1")).await;
let TestCodex { codex, .. } = test_codex().with_model("gpt-5.1").build(&server).await?;
codex
@@ -781,9 +767,7 @@ async fn configured_verbosity_not_sent_for_models_without_support() -> anyhow::R
skip_if_no_network!(Ok(()));
let server = MockServer::start().await;
let resp_mock =
responses::mount_sse_once_match(&server, path("/v1/responses"), sse_completed("resp1"))
.await;
let resp_mock = responses::mount_sse_once(&server, sse_completed("resp1")).await;
let TestCodex { codex, .. } = test_codex()
.with_model("gpt-5-codex")
.with_config(|config| {
@@ -821,9 +805,7 @@ async fn configured_verbosity_is_sent() -> anyhow::Result<()> {
skip_if_no_network!(Ok(()));
let server = MockServer::start().await;
let resp_mock =
responses::mount_sse_once_match(&server, path("/v1/responses"), sse_completed("resp1"))
.await;
let resp_mock = responses::mount_sse_once(&server, sse_completed("resp1")).await;
let TestCodex { codex, .. } = test_codex()
.with_model("gpt-5")
.with_config(|config| {
@@ -862,9 +844,7 @@ async fn includes_developer_instructions_message_in_request() {
skip_if_no_network!();
let server = MockServer::start().await;
let resp_mock =
responses::mount_sse_once_match(&server, path("/v1/responses"), sse_completed("resp1"))
.await;
let resp_mock = responses::mount_sse_once(&server, sse_completed("resp1")).await;
let model_provider = ModelProviderInfo {
base_url: Some(format!("{}/v1", server.uri())),

View File

@@ -18,7 +18,7 @@ use core_test_support::responses::ev_reasoning_text_delta;
use core_test_support::responses::ev_response_created;
use core_test_support::responses::ev_web_search_call_added;
use core_test_support::responses::ev_web_search_call_done;
use core_test_support::responses::mount_sse_once_match;
use core_test_support::responses::mount_sse_once;
use core_test_support::responses::sse;
use core_test_support::responses::start_mock_server;
use core_test_support::skip_if_no_network;
@@ -26,7 +26,6 @@ use core_test_support::test_codex::TestCodex;
use core_test_support::test_codex::test_codex;
use core_test_support::wait_for_event_match;
use pretty_assertions::assert_eq;
use wiremock::matchers::any;
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn user_message_item_is_emitted() -> anyhow::Result<()> {
@@ -37,7 +36,7 @@ async fn user_message_item_is_emitted() -> anyhow::Result<()> {
let TestCodex { codex, .. } = test_codex().build(&server).await?;
let first_response = sse(vec![ev_response_created("resp-1"), ev_completed("resp-1")]);
mount_sse_once_match(&server, any(), first_response).await;
mount_sse_once(&server, first_response).await;
codex
.submit(Op::UserInput {
@@ -93,7 +92,7 @@ async fn assistant_message_item_is_emitted() -> anyhow::Result<()> {
ev_assistant_message("msg-1", "all done"),
ev_completed("resp-1"),
]);
mount_sse_once_match(&server, any(), first_response).await;
mount_sse_once(&server, first_response).await;
codex
.submit(Op::UserInput {
@@ -149,7 +148,7 @@ async fn reasoning_item_is_emitted() -> anyhow::Result<()> {
reasoning_item,
ev_completed("resp-1"),
]);
mount_sse_once_match(&server, any(), first_response).await;
mount_sse_once(&server, first_response).await;
codex
.submit(Op::UserInput {
@@ -207,7 +206,7 @@ async fn web_search_item_is_emitted() -> anyhow::Result<()> {
web_search_done,
ev_completed("resp-1"),
]);
mount_sse_once_match(&server, any(), first_response).await;
mount_sse_once(&server, first_response).await;
codex
.submit(Op::UserInput {
@@ -259,7 +258,7 @@ async fn agent_message_content_delta_has_item_metadata() -> anyhow::Result<()> {
ev_assistant_message("msg-1", "streamed response"),
ev_completed("resp-1"),
]);
mount_sse_once_match(&server, any(), stream).await;
mount_sse_once(&server, stream).await;
codex
.submit(Op::UserInput {
@@ -324,7 +323,7 @@ async fn reasoning_content_delta_has_item_metadata() -> anyhow::Result<()> {
ev_reasoning_item("reasoning-1", &["step one"], &[]),
ev_completed("resp-1"),
]);
mount_sse_once_match(&server, any(), stream).await;
mount_sse_once(&server, stream).await;
codex
.submit(Op::UserInput {
@@ -381,7 +380,7 @@ async fn reasoning_raw_content_delta_respects_flag() -> anyhow::Result<()> {
ev_reasoning_item("reasoning-raw", &["complete"], &["raw detail"]),
ev_completed("resp-1"),
]);
mount_sse_once_match(&server, any(), stream).await;
mount_sse_once(&server, stream).await;
codex
.submit(Op::UserInput {

View File

@@ -42,7 +42,7 @@ async fn collect_tool_identifiers_for_model(model: &str) -> Vec<String> {
let server = MockServer::start().await;
let sse = sse_completed(model);
let resp_mock = responses::mount_sse_once_match(&server, wiremock::matchers::any(), sse).await;
let resp_mock = responses::mount_sse_once(&server, sse).await;
let model_provider = ModelProviderInfo {
base_url: Some(format!("{}/v1", server.uri())),

View File

@@ -13,7 +13,7 @@ use codex_core::shell::Shell;
use codex_core::shell::default_user_shell;
use codex_protocol::user_input::UserInput;
use core_test_support::load_sse_fixture_with_id;
use core_test_support::responses::mount_sse_once_match;
use core_test_support::responses::mount_sse_once;
use core_test_support::responses::start_mock_server;
use core_test_support::skip_if_no_network;
use core_test_support::test_codex::TestCodex;
@@ -21,7 +21,6 @@ use core_test_support::test_codex::test_codex;
use core_test_support::wait_for_event;
use std::collections::HashMap;
use tempfile::TempDir;
use wiremock::matchers::any;
fn text_user_input(text: String) -> serde_json::Value {
serde_json::json!({
@@ -70,8 +69,8 @@ async fn codex_mini_latest_tools() -> anyhow::Result<()> {
use pretty_assertions::assert_eq;
let server = start_mock_server().await;
let req1 = mount_sse_once_match(&server, any(), sse_completed("resp-1")).await;
let req2 = mount_sse_once_match(&server, any(), sse_completed("resp-2")).await;
let req1 = mount_sse_once(&server, sse_completed("resp-1")).await;
let req2 = mount_sse_once(&server, sse_completed("resp-2")).await;
let TestCodex { codex, .. } = test_codex()
.with_config(|config| {
@@ -128,8 +127,8 @@ async fn prompt_tools_are_consistent_across_requests() -> anyhow::Result<()> {
use pretty_assertions::assert_eq;
let server = start_mock_server().await;
let req1 = mount_sse_once_match(&server, any(), sse_completed("resp-1")).await;
let req2 = mount_sse_once_match(&server, any(), sse_completed("resp-2")).await;
let req1 = mount_sse_once(&server, sse_completed("resp-1")).await;
let req2 = mount_sse_once(&server, sse_completed("resp-2")).await;
let TestCodex { codex, config, .. } = test_codex()
.with_config(|config| {
@@ -247,8 +246,8 @@ async fn prefixes_context_and_instructions_once_and_consistently_across_requests
use pretty_assertions::assert_eq;
let server = start_mock_server().await;
let req1 = mount_sse_once_match(&server, any(), sse_completed("resp-1")).await;
let req2 = mount_sse_once_match(&server, any(), sse_completed("resp-2")).await;
let req1 = mount_sse_once(&server, sse_completed("resp-1")).await;
let req2 = mount_sse_once(&server, sse_completed("resp-2")).await;
let TestCodex { codex, config, .. } = test_codex()
.with_config(|config| {
@@ -328,8 +327,8 @@ async fn overrides_turn_context_but_keeps_cached_prefix_and_key_constant() -> an
use pretty_assertions::assert_eq;
let server = start_mock_server().await;
let req1 = mount_sse_once_match(&server, any(), sse_completed("resp-1")).await;
let req2 = mount_sse_once_match(&server, any(), sse_completed("resp-2")).await;
let req1 = mount_sse_once(&server, sse_completed("resp-1")).await;
let req2 = mount_sse_once(&server, sse_completed("resp-2")).await;
let TestCodex { codex, .. } = test_codex()
.with_config(|config| {
@@ -427,8 +426,8 @@ async fn per_turn_overrides_keep_cached_prefix_and_key_constant() -> anyhow::Res
use pretty_assertions::assert_eq;
let server = start_mock_server().await;
let req1 = mount_sse_once_match(&server, any(), sse_completed("resp-1")).await;
let req2 = mount_sse_once_match(&server, any(), sse_completed("resp-2")).await;
let req1 = mount_sse_once(&server, sse_completed("resp-1")).await;
let req2 = mount_sse_once(&server, sse_completed("resp-2")).await;
let TestCodex { codex, .. } = test_codex()
.with_config(|config| {
@@ -523,8 +522,8 @@ async fn send_user_turn_with_no_changes_does_not_send_environment_context() -> a
use pretty_assertions::assert_eq;
let server = start_mock_server().await;
let req1 = mount_sse_once_match(&server, any(), sse_completed("resp-1")).await;
let req2 = mount_sse_once_match(&server, any(), sse_completed("resp-2")).await;
let req1 = mount_sse_once(&server, sse_completed("resp-1")).await;
let req2 = mount_sse_once(&server, sse_completed("resp-2")).await;
let TestCodex { codex, config, .. } = test_codex()
.with_config(|config| {
@@ -611,8 +610,8 @@ async fn send_user_turn_with_changes_sends_environment_context() -> anyhow::Resu
let server = start_mock_server().await;
let req1 = mount_sse_once_match(&server, any(), sse_completed("resp-1")).await;
let req2 = mount_sse_once_match(&server, any(), sse_completed("resp-2")).await;
let req1 = mount_sse_once(&server, sse_completed("resp-1")).await;
let req2 = mount_sse_once(&server, sse_completed("resp-2")).await;
let TestCodex { codex, config, .. } = test_codex()
.with_config(|config| {
config.user_instructions = Some("be consistent and helpful".to_string());

View File

@@ -6,14 +6,13 @@ use core_test_support::responses::ev_assistant_message;
use core_test_support::responses::ev_completed;
use core_test_support::responses::ev_reasoning_item;
use core_test_support::responses::ev_response_created;
use core_test_support::responses::mount_sse_once_match;
use core_test_support::responses::mount_sse_once;
use core_test_support::responses::sse;
use core_test_support::responses::start_mock_server;
use core_test_support::skip_if_no_network;
use core_test_support::test_codex::test_codex;
use core_test_support::wait_for_event;
use std::sync::Arc;
use wiremock::matchers::any;
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn resume_includes_initial_messages_from_rollout_events() -> Result<()> {
@@ -31,7 +30,7 @@ async fn resume_includes_initial_messages_from_rollout_events() -> Result<()> {
ev_assistant_message("msg-1", "Completed first turn"),
ev_completed("resp-initial"),
]);
mount_sse_once_match(&server, any(), initial_sse).await;
mount_sse_once(&server, initial_sse).await;
codex
.submit(Op::UserInput {
@@ -83,7 +82,7 @@ async fn resume_includes_initial_messages_from_reasoning_events() -> Result<()>
ev_assistant_message("msg-1", "Completed reasoning turn"),
ev_completed("resp-initial"),
]);
mount_sse_once_match(&server, any(), initial_sse).await;
mount_sse_once(&server, initial_sse).await;
codex
.submit(Op::UserInput {

View File

@@ -21,7 +21,7 @@ use codex_core::protocol::SandboxPolicy;
use codex_protocol::config_types::ReasoningSummary;
use codex_protocol::user_input::UserInput;
use core_test_support::responses;
use core_test_support::responses::mount_sse_once_match;
use core_test_support::responses::mount_sse_once;
use core_test_support::skip_if_no_network;
use core_test_support::test_codex::test_codex;
use core_test_support::wait_for_event;
@@ -36,7 +36,6 @@ use tokio::process::Child;
use tokio::process::Command;
use tokio::time::Instant;
use tokio::time::sleep;
use wiremock::matchers::any;
static OPENAI_PNG: &str = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAD0AAAA9CAYAAAAeYmHpAAAE6klEQVR4Aeyau44UVxCGx1fZsmRLlm3Zoe0XcGQ5cUiCCIgJeS9CHgAhMkISQnIuGQgJEkBcxLW+nqnZ6uqqc+nuWRC7q/P3qetf9e+MtOwyX25O4Nep6JPyop++0qev9HrfgZ+F6r2DuB/vHOrt/UIkqdDHYvujOW6fO7h/CNEI+a5jc+pBR8uy0jVFsziYu5HtfSUk+Io34q921hLNctFSX0gwww+S8wce8K1LfCU+cYW4888aov8NxqvQILUPPReLOrm6zyLxa4i+6VZuFbJo8d1MOHZm+7VUtB/aIvhPWc/3SWg49JcwFLlHxuXKjtyloo+YNhuW3VS+WPBuUEMvCFKjEDVgFBQHXrnazpqiSxNZCkQ1kYiozsbm9Oz7l4i2Il7vGccGNWAc3XosDrZe/9P3ZnMmzHNEQw4smf8RQ87XEAMsC7Az0Au+dgXerfH4+sHvEc0SYGic8WBBUGqFH2gN7yDrazy7m2pbRTeRmU3+MjZmr1h6LJgPbGy23SI6GlYT0brQ71IY8Us4PNQCm+zepSbaD2BY9xCaAsD9IIj/IzFmKMSdHHonwdZATbTnYREf6/VZGER98N9yCWIvXQwXDoDdhZJoT8jwLnJXDB9w4Sb3e6nK5ndzlkTLnP3JBu4LKkbrYrU69gCVceV0JvpyuW1xlsUVngzhwMetn/XamtTORF9IO5YnWNiyeF9zCAfqR3fUW+vZZKLtgP+ts8BmQRBREAdRDhH3o8QuRh/YucNFz2BEjxbRN6LGzphfKmvP6v6QhqIQyZ8XNJ0W0X83MR1PEcJBNO2KC2Z1TW/v244scp9FwRViZxIOBF0Lctk7ZVSavdLvRlV1hz/ysUi9sr8CIcB3nvWBwA93ykTz18eAYxQ6N/K2DkPA1lv3iXCwmDUT7YkjIby9siXueIJj9H+pzSqJ9oIuJWTUgSSt4WO7o/9GGg0viR4VinNRUDoIj34xoCd6pxD3aK3zfdbnx5v1J3ZNNEJsE0sBG7N27ReDrJc4sFxz7dI/ZAbOmmiKvHBitQXpAdR6+F7v+/ol/tOouUV01EeMZQF2BoQDn6dP4XNr+j9GZEtEK1/L8pFw7bd3a53tsTa7WD+054jOFmPg1XBKPQgnqFfmFcy32ZRvjmiIIQTYFvyDxQ8nH8WIwwGwlyDjDznnilYyFr6njrlZwsKkBpO59A7OwgdzPEWRm+G+oeb7IfyNuzjEEVLrOVxJsxvxwF8kmCM6I2QYmJunz4u4TrADpfl7mlbRTWQ7VmrBzh3+C9f6Grc3YoGN9dg/SXFthpRsT6vobfXRs2VBlgBHXVMLHjDNbIZv1sZ9+X3hB09cXdH1JKViyG0+W9bWZDa/r2f9zAFR71sTzGpMSWz2iI4YssWjWo3REy1MDGjdwe5e0dFSiAC1JakBvu4/CUS8Eh6dqHdU0Or0ioY3W5ClSqDXAy7/6SRfgw8vt4I+tbvvNtFT2kVDhY5+IGb1rCqYaXNF08vSALsXCPmt0kQNqJT1p5eI1mkIV/BxCY1z85lOzeFbPBQHURkkPTlwTYK9gTVE25l84IbFFN+YJDHjdpn0gq6mrHht0dkcjbM4UL9283O5p77GN+SPW/QwVB4IUYg7Or+Kp7naR6qktP98LNF2UxWo9yObPIT9KYg+hK4i56no4rfnM0qeyFf6AwAAAP//trwR3wAAAAZJREFUAwBZ0sR75itw5gAAAABJRU5ErkJggg==";
@@ -51,9 +50,8 @@ async fn stdio_server_round_trip() -> anyhow::Result<()> {
let server_name = "rmcp";
let tool_name = format!("mcp__{server_name}__echo");
mount_sse_once_match(
mount_sse_once(
&server,
any(),
responses::sse(vec![
responses::ev_response_created("resp-1"),
responses::ev_function_call(call_id, &tool_name, "{\"message\":\"ping\"}"),
@@ -61,9 +59,8 @@ async fn stdio_server_round_trip() -> anyhow::Result<()> {
]),
)
.await;
mount_sse_once_match(
mount_sse_once(
&server,
any(),
responses::sse(vec![
responses::ev_assistant_message("msg-1", "rmcp echo tool completed successfully."),
responses::ev_completed("resp-2"),
@@ -190,9 +187,8 @@ async fn stdio_image_responses_round_trip() -> anyhow::Result<()> {
let tool_name = format!("mcp__{server_name}__image");
// First stream: model decides to call the image tool.
mount_sse_once_match(
mount_sse_once(
&server,
any(),
responses::sse(vec![
responses::ev_response_created("resp-1"),
responses::ev_function_call(call_id, &tool_name, "{}"),
@@ -201,9 +197,8 @@ async fn stdio_image_responses_round_trip() -> anyhow::Result<()> {
)
.await;
// Second stream: after tool execution, assistant emits a message and completes.
let final_mock = mount_sse_once_match(
let final_mock = mount_sse_once(
&server,
any(),
responses::sse(vec![
responses::ev_assistant_message("msg-1", "rmcp image tool completed successfully."),
responses::ev_completed("resp-2"),
@@ -531,9 +526,8 @@ async fn stdio_server_propagates_whitelisted_env_vars() -> anyhow::Result<()> {
let server_name = "rmcp_whitelist";
let tool_name = format!("mcp__{server_name}__echo");
mount_sse_once_match(
mount_sse_once(
&server,
any(),
responses::sse(vec![
responses::ev_response_created("resp-1"),
responses::ev_function_call(call_id, &tool_name, "{\"message\":\"ping\"}"),
@@ -541,9 +535,8 @@ async fn stdio_server_propagates_whitelisted_env_vars() -> anyhow::Result<()> {
]),
)
.await;
mount_sse_once_match(
mount_sse_once(
&server,
any(),
responses::sse(vec![
responses::ev_assistant_message("msg-1", "rmcp echo tool completed successfully."),
responses::ev_completed("resp-2"),
@@ -666,9 +659,8 @@ async fn streamable_http_tool_call_round_trip() -> anyhow::Result<()> {
let server_name = "rmcp_http";
let tool_name = format!("mcp__{server_name}__echo");
mount_sse_once_match(
mount_sse_once(
&server,
any(),
responses::sse(vec![
responses::ev_response_created("resp-1"),
responses::ev_function_call(call_id, &tool_name, "{\"message\":\"ping\"}"),
@@ -676,9 +668,8 @@ async fn streamable_http_tool_call_round_trip() -> anyhow::Result<()> {
]),
)
.await;
mount_sse_once_match(
mount_sse_once(
&server,
any(),
responses::sse(vec![
responses::ev_assistant_message(
"msg-1",
@@ -834,9 +825,8 @@ async fn streamable_http_with_oauth_round_trip() -> anyhow::Result<()> {
let server_name = "rmcp_http_oauth";
let tool_name = format!("mcp__{server_name}__echo");
mount_sse_once_match(
mount_sse_once(
&server,
any(),
responses::sse(vec![
responses::ev_response_created("resp-1"),
responses::ev_function_call(call_id, &tool_name, "{\"message\":\"ping\"}"),
@@ -844,9 +834,8 @@ async fn streamable_http_with_oauth_round_trip() -> anyhow::Result<()> {
]),
)
.await;
mount_sse_once_match(
mount_sse_once(
&server,
any(),
responses::sse(vec![
responses::ev_assistant_message(
"msg-1",

View File

@@ -29,7 +29,6 @@ use core_test_support::test_codex::test_codex;
use core_test_support::wait_for_event;
use serde_json::Value;
use serde_json::json;
use wiremock::matchers::any;
fn call_output(req: &ResponsesRequest, call_id: &str) -> (String, Option<bool>) {
let raw = req.function_call_output(call_id);
@@ -73,13 +72,13 @@ async fn shell_tool_executes_command_and_streams_output() -> anyhow::Result<()>
ev_local_shell_call(call_id, "completed", command),
ev_completed("resp-1"),
]);
responses::mount_sse_once_match(&server, any(), first_response).await;
responses::mount_sse_once(&server, first_response).await;
let second_response = sse(vec![
ev_assistant_message("msg-1", "all done"),
ev_completed("resp-2"),
]);
let second_mock = responses::mount_sse_once_match(&server, any(), second_response).await;
let second_mock = responses::mount_sse_once(&server, second_response).await;
let session_model = session_configured.model.clone();
@@ -139,13 +138,13 @@ async fn update_plan_tool_emits_plan_update_event() -> anyhow::Result<()> {
ev_function_call(call_id, "update_plan", &plan_args),
ev_completed("resp-1"),
]);
responses::mount_sse_once_match(&server, any(), first_response).await;
responses::mount_sse_once(&server, first_response).await;
let second_response = sse(vec![
ev_assistant_message("msg-1", "plan acknowledged"),
ev_completed("resp-2"),
]);
let second_mock = responses::mount_sse_once_match(&server, any(), second_response).await;
let second_mock = responses::mount_sse_once(&server, second_response).await;
let session_model = session_configured.model.clone();
@@ -215,13 +214,13 @@ async fn update_plan_tool_rejects_malformed_payload() -> anyhow::Result<()> {
ev_function_call(call_id, "update_plan", &invalid_args),
ev_completed("resp-1"),
]);
responses::mount_sse_once_match(&server, any(), first_response).await;
responses::mount_sse_once(&server, first_response).await;
let second_response = sse(vec![
ev_assistant_message("msg-1", "malformed plan payload"),
ev_completed("resp-2"),
]);
let second_mock = responses::mount_sse_once_match(&server, any(), second_response).await;
let second_mock = responses::mount_sse_once(&server, second_response).await;
let session_model = session_configured.model.clone();
@@ -303,13 +302,13 @@ async fn apply_patch_tool_executes_and_emits_patch_events() -> anyhow::Result<()
ev_apply_patch_function_call(call_id, &patch_content),
ev_completed("resp-1"),
]);
responses::mount_sse_once_match(&server, any(), first_response).await;
responses::mount_sse_once(&server, first_response).await;
let second_response = sse(vec![
ev_assistant_message("msg-1", "patch complete"),
ev_completed("resp-2"),
]);
let second_mock = responses::mount_sse_once_match(&server, any(), second_response).await;
let second_mock = responses::mount_sse_once(&server, second_response).await;
let session_model = session_configured.model.clone();
@@ -399,13 +398,13 @@ async fn apply_patch_reports_parse_diagnostics() -> anyhow::Result<()> {
ev_apply_patch_function_call(call_id, patch_content),
ev_completed("resp-1"),
]);
responses::mount_sse_once_match(&server, any(), first_response).await;
responses::mount_sse_once(&server, first_response).await;
let second_response = sse(vec![
ev_assistant_message("msg-1", "failed"),
ev_completed("resp-2"),
]);
let second_mock = responses::mount_sse_once_match(&server, any(), second_response).await;
let second_mock = responses::mount_sse_once(&server, second_response).await;
let session_model = session_configured.model.clone();

View File

@@ -472,8 +472,7 @@ time.sleep(60)
let start = Instant::now();
let output_str = tokio::time::timeout(Duration::from_secs(10), async {
submit_turn(
&test,
test.submit_turn_with_policies(
"run a command with a detached grandchild",
AskForApproval::Never,
SandboxPolicy::DangerFullAccess,

View File

@@ -20,7 +20,6 @@ use core_test_support::responses::ev_completed;
use core_test_support::responses::ev_function_call;
use core_test_support::responses::ev_response_created;
use core_test_support::responses::mount_sse_once;
use core_test_support::responses::mount_sse_once_match;
use core_test_support::responses::mount_sse_sequence;
use core_test_support::responses::sse;
use core_test_support::responses::start_mock_server;
@@ -33,7 +32,6 @@ use serde_json::Value;
use serde_json::json;
use std::collections::HashMap;
use std::time::Duration;
use wiremock::matchers::any;
// Verifies byte-truncation formatting for function error output (RespondToModel errors)
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
@@ -140,9 +138,8 @@ async fn tool_call_output_exceeds_limit_truncated_for_model() -> Result<()> {
]),
)
.await;
let mock2 = mount_sse_once_match(
let mock2 = mount_sse_once(
&server,
any(),
sse(vec![
responses::ev_assistant_message("msg-1", "done"),
responses::ev_completed("resp-2"),
@@ -222,9 +219,8 @@ async fn tool_call_output_truncated_only_once() -> Result<()> {
})
};
mount_sse_once_match(
mount_sse_once(
&server,
any(),
sse(vec![
responses::ev_response_created("resp-1"),
responses::ev_function_call(call_id, "shell", &serde_json::to_string(&args)?),
@@ -232,9 +228,8 @@ async fn tool_call_output_truncated_only_once() -> Result<()> {
]),
)
.await;
let mock2 = mount_sse_once_match(
let mock2 = mount_sse_once(
&server,
any(),
sse(vec![
responses::ev_assistant_message("msg-1", "done"),
responses::ev_completed("resp-2"),
@@ -277,9 +272,8 @@ async fn mcp_tool_call_output_exceeds_limit_truncated_for_model() -> Result<()>
let large_msg = "long-message-with-newlines-".repeat(600);
let args_json = serde_json::json!({ "message": large_msg });
mount_sse_once_match(
mount_sse_once(
&server,
any(),
sse(vec![
responses::ev_response_created("resp-1"),
responses::ev_function_call(call_id, &tool_name, &args_json.to_string()),
@@ -287,9 +281,8 @@ async fn mcp_tool_call_output_exceeds_limit_truncated_for_model() -> Result<()>
]),
)
.await;
let mock2 = mount_sse_once_match(
let mock2 = mount_sse_once(
&server,
any(),
sse(vec![
responses::ev_assistant_message("msg-1", "rmcp echo tool completed."),
responses::ev_completed("resp-2"),
@@ -373,9 +366,8 @@ async fn mcp_image_output_preserves_image_and_no_text_summary() -> Result<()> {
let server_name = "rmcp";
let tool_name = format!("mcp__{server_name}__image");
mount_sse_once_match(
mount_sse_once(
&server,
any(),
sse(vec![
ev_response_created("resp-1"),
ev_function_call(call_id, &tool_name, "{}"),
@@ -383,9 +375,8 @@ async fn mcp_image_output_preserves_image_and_no_text_summary() -> Result<()> {
]),
)
.await;
let final_mock = mount_sse_once_match(
let final_mock = mount_sse_once(
&server,
any(),
sse(vec![
ev_assistant_message("msg-1", "done"),
ev_completed("resp-2"),

View File

@@ -15,7 +15,6 @@ use pretty_assertions::assert_eq;
use serde_json::Value;
use serde_json::json;
use tempfile::TempDir;
use wiremock::matchers::any;
use responses::ev_assistant_message;
use responses::ev_completed;
@@ -35,7 +34,7 @@ async fn summarize_context_three_requests_and_instructions() -> anyhow::Result<(
let sse1 = sse(vec![ev_assistant_message("m1", "Done"), ev_completed("r1")]);
responses::mount_sse_once_match(&server, any(), sse1).await;
responses::mount_sse_once(&server, sse1).await;
let notify_dir = TempDir::new()?;
// write a script to the notify that touches a file next to it

View File

@@ -15,7 +15,7 @@ use core_test_support::responses::ev_assistant_message;
use core_test_support::responses::ev_completed;
use core_test_support::responses::ev_function_call;
use core_test_support::responses::ev_response_created;
use core_test_support::responses::mount_sse_once_match;
use core_test_support::responses::mount_sse_once;
use core_test_support::responses::sse;
use core_test_support::responses::start_mock_server;
use core_test_support::skip_if_no_network;
@@ -25,7 +25,6 @@ use core_test_support::wait_for_event_match;
use regex_lite::escape;
use std::path::PathBuf;
use tempfile::TempDir;
use wiremock::matchers::any;
#[tokio::test]
async fn user_shell_cmd_ls_and_cat_in_temp_dir() {
@@ -293,9 +292,8 @@ async fn user_shell_command_is_truncated_only_once() -> anyhow::Result<()> {
})
};
mount_sse_once_match(
mount_sse_once(
&server,
any(),
sse(vec![
ev_response_created("resp-1"),
ev_function_call(call_id, "shell", &serde_json::to_string(&args)?),
@@ -303,9 +301,8 @@ async fn user_shell_command_is_truncated_only_once() -> anyhow::Result<()> {
]),
)
.await;
let mock2 = mount_sse_once_match(
let mock2 = mount_sse_once(
&server,
any(),
sse(vec![
ev_assistant_message("msg-1", "done"),
ev_completed("resp-2"),

View File

@@ -24,7 +24,6 @@ use image::ImageBuffer;
use image::Rgba;
use image::load_from_memory;
use serde_json::Value;
use wiremock::matchers::any;
fn find_image_message(body: &Value) -> Option<&Value> {
body.get("input")
@@ -71,7 +70,7 @@ async fn user_turn_with_local_image_attaches_image() -> anyhow::Result<()> {
ev_assistant_message("msg-1", "done"),
ev_completed("resp-1"),
]);
let mock = responses::mount_sse_once_match(&server, any(), response).await;
let mock = responses::mount_sse_once(&server, response).await;
let session_model = session_configured.model.clone();
@@ -156,13 +155,13 @@ async fn view_image_tool_attaches_local_image() -> anyhow::Result<()> {
ev_function_call(call_id, "view_image", &arguments),
ev_completed("resp-1"),
]);
responses::mount_sse_once_match(&server, any(), first_response).await;
responses::mount_sse_once(&server, first_response).await;
let second_response = sse(vec![
ev_assistant_message("msg-1", "done"),
ev_completed("resp-2"),
]);
let mock = responses::mount_sse_once_match(&server, any(), second_response).await;
let mock = responses::mount_sse_once(&server, second_response).await;
let session_model = session_configured.model.clone();
@@ -266,13 +265,13 @@ async fn view_image_tool_errors_when_path_is_directory() -> anyhow::Result<()> {
ev_function_call(call_id, "view_image", &arguments),
ev_completed("resp-1"),
]);
responses::mount_sse_once_match(&server, any(), first_response).await;
responses::mount_sse_once(&server, first_response).await;
let second_response = sse(vec![
ev_assistant_message("msg-1", "done"),
ev_completed("resp-2"),
]);
let mock = responses::mount_sse_once_match(&server, any(), second_response).await;
let mock = responses::mount_sse_once(&server, second_response).await;
let session_model = session_configured.model.clone();
@@ -338,13 +337,13 @@ async fn view_image_tool_placeholder_for_non_image_files() -> anyhow::Result<()>
ev_function_call(call_id, "view_image", &arguments),
ev_completed("resp-1"),
]);
responses::mount_sse_once_match(&server, any(), first_response).await;
responses::mount_sse_once(&server, first_response).await;
let second_response = sse(vec![
ev_assistant_message("msg-1", "done"),
ev_completed("resp-2"),
]);
let mock = responses::mount_sse_once_match(&server, any(), second_response).await;
let mock = responses::mount_sse_once(&server, second_response).await;
let session_model = session_configured.model.clone();
@@ -429,13 +428,13 @@ async fn view_image_tool_errors_when_file_missing() -> anyhow::Result<()> {
ev_function_call(call_id, "view_image", &arguments),
ev_completed("resp-1"),
]);
responses::mount_sse_once_match(&server, any(), first_response).await;
responses::mount_sse_once(&server, first_response).await;
let second_response = sse(vec![
ev_assistant_message("msg-1", "done"),
ev_completed("resp-2"),
]);
let mock = responses::mount_sse_once_match(&server, any(), second_response).await;
let mock = responses::mount_sse_once(&server, second_response).await;
let session_model = session_configured.model.clone();

View File

@@ -4,7 +4,6 @@
use core_test_support::responses;
use core_test_support::test_codex_exec::test_codex_exec;
use serde_json::Value;
use wiremock::matchers::any;
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn exec_includes_output_schema_in_request() -> anyhow::Result<()> {
@@ -28,7 +27,7 @@ async fn exec_includes_output_schema_in_request() -> anyhow::Result<()> {
responses::ev_assistant_message("m1", "fixture hello"),
responses::ev_completed("resp1"),
]);
let response_mock = responses::mount_sse_once_match(&server, any(), body).await;
let response_mock = responses::mount_sse_once(&server, body).await;
test.cmd_with_server(&server)
.arg("--skip-git-repo-check")

View File

@@ -3,7 +3,6 @@
use core_test_support::responses;
use core_test_support::test_codex_exec::test_codex_exec;
use wiremock::matchers::any;
/// Verify that when the server reports an error, `codex-exec` exits with a
/// non-zero status code so automation can detect failures.
@@ -21,7 +20,7 @@ async fn exits_non_zero_when_server_reports_error() -> anyhow::Result<()> {
"error": {"code": "rate_limit_exceeded", "message": "synthetic server error"}
}
})]);
responses::mount_sse_once_match(&server, any(), body).await;
responses::mount_sse_once(&server, body).await;
test.cmd_with_server(&server)
.arg("--skip-git-repo-check")