perfgate_fake/
host_probe.rs1use perfgate_adapters::{HostProbe, HostProbeOptions};
4use perfgate_types::HostInfo;
5use std::sync::{Arc, Mutex};
6
7#[derive(Debug, Clone)]
38pub struct FakeHostProbe {
39 inner: Arc<Mutex<FakeHostProbeInner>>,
40}
41
42#[derive(Debug, Clone)]
43struct FakeHostProbeInner {
44 os: String,
45 arch: String,
46 cpu_count: Option<u32>,
47 memory_bytes: Option<u64>,
48 hostname_hash: Option<String>,
49}
50
51impl Default for FakeHostProbe {
52 fn default() -> Self {
53 Self::new()
54 }
55}
56
57impl FakeHostProbe {
58 pub fn new() -> Self {
67 Self {
68 inner: Arc::new(Mutex::new(FakeHostProbeInner {
69 os: "unknown".to_string(),
70 arch: "unknown".to_string(),
71 cpu_count: None,
72 memory_bytes: None,
73 hostname_hash: None,
74 })),
75 }
76 }
77
78 pub fn platform(os: &str, arch: &str, cpu_count: u32, memory_bytes: u64) -> Self {
89 Self::new()
90 .with_os(os)
91 .with_arch(arch)
92 .with_cpu_count(cpu_count)
93 .with_memory_bytes(memory_bytes)
94 }
95
96 pub fn with_os(self, os: &str) -> Self {
98 self.inner.lock().expect("lock").os = os.to_string();
99 self
100 }
101
102 pub fn with_arch(self, arch: &str) -> Self {
104 self.inner.lock().expect("lock").arch = arch.to_string();
105 self
106 }
107
108 pub fn with_cpu_count(self, count: u32) -> Self {
110 self.inner.lock().expect("lock").cpu_count = Some(count);
111 self
112 }
113
114 pub fn with_memory_bytes(self, bytes: u64) -> Self {
116 self.inner.lock().expect("lock").memory_bytes = Some(bytes);
117 self
118 }
119
120 pub fn with_hostname_hash(self, hash: &str) -> Self {
125 self.inner.lock().expect("lock").hostname_hash = Some(hash.to_string());
126 self
127 }
128
129 pub fn without_cpu_count(self) -> Self {
131 self.inner.lock().expect("lock").cpu_count = None;
132 self
133 }
134
135 pub fn without_memory(self) -> Self {
137 self.inner.lock().expect("lock").memory_bytes = None;
138 self
139 }
140}
141
142impl HostProbe for FakeHostProbe {
143 fn probe(&self, options: &HostProbeOptions) -> HostInfo {
144 let inner = self.inner.lock().expect("lock");
145
146 HostInfo {
147 os: inner.os.clone(),
148 arch: inner.arch.clone(),
149 cpu_count: inner.cpu_count,
150 memory_bytes: inner.memory_bytes,
151 hostname_hash: if options.include_hostname_hash {
152 inner.hostname_hash.clone()
153 } else {
154 None
155 },
156 }
157 }
158}
159
160#[cfg(test)]
161mod tests {
162 use super::*;
163
164 #[test]
165 fn new_probe_has_defaults() {
166 let probe = FakeHostProbe::new();
167 let info = probe.probe(&HostProbeOptions::default());
168
169 assert_eq!(info.os, "unknown");
170 assert_eq!(info.arch, "unknown");
171 assert!(info.cpu_count.is_none());
172 assert!(info.memory_bytes.is_none());
173 assert!(info.hostname_hash.is_none());
174 }
175
176 #[test]
177 fn with_methods_configure_values() {
178 let probe = FakeHostProbe::new()
179 .with_os("linux")
180 .with_arch("x86_64")
181 .with_cpu_count(8)
182 .with_memory_bytes(16 * 1024 * 1024 * 1024);
183
184 let info = probe.probe(&HostProbeOptions::default());
185
186 assert_eq!(info.os, "linux");
187 assert_eq!(info.arch, "x86_64");
188 assert_eq!(info.cpu_count, Some(8));
189 assert_eq!(info.memory_bytes, Some(16 * 1024 * 1024 * 1024));
190 }
191
192 #[test]
193 fn hostname_hash_respects_option() {
194 let probe = FakeHostProbe::new().with_hostname_hash("abc123");
195
196 let info_without = probe.probe(&HostProbeOptions {
197 include_hostname_hash: false,
198 });
199 assert!(info_without.hostname_hash.is_none());
200
201 let info_with = probe.probe(&HostProbeOptions {
202 include_hostname_hash: true,
203 });
204 assert_eq!(info_with.hostname_hash, Some("abc123".to_string()));
205 }
206
207 #[test]
208 fn platform_convenience_constructor() {
209 let probe = FakeHostProbe::platform("macos", "aarch64", 10, 32 * 1024 * 1024 * 1024);
210 let info = probe.probe(&HostProbeOptions::default());
211
212 assert_eq!(info.os, "macos");
213 assert_eq!(info.arch, "aarch64");
214 assert_eq!(info.cpu_count, Some(10));
215 assert_eq!(info.memory_bytes, Some(32 * 1024 * 1024 * 1024));
216 }
217
218 #[test]
219 fn without_methods_clear_values() {
220 let probe = FakeHostProbe::new()
221 .with_cpu_count(8)
222 .with_memory_bytes(1024)
223 .without_cpu_count()
224 .without_memory();
225
226 let info = probe.probe(&HostProbeOptions::default());
227
228 assert!(info.cpu_count.is_none());
229 assert!(info.memory_bytes.is_none());
230 }
231
232 #[test]
233 fn thread_safe_sharing() {
234 use std::sync::Arc;
235 use std::thread;
236
237 let probe = Arc::new(FakeHostProbe::new().with_os("linux"));
238
239 let handles: Vec<_> = (0..4)
240 .map(|_| {
241 let p = probe.clone();
242 thread::spawn(move || {
243 let info = p.probe(&HostProbeOptions::default());
244 assert_eq!(info.os, "linux");
245 })
246 })
247 .collect();
248
249 for h in handles {
250 h.join().unwrap();
251 }
252 }
253}