use sc_virtualization::VirtManager;
use sp_virtualization::{
tests::{make_handler, run_loop, RunResult, GAS_MAX},
CompileStatus, Module, ModuleError,
};
fn setup() -> sp_io::TestExternalities {
sp_tracing::try_init_simple();
let mut ext = sp_io::TestExternalities::default();
ext.register_extension(sp_virtualization::VirtManagerExt::new(VirtManager::default()));
ext
}
fn binary() -> &'static [u8] {
sp_virtualization_test_fixture::binary()
}
#[test]
fn run_all() {
setup().execute_with(|| sp_virtualization::run_tests(binary()));
}
#[test]
fn from_storage_key_cache_hit() {
let program = binary();
let key = b"some-cache-key";
setup().execute_with(|| {
let (_module, status) = Module::from_bytes(program, Some(key)).unwrap();
assert_eq!(status, CompileStatus::Compiled);
let (module, status) = Module::from_storage_key(key, b"").unwrap();
assert_eq!(status, CompileStatus::Cached);
let instance = module.instantiate().unwrap();
let execution = instance.prepare(b"counter").unwrap();
let mut gas_left = GAS_MAX;
let mut counter: u64 = 0;
let result = run_loop(execution, &mut gas_left, make_handler(&mut counter));
assert!(matches!(result, RunResult::Ok(_)));
assert_eq!(counter, 8);
});
}
#[test]
fn lookup_is_pure() {
let program = binary();
let key: &[u8] = b"stored-but-not-cached";
let mut ext = setup();
ext.insert(key.to_vec(), program.to_vec());
ext.execute_with(|| {
assert!(matches!(Module::lookup(key), Err(ModuleError::NotCached)));
let other: &[u8] = b"some-other-key";
let _ = Module::from_bytes(program, Some(other)).unwrap();
assert!(Module::lookup(other).is_ok());
});
}
#[test]
fn from_bytes_cache_hit() {
let program = binary();
let key = b"compile-twice";
setup().execute_with(|| {
let (_module, status) = Module::from_bytes(program, Some(key)).unwrap();
assert_eq!(status, CompileStatus::Compiled);
let (_module, status) = Module::from_bytes(program, Some(key)).unwrap();
assert_eq!(status, CompileStatus::Cached);
});
}
#[test]
fn from_bytes_none_skips_cache() {
let program = binary();
let key = b"would-be-key";
setup().execute_with(|| {
let (_module, status) = Module::from_bytes(program, None).unwrap();
assert_eq!(status, CompileStatus::Compiled);
assert!(matches!(Module::from_storage_key(key, b""), Err(ModuleError::NotFound)));
});
}
#[test]
fn from_storage_key_main_trie() {
let program = binary();
let key: &[u8] = b"code:my-program";
let mut ext = setup();
ext.insert(key.to_vec(), program.to_vec());
ext.execute_with(|| {
let (module, status) = Module::from_storage_key(key, b"").unwrap();
assert_eq!(status, CompileStatus::Compiled);
let instance = module.instantiate().unwrap();
let execution = instance.prepare(b"counter").unwrap();
let mut gas_left = GAS_MAX;
let mut counter: u64 = 0;
let result = run_loop(execution, &mut gas_left, make_handler(&mut counter));
assert!(matches!(result, RunResult::Ok(_)));
assert_eq!(counter, 8);
let (module, status) = Module::from_storage_key(key, b"").unwrap();
assert_eq!(status, CompileStatus::Cached);
let instance = module.instantiate().unwrap();
let execution = instance.prepare(b"counter").unwrap();
let mut counter: u64 = 0;
let result = run_loop(execution, &mut gas_left, make_handler(&mut counter));
assert!(matches!(result, RunResult::Ok(_)));
assert_eq!(counter, 8);
});
}
#[test]
fn from_storage_key_child_trie() {
let program = binary();
let key: &[u8] = b"code:my-program";
let child_trie = b"contracts";
let child_info = sp_storage::ChildInfo::new_default(child_trie);
let mut ext = setup();
ext.insert_child(child_info, key.to_vec(), program.to_vec());
ext.execute_with(|| {
let (module, status) = Module::from_storage_key(key, child_trie).unwrap();
assert_eq!(status, CompileStatus::Compiled);
let instance = module.instantiate().unwrap();
let execution = instance.prepare(b"counter").unwrap();
let mut gas_left = GAS_MAX;
let mut counter: u64 = 0;
let result = run_loop(execution, &mut gas_left, make_handler(&mut counter));
assert!(matches!(result, RunResult::Ok(_)));
assert_eq!(counter, 8);
});
}
#[test]
fn from_storage_key_invalid_image() {
let key: &[u8] = b"code:garbage";
let mut ext = setup();
ext.insert(key.to_vec(), b"this is not a valid polkavm program".to_vec());
ext.execute_with(|| {
assert!(matches!(Module::from_storage_key(key, b""), Err(ModuleError::InvalidImage)));
});
}