From 145e5c18c680e0da0e3240edbb83f77e2c001193 Mon Sep 17 00:00:00 2001 From: rxbryan Date: Wed, 15 Feb 2023 20:32:39 +0100 Subject: [PATCH] add test for node_loader class --- .../node_loader/source/node_loader_impl.cpp | 146 ++++++++----- source/scripts/node/test/CMakeLists.txt | 5 + source/scripts/node/test/source/test.js | 67 ++++++ source/tests/CMakeLists.txt | 1 + .../metacall-node-class-test/CMakeLists.txt | 154 ++++++++++++++ .../metacall-node-class-test/source/main.cpp | 28 +++ .../source/metacall_node_class_test.cpp | 201 ++++++++++++++++++ 7 files changed, 551 insertions(+), 51 deletions(-) create mode 100644 source/scripts/node/test/CMakeLists.txt create mode 100644 source/scripts/node/test/source/test.js create mode 100644 source/tests/metacall-node-class-test/CMakeLists.txt create mode 100644 source/tests/metacall-node-class-test/source/main.cpp create mode 100644 source/tests/metacall-node-class-test/source/metacall_node_class_test.cpp diff --git a/source/loaders/node_loader/source/node_loader_impl.cpp b/source/loaders/node_loader/source/node_loader_impl.cpp index 1b8029fd5..f796358f0 100644 --- a/source/loaders/node_loader/source/node_loader_impl.cpp +++ b/source/loaders/node_loader/source/node_loader_impl.cpp @@ -1054,16 +1054,16 @@ static napi_value node_loader_impl_class_constructor_callback(napi_env env, napi loader_impl_async_safe_cast closure_cast = { NULL }; napi_get_cb_info(env, info, NULL, NULL, NULL, &closure_cast.ptr); + /* Set environment */ closure_cast.safe->node_impl->env = env; - constructor ctor = class_default_constructor(closure_cast.safe->cls); char *klass_name_str = const_cast(class_name(closure_cast.safe->cls)); - std::string error_msg = "NodeJS Loader No default constructor in class: "; - error_msg += klass_name_str; + + constructor ctor = class_default_constructor(closure_cast.safe->cls); if (ctor == NULL) { - napi_throw_error(env, NULL, error_msg.c_str()); + log_write("metacall", LOG_LEVEL_INFO, "NodeJS Loader No default constructor in class: ", klass_name_str); } size_t argc = constructor_count(ctor); @@ -1083,13 +1083,13 @@ static napi_value node_loader_impl_class_constructor_callback(napi_env env, napi ctor = class_constructor(closure_cast.safe->cls, ids, argc); //convert class_name to lower case - while (*klass_name_str != '\0') + std::string obj_name(klass_name_str); + for (size_t i = 0; i < obj_name.size(); i++) { - *klass_name_str = std::tolower(*klass_name_str); - klass_name_str++; + obj_name[i] = std::tolower(obj_name[i]); } - object o = class_new(closure_cast.safe->cls, klass_name_str, ctor, args, argc); + object o = class_new(closure_cast.safe->cls, obj_name.c_str(), ctor, args, argc); if (ids != NULL) { @@ -1106,7 +1106,7 @@ static napi_value node_loader_impl_class_constructor_callback(napi_env env, napi if (v == NULL) { object_destroy(o); - error_msg = "NodeJS Loader Failed to create object for class: "; + std::string error_msg = "NodeJS Loader Failed to create object for class: "; error_msg += klass_name_str; napi_throw_error(env, NULL, error_msg.c_str()); } @@ -4474,7 +4474,7 @@ static value node_loader_impl_discover_object_safe(napi_env env, loader_impl_dis void node_loader_impl_discover_safe(napi_env env, loader_impl_async_discover_safe discover_safe) { static const char discover_str[] = "discover"; - napi_value function_table_object; + napi_value discover_table_object; napi_value discover_str_value; bool result = false; napi_handle_scope handle_scope; @@ -4485,7 +4485,7 @@ void node_loader_impl_discover_safe(napi_env env, loader_impl_async_discover_saf node_loader_impl_exception(env, status); /* Get function table object from reference */ - status = napi_get_reference_value(env, discover_safe->node_impl->function_table_object_ref, &function_table_object); + status = napi_get_reference_value(env, discover_safe->node_impl->function_table_object_ref, &discover_table_object); node_loader_impl_exception(env, status); @@ -4495,21 +4495,21 @@ void node_loader_impl_discover_safe(napi_env env, loader_impl_async_discover_saf node_loader_impl_exception(env, status); /* Check if exists in the table */ - status = napi_has_own_property(env, function_table_object, discover_str_value, &result); + status = napi_has_own_property(env, discover_table_object, discover_str_value, &result); node_loader_impl_exception(env, status); if (result == true) { - napi_value function_trampoline_discover; + napi_value trampoline_discover; napi_valuetype valuetype; napi_value argv[1]; - status = napi_get_named_property(env, function_table_object, discover_str, &function_trampoline_discover); + status = napi_get_named_property(env, discover_table_object, discover_str, &trampoline_discover); node_loader_impl_exception(env, status); - status = napi_typeof(env, function_trampoline_discover, &valuetype); + status = napi_typeof(env, trampoline_discover, &valuetype); node_loader_impl_exception(env, status); @@ -4530,72 +4530,79 @@ void node_loader_impl_discover_safe(napi_env env, loader_impl_async_discover_saf node_loader_impl_exception(env, status); - status = napi_call_function(env, global, function_trampoline_discover, 1, argv, &discover_map); + status = napi_call_function(env, global, trampoline_discover, 1, argv, &discover_map); node_loader_impl_exception(env, status); /* Convert return value (discover object) to context */ - napi_value func_names; - uint32_t func_names_length; + napi_value prop_names; + uint32_t prop_names_length; - status = napi_get_property_names(env, discover_map, &func_names); + status = napi_get_property_names(env, discover_map, &prop_names); node_loader_impl_exception(env, status); - status = napi_get_array_length(env, func_names, &func_names_length); + status = napi_get_array_length(env, prop_names, &prop_names_length); node_loader_impl_exception(env, status); - for (uint32_t index = 0; index < func_names_length; ++index) + for (uint32_t index = 0; index < prop_names_length; ++index) { - napi_value func_name; - size_t func_name_length; - char *func_name_str = NULL; + napi_value prop_name; + size_t prop_name_length; + char *prop_name_str = NULL; - status = napi_get_element(env, func_names, index, &func_name); + status = napi_get_element(env, prop_names, index, &prop_name); node_loader_impl_exception(env, status); - status = napi_get_value_string_utf8(env, func_name, NULL, 0, &func_name_length); + status = napi_get_value_string_utf8(env, prop_name, NULL, 0, &prop_name_length); node_loader_impl_exception(env, status); - if (func_name_length > 0) + if (prop_name_length > 0) { - func_name_str = static_cast(malloc(sizeof(char) * (func_name_length + 1))); + prop_name_str = static_cast(malloc(sizeof(char) * (prop_name_length + 1))); } - if (func_name_str != NULL) + if (prop_name_str != NULL) { - napi_value function_descriptor; - napi_value function_ptr; - napi_value function_sig; - napi_value function_types = nullptr; - napi_value function_ret = nullptr; - napi_value function_is_async; - uint32_t function_sig_length; + napi_value property_descriptor; - /* Get function name */ - status = napi_get_value_string_utf8(env, func_name, func_name_str, func_name_length + 1, &func_name_length); + /* Get property name */ + status = napi_get_value_string_utf8(env, prop_name, prop_name_str, prop_name_length + 1, &prop_name_length); node_loader_impl_exception(env, status); - /* Get function descriptor */ - status = napi_get_named_property(env, discover_map, func_name_str, &function_descriptor); + /* Get property descriptor */ + status = napi_get_named_property(env, discover_map, prop_name_str, &property_descriptor); node_loader_impl_exception(env, status); - /* Check if function pointer exists */ bool is_func = false; - status = napi_has_named_property(env, function_descriptor, "func", &is_func); + status = napi_has_named_property(env, property_descriptor, "func", &is_func); + + node_loader_impl_exception(env, status); + + bool is_klass = false; + + status = napi_has_named_property(env, property_descriptor, "klass", &is_klass); node_loader_impl_exception(env, status); + /* Check if a function pointer exists */ if (is_func == true) { + napi_value function_ptr; + napi_value function_sig; + napi_value function_types = nullptr; + napi_value function_ret = nullptr; + napi_value function_is_async; + uint32_t function_sig_length; + /* Get function pointer */ - status = napi_get_named_property(env, function_descriptor, "func", &function_ptr); + status = napi_get_named_property(env, property_descriptor, "func", &function_ptr); node_loader_impl_exception(env, status); @@ -4610,7 +4617,7 @@ void node_loader_impl_discover_safe(napi_env env, loader_impl_async_discover_saf } /* Get function signature */ - status = napi_get_named_property(env, function_descriptor, "signature", &function_sig); + status = napi_get_named_property(env, property_descriptor, "signature", &function_sig); node_loader_impl_exception(env, status); @@ -4630,7 +4637,7 @@ void node_loader_impl_discover_safe(napi_env env, loader_impl_async_discover_saf node_loader_impl_exception(env, status); /* Get function async */ - status = napi_get_named_property(env, function_descriptor, "async", &function_is_async); + status = napi_get_named_property(env, property_descriptor, "async", &function_is_async); node_loader_impl_exception(env, status); @@ -4648,13 +4655,13 @@ void node_loader_impl_discover_safe(napi_env env, loader_impl_async_discover_saf static const char types_str[] = "types"; bool has_types = false; - status = napi_has_named_property(env, function_descriptor, types_str, &has_types); + status = napi_has_named_property(env, property_descriptor, types_str, &has_types); node_loader_impl_exception(env, status); if (has_types == true) { - status = napi_get_named_property(env, function_descriptor, types_str, &function_types); + status = napi_get_named_property(env, property_descriptor, types_str, &function_types); node_loader_impl_exception(env, status); @@ -4673,13 +4680,13 @@ void node_loader_impl_discover_safe(napi_env env, loader_impl_async_discover_saf static const char ret_str[] = "ret"; bool has_ret = false; - status = napi_has_named_property(env, function_descriptor, ret_str, &has_ret); + status = napi_has_named_property(env, property_descriptor, ret_str, &has_ret); node_loader_impl_exception(env, status); if (has_ret == true) { - status = napi_get_named_property(env, function_descriptor, ret_str, &function_ret); + status = napi_get_named_property(env, property_descriptor, ret_str, &function_ret); node_loader_impl_exception(env, status); @@ -4706,7 +4713,7 @@ void node_loader_impl_discover_safe(napi_env env, loader_impl_async_discover_saf node_func->impl = discover_safe->node_impl->impl; /* Create function */ - function f = function_create(func_name_str, (size_t)function_sig_length, node_func, &function_node_singleton); + function f = function_create(prop_name_str, (size_t)function_sig_length, node_func, &function_node_singleton); if (f != NULL) { @@ -4838,8 +4845,45 @@ void node_loader_impl_discover_safe(napi_env env, loader_impl_async_discover_saf break; } } + else if (is_klass == true) + { + napi_value klass_ptr; + + /* Get klass pointer */ + status = napi_get_named_property(env, property_descriptor, "klass", &klass_ptr); + + node_loader_impl_exception(env, status); + + /* Check klass pointer type */ + status = napi_typeof(env, klass_ptr, &valuetype); + + node_loader_impl_exception(env, status); + + if (valuetype != napi_function) + { + napi_throw_type_error(env, nullptr, "Invalid NodeJS class"); + } + + struct loader_impl_discover_klass_safe_type discover_klass_safe = { + discover_safe->node_impl, + klass_ptr + }; + + value v = node_loader_impl_discover_klass_safe(env, &discover_klass_safe); + + if (v != NULL) + { + scope sp = context_scope(discover_safe->ctx); + if (scope_define(sp, class_name((klass)metacall_value_to_class(v)), v) != 0) + { + value_type_destroy(v); + discover_safe->result = 1; + break; + } + } + } - free(func_name_str); + free(prop_name_str); } } } diff --git a/source/scripts/node/test/CMakeLists.txt b/source/scripts/node/test/CMakeLists.txt new file mode 100644 index 000000000..738a820a1 --- /dev/null +++ b/source/scripts/node/test/CMakeLists.txt @@ -0,0 +1,5 @@ +# +# Configure nodejs project +# + +nodejs_project(test 0.1.0) diff --git a/source/scripts/node/test/source/test.js b/source/scripts/node/test/source/test.js new file mode 100644 index 000000000..be90b4c65 --- /dev/null +++ b/source/scripts/node/test/source/test.js @@ -0,0 +1,67 @@ +class Fibonacci { + fib_impl(n) { + if (n <= 2) { + return 1; + } else { + return fib_impl(n - 2) + fib_impl(n - 1); + } + } + + static fib(n) { + console.log("Fibbonaci of " + n + " = " + fib_impl(n)); + } +} + +class Test { + + constructor (num, str, cls, cls_args) { + this.int = 231; + this.b = 100; + this.hello_str = "hello!"; + + this.arr = [ 'K', 'G', 50, 100, "Hello", "world"]; + this.num = num; + this.str = str; + this.cls = Fibonacci; + + // TODO: Add test for this + this.obj = new cls(...cls_args); + // END-TODO + + console.log("NodeJs Loader: Test constructor Called!"); + } + + newFibonacci() { + return new Fibonacci; + } + + return_class() { + return Fibonacci; + } + + return_new_obj() { + return this.obj.return_bye('LBryan'); + } + + print() { + console.log(this.str); + } + + // Static method with no parameter and void return type + static hello(s) { + console.log("hello, world! running on " + s); + return 10; + } + + static sumArray(i) { + sum = 0; + + for (let c of i) + sum += c; + + return sum; + } + +} + +module.exports = Test \ No newline at end of file diff --git a/source/tests/CMakeLists.txt b/source/tests/CMakeLists.txt index cc9002ef7..e35c1bf8b 100644 --- a/source/tests/CMakeLists.txt +++ b/source/tests/CMakeLists.txt @@ -239,3 +239,4 @@ add_subdirectory(metacall_plugin_extension_destroy_order_test) add_subdirectory(metacall_cli_core_plugin_test) add_subdirectory(metacall_cli_core_plugin_await_test) add_subdirectory(metacall_backtrace_plugin_test) +add_subdirectory(metacall-node-class-test) diff --git a/source/tests/metacall-node-class-test/CMakeLists.txt b/source/tests/metacall-node-class-test/CMakeLists.txt new file mode 100644 index 000000000..b4057c196 --- /dev/null +++ b/source/tests/metacall-node-class-test/CMakeLists.txt @@ -0,0 +1,154 @@ +# Check if this loader is enabled +if(NOT OPTION_BUILD_LOADERS OR NOT OPTION_BUILD_LOADERS_NODE) + return() +endif() + +# +# Executable name and options +# + +# Target name +set(target metacall-node-class-test) +message(STATUS "Test ${target}") + +# +# Compiler warnings +# + +include(Warnings) + +# +# Compiler security +# + +include(SecurityFlags) + +# +# Sources +# + +set(include_path "${CMAKE_CURRENT_SOURCE_DIR}/include/${target}") +set(source_path "${CMAKE_CURRENT_SOURCE_DIR}/source") + +set(sources + ${source_path}/main.cpp + ${source_path}/metacall_node_class_test.cpp +) + +# Group source files +set(header_group "Header Files (API)") +set(source_group "Source Files") +source_group_by_path(${include_path} "\\\\.h$|\\\\.hpp$" + ${header_group} ${headers}) +source_group_by_path(${source_path} "\\\\.cpp$|\\\\.c$|\\\\.h$|\\\\.hpp$" + ${source_group} ${sources}) + +# +# Create executable +# + +# Build executable +add_executable(${target} + ${sources} +) + +# Create namespaced alias +add_executable(${META_PROJECT_NAME}::${target} ALIAS ${target}) + +# +# Project options +# + +set_target_properties(${target} + PROPERTIES + ${DEFAULT_PROJECT_OPTIONS} + FOLDER "${IDE_FOLDER}" +) + +# +# Include directories +# + +target_include_directories(${target} + PRIVATE + ${DEFAULT_INCLUDE_DIRECTORIES} + ${PROJECT_BINARY_DIR}/source/include +) + +# +# Libraries +# + +target_link_libraries(${target} + PRIVATE + ${DEFAULT_LIBRARIES} + + GTest + + ${META_PROJECT_NAME}::metacall +) + +# +# Compile definitions +# + +target_compile_definitions(${target} + PRIVATE + ${DEFAULT_COMPILE_DEFINITIONS} +) + +# +# Compile options +# + +target_compile_options(${target} + PRIVATE + ${DEFAULT_COMPILE_OPTIONS} +) + +# +# Linker options +# + +target_link_libraries(${target} + PRIVATE + ${DEFAULT_LINKER_OPTIONS} +) + +# +# Define test +# + +add_test(NAME ${target} + COMMAND $ +) + +# +# Define dependencies +# + +add_dependencies(${target} + node_loader + py_loader +) + +# +# Define test properties +# + +set_property(TEST ${target} + PROPERTY LABELS ${target} +) + +if(OPTION_BUILD_SANITIZER) + set_tests_properties(${target} PROPERTIES + PASS_REGULAR_EXPRESSION "[ PASSED ]" + ) +endif() + +include(TestEnvironmentVariables) + +test_environment_variables(${target} + "" + ${TESTS_ENVIRONMENT_VARIABLES} +) diff --git a/source/tests/metacall-node-class-test/source/main.cpp b/source/tests/metacall-node-class-test/source/main.cpp new file mode 100644 index 000000000..4676e4763 --- /dev/null +++ b/source/tests/metacall-node-class-test/source/main.cpp @@ -0,0 +1,28 @@ +/* + * Loader Library by Parra Studios + * A plugin for loading ruby code at run-time into a process. + * + * Copyright (C) 2016 - 2022 Vicente Eduardo Ferrer Garcia + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +int main(int argc, char *argv[]) +{ + ::testing::InitGoogleTest(&argc, argv); + + return RUN_ALL_TESTS(); +} diff --git a/source/tests/metacall-node-class-test/source/metacall_node_class_test.cpp b/source/tests/metacall-node-class-test/source/metacall_node_class_test.cpp new file mode 100644 index 000000000..2dc81cc7a --- /dev/null +++ b/source/tests/metacall-node-class-test/source/metacall_node_class_test.cpp @@ -0,0 +1,201 @@ +/* + * MetaCall Library by Parra Studios + * A library for providing a foreign function interface calls. + * + * Copyright (C) 2016 - 2022 Vicente Eduardo Ferrer Garcia + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +class metacall_node_class_test : public testing::Test +{ +public: +}; + +TEST_F(metacall_node_class_test, DefaultConstructor) +{ + metacall_print_info(); + + ASSERT_EQ((int)0, (int)metacall_initialize()); + +/* Python */ +#if defined(OPTION_BUILD_LOADERS_PY) + { + const char *py_scripts[] = { + "scripts/classname.py" + }; + + EXPECT_EQ((int)0, (int)metacall_load_from_file("py", py_scripts, sizeof(py_scripts) / sizeof(py_scripts[0]), NULL)); + } +#endif /* OPTION_BUILD_LOADERS_PY */ + +/* Node */ +#if defined(OPTION_BUILD_LOADERS_NODE) + { + void *new_object_v = NULL; + { /* TEST LOAD FROM FILE */ + const char *node_scripts[] = { + "scripts/test.js" + }; + + static const char tag[] = "node"; + + ASSERT_EQ((int)0, (int)metacall_load_from_file(tag, node_scripts, sizeof(node_scripts) / sizeof(node_scripts[0]), NULL)); + } + + { /* TEST STATIC GET, SET AND INVOKE */ + void *myclass = metacall_class("Test"); + + void *pyclass_value = metacall("return_class_function"); + ASSERT_EQ((enum metacall_value_id)METACALL_CLASS, (enum metacall_value_id)metacall_value_id(pyclass_value)); + //void *pyclass = metacall_value_to_class(pyclass_value); + + static const char john[] = "John Doe"; + + const void *pyconstructor_params[] = { + metacall_value_create_string(john, sizeof(john) - 1), // param1 + metacall_value_create_int(999999) // param2 + }; + + void *constructor_params[] = { + metacall_value_create_int(10), + metacall_value_create_string("Test String", 11), + pyclass_value, + metacall_value_create_array(pyconstructor_params, sizeof(pyconstructor_params) / sizeof(pyconstructor_params[0])) + }; + + new_object_v = metacall_class_new(myclass, "test", constructor_params, sizeof(constructor_params) / sizeof(constructor_params[0])); + ASSERT_NE((void *)NULL, (void *)new_object_v); + + metacall_value_destroy(new_object_v); + + { //Invoke static method + + { + void *args[] = { + metacall_value_create_int(1), + metacall_value_create_int(2), + metacall_value_create_int(3), + metacall_value_create_int(4), + metacall_value_create_int(5), + metacall_value_create_int(6), + metacall_value_create_int(7), + metacall_value_create_int(8), + metacall_value_create_int(9), + metacall_value_create_int(10) + }; + + void *ret = metacallt_class(myclass, "hello", METACALL_INT, args, sizeof(args) / sizeof(args[0])); + ASSERT_EQ((long)55, (long)metacall_value_to_long(ret)); + + metacall_value_destroy(ret); + } + + { + void *args[] = { + metacall_value_create_string("Metacall", 8) + }; + + void *ret = metacallt_class(myclass, "sumArray", METACALL_INT, args, 1); + ASSERT_EQ((long)10, (long)metacall_value_to_long(ret)); + + metacall_value_destroy(ret); + } + } + } + + { /* TEST NON STATIC GET, SET and INVOKE FROM CLASS OBJECT */ + + void *new_object = metacall_value_to_object(new_object_v); + + { + void *param1 = metacall_object_get(new_object, "num"); + ASSERT_EQ((long)10, (long)metacall_value_to_long(param1)); + metacall_value_destroy(param1); + } + + { + void *param1 = metacall_object_get(new_object, "hello_str"); + ASSERT_EQ((std::string) "hello!", (std::string)metacall_value_to_string(param1)); + metacall_value_destroy(param1); + } + + { + void *long_value = metacall_value_create_long(124124L); + int retcode = metacall_object_set(new_object, "b", long_value); + metacall_value_destroy(long_value); + ASSERT_EQ((int)0, int(retcode)); + + void *param2 = metacall_object_get(new_object, "b"); + ASSERT_EQ((enum metacall_value_id)METACALL_LONG, (enum metacall_value_id)metacall_value_id(param2)); + ASSERT_EQ((long)124124L, (long)metacall_value_to_long(param2)); + + metacall_value_destroy(param2); + } + + //Non Static function Invoke + { + void *ret = metacallv_object(new_object, "print", metacall_null_args, 0); + EXPECT_NE((void *)NULL, (void *)ret); + + metacall_value_destroy(ret); + } + + { + void *Fibonacci = metacallv_object(new_object, "return_class", metacall_null_args, 0); + ASSERT_EQ((enum metacall_value_id)METACALL_CLASS, (enum metacall_value_id)metacall_value_id(Fibonacci)); + + metacall_value_destroy(Fibonacci); + } + + { + void *param1 = metacallv_object(new_object, "return_bye", metacall_null_args, 0); + ASSERT_EQ((std::string) "bye LBryan", (std::string)metacall_value_to_string(param1)); + metacall_value_destroy(param1); + } + + metacall_value_destroy(new_object_v); + } + } +#endif /* OPTION_BUILD_LOADERS_NODE */ + + /* Print inspect information */ + { + size_t size = 0; + + struct metacall_allocator_std_type std_ctx = { &std::malloc, &std::realloc, &std::free }; + + void *allocator = metacall_allocator_create(METACALL_ALLOCATOR_STD, (void *)&std_ctx); + + char *inspect_str = metacall_inspect(&size, allocator); + + EXPECT_NE((char *)NULL, (char *)inspect_str); + + EXPECT_GT((size_t)size, (size_t)0); + + std::cout << inspect_str << std::endl; + + metacall_allocator_free(allocator, inspect_str); + + metacall_allocator_destroy(allocator); + } + + EXPECT_EQ((int)0, (int)metacall_destroy()); +}