test against test server

This commit is contained in:
Robin Appelman 2020-11-26 21:52:23 +01:00
commit 7860e8df34
7 changed files with 198 additions and 75 deletions

View file

@ -18,3 +18,4 @@ steamid-ng = "0.3"
[dev-dependencies] [dev-dependencies]
tokio = { version = "0.2", features = ["macros"] } tokio = { version = "0.2", features = ["macros"] }
sqlx = { version = "0.4", features = ["postgres", "runtime-tokio-rustls"] }

31
nginx_test.conf Normal file
View file

@ -0,0 +1,31 @@
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
client_max_body_size 200m;
if ($request_method = POST ) {
rewrite /upload /do_upload last;
break;
}
location /do_upload {
fastcgi_pass api:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /app/src/public/upload.php;
}
index index.php;
try_files $uri /index.php?$query_string /index.php;
location ~ ^(.+?\.php)(/.*)?$ {
fastcgi_param PATH_INFO $2;
fastcgi_pass api:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /app/src/public/index.php;
include fastcgi_params;
}
}

View file

@ -1,10 +1,11 @@
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use serde::{Deserialize, Deserializer, Serialize}; use serde::{Deserialize, Deserializer, Serialize};
use std::fmt; use std::fmt;
use reqwest::{Client, IntoUrl, Url, StatusCode}; use reqwest::{Client, IntoUrl, Url, StatusCode, multipart};
use thiserror::Error; use thiserror::Error;
use steamid_ng::SteamID; use steamid_ng::SteamID;
use std::borrow::Cow; use std::borrow::Cow;
use std::str::FromStr;
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum Error { pub enum Error {
@ -20,6 +21,8 @@ pub enum Error {
HashMisMatch, HashMisMatch,
#[error("Unknown server error")] #[error("Unknown server error")]
ServerError(u16), ServerError(u16),
#[error("Invalid response: {0}")]
InvalidResponse(String),
} }
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Deserialize)]
@ -427,7 +430,32 @@ impl ApiClient {
_ => Ok(()) _ => Ok(())
} }
} }
}
#[cfg(test)] pub async fn upload_demo(&self, file_name: String, body: Vec<u8>, red: String, blue: String, key: String) -> Result<u32, Error> {
mod tests; let form = multipart::Form::new()
.text("red", red)
.text("blue", blue)
.text("name", file_name)
.text("key", key);
let file = multipart::Part::bytes(body)
.file_name("demo.dem")
.mime_str("text/plain")?;
let form = form.part("demo", file);
let resp = self.client.post(self.base_url.join("/upload").unwrap())
.multipart(form)
.send()
.await?
.text()
.await?;
if resp == "Invalid key" {
return Err(Error::InvalidApiKey)
}
let tail = resp.split('/').last().unwrap_or_default();
u32::from_str(tail).map_err(|_| Error::InvalidResponse(resp))
}
}

View file

@ -1,59 +0,0 @@
use crate::{ApiClient, ListParams, ListOrder, Error};
use steamid_ng::SteamID;
#[tokio::test]
async fn test_list_demos() {
let client = ApiClient::default();
let demos = client.list(ListParams::default().with_order(ListOrder::Ascending), 1).await.unwrap();
assert_eq!(demos[0].id, 9);
assert_eq!(demos[0].uploader.id(), 1);
assert!(demos[0].uploader.user().is_none());
assert_eq!(demos[0].uploader.resolve(&client).await.unwrap().steam_id, SteamID::from(76561198024494988));
}
#[tokio::test]
async fn test_get_demo() {
let client = ApiClient::default();
let demo = client.get(9).await.unwrap();
assert_eq!(demo.id, 9);
assert_eq!(demo.uploader.id(), 1);
assert!(demo.uploader.user().is_some());
assert_eq!(demo.uploader.user().unwrap().steam_id, SteamID::from(76561198024494988));
assert_eq!(demo.uploader.resolve(&client).await.unwrap().steam_id, SteamID::from(76561198024494988));
assert_eq!(demo.players[0].player_id, 623);
assert_eq!(demo.players[0].user.id, 346);
}
#[tokio::test]
async fn test_get_chat() {
let client = ApiClient::default();
let chat = client.get_chat(447678).await.unwrap();
assert_eq!(chat.len(), 10);
assert_eq!(chat[0].user, "wiitabix");
assert_eq!(chat[0].time, 5);
assert_eq!(chat[0].message, "gl hf :)))))");
}
#[tokio::test]
async fn test_get_players() {
let client = ApiClient::default();
let demos = client.list(ListParams::default().with_order(ListOrder::Ascending), 1).await.unwrap();
assert_eq!(demos[0].players.len(), 0);
assert_eq!(demos[0].get_players(&client).await.unwrap().len(), 12);
}
#[tokio::test]
async fn test_set_url_invalid_key() {
let client = ApiClient::default();
let res = client.set_url(9, "test", "test", "http://example.com/test", [0; 16], "wrong").await;
assert!(matches!(res.unwrap_err(), Error::InvalidApiKey));
}

View file

@ -4,17 +4,14 @@ docker rm -f api-test-db
docker rm -f api-test-fpm docker rm -f api-test-fpm
docker rm -f api-test docker rm -f api-test
docker run -d --name api-test-db -e POSTGRES_PASSWORD=test demostf/db mkdir -p /tmp/api-test-data
docker run -d --name api-test-fpm --link api-test-db:db -v /demos \ chmod 0777 /tmp/api-test-data
docker run -d --name api-test-db -e POSTGRES_PASSWORD=test -p 15432:5432 demostf/db
docker run -d --name api-test-fpm --link api-test-db:db -v /tmp/api-test-data:/demos \
-e DEMO_ROOT=/demos -e DEMO_HOST=localhost -e DB_TYPE=pgsql \ -e DEMO_ROOT=/demos -e DEMO_HOST=localhost -e DB_TYPE=pgsql \
-e DB_HOST=db -e DB_PORT=5432 -e DB_DATABASE=postgres -e DB_USERNAME=postgres \ -e DB_HOST=db -e DB_PORT=5432 -e DB_DATABASE=postgres -e DB_USERNAME=postgres \
-e DB_PASSWORD=test -e APP_ROOT=https://localhost -e EDIT_SECRET=edit \ -e DB_PASSWORD=test -e APP_ROOT=http://api.localhost -e EDIT_SECRET=edit \
demostf/api demostf/api
docker run -d --name api-test --link api-test-fpm:api -e HOST=localhost -e UPLOAD_FASTCGI=api:9000 \ docker run -d --name api-test --link api-test-fpm:api\
-e UPLOAD_SCRIPT=/app/src/public/upload.php -p 8888:80 demostf/demos.tf -v $(pwd)/nginx_test.conf:/etc/nginx/conf.d/api.conf:ro -p 8888:80 nginx
sleep 2
# instead of having to deal with mocking steam login we just manually create our first user
docker exec -u postgres api-test-db psql -c "INSERT INTO users(steamid, name, avatar, token)
VALUES(76561198024494988, 'Icewind', 'http://cdn.akamai.steamstatic.com/steamcommunity/public/images/avatars/75/75b84075b70535c5cfb3499af03b3e4e7a7b556f_medium.jpg', 'test_token')"

BIN
tests/data/gully.dem Normal file

Binary file not shown.

125
tests/tests.rs Normal file
View file

@ -0,0 +1,125 @@
use demostf_client::{ApiClient, ListParams, ListOrder, Error};
use steamid_ng::SteamID;
use sqlx::postgres::PgPoolOptions;
async fn test_client() -> ApiClient {
let pool = PgPoolOptions::new()
.max_connections(5)
.connect("postgres://postgres:test@localhost:15432/postgres").await.unwrap();
let tables = ["chat", "demos", "kills", "players", "storage_keys", "teams", "upload_blacklist", "users"];
let mut transaction = pool.begin().await.unwrap();
for table in &tables {
sqlx::query(&format!("TRUNCATE TABLE {}", table)).execute(&mut transaction).await.unwrap();
sqlx::query(&format!("ALTER SEQUENCE {}_id_seq RESTART with 1", table)).execute(&mut transaction).await.unwrap();
}
sqlx::query("INSERT INTO users(steamid, name, avatar, token)\
VALUES(76561198024494988, 'Icewind', 'http://cdn.akamai.steamstatic.com/steamcommunity/public/images/avatars/75/75b84075b70535c5cfb3499af03b3e4e7a7b556f_medium.jpg', 'test_token')")
.execute(&mut transaction).await.unwrap();
transaction.commit().await.unwrap();
ApiClient::with_base_url("http://localhost:8888").unwrap()
}
#[tokio::test]
async fn test_get_user() {
let client = test_client().await;
let user = client.get_user(1).await.unwrap();
assert_eq!("Icewind", user.name);
}
async fn upload(client: &ApiClient, source: &str, name: &str, red: &str, blue: &str) -> u32 {
let data = std::fs::read(source).unwrap();
client.upload_demo(name.to_string(), data, red.to_string(), blue.to_string(), "test_token".to_string()).await.unwrap()
}
#[tokio::test]
async fn test_upload_invalid_key() {
let client = test_client().await;
let data = std::fs::read("./tests/data/gully.dem").unwrap();
let err = client.upload_demo("name.dem".to_string(), data, "red".to_string(), "blue".to_string(), "wrong_token".to_string()).await.unwrap_err();
assert!(matches!(err, Error::InvalidApiKey));
}
#[tokio::test]
async fn test_list_demos() {
let client = test_client().await;
let id = upload(&client, "./tests/data/gully.dem", "test.dem", "R", "B").await;
assert_eq!(1, id);
let demos = client.list(ListParams::default().with_order(ListOrder::Ascending), 1).await.unwrap();
assert_eq!(demos[0].id, 1);
assert_eq!(demos[0].uploader.id(), 1);
assert!(demos[0].uploader.user().is_none());
assert_eq!(demos[0].uploader.resolve(&client).await.unwrap().steam_id, SteamID::from(76561198024494988));
assert_eq!(demos[0].player_count, 12);
assert_eq!(demos[0].name, "test.dem");
assert_eq!(demos[0].red_score, 5);
assert_eq!(demos[0].blue_score, 3);
}
#[tokio::test]
async fn test_get_demo() {
let client = test_client().await;
let id = upload(&client, "./tests/data/gully.dem", "test.dem", "R", "B").await;
let demo = client.get(id).await.unwrap();
assert_eq!(demo.id, id);
assert_eq!(demo.uploader.id(), 1);
assert!(demo.uploader.user().is_some());
assert_eq!(demo.uploader.user().unwrap().steam_id, SteamID::from(76561198024494988));
assert_eq!(demo.uploader.resolve(&client).await.unwrap().steam_id, SteamID::from(76561198024494988));
assert_eq!(demo.players[0].player_id, 1);
assert_eq!(demo.players[0].user.id, 2);
assert_eq!(demo.players[0].user.name, "distraughtduck4");
}
#[tokio::test]
async fn test_get_chat() {
let client = test_client().await;
upload(&client, "./tests/data/gully.dem", "test.dem", "R", "B").await;
let chat = client.get_chat(1).await.unwrap();
assert_eq!(chat.len(), 134);
assert_eq!(chat[0].user, "distraughtduck4");
assert_eq!(chat[0].time, 0);
assert_eq!(chat[0].message, "[P-REC] Recording...");
}
#[tokio::test]
async fn test_get_players() {
let client = test_client().await;
upload(&client, "./tests/data/gully.dem", "test.dem", "R", "B").await;
let demos = client.list(ListParams::default().with_order(ListOrder::Ascending), 1).await.unwrap();
assert_eq!(demos[0].players.len(), 0);
assert_eq!(demos[0].get_players(&client).await.unwrap().len(), 12);
}
#[tokio::test]
async fn test_set_url_invalid_key() {
let client = test_client().await;
let res = client.set_url(9, "tests", "tests", "http://example.com/tests", [0; 16], "wrong").await;
assert!(matches!(res.unwrap_err(), Error::InvalidApiKey));
}