1
0
Fork 0
mirror of https://codeberg.org/demostf/sync.git synced 2026-06-03 16:44:07 +02:00

initial integration tests

This commit is contained in:
Robin Appelman 2019-10-27 17:54:48 +01:00
commit 26183042e0
4 changed files with 964 additions and 11 deletions

151
src/integration_tests.rs Normal file
View file

@ -0,0 +1,151 @@
use crate::{spawn_local_server, SyncCommand};
use portpicker::pick_unused_port;
use std::thread::sleep;
use std::time::Duration;
use websocket_lite::{Client, ClientBuilder, Message, NetworkStream};
use ws::Sender;
const DELAY: Duration = Duration::from_millis(50);
struct TestHandle {
server_sender: Sender,
connect: String,
}
impl TestHandle {
pub fn new() -> Self {
better_panic::install();
let port = pick_unused_port().expect("No ports free");
let server_sender = spawn_local_server(port);
// give the server some time to start
sleep(DELAY);
TestHandle {
server_sender,
connect: format!("ws://localhost:{}", port),
}
}
pub fn get_client(&self) -> Client<Box<dyn NetworkStream + Sync + Send + 'static>> {
ClientBuilder::new(&self.connect)
.unwrap()
.connect()
.unwrap()
}
}
impl Drop for TestHandle {
fn drop(&mut self) {
self.server_sender.shutdown().unwrap()
}
}
#[test]
fn integration_tests() {
let test = TestHandle::new();
let mut owner = test.get_client();
let mut client = test.get_client();
send(
&mut owner,
SyncCommand::Create {
session: "foo".to_string(),
token: "bar".to_string(),
},
);
send(
&mut owner,
SyncCommand::Tick {
session: "foo".to_string(),
tick: 99,
},
);
send(
&mut client,
SyncCommand::Join {
session: "foo".to_string(),
},
);
assert_eq!(
Some(SyncCommand::Tick {
session: "foo".to_string(),
tick: 99,
}),
receive(&mut client)
);
assert_eq!(
Some(SyncCommand::Play {
session: "foo".to_string(),
play: false
}),
receive(&mut client)
);
send(
&mut owner,
SyncCommand::Play {
session: "foo".to_string(),
play: true,
},
);
assert_eq!(
Some(SyncCommand::Play {
session: "foo".to_string(),
play: true
}),
receive(&mut client)
);
// should be ignored
send(
&mut client,
SyncCommand::Tick {
session: "foo".to_string(),
tick: 5,
},
);
let mut client2 = test.get_client();
send(
&mut client2,
SyncCommand::Join {
session: "foo".to_string(),
},
);
assert_eq!(
Some(SyncCommand::Tick {
session: "foo".to_string(),
tick: 99,
}),
receive(&mut client2)
);
assert_eq!(
Some(SyncCommand::Play {
session: "foo".to_string(),
play: true
}),
receive(&mut client2)
);
}
fn send<T: std::io::Write>(client: &mut Client<T>, command: SyncCommand) {
client
.send(Message::text(&serde_json::to_string(&command).unwrap()))
.unwrap();
sleep(DELAY);
}
fn receive<T: std::io::Read>(client: &mut Client<T>) -> Option<SyncCommand> {
client
.receive()
.unwrap()
.and_then(|message| message.as_text().map(|s| s.to_string()))
.map(|text| serde_json::from_str(&text).unwrap())
}

View file

@ -14,7 +14,7 @@ use std::time::{Duration, Instant};
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
#[serde(tag = "type")]
#[serde(rename_all = "lowercase")]
enum SyncCommand {
pub enum SyncCommand {
Create { session: String, token: String },
Join { session: String },
Tick { session: String, tick: u64 },
@ -182,13 +182,42 @@ impl Handler for Server {
}
}
/// Used to spawn a server in integration tests
#[cfg(test)]
pub fn spawn_local_server(port: u16) -> ws::Sender {
use std::sync::mpsc::channel;
use std::thread::spawn;
use ws::WebSocket;
let listen_address = format!("localhost:{}", port);
let (tx, rx) = channel();
spawn(move || {
let sessions: Rc<RefCell<HashMap<String, Session>>> = Rc::default();
let ws = WebSocket::new(|out: ws::Sender| Server {
out: out.into(),
sessions: sessions.clone(),
})
.unwrap();
let ws = ws.bind(listen_address).unwrap();
tx.send(ws.broadcaster()).unwrap();
ws.run().unwrap();
});
rx.recv().unwrap()
}
fn main() {
let port = std::env::var("PORT").unwrap_or_else(|_| "80".to_string());
let listen_address = format!("0.0.0.0:{}", port);
println!("listening on: {:?}", listen_address);
let sessions: Rc<RefCell<HashMap<String, Session>>> = Rc::new(RefCell::new(HashMap::new()));
let sessions: Rc<RefCell<HashMap<String, Session>>> = Rc::default();
listen(listen_address, |out| Server {
out: out.into(),
@ -418,11 +447,11 @@ mod tests {
vec![
SyncCommand::Tick {
session: "test".into(),
tick: 99
tick: 99,
},
SyncCommand::Play {
session: "test".into(),
play: true
play: true,
}
],
mock.received()
@ -516,8 +545,8 @@ mod tests {
assert_eq!(
vec![SyncCommand::Tick {
session: "test".into(),
tick: 999
},],
tick: 999,
}],
mock.received()
);
};
@ -569,3 +598,6 @@ mod tests {
};
}
}
#[cfg(test)]
mod integration_tests;