forked from lavina/lavina
139 lines
4.6 KiB
Rust
139 lines
4.6 KiB
Rust
|
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<ReadHalf<'_>>, buf: &mut Vec<u8>) -> Result<usize> {
|
||
|
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<u8>,
|
||
|
pub timeout: Duration,
|
||
|
}
|
||
|
|
||
|
enum TestSocket<'a> {
|
||
|
Unencrypted {
|
||
|
reader: NsReader<BufReader<ReadHalf<'a>>>,
|
||
|
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<Event<'_>> {
|
||
|
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<T: FromXml>(&mut self) -> Result<T> {
|
||
|
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, anyhow::Error>> = 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#"<?xml version="1.0"?>"#).await?;
|
||
|
s.send(r#"<stream:stream xmlns:stream="http://etherx.jabber.org/streams" to="vilunov.me" xml:lang="en" xmlns:xml="http://www.w3.org/XML/1998/namespace" xmlns="jabber:client" version="1.0">"#).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(())
|
||
|
}
|