restore dropped tests

This commit is contained in:
Roy Han
2026-03-12 17:02:18 -07:00
parent 43a21f349b
commit 6d40e7bede
2 changed files with 156 additions and 4 deletions

View File

@@ -1,10 +1,13 @@
use super::*;
use crate::codex::make_session_and_context;
use crate::config::test_config;
use assert_matches::assert_matches;
use codex_protocol::models::ContentItem;
use codex_protocol::models::ReasoningItemReasoningSummary;
use codex_protocol::models::ResponseItem;
use pretty_assertions::assert_eq;
use std::time::Duration;
use tempfile::tempdir;
fn user_msg(text: &str) -> ResponseItem {
ResponseItem::Message {
@@ -113,3 +116,39 @@ async fn ignores_session_prefix_messages_when_truncating() {
serde_json::to_value(&expected).unwrap()
);
}
#[tokio::test]
async fn shutdown_all_threads_bounded_submits_shutdown_to_every_thread() {
let temp_dir = tempdir().expect("tempdir");
let mut config = test_config();
config.codex_home = temp_dir.path().join("codex-home");
config.cwd = config.codex_home.clone();
std::fs::create_dir_all(&config.codex_home).expect("create codex home");
let manager = ThreadManager::with_models_provider_and_home_for_tests(
CodexAuth::from_api_key("dummy"),
config.model_provider.clone(),
config.codex_home.clone(),
);
let thread_1 = manager
.start_thread(config.clone())
.await
.expect("start first thread")
.thread_id;
let thread_2 = manager
.start_thread(config)
.await
.expect("start second thread")
.thread_id;
let report = manager
.shutdown_all_threads_bounded(Duration::from_secs(10))
.await;
let mut expected_completed = vec![thread_1, thread_2];
expected_completed.sort_by_key(std::string::ToString::to_string);
assert_eq!(report.completed, expected_completed);
assert!(report.submit_failed.is_empty());
assert!(report.timed_out.is_empty());
assert!(manager.list_thread_ids().await.is_empty());
}

View File

@@ -287,12 +287,15 @@ async fn emitted_image_content_item_drops_unsupported_explicit_detail() {
}
#[tokio::test]
async fn emitted_image_content_item_does_not_add_original_detail_when_not_requested() {
async fn emitted_image_content_item_does_not_force_original_when_enabled() {
let (_session, mut turn) = make_session_and_context().await;
Arc::make_mut(&mut turn.config)
.features
.enable(Feature::ImageDetailOriginal)
.expect("test config should allow feature update");
turn.features
.enable(Feature::ImageDetailOriginal)
.expect("test turn features should allow feature update");
turn.model_info.supports_image_detail_original = true;
let content_item =
@@ -307,6 +310,52 @@ async fn emitted_image_content_item_does_not_add_original_detail_when_not_reques
);
}
#[tokio::test]
async fn emitted_image_content_item_allows_explicit_original_detail_when_enabled() {
let (_session, mut turn) = make_session_and_context().await;
Arc::make_mut(&mut turn.config)
.features
.enable(Feature::ImageDetailOriginal)
.expect("test config should allow feature update");
turn.features
.enable(Feature::ImageDetailOriginal)
.expect("test turn features should allow feature update");
turn.model_info.supports_image_detail_original = true;
let content_item = emitted_image_content_item(
&turn,
"data:image/png;base64,AAA".to_string(),
Some(ImageDetail::Original),
);
assert_eq!(
content_item,
FunctionCallOutputContentItem::InputImage {
image_url: "data:image/png;base64,AAA".to_string(),
detail: Some(ImageDetail::Original),
}
);
}
#[tokio::test]
async fn emitted_image_content_item_drops_explicit_original_detail_when_disabled() {
let (_session, turn) = make_session_and_context().await;
let content_item = emitted_image_content_item(
&turn,
"data:image/png;base64,AAA".to_string(),
Some(ImageDetail::Original),
);
assert_eq!(
content_item,
FunctionCallOutputContentItem::InputImage {
image_url: "data:image/png;base64,AAA".to_string(),
detail: None,
}
);
}
#[test]
fn validate_emitted_image_url_accepts_case_insensitive_data_scheme() {
assert_eq!(
@@ -1347,6 +1396,59 @@ await codex.emitImage({ bytes: png, mimeType: "image/png", detail: "ultra" });
Ok(())
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn js_repl_emit_image_treats_null_detail_as_omitted() -> anyhow::Result<()> {
if !can_run_js_repl_runtime_tests().await {
return Ok(());
}
let (session, turn) = make_session_and_context().await;
if !turn
.model_info
.input_modalities
.contains(&InputModality::Image)
{
return Ok(());
}
let session = Arc::new(session);
let turn = Arc::new(turn);
*session.active_turn.lock().await = Some(crate::state::ActiveTurn::default());
let tracker = Arc::new(tokio::sync::Mutex::new(TurnDiffTracker::default()));
let manager = turn.js_repl.manager().await?;
let code = r#"
const png = Buffer.from(
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR4nGP4z8DwHwAFAAH/iZk9HQAAAABJRU5ErkJggg==",
"base64"
);
await codex.emitImage({ bytes: png, mimeType: "image/png", detail: null });
"#;
let result = manager
.execute(
Arc::clone(&session),
turn,
tracker,
JsReplArgs {
code: code.to_string(),
timeout_ms: Some(15_000),
},
)
.await?;
assert_eq!(
result.content_items.as_slice(),
[FunctionCallOutputContentItem::InputImage {
image_url: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR4nGP4z8DwHwAFAAH/iZk9HQAAAABJRU5ErkJggg==".to_string(),
detail: None,
}]
.as_slice()
);
assert!(session.get_pending_input_with_metadata().await.is_empty());
Ok(())
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn js_repl_emit_image_rejects_mixed_content() -> anyhow::Result<()> {
if !can_run_js_repl_runtime_tests().await {
@@ -1712,13 +1814,22 @@ async fn js_repl_imported_local_files_can_access_repl_globals() -> anyhow::Resul
}
let cwd_dir = tempdir()?;
let expected_home_dir = serde_json::to_string("/tmp/codex-home")?;
write_js_repl_test_module(
cwd_dir.path(),
"globals.js",
"console.log(codex.tmpDir === tmpDir);\nconsole.log(typeof codex.tool);\nconsole.log(\"local-file-console-ok\");\n",
&format!(
"const expectedHomeDir = {expected_home_dir};\nconsole.log(`tmp:${{codex.tmpDir === tmpDir}}`);\nconsole.log(`cwd:${{typeof codex.cwd}}:${{codex.cwd.length > 0}}`);\nconsole.log(`home:${{codex.homeDir === expectedHomeDir}}`);\nconsole.log(`tool:${{typeof codex.tool}}`);\nconsole.log(\"local-file-console-ok\");\n"
),
)?;
let (session, mut turn) = make_session_and_context().await;
session
.set_dependency_env(HashMap::from([(
"HOME".to_string(),
"/tmp/codex-home".to_string(),
)]))
.await;
turn.shell_environment_policy
.r#set
.remove("CODEX_JS_REPL_NODE_MODULE_DIRS");
@@ -1744,8 +1855,10 @@ async fn js_repl_imported_local_files_can_access_repl_globals() -> anyhow::Resul
},
)
.await?;
assert!(result.output.contains("true"));
assert!(result.output.contains("function"));
assert!(result.output.contains("tmp:true"));
assert!(result.output.contains("cwd:string:true"));
assert!(result.output.contains("home:true"));
assert!(result.output.contains("tool:function"));
assert!(result.output.contains("local-file-console-ok"));
Ok(())
}