use std::sync::Arc; use std::time::Duration; use anyhow::Result; use assert_matches::*; use prometheus::Registry as MetricsRegistry; use proto_xmpp::xml::{Continuation, FromXml, Parser}; use quick_xml::events::Event; use quick_xml::NsReader; use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader}; use tokio::net::tcp::{ReadHalf, WriteHalf}; use tokio::net::TcpStream; use lavina_core::player::PlayerRegistry; use lavina_core::repo::{Storage, StorageConfig}; use lavina_core::room::RoomRegistry; use projection_xmpp::{launch, ServerConfig}; use tokio_rustls::{TlsConnector, Connect}; use tokio_rustls::rustls::ClientConfig; pub async fn read_irc_message(reader: &mut BufReader>, buf: &mut Vec) -> Result { let mut size = 0; let res = reader.read_until(b'\n', buf).await?; size += res; return Ok(size); } struct TestScope<'a> { socket: TestSocket<'a>, buffer: Vec, pub timeout: Duration, } enum TestSocket<'a> { Unencrypted { reader: NsReader>>, writer: WriteHalf<'a>, }, } impl<'a> TestScope<'a> { fn new(stream: &mut TcpStream) -> TestScope<'_> { let (reader, writer) = stream.split(); let reader = NsReader::from_reader(BufReader::new(reader)); let buffer = vec![]; let timeout = Duration::from_millis(100); let socket = TestSocket::Unencrypted { reader, writer }; TestScope { socket, buffer, timeout, } } async fn send(&mut self, str: &str) -> Result<()> { match &mut self.socket { TestSocket::Unencrypted { reader: _, writer } => { writer.write_all(str.as_bytes()).await?; writer.write_all(b"\n").await?; writer.flush().await?; } } Ok(()) } async fn next_xml_event(&mut self) -> Result> { self.buffer.clear(); let event = match &mut self.socket { TestSocket::Unencrypted { reader, writer: _ } => { reader.read_event_into_async(&mut self.buffer).await? } }; Ok(event) } async fn read(&mut self) -> Result { self.buffer.clear(); let reader = match &mut self.socket { TestSocket::Unencrypted { reader, writer } => reader, }; let (ns, event) = reader.read_resolved_event_into_async(&mut self.buffer).await?; let mut parser: Continuation<_, std::result::Result> = T::parse().consume(ns, &event); loop { match parser { Continuation::Final(res) => return Ok(res?), Continuation::Continue(next) => { let (ns, event) = reader.read_resolved_event_into_async(&mut self.buffer).await?; parser = next.consume(ns, &event); } } } } async fn init_tls(&mut self) -> Result<()> { let mut root_store = tokio_rustls::rustls::RootCertStore::empty(); let connector = TlsConnector::from(Arc::new(ClientConfig::builder().with_safe_defaults().with_root_certificates(root_store).with_no_client_auth())); connector.connect(domain, stream) todo!() } } #[tokio::test] async fn scenario_basic() -> Result<()> { tracing_subscriber::fmt::init(); let config = ServerConfig { listen_on: "127.0.0.1:0".parse().unwrap(), cert: "tests/certs/xmpp.pem".parse().unwrap(), key: "tests/certs/xmpp.key".parse().unwrap(), }; 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.send(r#""#).await?; s.send(r#""#).await?; assert_matches!(s.next_xml_event().await?, Event::Decl(_) => {}); assert_matches!(s.next_xml_event().await?, Event::Start(b) => assert_eq!(b.local_name().into_inner(), b"stream")); stream.shutdown().await?; // wrap up server.terminate().await?; Ok(()) }