Skip to content

Commit

Permalink
Contract API tests (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
pmikolajczyk41 committed Aug 29, 2023
1 parent 7237808 commit 27aa56e
Show file tree
Hide file tree
Showing 7 changed files with 194 additions and 6 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/rust-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ on:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch:

concurrency:
Expand Down
41 changes: 39 additions & 2 deletions Cargo.lock

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

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ homepage = "https://github.com/Cardinal-Cryptography/drink"
license = "Apache-2.0"
readme = "README.md"
repository = "https://github.com/Cardinal-Cryptography/drink"
version = "0.1.2"
version = "0.1.3"

[workspace.dependencies]
anyhow = { version = "1.0.71" }
Expand All @@ -30,6 +30,7 @@ parity-scale-codec = { version = "3.6.0" }
ratatui = { version = "0.21.0" }
scale-info = { version = "2.5.0" }
thiserror = { version = "1.0.40" }
wat = { version = "1.0.71" }

# Substrate dependencies

Expand All @@ -43,4 +44,4 @@ sp-core = { version = "22.0.0" }

# Local dependencies

drink = { version = "0.1.2", path = "drink" }
drink = { version = "0.1.3", path = "drink" }
3 changes: 3 additions & 0 deletions drink/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,8 @@ parity-scale-codec = { workspace = true }
scale-info = { workspace = true }
thiserror = { workspace = true }

[dev-dependencies]
wat = { workspace = true }

[features]
session = ["contract-transcode"]
118 changes: 118 additions & 0 deletions drink/src/contract_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,3 +140,121 @@ pub fn decode_debug_buffer(buffer: &[u8]) -> Vec<String> {
let decoded = buffer.iter().map(|b| *b as char).collect::<String>();
decoded.split('\n').map(|s| s.to_string()).collect()
}

#[cfg(test)]
mod tests {
use frame_support::sp_runtime::traits::Hash;
use pallet_contracts::Origin;

use super::*;
use crate::{
chain_api::ChainApi, minimal::RuntimeEvent, MinimalRuntime, DEFAULT_ACTOR,
DEFAULT_GAS_LIMIT,
};

fn compile_module(contract_name: &str) -> Vec<u8> {
let path = [
std::env::var("CARGO_MANIFEST_DIR")
.as_deref()
.unwrap_or("drink"),
"/test-resources/",
contract_name,
".wat",
]
.concat();
wat::parse_file(path).expect("Failed to parse wat file")
}

#[test]
fn can_upload_code() {
let mut sandbox = Sandbox::<MinimalRuntime>::new().unwrap();
let wasm_binary = compile_module("dummy");
let hash = <<MinimalRuntime as frame_system::Config>::Hashing>::hash(&wasm_binary);

let result = sandbox.upload_contract(wasm_binary, DEFAULT_ACTOR, None);

assert!(result.is_ok());
assert_eq!(hash, result.unwrap().code_hash);
}

#[test]
fn can_deploy_contract() {
let mut sandbox = Sandbox::<MinimalRuntime>::new().unwrap();
let wasm_binary = compile_module("dummy");

let events_before = sandbox.get_current_block_events();
assert!(events_before.is_empty());

let result = sandbox.deploy_contract(
wasm_binary,
0,
vec![],
vec![],
DEFAULT_ACTOR,
DEFAULT_GAS_LIMIT,
None,
);
assert!(result.result.is_ok());
assert!(!result.result.unwrap().result.did_revert());

let events = result.events.expect("Drink should collect events");
let instantiation_event = events.last().expect("There should be an event");
assert!(matches!(
instantiation_event.event,
RuntimeEvent::Contracts(pallet_contracts::Event::<MinimalRuntime>::Instantiated { .. })
));
}

#[test]
fn can_call_contract() {
let mut sandbox = Sandbox::<MinimalRuntime>::new().unwrap();
let wasm_binary = compile_module("dummy");

let result = sandbox.deploy_contract(
wasm_binary,
0,
vec![],
vec![],
DEFAULT_ACTOR,
DEFAULT_GAS_LIMIT,
None,
);

let contract_address = result
.result
.expect("Contract should be deployed")
.account_id;

sandbox.reset_current_block_events();

let result = sandbox.call_contract(
contract_address.clone(),
0,
vec![],
DEFAULT_ACTOR,
DEFAULT_GAS_LIMIT,
None,
);
assert!(result.result.is_ok());
assert!(!result.result.unwrap().did_revert());

let events = result.events.expect("Drink should collect events");
assert!(events.len() == 2);

assert_eq!(
events[0].event,
RuntimeEvent::Contracts(pallet_contracts::Event::<MinimalRuntime>::ContractEmitted {
contract: contract_address.clone(),
data: vec![0, 0, 0, 0],
})
);

assert_eq!(
events[1].event,
RuntimeEvent::Contracts(pallet_contracts::Event::<MinimalRuntime>::Called {
contract: contract_address,
caller: Origin::Signed(DEFAULT_ACTOR),
}),
);
}
}
6 changes: 6 additions & 0 deletions drink/src/runtime/minimal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ use frame_support::{
};
use pallet_contracts::{DefaultAddressGenerator, Frame, Schedule};

// Re-export all pallets.
pub use frame_system;
pub use pallet_balances;
pub use pallet_contracts;
pub use pallet_timestamp;

type Block = frame_system::mocking::MockBlock<MinimalRuntime>;

frame_support::construct_runtime!(
Expand Down
25 changes: 25 additions & 0 deletions drink/test-resources/dummy.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
;; Dummy contract emitting a dummy event.
(module
(import "seal0" "seal_deposit_event" (func $seal_deposit_event (param i32 i32 i32 i32)))
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
(import "env" "memory" (memory 1 1))

(func (export "deploy"))

(func (export "call")
;; emit dummy event
(call $seal_deposit_event
(i32.const 0) ;; The topics buffer
(i32.const 0) ;; The topics buffer's length
(i32.const 8) ;; The data buffer
(i32.const 4) ;; The data buffer's length
)

;; exit with success
(call $seal_return
(i32.const 0) ;; flags
(i32.const 0) ;; returned value
(i32.const 4) ;; length of returned value
)
)
)

0 comments on commit 27aa56e

Please sign in to comment.