flowey_lib_hvlite/
run_test_igvm_agent_rpc_server.rs1use flowey::node::prelude::*;
19use std::collections::BTreeMap;
20
21flowey_request! {
22 pub struct Request {
23 pub env: ReadVar<BTreeMap<String, String>>,
25 pub done: WriteVar<SideEffect>,
27 }
28}
29
30new_simple_flow_node!(struct Node);
31
32impl SimpleFlowNode for Node {
33 type Request = Request;
34
35 fn imports(_ctx: &mut ImportCtx<'_>) {}
36
37 fn process_request(request: Self::Request, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
38 let Request { env, done } = request;
39
40 if !matches!(ctx.platform(), FlowPlatform::Windows) {
43 anyhow::bail!(
44 "run_test_igvm_agent_rpc_server only supports Windows. \
45 Callers should check the platform before requesting this node."
46 );
47 }
48
49 ctx.emit_rust_step("starting test_igvm_agent_rpc_server", |ctx| {
50 let env = env.claim(ctx);
51 done.claim(ctx);
52 move |rt| start_rpc_server(rt.read(env))
53 });
54
55 Ok(())
56 }
57}
58
59#[cfg(windows)]
60fn start_rpc_server(env: BTreeMap<String, String>) -> anyhow::Result<()> {
61 use std::os::windows::process::CommandExt;
62 use std::path::Path;
63
64 let test_content_dir = env
65 .get("VMM_TESTS_CONTENT_DIR")
66 .context("VMM_TESTS_CONTENT_DIR not set")?;
67 let test_output_path = env
68 .get("TEST_OUTPUT_PATH")
69 .context("TEST_OUTPUT_PATH not set")?;
70
71 let exe = Path::new(test_content_dir).join("test_igvm_agent_rpc_server.exe");
72
73 if !exe.exists() {
74 log::info!(
75 "test_igvm_agent_rpc_server.exe not found at {}, skipping",
76 exe.display()
77 );
78 return Ok(());
79 }
80
81 let log_file_path = Path::new(test_output_path).join("test_igvm_agent_rpc_server.log");
83 let log_file = std::fs::File::create(&log_file_path)?;
84 let log_file_stderr = log_file.try_clone()?;
85
86 log::info!(
87 "starting test_igvm_agent_rpc_server from {}, logs at: {}",
88 exe.display(),
89 log_file_path.display()
90 );
91
92 const CREATE_NEW_PROCESS_GROUP: u32 = 0x00000200;
95
96 let mut child = std::process::Command::new(&exe)
97 .stdin(std::process::Stdio::null())
98 .stdout(log_file)
99 .stderr(log_file_stderr)
100 .creation_flags(CREATE_NEW_PROCESS_GROUP)
101 .spawn()
102 .with_context(|| {
103 format!(
104 "failed to spawn test_igvm_agent_rpc_server: {}",
105 exe.display()
106 )
107 })?;
108
109 std::thread::sleep(std::time::Duration::from_millis(500));
111
112 match child.try_wait()? {
114 Some(status) => {
115 anyhow::bail!(
116 "test_igvm_agent_rpc_server exited unexpectedly with status: {:?}. \
117 Check logs at: {}",
118 status.code(),
119 log_file_path.display()
120 );
121 }
122 None => {
123 log::info!(
124 "test_igvm_agent_rpc_server started successfully (pid: {})",
125 child.id()
126 );
127 }
128 }
129
130 drop(child);
134
135 Ok(())
136}
137
138#[cfg(not(windows))]
139fn start_rpc_server(_env: BTreeMap<String, String>) -> anyhow::Result<()> {
140 anyhow::bail!("run_test_igvm_agent_rpc_server is only supported on Windows")
143}