use std::net::SocketAddr;
use std::sync::mpsc;
use std::sync::mpsc::{Receiver, Sender};
use std::time::Duration;
use crate::tcp_server::TcpMocker;
use crate::udp_server::UdpMocker;
use crate::ServerMockerError::UnableToSendInstructions;
use crate::{Instruction, ServerMockerError};
pub trait MockerOptions: Clone {
fn socket_address(&self) -> SocketAddr;
fn net_timeout(&self) -> Duration;
fn run(
self,
instruction_rx: Receiver<Vec<Instruction>>,
message_tx: Sender<Vec<u8>>,
error_tx: Sender<ServerMockerError>,
) -> Result<SocketAddr, ServerMockerError>;
}
pub struct ServerMocker<T> {
options: T,
socket_addr: SocketAddr,
instruction_tx: Sender<Vec<Instruction>>,
message_rx: Receiver<Vec<u8>>,
error_rx: Receiver<ServerMockerError>,
}
impl ServerMocker<TcpMocker> {
pub fn tcp() -> Result<Self, ServerMockerError> {
Self::tcp_with_port(0)
}
pub fn tcp_with_port(port: u16) -> Result<Self, ServerMockerError> {
let mut opts = TcpMocker::default();
opts.socket_addr.set_port(port);
Self::new_with_opts(opts)
}
}
impl ServerMocker<UdpMocker> {
pub fn udp() -> Result<Self, ServerMockerError> {
Self::udp_with_port(0)
}
pub fn udp_with_port(port: u16) -> Result<Self, ServerMockerError> {
let mut opts = UdpMocker::default();
opts.socket_addr.set_port(port);
Self::new_with_opts(opts)
}
}
impl<T: MockerOptions> ServerMocker<T> {
pub fn options(&self) -> &T {
&self.options
}
pub fn socket_address(&self) -> SocketAddr {
self.socket_addr
}
pub fn port(&self) -> u16 {
self.socket_addr.port()
}
pub fn add_mock_instructions(
&self,
instructions: Vec<Instruction>,
) -> Result<(), ServerMockerError> {
self.instruction_tx
.send(instructions)
.map_err(UnableToSendInstructions)
}
pub fn pop_received_message(&self) -> Option<Vec<u8>> {
self.message_rx
.recv_timeout(self.options.net_timeout())
.ok()
}
pub fn pop_server_error(&self) -> Option<ServerMockerError> {
self.error_rx.recv_timeout(self.options.net_timeout()).ok()
}
pub fn new_with_opts(options: T) -> Result<Self, ServerMockerError> {
let (instruction_tx, instruction_rx) = mpsc::channel();
let (message_tx, message_rx) = mpsc::channel();
let (error_tx, error_rx) = mpsc::channel();
let socket_addr = options.clone().run(instruction_rx, message_tx, error_tx)?;
Ok(Self {
options,
socket_addr,
instruction_tx,
message_rx,
error_rx,
})
}
}