Additional tests, macros for tests

This commit is contained in:
eraden 2022-06-05 21:03:22 +02:00
parent cf464beb27
commit a34f32dc15
10 changed files with 171 additions and 176 deletions

5
Cargo.lock generated
View File

@ -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"

View File

@ -4,6 +4,7 @@ members = [
"shared/model",
"shared/bus",
"shared/config",
"shared/testx",
# actors
"actors/account_manager",
"actors/cart_manager",

View File

@ -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" }

View File

@ -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);
}
}

View File

@ -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<FullAccount> = 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);
}
}

View File

@ -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<Stock> = 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<Stock> = 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));
}
}

View File

@ -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<Token> {
pub(crate) async fn token_by_jti(
msg: TokenByJti,
t: &mut sqlx::Transaction<'_, sqlx::Postgres>,
) -> Result<Token> {
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<Token> {
pub(crate) async fn create_token(
msg: CreateToken,
t: &mut sqlx::Transaction<'_, sqlx::Postgres>,
) -> Result<Token> {
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<Token> {
pub(crate) async fn create_extended_token(
msg: CreateExtendedToken,
t: &mut sqlx::Transaction<'_, sqlx::Postgres>,
) -> Result<Token> {
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<Database>) -> 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<Database>,
t: &mut sqlx::Transaction<'_, sqlx::Postgres>,
customer_id: Option<Uuid>,
role: Option<Role>,
subject: Option<AccountId>,
@ -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)));
}
}

View File

@ -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);

6
shared/testx/Cargo.toml Normal file
View File

@ -0,0 +1,6 @@
[package]
name = "testx"
version = "0.1.0"
edition = "2021"
[dependencies]

21
shared/testx/src/lib.rs Normal file
View File

@ -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();
};
}