1- #![ cfg( not( target_os = "windows" ) ) ]
21use std:: collections:: HashMap ;
32use std:: ffi:: OsStr ;
43use std:: fs;
@@ -24,6 +23,7 @@ use core_test_support::responses::sse;
2423use core_test_support:: responses:: start_mock_server;
2524use core_test_support:: skip_if_no_network;
2625use core_test_support:: skip_if_sandbox;
26+ use core_test_support:: skip_if_windows;
2727use core_test_support:: test_codex:: TestCodex ;
2828use core_test_support:: test_codex:: TestCodexHarness ;
2929use core_test_support:: test_codex:: test_codex;
@@ -155,6 +155,7 @@ fn collect_tool_outputs(bodies: &[Value]) -> Result<HashMap<String, ParsedUnifie
155155async fn unified_exec_intercepts_apply_patch_exec_command ( ) -> Result < ( ) > {
156156 skip_if_no_network ! ( Ok ( ( ) ) ) ;
157157 skip_if_sandbox ! ( Ok ( ( ) ) ) ;
158+ skip_if_windows ! ( Ok ( ( ) ) ) ;
158159
159160 let builder = test_codex ( ) . with_config ( |config| {
160161 config. include_apply_patch_tool = true ;
@@ -279,6 +280,7 @@ async fn unified_exec_intercepts_apply_patch_exec_command() -> Result<()> {
279280async fn unified_exec_emits_exec_command_begin_event ( ) -> Result < ( ) > {
280281 skip_if_no_network ! ( Ok ( ( ) ) ) ;
281282 skip_if_sandbox ! ( Ok ( ( ) ) ) ;
283+ skip_if_windows ! ( Ok ( ( ) ) ) ;
282284
283285 let server = start_mock_server ( ) . await ;
284286
@@ -350,6 +352,7 @@ async fn unified_exec_emits_exec_command_begin_event() -> Result<()> {
350352async fn unified_exec_resolves_relative_workdir ( ) -> Result < ( ) > {
351353 skip_if_no_network ! ( Ok ( ( ) ) ) ;
352354 skip_if_sandbox ! ( Ok ( ( ) ) ) ;
355+ skip_if_windows ! ( Ok ( ( ) ) ) ;
353356
354357 let server = start_mock_server ( ) . await ;
355358
@@ -427,6 +430,7 @@ async fn unified_exec_resolves_relative_workdir() -> Result<()> {
427430async fn unified_exec_respects_workdir_override ( ) -> Result < ( ) > {
428431 skip_if_no_network ! ( Ok ( ( ) ) ) ;
429432 skip_if_sandbox ! ( Ok ( ( ) ) ) ;
433+ skip_if_windows ! ( Ok ( ( ) ) ) ;
430434
431435 let server = start_mock_server ( ) . await ;
432436
@@ -505,6 +509,7 @@ async fn unified_exec_respects_workdir_override() -> Result<()> {
505509async fn unified_exec_emits_exec_command_end_event ( ) -> Result < ( ) > {
506510 skip_if_no_network ! ( Ok ( ( ) ) ) ;
507511 skip_if_sandbox ! ( Ok ( ( ) ) ) ;
512+ skip_if_windows ! ( Ok ( ( ) ) ) ;
508513
509514 let server = start_mock_server ( ) . await ;
510515
@@ -591,6 +596,7 @@ async fn unified_exec_emits_exec_command_end_event() -> Result<()> {
591596async fn unified_exec_emits_output_delta_for_exec_command ( ) -> Result < ( ) > {
592597 skip_if_no_network ! ( Ok ( ( ) ) ) ;
593598 skip_if_sandbox ! ( Ok ( ( ) ) ) ;
599+ skip_if_windows ! ( Ok ( ( ) ) ) ;
594600
595601 let server = start_mock_server ( ) . await ;
596602
@@ -662,6 +668,7 @@ async fn unified_exec_emits_output_delta_for_exec_command() -> Result<()> {
662668async fn unified_exec_emits_output_delta_for_write_stdin ( ) -> Result < ( ) > {
663669 skip_if_no_network ! ( Ok ( ( ) ) ) ;
664670 skip_if_sandbox ! ( Ok ( ( ) ) ) ;
671+ skip_if_windows ! ( Ok ( ( ) ) ) ;
665672
666673 let server = start_mock_server ( ) . await ;
667674
@@ -761,6 +768,7 @@ async fn unified_exec_emits_output_delta_for_write_stdin() -> Result<()> {
761768async fn unified_exec_emits_begin_for_write_stdin ( ) -> Result < ( ) > {
762769 skip_if_no_network ! ( Ok ( ( ) ) ) ;
763770 skip_if_sandbox ! ( Ok ( ( ) ) ) ;
771+ skip_if_windows ! ( Ok ( ( ) ) ) ;
764772
765773 let server = start_mock_server ( ) . await ;
766774
@@ -857,6 +865,7 @@ async fn unified_exec_emits_begin_for_write_stdin() -> Result<()> {
857865async fn unified_exec_emits_begin_event_for_write_stdin_requests ( ) -> Result < ( ) > {
858866 skip_if_no_network ! ( Ok ( ( ) ) ) ;
859867 skip_if_sandbox ! ( Ok ( ( ) ) ) ;
868+ skip_if_windows ! ( Ok ( ( ) ) ) ;
860869
861870 let server = start_mock_server ( ) . await ;
862871
@@ -978,6 +987,7 @@ async fn unified_exec_emits_begin_event_for_write_stdin_requests() -> Result<()>
978987async fn exec_command_reports_chunk_and_exit_metadata ( ) -> Result < ( ) > {
979988 skip_if_no_network ! ( Ok ( ( ) ) ) ;
980989 skip_if_sandbox ! ( Ok ( ( ) ) ) ;
990+ skip_if_windows ! ( Ok ( ( ) ) ) ;
981991
982992 let server = start_mock_server ( ) . await ;
983993
@@ -1085,6 +1095,7 @@ async fn exec_command_reports_chunk_and_exit_metadata() -> Result<()> {
10851095async fn unified_exec_respects_early_exit_notifications ( ) -> Result < ( ) > {
10861096 skip_if_no_network ! ( Ok ( ( ) ) ) ;
10871097 skip_if_sandbox ! ( Ok ( ( ) ) ) ;
1098+ skip_if_windows ! ( Ok ( ( ) ) ) ;
10881099
10891100 let server = start_mock_server ( ) . await ;
10901101
@@ -1177,6 +1188,7 @@ async fn unified_exec_respects_early_exit_notifications() -> Result<()> {
11771188async fn write_stdin_returns_exit_metadata_and_clears_session ( ) -> Result < ( ) > {
11781189 skip_if_no_network ! ( Ok ( ( ) ) ) ;
11791190 skip_if_sandbox ! ( Ok ( ( ) ) ) ;
1191+ skip_if_windows ! ( Ok ( ( ) ) ) ;
11801192
11811193 let server = start_mock_server ( ) . await ;
11821194
@@ -1338,6 +1350,7 @@ async fn write_stdin_returns_exit_metadata_and_clears_session() -> Result<()> {
13381350async fn unified_exec_emits_end_event_when_session_dies_via_stdin ( ) -> Result < ( ) > {
13391351 skip_if_no_network ! ( Ok ( ( ) ) ) ;
13401352 skip_if_sandbox ! ( Ok ( ( ) ) ) ;
1353+ skip_if_windows ! ( Ok ( ( ) ) ) ;
13411354
13421355 let server = start_mock_server ( ) . await ;
13431356
@@ -1442,6 +1455,7 @@ async fn unified_exec_emits_end_event_when_session_dies_via_stdin() -> Result<()
14421455async fn unified_exec_reuses_session_via_stdin ( ) -> Result < ( ) > {
14431456 skip_if_no_network ! ( Ok ( ( ) ) ) ;
14441457 skip_if_sandbox ! ( Ok ( ( ) ) ) ;
1458+ skip_if_windows ! ( Ok ( ( ) ) ) ;
14451459
14461460 let server = start_mock_server ( ) . await ;
14471461
@@ -1553,6 +1567,7 @@ async fn unified_exec_reuses_session_via_stdin() -> Result<()> {
15531567async fn unified_exec_streams_after_lagged_output ( ) -> Result < ( ) > {
15541568 skip_if_no_network ! ( Ok ( ( ) ) ) ;
15551569 skip_if_sandbox ! ( Ok ( ( ) ) ) ;
1570+ skip_if_windows ! ( Ok ( ( ) ) ) ;
15561571
15571572 let server = start_mock_server ( ) . await ;
15581573
16841699async fn unified_exec_timeout_and_followup_poll ( ) -> Result < ( ) > {
16851700 skip_if_no_network ! ( Ok ( ( ) ) ) ;
16861701 skip_if_sandbox ! ( Ok ( ( ) ) ) ;
1702+ skip_if_windows ! ( Ok ( ( ) ) ) ;
16871703
16881704 let server = start_mock_server ( ) . await ;
16891705
@@ -1790,6 +1806,7 @@ async fn unified_exec_timeout_and_followup_poll() -> Result<()> {
17901806async fn unified_exec_formats_large_output_summary ( ) -> Result < ( ) > {
17911807 skip_if_no_network ! ( Ok ( ( ) ) ) ;
17921808 skip_if_sandbox ! ( Ok ( ( ) ) ) ;
1809+ skip_if_windows ! ( Ok ( ( ) ) ) ;
17931810
17941811 let server = start_mock_server ( ) . await ;
17951812
18751892async fn unified_exec_runs_under_sandbox ( ) -> Result < ( ) > {
18761893 skip_if_no_network ! ( Ok ( ( ) ) ) ;
18771894 skip_if_sandbox ! ( Ok ( ( ) ) ) ;
1895+ skip_if_windows ! ( Ok ( ( ) ) ) ;
18781896
18791897 let server = start_mock_server ( ) . await ;
18801898
@@ -2067,11 +2085,83 @@ async fn unified_exec_python_prompt_under_seatbelt() -> Result<()> {
20672085 Ok ( ( ) )
20682086}
20692087
2088+ #[ tokio:: test( flavor = "multi_thread" , worker_threads = 2 ) ]
2089+ async fn unified_exec_runs_on_all_platforms ( ) -> Result < ( ) > {
2090+ skip_if_no_network ! ( Ok ( ( ) ) ) ;
2091+ skip_if_sandbox ! ( Ok ( ( ) ) ) ;
2092+
2093+ let server = start_mock_server ( ) . await ;
2094+
2095+ let mut builder = test_codex ( ) . with_config ( |config| {
2096+ config. features . enable ( Feature :: UnifiedExec ) ;
2097+ } ) ;
2098+ let TestCodex {
2099+ codex,
2100+ cwd,
2101+ session_configured,
2102+ ..
2103+ } = builder. build ( & server) . await ?;
2104+
2105+ let call_id = "uexec" ;
2106+ let args = serde_json:: json!( {
2107+ "cmd" : "echo 'hello crossplat'" ,
2108+ } ) ;
2109+
2110+ let responses = vec ! [
2111+ sse( vec![
2112+ ev_response_created( "resp-1" ) ,
2113+ ev_function_call( call_id, "exec_command" , & serde_json:: to_string( & args) ?) ,
2114+ ev_completed( "resp-1" ) ,
2115+ ] ) ,
2116+ sse( vec![
2117+ ev_assistant_message( "msg-1" , "done" ) ,
2118+ ev_completed( "resp-2" ) ,
2119+ ] ) ,
2120+ ] ;
2121+ mount_sse_sequence ( & server, responses) . await ;
2122+
2123+ let session_model = session_configured. model . clone ( ) ;
2124+
2125+ codex
2126+ . submit ( Op :: UserTurn {
2127+ items : vec ! [ UserInput :: Text {
2128+ text: "summarize large output" . into( ) ,
2129+ } ] ,
2130+ final_output_json_schema : None ,
2131+ cwd : cwd. path ( ) . to_path_buf ( ) ,
2132+ approval_policy : AskForApproval :: Never ,
2133+ sandbox_policy : SandboxPolicy :: DangerFullAccess ,
2134+ model : session_model,
2135+ effort : None ,
2136+ summary : ReasoningSummary :: Auto ,
2137+ } )
2138+ . await ?;
2139+
2140+ wait_for_event ( & codex, |event| matches ! ( event, EventMsg :: TaskComplete ( _) ) ) . await ;
2141+
2142+ let requests = server. received_requests ( ) . await . expect ( "recorded requests" ) ;
2143+ assert ! ( !requests. is_empty( ) , "expected at least one POST request" ) ;
2144+
2145+ let bodies = requests
2146+ . iter ( )
2147+ . map ( |req| req. body_json :: < Value > ( ) . expect ( "request json" ) )
2148+ . collect :: < Vec < _ > > ( ) ;
2149+
2150+ let outputs = collect_tool_outputs ( & bodies) ?;
2151+ let output = outputs. get ( call_id) . expect ( "missing output" ) ;
2152+
2153+ // TODO: Weaker match because windows produces control characters
2154+ assert_regex_match ( ".*hello crossplat.*" , & output. output ) ;
2155+
2156+ Ok ( ( ) )
2157+ }
2158+
20702159#[ tokio:: test( flavor = "multi_thread" , worker_threads = 2 ) ]
20712160#[ ignore]
20722161async fn unified_exec_prunes_exited_sessions_first ( ) -> Result < ( ) > {
20732162 skip_if_no_network ! ( Ok ( ( ) ) ) ;
20742163 skip_if_sandbox ! ( Ok ( ( ) ) ) ;
2164+ skip_if_windows ! ( Ok ( ( ) ) ) ;
20752165
20762166 let server = start_mock_server ( ) . await ;
20772167
0 commit comments