Add city gameplay, snapshot migrations, administration and Compose operations
This commit is contained in:
1 parent
3b1fcd996a
commit
85df37c26e
24 files changed
+1042
-55
No files matched your search
@@ -31,6 +31,19 @@ async fn read(
|
||||
}
|
||||
}
|
||||
}
|
||||
async fn http_request(
|
||||
address: std::net::SocketAddr,
|
||||
path: &str,
|
||||
method: &str,
|
||||
token: &str,
|
||||
) -> String {
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
let mut socket = tokio::net::TcpStream::connect(address).await.unwrap();
|
||||
socket.write_all(format!("{method} {path} HTTP/1.1\r\nHost: localhost\r\nAuthorization: Bearer {token}\r\nContent-Length: 0\r\nConnection: close\r\n\r\n").as_bytes()).await.unwrap();
|
||||
let mut response = String::new();
|
||||
socket.read_to_string(&mut response).await.unwrap();
|
||||
response
|
||||
}
|
||||
#[tokio::test]
|
||||
async fn thirty_observers_snapshot_delta_vote_and_restart() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
@@ -38,6 +51,7 @@ async fn thirty_observers_snapshot_delta_vote_and_restart() {
|
||||
let app = App::new(Config {
|
||||
cities: dir.path().join("cities"),
|
||||
saves: dir.path().join("rooms"),
|
||||
admin_token: Some("test-only-administrator-token-32-chars".into()),
|
||||
..Default::default()
|
||||
})
|
||||
.unwrap();
|
||||
@@ -63,6 +77,26 @@ async fn thirty_observers_snapshot_delta_vote_and_restart() {
|
||||
let value: serde_json::Value =
|
||||
serde_json::from_str(response.split("\r\n\r\n").nth(1).unwrap()).unwrap();
|
||||
let id = value["id"].as_str().unwrap().to_string();
|
||||
assert!(http_request(address, "/api/admin", "GET", "wrong")
|
||||
.await
|
||||
.starts_with("HTTP/1.1 401"));
|
||||
assert!(http_request(
|
||||
address,
|
||||
"/api/admin",
|
||||
"GET",
|
||||
"test-only-administrator-token-32-chars"
|
||||
)
|
||||
.await
|
||||
.starts_with("HTTP/1.1 200"));
|
||||
let checkpoint = http_request(
|
||||
address,
|
||||
&format!("/api/admin/rooms/{id}/checkpoint"),
|
||||
"POST",
|
||||
"test-only-administrator-token-32-chars",
|
||||
)
|
||||
.await;
|
||||
assert!(checkpoint.starts_with("HTTP/1.1 200"), "{checkpoint}");
|
||||
assert!(citygen_server::storage::load(&dir.path().join("rooms"), &id).is_ok());
|
||||
let mut sockets = vec![];
|
||||
for i in 0..30 {
|
||||
let (mut socket, _) =
|
||||
@@ -117,6 +151,37 @@ async fn thirty_observers_snapshot_delta_vote_and_restart() {
|
||||
}
|
||||
}
|
||||
// 31st observer must be rejected without affecting existing players.
|
||||
let command = p::ClientMessage {
|
||||
body: Some(client_message::Body::Intervene(p::Intervene {
|
||||
action: "meal".into(),
|
||||
})),
|
||||
}
|
||||
.encode_to_vec();
|
||||
s.send(tokio_tungstenite::tungstenite::Message::Binary(
|
||||
command.clone().into(),
|
||||
))
|
||||
.await
|
||||
.unwrap();
|
||||
s.send(tokio_tungstenite::tungstenite::Message::Binary(
|
||||
command.into(),
|
||||
))
|
||||
.await
|
||||
.unwrap();
|
||||
loop {
|
||||
if let Some(server_message::Body::Error(error)) = read(s).await.body {
|
||||
assert_eq!(error.code, "COMMAND_LIMIT");
|
||||
break;
|
||||
}
|
||||
}
|
||||
loop {
|
||||
if let Some(server_message::Body::Gameplay(state)) = read(s).await.body {
|
||||
assert!(
|
||||
state.pending.iter().any(|p| p == "meal")
|
||||
|| state.events.iter().any(|e| e.kind == "meal")
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
let (mut extra, _) =
|
||||
tokio_tungstenite::connect_async(format!("ws://{address}/api/rooms/{id}/ws"))
|
||||
.await
|
||||
@@ -232,6 +297,14 @@ async fn thirty_observers_snapshot_delta_vote_and_restart() {
|
||||
))
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(http_request(
|
||||
address,
|
||||
"/api/admin",
|
||||
"GET",
|
||||
"test-only-administrator-token-32-chars"
|
||||
)
|
||||
.await
|
||||
.starts_with("HTTP/1.1 404"));
|
||||
assert!(
|
||||
matches!(read(&mut socket).await.body,Some(server_message::Body::Welcome(w)) if w.tick>=saved.tick)
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user