Skip to content

Commit

Permalink
test: add more test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
chungquantin committed Sep 20, 2024
1 parent baab872 commit cb48a4d
Show file tree
Hide file tree
Showing 3 changed files with 247 additions and 12 deletions.
7 changes: 3 additions & 4 deletions pop-api/examples/fungibles/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,9 @@ mod fungibles {
return Ok(());
}

let allowance = self.allowance(caller, spender);
api::increase_allowance(self.id, spender, value).map_err(PSP22Error::from)?;
let allowance = self.allowance(caller, spender).saturating_add(value);
self.emit_approval_event(caller, spender, allowance);
self.emit_approval_event(caller, spender, allowance.saturating_add(value));
Ok(())
}

Expand All @@ -224,8 +224,7 @@ mod fungibles {
}

api::decrease_allowance(self.id, spender, value).map_err(PSP22Error::from)?;
let allowance = allowance.saturating_sub(value);
self.emit_approval_event(caller, spender, allowance);
self.emit_approval_event(caller, spender, allowance.saturating_sub(value));
Ok(())
}
}
Expand Down
198 changes: 191 additions & 7 deletions pop-api/examples/fungibles/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,25 @@ fn new_existing_constructor_deployment_fails(
Ok(())
}

#[drink::test(sandbox = Sandbox)]
fn balance_of_works(mut session: Session) -> Result<(), Box<dyn std::error::Error>> {
let _ = env_logger::try_init();
// Deploy a new contract.
deploy_with_new_constructor(
&mut session,
BundleProvider::local()?,
TOKEN_ID,
TOKEN_MIN_BALANCE,
)?;
// Mint tokens.
const AMOUNT: Balance = 12_000;
assert_ok!(mint(&mut session, ALICE, AMOUNT));
// Tokens were minted with the right amount.
assert_eq!(balance_of(&mut session, ALICE), AMOUNT);
assert_eq!(balance_of(&mut session, ALICE), session.sandbox().balance_of(&TOKEN_ID, &ALICE));
Ok(())
}

#[drink::test(sandbox = Sandbox)]
fn mint_works(mut session: Session) -> Result<(), Box<dyn std::error::Error>> {
let _ = env_logger::try_init();
Expand Down Expand Up @@ -156,7 +175,7 @@ fn burn_zero_value_works(mut session: Session) -> Result<(), Box<dyn std::error:
}

#[drink::test(sandbox = Sandbox)]
fn burn_fails_with_insufficient_amount(
fn burn_fails_with_insufficient_balance(
mut session: Session,
) -> Result<(), Box<dyn std::error::Error>> {
let _ = env_logger::try_init();
Expand All @@ -170,7 +189,7 @@ fn burn_fails_with_insufficient_amount(
// Mint tokens.
const AMOUNT: Balance = 12_000;
assert_ok!(mint(&mut session, ALICE, AMOUNT));
// Burn tokens reverted with `InsufficientBalance`.
// Failed with `InsufficientBalance`.
expect_call_reverted(
&mut session,
BURN,
Expand All @@ -192,22 +211,187 @@ fn transfer_works(mut session: Session) -> Result<(), Box<dyn std::error::Error>
)?;
// Mint tokens.
const AMOUNT: Balance = 12_000;
const TRANSFERED: Balance = 500;
const TRANSFERRED: Balance = 500;
assert_ok!(mint(&mut session, contract.clone(), AMOUNT));
assert_ok!(mint(&mut session, BOB, AMOUNT));
// Transfer tokens from `contract` to `account`.
session.set_actor(contract.clone());
assert_ok!(transfer(&mut session, BOB, TRANSFERED));
assert_ok!(transfer(&mut session, BOB, TRANSFERRED));
// Successfully emit event.
let expected = Transfer {
from: Some(account_id_from_slice(contract.clone().as_ref())),
to: Some(account_id_from_slice(BOB.as_ref())),
value: TRANSFERED,
value: TRANSFERRED,
}
.encode();
assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice());

assert_eq!(balance_of(&mut session, contract), AMOUNT - TRANSFERRED);
assert_eq!(balance_of(&mut session, BOB), AMOUNT + TRANSFERRED);
Ok(())
}

#[drink::test(sandbox = Sandbox)]
fn transfer_zero_value_works(mut session: Session) -> Result<(), Box<dyn std::error::Error>> {
let _ = env_logger::try_init();
// Deploy a new contract.
deploy_with_new_constructor(
&mut session,
BundleProvider::local()?,
TOKEN_ID,
TOKEN_MIN_BALANCE,
)?;
assert_ok!(transfer(&mut session, ALICE, 0));
// No event emitted.
assert_eq!(last_contract_event(&session), None);
Ok(())
}

#[drink::test(sandbox = Sandbox)]
fn transfer_fails_with_insufficient_balance(
mut session: Session,
) -> Result<(), Box<dyn std::error::Error>> {
let _ = env_logger::try_init();
// Deploy a new contract.
let contract = deploy_with_new_constructor(
&mut session,
BundleProvider::local()?,
TOKEN_ID,
TOKEN_MIN_BALANCE,
)?;
// Mint tokens.
const AMOUNT: Balance = 12_000;
assert_ok!(mint(&mut session, contract.clone(), AMOUNT));
assert_ok!(mint(&mut session, BOB, AMOUNT));

session.set_actor(contract.clone());
// Failed with `InsufficientBalance`.
expect_call_reverted(
&mut session,
TRANSFER,
vec![BOB.to_string(), (AMOUNT + 1).to_string()],
PSP22Error::InsufficientBalance,
);
Ok(())
}

#[drink::test(sandbox = Sandbox)]
fn approve_works(mut session: Session) -> Result<(), Box<dyn std::error::Error>> {
let _ = env_logger::try_init();
// Deploy a new contract.
let contract = deploy_with_new_constructor(
&mut session,
BundleProvider::local()?,
TOKEN_ID,
TOKEN_MIN_BALANCE,
)?;

const AMOUNT: Balance = 12_000;
// Mint tokens.
assert_ok!(mint(&mut session, contract.clone(), AMOUNT));
// Successfully apporve.
session.set_actor(contract.clone());
assert_ok!(approve(&mut session, ALICE, AMOUNT / 2));
// Successfully emit event.
let expected = Approval {
owner: account_id_from_slice(contract.clone().as_ref()),
spender: account_id_from_slice(ALICE.as_ref()),
value: AMOUNT / 2,
}
.encode();
assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice());
assert_eq!(allowance(&mut session, contract, ALICE), AMOUNT / 2);
Ok(())
}

#[drink::test(sandbox = Sandbox)]
fn increase_allowance_works(mut session: Session) -> Result<(), Box<dyn std::error::Error>> {
let _ = env_logger::try_init();
// Deploy a new contract.
let contract = deploy_with_new_constructor(
&mut session,
BundleProvider::local()?,
TOKEN_ID,
TOKEN_MIN_BALANCE,
)?;

const AMOUNT: Balance = 12_000;
// Mint tokens.
assert_ok!(mint(&mut session, contract.clone(), AMOUNT));
// Successfully apporve.
session.set_actor(contract.clone());
assert_ok!(approve(&mut session, ALICE, AMOUNT / 2));
assert_ok!(increase_allowance(&mut session, ALICE, AMOUNT / 2));
// Successfully emit event.
let expected = Approval {
owner: account_id_from_slice(contract.clone().as_ref()),
spender: account_id_from_slice(ALICE.as_ref()),
value: AMOUNT,
}
.encode();
assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice());
assert_eq!(allowance(&mut session, contract, ALICE), AMOUNT);
Ok(())
}

assert_eq!(balance_of(&mut session, contract), AMOUNT - TRANSFERED);
assert_eq!(balance_of(&mut session, BOB), AMOUNT + TRANSFERED);
#[drink::test(sandbox = Sandbox)]
fn decrease_allowance_works(mut session: Session) -> Result<(), Box<dyn std::error::Error>> {
let _ = env_logger::try_init();
// Deploy a new contract.
let contract = deploy_with_new_constructor(
&mut session,
BundleProvider::local()?,
TOKEN_ID,
TOKEN_MIN_BALANCE,
)?;

const AMOUNT: Balance = 12_000;
// Mint tokens.
assert_ok!(mint(&mut session, contract.clone(), AMOUNT));
// Successfully apporve.
session.set_actor(contract.clone());
assert_ok!(approve(&mut session, ALICE, AMOUNT / 2));
assert_ok!(decrease_allowance(&mut session, ALICE, 1));
// Successfully emit event.
let expected = Approval {
owner: account_id_from_slice(contract.clone().as_ref()),
spender: account_id_from_slice(ALICE.as_ref()),
value: AMOUNT / 2 - 1,
}
.encode();
assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice());
assert_eq!(allowance(&mut session, contract, ALICE), AMOUNT / 2 - 1);
Ok(())
}

#[drink::test(sandbox = Sandbox)]
fn transfer_from_works(mut session: Session) -> Result<(), Box<dyn std::error::Error>> {
let _ = env_logger::try_init();
// Deploy a new contract.
let contract = deploy_with_new_constructor(
&mut session,
BundleProvider::local()?,
TOKEN_ID,
TOKEN_MIN_BALANCE,
)?;

const AMOUNT: Balance = 12_000;
// Mint tokens.
assert_ok!(mint(&mut session, contract.clone(), AMOUNT));
// Successfully transfer from `owner`.
session.set_actor(contract.clone());
assert_ok!(approve(&mut session, ALICE, AMOUNT / 2));
assert_eq!(allowance(&mut session, contract.clone(), ALICE), AMOUNT / 2);

session.set_actor(ALICE);
assert_ok!(transfer_from(&mut session, contract, BOB, AMOUNT / 2));
// Successfully emit event.
let expected = Transfer {
from: Some(account_id_from_slice(ALICE.as_ref())),
to: Some(account_id_from_slice(BOB.as_ref())),
value: AMOUNT / 4,
}
.encode();
assert_eq!(last_contract_event(&session).unwrap(), expected.as_slice());
Ok(())
}
54 changes: 53 additions & 1 deletion pop-api/examples/fungibles/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,14 @@ use scale::{Decode, Encode};
use super::*;

// PSP22 functions.
pub const ALLOWANCE: &str = "Psp22::allowance";
pub const BALANCE_OF: &str = "Psp22::balance_of";
pub const TOTAL_SUPPLY: &str = "Psp22::total_supply";
pub const TRANSFER: &str = "Psp22::transfer";
pub const TRANSFER_FROM: &str = "Psp22::transfer_from";
pub const APPROVE: &str = "Psp22::approve";
pub const INCREASE_ALLOWANCE: &str = "Psp22::increase_allowance";
pub const DECREASE_ALLOWANCE: &str = "Psp22::decrease_allowance";
// PSP22Metadata functions.
pub const TOKEN_NAME: &str = "Psp22Metadata::token_name";
pub const TOKEN_SYMBOL: &str = "Psp22Metadata::token_symbol";
Expand Down Expand Up @@ -90,7 +95,7 @@ pub(super) fn deploy_with_new_existing_constructor(
session.deploy_bundle(bundle, "new_existing", &[id.to_string()], NO_SALT, Some(INIT_VALUE))
}

// Test methods for `PSP22`.`
// Test methods for `PSP22`.

pub(super) fn total_supply(session: &mut Session<Sandbox>) -> Balance {
decoded_call::<Balance>(session, TOTAL_SUPPLY, vec![], None).unwrap()
Expand All @@ -100,6 +105,15 @@ pub(super) fn balance_of(session: &mut Session<Sandbox>, owner: AccountId32) ->
decoded_call::<Balance>(session, BALANCE_OF, vec![owner.to_string()], None).unwrap()
}

pub(super) fn allowance(
session: &mut Session<Sandbox>,
owner: AccountId32,
spender: AccountId32,
) -> Balance {
decoded_call::<Balance>(session, ALLOWANCE, vec![owner.to_string(), spender.to_string()], None)
.unwrap()
}

pub(super) fn transfer(
session: &mut Session<Sandbox>,
to: AccountId32,
Expand All @@ -109,6 +123,44 @@ pub(super) fn transfer(
Ok(session.call(TRANSFER, &vec![to.to_string(), amount.to_string(), data], None)??)
}

pub(super) fn transfer_from(
session: &mut Session<Sandbox>,
from: AccountId32,
to: AccountId32,
amount: Balance,
) -> Result<(), Box<dyn std::error::Error>> {
let data = serde_json::to_string::<[u8; 0]>(&[]).unwrap();
Ok(session.call(
TRANSFER_FROM,
&vec![from.to_string(), to.to_string(), amount.to_string(), data],
None,
)??)
}

pub(super) fn approve(
session: &mut Session<Sandbox>,
spender: AccountId32,
value: Balance,
) -> Result<(), Box<dyn std::error::Error>> {
Ok(session.call(APPROVE, &vec![spender.to_string(), value.to_string()], None)??)
}

pub(super) fn increase_allowance(
session: &mut Session<Sandbox>,
spender: AccountId32,
value: Balance,
) -> Result<(), Box<dyn std::error::Error>> {
Ok(session.call(INCREASE_ALLOWANCE, &vec![spender.to_string(), value.to_string()], None)??)
}

pub(super) fn decrease_allowance(
session: &mut Session<Sandbox>,
spender: AccountId32,
value: Balance,
) -> Result<(), Box<dyn std::error::Error>> {
Ok(session.call(DECREASE_ALLOWANCE, &vec![spender.to_string(), value.to_string()], None)??)
}

// Test methods for `PSP22Metadata``.

pub(super) fn token_name(session: &mut Session<Sandbox>) -> String {
Expand Down

0 comments on commit cb48a4d

Please sign in to comment.