From 8f6b34db10c591507271845150314be7a07cee19 Mon Sep 17 00:00:00 2001 From: Ilion Beyst Date: Fri, 30 Sep 2022 17:28:24 +0200 Subject: [PATCH] add integration test stub --- planetwars-server/Cargo.toml | 4 +- planetwars-server/src/lib.rs | 23 +++++++---- planetwars-server/tests/integration.rs | 57 ++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 9 deletions(-) create mode 100644 planetwars-server/tests/integration.rs diff --git a/planetwars-server/Cargo.toml b/planetwars-server/Cargo.toml index 2b3916c..6fb46d5 100644 --- a/planetwars-server/Cargo.toml +++ b/planetwars-server/Cargo.toml @@ -49,4 +49,6 @@ shlex = "1.1" tonic-build = "0.7.2" [dev-dependencies] -parking_lot = "0.11" +tower = { version = "0.4", features = ["util"] } +parking_lot = "0.12" +tempfile = "3" \ No newline at end of file diff --git a/planetwars-server/src/lib.rs b/planetwars-server/src/lib.rs index 6018eee..1301adb 100644 --- a/planetwars-server/src/lib.rs +++ b/planetwars-server/src/lib.rs @@ -112,7 +112,8 @@ fn init_directories(config: &GlobalConfig) -> std::io::Result<()> { Ok(()) } -pub fn api() -> Router { +// just the routes, without connecting state +fn api() -> Router { Router::new() .route("/register", post(routes::users::register)) .route("/login", post(routes::users::login)) @@ -140,6 +141,14 @@ pub fn api() -> Router { .route("/save_bot", post(routes::bots::save_bot)) } +// full service +pub fn create_pw_api(global_config: Arc, db_pool: DbPool) -> Router { + Router::new() + .nest("/api", api()) + .layer(Extension(db_pool)) + .layer(Extension(global_config)) +} + pub fn get_config() -> Result { config::Config::builder() .add_source(config::File::with_name("configuration.toml")) @@ -175,16 +184,14 @@ pub async fn run_app() { tokio::spawn(run_registry(global_config.clone(), db_pool.clone())); tokio::spawn(run_client_api(global_config.clone(), db_pool.clone())); - let api_service = Router::new() - .nest("/api", api()) - .layer(Extension(db_pool)) - .layer(Extension(global_config)) - .into_make_service(); - // TODO: put in config let addr = SocketAddr::from(([127, 0, 0, 1], 9000)); - axum::Server::bind(&addr).serve(api_service).await.unwrap(); + let pw_api_service = create_pw_api(global_config, db_pool).into_make_service(); + axum::Server::bind(&addr) + .serve(pw_api_service) + .await + .unwrap(); } // we can also write a custom extractor that grabs a connection from the pool diff --git a/planetwars-server/tests/integration.rs b/planetwars-server/tests/integration.rs new file mode 100644 index 0000000..29589ad --- /dev/null +++ b/planetwars-server/tests/integration.rs @@ -0,0 +1,57 @@ +use axum::{ + body::Body, + http::{self, Request, StatusCode}, +}; +use planetwars_server::{create_db_pool, create_pw_api, GlobalConfig}; +use serde_json::{self, json, Value as JsonValue}; +use std::{io, path::Path, sync::Arc}; +use tempfile::TempDir; +use tower::ServiceExt; + +// Used to serialize tests that access the database. +// TODO: see to what degree we could support transactional testing. +static DB_LOCK: parking_lot::Mutex<()> = parking_lot::Mutex::new(()); + +fn create_subdir>(base_path: &Path, p: P) -> io::Result { + let dir_path = base_path.join(p); + std::fs::create_dir(&dir_path)?; + let dir_path_string = dir_path.into_os_string().into_string().unwrap(); + Ok(dir_path_string) +} + +#[tokio::test] +async fn test_application() -> io::Result<()> { + let _db_guard = DB_LOCK.lock(); + let data_dir = TempDir::new().expect("failed to create temp dir"); + let config = Arc::new(GlobalConfig { + database_url: "postgresql://planetwars:planetwars@localhost/planetwars-test".to_string(), + python_runner_image: "python:3.10-slim-buster".to_string(), + container_registry_url: "localhost:9001".to_string(), + root_url: "localhost:3000".to_string(), + bots_directory: create_subdir(data_dir.path(), "bots")?, + match_logs_directory: create_subdir(data_dir.path(), "matches")?, + maps_directory: create_subdir(data_dir.path(), "maps")?, + registry_directory: create_subdir(data_dir.path(), "registry")?, + registry_admin_password: "secret_admin_password".to_string(), + ranker_enabled: false, + }); + let db_pool = create_db_pool(&config).await; + let app = create_pw_api(config, db_pool); + + let response = app + .oneshot( + Request::builder() + .method(http::Method::GET) + .uri("/api/bots") + .body(Body::empty()) + .unwrap(), + ) + .await + .unwrap(); + + assert_eq!(response.status(), StatusCode::OK); + let body = hyper::body::to_bytes(response.into_body()).await.unwrap(); + let resp: JsonValue = serde_json::from_slice(&body).unwrap(); + assert_eq!(resp, json!([])); + Ok(()) +}