diff --git a/src/db/_accounts.rs b/src/db/_accounts.rs index 2c51fea..fd26775 100644 --- a/src/db/_accounts.rs +++ b/src/db/_accounts.rs @@ -5,7 +5,7 @@ use crate::db::_external_id::{AccountId, Id, UserId}; use crate::db::_securities::Security; use crate::db::_users::User; use crate::db::external_id::SecurityId; -use crate::util::{CustomResult, Error, TransactionHelper}; +use crate::util::{CustomResult, Error}; #[derive(PartialEq, Debug)] pub enum AccountType { diff --git a/src/db/_cheques.rs b/src/db/_cheques.rs index ad9e1b8..0b60a5f 100644 --- a/src/db/_cheques.rs +++ b/src/db/_cheques.rs @@ -6,7 +6,7 @@ pub type Drawer = (UserId, AccountId, SecurityId); pub type Payee = (UserId, SecurityId); #[derive(Debug)] -pub struct SecurityEmitterCheque { +pub struct Cheque { pub drawer_user_id: UserId, pub drawer_account_id: AccountId, pub security_id: SecurityId, @@ -15,12 +15,12 @@ pub struct SecurityEmitterCheque { pub amount: i64, } -impl SecurityEmitterCheque { +impl Cheque { pub fn new(drawer: Drawer, payee: Payee, amount: i64, - cheque_number: i64) -> SecurityEmitterCheque { - SecurityEmitterCheque { + cheque_number: i64) -> Cheque { + Cheque { drawer_user_id: drawer.0, drawer_account_id: drawer.1, security_id: drawer.2, @@ -30,11 +30,3 @@ impl SecurityEmitterCheque { } } } - -#[cfg(test)] -pub mod test { - use super::*; - - #[test] - fn test_foo() {} -} \ No newline at end of file diff --git a/src/db/_interests.rs b/src/db/_interests.rs new file mode 100644 index 0000000..139597f --- /dev/null +++ b/src/db/_interests.rs @@ -0,0 +1,2 @@ + + diff --git a/src/db/mod.rs b/src/db/mod.rs index 98131e1..cf98e4c 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -4,6 +4,7 @@ mod _accounts; mod _cheques; mod _external_id; mod _test_utils; +mod _interests; pub mod external_id { pub use super::_external_id::*; @@ -28,7 +29,7 @@ pub mod accounts { } pub mod cheques { - pub use super::_cheques::{SecurityEmitterCheque, Drawer, Payee}; + pub use super::_cheques::{Cheque, Drawer, Payee}; } pub mod test_utils { diff --git a/src/main.rs b/src/main.rs index 8e42610..054f9f2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -162,7 +162,7 @@ fn process_command_line(conn: &mut Connection, m: &ArgMatches, logic: &mut dyn C } #[cfg(test)] -mod test { +mod cli_test { use super::*; struct TestCommandLineLogic { diff --git a/src/services/_transactions.rs b/src/services/_transactions.rs index 10b61cd..8ce661a 100644 --- a/src/services/_transactions.rs +++ b/src/services/_transactions.rs @@ -2,13 +2,13 @@ use rusqlite::{Connection, ffi, params, Params, Savepoint, Transaction}; use crate::db::{accounts, securities}; use crate::db::accounts::{Account, get_account_by_id}; -use crate::db::cheques::SecurityEmitterCheque; +use crate::db::cheques::Cheque; use crate::db::external_id::AccountId; use crate::db::securities::get_security_by_id; use crate::util::*; fn _move_securities(tx: &Savepoint, - cheque: &SecurityEmitterCheque, + cheque: &Cheque, account_id: &AccountId) -> CustomResult<()> { let drawer_receipt = accounts::add_to_account(tx, &cheque.drawer_account_id, -cheque.amount)?; let payee_receipt = accounts::add_to_account(tx, account_id, cheque.amount)?; @@ -20,7 +20,7 @@ fn _move_securities(tx: &Savepoint, } fn _add_cheque_to_cashed_cheques_log(tx: &Connection, - cheque: &SecurityEmitterCheque, + cheque: &Cheque, account_id: &AccountId) -> Result<(), Error> { let q = " INSERT INTO cashed_cheques( @@ -44,7 +44,7 @@ fn _add_cheque_to_cashed_cheques_log(tx: &Connection, } fn cash_cheque_unsafe(savepoint: &Savepoint, - cheque: &SecurityEmitterCheque, + cheque: &Cheque, account_id: &AccountId) -> CustomResult<()> { if cheque.amount < 0 { return Err(Error::InvalidAmount(format!("The cheque {:?} has a negative amount.", cheque))); @@ -63,7 +63,7 @@ fn cash_cheque_unsafe(savepoint: &Savepoint, } fn cash_cheque(tx: &mut Transaction, - cheque: &SecurityEmitterCheque, + cheque: &Cheque, account_id: &AccountId) -> CustomResult<()> { let mut savepoint = tx.savepoint().map_err(Error::SqlError)?; let ret = cash_cheque_unsafe(&savepoint, cheque, account_id); @@ -98,30 +98,57 @@ mod test_caching_cheques { return conn; } - fn setup_basic() -> (Connection, Drawer, Payee, AccountId) { + fn setup_security_emitter() -> (Connection, Drawer, Payee, AccountId) { let mut conn = setup_conn(); let tx = conn.transaction().unwrap(); let (users, securities, accounts) = test_utils::setup_basic_environment(&tx).unwrap(); let sec = securities.get(0).unwrap(); let drawer = users.get(0).unwrap(); let payee = users.get(1).unwrap(); - let drawer_account = create_security_emitter_account(&tx, &sec.id(), &drawer.id()).unwrap(); + let security_emitter_account = create_security_emitter_account(&tx, &sec.id(), &drawer.id()).unwrap(); let payee_account = create_checking_account(&tx, &sec.id(), &payee.id()).unwrap(); tx.commit().unwrap(); - let drawer: Drawer = (drawer.id(), drawer_account.id(), sec.id()); + let security_emitter: Drawer = (drawer.id(), security_emitter_account.id(), sec.id()); let payee: Payee = (payee.id(), sec.id()); - (conn, drawer, payee, payee_account.id()) + (conn, security_emitter, payee, payee_account.id()) + } + + fn _create_100_secs_in_payee_account(tx: &mut Transaction, security_emitter: &Drawer, payee: &Payee, payee_account: &AccountId) { + let cheque = Cheque::new( + security_emitter.clone(), payee.clone(), 100, 99); + + cash_cheque(tx, &cheque, &payee_account).unwrap(); + } + + fn _create_drawer(payee: Payee, payee_account: AccountId) -> Drawer { + (payee.0, payee_account, payee.1) + } + + fn setup_basic() -> (Connection, Drawer, Payee, AccountId) { + let (mut conn, security_emitter, payee, payee_account) = setup_security_emitter(); + + let mut tx = conn.transaction().unwrap(); + + _create_100_secs_in_payee_account(&mut tx, &security_emitter, &payee, &payee_account); + let reg_account = create_checking_account(&tx, &security_emitter.2, &security_emitter.0).unwrap(); + + tx.commit().unwrap(); + + let drawer: Drawer = _create_drawer(payee, payee_account); + let new_payee: Payee = (security_emitter.0, security_emitter.2); + + return (conn, drawer, new_payee, reg_account.id()) } #[test] - fn test_basic_happy_path() -> CustomResult<()> { - let (mut conn, drawer, payee, payee_account) = setup_basic(); + fn test_happy_path_currency_emitter() -> CustomResult<()> { + let (mut conn, security_emitter, payee, payee_account) = setup_security_emitter(); let mut tx = conn.transaction().unwrap(); - let cheque = SecurityEmitterCheque::new( - drawer, payee, 1000, 99); + let cheque = Cheque::new( + security_emitter, payee, 1000, 99); cash_cheque(&mut tx, &cheque, &payee_account)?; tx.commit().unwrap(); @@ -134,30 +161,56 @@ mod test_caching_cheques { } #[test] - fn test_negative_cheque() -> CustomResult<()> { + fn test_happy_path_regular_cheque() -> CustomResult<()> { let (mut conn, drawer, payee, payee_account) = setup_basic(); let mut tx = conn.transaction().unwrap(); - let cheque = SecurityEmitterCheque::new( - drawer, payee, -1000, 99); + let cheque = Cheque::new( + drawer.clone(), payee, 25, 10001); + + cash_cheque(&mut tx, &cheque, &payee_account)?; + + let payee_acc = get_account_by_id(&tx, &payee_account).unwrap(); + assert_eq!(payee_acc.raw_amount(), 25); + + let drawer_acc = get_account_by_id(&tx, &drawer.1).unwrap(); + assert_eq!(drawer_acc.raw_amount(), 75); + + Ok(()) + } + + fn test_negative_cheque(conn: &mut Connection, drawer: Drawer, payee: Payee, payee_account: AccountId) -> CustomResult<()> { + let mut tx = conn.transaction().unwrap(); + + let cheque = Cheque::new( + drawer, payee, -1, 99); let ret = cash_cheque(&mut tx, &cheque, &payee_account); match ret { Err(Error::InvalidAmount(_)) => Ok(()), - _ => Err(Error::Testing("Expected double spending error here.".to_string())) + _ => Err(Error::Testing("Expected invalid amount error here.".to_string())) } } #[test] - fn test_double_spend() -> CustomResult<()> { + fn test_negative_security_emitter_cheque() -> CustomResult<()> { + let (mut conn, security_emitter, payee, payee_account) = setup_security_emitter(); + test_negative_cheque(&mut conn, security_emitter, payee, payee_account) + } + + #[test] + fn test_negative_regular_cheque() -> CustomResult<()> { let (mut conn, drawer, payee, payee_account) = setup_basic(); - let amount = 1000; + test_negative_cheque(&mut conn, drawer, payee, payee_account) + } + + fn test_double_spend(conn: &mut Connection, drawer: Drawer, payee: Payee, payee_account: AccountId) -> CustomResult<()> { let mut tx = conn.transaction().unwrap(); - let cheque = SecurityEmitterCheque::new( + let cheque = Cheque::new( drawer, payee, - 1000, + 10, 99, ); @@ -173,16 +226,25 @@ mod test_caching_cheques { } #[test] - fn test_invalid_drawer() -> CustomResult<()> { + fn test_double_spend_security_emitter_cheque() -> CustomResult<()> { + let (mut conn, security_emitter, payee, payee_account) = setup_security_emitter(); + test_double_spend(&mut conn, security_emitter, payee, payee_account) + } + + #[test] + fn test_double_spend_regular_emitter_cheque() -> CustomResult<()> { let (mut conn, drawer, payee, payee_account) = setup_basic(); - let amount = 1000; + test_double_spend(&mut conn, drawer, payee, payee_account) + } + + fn test_invalid_drawer(conn: &mut Connection, drawer: Drawer, payee: Payee, payee_account: AccountId) -> CustomResult<()> { let mut tx = conn.transaction().unwrap(); let not_currency_owner_user_id = UserId::from_id(drawer.0.get_id() + 72623); let not_currency_owner: Drawer = (not_currency_owner_user_id, drawer.1, drawer.2); - let cheque = SecurityEmitterCheque::new( + let cheque = Cheque::new( not_currency_owner, payee, - 1000, + 100, 99, ); @@ -194,14 +256,24 @@ mod test_caching_cheques { } #[test] - fn test_invalid_payee() -> CustomResult<()> { - let (mut conn, drawer, payee, payee_account) = setup_basic(); - let mut tx = conn.transaction().unwrap(); - // let wrong_payee_account = create_checking_account(&tx, &sec.id(), &payee.id()).unwrap(); - let wrong_payee_account = &drawer.1; + fn test_invalid_drawer_security_emitter() -> CustomResult<()> { + let (mut conn, security_emitter, payee, payee_account) = setup_security_emitter(); + test_invalid_drawer(&mut conn, security_emitter, payee, payee_account) + } - let cheque = SecurityEmitterCheque::new( - drawer.clone(), payee.clone(), 1000, 99); + #[test] + fn test_invalid_drawer_regular_cheque() -> CustomResult<()> { + let (mut conn, drawer, payee, payee_account) = setup_basic(); + test_invalid_drawer(&mut conn, drawer, payee, payee_account) + } + + fn test_invalid_payee(conn: &mut Connection, security_emitter: Drawer, payee: Payee, payee_account: AccountId) -> CustomResult<()> { + let (mut conn, security_emitter, payee, payee_account) = setup_security_emitter(); + let mut tx = conn.transaction().unwrap(); + let wrong_payee_account = &security_emitter.1; + + let cheque = Cheque::new( + security_emitter.clone(), payee.clone(), 1000, 99); let ret = cash_cheque(&mut tx, &cheque, wrong_payee_account); match ret { @@ -209,4 +281,17 @@ mod test_caching_cheques { _ => Err(Error::Testing("Expected invalid payee here.".to_string())) } } + + + #[test] + fn test_invalid_payee_security_emitter_cheque() -> CustomResult<()> { + let (mut conn, security_emitter, payee, payee_account) = setup_security_emitter(); + test_invalid_payee(&mut conn, security_emitter, payee, payee_account) + } + + #[test] + fn test_invalid_payee_regular_cheque() -> CustomResult<()> { + let (mut conn, drawer, payee, payee_account) = setup_basic(); + test_invalid_payee(&mut conn, drawer, payee, payee_account) + } } \ No newline at end of file