swactor/crates/mvp-system/tests/local_unmocked_mvp_e2e.rs

120 lines
4.1 KiB
Rust
Raw Normal View History

use std::io::Write;
2026-07-07 10:40:02 +00:00
use std::path::PathBuf;
use std::process::{Command, ExitCode, Stdio};
#[path = "support/dumb_worker.rs"]
mod dumb_worker;
#[path = "support/local_e2e.rs"]
mod local_e2e;
fn main() -> ExitCode {
let args = std::env::args().collect::<Vec<_>>();
match std::env::var("MVP_TEST_ROLE").ok().as_deref() {
Some("dumb-worker") => return dumb_worker::run_main(),
Some("local-e2e") => return local_e2e::run_main(),
Some(role) => {
eprintln!("unknown MVP_TEST_ROLE={role}");
return ExitCode::from(2);
}
None => {}
}
if args.iter().any(|arg| arg == "--role=node") {
return local_e2e::run_main();
}
local_e2e_binary_drives_real_local_process_deployment();
dumb_worker_is_a_real_child_process_protocol_endpoint();
ExitCode::SUCCESS
}
fn local_e2e_binary_drives_real_local_process_deployment() {
2026-07-07 10:40:02 +00:00
let output = Command::new(current_test_exe())
.env("MVP_TEST_ROLE", "local-e2e")
.output()
2026-07-07 10:40:02 +00:00
.expect("run local e2e supervisor");
assert!(
output.status.success(),
"mvp-local-e2e failed\nstdout:\n{}\nstderr:\n{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
let value: serde_json::Value = serde_json::from_slice(&output.stdout).expect("json stdout");
assert_eq!(value["ok"], true);
assert_eq!(value["actor_plane"], "iroh-swactor");
assert_eq!(value["data_plane"], "tcp-loopback-streams");
assert_eq!(value["worker_processes"], "mvp-dumb-worker-per-node");
2026-06-24 15:23:09 +00:00
assert_eq!(
value["engine_builder_pattern"],
"pool-first-static-launcher"
);
assert_eq!(value["engine_builder_node_count"], 3);
assert_eq!(value["engine_builder_stage_assignments"], 2);
assert!(
value["engine_builder_event_count"]
.as_u64()
.is_some_and(|count| count >= 10),
"{value}"
);
assert_eq!(value["injected_prompt_observed"], true);
assert_eq!(value["token_received_observed"], true);
assert_eq!(value["run_completed_observed"], true);
assert_eq!(value["run_torn_down_observed"], true);
assert_eq!(value["stop_sent_to_all_nodes"], true);
assert_eq!(value["stage_ready_stdout_count"], 2);
assert!(value["processes"]["node0"].as_u64().is_some(), "{value}");
assert!(value["processes"]["node1"].as_u64().is_some(), "{value}");
assert!(
value["node0_endpoint"]["addrs"]
.as_array()
.is_some_and(|addrs| !addrs.is_empty()),
"{value}"
);
assert!(
value["node1_endpoint"]["addrs"]
.as_array()
.is_some_and(|addrs| !addrs.is_empty()),
"{value}"
);
}
fn dumb_worker_is_a_real_child_process_protocol_endpoint() {
2026-07-07 10:40:02 +00:00
let mut child = Command::new(current_test_exe())
.env("MVP_TEST_ROLE", "dumb-worker")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
2026-07-07 10:40:02 +00:00
.expect("spawn dumb worker test role");
{
let stdin = child.stdin.as_mut().expect("worker stdin");
writeln!(
stdin,
"{{\"type\":\"InitializeWorker\",\"helper_abi_version\":1}}"
)
.expect("write initialize");
writeln!(stdin, "{{\"type\":\"ExecuteStep\",\"step_id\":7}}").expect("write execute");
writeln!(stdin, "{{\"type\":\"ShutdownWorker\"}}").expect("write shutdown");
}
let output = child.wait_with_output().expect("worker output");
assert!(
output.status.success(),
"worker failed\nstdout:\n{}\nstderr:\n{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
let stdout = String::from_utf8(output.stdout).expect("utf8 stdout");
assert!(stdout.contains("\"type\":\"WorkerReady\""), "{stdout}");
assert!(stdout.contains("\"type\":\"StepCompleted\""), "{stdout}");
assert!(stdout.contains("\"step_id\":7"), "{stdout}");
assert!(stdout.contains("\"type\":\"WorkerStopped\""), "{stdout}");
}
2026-07-07 10:40:02 +00:00
fn current_test_exe() -> PathBuf {
std::env::current_exe().expect("current test exe")
}