From 12e2dbea40e3914c5cabcd07324d1c239fe20513 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alf-Andr=C3=A9=20Walla?= Date: Sun, 14 Jan 2024 20:09:38 +0100 Subject: [PATCH] Add unit test for dynamic calls with arguments --- engine/scripts/src/gameplay.cpp | 39 ----------------------- engine/src/main.cpp | 55 --------------------------------- engine/src/script/script.hpp | 12 +++++++ programs/dynamic_calls.json | 7 ++--- tests/basic.cpp | 53 +++++++++++++++++++++++++++++++ 5 files changed, 68 insertions(+), 98 deletions(-) diff --git a/engine/scripts/src/gameplay.cpp b/engine/scripts/src/gameplay.cpp index 383176a..b9aa35c 100644 --- a/engine/scripts/src/gameplay.cpp +++ b/engine/scripts/src/gameplay.cpp @@ -45,32 +45,6 @@ static void inline_dyncall_handler() return_fast(); } -static void opaque_dyncall_args_x4() -{ - sys_empty(); - sys_testing123(4, 5, 6, 7.0f, 8.0f, 9.0f); - sys_empty(); - sys_testing123(4, 5, 6, 7.0f, 8.0f, 9.0f); - sys_empty(); - sys_testing123(4, 5, 6, 7.0f, 8.0f, 9.0f); - sys_empty(); - sys_testing123(4, 5, 6, 7.0f, 8.0f, 9.0f); - return_fast(); -} - -static void inline_dyncall_args_x4() -{ - isys_empty(); - isys_testing123(4, 5, 6, 7.0, 8.0, 9.0); - isys_empty(); - isys_testing123(4, 5, 6, 7.0, 8.0, 9.0); - isys_empty(); - isys_testing123(4, 5, 6, 7.0, 8.0, 9.0); - isys_empty(); - isys_testing123(4, 5, 6, 7.0, 8.0, 9.0); - return_fast(); -} - PUBLIC(void public_donothing()) { /* nothing */ @@ -101,8 +75,6 @@ PUBLIC(void benchmarks()) measure("Direct thread creation overhead", direct_thread_function); measure("Dynamic call handler x4 (inline)", inline_dyncall_handler); measure("Dynamic call handler x4 (call)", opaque_dyncall_handler); - measure("Dynamic call args x8 (inline)", inline_dyncall_args_x4); - measure("Dynamic call args x8 (call)", opaque_dyncall_args_x4); //benchmark_multiprocessing(); } @@ -140,14 +112,3 @@ PUBLIC(void myobject_death(GameObject& object)) /* SFX: Ugh... */ object.alive = false; } - -PUBLIC(void test_dynamic_functions()) -{ - // See: dynamic_calls.json - // 1: A simple no-argument dynamic call - sys_testing(); - // 2: A dynamic call that takes a zero-terminated string, and then a string with length - sys_testing_strings("Hello World!", "Hello World!", 12); - // 3: A dynamic call that takes a few integers and floats - sys_testing123(4, 5, 6, 7.0, 8.0, 9.0); -} diff --git a/engine/src/main.cpp b/engine/src/main.cpp index 0548fa0..ba0189f 100644 --- a/engine/src/main.cpp +++ b/engine/src/main.cpp @@ -155,47 +155,6 @@ int main() strf::to(stdout)("...\n"); - /* Verify dynamic functions are working */ - int called = 0x0; - gameplay.set_dynamic_call( - "void sys_testing ()", - [&](auto&) - { - called |= 0x1; - }); - gameplay.set_dynamic_call( - "void sys_testing_strings (const char*, const char*, size_t)", - [&](auto& s) - { - // Argument 1: A heap-allocated string - // Argument 2: A string-view pointing into guest memory - const auto [str, view] - = s.machine().template sysargs(); - if (str == "Hello World!" && view == "Hello World!") - { - called |= 0x2; - } - }); - gameplay.set_dynamic_call( - "void sys_testing123 (int, int, int, float, float, float)", - [&](auto& s) - { - const auto [arg1, arg2, arg3, arg4, arg5, arg6] - = s.machine().template sysargs(); - if (arg1 == 4 && arg2 == 5 && arg3 == 6 && arg4 == 7.0 && arg5 == 8.0 && arg6 == 9.0) - { - called |= 0x4; - } - }); - gameplay.call("test_dynamic_functions"); - // All the functions should have been called - if (called != (0x1 | 0x2 | 0x4)) { - strf::to(stderr)( - "Error: Dynamic calls not invoked or did not set locals!?\n"); - exit(1); - } - - strf::to(stdout)("* Dynamic call tests passed!\n"); if (Script::get_global_setting("benchmarks").value_or(false)) { @@ -204,20 +163,6 @@ int main() // Benchmarks of various features gameplay.call("benchmarks"); - - // Fork benchmarks - strf::to(stdout)("Benchmarking RISC-V machine fork:\n"); - Script::benchmark( - [&gameplay] - { - // Forking the underlying virtual machine - const riscv::MachineOptions options { - .memory_max = 16ULL << 20, - .stack_size = 2ULL << 20, - .use_memory_arena = true - }; - riscv::Machine fork { gameplay.machine(), options }; - }); } strf::to(stdout)("...\nBringing up the main screen!\n"); diff --git a/engine/src/script/script.hpp b/engine/src/script/script.hpp index 29be4ce..e2d9a33 100644 --- a/engine/src/script/script.hpp +++ b/engine/src/script/script.hpp @@ -106,6 +106,12 @@ struct Script void dynamic_call_hash(uint32_t hash, gaddr_t strname); void dynamic_call_array(uint32_t idx); + /// @brief Retrieve arguments passed to a dynamic call, specifying each type. + /// @tparam ...Args The types of arguments to retrieve. + /// @return A tuple of arguments. + template + auto args() const; + auto& dynargs() { return m_arguments; @@ -383,6 +389,12 @@ inline void Script::resume(uint64_t cycles) } } +template +inline auto Script::args() const +{ + return machine().sysargs (); +} + /** * This uses RAII to sequentially allocate a range * for the objects, which is freed on destruction. diff --git a/programs/dynamic_calls.json b/programs/dynamic_calls.json index cbbc986..340ad62 100644 --- a/programs/dynamic_calls.json +++ b/programs/dynamic_calls.json @@ -17,8 +17,7 @@ "GUI::widget_set_pos": "void sys_gui_widget_set_pos (unsigned, int, int)", "GUI::widget_callback": "void sys_gui_widget_callback (unsigned, gui_callback, void *, size_t)", - "empty": "void sys_empty ()", - "testing": "void sys_testing ()", - "testing_strings": "void sys_testing_strings (const char*, const char*, size_t)", - "testing123": "void sys_testing123 (int, int, int, float, float, float)" + "empty": "void sys_empty ()", + "test_string": "void sys_test_strings (const char*, const char*, size_t)", + "test_3i_3f": "void sys_test_3i3f (int, int, int, float, float, float)" } diff --git a/tests/basic.cpp b/tests/basic.cpp index 9191283..fe03c9d 100644 --- a/tests/basic.cpp +++ b/tests/basic.cpp @@ -101,3 +101,56 @@ TEST_CASE("Verify late dynamic calls work", "[Basic]") REQUIRE(ret == 666); REQUIRE(count == 2); } + +TEST_CASE("Verify dynamic calls with arguments", "[Basic]") +{ + const auto program = build_and_load(R"M( + #include + + extern "C" void test_strings() { + sys_test_strings("1234", "45678", 5); + } + extern "C" void test_args() { + sys_test_3i3f(123, 456, 789, 10.0f, 100.0f, 1000.0f); + } + + int main() { + })M"); + + int strings_called = 0; + int args_called = 0; + + Script::set_dynamic_call("void sys_test_strings (const char*, const char*, size_t)", + [&] (Script& script) { + auto [str, view] = script.args (); + REQUIRE(str == "1234"); + REQUIRE(view == "45678"); + strings_called += 1; + }); + Script::set_dynamic_call("void sys_test_3i3f (int, int, int, float, float, float)", + [&] (Script& script) { + auto [i1, i2, i3, f1, f2, f3] = script.args (); + REQUIRE(i1 == 123); + REQUIRE(i2 == 456); + REQUIRE(i3 == 789); + REQUIRE(f1 == 10.0f); + REQUIRE(f2 == 100.0f); + REQUIRE(f3 == 1000.0f); + args_called += 1; + }); + + Script script {program, "MyScript", "/tmp/myscript"}; + + REQUIRE(strings_called == 0); + REQUIRE(args_called == 0); + + script.call("test_strings"); + + REQUIRE(strings_called == 1); + REQUIRE(args_called == 0); + + script.call("test_args"); + + REQUIRE(strings_called == 1); + REQUIRE(args_called == 1); +}