Fixed unit tests.
This commit is contained in:
1 parent
1f05ae1957
commit
80153dd6ad
3 files changed
+97
-45
No files matched your search
+93
-44
@@ -1,12 +1,12 @@
|
||||
use fraction::Fraction;
|
||||
use rusqlite::{params, Connection, OptionalExtension, Result, Row};
|
||||
use rusqlite::{params, Connection, ErrorCode, OptionalExtension, Result, Row};
|
||||
|
||||
use crate::db::_external_id::{AccountId, Id, UserId};
|
||||
use crate::db::_securities::Security;
|
||||
|
||||
use crate::db::external_id::SecurityId;
|
||||
use crate::util::{CustomResult, Error};
|
||||
use crate::util::Error::FuckingError;
|
||||
use crate::util::{CustomResult, Error};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AccountType {
|
||||
@@ -15,19 +15,18 @@ pub enum AccountType {
|
||||
}
|
||||
|
||||
impl AccountType {
|
||||
|
||||
fn from_string(s: & String) -> Option<AccountType>{
|
||||
fn from_string(s: &String) -> Option<AccountType> {
|
||||
if s == "security_emitter" {
|
||||
Some(AccountType::SecurityEmitter)
|
||||
} else if s == "checking"{
|
||||
} else if s == "checking" {
|
||||
Some(AccountType::Checking)
|
||||
}else{
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
pub fn from_row(row: &Row) -> Result<AccountType> {
|
||||
let s: String = row.get("acc_account_type")?;
|
||||
AccountType::from_string(& s).ok_or(rusqlite::Error::ExecuteReturnedResults)
|
||||
AccountType::from_string(&s).ok_or(rusqlite::Error::ExecuteReturnedResults)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,12 +40,13 @@ impl PartialEq for AccountType {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for AccountType{
|
||||
impl ToString for AccountType {
|
||||
fn to_string(&self) -> String {
|
||||
match self {
|
||||
AccountType::Checking => "checking",
|
||||
AccountType::SecurityEmitter => "security_emitter",
|
||||
}.to_string()
|
||||
}
|
||||
.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,9 +107,9 @@ impl Account {
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Account{
|
||||
impl Clone for Account {
|
||||
fn clone(&self) -> Self {
|
||||
Account{
|
||||
Account {
|
||||
id: self.id,
|
||||
amount: self.amount,
|
||||
timestamp: self.timestamp,
|
||||
@@ -117,7 +117,6 @@ impl Clone for Account{
|
||||
account_type: self.account_type.clone(),
|
||||
label: self.label.clone(),
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#[derive(Debug)]
|
||||
@@ -192,7 +191,7 @@ pub fn list_accounts<'a>(conn: &Connection) -> CustomResult<Vec<Account>> {
|
||||
return Ok(ret);
|
||||
}
|
||||
|
||||
pub fn list_user_accounts(conn: &Connection, user_id: & UserId) -> CustomResult<Vec<Account>> {
|
||||
pub fn list_user_accounts(conn: &Connection, user_id: &UserId) -> CustomResult<Vec<Account>> {
|
||||
let q = "SELECT acc.id AS acc_id,
|
||||
acc.amount AS acc_amount,
|
||||
UNIXEPOCH(acc.timestamp) AS acc_timestamp,
|
||||
@@ -237,7 +236,10 @@ pub fn get_account_by_id(tx: &Connection, id: &AccountId) -> CustomResult<Accoun
|
||||
.map_err(Error::SqlError);
|
||||
}
|
||||
|
||||
pub fn get_checking_accounts_for_sec_id(tx: &Connection, sec_id: &SecurityId) -> CustomResult<Vec<Account>> {
|
||||
pub fn get_checking_accounts_for_sec_id(
|
||||
tx: &Connection,
|
||||
sec_id: &SecurityId,
|
||||
) -> CustomResult<Vec<Account>> {
|
||||
let q = "
|
||||
SELECT acc.id AS acc_id,
|
||||
acc.amount AS acc_amount,
|
||||
@@ -260,7 +262,6 @@ pub fn get_checking_accounts_for_sec_id(tx: &Connection, sec_id: &SecurityId) ->
|
||||
.map(Result::unwrap)
|
||||
.collect();
|
||||
return Ok(ret);
|
||||
|
||||
}
|
||||
|
||||
fn create_account(
|
||||
@@ -353,7 +354,7 @@ impl AccountChangeReceipt {
|
||||
amount: row.get("amount")?,
|
||||
timestamp: row.get("timestamp")?,
|
||||
security_id: SecurityId::from_id(row.get("security_id")?),
|
||||
account_type: AccountType::from_row(row)?
|
||||
account_type: AccountType::from_row(row)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -373,6 +374,13 @@ fn update_account_history(tx: &Connection, account_id: &AccountId) -> CustomResu
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn is_invalid_amount_error(e: &rusqlite::Error) -> bool {
|
||||
match e {
|
||||
rusqlite::Error::SqliteFailure(uf, _) => uf.code == ErrorCode::ConstraintViolation,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Super low level functions that needs to be wrapped in something else.
|
||||
///
|
||||
/// This method does NOT guarantee that all amount added into an account
|
||||
@@ -398,16 +406,23 @@ pub fn add_to_account(
|
||||
security AS security_id
|
||||
";
|
||||
let params = params![amount, account_id];
|
||||
let ret = tx
|
||||
.query_row(q, params, AccountChangeReceipt::from_row)
|
||||
.map_err(Error::SqlError);
|
||||
let res = tx.query_row(q, params, AccountChangeReceipt::from_row);
|
||||
let ret = res.map_err(|e| {
|
||||
if is_invalid_amount_error(&e) {
|
||||
Error::InvalidAmount(format!("Invalid value {:} added to account {:}", amount, account_id))
|
||||
} else {
|
||||
Error::SqlError(e)
|
||||
}
|
||||
})?;
|
||||
update_account_history(tx, account_id)?;
|
||||
return ret;
|
||||
return Ok(ret);
|
||||
}
|
||||
|
||||
pub fn get_number_of_accounts(tx: &Connection,
|
||||
sec: &SecurityId,
|
||||
account_type: AccountType) -> CustomResult<i64>{
|
||||
pub fn get_number_of_accounts(
|
||||
tx: &Connection,
|
||||
sec: &SecurityId,
|
||||
account_type: AccountType,
|
||||
) -> CustomResult<i64> {
|
||||
let q = "
|
||||
SELECT COUNT(*) AS count
|
||||
FROM accounts
|
||||
@@ -415,15 +430,15 @@ pub fn get_number_of_accounts(tx: &Connection,
|
||||
AND account_type = ?
|
||||
";
|
||||
let params = params![sec, account_type.to_string()];
|
||||
tx.query_row(q, params, |row| row.get("count")).map_err(Error::SqlError)
|
||||
tx.query_row(q, params, |row| row.get("count"))
|
||||
.map_err(Error::SqlError)
|
||||
}
|
||||
|
||||
/// Market cap is computer by summing the security emitter accounts.
|
||||
/// We use this technique because the sum of the security
|
||||
/// emitter accounts MUST equals (more or less very tiny interest
|
||||
/// amounts) the sum of the checking accounts.
|
||||
pub fn get_security_market_cap(tx: &Connection,
|
||||
sec: &SecurityId) -> CustomResult<i64> {
|
||||
pub fn get_security_market_cap(tx: &Connection, sec: &SecurityId) -> CustomResult<i64> {
|
||||
let q = "
|
||||
SELECT COALESCE(-1 * SUM(amount), 0) AS count
|
||||
FROM accounts
|
||||
@@ -431,7 +446,8 @@ pub fn get_security_market_cap(tx: &Connection,
|
||||
AND account_type = ?
|
||||
";
|
||||
let params = params![sec, AccountType::SecurityEmitter.to_string()];
|
||||
tx.query_row(q, params, |row| row.get("count")).map_err(Error::SqlError)
|
||||
tx.query_row(q, params, |row| row.get("count"))
|
||||
.map_err(Error::SqlError)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -472,14 +488,13 @@ mod test_accounts {
|
||||
return Ok(ret);
|
||||
}
|
||||
|
||||
fn assert_test_account_type_to_string_and_from_row_works(account_type: AccountType){
|
||||
fn assert_test_account_type_to_string_and_from_row_works(account_type: AccountType) {
|
||||
let serialized = account_type.to_string();
|
||||
assert_eq!(AccountType::from_string(&serialized).unwrap(), account_type);
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_account_type_to_string_and_from_row(){
|
||||
fn test_account_type_to_string_and_from_row() {
|
||||
assert_test_account_type_to_string_and_from_row_works(AccountType::Checking);
|
||||
assert_test_account_type_to_string_and_from_row_works(AccountType::SecurityEmitter);
|
||||
}
|
||||
@@ -492,10 +507,12 @@ mod test_accounts {
|
||||
let sec = secs.get(0).unwrap();
|
||||
let tx = conn.transaction().unwrap();
|
||||
|
||||
let acc = create_checking_account(&tx,
|
||||
&sec.id(),
|
||||
&user.id(),
|
||||
&format!("Account for {:} in {:}", sec.id(), user.id()))?;
|
||||
let acc = create_checking_account(
|
||||
&tx,
|
||||
&sec.id(),
|
||||
&user.id(),
|
||||
&format!("Account for {:} in {:}", sec.id(), user.id()),
|
||||
)?;
|
||||
assert_eq!(acc.account_type, AccountType::Checking);
|
||||
assert_eq!(0, acc.raw_amount());
|
||||
|
||||
@@ -567,7 +584,7 @@ mod test_accounts {
|
||||
let tx = conn.transaction().unwrap();
|
||||
let sec = secs.get(0).unwrap().id();
|
||||
let user = users.get(0).unwrap().id();
|
||||
let acc = create_checking_account(&tx, &sec, &user, & "acc".to_string()).unwrap();
|
||||
let acc = create_checking_account(&tx, &sec, &user, &"acc".to_string()).unwrap();
|
||||
let receipt = add_to_account(&tx, &acc.id(), 33)?;
|
||||
assert_eq!(receipt.account_id, acc.id());
|
||||
assert_eq!(receipt.amount, 33);
|
||||
@@ -591,7 +608,7 @@ mod test_accounts {
|
||||
let tx = conn.transaction().unwrap();
|
||||
let sec = secs.get(0).unwrap().id();
|
||||
let user = users.get(0).unwrap().id();
|
||||
let acc = create_security_emitter_account(&tx, &sec, &user, & "acc".to_string())?;
|
||||
let acc = create_security_emitter_account(&tx, &sec, &user, &"acc".to_string())?;
|
||||
|
||||
let receipt = add_to_account(&tx, &acc.id(), -33)?;
|
||||
assert_eq!(receipt.account_id, acc.id());
|
||||
@@ -608,16 +625,30 @@ mod test_accounts {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_to_account_unfounded_err() -> CustomResult<()> {
|
||||
let (mut conn, users, secs) = setup();
|
||||
let sec = secs.get(0).unwrap().id();
|
||||
let user = users.get(0).unwrap().id();
|
||||
// let sec_emitter_acc = create_security_emitter_account(&conn, &sec, &user, & "sec emitter acc".to_string())?;
|
||||
let checking_account =
|
||||
create_checking_account(&conn, &sec, &user, &"checking acc".to_string())?;
|
||||
match add_to_account(&conn, &checking_account.id(), -33) {
|
||||
Err(Error::InvalidAmount(_)) => Ok(()),
|
||||
_ => Err(Error::Testing("Expected InvalidAmount error".to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_list_user_accounts() -> CustomResult<()> {
|
||||
let (mut conn, users, secs) = setup();
|
||||
{
|
||||
let tx = conn.transaction().unwrap();
|
||||
create_all_accounts(& tx, &users, &secs)?;
|
||||
create_all_accounts(&tx, &users, &secs)?;
|
||||
tx.commit().map_err(Error::SqlError)?;
|
||||
}
|
||||
|
||||
let res = list_user_accounts(& conn, & users[0].id())?;
|
||||
let res = list_user_accounts(&conn, &users[0].id())?;
|
||||
assert_eq!(res.len(), 2);
|
||||
Ok(())
|
||||
}
|
||||
@@ -625,15 +656,28 @@ mod test_accounts {
|
||||
#[test]
|
||||
fn test_get_number_of_accounts() -> CustomResult<()> {
|
||||
let (mut conn, users, secs) = setup();
|
||||
create_all_accounts(&conn, &users, &secs)?;
|
||||
create_all_accounts(&conn, &users, &secs)?;
|
||||
let n = get_number_of_accounts(&conn, &secs.get(0).unwrap().id(), AccountType::Checking)?;
|
||||
assert_eq!(n, 2);
|
||||
|
||||
let n = get_number_of_accounts(&conn, &secs.get(0).unwrap().id(), AccountType::SecurityEmitter)?;
|
||||
let n = get_number_of_accounts(
|
||||
&conn,
|
||||
&secs.get(0).unwrap().id(),
|
||||
AccountType::SecurityEmitter,
|
||||
)?;
|
||||
assert_eq!(n, 0);
|
||||
|
||||
create_security_emitter_account(&conn, &secs.get(0).unwrap().id(), &users.get(0).unwrap().id(), &"".to_string())?;
|
||||
let n = get_number_of_accounts(&conn, &secs.get(0).unwrap().id(), AccountType::SecurityEmitter)?;
|
||||
create_security_emitter_account(
|
||||
&conn,
|
||||
&secs.get(0).unwrap().id(),
|
||||
&users.get(0).unwrap().id(),
|
||||
&"".to_string(),
|
||||
)?;
|
||||
let n = get_number_of_accounts(
|
||||
&conn,
|
||||
&secs.get(0).unwrap().id(),
|
||||
AccountType::SecurityEmitter,
|
||||
)?;
|
||||
assert_eq!(n, 1);
|
||||
Ok(())
|
||||
}
|
||||
@@ -641,9 +685,14 @@ mod test_accounts {
|
||||
#[test]
|
||||
fn test_get_security_market_cap() -> CustomResult<()> {
|
||||
let (mut conn, users, secs) = setup();
|
||||
let accounts = create_all_accounts(&conn, &users, &secs.get(0..1).unwrap().to_vec())?;
|
||||
let accounts = create_all_accounts(&conn, &users, &secs.get(0..1).unwrap().to_vec())?;
|
||||
let sec_id = &secs.get(0).unwrap().id();
|
||||
let sec_emitter = create_security_emitter_account(&conn, sec_id, &users.get(0).unwrap().id(), &"".to_string())?;
|
||||
let sec_emitter = create_security_emitter_account(
|
||||
&conn,
|
||||
sec_id,
|
||||
&users.get(0).unwrap().id(),
|
||||
&"".to_string(),
|
||||
)?;
|
||||
|
||||
let n = get_security_market_cap(&conn, sec_id)?;
|
||||
assert_eq!(n, 0);
|
||||
|
||||
Reference in new issue
Block a user