diff --git a/crates/coa-core/examples/manager_launcher_e2e.rs b/crates/coa-core/examples/manager_launcher_e2e.rs index a9dc9f9..777e4c8 100644 --- a/crates/coa-core/examples/manager_launcher_e2e.rs +++ b/crates/coa-core/examples/manager_launcher_e2e.rs @@ -85,10 +85,21 @@ fn main() { assert_eq!(std::fs::read(&manage_py).unwrap(), original, "manage.py is not rewritten"); assert_eq!(realm_name(root), "AzerothCore", "no profile: the launcher's own realm name"); + let shipped = root.join("Scripts/coa-launcher.exe"); + let supervisor = state::running(root, "supervisor").expect("a supervisor"); + println!("[supervisor] {}", supervisor.exe); + let expected = if shipped.is_file() { "coa-launcher.exe" } else { "python.exe" }; + assert!(supervisor.exe.to_lowercase().ends_with(expected), "the world is supervised by {expected}"); + // 2 assert!(drive(root, Verb::StopAll).ok, "stop-all"); assert!(nothing_running(root), "1-2 left something running"); + // 2b: the repack's Python launcher stops a world the Manager started + assert!(drive(root, Verb::StartAll).ok); + assert!(manage(root, "stop-all").0, "manage.py stops what the Manager started"); + assert!(nothing_running(root), "2b left something running"); + // 3 assert!(manage(root, "start-all").0); assert!(drive(root, Verb::StopAll).ok, "driver stops what manage.py started"); diff --git a/crates/coa-core/src/ra.rs b/crates/coa-core/src/ra.rs index 5764488..cad0bcd 100644 --- a/crates/coa-core/src/ra.rs +++ b/crates/coa-core/src/ra.rs @@ -88,12 +88,26 @@ impl Ra { self.command(c) } - /// Send a command the server does not answer before it closes the console (`server shutdown`), and return at - /// once. + /// Send a command whose answer does not matter (`server shutdown`). The reply is still read (up to the next + /// prompt, the end of the connection, or a few seconds): closing a socket that holds unread data resets the + /// connection, and the server can then drop the command it has not processed yet. pub fn send_without_answer(mut self, cmd: &str) -> Result<()> { let c = crate::console::check_command(cmd)?; self.stream.write_all(format!("{c}\r\n").as_bytes())?; self.stream.flush()?; + self.stream.set_read_timeout(Some(Duration::from_secs(10)))?; + let mut seen = Vec::new(); + let mut buf = [0u8; 4096]; + while let Ok(n) = self.stream.read(&mut buf) { + if n == 0 { + break; + } + seen.extend_from_slice(&buf[..n]); + if seen.ends_with(b"AC>") || seen.len() > 1 << 20 { + break; + } + } + let _ = self.stream.shutdown(std::net::Shutdown::Both); Ok(()) }