use std::{
io,
net::{Ipv4Addr, SocketAddr, TcpListener as StdTcpListener},
};
use bincode::{Decode, Encode};
use rstest::fixture;
use super::{Bound, ServerError, WireframeServer};
use crate::app::WireframeApp;
#[derive(Debug, Clone, PartialEq, Encode, Decode)]
pub struct TestPreamble {
pub id: u32,
pub message: String,
}
#[fixture]
pub fn factory() -> impl Fn() -> WireframeApp + Send + Sync + Clone + 'static {
|| WireframeApp::default()
}
#[fixture]
pub fn free_listener() -> io::Result<StdTcpListener> {
let addr = SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 0);
StdTcpListener::bind(addr)
}
#[cfg(test)]
pub fn free_addr() -> io::Result<SocketAddr> {
let listener = free_listener()?;
listener_addr(&listener)
}
#[cfg(test)]
pub fn listener_addr(listener: &StdTcpListener) -> io::Result<SocketAddr> { listener.local_addr() }
pub fn bind_server<F>(
factory: F,
listener: StdTcpListener,
) -> Result<WireframeServer<F, (), Bound>, ServerError>
where
F: Fn() -> WireframeApp + Send + Sync + Clone + 'static,
{
WireframeServer::new(factory).bind_existing_listener(listener)
}
#[cfg(test)]
pub fn server_with_preamble<F>(factory: F) -> WireframeServer<F, TestPreamble>
where
F: Fn() -> WireframeApp + Send + Sync + Clone + 'static,
{
WireframeServer::new(factory).with_preamble::<TestPreamble>()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn free_addr_uses_localhost() {
let addr = free_addr().expect("free_addr should succeed");
assert_eq!(addr.ip(), std::net::IpAddr::from(Ipv4Addr::LOCALHOST));
}
#[test]
fn listener_addr_matches_local_addr() {
let listener = free_listener().expect("free_listener should succeed");
let addr = listener_addr(&listener).expect("listener_addr should succeed");
let local_addr = listener
.local_addr()
.expect("listener.local_addr should succeed");
assert_eq!(addr, local_addr);
}
#[test]
fn server_with_preamble_is_unbound() {
let server = server_with_preamble(factory());
assert!(server.local_addr().is_none());
}
}