Download codex-rs/code-mode-runtime/src/cell_actor/tests.rs from SaylorTwift/codex: direct link, hf CLI and curl.
- Browser
- Download file 20.9 kB
-
https://huggingface.co/SaylorTwift/codex/resolve/main/codex-rs/code-mode-runtime/src/cell_actor/tests.rs
- Command line
-
hf download hf://SaylorTwift/codex/codex-rs/code-mode-runtime/src/cell_actor/tests.rs
-
curl -L -o tests.rs https://huggingface.co/SaylorTwift/codex/resolve/main/codex-rs/code-mode-runtime/src/cell_actor/tests.rs
20.9 kB
| use std::collections::HashMap; | |
| use std::sync::Arc; | |
| use std::sync::atomic::AtomicBool; | |
| use std::sync::atomic::Ordering; | |
| use std::sync::mpsc as std_mpsc; | |
| use std::time::Duration; | |
| use codex_code_mode_protocol::ExecuteRequest; | |
| use codex_code_mode_protocol::FunctionCallOutputContentItem; | |
| use pretty_assertions::assert_eq; | |
| use serde_json::Value as JsonValue; | |
| use tokio::sync::mpsc; | |
| use tokio::sync::oneshot; | |
| use tokio_util::sync::CancellationToken; | |
| use super::*; | |
| use crate::session_runtime::OutputItem; | |
| struct TestHost; | |
| struct RecordingHost { | |
| notified: AtomicBool, | |
| } | |
| impl CellHost for TestHost { | |
| async fn invoke_tool( | |
| &self, | |
| _invocation: CellToolCall, | |
| _cancellation_token: CancellationToken, | |
| ) -> Result<JsonValue, String> { | |
| Err("unexpected tool call".to_string()) | |
| } | |
| async fn notify( | |
| &self, | |
| _call_id: String, | |
| _text: String, | |
| _cancellation_token: CancellationToken, | |
| ) -> Result<(), String> { | |
| Ok(()) | |
| } | |
| async fn commit_completion( | |
| &self, | |
| _stored_value_writes: HashMap<String, JsonValue>, | |
| event: CellEvent, | |
| pending_initial_yield_items: Option<Vec<OutputItem>>, | |
| cell_state: Arc<CellState>, | |
| ) -> CompletionCommit { | |
| cell_state.commit_completion(event, pending_initial_yield_items, || {}) | |
| } | |
| async fn closed(&self) {} | |
| } | |
| impl CellHost for RecordingHost { | |
| async fn invoke_tool( | |
| &self, | |
| _invocation: CellToolCall, | |
| _cancellation_token: CancellationToken, | |
| ) -> Result<JsonValue, String> { | |
| Err("unexpected tool call".to_string()) | |
| } | |
| async fn notify( | |
| &self, | |
| _call_id: String, | |
| _text: String, | |
| _cancellation_token: CancellationToken, | |
| ) -> Result<(), String> { | |
| self.notified.store(true, Ordering::Release); | |
| Ok(()) | |
| } | |
| async fn commit_completion( | |
| &self, | |
| _stored_value_writes: HashMap<String, JsonValue>, | |
| event: CellEvent, | |
| pending_initial_yield_items: Option<Vec<OutputItem>>, | |
| cell_state: Arc<CellState>, | |
| ) -> CompletionCommit { | |
| cell_state.commit_completion(event, pending_initial_yield_items, || {}) | |
| } | |
| async fn closed(&self) {} | |
| } | |
| struct CellActorHarness { | |
| event_tx: mpsc::UnboundedSender<RuntimeEvent>, | |
| handle: CellHandle, | |
| initial_event_rx: oneshot::Receiver<Result<CellEvent, CellError>>, | |
| task: tokio::task::JoinHandle<()>, | |
| runtime_control_rx: std_mpsc::Receiver<RuntimeControlCommand>, | |
| _runtime_event_rx: mpsc::UnboundedReceiver<RuntimeEvent>, | |
| } | |
| fn spawn_cell_actor_harness(initial_observe_mode: ObserveMode) -> CellActorHarness { | |
| spawn_cell_actor_harness_with_host(initial_observe_mode, Arc::new(TestHost)) | |
| } | |
| fn spawn_cell_actor_harness_with_host<H: CellHost>( | |
| initial_observe_mode: ObserveMode, | |
| host: Arc<H>, | |
| ) -> CellActorHarness { | |
| spawn_cell_actor_harness_with_host_and_failure_handler( | |
| initial_observe_mode, | |
| host, | |
| /*task_failure_handler*/ None, | |
| ) | |
| } | |
| fn spawn_cell_actor_harness_with_host_and_failure_handler<H: CellHost>( | |
| initial_observe_mode: ObserveMode, | |
| host: Arc<H>, | |
| task_failure_handler: Option<TaskFailureHandler>, | |
| ) -> CellActorHarness { | |
| let (event_tx, event_rx) = mpsc::unbounded_channel(); | |
| let (command_tx, command_rx) = mpsc::unbounded_channel(); | |
| let (initial_event_tx, initial_event_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(), | |
| ExecuteRequest { | |
| tool_call_id: "call-1".to_string(), | |
| enabled_tools: Vec::new(), | |
| source: "await new Promise(() => {});".to_string(), | |
| yield_time_ms: None, | |
| max_output_tokens: None, | |
| }, | |
| runtime_event_tx, | |
| PendingRuntimeMode::PauseUntilResumed, | |
| /*task_failure_handler*/ None, | |
| ) | |
| .unwrap(); | |
| let (runtime_control_tx, runtime_control_rx) = std_mpsc::channel(); | |
| let cell_state = Arc::new(CellState::new(CancellationToken::new())); | |
| let handle = CellHandle::new(command_tx, Arc::clone(&cell_state)); | |
| let task = tokio::spawn(run_cell( | |
| host, | |
| CellContext { | |
| runtime_tx, | |
| runtime_control_tx, | |
| runtime_terminate_handle, | |
| cell_state, | |
| }, | |
| event_rx, | |
| command_rx, | |
| Observer { | |
| mode: initial_observe_mode, | |
| response_tx: initial_event_tx, | |
| }, | |
| task_failure_handler, | |
| )); | |
| CellActorHarness { | |
| event_tx, | |
| handle, | |
| initial_event_rx, | |
| task, | |
| runtime_control_rx, | |
| _runtime_event_rx: runtime_event_rx, | |
| } | |
| } | |
| async fn unexpected_runtime_thread_exit_is_reported_to_the_session_owner() { | |
| let (failure_tx, mut failure_rx) = mpsc::unbounded_channel(); | |
| let harness = spawn_cell_actor_harness_with_host_and_failure_handler( | |
| ObserveMode::YieldAfter(Duration::from_secs(60)), | |
| Arc::new(TestHost), | |
| Some(Arc::new(move |reason| { | |
| let _ = failure_tx.send(reason); | |
| })), | |
| ); | |
| drop(harness.event_tx); | |
| assert_eq!( | |
| tokio::time::timeout(Duration::from_secs(1), failure_rx.recv()) | |
| .await | |
| .expect("runtime failure timeout") | |
| .expect("runtime failure"), | |
| "code-mode V8 runtime thread ended unexpectedly" | |
| ); | |
| assert!( | |
| harness | |
| .initial_event_rx | |
| .await | |
| .expect("initial event") | |
| .is_ok() | |
| ); | |
| harness.task.await.expect("cell task"); | |
| } | |
| async fn runtime_thread_panic_remains_a_cell_error_without_owner_supervision() { | |
| let harness = spawn_cell_actor_harness(ObserveMode::YieldAfter(Duration::from_secs(60))); | |
| harness | |
| .event_tx | |
| .send(RuntimeEvent::ThreadPanicked) | |
| .expect("runtime panic event"); | |
| drop(harness.event_tx); | |
| assert_eq!( | |
| harness.initial_event_rx.await.expect("initial event"), | |
| Ok(CellEvent::Completed { | |
| content_items: Vec::new(), | |
| error_text: Some("exec runtime ended unexpectedly".to_string()), | |
| }) | |
| ); | |
| harness.task.await.expect("cell task"); | |
| } | |
| async fn wait_for_notification(host: &RecordingHost) { | |
| tokio::time::timeout(Duration::from_secs(1), async { | |
| while !host.notified.load(Ordering::Acquire) { | |
| tokio::task::yield_now().await; | |
| } | |
| }) | |
| .await | |
| .expect("notification barrier timed out"); | |
| } | |
| async fn yield_timer_preempts_buffered_runtime_output() { | |
| let harness = spawn_cell_actor_harness(ObserveMode::YieldAfter(Duration::ZERO)); | |
| 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_event_rx.await.unwrap(), | |
| Ok(CellEvent::Yielded { | |
| content_items: Vec::new(), | |
| }) | |
| ); | |
| let termination = harness.handle.terminate(); | |
| drop(harness.event_tx); | |
| assert_eq!( | |
| termination.await, | |
| Ok(CellEvent::Terminated { | |
| content_items: vec![OutputItem::Text { | |
| text: "queued output".to_string(), | |
| }], | |
| }) | |
| ); | |
| harness.task.await.unwrap(); | |
| } | |
| async fn queued_termination_preempts_unobserved_runtime_completion() { | |
| let harness = spawn_cell_actor_harness(ObserveMode::YieldAfter(Duration::from_secs(60))); | |
| harness | |
| .event_tx | |
| .send(RuntimeEvent::Result { | |
| stored_value_writes: HashMap::new(), | |
| error_text: None, | |
| }) | |
| .unwrap(); | |
| let termination = harness.handle.terminate(); | |
| let terminated = Ok(CellEvent::Terminated { | |
| content_items: Vec::new(), | |
| }); | |
| assert_eq!(termination.await, terminated.clone()); | |
| assert_eq!(harness.initial_event_rx.await.unwrap(), terminated); | |
| harness.task.await.unwrap(); | |
| } | |
| async fn observation_dropped_before_dequeue_does_not_consume_output() { | |
| let host = Arc::new(RecordingHost::default()); | |
| let harness = spawn_cell_actor_harness_with_host( | |
| ObserveMode::YieldAfter(Duration::from_secs(60)), | |
| Arc::clone(&host), | |
| ); | |
| harness.event_tx.send(RuntimeEvent::YieldRequested).unwrap(); | |
| assert!(harness.initial_event_rx.await.unwrap().is_ok()); | |
| drop( | |
| harness | |
| .handle | |
| .observe(ObserveMode::YieldAfter(Duration::from_secs(60))), | |
| ); | |
| harness | |
| .event_tx | |
| .send(RuntimeEvent::ContentItem( | |
| FunctionCallOutputContentItem::InputText { | |
| text: "survives pre-dequeue cancellation".to_string(), | |
| }, | |
| )) | |
| .unwrap(); | |
| harness.event_tx.send(RuntimeEvent::YieldRequested).unwrap(); | |
| harness | |
| .event_tx | |
| .send(RuntimeEvent::Notify { | |
| call_id: "after-dropped-command".to_string(), | |
| text: "barrier".to_string(), | |
| }) | |
| .unwrap(); | |
| wait_for_notification(&host).await; | |
| assert_eq!( | |
| harness | |
| .handle | |
| .observe(ObserveMode::YieldAfter(Duration::ZERO)) | |
| .await, | |
| Ok(CellEvent::Yielded { | |
| content_items: vec![OutputItem::Text { | |
| text: "survives pre-dequeue cancellation".to_string(), | |
| }], | |
| }) | |
| ); | |
| let termination = harness.handle.terminate(); | |
| drop(harness.event_tx); | |
| assert_eq!( | |
| termination.await, | |
| Ok(CellEvent::Terminated { | |
| content_items: Vec::new(), | |
| }) | |
| ); | |
| harness.task.await.unwrap(); | |
| } | |
| async fn dropped_yield_observer_preserves_output_for_the_next_observation() { | |
| let host = Arc::new(RecordingHost::default()); | |
| let harness = spawn_cell_actor_harness_with_host( | |
| ObserveMode::YieldAfter(Duration::from_secs(60)), | |
| Arc::clone(&host), | |
| ); | |
| harness.event_tx.send(RuntimeEvent::YieldRequested).unwrap(); | |
| assert!(harness.initial_event_rx.await.unwrap().is_ok()); | |
| let dropped_observation = harness | |
| .handle | |
| .observe(ObserveMode::YieldAfter(Duration::from_secs(60))); | |
| assert_eq!( | |
| harness | |
| .handle | |
| .observe(ObserveMode::YieldAfter(Duration::ZERO)) | |
| .await, | |
| Err(CellError::Busy) | |
| ); | |
| drop(dropped_observation); | |
| harness | |
| .event_tx | |
| .send(RuntimeEvent::ContentItem( | |
| FunctionCallOutputContentItem::InputText { | |
| text: "survives active cancellation".to_string(), | |
| }, | |
| )) | |
| .unwrap(); | |
| harness.event_tx.send(RuntimeEvent::YieldRequested).unwrap(); | |
| harness | |
| .event_tx | |
| .send(RuntimeEvent::Notify { | |
| call_id: "after-dropped-observer".to_string(), | |
| text: "barrier".to_string(), | |
| }) | |
| .unwrap(); | |
| wait_for_notification(&host).await; | |
| assert_eq!( | |
| harness | |
| .handle | |
| .observe(ObserveMode::YieldAfter(Duration::ZERO)) | |
| .await, | |
| Ok(CellEvent::Yielded { | |
| content_items: vec![OutputItem::Text { | |
| text: "survives active cancellation".to_string(), | |
| }], | |
| }) | |
| ); | |
| let termination = harness.handle.terminate(); | |
| drop(harness.event_tx); | |
| assert_eq!( | |
| termination.await, | |
| Ok(CellEvent::Terminated { | |
| content_items: Vec::new(), | |
| }) | |
| ); | |
| harness.task.await.unwrap(); | |
| } | |
| async fn dropped_pending_observer_preserves_the_frontier_for_the_next_observation() { | |
| let host = Arc::new(RecordingHost::default()); | |
| let harness = spawn_cell_actor_harness_with_host( | |
| ObserveMode::YieldAfter(Duration::from_secs(60)), | |
| Arc::clone(&host), | |
| ); | |
| harness.event_tx.send(RuntimeEvent::YieldRequested).unwrap(); | |
| assert!(harness.initial_event_rx.await.unwrap().is_ok()); | |
| let dropped_observation = harness.handle.observe(ObserveMode::PendingFrontier); | |
| assert_eq!( | |
| harness.handle.observe(ObserveMode::PendingFrontier).await, | |
| Err(CellError::Busy) | |
| ); | |
| drop(dropped_observation); | |
| harness | |
| .event_tx | |
| .send(RuntimeEvent::ToolCall { | |
| id: "tool-1".to_string(), | |
| name: codex_protocol::ToolName { | |
| name: "echo".to_string(), | |
| namespace: None, | |
| }, | |
| kind: codex_code_mode_protocol::CodeModeToolKind::Function, | |
| input: Some(serde_json::json!({})), | |
| }) | |
| .unwrap(); | |
| harness.event_tx.send(RuntimeEvent::Pending).unwrap(); | |
| harness | |
| .event_tx | |
| .send(RuntimeEvent::Notify { | |
| call_id: "after-dropped-pending".to_string(), | |
| text: "barrier".to_string(), | |
| }) | |
| .unwrap(); | |
| wait_for_notification(&host).await; | |
| assert_eq!( | |
| harness.handle.observe(ObserveMode::PendingFrontier).await, | |
| Ok(CellEvent::Pending { | |
| content_items: Vec::new(), | |
| pending_tool_call_ids: vec!["tool-1".to_string()], | |
| }) | |
| ); | |
| assert!(matches!( | |
| harness.runtime_control_rx.try_recv(), | |
| Err(std_mpsc::TryRecvError::Empty) | |
| )); | |
| let termination = harness.handle.terminate(); | |
| drop(harness.event_tx); | |
| assert_eq!( | |
| termination.await, | |
| Ok(CellEvent::Terminated { | |
| content_items: Vec::new(), | |
| }) | |
| ); | |
| harness.task.await.unwrap(); | |
| } | |
| async fn only_the_first_termination_claims_a_buffered_completion() { | |
| let cell_state = CellState::new(CancellationToken::new()); | |
| let completion = CellEvent::Completed { | |
| content_items: Vec::new(), | |
| error_text: None, | |
| }; | |
| assert_eq!( | |
| cell_state.commit_completion( | |
| completion.clone(), | |
| /*pending_initial_yield_items*/ None, | |
| || {} | |
| ), | |
| CompletionCommit::Committed | |
| ); | |
| assert!(matches!( | |
| cell_state.deliver_completion(/*response_tx*/ None), | |
| CompletionDelivery::Buffered | |
| )); | |
| let first_termination = cell_state.request_termination(); | |
| assert_eq!( | |
| cell_state.request_termination().await, | |
| Err(CellError::AlreadyTerminating) | |
| ); | |
| assert_eq!(first_termination.await, Ok(completion.clone())); | |
| assert_eq!( | |
| cell_state.finish_termination(CellEvent::Terminated { | |
| content_items: Vec::new(), | |
| }), | |
| Some(completion) | |
| ); | |
| } | |
| async fn termination_claim_prevents_stored_value_commit() { | |
| let cell_state = CellState::new(CancellationToken::new()); | |
| let termination = cell_state.request_termination(); | |
| let mut commit_ran = false; | |
| let completion = CellEvent::Completed { | |
| content_items: Vec::new(), | |
| error_text: None, | |
| }; | |
| assert_eq!( | |
| cell_state.commit_completion( | |
| completion.clone(), | |
| /*pending_initial_yield_items*/ None, | |
| || commit_ran = true | |
| ), | |
| CompletionCommit::Rejected(completion) | |
| ); | |
| assert!(!commit_ran); | |
| let terminated = CellEvent::Terminated { | |
| content_items: Vec::new(), | |
| }; | |
| assert_eq!( | |
| cell_state.finish_termination(terminated.clone()), | |
| Some(terminated.clone()) | |
| ); | |
| assert_eq!(termination.await, Ok(terminated)); | |
| } | |
| fn failed_completion_delivery_rebuffers_the_event() { | |
| let cell_state = CellState::new(CancellationToken::new()); | |
| let event = CellEvent::Completed { | |
| content_items: Vec::new(), | |
| error_text: None, | |
| }; | |
| assert_eq!( | |
| cell_state.commit_completion( | |
| event.clone(), | |
| /*pending_initial_yield_items*/ None, | |
| || {} | |
| ), | |
| CompletionCommit::Committed | |
| ); | |
| let (response_tx, response_rx) = oneshot::channel(); | |
| drop(response_rx); | |
| assert!(matches!( | |
| cell_state.deliver_completion(Some(response_tx)), | |
| CompletionDelivery::Buffered | |
| )); | |
| assert!(cell_state.accepting_observations()); | |
| let (response_tx, mut response_rx) = oneshot::channel(); | |
| assert!(matches!( | |
| cell_state.route_observation(ObserveMode::YieldAfter(Duration::ZERO), response_tx), | |
| ObservationDelivery::Delivered | |
| )); | |
| assert_eq!(response_rx.try_recv(), Ok(Ok(event))); | |
| } | |
| fn buffered_initial_yield_precedes_buffered_completion_for_yield_observer() { | |
| let cell_state = CellState::new(CancellationToken::new()); | |
| let completion = CellEvent::Completed { | |
| content_items: vec![OutputItem::Text { | |
| text: "after".to_string(), | |
| }], | |
| error_text: None, | |
| }; | |
| assert_eq!( | |
| cell_state.commit_completion( | |
| completion.clone(), | |
| Some(vec![OutputItem::Text { | |
| text: "before".to_string(), | |
| }]), | |
| || {} | |
| ), | |
| CompletionCommit::Committed | |
| ); | |
| assert!(matches!( | |
| cell_state.deliver_completion(/*response_tx*/ None), | |
| CompletionDelivery::Buffered | |
| )); | |
| let (response_tx, mut response_rx) = oneshot::channel(); | |
| assert!(matches!( | |
| cell_state.route_observation(ObserveMode::YieldAfter(Duration::ZERO), response_tx), | |
| ObservationDelivery::Buffered | |
| )); | |
| assert_eq!( | |
| response_rx.try_recv(), | |
| Ok(Ok(CellEvent::Yielded { | |
| content_items: vec![OutputItem::Text { | |
| text: "before".to_string(), | |
| }], | |
| })) | |
| ); | |
| let (response_tx, mut response_rx) = oneshot::channel(); | |
| assert!(matches!( | |
| cell_state.route_observation(ObserveMode::YieldAfter(Duration::ZERO), response_tx), | |
| ObservationDelivery::Delivered | |
| )); | |
| assert_eq!(response_rx.try_recv(), Ok(Ok(completion))); | |
| } | |
| fn pending_observer_merges_initial_yield_and_completion_output() { | |
| let cell_state = CellState::new(CancellationToken::new()); | |
| assert_eq!( | |
| cell_state.commit_completion( | |
| CellEvent::Completed { | |
| content_items: vec![OutputItem::Text { | |
| text: "after".to_string(), | |
| }], | |
| error_text: None, | |
| }, | |
| Some(vec![OutputItem::Text { | |
| text: "before".to_string(), | |
| }]), | |
| || {} | |
| ), | |
| CompletionCommit::Committed | |
| ); | |
| assert!(matches!( | |
| cell_state.deliver_completion(/*response_tx*/ None), | |
| CompletionDelivery::Buffered | |
| )); | |
| let (response_tx, mut response_rx) = oneshot::channel(); | |
| assert!(matches!( | |
| cell_state.route_observation(ObserveMode::PendingFrontier, response_tx), | |
| ObservationDelivery::Delivered | |
| )); | |
| assert_eq!( | |
| response_rx.try_recv(), | |
| Ok(Ok(CellEvent::Completed { | |
| content_items: vec![ | |
| OutputItem::Text { | |
| text: "before".to_string(), | |
| }, | |
| OutputItem::Text { | |
| text: "after".to_string(), | |
| }, | |
| ], | |
| error_text: None, | |
| })) | |
| ); | |
| } | |
| fn dropped_pending_observation_preserves_the_initial_yield_boundary() { | |
| let cell_state = CellState::new(CancellationToken::new()); | |
| let completion = CellEvent::Completed { | |
| content_items: vec![OutputItem::Text { | |
| text: "after".to_string(), | |
| }], | |
| error_text: None, | |
| }; | |
| assert_eq!( | |
| cell_state.commit_completion( | |
| completion.clone(), | |
| Some(vec![OutputItem::Text { | |
| text: "before".to_string(), | |
| }]), | |
| || {} | |
| ), | |
| CompletionCommit::Committed | |
| ); | |
| assert!(matches!( | |
| cell_state.deliver_completion(/*response_tx*/ None), | |
| CompletionDelivery::Buffered | |
| )); | |
| let (response_tx, response_rx) = oneshot::channel(); | |
| drop(response_rx); | |
| assert!(matches!( | |
| cell_state.route_observation(ObserveMode::PendingFrontier, response_tx), | |
| ObservationDelivery::Buffered | |
| )); | |
| let (response_tx, mut response_rx) = oneshot::channel(); | |
| assert!(matches!( | |
| cell_state.route_observation(ObserveMode::YieldAfter(Duration::ZERO), response_tx), | |
| ObservationDelivery::Buffered | |
| )); | |
| assert_eq!( | |
| response_rx.try_recv(), | |
| Ok(Ok(CellEvent::Yielded { | |
| content_items: vec![OutputItem::Text { | |
| text: "before".to_string(), | |
| }], | |
| })) | |
| ); | |
| let (response_tx, mut response_rx) = oneshot::channel(); | |
| assert!(matches!( | |
| cell_state.route_observation(ObserveMode::YieldAfter(Duration::ZERO), response_tx), | |
| ObservationDelivery::Delivered | |
| )); | |
| assert_eq!(response_rx.try_recv(), Ok(Ok(completion))); | |
| } | |