use std::sync::atomic::{AtomicU64, Ordering};
use crate::types::Time;
use crate::web::extract::Request;
use crate::web::response::Response;
use crate::web::router::Router;
pub struct VirtualServer {
router: Router,
request_count: AtomicU64,
}
impl VirtualServer {
#[must_use]
pub fn new(router: Router) -> Self {
Self {
router,
request_count: AtomicU64::new(0),
}
}
pub fn handle(&self, req: Request) -> Response {
self.request_count.fetch_add(1, Ordering::Relaxed);
self.router.handle(req)
}
pub fn handle_at(&self, req: Request, now: Time) -> (Response, Time) {
let resp = self.handle(req);
(resp, now)
}
#[must_use]
pub fn request_count(&self) -> u64 {
self.request_count.load(Ordering::Relaxed)
}
#[must_use]
pub fn router(&self) -> &Router {
&self.router
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::web::handler::FnHandler;
use crate::web::response::StatusCode;
use crate::web::router::get;
#[test]
fn server_handles_request() {
let router = Router::new().route("/hello", get(FnHandler::new(|| "world")));
let server = VirtualServer::new(router);
let resp = server.handle(Request::new("GET", "/hello"));
assert_eq!(resp.status, StatusCode::OK);
assert_eq!(server.request_count(), 1);
}
#[test]
fn server_404_for_unknown_route() {
let router = Router::new();
let server = VirtualServer::new(router);
let resp = server.handle(Request::new("GET", "/missing"));
assert_eq!(resp.status, StatusCode::NOT_FOUND);
}
#[test]
fn server_counts_requests() {
let router = Router::new().route("/", get(FnHandler::new(|| "ok")));
let server = VirtualServer::new(router);
for _ in 0..5 {
server.handle(Request::new("GET", "/"));
}
assert_eq!(server.request_count(), 5);
}
#[test]
fn server_handle_at_returns_time() {
let router = Router::new().route("/", get(FnHandler::new(|| "ok")));
let server = VirtualServer::new(router);
let now = Time::from_millis(1000);
let (resp, time) = server.handle_at(Request::new("GET", "/"), now);
assert_eq!(resp.status, StatusCode::OK);
assert_eq!(time, now);
}
}