Files
codex/codex-rs/code-mode/src/remote_session_tests.rs
Channing Conger 7d8906b478 [codex] wire process-owned code mode host into core (#30142)
## Summary

- add the `code_mode_host` feature flag and select
`ProcessOwnedCodeModeSessionProvider` in `CodeModeService` when enabled
- initialize code-mode sessions lazily so a missing host reports a tool
error without failing thread startup
- resolve `codex-code-mode-host` beside the running Codex binary by
default while preserving `CODEX_CODE_MODE_HOST_PATH` as an override
- add unit and end-to-end coverage for host resolution and graceful
missing-host behavior

## Why

This wires the process-owned session client from #30112 into the core
service behind an opt-in rollout gate. Packaged Codex installations can
place the helper in the same `bin` directory as the main executable
without relying on `PATH`, while development and custom installations
can continue to override the helper path.

## Stack

- Depends on #30112
- Base branch: `cconger/process-owned-session-runtime-4-client`

## Validation

Build `codex` and `codex-code-mode-host`
`CODEX_CODE_MODE_HOST_PATH="$PWD/target/debug/codex-code-mode-host"
./target/debug/codex --enable code_mode_host`
2026-06-26 00:23:33 -07:00

104 lines
2.7 KiB
Rust

use std::io;
use std::path::PathBuf;
use std::sync::Arc;
use codex_code_mode_protocol::CodeModeSessionProvider;
use super::ProcessOwnedCodeModeSession;
use super::ProcessOwnedCodeModeSessionProvider;
use super::resolve_host_program;
use crate::NoopCodeModeSessionDelegate;
#[test]
fn provider_reuses_its_live_process_host() {
let provider = ProcessOwnedCodeModeSessionProvider::default();
let first = provider.process_host();
let second = provider.process_host();
assert!(Arc::ptr_eq(&first, &second));
}
#[test]
fn host_program_override_takes_precedence() {
assert_eq!(
resolve_host_program(
Some("custom-code-mode-host".into()),
Ok(PathBuf::from("/opt/codex/bin/codex")),
),
PathBuf::from("custom-code-mode-host")
);
}
#[test]
fn host_program_is_next_to_the_main_executable_even_when_missing() {
let executable_name = if cfg!(windows) {
"codex-code-mode-host.exe"
} else {
"codex-code-mode-host"
};
assert_eq!(
resolve_host_program(
/*override_path*/ None,
Ok(PathBuf::from("/opt/codex/bin/codex")),
),
PathBuf::from("/opt/codex/bin").join(executable_name)
);
}
#[test]
fn host_program_falls_back_to_its_name_when_main_executable_is_unknown() {
let executable_name = if cfg!(windows) {
"codex-code-mode-host.exe"
} else {
"codex-code-mode-host"
};
assert_eq!(
resolve_host_program(
/*override_path*/ None,
Err(io::Error::new(
io::ErrorKind::NotFound,
"missing executable"
)),
),
PathBuf::from(executable_name)
);
}
#[tokio::test]
async fn provider_reports_host_spawn_failure() {
let provider = ProcessOwnedCodeModeSessionProvider::with_host_program(
"codex-code-mode-host-does-not-exist".into(),
);
let error = provider
.create_session(Arc::new(NoopCodeModeSessionDelegate))
.await
.err()
.expect("session creation should fail");
assert!(error.contains("failed to spawn code-mode host"));
}
#[tokio::test]
async fn shutdown_before_open_does_not_spawn_the_host() {
let session = ProcessOwnedCodeModeSession::new();
session.shutdown().await.expect("shutdown session");
let error = session
.execute(codex_code_mode_protocol::ExecuteRequest {
tool_call_id: "call-1".to_string(),
enabled_tools: Vec::new(),
source: "text('unreachable')".to_string(),
yield_time_ms: None,
max_output_tokens: None,
})
.await
.err()
.expect("shutdown session should reject execution");
assert_eq!(error, "code mode session is shutting down");
}