From a34f32dc152ae29dc9ac4c8d8529b5515305d6e9 Mon Sep 17 00:00:00 2001 From: eraden Date: Sun, 5 Jun 2022 21:03:22 +0200 Subject: [PATCH] Additional tests, macros for tests --- Cargo.lock | 5 + Cargo.toml | 1 + actors/database_manager/Cargo.toml | 3 + .../database_manager/src/account_addresses.rs | 12 +- actors/database_manager/src/accounts.rs | 83 ++-------- actors/database_manager/src/stocks.rs | 60 ++++--- actors/database_manager/src/tokens.rs | 154 +++++++++--------- shared/model/src/lib.rs | 2 +- shared/testx/Cargo.toml | 6 + shared/testx/src/lib.rs | 21 +++ 10 files changed, 171 insertions(+), 176 deletions(-) create mode 100644 shared/testx/Cargo.toml create mode 100644 shared/testx/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 60fb911..3737bd3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1162,6 +1162,7 @@ dependencies = [ "serde", "sqlx", "sqlx-core", + "testx", "thiserror", "uuid 0.8.2", ] @@ -3830,6 +3831,10 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "testx" +version = "0.1.0" + [[package]] name = "thiserror" version = "1.0.31" diff --git a/Cargo.toml b/Cargo.toml index 3022ab9..2b51dec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "shared/model", "shared/bus", "shared/config", + "shared/testx", # actors "actors/account_manager", "actors/cart_manager", diff --git a/actors/database_manager/Cargo.toml b/actors/database_manager/Cargo.toml index 75fcef3..65b7aa7 100644 --- a/actors/database_manager/Cargo.toml +++ b/actors/database_manager/Cargo.toml @@ -30,3 +30,6 @@ rand = { version = "0.8.5", optional = true } itertools = { version = "0.10.3" } serde = { version = "1.0", features = ["derive"] } + +[dev-dependencies] +testx = { path = "../../shared/testx" } diff --git a/actors/database_manager/src/account_addresses.rs b/actors/database_manager/src/account_addresses.rs index 45c74aa..2a06621 100644 --- a/actors/database_manager/src/account_addresses.rs +++ b/actors/database_manager/src/account_addresses.rs @@ -248,15 +248,7 @@ mod test { #[actix::test] async fn full_check() { - let config = config::default_load(&mut NoOpts); - config - .lock() - .database_mut() - .set_url("postgres://postgres@localhost/bazzar_test"); - - let db = Database::build(config).await; - let pool = db.pool(); - let mut t = pool.begin().await.unwrap(); + testx::db_t!(t); // account let account = test_create_account(&mut t).await; @@ -351,7 +343,7 @@ mod test { .await .unwrap(); - t.rollback().await.unwrap(); + testx::db_rollback!(t); assert_eq!(default_address, address); } } diff --git a/actors/database_manager/src/accounts.rs b/actors/database_manager/src/accounts.rs index c2a798f..83d43b9 100644 --- a/actors/database_manager/src/accounts.rs +++ b/actors/database_manager/src/accounts.rs @@ -268,15 +268,7 @@ mod tests { #[actix::test] async fn create_account() { - let config = config::default_load(&mut NoOpts); - config - .lock() - .database_mut() - .set_url("postgres://postgres@localhost/bazzar_test"); - - let db = Database::build(config).await; - let pool = db.pool(); - let mut t = pool.begin().await.unwrap(); + testx::db_t!(t); let login: String = fake::faker::internet::en::Username().fake(); let email: String = fake::faker::internet::en::FreeEmail().fake(); @@ -310,36 +302,21 @@ mod tests { #[actix::test] async fn all_accounts() { - let config = config::default_load(&mut NoOpts); - config - .lock() - .database_mut() - .set_url("postgres://postgres@localhost/bazzar_test"); - - let db = Database::build(config).await; - let pool = db.pool(); - let mut t = pool.begin().await.unwrap(); + testx::db_t!(t); test_create_account(&mut t, None, None, None).await; test_create_account(&mut t, None, None, None).await; test_create_account(&mut t, None, None, None).await; let v: Vec = super::all_accounts(AllAccounts, &mut t).await.unwrap(); + + testx::db_rollback!(t); assert!(v.len() >= 3); - t.rollback().await.unwrap(); } #[actix::test] async fn update_account_without_pass() { - let config = config::default_load(&mut NoOpts); - config - .lock() - .database_mut() - .set_url("postgres://postgres@localhost/bazzar_test"); - - let db = Database::build(config).await; - let pool = db.pool(); - let mut t = pool.begin().await.unwrap(); + testx::db_t!(t); let original_login: String = fake::faker::internet::en::Username().fake(); let original_email: String = fake::faker::internet::en::FreeEmail().fake(); @@ -380,22 +357,14 @@ mod tests { state: AccountState::Active, }; - t.rollback().await.unwrap(); + testx::db_rollback!(t); assert_ne!(original_account, expected); assert_eq!(updated_account, expected); } #[actix::test] async fn update_account_with_pass() { - let config = config::default_load(&mut NoOpts); - config - .lock() - .database_mut() - .set_url("postgres://postgres@localhost/bazzar_test"); - - let db = Database::build(config).await; - let pool = db.pool(); - let mut t = pool.begin().await.unwrap(); + testx::db_t!(t); let original_login: String = fake::faker::internet::en::Username().fake(); let original_email: String = fake::faker::internet::en::FreeEmail().fake(); @@ -437,22 +406,14 @@ mod tests { state: AccountState::Active, }; - t.rollback().await.unwrap(); + testx::db_rollback!(t); assert_ne!(original_account, expected); assert_eq!(updated_account, expected); } #[actix::test] async fn find() { - let config = config::default_load(&mut NoOpts); - config - .lock() - .database_mut() - .set_url("postgres://postgres@localhost/bazzar_test"); - - let db = Database::build(config).await; - let pool = db.pool(); - let mut t = pool.begin().await.unwrap(); + testx::db_t!(t); let account = test_create_account(&mut t, None, None, None).await; @@ -465,21 +426,13 @@ mod tests { .await .unwrap(); - t.rollback().await.unwrap(); + testx::db_rollback!(t); assert_eq!(account, res); } #[actix::test] async fn find_identity_email() { - let config = config::default_load(&mut NoOpts); - config - .lock() - .database_mut() - .set_url("postgres://postgres@localhost/bazzar_test"); - - let db = Database::build(config).await; - let pool = db.pool(); - let mut t = pool.begin().await.unwrap(); + testx::db_t!(t); let account = test_create_account(&mut t, None, None, None).await; @@ -493,21 +446,13 @@ mod tests { .await .unwrap(); - t.rollback().await.unwrap(); + testx::db_rollback!(t); assert_eq!(account, res); } #[actix::test] async fn find_identity_login() { - let config = config::default_load(&mut NoOpts); - config - .lock() - .database_mut() - .set_url("postgres://postgres@localhost/bazzar_test"); - - let db = Database::build(config).await; - let pool = db.pool(); - let mut t = pool.begin().await.unwrap(); + testx::db_t!(t); let account = test_create_account(&mut t, None, None, None).await; @@ -521,7 +466,7 @@ mod tests { .await .unwrap(); - t.rollback().await.unwrap(); + testx::db_rollback!(t); assert_eq!(account, res); } } diff --git a/actors/database_manager/src/stocks.rs b/actors/database_manager/src/stocks.rs index 93ad515..3020538 100644 --- a/actors/database_manager/src/stocks.rs +++ b/actors/database_manager/src/stocks.rs @@ -31,6 +31,7 @@ async fn all_stocks( r#" SELECT id, product_id, quantity, quantity_unit FROM stocks +ORDER BY id ASC "#, ) .fetch_all(pool) @@ -235,30 +236,16 @@ mod tests { #[actix::test] async fn create_stock() { - let config = config::default_load(&mut NoOpts); - config - .lock() - .database_mut() - .set_url("postgres://postgres@localhost/bazzar_test"); + testx::db_t!(t); - let db = Database::build(config).await; - let pool = db.pool(); - let mut t = pool.begin().await.unwrap(); test_stock(&mut t, None, None, None).await; - t.rollback().await.unwrap(); + + testx::db_rollback!(t); } #[actix::test] async fn products_stock() { - let config = config::default_load(&mut NoOpts); - config - .lock() - .database_mut() - .set_url("postgres://postgres@localhost/bazzar_test"); - - let db = Database::build(config).await; - let pool = db.pool(); - let mut t = pool.begin().await.unwrap(); + testx::db_t!(t); let first = test_stock(&mut t, None, None, None).await; let second = test_stock(&mut t, None, None, None).await; @@ -272,7 +259,42 @@ mod tests { .await .unwrap(); - t.rollback().await.unwrap(); + testx::db_rollback!(t); assert_eq!(stocks, vec![first, second]); } + + #[actix::test] + async fn all_stocks() { + testx::db_t!(t); + + let first = test_stock(&mut t, None, None, None).await; + let second = test_stock(&mut t, None, None, None).await; + + let stocks: Vec = super::all_stocks(AllStocks, &mut t).await.unwrap(); + + testx::db_rollback!(t); + assert_eq!(stocks, vec![first, second]); + } + + #[actix::test] + async fn delete_stock() { + testx::db_t!(t); + + let first = test_stock(&mut t, None, None, None).await; + let second = test_stock(&mut t, None, None, None).await; + + let deleted: Option = super::delete_stock( + DeleteStock { + stock_id: second.id, + }, + &mut t, + ) + .await + .unwrap(); + // let reloaded = super::Stock + + testx::db_rollback!(t); + assert_eq!(deleted, Some(second)); + assert_ne!(deleted, Some(first)); + } } diff --git a/actors/database_manager/src/tokens.rs b/actors/database_manager/src/tokens.rs index 1759e0c..7c94d77 100644 --- a/actors/database_manager/src/tokens.rs +++ b/actors/database_manager/src/tokens.rs @@ -1,6 +1,5 @@ use actix::Message; use model::{AccountId, Audience, Token}; -use sqlx::PgPool; use crate::{db_async_handler, Result}; @@ -36,16 +35,19 @@ pub struct TokenByJti { pub jti: uuid::Uuid, } -db_async_handler!(TokenByJti, token_by_jti, Token); +db_async_handler!(TokenByJti, token_by_jti, Token, inner_token_by_jti); -pub(crate) async fn token_by_jti(msg: TokenByJti, pool: PgPool) -> Result { +pub(crate) async fn token_by_jti( + msg: TokenByJti, + t: &mut sqlx::Transaction<'_, sqlx::Postgres>, +) -> Result { sqlx::query_as(r#" SELECT id, customer_id, role, issuer, subject, audience, expiration_time, not_before_time, issued_at_time, jwt_id FROM tokens WHERE jwt_id = $1 AND expiration_time > now() "#) .bind(msg.jti) - .fetch_one(&pool) + .fetch_one(t) .await .map_err(|e| { log::error!("{e:?}"); @@ -62,9 +64,12 @@ pub struct CreateToken { pub audience: Audience, } -db_async_handler!(CreateToken, create_token, Token); +db_async_handler!(CreateToken, create_token, Token, inner_create_token); -pub(crate) async fn create_token(msg: CreateToken, pool: PgPool) -> Result { +pub(crate) async fn create_token( + msg: CreateToken, + t: &mut sqlx::Transaction<'_, sqlx::Postgres>, +) -> Result { let CreateToken { customer_id, role, @@ -80,7 +85,7 @@ RETURNING id, customer_id, role, issuer, subject, audience, expiration_time, not .bind(role) .bind(subject) .bind(audience) - .fetch_one(&pool) + .fetch_one(t) .await .map_err(|e| { log::error!("{e:?}"); @@ -98,9 +103,17 @@ pub struct CreateExtendedToken { pub expiration_time: chrono::NaiveDateTime, } -db_async_handler!(CreateExtendedToken, create_extended_token, Token); +db_async_handler!( + CreateExtendedToken, + create_extended_token, + Token, + inner_create_extended_token +); -pub(crate) async fn create_extended_token(msg: CreateExtendedToken, pool: PgPool) -> Result { +pub(crate) async fn create_extended_token( + msg: CreateExtendedToken, + t: &mut sqlx::Transaction<'_, sqlx::Postgres>, +) -> Result { let CreateExtendedToken { customer_id, role, @@ -118,7 +131,7 @@ RETURNING id, customer_id, role, issuer, subject, audience, expiration_time, not .bind(subject) .bind(audience) .bind(expiration_time) - .fetch_one(&pool) + .fetch_one(t) .await .map_err(|e| { log::error!("{e:?}"); @@ -128,7 +141,6 @@ RETURNING id, customer_id, role, issuer, subject, audience, expiration_time, not #[cfg(test)] mod tests { - use actix::Addr; use config::UpdateConfig; use fake::Fake; use model::*; @@ -140,25 +152,27 @@ mod tests { impl UpdateConfig for NoOpts {} - async fn test_create_account(db: Addr) -> FullAccount { + async fn test_create_account(t: &mut sqlx::Transaction<'_, sqlx::Postgres>) -> FullAccount { use fake::faker::internet::en; let login: String = en::Username().fake(); let email: String = en::FreeEmail().fake(); let hash: String = en::Password(10..20).fake(); - db.send(CreateAccount { - email: Email::new(email), - login: Login::new(login), - pass_hash: PassHash::new(hash), - role: Role::Admin, - }) + crate::create_account( + CreateAccount { + email: Email::new(email), + login: Login::new(login), + pass_hash: PassHash::new(hash), + role: Role::Admin, + }, + t, + ) .await .unwrap() - .unwrap() } async fn test_create_token_extended( - db: Addr, + t: &mut sqlx::Transaction<'_, sqlx::Postgres>, customer_id: Option, role: Option, subject: Option, @@ -169,93 +183,77 @@ mod tests { let role = role.unwrap_or_else(|| Role::Admin); let subject = match subject { Some(id) => id, - _ => test_create_account(db.clone()).await.id, + _ => test_create_account(t).await.id, }; let audience = audience.unwrap_or_else(|| Audience::Web); let expiration_time = expiration_time .unwrap_or_else(|| (chrono::Utc::now() + chrono::Duration::days(60)).naive_utc()); - db.send(CreateExtendedToken { - customer_id, - role, - subject, - audience, - expiration_time, - }) + super::create_extended_token( + CreateExtendedToken { + customer_id, + role, + subject, + audience, + expiration_time, + }, + t, + ) .await .unwrap() - .unwrap() } #[actix::test] async fn create_token() { - let config = config::default_load(&mut NoOpts); - config - .lock() - .database_mut() - .set_url("postgres://postgres@localhost/bazzar_test"); + testx::db_t!(t); - let db = Database::build(config).await.start(); - - db.send(CreateToken { - customer_id: Uuid::new_v4(), - role: Role::Admin, - subject: test_create_account(db.clone()).await.id, - audience: Audience::Web, - }) + super::create_token( + CreateToken { + customer_id: Uuid::new_v4(), + role: Role::Admin, + subject: test_create_account(&mut t).await.id, + audience: Audience::Web, + }, + &mut t, + ) .await - .unwrap() .unwrap(); } #[actix::test] async fn create_extended_token() { - let config = config::default_load(&mut NoOpts); - config - .lock() - .database_mut() - .set_url("postgres://postgres@localhost/bazzar_test"); + testx::db_t!(t); - let db = Database::build(config).await.start(); + test_create_account(&mut t).await; - test_create_account(db).await; + testx::db_rollback!(t); } #[actix::test] async fn find_by_jti() { - let config = config::default_load(&mut NoOpts); - config - .lock() - .database_mut() - .set_url("postgres://postgres@localhost/bazzar_test"); + testx::db_t!(t); - let db = Database::build(config).await.start(); + let original = test_create_token_extended(&mut t, None, None, None, None, None).await; - let original = test_create_token_extended(db.clone(), None, None, None, None, None).await; - - let found = db - .send(TokenByJti { + let found = super::token_by_jti( + TokenByJti { jti: original.jwt_id, - }) - .await - .unwrap() - .unwrap(); + }, + &mut t, + ) + .await + .unwrap(); + testx::db_rollback!(t); assert_eq!(found, original); } #[actix::test] async fn find_by_jti_expired() { - let config = config::default_load(&mut NoOpts); - config - .lock() - .database_mut() - .set_url("postgres://postgres@localhost/bazzar_test"); - - let db = Database::build(config).await.start(); + testx::db_t!(t); let original = test_create_token_extended( - db.clone(), + &mut t, None, None, None, @@ -264,13 +262,15 @@ mod tests { ) .await; - let found = db - .send(TokenByJti { + let found = super::token_by_jti( + TokenByJti { jti: original.jwt_id, - }) - .await - .unwrap(); + }, + &mut t, + ) + .await; + testx::db_rollback!(t); assert_eq!(found, Err(crate::Error::Token(super::Error::Jti))); } } diff --git a/shared/model/src/lib.rs b/shared/model/src/lib.rs index 5f0092d..4fcaa5f 100644 --- a/shared/model/src/lib.rs +++ b/shared/model/src/lib.rs @@ -862,7 +862,7 @@ pub struct Product { #[cfg_attr(feature = "dummy", derive(fake::Dummy))] #[cfg_attr(feature = "db", derive(sqlx::Type))] #[cfg_attr(feature = "db", sqlx(transparent))] -#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Copy, Clone, Serialize, Deserialize)] #[serde(transparent)] pub struct StockId(pub RecordId); diff --git a/shared/testx/Cargo.toml b/shared/testx/Cargo.toml new file mode 100644 index 0000000..e50238b --- /dev/null +++ b/shared/testx/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "testx" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/shared/testx/src/lib.rs b/shared/testx/src/lib.rs new file mode 100644 index 0000000..cf1545b --- /dev/null +++ b/shared/testx/src/lib.rs @@ -0,0 +1,21 @@ +#[macro_export] +macro_rules! db_t { + ($t: ident) => { + let config = config::default_load(&mut NoOpts); + config + .lock() + .database_mut() + .set_url("postgres://postgres@localhost/bazzar_test"); + + let db = Database::build(config).await; + let pool = db.pool(); + let mut $t = pool.begin().await.unwrap(); + }; +} + +#[macro_export] +macro_rules! db_rollback { + ($t: expr) => { + $t.rollback().await.unwrap(); + }; +}