2022-10-14 12:51:19 +02:00
import org.scalatest.FunSuite
import exceptions._
class AccountTests extends FunSuite {
2022-11-18 14:31:09 +01:00
2022-10-14 12:51:19 +02:00
val bank = new Bank ( )
test ( "Test 01: Valid account withdrawal" ) {
val acc = new Account ( bank , 500 )
val result = acc . withdraw ( 250 )
assert ( acc . getBalanceAmount == 250 )
assert ( result . isLeft )
}
test ( "Test 02: Invalid account withdrawal should throw exception" ) {
val acc = new Account ( bank , 500 )
val result = acc . withdraw ( 750 )
assert ( acc . getBalanceAmount == 500 )
assert ( result . isRight )
}
test ( "Test 03: Withdrawal of negative amount should throw exception" ) {
val acc = new Account ( bank , 500 )
val result = acc . withdraw ( - 100 )
assert ( acc . getBalanceAmount == 500 )
assert ( result . isRight )
}
test ( "Test 04: Valid account deposit" ) {
val acc = new Account ( bank , 500 )
val result = acc . deposit ( 250 )
assert ( acc . getBalanceAmount == 750 )
assert ( result . isLeft )
}
test ( "Test 05: Deposit of negative amount should throw exception" ) {
val acc = new Account ( bank , 500 )
val result = acc . deposit ( - 50 )
assert ( acc . getBalanceAmount == 500 )
assert ( result . isRight )
}
test ( "Test 06: Correct balance amount after several withdrawals and deposits" ) {
val acc = new Account ( bank , 50000 )
val first = Main . thread {
for ( i <- 0 until 100 ) {
acc . withdraw ( 10 ) ; Thread . sleep ( 10 )
}
}
val second = Main . thread {
for ( i <- 0 until 100 ) {
acc . deposit ( 5 ) ; Thread . sleep ( 20 )
}
}
val third = Main . thread {
for ( i <- 0 until 100 ) {
acc . withdraw ( 50 ) ; Thread . sleep ( 10 )
}
}
val fourth = Main . thread {
for ( i <- 0 until 100 ) {
acc . deposit ( 100 ) ; Thread . sleep ( 10 )
}
}
first . join ( )
second . join ( )
third . join ( )
fourth . join ( )
assert ( acc . getBalanceAmount == 54500 )
}
}
class AccountTransferTests extends FunSuite {
test ( "Test 07: Valid transfer between accounts" ) {
val bank = new Bank ( )
val acc1 = bank . addAccount ( 100 )
val acc2 = bank . addAccount ( 200 )
acc1 transferTo ( acc2 , 50 )
while ( bank . getProcessedTransactionsAsList . size != 1 ) {
Thread . sleep ( 100 )
}
assert ( bank . getProcessedTransactionsAsList . last . status == TransactionStatus . SUCCESS )
assert ( ( acc1 . getBalanceAmount == 50 ) && ( acc2 . getBalanceAmount == 250 ) )
}
test ( "Test 08: Transfer of negative amount between accounts should fail" ) {
val bank = new Bank ( )
val acc1 = bank . addAccount ( 500 )
val acc2 = bank . addAccount ( 1000 )
acc1 transferTo ( acc2 , - 100 )
while ( bank . getProcessedTransactionsAsList . size != 1 ) {
Thread . sleep ( 100 )
}
assert ( bank . getProcessedTransactionsAsList . last . status == TransactionStatus . FAILED )
assert ( ( acc1 . getBalanceAmount == 500 ) && ( acc2 . getBalanceAmount == 1000 ) )
}
2022-11-18 14:31:09 +01:00
2022-10-14 12:51:19 +02:00
test ( "Test 09: Invalid transfer between accounts due to insufficient funds should lead to transaction status FAILED and no money should be transferred between accounts" ) {
val bank = new Bank ( )
val acc1 = new Account ( bank , 100 )
val acc2 = new Account ( bank , 1000 )
acc1 transferTo ( acc2 , 150 )
while ( bank . getProcessedTransactionsAsList . size != 1 ) {
Thread . sleep ( 100 )
}
assert ( bank . getProcessedTransactionsAsList . last . status == TransactionStatus . FAILED )
assert ( ( acc1 . getBalanceAmount == 100 ) && ( acc2 . getBalanceAmount == 1000 ) )
}
2022-11-18 14:31:09 +01:00
2022-10-14 12:51:19 +02:00
test ( "Test 10: Correct balance amounts after several transfers" ) {
val bank = new Bank ( )
val acc1 = new Account ( bank , 3000 )
val acc2 = new Account ( bank , 5000 )
val first = Main . thread {
for ( i <- 0 until 100 ) {
bank addTransactionToQueue ( acc1 , acc2 , 30 )
}
}
val second = Main . thread {
for ( i <- 0 until 100 ) {
bank addTransactionToQueue ( acc2 , acc1 , 23 )
}
}
first . join ( )
second . join ( )
while ( bank . getProcessedTransactionsAsList . size != 200 ) {
Thread . sleep ( 100 )
}
assert ( ( acc1 . getBalanceAmount == 2300 ) && ( acc2 . getBalanceAmount == 5700 ) )
}
test ( "Test 11: Failed transactions should retry and potentially succeed with multiple allowed attempts" ) {
var failed = 0
for ( x <- 1 to 100 ) {
val bank = new Bank ( allowedAttempts = 3 )
val acc1 = new Account ( bank , 100 )
val acc2 = new Account ( bank , 100 )
val acc3 = new Account ( bank , 100 )
for ( i <- 1 to 6 ) { acc1 transferTo ( acc2 , 50 ) }
for ( j <- 1 to 2 ) { acc3 transferTo ( acc1 , 50 ) }
while ( bank . getProcessedTransactionsAsList . size != 8 ) {
Thread . sleep ( 100 )
}
if ( ! ( acc1 . getBalanceAmount == 0
&& acc2 . getBalanceAmount == 300
&& acc3 . getBalanceAmount == 0 ) ) failed += 1
}
assert ( failed <= 5 )
}
test ( "Test 12: Some transactions should be stopped with only one allowed attempt" ) {
var failed = 0
for ( x <- 1 to 100 ) {
2022-11-18 14:31:09 +01:00
// This test is very unstable for more than 1 workers,
// so we have edited it to only use one worker.
val bank = new Bank ( allowedAttempts = 1 , workers = 1 )
2022-10-14 12:51:19 +02:00
val acc1 = new Account ( bank , 100 )
val acc2 = new Account ( bank , 100 )
val acc3 = new Account ( bank , 100 )
for ( i <- 1 to 6 ) { acc1 transferTo ( acc2 , 50 ) }
for ( j <- 1 to 2 ) { acc3 transferTo ( acc1 , 50 ) }
while ( bank . getProcessedTransactionsAsList . size != 8 ) {
Thread . sleep ( 100 )
}
if ( ! ( acc2 . getBalanceAmount != 300 && acc3 . getBalanceAmount == 0 ) ) failed += 1
}
assert ( failed <= 5 )
}
}