Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/add event testing #71

Merged
merged 4 commits into from
Feb 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions contracts/token/fungible/src/extensions/burnable/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::{
mintable::mint,
},
storage::{allowance, approve, balance, total_supply},
test::event_utils::EventAssertion,
};

#[contract]
Expand All @@ -26,6 +27,11 @@ fn burn_works() {
burn(&e, &account, 50);
assert_eq!(balance(&e, &account), 50);
assert_eq!(total_supply(&e), 50);

let event_assert = EventAssertion::new(&e, address.clone());
event_assert.assert_event_count(2);
event_assert.assert_mint(&account, 100);
event_assert.assert_burn(&account, 50);
});
}

Expand All @@ -43,6 +49,12 @@ fn burn_with_allowance_works() {
assert_eq!(balance(&e, &owner), 70);
assert_eq!(balance(&e, &spender), 0);
assert_eq!(total_supply(&e), 70);

let event_assert = EventAssertion::new(&e, address.clone());
event_assert.assert_event_count(3);
event_assert.assert_mint(&owner, 100);
event_assert.assert_approve(&owner, &spender, 30, 1000);
event_assert.assert_burn(&owner, 30);
});
}

Expand Down
6 changes: 6 additions & 0 deletions contracts/token/fungible/src/extensions/mintable/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use soroban_sdk::{contract, testutils::Address as _, Address, Env};
use crate::{
extensions::mintable::storage::mint,
storage::{balance, total_supply},
test::event_utils::EventAssertion,
};

#[contract]
Expand All @@ -15,11 +16,16 @@ struct MockContract;
#[test]
fn mint_works() {
let e = Env::default();
e.mock_all_auths();
let address = e.register(MockContract, ());
let account = Address::generate(&e);
e.as_contract(&address, || {
mint(&e, &account, 100);
assert_eq!(balance(&e, &account), 100);
assert_eq!(total_supply(&e), 100);

let event_assert = EventAssertion::new(&e, address.clone());
event_assert.assert_event_count(1);
event_assert.assert_mint(&account, 100);
});
}
15 changes: 13 additions & 2 deletions contracts/token/fungible/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ use crate::{
},
};

pub mod event_utils;
use event_utils::EventAssertion;

#[contract]
struct MockContract;

Expand Down Expand Up @@ -208,8 +211,10 @@ fn transfer_works() {
assert_eq!(balance(&e, &from), 50);
assert_eq!(balance(&e, &recipient), 50);

let events = e.events().all();
assert_eq!(events.len(), 2);
let event_assert = EventAssertion::new(&e, address.clone());
event_assert.assert_event_count(2);
event_assert.assert_mint(&from, 100);
event_assert.assert_transfer(&from, &recipient, 50);
});
}

Expand Down Expand Up @@ -258,6 +263,12 @@ fn approve_and_transfer_from() {

let updated_allowance = allowance(&e, &owner, &spender);
assert_eq!(updated_allowance, 20);

let event_assert = EventAssertion::new(&e, address.clone());
event_assert.assert_event_count(3);
event_assert.assert_mint(&owner, 100);
event_assert.assert_approve(&owner, &spender, 50, 1000);
event_assert.assert_transfer(&owner, &recipient, 30);
});
}

Expand Down
138 changes: 138 additions & 0 deletions contracts/token/fungible/src/test/event_utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
use soroban_sdk::{symbol_short, testutils::Events, Address, Env, IntoVal, Symbol, Val, Vec};

pub struct EventAssertion<'a> {
env: &'a Env,
contract: Address,
}

impl<'a> EventAssertion<'a> {
pub fn new(env: &'a Env, contract: Address) -> Self {
Self { env, contract }
}

pub fn assert_transfer(&self, from: &Address, to: &Address, amount: i128) {
let events = self.env.events().all();
let transfer_event = events.iter().find(|e| {
let topics: Vec<Val> = e.1.clone();
let topic_symbol: Symbol = topics.first().unwrap().into_val(self.env);
topic_symbol == symbol_short!("transfer")
});

assert!(transfer_event.is_some(), "Transfer event not found in event log");

let (contract, topics, data) = transfer_event.unwrap();
assert_eq!(contract, self.contract, "Event from wrong contract");

let topics: Vec<Val> = topics.clone();
assert_eq!(topics.len(), 3, "Transfer event should have 3 topics");

let topic_symbol: Symbol = topics.get_unchecked(0).into_val(self.env);
assert_eq!(topic_symbol, symbol_short!("transfer"));

let event_from: Address = topics.get_unchecked(1).into_val(self.env);
let event_to: Address = topics.get_unchecked(2).into_val(self.env);
let event_amount: i128 = data.into_val(self.env);

assert_eq!(&event_from, from, "Transfer event has wrong from address");
assert_eq!(&event_to, to, "Transfer event has wrong to address");
assert_eq!(event_amount, amount, "Transfer event has wrong amount");
}

pub fn assert_mint(&self, to: &Address, amount: i128) {
let events = self.env.events().all();
let mint_event = events.iter().find(|e| {
let topics: Vec<Val> = e.1.clone();
let topic_symbol: Symbol = topics.first().unwrap().into_val(self.env);
topic_symbol == symbol_short!("mint")
});

assert!(mint_event.is_some(), "Mint event not found in event log");

let (contract, topics, data) = mint_event.unwrap();
assert_eq!(contract, self.contract, "Event from wrong contract");

let topics: Vec<Val> = topics.clone();
assert_eq!(topics.len(), 2, "Mint event should have 2 topics");

let topic_symbol: Symbol = topics.get_unchecked(0).into_val(self.env);
assert_eq!(topic_symbol, symbol_short!("mint"));

let event_to: Address = topics.get_unchecked(1).into_val(self.env);
let event_amount: i128 = data.into_val(self.env);

assert_eq!(&event_to, to, "Mint event has wrong to address");
assert_eq!(event_amount, amount, "Mint event has wrong amount");
}

pub fn assert_burn(&self, from: &Address, amount: i128) {
let events = self.env.events().all();
let burn_event = events.iter().find(|e| {
let topics: Vec<Val> = e.1.clone();
let topic_symbol: Symbol = topics.first().unwrap().into_val(self.env);
topic_symbol == symbol_short!("burn")
});

assert!(burn_event.is_some(), "Burn event not found in event log");

let (contract, topics, data) = burn_event.unwrap();
assert_eq!(contract, self.contract, "Event from wrong contract");

let topics: Vec<Val> = topics.clone();
assert_eq!(topics.len(), 2, "Burn event should have 2 topics");

let topic_symbol: Symbol = topics.get_unchecked(0).into_val(self.env);
assert_eq!(topic_symbol, symbol_short!("burn"));

let event_from: Address = topics.get_unchecked(1).into_val(self.env);
let event_amount: i128 = data.into_val(self.env);

assert_eq!(&event_from, from, "Burn event has wrong from address");
assert_eq!(event_amount, amount, "Burn event has wrong amount");
}

pub fn assert_event_count(&self, expected: usize) {
let events = self.env.events().all();
assert_eq!(
events.len() as usize,
expected,
"Expected {} events, found {}",
expected,
events.len()
);
}

pub fn assert_approve(
&self,
owner: &Address,
spender: &Address,
amount: i128,
live_until_ledger: u32,
) {
let events = self.env.events().all();
let approve_event = events.iter().find(|e| {
let topics: Vec<Val> = e.1.clone();
let topic_symbol: Symbol = topics.first().unwrap().into_val(self.env);
topic_symbol == symbol_short!("approve")
});

assert!(approve_event.is_some(), "Approve event not found in event log");

let (contract, topics, data) = approve_event.unwrap();
assert_eq!(contract, self.contract, "Event from wrong contract");

let topics: Vec<Val> = topics.clone();
assert_eq!(topics.len(), 3, "Approve event should have 3 topics");

let topic_symbol: Symbol = topics.get_unchecked(0).into_val(self.env);
assert_eq!(topic_symbol, symbol_short!("approve"));

let event_owner: Address = topics.get_unchecked(1).into_val(self.env);
let event_spender: Address = topics.get_unchecked(2).into_val(self.env);
let event_data: (i128, u32) = data.into_val(self.env);

assert_eq!(&event_owner, owner, "Approve event has wrong owner address");
assert_eq!(&event_spender, spender, "Approve event has wrong spender address");
assert_eq!(event_data.0, amount, "Approve event has wrong amount");
assert_eq!(event_data.1, live_until_ledger, "Approve event has wrong live_until_ledger");
}
}
Loading