mirror of
https://codeberg.org/demostf/api-client.git
synced 2026-06-03 16:44:09 +02:00
test against test server
This commit is contained in:
parent
1819854997
commit
7860e8df34
7 changed files with 198 additions and 75 deletions
|
|
@ -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
31
nginx_test.conf
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
34
src/lib.rs
34
src/lib.rs
|
|
@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn upload_demo(&self, file_name: String, body: Vec<u8>, red: String, blue: String, key: String) -> Result<u32, Error> {
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
let tail = resp.split('/').last().unwrap_or_default();
|
||||||
mod tests;
|
u32::from_str(tail).map_err(|_| Error::InvalidResponse(resp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
59
src/tests.rs
59
src/tests.rs
|
|
@ -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));
|
|
||||||
}
|
|
||||||
|
|
@ -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
BIN
tests/data/gully.dem
Normal file
Binary file not shown.
125
tests/tests.rs
Normal file
125
tests/tests.rs
Normal 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));
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue