diff --git a/proto/src/server/client.rs b/proto/src/server/client.rs index f205f09..2a89bef 100644 --- a/proto/src/server/client.rs +++ b/proto/src/server/client.rs @@ -22,6 +22,7 @@ pub struct Client { } /// Contents of a successful login response. +#[derive(Debug, Eq, PartialEq)] pub struct LoginInfo { /// The server's message of the day. pub motd: String, @@ -121,19 +122,18 @@ impl Client { #[cfg(test)] mod tests { - use tokio::net::TcpStream; + use std::net::Ipv4Addr; + use tokio::net::{TcpListener, TcpStream}; use tokio::sync::mpsc; - use crate::server::testing::{ - ServerBuilder, ShutdownType, UserStatusHandlerFactory, UserStatusMap, - }; + use crate::core::{FrameReader, FrameWriter}; use crate::server::{ - Credentials, ServerRequest, ServerResponse, UserStatusRequest, - UserStatusResponse, + Credentials, LoginRequest, LoginResponse, ServerRequest, ServerResponse, + UserStatusRequest, UserStatusResponse, }; use crate::UserStatus; - use super::Client; + use super::{Client, LoginInfo}; // Enable capturing logs in tests. fn init() { @@ -159,82 +159,89 @@ mod tests { async fn login_success() { init(); - let (server, handle) = - ServerBuilder::new(UserStatusHandlerFactory::default()) - .bind() + let listener = TcpListener::bind("localhost:0").await.expect("binding"); + let address = listener.local_addr().expect("getting local address"); + + let server_task = tokio::spawn(async move { + let (mut stream, _) = listener.accept().await.expect("accepting"); + let (read_half, write_half) = stream.split(); + let mut reader = FrameReader::new(read_half); + let mut writer = FrameWriter::new(write_half); + + let frame = reader.read().await.expect("reading login request"); + assert_eq!( + frame, + Some(ServerRequest::LoginRequest(LoginRequest { + user_name: "alice".to_string(), + password: "sekrit".to_string(), + digest: "286da88eb442032bdd3913979af76e8a".to_string(), + major: 181, + minor: 100, + })) + ); + + writer + .write(&ServerResponse::LoginResponse(LoginResponse::LoginOk { + ip: Ipv4Addr::new(1, 2, 3, 4), + motd: "motd".to_string(), + password_md5_opt: None, + })) .await - .expect("binding server"); - let server_task = tokio::spawn(server.serve()); - - let stream = TcpStream::connect(handle.address()) - .await - .expect("connecting"); - - let worker = Client::new(stream) - .login(credentials()) - .await - .expect("logging in"); - - drop(worker); - - handle.shutdown(ShutdownType::LameDuck); - server_task - .await - .expect("joining server") - .expect("running server"); - } - - #[tokio::test] - async fn simple_exchange() { - init(); - - let response = UserStatusResponse { - user_name: "shruti".to_string(), - status: UserStatus::Online, - is_privileged: false, - }; - - let mut user_status_map = UserStatusMap::default(); - user_status_map.insert(response.clone()); - - let (server, handle) = - ServerBuilder::new(UserStatusHandlerFactory::new(user_status_map)) - .bind() + .expect("writing login response"); + + let frame = reader.read().await.expect("reading user status request"); + assert_eq!( + frame, + Some(ServerRequest::UserStatusRequest(UserStatusRequest { + user_name: "shruti".to_string(), + })) + ); + + writer + .write(&ServerResponse::UserStatusResponse(UserStatusResponse { + user_name: "shruti".to_string(), + status: UserStatus::Online, + is_privileged: false, + })) .await - .expect("binding server"); - let server_task = tokio::spawn(server.serve()); + .expect("writing user status response"); + }); - let stream = TcpStream::connect(handle.address()) - .await - .expect("connecting"); + let stream = TcpStream::connect(address).await.expect("connecting"); - let (_, mut worker) = Client::new(stream) + let (info, mut worker) = Client::new(stream) .login(credentials()) .await .expect("logging in"); + assert_eq!( + info, + LoginInfo { + motd: "motd".to_string(), + public_ip: Ipv4Addr::new(1, 2, 3, 4), + } + ); + let (request_tx, request_rx) = mpsc::channel(100); let (response_tx, mut response_rx) = mpsc::channel(100); + let worker_task = + tokio::spawn(async move { worker.run(response_tx, request_rx).await }); + request_tx .send(ServerRequest::UserStatusRequest(UserStatusRequest { user_name: "shruti".to_string(), })) .await .expect("sending shruti"); - request_tx - .send(ServerRequest::UserStatusRequest(UserStatusRequest { - user_name: "karandeep".to_string(), - })) - .await - .expect("sending karandeep"); - - let worker_task = - tokio::spawn(async move { worker.run(response_tx, request_rx).await }); assert_eq!( response_rx.recv().await, - Some(ServerResponse::UserStatusResponse(response)) + Some(ServerResponse::UserStatusResponse(UserStatusResponse { + user_name: "shruti".to_string(), + status: UserStatus::Online, + is_privileged: false, + })) ); drop(request_tx); @@ -243,10 +250,6 @@ mod tests { .expect("joining worker") .expect("running worker"); - handle.shutdown(ShutdownType::LameDuck); - server_task - .await - .expect("joining server") - .expect("running server"); + server_task.await.expect("joining server"); } }