Codex Handbook
code-mode/src/service_contract_tests.rs 634 lines
use std::collections::HashMap;use std::sync::Arc;use std::sync::atomic::AtomicBool;use std::sync::atomic::AtomicU64;use std::sync::atomic::Ordering;use std::time::Duration;use codex_protocol::ToolName;use pretty_assertions::assert_eq;use tokio::sync::Notify;use tokio::sync::mpsc;use tokio::sync::oneshot;use tokio_util::sync::CancellationToken;use super::*;use crate::CodeModeToolKind;use crate::ToolDefinition;#[derive(Debug, PartialEq)]enum DelegateEvent {    NotificationStarted,    NotificationCancelled,    ToolStarted,    ToolCancelled,    CellClosed(CellId),}struct BlockingDelegate {    events_tx: mpsc::UnboundedSender<DelegateEvent>,    notification_finished: AtomicBool,    tool_finished: AtomicBool,}struct HeldNotificationDelegate {    events_tx: mpsc::UnboundedSender<DelegateEvent>,    notification_release: Notify,}impl HeldNotificationDelegate {    fn new() -> (Arc<Self>, mpsc::UnboundedReceiver<DelegateEvent>) {        let (events_tx, events_rx) = mpsc::unbounded_channel();        (            Arc::new(Self {                events_tx,                notification_release: Notify::new(),            }),            events_rx,        )    }    fn release_notification(&self) {        self.notification_release.notify_one();    }}impl CodeModeSessionDelegate for HeldNotificationDelegate {    fn invoke_tool<'a>(        &'a self,        _invocation: CodeModeNestedToolCall,        cancellation_token: CancellationToken,    ) -> ToolInvocationFuture<'a> {        Box::pin(async move {            cancellation_token.cancelled().await;            Err("cancelled".to_string())        })    }    fn notify<'a>(        &'a self,        _call_id: String,        _cell_id: CellId,        _text: String,        cancellation_token: CancellationToken,    ) -> NotificationFuture<'a> {        Box::pin(async move {            let _ = self.events_tx.send(DelegateEvent::NotificationStarted);            cancellation_token.cancelled().await;            let _ = self.events_tx.send(DelegateEvent::NotificationCancelled);            self.notification_release.notified().await;            Ok(())        })    }    fn cell_closed(&self, cell_id: &CellId) {        let _ = self            .events_tx            .send(DelegateEvent::CellClosed(cell_id.clone()));    }}struct CellControlHarness {    event_tx: mpsc::UnboundedSender<RuntimeEvent>,    control_tx: mpsc::UnboundedSender<CellControlCommand>,    initial_response_rx: oneshot::Receiver<Result<RuntimeResponse, String>>,    task: tokio::task::JoinHandle<()>,    _runtime_event_rx: mpsc::UnboundedReceiver<RuntimeEvent>,}fn spawn_cell_control_harness(    initial_yield_time_ms: Option<u64>,    delegate: Arc<dyn CodeModeSessionDelegate>,) -> CellControlHarness {    let (event_tx, event_rx) = mpsc::unbounded_channel();    let (control_tx, control_rx) = mpsc::unbounded_channel();    let (initial_response_tx, initial_response_rx) = oneshot::channel();    let (runtime_event_tx, runtime_event_rx) = mpsc::unbounded_channel();    let (runtime_tx, runtime_control_tx, runtime_terminate_handle) = spawn_runtime(        HashMap::new(),        execute_request("await new Promise(() => {});"),        runtime_event_tx,        PendingRuntimeMode::Continue,    )    .unwrap();    let inner = Arc::new(Inner {        stored_values: Mutex::new(HashMap::new()),        cells: Mutex::new(HashMap::new()),        delegate,        shutting_down: AtomicBool::new(false),        next_cell_id: AtomicU64::new(1),    });    let task = tokio::spawn(run_cell_control(        inner,        CellControlContext {            cell_id: cell_id("1"),            runtime_tx,            runtime_control_tx,            pending_mode: PendingRuntimeMode::Continue,            runtime_terminate_handle,            cancellation_token: CancellationToken::new(),        },        event_rx,        control_rx,        CellResponseSender::Runtime(initial_response_tx),        initial_yield_time_ms,    ));    CellControlHarness {        event_tx,        control_tx,        initial_response_rx,        task,        _runtime_event_rx: runtime_event_rx,    }}impl BlockingDelegate {    fn new() -> (Arc<Self>, mpsc::UnboundedReceiver<DelegateEvent>) {        let (events_tx, events_rx) = mpsc::unbounded_channel();        (            Arc::new(Self {                events_tx,                notification_finished: AtomicBool::new(false),                tool_finished: AtomicBool::new(false),            }),            events_rx,        )    }}impl CodeModeSessionDelegate for BlockingDelegate {    fn invoke_tool<'a>(        &'a self,        _invocation: CodeModeNestedToolCall,        cancellation_token: CancellationToken,    ) -> ToolInvocationFuture<'a> {        Box::pin(async move {            let _ = self.events_tx.send(DelegateEvent::ToolStarted);            cancellation_token.cancelled().await;            self.tool_finished.store(true, Ordering::Release);            let _ = self.events_tx.send(DelegateEvent::ToolCancelled);            Err("cancelled".to_string())        })    }    fn notify<'a>(        &'a self,        _call_id: String,        _cell_id: CellId,        _text: String,        cancellation_token: CancellationToken,    ) -> NotificationFuture<'a> {        Box::pin(async move {            let _ = self.events_tx.send(DelegateEvent::NotificationStarted);            cancellation_token.cancelled().await;            self.notification_finished.store(true, Ordering::Release);            let _ = self.events_tx.send(DelegateEvent::NotificationCancelled);            Err("cancelled".to_string())        })    }    fn cell_closed(&self, cell_id: &CellId) {        let _ = self            .events_tx            .send(DelegateEvent::CellClosed(cell_id.clone()));    }}fn cell_id(value: &str) -> CellId {    CellId::new(value.to_string())}fn execute_request(source: &str) -> ExecuteRequest {    ExecuteRequest {        tool_call_id: "call-1".to_string(),        enabled_tools: Vec::new(),        source: source.to_string(),        yield_time_ms: Some(1),        max_output_tokens: None,    }}fn blocking_tool() -> ToolDefinition {    ToolDefinition {        name: "block".to_string(),        tool_name: ToolName::plain("block"),        description: String::new(),        kind: CodeModeToolKind::Function,        input_schema: None,        output_schema: None,    }}async fn next_event(events_rx: &mut mpsc::UnboundedReceiver<DelegateEvent>) -> DelegateEvent {    tokio::time::timeout(Duration::from_secs(2), events_rx.recv())        .await        .expect("delegate event timeout")        .expect("delegate event channel closed")}#[tokio::test]async fn yield_timer_preempts_buffered_runtime_output() {    let harness = spawn_cell_control_harness(        Some(/*initial_yield_time_ms*/ 0),        Arc::new(NoopCodeModeSessionDelegate),    );    harness.event_tx.send(RuntimeEvent::Started).unwrap();    harness        .event_tx        .send(RuntimeEvent::ContentItem(            FunctionCallOutputContentItem::InputText {                text: "queued output".to_string(),            },        ))        .unwrap();    assert_eq!(        harness.initial_response_rx.await.unwrap(),        Ok(RuntimeResponse::Yielded {            cell_id: cell_id("1"),            content_items: Vec::new(),        })    );    let (termination_tx, termination_rx) = oneshot::channel();    harness        .control_tx        .send(CellControlCommand::Terminate {            response_tx: termination_tx,        })        .unwrap();    drop(harness.event_tx);    assert_eq!(        termination_rx.await.unwrap(),        Ok(RuntimeResponse::Terminated {            cell_id: cell_id("1"),            content_items: vec![FunctionCallOutputContentItem::InputText {                text: "queued output".to_string(),            }],        })    );    harness.task.await.unwrap();}#[tokio::test]async fn queued_termination_preempts_unobserved_runtime_completion() {    let harness = spawn_cell_control_harness(        Some(/*initial_yield_time_ms*/ 60_000),        Arc::new(NoopCodeModeSessionDelegate),    );    harness        .event_tx        .send(RuntimeEvent::Result {            stored_value_writes: HashMap::new(),            error_text: None,        })        .unwrap();    let (termination_tx, termination_rx) = oneshot::channel();    harness        .control_tx        .send(CellControlCommand::Terminate {            response_tx: termination_tx,        })        .unwrap();    let terminated = Ok(RuntimeResponse::Terminated {        cell_id: cell_id("1"),        content_items: Vec::new(),    });    assert_eq!(termination_rx.await.unwrap(), terminated.clone());    assert_eq!(harness.initial_response_rx.await.unwrap(), terminated);    harness.task.await.unwrap();}#[tokio::test]async fn yields_and_resumes() {    let service = CodeModeService::new();    let cell = service        .execute(execute_request(            r#"text("before"); yield_control(); text("after");"#,        ))        .await        .unwrap();    assert_eq!(        cell.initial_response().await.unwrap(),        RuntimeResponse::Yielded {            cell_id: cell_id("1"),            content_items: vec![FunctionCallOutputContentItem::InputText {                text: "before".to_string(),            }],        }    );    assert_eq!(        service            .wait(WaitRequest {                cell_id: cell_id("1"),                yield_time_ms: 1,            })            .await            .unwrap(),        WaitOutcome::LiveCell(RuntimeResponse::Result {            cell_id: cell_id("1"),            content_items: vec![FunctionCallOutputContentItem::InputText {                text: "after".to_string(),            }],            error_text: None,        })    );}#[tokio::test]async fn returns_and_resumes_from_the_pending_frontier() {    let service = CodeModeService::new();    assert_eq!(        service            .execute_to_pending(execute_request(                r#"await new Promise((resolve) => setTimeout(resolve, 60_000));text("after");"#,            ))            .await            .unwrap(),        ExecuteToPendingOutcome::Pending {            cell_id: cell_id("1"),            content_items: Vec::new(),            pending_tool_call_ids: Vec::new(),        }    );    service        .inner        .cells        .lock()        .await        .get(&cell_id("1"))        .unwrap()        .runtime_tx        .send(RuntimeCommand::TimeoutFired { id: 1 })        .unwrap();    assert_eq!(        service            .wait_to_pending(WaitToPendingRequest {                cell_id: cell_id("1"),            })            .await            .unwrap(),        WaitToPendingOutcome::LiveCell(ExecuteToPendingOutcome::Completed(            RuntimeResponse::Result {                cell_id: cell_id("1"),                content_items: vec![FunctionCallOutputContentItem::InputText {                    text: "after".to_string(),                }],                error_text: None,            }        ))    );}#[tokio::test]async fn observed_natural_completion_wins_over_termination() {    let (delegate, mut events_rx) = BlockingDelegate::new();    let harness =        spawn_cell_control_harness(Some(/*initial_yield_time_ms*/ 60_000), delegate.clone());    harness.event_tx.send(RuntimeEvent::YieldRequested).unwrap();    assert_eq!(        harness.initial_response_rx.await.unwrap(),        Ok(RuntimeResponse::Yielded {            cell_id: cell_id("1"),            content_items: Vec::new(),        })    );    harness        .event_tx        .send(RuntimeEvent::ContentItem(            FunctionCallOutputContentItem::InputText {                text: "done".to_string(),            },        ))        .unwrap();    harness        .event_tx        .send(RuntimeEvent::Result {            stored_value_writes: HashMap::new(),            error_text: None,        })        .unwrap();    harness        .event_tx        .send(RuntimeEvent::Notify {            call_id: "notify-1".to_string(),            text: "completion observed".to_string(),        })        .unwrap();    assert_eq!(        next_event(&mut events_rx).await,        DelegateEvent::NotificationStarted    );    let (termination_tx, termination_rx) = oneshot::channel();    harness        .control_tx        .send(CellControlCommand::Terminate {            response_tx: termination_tx,        })        .unwrap();    assert_eq!(        termination_rx.await.unwrap(),        Ok(RuntimeResponse::Result {            cell_id: cell_id("1"),            content_items: vec![FunctionCallOutputContentItem::InputText {                text: "done".to_string(),            }],            error_text: None,        })    );    harness.task.await.unwrap();    assert!(delegate.notification_finished.load(Ordering::Acquire));    assert_eq!(        next_event(&mut events_rx).await,        DelegateEvent::NotificationCancelled    );    assert_eq!(        next_event(&mut events_rx).await,        DelegateEvent::CellClosed(cell_id("1"))    );}#[tokio::test]async fn termination_cancels_pending_callbacks_before_responding() {    let (delegate, mut events_rx) = BlockingDelegate::new();    let service = CodeModeService::with_delegate(delegate.clone());    let cell = service        .execute(execute_request(            r#"notify("pending"); await new Promise(() => {});"#,        ))        .await        .unwrap();    assert_eq!(        next_event(&mut events_rx).await,        DelegateEvent::NotificationStarted    );    assert_eq!(        cell.initial_response().await.unwrap(),        RuntimeResponse::Yielded {            cell_id: cell_id("1"),            content_items: Vec::new(),        }    );    assert_eq!(        service.terminate(cell_id("1")).await.unwrap(),        WaitOutcome::LiveCell(RuntimeResponse::Terminated {            cell_id: cell_id("1"),            content_items: Vec::new(),        })    );    assert!(delegate.notification_finished.load(Ordering::Acquire));    assert_eq!(        next_event(&mut events_rx).await,        DelegateEvent::NotificationCancelled    );    assert_eq!(        next_event(&mut events_rx).await,        DelegateEvent::CellClosed(cell_id("1"))    );}#[tokio::test]async fn repeated_termination_is_rejected_while_callback_cleanup_is_pending() {    let (delegate, mut events_rx) = HeldNotificationDelegate::new();    let service = Arc::new(CodeModeService::with_delegate(delegate.clone()));    let cell = service        .execute(execute_request(            r#"notify("pending"); await new Promise(() => {});"#,        ))        .await        .unwrap();    assert_eq!(        next_event(&mut events_rx).await,        DelegateEvent::NotificationStarted    );    assert_eq!(        cell.initial_response().await.unwrap(),        RuntimeResponse::Yielded {            cell_id: cell_id("1"),            content_items: Vec::new(),        }    );    let terminating_service = Arc::clone(&service);    let first_termination =        tokio::spawn(async move { terminating_service.terminate(cell_id("1")).await });    assert_eq!(        next_event(&mut events_rx).await,        DelegateEvent::NotificationCancelled    );    let repeated_termination = service.terminate(cell_id("1")).await;    delegate.release_notification();    assert_eq!(        repeated_termination.unwrap_err(),        "exec cell 1 is already terminating"    );    assert_eq!(        first_termination.await.unwrap().unwrap(),        WaitOutcome::LiveCell(RuntimeResponse::Terminated {            cell_id: cell_id("1"),            content_items: Vec::new(),        })    );    assert_eq!(        next_event(&mut events_rx).await,        DelegateEvent::CellClosed(cell_id("1"))    );}#[tokio::test]async fn second_observer_is_rejected_without_displacing_the_first() {    let service = CodeModeService::new();    let cell = service        .execute(execute_request("await new Promise(() => {});"))        .await        .unwrap();    assert_eq!(        cell.initial_response().await.unwrap(),        RuntimeResponse::Yielded {            cell_id: cell_id("1"),            content_items: Vec::new(),        }    );    let first_observer = service        .begin_wait(WaitRequest {            cell_id: cell_id("1"),            yield_time_ms: 60_000,        })        .await;    assert_eq!(        service            .wait(WaitRequest {                cell_id: cell_id("1"),                yield_time_ms: 60_000,            })            .await            .unwrap_err(),        "exec cell 1 already has an active observer"    );    let terminated = RuntimeResponse::Terminated {        cell_id: cell_id("1"),        content_items: Vec::new(),    };    assert_eq!(        service.terminate(cell_id("1")).await.unwrap(),        WaitOutcome::LiveCell(terminated.clone())    );    assert_eq!(        first_observer.await.unwrap(),        WaitOutcome::LiveCell(terminated)    );}#[tokio::test]async fn natural_completion_cleans_up_callbacks_before_responding() {    let (delegate, mut events_rx) = BlockingDelegate::new();    let service = CodeModeService::with_delegate(delegate.clone());    let cell = service        .execute(ExecuteRequest {            enabled_tools: vec![blocking_tool()],            source: r#"tools.block({}); text("done");"#.to_string(),            yield_time_ms: Some(60_000),            ..execute_request("")        })        .await        .unwrap();    assert_eq!(next_event(&mut events_rx).await, DelegateEvent::ToolStarted);    assert_eq!(        cell.initial_response().await.unwrap(),        RuntimeResponse::Result {            cell_id: cell_id("1"),            content_items: vec![FunctionCallOutputContentItem::InputText {                text: "done".to_string(),            }],            error_text: None,        }    );    assert!(delegate.tool_finished.load(Ordering::Acquire));    assert_eq!(        next_event(&mut events_rx).await,        DelegateEvent::ToolCancelled    );    assert_eq!(        next_event(&mut events_rx).await,        DelegateEvent::CellClosed(cell_id("1"))    );}