use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use std::time::Duration;
pub fn self_exec_argv(entry: &str) -> Vec<String> {
vec![
std::env::current_exe()
.unwrap()
.to_string_lossy()
.to_string(),
format!("agent::testbin::{entry}"),
"--exact".into(),
"--ignored".into(),
"--nocapture".into(),
"--test-threads=1".into(),
]
}
fn exit_with_parent() {
let ppid = unsafe { libc::getppid() };
if ppid <= 1 {
std::process::exit(0);
}
std::thread::spawn(move || loop {
std::thread::sleep(Duration::from_millis(300));
let now = unsafe { libc::getppid() };
if now != ppid || now <= 1 {
std::process::exit(0);
}
});
}
fn child_port() -> Option<u16> {
std::env::var("ZAKURO_AGENT_CHILD_PORT").ok()?.parse().ok()
}
#[test]
#[ignore = "self-exec entry point for the agent integration tests"]
fn fake_worker_main() {
let Some(port) = child_port() else { return };
exit_with_parent();
let name = std::env::var("ZAKURO_AGENT_CHILD_NAME").unwrap_or_else(|_| "fake".into());
let server = tiny_http::Server::http(("127.0.0.1", port)).unwrap();
let execute_count = Arc::new(AtomicU64::new(0));
let info_count = Arc::new(AtomicU64::new(0));
for req in server.incoming_requests() {
let body = if req.url().starts_with("/execute_count") {
format!(r#"{{"count":{}}}"#, execute_count.load(Ordering::SeqCst))
} else if req.url().starts_with("/info_count") {
format!(r#"{{"count":{}}}"#, info_count.load(Ordering::SeqCst))
} else if req.url().starts_with("/info") {
info_count.fetch_add(1, Ordering::SeqCst);
format!(
r#"{{"name":"{name}","worker_type":"zakuro","resources":{{"cpus_total":1.0,"cpus_available":1.0,"memory_total":1073741824,"memory_available":1073741824,"gpus_total":0,"gpus_available":0}},"pricing":{{"price_per_hour":3.6,"min_charge":0.001}}}}"#
)
} else if req.url().starts_with("/execute") {
execute_count.fetch_add(1, Ordering::SeqCst);
r#"{"result":"ok"}"#.to_string()
} else {
r#"{"status":"healthy"}"#.to_string()
};
let _ = req.respond(tiny_http::Response::from_string(body).with_header(
tiny_http::Header::from_bytes("Content-Type", "application/json").unwrap(),
));
}
}
#[test]
#[ignore = "self-exec entry point for the agent integration tests"]
fn broker_main() {
let Some(port) = child_port() else { return };
exit_with_parent();
let config = crate::broker::BrokerConfig {
host: "127.0.0.1".into(),
port,
verbose: false,
daemon: true,
enable_discovery: true,
health_check_interval: 1,
worker_timeout: 5,
enable_p2p: false,
peer_key: None,
owner_user_id: None,
node_name: Some("agent-it".into()),
worker_key: None,
api_url: None,
api_key: None,
discovery: crate::broker::DiscoveryConfig::default(),
..crate::broker::BrokerConfig::default()
};
let _ = crate::broker::start_server(config);
}