Skip to content

Instantly share code, notes, and snippets.

@sgerodes
Last active January 13, 2024 05:05
Show Gist options
  • Save sgerodes/aef60ce1dd2dda681c45c59d6b9357e0 to your computer and use it in GitHub Desktop.
Save sgerodes/aef60ce1dd2dda681c45c59d6b9357e0 to your computer and use it in GitHub Desktop.
PBA assignment 2 tests
use super::*;
use super::test_utils::*;
pub fn wallet_with_alice() -> Wallet {
Wallet::new(vec![Address::Alice].into_iter())
}
mod tests {
use super::*;
#[test]
fn genesis_block_has_always_same_hash() {
// just ot check if two different genesis block object will equal in their id hash
assert_eq!(Block::genesis().id(), Block::genesis().id());
}
/// Test: ensure_error_is_returned_if_no_address_is_submitted
/// Purpose: To validate that the wallet, when initialized without any addresses, handles
/// various operations correctly by returning either 'NoOwnedAddresses' or 'ForeignAddress' errors.
/// Cases Tested:
/// 1. total_assets_of for a non-existent address should return a relevant error.
/// 2. all_coins_of for a non-existent address should return a relevant error.
/// 3. create_manual_transaction with an empty address list should return 'NoOwnedAddresses'.
/// 4. create_automatic_transaction with an empty address list should return 'NoOwnedAddresses'.
#[test]
fn ensure_error_is_returned_if_no_address_is_submitted() {
let mut node = MockNode::new();
let wallet = Wallet::new(std::iter::empty());
let b1 = node.add_block_as_best(Block::genesis().id(), vec![]);
fn is_either_not_owned_or_foreign(error: WalletError) -> bool {
match error {
WalletError::NoOwnedAddresses | WalletError::ForeignAddress => true,
_ => false,
}
}
assert!(wallet.total_assets_of(Address::Alice).err().map_or(false, is_either_not_owned_or_foreign));
assert!(wallet.all_coins_of(Address::Alice).err().map_or(false, is_either_not_owned_or_foreign));
//assert_eq!(wallet.coin_details(&CoinId(1)), Err(WalletError::NoOwnedAddresses));
assert_eq!(wallet.create_manual_transaction(vec![], vec![]), Err(WalletError::NoOwnedAddresses));
assert_eq!(wallet.create_automatic_transaction(Address::Alice, 1, 1), Err(WalletError::NoOwnedAddresses));
}
/// Purpose: Ensure the wallet returns 'OutputsExceedInputs' error when output values exceed input values in a manual transaction.
/// Process:
/// 1. Sync the wallet with a mock node containing a mint transaction.
/// 2. Attempt to create a manual transaction with output value greater than the available coin value.
/// 3. Confirm that the wallet correctly identifies and returns the 'OutputsExceedInputs' error.
#[test]
fn manual_transaction_outputs_exceed_inputs() {
let mut wallet = wallet_with_alice();
let coin = Coin { value: 100, owner: Address::Alice };
let mint_tx = Transaction { inputs: vec![], outputs: vec![coin.clone()] };
let coin_id = mint_tx.coin_id(0);
let mut node = MockNode::new();
node.add_block_as_best(Block::genesis().id(), vec![mint_tx]);
wallet.sync(&node);
let output_coin = Coin { value: 200, owner: Address::Bob };
let create_tx_result = wallet.create_manual_transaction(vec![coin_id], vec![output_coin]);
assert_eq!(create_tx_result, Err(WalletError::OutputsExceedInputs));
}
/// Purpose: Validate that the wallet returns 'OutputsExceedInputs' error for automatic transactions when requested output value exceeds the total value of owned coins.
/// Process:
/// 1. Sync wallet with a mock node containing a transaction minting coins to Alice.
/// 2. Attempt to create an automatic transaction requesting a transfer amount larger than the minted coin value.
/// 3. Check if the wallet correctly identifies the discrepancy and returns the 'OutputsExceedInputs' error.
#[test]
fn automatic_transaction_outputs_exceed_inputs() {
let mut wallet = wallet_with_alice();
let coin = Coin { value: 100, owner: Address::Alice };
let mint_tx = Transaction { inputs: vec![], outputs: vec![coin] };
let mut node = MockNode::new();
node.add_block_as_best(Block::genesis().id(), vec![mint_tx]);
wallet.sync(&node);
let create_tx_result = wallet.create_automatic_transaction(Address::Bob, 200, 0);
assert_eq!(create_tx_result, Err(WalletError::OutputsExceedInputs));
}
/// Purpose: Test that the wallet returns 'UnknownCoin' error when queried for a CoinId not tracked by the wallet.
/// Process:
/// 1. Create a wallet with Alice's address and sync it with a mock node containing a transaction minting coins to Alice.
/// 2. Attempt to query details of a coin (with a new CoinId) that was not part of any synced transactions.
/// 3. Check if the wallet returns 'UnknownCoin' error, indicating the coin is not known to the wallet.
#[test]
fn test_unknown_coin_id_error() {
let mut node = MockNode::new();
let mut wallet = Wallet::new(vec![Address::Alice].into_iter());
let coin = Coin { value: 100, owner: Address::Alice };
let tx = Transaction { inputs: vec![], outputs: vec![coin] };
let block_id = node.add_block_as_best(Block::genesis().id(), vec![tx]);
wallet.sync(&node);
let coin2 = Coin { value: 100000, owner: Address::Custom(0) };
let tx = Transaction { inputs: vec![], outputs: vec![coin2] };
let coin2_id = tx.coin_id(0);
assert_eq!(wallet.coin_details(&coin2_id), Err(WalletError::UnknownCoin));
}
/// Purpose: Test for 'UnknownCoin' error in create_manual_transaction with an unknown CoinId.
/// Process:
/// 1. Create a wallet with Alice's address.
/// 2. Generate a dummy transaction and create an unrealistic CoinId (not part of any transaction).
/// 3. Attempt to create a manual transaction using the unknown CoinId as input.
/// 4. Verify that the wallet returns 'UnknownCoin' error, indicating the input coin is not recognized.
#[test]
fn unknown_coin_error_in_manual_transaction() {
let wallet = wallet_with_alice();
let dummy_tx = create_dummy_transaction();
let unknown_coin_id = dummy_tx.coin_id(9999);
let output_coins = vec![Coin {
value: 50,
owner: Address::Bob,
}];
let result = wallet.create_manual_transaction(vec![unknown_coin_id], output_coins);
assert!(matches!(result, Err(WalletError::UnknownCoin)));
}
/// Purpose: Test for 'ForeignAddress' error in total_assets_of and all_coins_of methods.
/// Process:
/// 1. Initialize a wallet with Alice's address.
/// 2. Attempt to query the total assets and all coins of Bob (who is not in the wallet).
/// 3. Verify that both queries result in 'ForeignAddress' errors, indicating the address is not managed by the wallet.
#[test]
fn foreign_address_error() {
let wallet = wallet_with_alice();
let result = wallet.total_assets_of(Address::Bob);
assert!(matches!(result, Err(WalletError::ForeignAddress)));
let coin_id_result = wallet.all_coins_of(Address::Bob);
assert!(matches!(coin_id_result, Err(WalletError::ForeignAddress)));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment