Skip to content

Commit

Permalink
added test setup and 2 simple tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mihaicalinluca committed Oct 4, 2023
1 parent 103b9a5 commit dfe544f
Show file tree
Hide file tree
Showing 2 changed files with 206 additions and 4 deletions.
6 changes: 2 additions & 4 deletions contracts/mvx-game-sc/src/private.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,8 @@ pub trait PrivateModule: crate::storage::StorageModule {
let approved_token_id = self.token_id().get();
let start_fee = self.game_start_fee().get();

require!(
token_id == &approved_token_id && amount == &start_fee,
"start game payment not right"
);
require!(token_id == &approved_token_id, "wrong token id");
require!(amount == &start_fee, "start game payment amount not right");
}

fn validate_join_game(
Expand Down
204 changes: 204 additions & 0 deletions contracts/mvx-game-sc/tests/game_sc_blackbox_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
use multiversx_sc::{
codec::{multi_types::OptionalValue, CodecFrom},
storage::mappers::SingleValue,
types::{Address, EgldOrEsdtTokenIdentifier, TokenIdentifier},
};
use multiversx_sc_scenario::{api::StaticApi, num_bigint::BigUint, scenario_model::*, *};
use mvx_game_sc::{
storage::{ProxyTrait, StorageModule},
types::{GameSettings, Status},
ProxyTrait as _,
};

const GAME_SC_PATH: &str = "file:output/mvx-game-sc.wasm";
const BALANCE: u64 = 100_000_000u64;
const TOKEN_ID: &str = "str:GAME-123456";
const TOKEN_ID_BY: &[u8] = b"GAME-123456";
const STARTING_FEE: u64 = 20u64;
const USER1_ADDR: &str = "address:user1";
const USER2_ADDR: &str = "address:user2";
const OWNER_ADDR: &str = "address:owner";
const GAME_SC_ADDR: &str = "sc:mvx_game_sc";

fn world() -> ScenarioWorld {
let mut blockchain = ScenarioWorld::new();
blockchain.set_current_dir_from_workspace("contracts/mvx-game-sc");

blockchain.register_contract(GAME_SC_PATH, mvx_game_sc::ContractBuilder);
blockchain
}

struct GameContractState {
world: ScenarioWorld,
user1: AddressValue,
user2: AddressValue,
owner: AddressValue,
}

impl GameContractState {
fn new() -> Self {
let mut world = world();
world.start_trace().set_state_step(
SetStateStep::new()
.put_account(
OWNER_ADDR,
Account::new()
.nonce(1)
.balance(BALANCE)
.esdt_balance(TOKEN_ID, BALANCE),
)
.put_account(
USER1_ADDR,
Account::new()
.nonce(2)
.balance(BALANCE)
.esdt_balance(TOKEN_ID, BALANCE),
)
.put_account(
USER2_ADDR,
Account::new()
.nonce(3)
.balance(BALANCE)
.esdt_balance(TOKEN_ID, BALANCE),
),
);

let user1 = AddressValue::from(USER1_ADDR);
let user2 = AddressValue::from(USER2_ADDR);
let owner = AddressValue::from(OWNER_ADDR);

Self {
world,
user1,
user2,
owner,
}
}

fn deploy(&mut self, game_sc: &mut ContractInfo<mvx_game_sc::Proxy<StaticApi>>) -> &mut Self {
let game_sc_code = self.world.code_expression(GAME_SC_PATH);

self.world
.set_state_step(SetStateStep::new().new_address(OWNER_ADDR, 1, GAME_SC_ADDR))
.sc_deploy(
ScDeployStep::new()
.from(OWNER_ADDR)
.code(game_sc_code)
.call(game_sc.init(
OptionalValue::Some(true),
OptionalValue::Some(BigUint::from(STARTING_FEE)),
OptionalValue::Some(EgldOrEsdtTokenIdentifier::esdt(
TokenIdentifier::from(TOKEN_ID_BY),
)),
))
.expect(TxExpect::ok().no_result()),
);

self
}

fn create_game(
&mut self,
waiting_time: u64,
number_of_players_min: u64,
number_of_players_max: u64,
wager: BigUint,
caller: &str,
game_sc: &mut ContractInfo<mvx_game_sc::Proxy<StaticApi>>,
) -> &mut Self {
self.world.sc_call(
ScCallStep::new()
.from(caller)
.to(GAME_SC_ADDR)
.esdt_transfer(TOKEN_ID, 0u64, BigUint::from(STARTING_FEE))
.call(game_sc.create_game(
waiting_time,
number_of_players_min,
number_of_players_max,
wager,
))
.expect(TxExpect::ok().no_result()),
);

self
}

fn join_game(
&mut self,
game_id: u64,
caller: &str,
amount: &BigUint,
game_sc: &mut ContractInfo<mvx_game_sc::Proxy<StaticApi>>,
) -> &mut Self {
self.world.sc_call(
ScCallStep::new()
.from(caller)
.to(GAME_SC_ADDR)
.esdt_transfer(TOKEN_ID, 0u64, amount)
.call(game_sc.join_game(game_id))
.expect(TxExpect::ok().no_result()),
);
self
}
}

#[test]
fn game_sc_deploy_test() {
let mut state = GameContractState::new();
let mut game_sc = ContractInfo::<mvx_game_sc::Proxy<StaticApi>>::new(GAME_SC_ADDR);

state.deploy(&mut game_sc);
}

#[test]
fn game_sc_simple_game_flow() {
let mut state = GameContractState::new();
let mut game_sc = ContractInfo::<mvx_game_sc::Proxy<StaticApi>>::new(GAME_SC_ADDR);

let waiting_time = 100u64;
let number_of_players_min = 1u64;
let number_of_players_max = 4u64;
let wager = BigUint::from(100u64);

//deploy
state.deploy(&mut game_sc);

//check last game id before creation
state.world.sc_query(
ScQueryStep::new()
.to(GAME_SC_ADDR)
.function("getLastGameId")
.expect(TxExpect::ok().result("")),
);

//create first game
state.create_game(
waiting_time,
number_of_players_min,
number_of_players_max,
wager.clone(),
OWNER_ADDR,
&mut game_sc,
);

//check last game id, needs to be 1
state.world.sc_query(
ScQueryStep::new()
.to(GAME_SC_ADDR)
.function("getLastGameId")
.expect(TxExpect::ok().result("1")),
);

//user1 tries to join the game, timestamp is ok, max players not reached, should work
state.join_game(1u64, USER1_ADDR, &wager, &mut game_sc);

//min number of players reached, game should be valid
let game_settings: SingleValue<GameSettings<StaticApi>> = game_sc
.game_settings(1u64)
.into_vm_query()
.expect(TxExpect::ok())
.execute(&mut state.world);

assert_eq!(game_settings.into().status, Status::Valid);
}

0 comments on commit dfe544f

Please sign in to comment.