From 8302fe1ab1b05f3cd4e3caab169e9ac3f424da0a Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Tue, 30 Jan 2024 18:46:20 +0100 Subject: [PATCH] Add node intensive async test. --- source/tests/CMakeLists.txt | 1 + .../CMakeLists.txt | 147 ++++++++++++ .../source/main.cpp | 28 +++ .../metacall_node_async_multiple_test.cpp | 210 ++++++++++++++++++ 4 files changed, 386 insertions(+) create mode 100644 source/tests/metacall_node_async_multiple_test/CMakeLists.txt create mode 100644 source/tests/metacall_node_async_multiple_test/source/main.cpp create mode 100644 source/tests/metacall_node_async_multiple_test/source/metacall_node_async_multiple_test.cpp diff --git a/source/tests/CMakeLists.txt b/source/tests/CMakeLists.txt index 34502c1f7..275c81d76 100644 --- a/source/tests/CMakeLists.txt +++ b/source/tests/CMakeLists.txt @@ -130,6 +130,7 @@ add_subdirectory(metacall_node_event_loop_signal_test) add_subdirectory(metacall_node_call_test) add_subdirectory(metacall_node_inline_test) add_subdirectory(metacall_node_async_test) +add_subdirectory(metacall_node_async_multiple_test) add_subdirectory(metacall_node_reentrant_test) add_subdirectory(metacall_node_port_test) add_subdirectory(metacall_node_port_await_test) diff --git a/source/tests/metacall_node_async_multiple_test/CMakeLists.txt b/source/tests/metacall_node_async_multiple_test/CMakeLists.txt new file mode 100644 index 000000000..7fc6365c9 --- /dev/null +++ b/source/tests/metacall_node_async_multiple_test/CMakeLists.txt @@ -0,0 +1,147 @@ +# Check if this loader is enabled +if(NOT OPTION_BUILD_LOADERS OR NOT OPTION_BUILD_LOADERS_NODE OR NOT OPTION_BUILD_SCRIPTS OR NOT OPTION_BUILD_SCRIPTS_NODE) + return() +endif() + +# +# Executable name and options +# + +# Target name +set(target metacall-node-async-multiple-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_async_multiple_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 +) + +# +# Define test properties +# + +set_property(TEST ${target} + PROPERTY LABELS ${target} +) + +include(TestEnvironmentVariables) + +test_environment_variables(${target} + "" + ${TESTS_ENVIRONMENT_VARIABLES} +) diff --git a/source/tests/metacall_node_async_multiple_test/source/main.cpp b/source/tests/metacall_node_async_multiple_test/source/main.cpp new file mode 100644 index 000000000..11ddf3f59 --- /dev/null +++ b/source/tests/metacall_node_async_multiple_test/source/main.cpp @@ -0,0 +1,28 @@ +/* + * MetaCall Library by Parra Studios + * A library for providing a foreign function interface calls. + * + * Copyright (C) 2016 - 2024 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_async_multiple_test/source/metacall_node_async_multiple_test.cpp b/source/tests/metacall_node_async_multiple_test/source/metacall_node_async_multiple_test.cpp new file mode 100644 index 000000000..629b1c789 --- /dev/null +++ b/source/tests/metacall_node_async_multiple_test/source/metacall_node_async_multiple_test.cpp @@ -0,0 +1,210 @@ +/* + * MetaCall Library by Parra Studios + * A library for providing a foreign function interface calls. + * + * Copyright (C) 2016 - 2024 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 + +#include + +std::atomic success_callbacks{}; + +class metacall_node_async_multiple_test : public testing::Test +{ +public: +}; + +TEST_F(metacall_node_async_multiple_test, DefaultConstructor) +{ + const size_t iteration_size = 1000; + + struct async_context + { + int value; + } ctx = { + 234 + }; + + metacall_print_info(); + + ASSERT_EQ((int)0, (int)metacall_initialize()); + +/* NodeJS */ +#if defined(OPTION_BUILD_LOADERS_NODE) + { + const char buffer[] = + "const util = require('util');\n" + "const delay = ms => new Promise(resolve => setTimeout(resolve, ms))\n" + "async function f(x) {\n" + "\tawait delay(2000);\n" + "\treturn new Promise(r => console.log(`Promise f executed: ${util.inspect(r)} -> ${x}`) || r(x));\n" + "}\n" + "async function g(x) {\n" + "\tawait delay(2000);\n" + "\treturn new Promise((_, r) => console.log(`Promise g executed: ${util.inspect(r)} -> ${x}`) || r(x));\n" + "}\n" + "async function h() {\n" + "\tawait delay(2000);\n" + "\treturn new Promise((resolve) => resolve(34));\n" + "}\n" + "module.exports = { f, g, h };\n"; + + EXPECT_EQ((int)0, (int)metacall_load_from_memory("node", buffer, sizeof(buffer), NULL)); + + for (size_t i = 0; i < iteration_size; ++i) + { + void *args[] = { + metacall_value_create_double(10.0) + }; + + /* Test resolve */ + void *future = metacall_await( + "f", args, [](void *result, void *data) -> void * { + EXPECT_NE((void *) NULL, (void *) result); + + EXPECT_EQ((enum metacall_value_id) metacall_value_id(result), (enum metacall_value_id) METACALL_DOUBLE); + + EXPECT_EQ((double) 10.0, (double) metacall_value_to_double(result)); + + EXPECT_NE((void *) NULL, (void *) data); + + struct async_context * ctx = static_cast(data); + + EXPECT_EQ((int) 234, (int) ctx->value); + + printf("Resolve C Callback\n"); + + return metacall_value_create_double(15.0); }, [](void *, void *) -> void * { + int this_should_never_be_executed = 0; + + EXPECT_EQ((int) 1, (int) this_should_never_be_executed); + + printf("Reject C Callback\n"); + + return NULL; }, static_cast(&ctx)); + + EXPECT_NE((void *)NULL, (void *)future); + + EXPECT_EQ((enum metacall_value_id)metacall_value_id(future), (enum metacall_value_id)METACALL_FUTURE); + + metacall_value_destroy(future); + + /* Test reject */ + future = metacall_await( + "g", args, [](void *, void *) -> void * { + int this_should_never_be_executed = 0; + + EXPECT_EQ((int) 1, (int) this_should_never_be_executed); + + printf("Resolve C Callback\n"); + + return NULL; }, [](void *result, void *data) -> void * { + EXPECT_NE((void *) NULL, (void *) result); + + EXPECT_EQ((enum metacall_value_id) metacall_value_id(result), (enum metacall_value_id) METACALL_DOUBLE); + + EXPECT_EQ((double) 10.0, (double) metacall_value_to_double(result)); + + EXPECT_NE((void *) NULL, (void *) data); + + struct async_context * ctx = static_cast(data); + + EXPECT_EQ((int) 234, (int) ctx->value); + + printf("Reject C Callback\n"); + + ++success_callbacks; + + return metacall_value_create_double(15.0); }, static_cast(&ctx)); + + EXPECT_NE((void *)NULL, (void *)future); + + EXPECT_EQ((enum metacall_value_id)metacall_value_id(future), (enum metacall_value_id)METACALL_FUTURE); + + metacall_value_destroy(future); + + metacall_value_destroy(args[0]); + + /* Test future */ + future = metacall("h"); + + EXPECT_NE((void *)NULL, (void *)future); + + EXPECT_EQ((enum metacall_value_id)metacall_value_id(future), (enum metacall_value_id)METACALL_FUTURE); + + void *ret = metacall_await_future( + metacall_value_to_future(future), [](void *result, void *) -> void * { + EXPECT_NE((void *) NULL, (void *) result); + + EXPECT_EQ((enum metacall_value_id) metacall_value_id(result), (enum metacall_value_id) METACALL_DOUBLE); + + EXPECT_EQ((double) 34.0, (double) metacall_value_to_double(result)); + + ++success_callbacks; + + return metacall_value_create_double(155.0); }, [](void *, void *) -> void * { + int this_should_never_be_executed = 0; + + EXPECT_EQ((int) 1, (int) this_should_never_be_executed); + + return NULL; }, NULL); + + metacall_value_destroy(future); + + EXPECT_NE((void *)NULL, (void *)ret); + + EXPECT_EQ((enum metacall_value_id)metacall_value_id(ret), (enum metacall_value_id)METACALL_FUTURE); + + void *last = metacall_await_future( + metacall_value_to_future(ret), [](void *result, void *) -> void * { + EXPECT_NE((void *) NULL, (void *) result); + + EXPECT_EQ((enum metacall_value_id) metacall_value_id(result), (enum metacall_value_id) METACALL_DOUBLE); + + EXPECT_EQ((double) 155.0, (double) metacall_value_to_double(result)); + + ++success_callbacks; + + return NULL; }, [](void *, void *) -> void * { + int this_should_never_be_executed = 0; + + EXPECT_EQ((int) 1, (int) this_should_never_be_executed); + + return NULL; }, NULL); + + metacall_value_destroy(last); + + metacall_value_destroy(ret); + } + } +#endif /* OPTION_BUILD_LOADERS_NODE */ + + EXPECT_EQ((int)0, (int)metacall_destroy()); + +/* NodeJS */ +#if defined(OPTION_BUILD_LOADERS_NODE) + { + /* Total amount of successful callbacks must be 3 */ + EXPECT_EQ((int)success_callbacks, (int)(3 * iteration_size)); + } +#endif /* OPTION_BUILD_LOADERS_NODE */ +}