use std::time::Duration; use anyhow::Result; use lavina_core::repo::{Storage, StorageConfig}; use lavina_core::{player::PlayerRegistry, room::RoomRegistry}; use projection_irc::{launch, read_irc_message, ServerConfig}; use prometheus::Registry as MetricsRegistry; use tokio::io::{AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufReader}; use tokio::net::tcp::{ReadHalf, WriteHalf}; use tokio::net::TcpStream; struct TestScope<'a> { reader: BufReader>, writer: WriteHalf<'a>, buffer: Vec, pub timeout: Duration, } impl<'a> TestScope<'a> { fn new(stream: &mut TcpStream) -> TestScope<'_> { let (reader, writer) = stream.split(); let reader = BufReader::new(reader); TestScope { reader, writer, buffer: vec![], timeout: Duration::from_millis(100), } } async fn send(&mut self, str: &(impl AsRef + ?Sized)) -> Result<()> { self.writer.write_all(str.as_ref().as_bytes()).await?; self.writer.write_all(b"\r\n").await?; self.writer.flush().await?; Ok(()) } async fn expect(&mut self, str: &str) -> Result<()> { let len = tokio::time::timeout(self.timeout, read_irc_message(&mut self.reader, &mut self.buffer)).await??; assert_eq!(std::str::from_utf8(&self.buffer[..len - 2])?, str); self.buffer.clear(); Ok(()) } async fn assert(&mut self, f: impl FnOnce(&str) -> Result<()>) -> Result<()> { let len = tokio::time::timeout(self.timeout, read_irc_message(&mut self.reader, &mut self.buffer)).await??; let res = f(std::str::from_utf8(&self.buffer[..len - 2])?); self.buffer.clear(); res } } #[tokio::test] async fn scenario_basic() -> Result<()> { let config = ServerConfig { listen_on: "127.0.0.1:0".parse().unwrap(), server_name: "testserver".into(), }; let mut metrics = MetricsRegistry::new(); let mut storage = Storage::open(StorageConfig { db_path: ":memory:".into(), }) .await?; let rooms = RoomRegistry::new(&mut metrics, storage.clone()).unwrap(); let players = PlayerRegistry::empty(rooms.clone(), &mut metrics).unwrap(); let server = launch(config, players, rooms, metrics, storage.clone()).await.unwrap(); // test scenario storage.create_user("tester").await?; storage.set_password("tester", "password").await?; let mut stream = TcpStream::connect(server.addr).await?; let mut s = TestScope::new(&mut stream); s.expect(":testserver NOTICE * :Welcome to my server!").await?; s.send("PASS password").await?; s.send("NICK tester").await?; s.send("USER UserName 0 * :Real Name").await?; s.expect(":testserver 001 tester :Welcome to Kek Server").await?; s.expect(":testserver 002 tester :Welcome to Kek Server").await?; s.expect(":testserver 003 tester :Welcome to Kek Server").await?; s.expect(":testserver 004 tester testserver kek-0.1.alpha.3 r CFILPQbcefgijklmnopqrstvz").await?; s.expect(":testserver 005 tester CHANTYPES=# :are supported by this server").await?; stream.shutdown().await?; // wrap up server.terminate().await.unwrap(); Ok(()) }