10#include <sysio/vm/backend.hpp>
91template<
typename Host>
97 auto from_wasm(
void* ptr)
const -> std::enable_if_t<std::is_pointer_v<T>,
T> {
98 return static_cast<T>(ptr);
101 auto from_wasm(
void* ptr)
const -> std::enable_if_t<std::is_lvalue_reference_v<T>,
T> {
102 return *
static_cast<std::remove_reference_t<T>*
>(ptr);
105 auto to_wasm(
T*&& ptr) ->
const volatile void* {
109 auto to_wasm(
T& ref) ->
const volatile void* {
117 ref(
T& arg) : val(&arg) {}
118 operator T&() {
return *val; }
123using maybe_ref = std::conditional_t<std::is_reference_v<T>, ref<std::remove_reference_t<T>>,
T>;
126maybe_ref<T> global_test_value;
128struct static_host_function {
130 static void put(
T t) { global_test_value<T> = t; }
132 static T get() {
return global_test_value<T>; }
135struct member_host_function {
137 void put(
T t) { global_test_value<T> = t; }
139 T get()
const {
return global_test_value<T>; }
150template<
class Functions,
class Host,
class Impl>
180 template<
typename...
A>
182 if constexpr (std::is_same_v<Host, std::nullptr_t>) {
188 template<
typename...
A>
190 if constexpr (std::is_same_v<Host, std::nullptr_t>) {
205const std::vector<std::string>
fun_prefixes = {
"",
"call.",
"call_indirect." };
208std::vector<T>
test_values = { 0, 1, std::numeric_limits<T>::min(), std::numeric_limits<T>::max() };
214 static int counter = 4;
218template<
typename T,
typename B>
221 fun +=
"put_" +
name;
229template<
typename T,
typename B>
232 fun +=
"put_" +
name;
240template<
typename T,
typename B>
243 fun +=
"put_" +
name;
251template<
typename T,
typename B,
typename F>
254 fun +=
"get_" +
name;
256 global_test_value<T> =
value;
262template<
typename T,
typename B>
265 fun +=
"get_" +
name;
267 global_test_value<T> =
const_cast<T>(
bkend.
get_context().linear_memory() + offset);
272template<
typename T,
typename B>
275 fun +=
"get_" +
name;
277 global_test_value<T> =
const_cast<T>(*(
bkend.
get_context().linear_memory() + offset));
282template<
class Backend>
287 CHECK(global_test_value<bool> ==
true);
289 CHECK(global_test_value<bool> ==
false);
292 CHECK(global_test_value<bool> ==
true);
294 CHECK(global_test_value<bool> ==
true);
315 member_host_function mhf;
319template<
class Backend>
321 for(
auto fun : {
"call.get_b",
"call_indirect.get_b"}) {
322 global_test_value<bool> =
false;
324 global_test_value<bool> =
true;
346 member_host_function mhf;
420 using type_converter::type_converter;
424 -> std::enable_if_t<std::is_same_v<T, has_stateful_conversion>,
452#warning TODO figure out a way to make this work with the new host function system
456struct has_multi_converter {
460static std::vector<int> multi_converter_destructor_order;
461struct multi_converter {
464 operator has_multi_converter()
const {
return { v1, v2 }; }
465 ~multi_converter() { multi_converter_destructor_order.push_back(v1); }
466 multi_converter(multi_converter&&) =
delete;
469struct host_functions_multi_converter {
470 static unsigned test(has_multi_converter x, has_multi_converter
y) {
471 return 1*x.v1 + 10*x.v2 + 100*
y.v1 + 1000*
y.v2;
476 using type_converter::type_converter;
480 -> std::enable_if_t<std::is_same_v<T, has_multi_converter>,
487 host_functions_multi_converter
host;
500 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x09, 0x01, 0x60,
501 0x04, 0x7f, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, 0x02, 0x0d, 0x01, 0x04, 0x68,
502 0x6f, 0x73, 0x74, 0x04, 0x74, 0x65, 0x73, 0x74, 0x00, 0x00, 0x07, 0x08,
503 0x01, 0x04, 0x74, 0x65, 0x73, 0x74, 0x00, 0x00
507 multi_converter_destructor_order.clear();
509 CHECK(multi_converter_destructor_order == std::vector{1, 3});
534template<
typename Impl>
542 rhf_t::template add<&host_functions_exit<TestType>::test>(
"host",
"test");
543 rhf_t::template add<&host_functions_exit<TestType>::test>(
"host",
"test2");
bool call(host_t *host, uint32_t func_index, Args... args)
auto call_with_return(host_t &host, const std::string_view &mod, const std::string_view &func, Args... args)
backend_t bkend(hello_wasm, ehm, &wa)
void check_put(B &bkend, const std::string &name)
void check_get_ptr(B &bkend, const std::string &name)
void check_put_ref(B &bkend, const std::string &name)
void c_style_host_function_0()
const std::vector< std::string > fun_prefixes
void c_style_host_function_4(const state_t &ss)
std::vector< T > test_values
wasm_code host_functions_tests_1_code
void test_parameters(Backend &&bkend)
std::vector< bool > test_values< bool >
void c_style_host_function_3(int a, float b)
void check_get(B &bkend, const std::string &name, F getter)
void test_results(Backend &&bkend)
void check_get_ref(B &bkend, const std::string &name)
void c_style_host_function_1(int s)
int c_style_host_function_state
void c_style_host_function_2(int a, int b)
void check_put_ptr(B &bkend, const std::string &name)
std::vector< uint8_t > host_functions_test_0_wasm
unsigned char host_functions_tests_1_wasm[]
#define CHECK_THROWS_AS(expr, exceptionType)
basic_type_converter< sysio::vm::execution_interface > type_converter
std::vector< uint8_t > wasm_code
std::vector< uint8_t > read_wasm(const std::string &fname)
@ test
Unit testing utility error code.
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
#define T(meth, val, expected)
schedule config_dir_name data_dir_name p2p_port http_port file_size name host(p2p_endpoint)) FC_REFLECT(tn_node_def
unsigned __int64 uint64_t
auto from_wasm(wasm_ptr_t ptr, wasm_size_t len, tag< T >={}) const -> std::enable_if_t< is_span_type_v< T >, T >
Impl::template context< registered_host_functions< host_functions_exit > > * context
static int test(has_stateful_conversion x)
static int test2(has_stateful_conversion x)
decltype(auto) get_context()
static void init_host_functions()
auto call_with_return(A &&... a)
static void add(const std::string &name)
static int test2(int value)
static int test(int value)
auto from_wasm(uint32_t val) const -> std::enable_if_t< std::is_same_v< T, has_stateful_conversion >, stateful_conversion >
auto from_wasm(vm::wasm_ptr_t ptr) const -> std::enable_if_t< std::is_pointer_v< T >, vm::argument_proxy< T > >
Immutable except for fc::from_variant.
static void add(const std::string &mod, const std::string &name)
static void resolve(Module &mod)
uint32_t to_wasm(bool &&value)
auto from_wasm(wasm_ptr_t ptr, wasm_size_t len, tag< T >={}) const -> std::enable_if_t< is_span_type_v< T >, T >
#define BACKEND_TEST_CASE(name, tags)