2017-05-03 11:06:26 +03:00
///! Basic tests for instructions/constructions, missing in wabt tests
2017-06-14 14:09:00 +03:00
use std ::sync ::{ Arc , Weak } ;
2017-08-03 11:25:44 +03:00
use std ::cell ::RefCell ;
2017-07-31 11:58:24 +03:00
use std ::collections ::HashMap ;
2017-05-03 11:06:26 +03:00
use builder ::module ;
use elements ::{ ExportEntry , Internal , ImportEntry , External , GlobalEntry , GlobalType ,
2017-09-04 12:00:01 +03:00
InitExpr , ValueType , BlockType , Opcodes , Opcode , FunctionType , TableType , MemoryType } ;
2017-08-01 16:15:08 +03:00
use interpreter ::{ Error , UserError , ProgramInstance , DefaultProgramInstance , DefaultModuleInstance } ;
2017-07-31 11:58:24 +03:00
use interpreter ::env_native ::{ env_native_module , UserDefinedElements , UserFunctionExecutor , UserFunctionDescriptor } ;
2017-05-19 09:36:50 +03:00
use interpreter ::memory ::MemoryInstance ;
2017-08-01 13:16:25 +03:00
use interpreter ::module ::{ ModuleInstanceInterface , CallerContext , ItemIndex , ExecutionParams , ExportEntryType , FunctionSignature } ;
2017-06-14 14:09:00 +03:00
use interpreter ::validator ::{ FunctionValidationContext , Validator } ;
2017-07-31 11:58:24 +03:00
use interpreter ::value ::{ RuntimeValue , TryInto } ;
use interpreter ::variable ::{ VariableInstance , ExternalVariableValue , VariableType } ;
2017-05-03 11:06:26 +03:00
#[ test ]
fn import_function ( ) {
let module1 = module ( )
. with_export ( ExportEntry ::new ( " external_func " . into ( ) , Internal ::Function ( 0 ) ) )
. function ( )
. signature ( ) . return_type ( ) . i32 ( ) . build ( )
. body ( ) . with_opcodes ( Opcodes ::new ( vec! [
Opcode ::I32Const ( 3 ) ,
Opcode ::End ,
] ) ) . build ( )
. build ( )
. build ( ) ;
let module2 = module ( )
. with_import ( ImportEntry ::new ( " external_module " . into ( ) , " external_func " . into ( ) , External ::Function ( 0 ) ) )
. function ( )
. signature ( ) . return_type ( ) . i32 ( ) . build ( )
. body ( ) . with_opcodes ( Opcodes ::new ( vec! [
Opcode ::Call ( 0 ) ,
Opcode ::I32Const ( 7 ) ,
Opcode ::I32Add ,
Opcode ::End ,
] ) ) . build ( )
. build ( )
. build ( ) ;
2017-08-01 14:44:33 +03:00
let program = DefaultProgramInstance ::new ( ) . unwrap ( ) ;
2017-06-13 12:01:59 +03:00
let external_module = program . add_module ( " external_module " , module1 , None ) . unwrap ( ) ;
let main_module = program . add_module ( " main " , module2 , None ) . unwrap ( ) ;
2017-05-03 11:06:26 +03:00
2017-05-18 15:08:55 +03:00
assert_eq! ( external_module . execute_index ( 0 , vec! [ ] . into ( ) ) . unwrap ( ) . unwrap ( ) , RuntimeValue ::I32 ( 3 ) ) ;
assert_eq! ( main_module . execute_index ( 1 , vec! [ ] . into ( ) ) . unwrap ( ) . unwrap ( ) , RuntimeValue ::I32 ( 10 ) ) ;
2017-05-03 11:06:26 +03:00
}
2017-05-12 19:49:51 +03:00
#[ test ]
fn wrong_import ( ) {
let side_module = module ( )
. with_export ( ExportEntry ::new ( " cool_func " . into ( ) , Internal ::Function ( 0 ) ) )
. function ( )
. signature ( ) . return_type ( ) . i32 ( ) . build ( )
. body ( ) . with_opcodes ( Opcodes ::new ( vec! [
Opcode ::I32Const ( 3 ) ,
Opcode ::End ,
] ) ) . build ( )
. build ( )
. build ( ) ;
let module = module ( )
. with_import ( ImportEntry ::new ( " side_module " . into ( ) , " not_cool_func " . into ( ) , External ::Function ( 0 ) ) )
. function ( )
. signature ( ) . return_type ( ) . i32 ( ) . build ( )
. body ( ) . with_opcodes ( Opcodes ::new ( vec! [
Opcode ::Call ( 0 ) ,
Opcode ::I32Const ( 7 ) ,
Opcode ::I32Add ,
Opcode ::End ,
] ) ) . build ( )
. build ( )
. build ( ) ;
2017-08-01 14:44:33 +03:00
let program = DefaultProgramInstance ::new ( ) . unwrap ( ) ;
2017-06-13 12:01:59 +03:00
let _side_module_instance = program . add_module ( " side_module " , side_module , None ) . unwrap ( ) ;
2017-11-23 13:42:17 +03:00
assert! ( program . add_module ( " main " , module , None ) . is_err ( ) ) ;
2017-05-12 19:49:51 +03:00
}
2017-05-03 11:06:26 +03:00
#[ test ]
fn global_get_set ( ) {
let module = module ( )
. with_global ( GlobalEntry ::new ( GlobalType ::new ( ValueType ::I32 , true ) , InitExpr ::new ( vec! [ Opcode ::I32Const ( 42 ) ] ) ) )
. function ( )
. signature ( ) . return_type ( ) . i32 ( ) . build ( )
. body ( ) . with_opcodes ( Opcodes ::new ( vec! [
Opcode ::GetGlobal ( 0 ) ,
Opcode ::I32Const ( 8 ) ,
Opcode ::I32Add ,
Opcode ::SetGlobal ( 0 ) ,
Opcode ::GetGlobal ( 0 ) ,
Opcode ::End ,
] ) ) . build ( )
. build ( )
. build ( ) ;
2017-08-01 14:44:33 +03:00
let program = DefaultProgramInstance ::new ( ) . unwrap ( ) ;
2017-06-22 17:52:05 +03:00
let module = program . add_module ( " main " , module , None ) . unwrap ( ) ;
2017-05-18 15:08:55 +03:00
assert_eq! ( module . execute_index ( 0 , vec! [ ] . into ( ) ) . unwrap ( ) . unwrap ( ) , RuntimeValue ::I32 ( 50 ) ) ;
2017-07-11 19:12:01 +03:00
assert_eq! ( module . execute_index ( 0 , vec! [ ] . into ( ) ) . unwrap ( ) . unwrap ( ) , RuntimeValue ::I32 ( 58 ) ) ;
2017-05-03 11:06:26 +03:00
}
2017-05-15 15:40:08 +03:00
2017-06-26 17:32:18 +03:00
const SIGNATURE_I32_I32 : & 'static [ ValueType ] = & [ ValueType ::I32 , ValueType ::I32 ] ;
2017-06-14 17:07:22 +03:00
2017-06-26 11:54:17 +03:00
const SIGNATURES : & 'static [ UserFunctionDescriptor ] = & [
UserFunctionDescriptor ::Static (
" add " ,
2017-06-26 17:32:18 +03:00
SIGNATURE_I32_I32 ,
2017-06-26 11:54:17 +03:00
Some ( ValueType ::I32 ) ,
) ,
UserFunctionDescriptor ::Static (
" sub " ,
2017-06-26 17:32:18 +03:00
SIGNATURE_I32_I32 ,
2017-06-26 11:54:17 +03:00
Some ( ValueType ::I32 ) ,
) ,
2017-08-01 13:16:25 +03:00
UserFunctionDescriptor ::Static (
" err " ,
SIGNATURE_I32_I32 ,
Some ( ValueType ::I32 ) ,
) ,
2017-06-14 17:07:22 +03:00
] ;
2017-07-31 11:58:24 +03:00
const NO_SIGNATURES : & 'static [ UserFunctionDescriptor ] = & [ ] ;
// 'external' variable
struct MeasuredVariable {
pub val : i32 ,
}
2017-08-01 16:15:08 +03:00
impl ExternalVariableValue < UserErrorWithCode > for MeasuredVariable {
2017-07-31 11:58:24 +03:00
fn get ( & self ) -> RuntimeValue {
RuntimeValue ::I32 ( self . val )
}
2017-08-01 16:15:08 +03:00
fn set ( & mut self , val : RuntimeValue ) -> Result < ( ) , Error < UserErrorWithCode > > {
2017-07-31 11:58:24 +03:00
self . val = val . try_into ( ) ? ;
Ok ( ( ) )
}
}
2017-08-01 13:16:25 +03:00
// custom user error
#[ derive(Debug, Clone, PartialEq) ]
2017-08-01 16:15:08 +03:00
struct UserErrorWithCode {
2017-08-01 13:16:25 +03:00
error_code : i32 ,
}
2017-08-01 16:15:08 +03:00
impl ::std ::fmt ::Display for UserErrorWithCode {
2017-08-01 13:16:25 +03:00
fn fmt ( & self , f : & mut ::std ::fmt ::Formatter ) -> Result < ( ) , ::std ::fmt ::Error > {
write! ( f , " {} " , self . error_code )
}
}
2017-08-01 16:15:08 +03:00
impl UserError for UserErrorWithCode { }
2017-08-01 13:16:25 +03:00
2017-06-21 09:23:20 +03:00
// user function executor
struct FunctionExecutor {
2017-08-01 16:15:08 +03:00
pub memory : Arc < MemoryInstance < UserErrorWithCode > > ,
2017-06-21 09:23:20 +03:00
pub values : Vec < i32 > ,
}
2017-05-19 09:36:50 +03:00
2017-08-01 16:15:08 +03:00
impl UserFunctionExecutor < UserErrorWithCode > for FunctionExecutor {
fn execute ( & mut self , name : & str , context : CallerContext < UserErrorWithCode > ) -> Result < Option < RuntimeValue > , Error < UserErrorWithCode > > {
2017-06-21 09:23:20 +03:00
match name {
" add " = > {
let memory_value = self . memory . get ( 0 , 1 ) . unwrap ( ) [ 0 ] ;
2017-06-26 17:32:18 +03:00
let fn_argument_unused = context . value_stack . pop_as ::< u32 > ( ) . unwrap ( ) as u8 ;
2017-06-21 09:23:20 +03:00
let fn_argument = context . value_stack . pop_as ::< u32 > ( ) . unwrap ( ) as u8 ;
2017-06-26 17:32:18 +03:00
assert_eq! ( fn_argument_unused , 0 ) ;
2017-06-21 09:23:20 +03:00
let sum = memory_value + fn_argument ;
self . memory . set ( 0 , & vec! [ sum ] ) . unwrap ( ) ;
self . values . push ( sum as i32 ) ;
Ok ( Some ( RuntimeValue ::I32 ( sum as i32 ) ) )
} ,
" sub " = > {
let memory_value = self . memory . get ( 0 , 1 ) . unwrap ( ) [ 0 ] ;
2017-06-26 17:32:18 +03:00
let fn_argument_unused = context . value_stack . pop_as ::< u32 > ( ) . unwrap ( ) as u8 ;
2017-06-21 09:23:20 +03:00
let fn_argument = context . value_stack . pop_as ::< u32 > ( ) . unwrap ( ) as u8 ;
2017-06-26 17:32:18 +03:00
assert_eq! ( fn_argument_unused , 0 ) ;
2017-06-21 09:23:20 +03:00
let diff = memory_value - fn_argument ;
self . memory . set ( 0 , & vec! [ diff ] ) . unwrap ( ) ;
self . values . push ( diff as i32 ) ;
Ok ( Some ( RuntimeValue ::I32 ( diff as i32 ) ) )
} ,
2017-08-01 13:16:25 +03:00
" err " = > {
2017-08-01 16:15:08 +03:00
Err ( Error ::User ( UserErrorWithCode { error_code : 777 } ) )
2017-08-01 13:16:25 +03:00
} ,
_ = > Err ( Error ::Trap ( " not implemented " . into ( ) ) . into ( ) ) ,
2017-05-19 09:36:50 +03:00
}
}
2017-06-21 09:23:20 +03:00
}
2017-05-19 09:36:50 +03:00
2017-06-21 09:23:20 +03:00
#[ test ]
2017-07-31 11:58:24 +03:00
fn native_env_function ( ) {
2017-05-19 09:36:50 +03:00
// create new program
2017-08-01 14:44:33 +03:00
let program = ProgramInstance ::new ( ) . unwrap ( ) ;
2017-05-19 09:36:50 +03:00
// => env module is created
let env_instance = program . module ( " env " ) . unwrap ( ) ;
// => linear memory is created
let env_memory = env_instance . memory ( ItemIndex ::Internal ( 0 ) ) . unwrap ( ) ;
2017-05-15 15:40:08 +03:00
2017-06-13 12:01:59 +03:00
// create native env module executor
2017-05-19 09:36:50 +03:00
let mut executor = FunctionExecutor {
memory : env_memory . clone ( ) ,
values : Vec ::new ( ) ,
} ;
{
2017-08-01 13:16:25 +03:00
let functions = UserDefinedElements {
2017-07-31 11:58:24 +03:00
executor : Some ( & mut executor ) ,
globals : HashMap ::new ( ) ,
2017-06-14 17:07:22 +03:00
functions : ::std ::borrow ::Cow ::from ( SIGNATURES ) ,
2017-05-19 09:36:50 +03:00
} ;
let native_env_instance = Arc ::new ( env_native_module ( env_instance , functions ) . unwrap ( ) ) ;
let params = ExecutionParams ::with_external ( " env " . into ( ) , native_env_instance ) ;
2017-06-13 12:01:59 +03:00
let module = module ( )
. with_import ( ImportEntry ::new ( " env " . into ( ) , " add " . into ( ) , External ::Function ( 0 ) ) )
. with_import ( ImportEntry ::new ( " env " . into ( ) , " sub " . into ( ) , External ::Function ( 0 ) ) )
. function ( )
2017-06-26 17:32:18 +03:00
. signature ( ) . param ( ) . i32 ( ) . param ( ) . i32 ( ) . return_type ( ) . i32 ( ) . build ( )
2017-06-13 12:01:59 +03:00
. body ( ) . with_opcodes ( Opcodes ::new ( vec! [
Opcode ::GetLocal ( 0 ) ,
2017-06-26 17:32:18 +03:00
Opcode ::GetLocal ( 1 ) ,
2017-06-13 12:01:59 +03:00
Opcode ::Call ( 0 ) ,
Opcode ::End ,
] ) ) . build ( )
. build ( )
. function ( )
2017-06-26 17:32:18 +03:00
. signature ( ) . param ( ) . i32 ( ) . param ( ) . i32 ( ) . return_type ( ) . i32 ( ) . build ( )
2017-06-13 12:01:59 +03:00
. body ( ) . with_opcodes ( Opcodes ::new ( vec! [
Opcode ::GetLocal ( 0 ) ,
2017-06-26 17:32:18 +03:00
Opcode ::GetLocal ( 1 ) ,
2017-06-13 12:01:59 +03:00
Opcode ::Call ( 1 ) ,
Opcode ::End ,
] ) ) . build ( )
. build ( )
. build ( ) ;
// load module
let module_instance = program . add_module ( " main " , module , Some ( & params . externals ) ) . unwrap ( ) ;
{
2017-06-26 17:32:18 +03:00
assert_eq! ( module_instance . execute_index ( 2 , params . clone ( ) . add_argument ( RuntimeValue ::I32 ( 7 ) ) . add_argument ( RuntimeValue ::I32 ( 0 ) ) ) . unwrap ( ) . unwrap ( ) , RuntimeValue ::I32 ( 7 ) ) ;
assert_eq! ( module_instance . execute_index ( 2 , params . clone ( ) . add_argument ( RuntimeValue ::I32 ( 50 ) ) . add_argument ( RuntimeValue ::I32 ( 0 ) ) ) . unwrap ( ) . unwrap ( ) , RuntimeValue ::I32 ( 57 ) ) ;
assert_eq! ( module_instance . execute_index ( 3 , params . clone ( ) . add_argument ( RuntimeValue ::I32 ( 15 ) ) . add_argument ( RuntimeValue ::I32 ( 0 ) ) ) . unwrap ( ) . unwrap ( ) , RuntimeValue ::I32 ( 42 ) ) ;
2017-06-13 12:01:59 +03:00
}
2017-05-19 09:36:50 +03:00
}
assert_eq! ( executor . memory . get ( 0 , 1 ) . unwrap ( ) [ 0 ] , 42 ) ;
assert_eq! ( executor . values , vec! [ 7 , 57 , 42 ] ) ;
}
2017-06-14 14:09:00 +03:00
2017-08-03 11:25:44 +03:00
#[ test ]
fn native_env_function_own_memory ( ) {
// create program + env module is auto instantiated + env module memory is instantiated (we do not need this)
let program = ProgramInstance ::new ( ) . unwrap ( ) ;
struct OwnMemoryReference {
pub memory : RefCell < Option < Arc < MemoryInstance < UserErrorWithCode > > > > ,
}
struct OwnMemoryExecutor {
pub memory_ref : Arc < OwnMemoryReference > ,
}
impl UserFunctionExecutor < UserErrorWithCode > for OwnMemoryExecutor {
fn execute ( & mut self , name : & str , context : CallerContext < UserErrorWithCode > ) -> Result < Option < RuntimeValue > , Error < UserErrorWithCode > > {
match name {
" add " = > {
let memory = self . memory_ref . memory . borrow_mut ( ) . as_ref ( ) . expect ( " initialized before execution; qed " ) . clone ( ) ;
let memory_value = memory . get ( 0 , 1 ) . unwrap ( ) [ 0 ] ;
let fn_argument_unused = context . value_stack . pop_as ::< u32 > ( ) . unwrap ( ) as u8 ;
let fn_argument = context . value_stack . pop_as ::< u32 > ( ) . unwrap ( ) as u8 ;
assert_eq! ( fn_argument_unused , 0 ) ;
let sum = memory_value + fn_argument ;
memory . set ( 0 , & vec! [ sum ] ) . unwrap ( ) ;
Ok ( Some ( RuntimeValue ::I32 ( sum as i32 ) ) )
} ,
_ = > Err ( Error ::Trap ( " not implemented " . into ( ) ) . into ( ) ) ,
}
}
}
let env_instance = program . module ( " env " ) . unwrap ( ) ;
let memory_ref = Arc ::new ( OwnMemoryReference { memory : RefCell ::new ( None ) } ) ;
let mut executor = OwnMemoryExecutor { memory_ref : memory_ref . clone ( ) } ;
let native_env_instance = Arc ::new ( env_native_module ( env_instance , UserDefinedElements {
executor : Some ( & mut executor ) ,
globals : HashMap ::new ( ) ,
functions : ::std ::borrow ::Cow ::from ( SIGNATURES ) ,
} ) . unwrap ( ) ) ;
let params = ExecutionParams ::with_external ( " env " . into ( ) , native_env_instance ) ;
// create module definition with its own memory
// => since we do not import env' memory, all instructions from this module will access this memory
let module = module ( )
. memory ( ) . build ( ) // new memory is created
. with_import ( ImportEntry ::new ( " env " . into ( ) , " add " . into ( ) , External ::Function ( 0 ) ) ) // import 'native' function
. function ( ) // add simple wasm function
. signature ( ) . param ( ) . i32 ( ) . param ( ) . i32 ( ) . return_type ( ) . i32 ( ) . build ( )
. body ( ) . with_opcodes ( Opcodes ::new ( vec! [
Opcode ::GetLocal ( 0 ) ,
Opcode ::GetLocal ( 1 ) ,
Opcode ::Call ( 0 ) ,
Opcode ::End ,
] ) ) . build ( )
. build ( )
. build ( ) ;
// instantiate module
let module_instance = program . add_module ( " main " , module , Some ( & params . externals ) ) . unwrap ( ) ;
// now get memory reference
let module_memory = module_instance . memory ( ItemIndex ::Internal ( 0 ) ) . unwrap ( ) ;
2017-11-23 13:42:17 +03:00
// post-initialize our executor with memory reference
2017-08-03 11:25:44 +03:00
* memory_ref . memory . borrow_mut ( ) = Some ( module_memory ) ;
// now execute function => executor updates memory
assert_eq! ( module_instance . execute_index ( 1 , params . clone ( ) . add_argument ( RuntimeValue ::I32 ( 7 ) ) . add_argument ( RuntimeValue ::I32 ( 0 ) ) ) . unwrap ( ) . unwrap ( ) ,
RuntimeValue ::I32 ( 7 ) ) ;
}
2017-07-31 11:58:24 +03:00
#[ test ]
fn native_env_global ( ) {
// module constructor
let module_constructor = | elements | {
let program = ProgramInstance ::new ( ) . unwrap ( ) ;
let env_instance = program . module ( " env " ) . unwrap ( ) ;
let native_env_instance = Arc ::new ( env_native_module ( env_instance . clone ( ) , elements ) . unwrap ( ) ) ;
let params = ExecutionParams ::with_external ( " env " . into ( ) , native_env_instance ) ;
let module = module ( )
. with_import ( ImportEntry ::new ( " env " . into ( ) , " ext_global " . into ( ) , External ::Global ( GlobalType ::new ( ValueType ::I32 , false ) ) ) )
. function ( )
. signature ( ) . return_type ( ) . i32 ( ) . build ( )
. body ( ) . with_opcodes ( Opcodes ::new ( vec! [
Opcode ::GetGlobal ( 0 ) ,
Opcode ::End ,
] ) ) . build ( )
. build ( )
. build ( ) ;
program . add_module ( " main " , module , Some ( & params . externals ) ) ?
. execute_index ( 0 , params . clone ( ) )
} ;
// try to add module, exporting non-existant env' variable => error
{
assert! ( module_constructor ( UserDefinedElements {
executor : None ,
globals : HashMap ::new ( ) ,
functions : ::std ::borrow ::Cow ::from ( NO_SIGNATURES ) ,
} ) . is_err ( ) ) ;
}
// now add simple variable natively => ok
{
assert_eq! ( module_constructor ( UserDefinedElements {
executor : None ,
globals : vec ! [ ( " ext_global " . into ( ) , Arc ::new ( VariableInstance ::new ( false , VariableType ::I32 , RuntimeValue ::I32 ( 777 ) ) . unwrap ( ) ) ) ] . into_iter ( ) . collect ( ) ,
functions : ::std ::borrow ::Cow ::from ( NO_SIGNATURES ) ,
} ) . unwrap ( ) . unwrap ( ) , RuntimeValue ::I32 ( 777 ) ) ;
}
// now add 'getter+setter' variable natively => ok
{
assert_eq! ( module_constructor ( UserDefinedElements {
executor : None ,
globals : vec ! [ ( " ext_global " . into ( ) , Arc ::new ( VariableInstance ::new_external_global ( false , VariableType ::I32 , Box ::new ( MeasuredVariable { val : 345 } ) ) . unwrap ( ) ) ) ] . into_iter ( ) . collect ( ) ,
functions : ::std ::borrow ::Cow ::from ( NO_SIGNATURES ) ,
} ) . unwrap ( ) . unwrap ( ) , RuntimeValue ::I32 ( 345 ) ) ;
}
}
2017-08-01 13:16:25 +03:00
#[ test ]
fn native_custom_error ( ) {
2017-08-01 14:44:33 +03:00
let program = ProgramInstance ::new ( ) . unwrap ( ) ;
2017-08-01 13:16:25 +03:00
let env_instance = program . module ( " env " ) . unwrap ( ) ;
let env_memory = env_instance . memory ( ItemIndex ::Internal ( 0 ) ) . unwrap ( ) ;
let mut executor = FunctionExecutor { memory : env_memory . clone ( ) , values : Vec ::new ( ) } ;
let functions = UserDefinedElements {
executor : Some ( & mut executor ) ,
globals : HashMap ::new ( ) ,
functions : ::std ::borrow ::Cow ::from ( SIGNATURES ) ,
} ;
let native_env_instance = Arc ::new ( env_native_module ( env_instance , functions ) . unwrap ( ) ) ;
let params = ExecutionParams ::with_external ( " env " . into ( ) , native_env_instance ) ;
let module = module ( )
. with_import ( ImportEntry ::new ( " env " . into ( ) , " err " . into ( ) , External ::Function ( 0 ) ) )
. function ( )
. signature ( ) . param ( ) . i32 ( ) . param ( ) . i32 ( ) . return_type ( ) . i32 ( ) . build ( )
. body ( ) . with_opcodes ( Opcodes ::new ( vec! [
Opcode ::GetLocal ( 0 ) ,
Opcode ::GetLocal ( 1 ) ,
Opcode ::Call ( 0 ) ,
Opcode ::End ,
] ) ) . build ( )
. build ( )
. build ( ) ;
let module_instance = program . add_module ( " main " , module , Some ( & params . externals ) ) . unwrap ( ) ;
assert_eq! ( module_instance . execute_index ( 0 , params . clone ( ) . add_argument ( RuntimeValue ::I32 ( 7 ) ) . add_argument ( RuntimeValue ::I32 ( 0 ) ) ) ,
2017-08-01 16:15:08 +03:00
Err ( Error ::User ( UserErrorWithCode { error_code : 777 } ) ) ) ;
2017-08-01 13:16:25 +03:00
assert_eq! ( module_instance . execute_index ( 1 , params . clone ( ) . add_argument ( RuntimeValue ::I32 ( 7 ) ) . add_argument ( RuntimeValue ::I32 ( 0 ) ) ) ,
2017-08-01 16:15:08 +03:00
Err ( Error ::User ( UserErrorWithCode { error_code : 777 } ) ) ) ;
2017-08-01 13:16:25 +03:00
}
2017-07-25 14:31:17 +03:00
#[ test ]
2017-07-25 15:26:31 +03:00
fn import_env_mutable_global ( ) {
2017-08-01 14:44:33 +03:00
let program = DefaultProgramInstance ::new ( ) . unwrap ( ) ;
2017-07-25 14:31:17 +03:00
2017-07-25 15:26:31 +03:00
let module = module ( )
. with_import ( ImportEntry ::new ( " env " . into ( ) , " STACKTOP " . into ( ) , External ::Global ( GlobalType ::new ( ValueType ::I32 , false ) ) ) )
. build ( ) ;
2017-07-25 14:31:17 +03:00
2017-07-25 15:26:31 +03:00
program . add_module ( " main " , module , None ) . unwrap ( ) ;
2017-07-25 14:31:17 +03:00
}
2017-06-21 09:23:20 +03:00
#[ test ]
fn env_native_export_entry_type_check ( ) {
2017-08-01 14:44:33 +03:00
let program = ProgramInstance ::new ( ) . unwrap ( ) ;
2017-06-21 09:23:20 +03:00
let mut function_executor = FunctionExecutor {
memory : program . module ( " env " ) . unwrap ( ) . memory ( ItemIndex ::Internal ( 0 ) ) . unwrap ( ) ,
values : Vec ::new ( ) ,
} ;
2017-07-31 11:58:24 +03:00
let native_env_instance = Arc ::new ( env_native_module ( program . module ( " env " ) . unwrap ( ) , UserDefinedElements {
executor : Some ( & mut function_executor ) ,
2017-11-23 13:42:17 +03:00
globals : vec ! [ ( " ext_global " . into ( ) , Arc ::new ( VariableInstance ::new ( false , VariableType ::I32 , RuntimeValue ::I32 ( 1312 ) ) . unwrap ( ) ) ) ] . into_iter ( ) . collect ( ) ,
2017-06-21 09:23:20 +03:00
functions : ::std ::borrow ::Cow ::from ( SIGNATURES ) ,
} ) . unwrap ( ) ) ;
2017-06-26 17:32:18 +03:00
assert! ( native_env_instance . export_entry ( " add " , & ExportEntryType ::Function ( FunctionSignature ::Module ( & FunctionType ::new ( vec! [ ValueType ::I32 , ValueType ::I32 ] , Some ( ValueType ::I32 ) ) ) ) ) . is_ok ( ) ) ;
2017-11-23 13:42:17 +03:00
match native_env_instance . export_entry ( " add " , & ExportEntryType ::Function ( FunctionSignature ::Module ( & FunctionType ::new ( vec! [ ] , Some ( ValueType ::I32 ) ) ) ) ) {
Err ( Error ::Validation ( _ ) ) = > { } ,
result = > panic! ( " Unexpected result {:?} . " , result ) ,
}
match native_env_instance . export_entry ( " add " , & ExportEntryType ::Function ( FunctionSignature ::Module ( & FunctionType ::new ( vec! [ ValueType ::I32 , ValueType ::I32 ] , None ) ) ) ) {
Err ( Error ::Validation ( _ ) ) = > { } ,
result = > panic! ( " Unexpected result {:?} . " , result ) ,
}
match native_env_instance . export_entry ( " add " , & ExportEntryType ::Function ( FunctionSignature ::Module ( & FunctionType ::new ( vec! [ ValueType ::I32 , ValueType ::I32 ] , Some ( ValueType ::I64 ) ) ) ) ) {
Err ( Error ::Validation ( _ ) ) = > { } ,
result = > panic! ( " Unexpected result {:?} . " , result ) ,
}
assert! ( native_env_instance . export_entry ( " ext_global " , & ExportEntryType ::Global ( VariableType ::I32 ) ) . is_ok ( ) ) ;
match native_env_instance . export_entry ( " ext_global " , & ExportEntryType ::Global ( VariableType ::F32 ) ) {
Err ( Error ::Validation ( _ ) ) = > { } ,
result = > panic! ( " Unexpected result {:?} . " , result ) ,
}
2017-06-21 09:23:20 +03:00
}
2017-06-14 14:09:00 +03:00
#[ test ]
fn if_else_with_return_type_validation ( ) {
2017-08-01 14:44:33 +03:00
let module_instance = DefaultModuleInstance ::new ( Weak ::default ( ) , " test " . into ( ) , module ( ) . build ( ) ) . unwrap ( ) ;
2017-07-31 11:58:24 +03:00
let mut context = FunctionValidationContext ::new ( & module_instance , None , & [ ] , 1024 , 1024 , FunctionSignature ::Module ( & FunctionType ::default ( ) ) ) ;
2017-06-14 14:09:00 +03:00
2017-06-19 13:55:53 +03:00
Validator ::validate_function ( & mut context , BlockType ::NoResult , & [
2017-06-14 14:09:00 +03:00
Opcode ::I32Const ( 1 ) ,
2017-06-22 17:52:05 +03:00
Opcode ::If ( BlockType ::NoResult ) ,
2017-06-14 14:09:00 +03:00
Opcode ::I32Const ( 1 ) ,
2017-06-22 17:52:05 +03:00
Opcode ::If ( BlockType ::Value ( ValueType ::I32 ) ) ,
2017-06-14 14:09:00 +03:00
Opcode ::I32Const ( 1 ) ,
2017-06-22 17:52:05 +03:00
Opcode ::Else ,
2017-06-14 14:09:00 +03:00
Opcode ::I32Const ( 2 ) ,
Opcode ::End ,
2017-06-22 17:52:05 +03:00
Opcode ::Drop ,
Opcode ::End ,
2017-06-14 14:09:00 +03:00
Opcode ::End ,
2017-06-19 13:55:53 +03:00
] ) . unwrap ( ) ;
2017-06-14 14:09:00 +03:00
}
2017-09-04 12:00:01 +03:00
#[ test ]
fn memory_import_limits_initial ( ) {
let core_module = module ( )
. memory ( ) . with_min ( 10 ) . build ( )
. with_export ( ExportEntry ::new ( " memory " . into ( ) , Internal ::Memory ( 0 ) ) )
. build ( ) ;
let program = DefaultProgramInstance ::new ( ) . unwrap ( ) ;
program . add_module ( " core " , core_module , None ) . unwrap ( ) ;
let test_cases = vec! [
( 9 , false ) ,
( 10 , false ) ,
( 11 , true ) ,
] ;
for test_case in test_cases {
let ( import_initial , is_error ) = test_case ;
let client_module = module ( )
. with_import ( ImportEntry ::new ( " core " . into ( ) , " memory " . into ( ) , External ::Memory ( MemoryType ::new ( import_initial , None ) ) ) )
. build ( ) ;
match program . add_module ( " client " , client_module , None ) . map ( | _ | ( ) ) {
Ok ( _ ) if ! is_error = > ( ) ,
Err ( Error ::Validation ( ref actual_error ) )
if is_error & & actual_error = = & format! ( " trying to import memory with initial=10 and import.initial= {} " , import_initial ) = > ( ) ,
x @ _ = > panic! ( " unexpected result for test_case {:?} : {:?} " , test_case , x ) ,
}
}
}
#[ test ]
fn memory_import_limits_maximum ( ) {
#[ derive(Debug, Clone, Copy, PartialEq) ]
2017-09-04 12:25:23 +03:00
enum MaximumError { ValueMismatch , Ok } ;
2017-09-04 12:00:01 +03:00
let test_cases = vec! [
2017-09-04 12:25:23 +03:00
( None , Some ( 100 ) , MaximumError ::Ok ) ,
( Some ( 100 ) , None , MaximumError ::Ok ) ,
2017-09-04 12:00:01 +03:00
( Some ( 100 ) , Some ( 98 ) , MaximumError ::ValueMismatch ) ,
( Some ( 100 ) , Some ( 100 ) , MaximumError ::Ok ) ,
( Some ( 100 ) , Some ( 101 ) , MaximumError ::Ok ) ,
( None , None , MaximumError ::Ok ) ,
] ;
let program = DefaultProgramInstance ::new ( ) . unwrap ( ) ;
for test_case in test_cases {
let ( core_maximum , client_maximum , expected_err ) = test_case ;
let core_module = module ( )
. memory ( ) . with_min ( 10 ) . with_max ( core_maximum ) . build ( )
. with_export ( ExportEntry ::new ( " memory " . into ( ) , Internal ::Memory ( 0 ) ) )
. build ( ) ;
let client_module = module ( )
. with_import ( ImportEntry ::new ( " core " . into ( ) , " memory " . into ( ) , External ::Memory ( MemoryType ::new ( 10 , client_maximum ) ) ) )
. build ( ) ;
program . add_module ( " core " , core_module , None ) . unwrap ( ) ;
match program . add_module ( " client " , client_module , None ) . map ( | _ | ( ) ) {
Err ( Error ::Validation ( actual_err ) ) = > match expected_err {
MaximumError ::ValueMismatch
if actual_err = = format! ( " trying to import memory with maximum= {} and import.maximum= {} " , core_maximum . unwrap_or_default ( ) , client_maximum . unwrap_or_default ( ) ) = > ( ) ,
_ = > panic! ( " unexpected validation error for test_case {:?} : {} " , test_case , actual_err ) ,
} ,
Ok ( _ ) if expected_err = = MaximumError ::Ok = > ( ) ,
x @ _ = > panic! ( " unexpected result for test_case {:?} : {:?} " , test_case , x ) ,
}
}
}
#[ test ]
fn table_import_limits_initial ( ) {
let core_module = module ( )
. table ( ) . with_min ( 10 ) . build ( )
. with_export ( ExportEntry ::new ( " table " . into ( ) , Internal ::Table ( 0 ) ) )
. build ( ) ;
let program = DefaultProgramInstance ::new ( ) . unwrap ( ) ;
program . add_module ( " core " , core_module , None ) . unwrap ( ) ;
let test_cases = vec! [
( 9 , false ) ,
( 10 , false ) ,
( 11 , true ) ,
] ;
for test_case in test_cases {
let ( import_initial , is_error ) = test_case ;
let client_module = module ( )
. with_import ( ImportEntry ::new ( " core " . into ( ) , " table " . into ( ) , External ::Table ( TableType ::new ( import_initial , None ) ) ) )
. build ( ) ;
match program . add_module ( " client " , client_module , None ) . map ( | _ | ( ) ) {
Ok ( _ ) if ! is_error = > ( ) ,
Err ( Error ::Validation ( ref actual_error ) )
if is_error & & actual_error = = & format! ( " trying to import table with initial=10 and import.initial= {} " , import_initial ) = > ( ) ,
x @ _ = > panic! ( " unexpected result for test_case {:?} : {:?} " , test_case , x ) ,
}
}
}
#[ test ]
fn table_import_limits_maximum ( ) {
#[ derive(Debug, Clone, Copy, PartialEq) ]
2017-09-04 12:25:23 +03:00
enum MaximumError { ValueMismatch , Ok } ;
2017-09-04 12:00:01 +03:00
let test_cases = vec! [
2017-09-04 12:25:23 +03:00
( None , Some ( 100 ) , MaximumError ::Ok ) ,
( Some ( 100 ) , None , MaximumError ::Ok ) ,
2017-09-04 12:00:01 +03:00
( Some ( 100 ) , Some ( 98 ) , MaximumError ::ValueMismatch ) ,
( Some ( 100 ) , Some ( 100 ) , MaximumError ::Ok ) ,
( Some ( 100 ) , Some ( 101 ) , MaximumError ::Ok ) ,
( None , None , MaximumError ::Ok ) ,
] ;
let program = DefaultProgramInstance ::new ( ) . unwrap ( ) ;
for test_case in test_cases {
let ( core_maximum , client_maximum , expected_err ) = test_case ;
let core_module = module ( )
. table ( ) . with_min ( 10 ) . with_max ( core_maximum ) . build ( )
. with_export ( ExportEntry ::new ( " table " . into ( ) , Internal ::Table ( 0 ) ) )
. build ( ) ;
let client_module = module ( )
. with_import ( ImportEntry ::new ( " core " . into ( ) , " table " . into ( ) , External ::Table ( TableType ::new ( 10 , client_maximum ) ) ) )
. build ( ) ;
program . add_module ( " core " , core_module , None ) . unwrap ( ) ;
match program . add_module ( " client " , client_module , None ) . map ( | _ | ( ) ) {
Err ( Error ::Validation ( actual_err ) ) = > match expected_err {
MaximumError ::ValueMismatch
if actual_err = = format! ( " trying to import table with maximum= {} and import.maximum= {} " , core_maximum . unwrap_or_default ( ) , client_maximum . unwrap_or_default ( ) ) = > ( ) ,
_ = > panic! ( " unexpected validation error for test_case {:?} : {} " , test_case , actual_err ) ,
} ,
Ok ( _ ) if expected_err = = MaximumError ::Ok = > ( ) ,
x @ _ = > panic! ( " unexpected result for test_case {:?} : {:?} " , test_case , x ) ,
}
}
}