use crate::monitor::ApiError;
use crate::monitor::listener::ApiListener;
use crate::network::{AdapterKind, AdapterSnapshot, AddressFetcher, FetchError};
use crate::time::Clock;
use std::collections::VecDeque;
use std::pin::Pin;
use std::sync::Mutex;
use std::sync::atomic::{AtomicU64, Ordering};
use std::task::{Context, Poll};
use std::time::{Duration, SystemTime};
use tokio_stream::Stream;
pub struct MockClock {
secs: AtomicU64,
}
impl MockClock {
pub fn new(initial_secs: u64) -> Self {
Self {
secs: AtomicU64::new(initial_secs),
}
}
}
impl Clock for MockClock {
fn now(&self) -> SystemTime {
SystemTime::UNIX_EPOCH + Duration::from_secs(self.secs.load(Ordering::SeqCst))
}
}
pub struct MockFetcher {
results: Mutex<VecDeque<Result<Vec<AdapterSnapshot>, FetchError>>>,
}
impl MockFetcher {
pub fn returning_snapshots(snapshots: Vec<Vec<AdapterSnapshot>>) -> Self {
Self {
results: Mutex::new(snapshots.into_iter().map(Ok).collect()),
}
}
pub fn new(results: Vec<Result<Vec<AdapterSnapshot>, FetchError>>) -> Self {
Self {
results: Mutex::new(results.into()),
}
}
}
impl AddressFetcher for MockFetcher {
fn fetch(&self) -> Result<Vec<AdapterSnapshot>, FetchError> {
self.results
.lock()
.unwrap()
.pop_front()
.unwrap_or_else(|| Ok(vec![]))
}
}
pub struct MockApiStream {
events: Mutex<VecDeque<Option<Result<(), ApiError>>>>,
}
impl MockApiStream {
pub fn new(events: Vec<Option<Result<(), ApiError>>>) -> Self {
Self {
events: Mutex::new(events.into()),
}
}
}
impl Stream for MockApiStream {
type Item = Result<(), ApiError>;
fn poll_next(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let mut events = self.events.lock().unwrap();
match events.pop_front() {
Some(Some(result)) => Poll::Ready(Some(result)),
Some(None) => Poll::Ready(None), None => Poll::Pending, }
}
}
pub struct MockApiListener {
events: Vec<Option<Result<(), ApiError>>>,
}
impl MockApiListener {
pub fn new(events: Vec<Option<Result<(), ApiError>>>) -> Self {
Self { events }
}
pub fn failing() -> Self {
Self {
events: vec![Some(Err(ApiError::Stopped))],
}
}
pub fn pending() -> Self {
Self { events: vec![] }
}
}
impl ApiListener for MockApiListener {
type Stream = MockApiStream;
fn into_stream(self) -> Self::Stream {
MockApiStream::new(self.events)
}
}
pub fn make_snapshot(name: &str, ipv4: Vec<&str>, ipv6: Vec<&str>) -> AdapterSnapshot {
AdapterSnapshot::new(
name,
AdapterKind::Ethernet,
ipv4.into_iter().map(|s| s.parse().unwrap()).collect(),
ipv6.into_iter().map(|s| s.parse().unwrap()).collect(),
)
}