use perfgate_adapters::{HostProbe, HostProbeOptions};
use perfgate_types::HostInfo;
use std::sync::{Arc, Mutex};
#[derive(Debug, Clone)]
pub struct FakeHostProbe {
inner: Arc<Mutex<FakeHostProbeInner>>,
}
#[derive(Debug, Clone)]
struct FakeHostProbeInner {
os: String,
arch: String,
cpu_count: Option<u32>,
memory_bytes: Option<u64>,
hostname_hash: Option<String>,
}
impl Default for FakeHostProbe {
fn default() -> Self {
Self::new()
}
}
impl FakeHostProbe {
pub fn new() -> Self {
Self {
inner: Arc::new(Mutex::new(FakeHostProbeInner {
os: "unknown".to_string(),
arch: "unknown".to_string(),
cpu_count: None,
memory_bytes: None,
hostname_hash: None,
})),
}
}
pub fn platform(os: &str, arch: &str, cpu_count: u32, memory_bytes: u64) -> Self {
Self::new()
.with_os(os)
.with_arch(arch)
.with_cpu_count(cpu_count)
.with_memory_bytes(memory_bytes)
}
pub fn with_os(self, os: &str) -> Self {
self.inner.lock().expect("lock").os = os.to_string();
self
}
pub fn with_arch(self, arch: &str) -> Self {
self.inner.lock().expect("lock").arch = arch.to_string();
self
}
pub fn with_cpu_count(self, count: u32) -> Self {
self.inner.lock().expect("lock").cpu_count = Some(count);
self
}
pub fn with_memory_bytes(self, bytes: u64) -> Self {
self.inner.lock().expect("lock").memory_bytes = Some(bytes);
self
}
pub fn with_hostname_hash(self, hash: &str) -> Self {
self.inner.lock().expect("lock").hostname_hash = Some(hash.to_string());
self
}
pub fn without_cpu_count(self) -> Self {
self.inner.lock().expect("lock").cpu_count = None;
self
}
pub fn without_memory(self) -> Self {
self.inner.lock().expect("lock").memory_bytes = None;
self
}
}
impl HostProbe for FakeHostProbe {
fn probe(&self, options: &HostProbeOptions) -> HostInfo {
let inner = self.inner.lock().expect("lock");
HostInfo {
os: inner.os.clone(),
arch: inner.arch.clone(),
cpu_count: inner.cpu_count,
memory_bytes: inner.memory_bytes,
hostname_hash: if options.include_hostname_hash {
inner.hostname_hash.clone()
} else {
None
},
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_probe_has_defaults() {
let probe = FakeHostProbe::new();
let info = probe.probe(&HostProbeOptions::default());
assert_eq!(info.os, "unknown");
assert_eq!(info.arch, "unknown");
assert!(info.cpu_count.is_none());
assert!(info.memory_bytes.is_none());
assert!(info.hostname_hash.is_none());
}
#[test]
fn with_methods_configure_values() {
let probe = FakeHostProbe::new()
.with_os("linux")
.with_arch("x86_64")
.with_cpu_count(8)
.with_memory_bytes(16 * 1024 * 1024 * 1024);
let info = probe.probe(&HostProbeOptions::default());
assert_eq!(info.os, "linux");
assert_eq!(info.arch, "x86_64");
assert_eq!(info.cpu_count, Some(8));
assert_eq!(info.memory_bytes, Some(16 * 1024 * 1024 * 1024));
}
#[test]
fn hostname_hash_respects_option() {
let probe = FakeHostProbe::new().with_hostname_hash("abc123");
let info_without = probe.probe(&HostProbeOptions {
include_hostname_hash: false,
});
assert!(info_without.hostname_hash.is_none());
let info_with = probe.probe(&HostProbeOptions {
include_hostname_hash: true,
});
assert_eq!(info_with.hostname_hash, Some("abc123".to_string()));
}
#[test]
fn platform_convenience_constructor() {
let probe = FakeHostProbe::platform("macos", "aarch64", 10, 32 * 1024 * 1024 * 1024);
let info = probe.probe(&HostProbeOptions::default());
assert_eq!(info.os, "macos");
assert_eq!(info.arch, "aarch64");
assert_eq!(info.cpu_count, Some(10));
assert_eq!(info.memory_bytes, Some(32 * 1024 * 1024 * 1024));
}
#[test]
fn without_methods_clear_values() {
let probe = FakeHostProbe::new()
.with_cpu_count(8)
.with_memory_bytes(1024)
.without_cpu_count()
.without_memory();
let info = probe.probe(&HostProbeOptions::default());
assert!(info.cpu_count.is_none());
assert!(info.memory_bytes.is_none());
}
#[test]
fn thread_safe_sharing() {
use std::sync::Arc;
use std::thread;
let probe = Arc::new(FakeHostProbe::new().with_os("linux"));
let handles: Vec<_> = (0..4)
.map(|_| {
let p = probe.clone();
thread::spawn(move || {
let info = p.probe(&HostProbeOptions::default());
assert_eq!(info.os, "linux");
})
})
.collect();
for h in handles {
h.join().unwrap();
}
}
}