Files
codex/codex-rs/exec-server/tests/suite/list_tools.rs
Michael Bolin 87f5b69b24 fix: ensure accept_elicitation_for_prompt_rule() test passes locally (#7832)
When I originally introduced `accept_elicitation_for_prompt_rule()` in
https://github.com/openai/codex/pull/7617, it worked for me locally
because I had run `codex-rs/exec-server/tests/suite/bash` once myself,
which had the side-effect of installing the corresponding DotSlash
artifact.

In CI, I added explicit logic to do this as part of
`.github/workflows/rust-ci.yml`, which meant the test also passed in CI,
but this logic should have been done as part of the test so that it
would work locally for devs who had not installed the DotSlash artifact
for `codex-rs/exec-server/tests/suite/bash` before. This PR updates the
test to do this (and deletes the setup logic from `rust-ci.yml`),
creating a new `DOTSLASH_CACHE` in a temp directory so that this is
handled independently for each test.

While here, also added a check to ensure that the `codex` binary has
been built prior to running the test, as we have to ensure it is
symlinked as `codex-linux-sandbox` on Linux in order for the integration
test to work on that platform.
2025-12-10 15:17:13 -08:00

79 lines
2.7 KiB
Rust

#![allow(clippy::unwrap_used, clippy::expect_used)]
use std::borrow::Cow;
use std::fs;
use std::sync::Arc;
use anyhow::Result;
use exec_server_test_support::create_transport;
use pretty_assertions::assert_eq;
use rmcp::ServiceExt;
use rmcp::model::Tool;
use rmcp::model::object;
use serde_json::json;
use tempfile::TempDir;
/// Verify the list_tools call to the MCP server returns the expected response.
#[tokio::test(flavor = "current_thread")]
async fn list_tools() -> Result<()> {
let codex_home = TempDir::new()?;
let policy_dir = codex_home.path().join("policy");
fs::create_dir_all(&policy_dir)?;
fs::write(
policy_dir.join("default.codexpolicy"),
r#"prefix_rule(pattern=["ls"], decision="prompt")"#,
)?;
let dotslash_cache_temp_dir = TempDir::new()?;
let dotslash_cache = dotslash_cache_temp_dir.path();
let transport = create_transport(codex_home.path(), dotslash_cache).await?;
let service = ().serve(transport).await?;
let tools = service.list_tools(Default::default()).await?.tools;
assert_eq!(
vec![Tool {
name: Cow::Borrowed("shell"),
title: None,
description: Some(Cow::Borrowed(
"Runs a shell command and returns its output. You MUST provide the workdir as an absolute path."
)),
input_schema: Arc::new(object(json!({
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"command": {
"description": "The bash string to execute.",
"type": "string",
},
"login": {
"description": "Launch Bash with -lc instead of -c: defaults to true.",
"nullable": true,
"type": "boolean",
},
"timeout_ms": {
"description": "The timeout for the command in milliseconds.",
"format": "uint64",
"minimum": 0,
"nullable": true,
"type": "integer",
},
"workdir": {
"description": "The working directory to execute the command in. Must be an absolute path.",
"type": "string",
},
},
"required": [
"command",
"workdir",
],
"title": "ExecParams",
"type": "object",
}))),
output_schema: None,
annotations: None,
icons: None,
meta: None
}],
tools
);
Ok(())
}