Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ If you don’t have the tool:
- Prefer deep equals comparisons whenever possible. Perform `assert_eq!()` on entire objects, rather than individual fields.
- Avoid mutating process environment in tests; prefer passing environment-derived flags or dependencies from above.

### Spawning workspace binaries in tests (Cargo vs Buck2)

- Prefer `codex_utils_cargo_bin::cargo_bin("...")` over `assert_cmd::Command::cargo_bin(...)` or `escargot` when tests need to spawn first-party binaries.
- Under Buck2, `CARGO_BIN_EXE_*` may be project-relative (e.g. `buck-out/...`), which breaks if a test changes its working directory. `codex_utils_cargo_bin::cargo_bin` resolves to an absolute path first.
- When locating fixture files under Buck2, avoid `env!("CARGO_MANIFEST_DIR")` (Buck codegen sets it to `"."`). Prefer deriving paths from `codex_utils_cargo_bin::buck_project_root()` when needed.

### Integration tests (core)

- Prefer the utilities in `core_test_support::responses` when writing end-to-end Codex tests.
Expand Down
26 changes: 19 additions & 7 deletions codex-rs/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions codex-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ members = [
"tui",
"tui2",
"utils/absolute-path",
"utils/cargo-bin",
"utils/git",
"utils/cache",
"utils/image",
Expand Down Expand Up @@ -93,6 +94,7 @@ codex-tui = { path = "tui" }
codex-tui2 = { path = "tui2" }
codex-utils-absolute-path = { path = "utils/absolute-path" }
codex-utils-cache = { path = "utils/cache" }
codex-utils-cargo-bin = { path = "utils/cargo-bin" }
codex-utils-image = { path = "utils/image" }
codex-utils-json-to-toml = { path = "utils/json-to-toml" }
codex-utils-pty = { path = "utils/pty" }
Expand Down
1 change: 0 additions & 1 deletion codex-rs/app-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ uuid = { workspace = true, features = ["serde", "v7"] }

[dev-dependencies]
app_test_support = { workspace = true }
assert_cmd = { workspace = true }
base64 = { workspace = true }
core_test_support = { workspace = true }
mcp-types = { workspace = true }
Expand Down
2 changes: 1 addition & 1 deletion codex-rs/app-server/tests/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ path = "lib.rs"

[dependencies]
anyhow = { workspace = true }
assert_cmd = { workspace = true }
base64 = { workspace = true }
chrono = { workspace = true }
codex-app-server-protocol = { workspace = true }
codex-core = { workspace = true, features = ["test-support"] }
codex-protocol = { workspace = true }
codex-utils-cargo-bin = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
tokio = { workspace = true, features = [
Expand Down
10 changes: 2 additions & 8 deletions codex-rs/app-server/tests/common/mcp_process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use tokio::process::ChildStdin;
use tokio::process::ChildStdout;

use anyhow::Context;
use assert_cmd::prelude::*;
use codex_app_server_protocol::AddConversationListenerParams;
use codex_app_server_protocol::ArchiveConversationParams;
use codex_app_server_protocol::CancelLoginAccountParams;
Expand Down Expand Up @@ -49,7 +48,6 @@ use codex_app_server_protocol::ThreadResumeParams;
use codex_app_server_protocol::ThreadStartParams;
use codex_app_server_protocol::TurnInterruptParams;
use codex_app_server_protocol::TurnStartParams;
use std::process::Command as StdCommand;
use tokio::process::Command;

pub struct McpProcess {
Expand Down Expand Up @@ -78,12 +76,8 @@ impl McpProcess {
codex_home: &Path,
env_overrides: &[(&str, Option<&str>)],
) -> anyhow::Result<Self> {
// Use assert_cmd to locate the binary path and then switch to tokio::process::Command
let std_cmd = StdCommand::cargo_bin("codex-app-server")
.context("should find binary for codex-mcp-server")?;

let program = std_cmd.get_program().to_owned();

let program = codex_utils_cargo_bin::cargo_bin("codex-app-server")
.context("should find binary for codex-app-server")?;
let mut cmd = Command::new(program);

cmd.stdin(Stdio::piped());
Expand Down
1 change: 1 addition & 0 deletions codex-rs/apply-patch/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ tree-sitter-bash = { workspace = true }
[dev-dependencies]
assert_cmd = { workspace = true }
assert_matches = { workspace = true }
codex-utils-cargo-bin = { workspace = true }
pretty_assertions = { workspace = true }
tempfile = { workspace = true }
29 changes: 15 additions & 14 deletions codex-rs/apply-patch/tests/suite/cli.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
use assert_cmd::prelude::*;
use assert_cmd::Command;
use std::fs;
use std::process::Command;
use tempfile::tempdir;

fn apply_patch_command() -> anyhow::Result<Command> {
Ok(Command::new(codex_utils_cargo_bin::cargo_bin(
"apply_patch",
)?))
}

#[test]
fn test_apply_patch_cli_add_and_update() -> anyhow::Result<()> {
let tmp = tempdir()?;
Expand All @@ -16,8 +21,7 @@ fn test_apply_patch_cli_add_and_update() -> anyhow::Result<()> {
+hello
*** End Patch"#
);
Command::cargo_bin("apply_patch")
.expect("should find apply_patch binary")
apply_patch_command()?
.arg(add_patch)
.current_dir(tmp.path())
.assert()
Expand All @@ -34,8 +38,7 @@ fn test_apply_patch_cli_add_and_update() -> anyhow::Result<()> {
+world
*** End Patch"#
);
Command::cargo_bin("apply_patch")
.expect("should find apply_patch binary")
apply_patch_command()?
.arg(update_patch)
.current_dir(tmp.path())
.assert()
Expand All @@ -59,10 +62,9 @@ fn test_apply_patch_cli_stdin_add_and_update() -> anyhow::Result<()> {
+hello
*** End Patch"#
);
let mut cmd =
assert_cmd::Command::cargo_bin("apply_patch").expect("should find apply_patch binary");
cmd.current_dir(tmp.path());
cmd.write_stdin(add_patch)
apply_patch_command()?
.current_dir(tmp.path())
.write_stdin(add_patch)
.assert()
.success()
.stdout(format!("Success. Updated the following files:\nA {file}\n"));
Expand All @@ -77,10 +79,9 @@ fn test_apply_patch_cli_stdin_add_and_update() -> anyhow::Result<()> {
+world
*** End Patch"#
);
let mut cmd =
assert_cmd::Command::cargo_bin("apply_patch").expect("should find apply_patch binary");
cmd.current_dir(tmp.path());
cmd.write_stdin(update_patch)
apply_patch_command()?
.current_dir(tmp.path())
.write_stdin(update_patch)
.assert()
.success()
.stdout(format!("Success. Updated the following files:\nM {file}\n"));
Expand Down
24 changes: 15 additions & 9 deletions codex-rs/apply-patch/tests/suite/scenarios.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use assert_cmd::prelude::*;
use pretty_assertions::assert_eq;
use std::collections::BTreeMap;
use std::fs;
Expand All @@ -9,7 +8,8 @@ use tempfile::tempdir;

#[test]
fn test_apply_patch_scenarios() -> anyhow::Result<()> {
for scenario in fs::read_dir("tests/fixtures/scenarios")? {
let scenarios_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/scenarios");
for scenario in fs::read_dir(scenarios_dir)? {
let scenario = scenario?;
let path = scenario.path();
if path.is_dir() {
Expand All @@ -36,7 +36,7 @@ fn run_apply_patch_scenario(dir: &Path) -> anyhow::Result<()> {
// Run apply_patch in the temporary directory. We intentionally do not assert
// on the exit status here; the scenarios are specified purely in terms of
// final filesystem state, which we compare below.
Command::cargo_bin("apply_patch")?
Command::new(codex_utils_cargo_bin::cargo_bin("apply_patch")?)
.arg(patch)
.current_dir(tmp.path())
.output()?;
Expand Down Expand Up @@ -82,11 +82,15 @@ fn snapshot_dir_recursive(
continue;
};
let rel = stripped.to_path_buf();
let file_type = entry.file_type()?;
if file_type.is_dir() {

// Under Buck2, files in `__srcs` are often materialized as symlinks.
// Use `metadata()` (follows symlinks) so our fixture snapshots work
// under both Cargo and Buck2.
let metadata = fs::metadata(&path)?;
if metadata.is_dir() {
entries.insert(rel.clone(), Entry::Dir);
snapshot_dir_recursive(base, &path, entries)?;
} else if file_type.is_file() {
} else if metadata.is_file() {
let contents = fs::read(&path)?;
entries.insert(rel, Entry::File(contents));
}
Expand All @@ -98,12 +102,14 @@ fn copy_dir_recursive(src: &Path, dst: &Path) -> anyhow::Result<()> {
for entry in fs::read_dir(src)? {
let entry = entry?;
let path = entry.path();
let file_type = entry.file_type()?;
let dest_path = dst.join(entry.file_name());
if file_type.is_dir() {

// See note in `snapshot_dir_recursive` about Buck2 symlink trees.
let metadata = fs::metadata(&path)?;
if metadata.is_dir() {
fs::create_dir_all(&dest_path)?;
copy_dir_recursive(&path, &dest_path)?;
} else if file_type.is_file() {
} else if metadata.is_file() {
if let Some(parent) = dest_path.parent() {
fs::create_dir_all(parent)?;
}
Expand Down
4 changes: 2 additions & 2 deletions codex-rs/apply-patch/tests/suite/tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ use std::path::Path;
use tempfile::tempdir;

fn run_apply_patch_in_dir(dir: &Path, patch: &str) -> anyhow::Result<assert_cmd::assert::Assert> {
let mut cmd = Command::cargo_bin("apply_patch")?;
let mut cmd = Command::new(codex_utils_cargo_bin::cargo_bin("apply_patch")?);
cmd.current_dir(dir);
Ok(cmd.arg(patch).assert())
}

fn apply_patch_command(dir: &Path) -> anyhow::Result<Command> {
let mut cmd = Command::cargo_bin("apply_patch")?;
let mut cmd = Command::new(codex_utils_cargo_bin::cargo_bin("apply_patch")?);
cmd.current_dir(dir);
Ok(cmd)
}
Expand Down
1 change: 1 addition & 0 deletions codex-rs/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ codex_windows_sandbox = { package = "codex-windows-sandbox", path = "../windows-
[dev-dependencies]
assert_cmd = { workspace = true }
assert_matches = { workspace = true }
codex-utils-cargo-bin = { workspace = true }
predicates = { workspace = true }
pretty_assertions = { workspace = true }
tempfile = { workspace = true }
2 changes: 1 addition & 1 deletion codex-rs/cli/tests/execpolicy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ prefix_rule(
"#,
)?;

let output = Command::cargo_bin("codex")?
let output = Command::new(codex_utils_cargo_bin::cargo_bin("codex")?)
.env("CODEX_HOME", codex_home.path())
.args([
"execpolicy",
Expand Down
2 changes: 1 addition & 1 deletion codex-rs/cli/tests/mcp_add_remove.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use pretty_assertions::assert_eq;
use tempfile::TempDir;

fn codex_command(codex_home: &Path) -> Result<assert_cmd::Command> {
let mut cmd = assert_cmd::Command::cargo_bin("codex")?;
let mut cmd = assert_cmd::Command::new(codex_utils_cargo_bin::cargo_bin("codex")?);
cmd.env("CODEX_HOME", codex_home);
Ok(cmd)
}
Expand Down
Loading
Loading