#![cfg(unix)]
use std::io::{BufRead, BufReader, Write};
use std::os::unix::net::UnixStream;
use std::path::Path;
use std::time::Duration;
use rch_common::e2e::harness::{HarnessResult, TestHarnessBuilder};
fn send_request(socket_path: &Path, request: &str) -> std::io::Result<String> {
let mut stream = UnixStream::connect(socket_path)?;
stream.set_read_timeout(Some(Duration::from_secs(5)))?;
stream.set_write_timeout(Some(Duration::from_secs(5)))?;
writeln!(stream, "{}", request)?;
stream.flush()?;
let reader = BufReader::new(&stream);
let mut response = String::new();
let mut in_body = false;
for line in reader.lines() {
let line = line?;
if in_body {
response.push_str(&line);
response.push('\n');
} else if line.is_empty() {
in_body = true;
}
}
Ok(response.trim().to_string())
}
#[test]
fn test_daemon_startup_shutdown_cycles() -> HarnessResult<()> {
let _guard = rch_common::test_guard!();
let harness = TestHarnessBuilder::new("daemon_stability_cycles")
.cleanup_on_success(true)
.cleanup_on_failure(false)
.build()?;
let workers_config = r#"
[[workers]]
id = "test-worker"
host = "localhost"
user = "test"
total_slots = 4
"#;
harness.create_workers_config(workers_config)?;
let socket_path = harness.test_dir().join("rchd.sock");
let socket_arg = socket_path.to_string_lossy().to_string();
for cycle in 1..=3 {
harness
.logger
.info(format!("Starting daemon cycle {cycle}"));
harness.start_daemon(&["--socket", &socket_arg, "--foreground"])?;
harness.wait_for_socket(&socket_path, Duration::from_secs(10))?;
let response = send_request(&socket_path, "GET /health")
.map_err(rch_common::e2e::harness::HarnessError::Io)?;
harness.assert(
response.contains("\"status\""),
"Health response should include status",
)?;
harness.stop_process("daemon")?;
std::thread::sleep(Duration::from_millis(300));
}
harness.mark_passed();
Ok(())
}
#[test]
fn test_daemon_request_burst() -> HarnessResult<()> {
let _guard = rch_common::test_guard!();
let harness = TestHarnessBuilder::new("daemon_stability_burst")
.cleanup_on_success(true)
.cleanup_on_failure(false)
.build()?;
let workers_config = r#"
[[workers]]
id = "test-worker"
host = "localhost"
user = "test"
total_slots = 4
"#;
harness.create_workers_config(workers_config)?;
let socket_path = harness.test_dir().join("rchd.sock");
let socket_arg = socket_path.to_string_lossy().to_string();
harness.start_daemon(&["--socket", &socket_arg, "--foreground"])?;
harness.wait_for_socket(&socket_path, Duration::from_secs(10))?;
for _ in 0..100 {
let response = send_request(&socket_path, "GET /health")
.map_err(rch_common::e2e::harness::HarnessError::Io)?;
harness.assert(
response.contains("\"status\""),
"Health response should include status",
)?;
}
harness.mark_passed();
Ok(())
}