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:
parent
ac43f7c548
commit
26183042e0
4 changed files with 964 additions and 11 deletions
777
Cargo.lock
generated
777
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -13,3 +13,6 @@ enum_dispatch = "0.1"
|
|||
|
||||
[dev-dependencies]
|
||||
maplit = "1.0"
|
||||
portpicker = "0.1.0"
|
||||
websocket-lite = "0.3.0-alpha.6"
|
||||
better-panic = "0.2.0"
|
||||
151
src/integration_tests.rs
Normal file
151
src/integration_tests.rs
Normal 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())
|
||||
}
|
||||
44
src/main.rs
44
src/main.rs
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue