use pchain_runtime::TransitionError;
use pchain_types::blockchain::ExitStatus;
use crate::common::{
compute_contract_address, ArgsBuilder, CallResult, SimulateWorldState, TestData,
CONTRACT_CACHE_FOLDER,
};
mod common;
#[test]
fn test_view() {
let wasm_bytes = TestData::get_test_contract_code("basic_contract");
let method_args = "arg".to_string();
let contract_address = compute_contract_address([123u8; 32], 0);
let mut sws = SimulateWorldState::default();
sws.add_contract(contract_address, wasm_bytes, pchain_runtime::cbi_version());
let (receipt, error) = pchain_runtime::Runtime::new()
.set_smart_contract_cache(pchain_runtime::Cache::new(std::path::Path::new(
CONTRACT_CACHE_FOLDER,
)))
.view(
sws.world_state.clone(),
u64::MAX,
contract_address,
"emit_event_with_return".to_string(),
ArgsBuilder::new().add(method_args.clone()).args,
);
assert!(error.is_none());
let gas_used = receipt.gas_used;
println!("{:?}", receipt.return_values);
let result_value: u32 = CallResult::parse(receipt.return_values).unwrap();
assert_eq!(result_value as usize, method_args.len());
assert!(receipt
.logs
.iter()
.find(|e| {
String::from_utf8(e.topic.clone()).unwrap() == "topic: Hello From".to_string()
&& String::from_utf8(e.value.clone()).unwrap()
== format!("Hello, Contract. From: {}", method_args).to_string()
})
.is_some());
let (receipt, error) = pchain_runtime::Runtime::new()
.set_smart_contract_cache(pchain_runtime::Cache::new(std::path::Path::new(
CONTRACT_CACHE_FOLDER,
)))
.view(
sws.world_state.clone(),
u64::MAX,
contract_address,
"emit_event_with_return".to_string(),
ArgsBuilder::new().add(method_args.clone()).args,
);
assert!(error.is_none());
assert_eq!(receipt.gas_used, gas_used);
let (receipt, error) = pchain_runtime::Runtime::new()
.set_smart_contract_cache(pchain_runtime::Cache::new(std::path::Path::new(
CONTRACT_CACHE_FOLDER,
)))
.view(
sws.world_state,
u64::MAX,
[123u8; 32],
"emit_event_with_return".to_string(),
ArgsBuilder::new().add(method_args.clone()).args,
);
assert_eq!(receipt.exit_status, ExitStatus::Failed);
assert_eq!(error, Some(TransitionError::InvalidCBI));
if std::path::Path::new(CONTRACT_CACHE_FOLDER).exists() {
std::fs::remove_dir_all(CONTRACT_CACHE_FOLDER).unwrap();
}
}
#[test]
fn test_view_failure() {
let wasm_bytes = TestData::get_test_contract_code("basic_contract");
let target = [2u8; 32];
let mut sws = SimulateWorldState::default();
sws.add_contract(target, wasm_bytes, pchain_runtime::cbi_version());
let (receipt, error) = pchain_runtime::Runtime::new().view(
sws.world_state.clone(),
u64::MAX,
target,
"emit_event_with_return".to_string(),
ArgsBuilder::new()
.add(1u8) .args,
);
assert_eq!(receipt.exit_status, ExitStatus::Failed);
assert_eq!(error, Some(TransitionError::RuntimeError));
let (receipt, error) = pchain_runtime::Runtime::new().view(
sws.world_state.clone(),
1_000_000, target,
"emit_event_with_return".to_string(),
ArgsBuilder::new().add("arg".to_string()).args,
);
assert_eq!(receipt.exit_status, ExitStatus::GasExhausted);
assert_eq!(error, Some(TransitionError::ExecutionProperGasExhausted));
let (receipt, error) = pchain_runtime::Runtime::new().view(
sws.world_state,
u64::MAX,
target,
"set_state_without_self".to_string(),
ArgsBuilder::new().add(1u8).args,
);
assert_eq!(receipt.exit_status, ExitStatus::Failed);
assert_eq!(error, Some(TransitionError::RuntimeError));
}