Skip to content

Commit

Permalink
add test that composes wasms
Browse files Browse the repository at this point in the history
  • Loading branch information
sdbondi committed Aug 9, 2022
1 parent d86a0ca commit a75bccc
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 20 deletions.
12 changes: 11 additions & 1 deletion dan_layer/engine/tests/hello_world/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,21 @@ use tari_template_macros::template;

#[template]
mod hello_world {
struct HelloWorld {}
struct HelloWorld {
greeting: String,
}

impl HelloWorld {
pub fn greet() -> String {
"Hello World!".to_string()
}

pub fn new(greeting: String) -> Self {
Self { greeting }
}

pub fn custom_greeting(&self, name: String) -> String {
format!("{} {}!", self.greeting, name)
}
}
}
64 changes: 45 additions & 19 deletions dan_layer/engine/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

mod mock_runtime_interface;

use std::path::Path;

use borsh::BorshDeserialize;
use mock_runtime_interface::MockRuntimeInterface;
use tari_crypto::ristretto::RistrettoSecretKey;
Expand All @@ -32,28 +34,30 @@ use tari_dan_engine::{
state_store::{memory::MemoryStateStore, AtomicDb, StateReader},
wasm::compile::compile_template,
};
use tari_template_abi::encode;
use tari_template_lib::models::{ComponentId, ComponentInstance, PackageId};
use tari_template_lib::{
args,
models::{ComponentId, ComponentInstance, PackageId},
};

#[test]
fn test_hello_world() {
let template_test = TemplateTest::new("HelloWorld".to_string(), "tests/hello_world".to_string());
let result: String = template_test.call_function("greet".to_string(), vec![]);
let template_test = TemplateTest::new(vec!["tests/hello_world"]);
let result: String = template_test.call_function("HelloWorld", "greet", args![]);

assert_eq!(result, "Hello World!");
}

#[test]
fn test_state() {
let template_test = TemplateTest::new("State".to_string(), "tests/state".to_string());
let template_test = TemplateTest::new(vec!["tests/state"]);
let store = template_test.state_store();

// constructor
let component_id1: ComponentId = template_test.call_function("new".to_string(), vec![]);
let component_id1: ComponentId = template_test.call_function("State", "new", args![]);
template_test.assert_calls(&["emit_log", "create_component"]);
template_test.clear_calls();

let component_id2: ComponentId = template_test.call_function("new".to_string(), vec![]);
let component_id2: ComponentId = template_test.call_function("State", "new", args![]);
assert_ne!(component_id1, component_id2);

let component: ComponentInstance = store
Expand All @@ -73,35 +77,57 @@ fn test_state() {

// call the "set" method to update the instance value
let new_value = 20_u32;
template_test.call_method::<()>(component_id2, "set".to_string(), vec![encode(&new_value).unwrap()]);
template_test.call_method::<()>(component_id2, "set", args![new_value]);

// call the "get" method to get the current value
let value: u32 = template_test.call_method(component_id2, "get".to_string(), vec![]);
let value: u32 = template_test.call_method(component_id2, "get", args![]);

assert_eq!(value, new_value);
}

#[test]
fn test_composed() {
let template_test = TemplateTest::new(vec!["tests/state", "tests/hello_world"]);

let component_state: ComponentId = template_test.call_function("State", "new", args![]);
let component_hw: ComponentId = template_test.call_function("HelloWorld", "new", args!["أهلا"]);

let result: String = template_test.call_method(component_hw, "custom_greeting", args!["Wasm"]);
assert_eq!(result, "أهلا Wasm!");

// call the "set" method to update the instance value
let new_value = 20_u32;
template_test.call_method::<()>(component_state, "set", args![new_value]);

// call the "get" method to get the current value
let value: u32 = template_test.call_method(component_state, "get", args![]);

assert_eq!(value, new_value);
}

struct TemplateTest {
template_name: String,
package_id: PackageId,
processor: InstructionProcessor<MockRuntimeInterface>,
secret_key: RistrettoSecretKey,
runtime_interface: MockRuntimeInterface,
}

impl TemplateTest {
pub fn new(template_name: String, template_path: String) -> Self {
pub fn new<P: AsRef<Path>>(template_paths: Vec<P>) -> Self {
let runtime_interface = MockRuntimeInterface::new();
let mut processor = InstructionProcessor::new(runtime_interface.clone());
let (secret_key, _pk) = create_key_pair();

let wasm = compile_template(template_path).unwrap();
let package = Package::builder().add_wasm_module(wasm).build().unwrap();
let wasms = template_paths.into_iter().map(|path| compile_template(path).unwrap());
let mut builder = Package::builder();
for wasm in wasms {
builder.add_wasm_module(wasm);
}
let package = builder.build().unwrap();
let package_id = package.id();
processor.load(package);

Self {
template_name,
package_id,
processor,
secret_key,
Expand All @@ -122,13 +148,13 @@ impl TemplateTest {
self.runtime_interface.clear_calls();
}

pub fn call_function<T>(&self, func_name: String, args: Vec<Vec<u8>>) -> T
pub fn call_function<T>(&self, template_name: &str, func_name: &str, args: Vec<Vec<u8>>) -> T
where T: BorshDeserialize {
let instruction = InstructionBuilder::new()
.add_instruction(Instruction::CallFunction {
package_id: self.package_id,
template: self.template_name.clone(),
function: func_name,
template: template_name.to_owned(),
function: func_name.to_owned(),
args,
})
.sign(&self.secret_key)
Expand All @@ -138,13 +164,13 @@ impl TemplateTest {
result[0].decode::<T>().unwrap()
}

pub fn call_method<T>(&self, component_id: ComponentId, method_name: String, args: Vec<Vec<u8>>) -> T
pub fn call_method<T>(&self, component_id: ComponentId, method_name: &str, args: Vec<Vec<u8>>) -> T
where T: BorshDeserialize {
let instruction = InstructionBuilder::new()
.add_instruction(Instruction::CallMethod {
package_id: self.package_id,
component_id,
method: method_name,
method: method_name.to_owned(),
args,
})
.sign(&self.secret_key)
Expand Down
19 changes: 19 additions & 0 deletions dan_layer/template_lib/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,22 @@ pub struct SetComponentStateArg {
pub component_id: ComponentId,
pub state: Vec<u8>,
}

#[macro_export]
macro_rules! __template_lib_count {
() => (0usize);
( $x:tt $($next:tt)* ) => (1usize + $crate::__template_lib_count!($($next)*));
}

#[macro_export]
macro_rules! args {
() => (Vec::new());

($($args:expr),+) => {{
let mut args = Vec::with_capacity($crate::__template_lib_count!($($args),+));
$(
args.push(tari_template_abi::encode(&$args).unwrap());
)+
args
}}
}
1 change: 1 addition & 0 deletions dan_layer/template_lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub mod abi_context;
mod hash;
pub use hash::Hash;

#[macro_use]
pub mod args;
pub mod models;
pub mod ops;
Expand Down

0 comments on commit a75bccc

Please sign in to comment.