mirror of
https://github.com/openai/codex.git
synced 2026-10-21 17:48:44 +00:00
## Why Keep the TestAppServer builder API change reviewable by moving the repository-wide caller migration into a mechanical follow-up. ## What - replace TestAppServer constructor callsites with equivalent builder chains - preserve each caller's automatic-environment, args, program, env, managed-config, plugin-startup, and JSON-logging behavior - make no TestAppServer implementation changes ## Validation - cargo check -p codex-app-server --tests ## Cleanup stack 1. [#31425 test: add TestAppServer builder](https://github.com/openai/codex/pull/31425) 2. [#31451 test: migrate TestAppServer callers to builder](https://github.com/openai/codex/pull/31451) 3. [#31452 test: remove TestAppServer constructors](https://github.com/openai/codex/pull/31452)
133 lines
4.2 KiB
Rust
133 lines
4.2 KiB
Rust
use anyhow::Context;
|
|
use anyhow::Result;
|
|
use app_test_support::TestAppServer;
|
|
use app_test_support::to_response;
|
|
use app_test_support::write_mock_responses_config_toml;
|
|
use codex_app_server_protocol::JSONRPCResponse;
|
|
use codex_app_server_protocol::RequestId;
|
|
use codex_app_server_protocol::ThreadStartParams;
|
|
use codex_app_server_protocol::ThreadStartResponse;
|
|
use codex_app_server_protocol::TurnStartParams;
|
|
use codex_app_server_protocol::UserInput as V2UserInput;
|
|
use core_test_support::responses;
|
|
use pretty_assertions::assert_eq;
|
|
use std::collections::BTreeMap;
|
|
use std::time::Duration;
|
|
use tempfile::TempDir;
|
|
use tokio::time::timeout;
|
|
|
|
const DEFAULT_READ_TIMEOUT: Duration = Duration::from_secs(10);
|
|
|
|
#[tokio::test]
|
|
async fn thread_start_with_auto_env_exposes_fixture_cwd_to_model() -> Result<()> {
|
|
let server = responses::start_mock_server().await;
|
|
let response_mock = responses::mount_sse_once(
|
|
&server,
|
|
responses::sse(vec![
|
|
responses::ev_response_created("resp-1"),
|
|
responses::ev_assistant_message("msg-1", "done"),
|
|
responses::ev_completed("resp-1"),
|
|
]),
|
|
)
|
|
.await;
|
|
let codex_home = TempDir::new()?;
|
|
write_mock_responses_config_toml(
|
|
codex_home.path(),
|
|
&server.uri(),
|
|
&BTreeMap::new(),
|
|
/*auto_compact_limit*/ 100_000,
|
|
/*requires_openai_auth*/ None,
|
|
"mock_provider",
|
|
"compact",
|
|
)?;
|
|
|
|
let mut mcp = TestAppServer::builder()
|
|
.with_codex_home(codex_home.path())
|
|
.build()
|
|
.await?;
|
|
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
|
let expected_environment = mcp.auto_env_params()?;
|
|
|
|
let err = mcp
|
|
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
|
environments: Some(Vec::new()),
|
|
..Default::default()
|
|
})
|
|
.await
|
|
.expect_err("the auto-env helper should reject caller-supplied environments");
|
|
assert_eq!(
|
|
err.to_string(),
|
|
"send_thread_start_request_with_auto_env requires params.environments to be omitted"
|
|
);
|
|
|
|
let request_id = mcp
|
|
.send_thread_start_request_with_auto_env(ThreadStartParams::default())
|
|
.await?;
|
|
let response: JSONRPCResponse = timeout(
|
|
DEFAULT_READ_TIMEOUT,
|
|
mcp.read_stream_until_response_message(RequestId::Integer(request_id)),
|
|
)
|
|
.await??;
|
|
let ThreadStartResponse { thread, .. } = to_response::<ThreadStartResponse>(response)?;
|
|
|
|
let request_id = mcp
|
|
.send_turn_start_request(TurnStartParams {
|
|
thread_id: thread.id,
|
|
input: vec![V2UserInput::Text {
|
|
text: "report the current directory".to_string(),
|
|
text_elements: Vec::new(),
|
|
}],
|
|
..Default::default()
|
|
})
|
|
.await?;
|
|
let _: JSONRPCResponse = timeout(
|
|
DEFAULT_READ_TIMEOUT,
|
|
mcp.read_stream_until_response_message(RequestId::Integer(request_id)),
|
|
)
|
|
.await??;
|
|
|
|
timeout(
|
|
DEFAULT_READ_TIMEOUT,
|
|
mcp.read_stream_until_notification_message("turn/completed"),
|
|
)
|
|
.await??;
|
|
|
|
let environment_context = response_mock
|
|
.single_request()
|
|
.message_input_texts("user")
|
|
.into_iter()
|
|
.find(|text| text.starts_with("<environment_context>"))
|
|
.context("environment context should be model visible")?;
|
|
let model_cwd = environment_context
|
|
.lines()
|
|
.find(|line| line.trim_start().starts_with("<cwd>"))
|
|
.map(str::trim);
|
|
let expected_cwd = format!("<cwd>{}</cwd>", expected_environment.cwd);
|
|
assert_eq!(model_cwd, Some(expected_cwd.as_str()));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn auto_env_rejects_explicit_environment_config() -> Result<()> {
|
|
let codex_home = TempDir::new()?;
|
|
std::fs::write(codex_home.path().join("environments.toml"), "")?;
|
|
|
|
let result = TestAppServer::builder()
|
|
.with_codex_home(codex_home.path())
|
|
.build()
|
|
.await;
|
|
let Err(err) = result else {
|
|
anyhow::bail!("auto-env construction unexpectedly succeeded");
|
|
};
|
|
assert_eq!(
|
|
err.to_string(),
|
|
format!(
|
|
"automatic environment cannot be used when {} exists",
|
|
codex_home.path().join("environments.toml").display()
|
|
)
|
|
);
|
|
|
|
Ok(())
|
|
}
|