diff options
author | 2020-11-15 03:53:47 +1100 | |
---|---|---|
committer | 2020-11-15 03:53:47 +1100 | |
commit | 55b8ca317ab1f77850f498c1523355e1f5dd8d03 (patch) | |
tree | bada7948236b18684609f47024cc9ca227a5ef89 /3rdparty/sol2/test_functions.cpp | |
parent | 4db7f0439c3b841eb07d2320e39be38269e6cd56 (diff) |
-Switch to building MAME as C++17.
* Updated sol2 to 3.2.2
* Updated pugixml to 1.10
* Increased minimum clang version to 6
* Cleaned up some stuff that can use new features
Diffstat (limited to '3rdparty/sol2/test_functions.cpp')
-rw-r--r-- | 3rdparty/sol2/test_functions.cpp | 1066 |
1 files changed, 0 insertions, 1066 deletions
diff --git a/3rdparty/sol2/test_functions.cpp b/3rdparty/sol2/test_functions.cpp deleted file mode 100644 index f47a08dc6e1..00000000000 --- a/3rdparty/sol2/test_functions.cpp +++ /dev/null @@ -1,1066 +0,0 @@ -#define SOL_CHECK_ARGUMENTS - -#include <catch.hpp> -#include <sol.hpp> -#include <iostream> -#include "test_stack_guard.hpp" - -std::function<int()> makefn() { - auto fx = []() -> int { - return 0x1456789; - }; - return fx; -} - -template <typename T> -T va_func(sol::variadic_args va, T first) { - T s = 0; - for (auto arg : va) { - T v = arg; - s += v; - } - std::cout << first << std::endl; - std::cout << s << std::endl; - - return s; -} - -void takefn(std::function<int()> purr) { - if (purr() != 0x1456789) - throw 0; -} - -struct A { - int a = 0xA; int bark() { return 1; } -}; - -std::tuple<int, int> bark(int num_value, A* a) { - return std::tuple<int, int>(num_value * 2, a->bark()); -} - -void test_free_func(std::function<void()> f) { - f(); -} - -void test_free_func2(std::function<int(int)> f, int arg1) { - int val = f(arg1); - if (val != arg1) - throw sol::error("failed function call!"); -} - -int overloaded(int x) { - INFO(x); - return 3; -} - -int overloaded(int x, int y) { - INFO(x << " " << y); - return 7; -} - -int overloaded(int x, int y, int z) { - INFO(x << " " << y << " " << z); - return 11; -} - -int non_overloaded(int x, int y, int z) { - INFO(x << " " << y << " " << z); - return 13; -} - -namespace sep { - int plop_xyz(int x, int y, std::string z) { - INFO(x << " " << y << " " << z); - return 11; - } -} - -int func_1(int) { - return 1; -} - -std::string func_1s(std::string a) { - return "string: " + a; -} - -int func_2(int, int) { - return 2; -} - -void func_3(int, int, int) { - -} - -int f1(int) { return 32; } -int f2(int, int) { return 1; } -struct fer { - double f3(int, int) { - return 2.5; - } -}; - -TEST_CASE("functions/tuple-returns", "Make sure tuple returns are ordered properly") { - sol::state lua; - lua.script("function f() return '3', 4 end"); - - std::tuple<std::string, int> result = lua["f"](); - auto s = std::get<0>(result); - auto v = std::get<1>(result); - REQUIRE(s == "3"); - REQUIRE(v == 4); -} - -TEST_CASE("functions/overload-resolution", "Check if overloaded function resolution templates compile/work") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.set_function("non_overloaded", non_overloaded); - REQUIRE_NOTHROW(lua.script("x = non_overloaded(1, 2, 3)\nprint(x)")); - - /* - // Cannot reasonably support: clang++ refuses to try enough - // deductions to make this work - lua.set_function<int>("overloaded", overloaded); - REQUIRE_NOTHROW(lua.script("print(overloaded(1))")); - - lua.set_function<int, int>("overloaded", overloaded); - REQUIRE_NOTHROW(lua.script("print(overloaded(1, 2))")); - - lua.set_function<int, int, int>("overloaded", overloaded); - REQUIRE_NOTHROW(lua.script("print(overloaded(1, 2, 3))")); - */ - lua.set_function("overloaded", sol::resolve<int(int)>(overloaded)); - REQUIRE_NOTHROW(lua.script("print(overloaded(1))")); - - lua.set_function("overloaded", sol::resolve<int(int, int)>(overloaded)); - REQUIRE_NOTHROW(lua.script("print(overloaded(1, 2))")); - - lua.set_function("overloaded", sol::resolve<int(int, int, int)>(overloaded)); - REQUIRE_NOTHROW(lua.script("print(overloaded(1, 2, 3))")); -} - -TEST_CASE("functions/return-order-and-multi-get", "Check if return order is in the same reading order specified in Lua") { - const static std::tuple<int, int, int> triple = std::make_tuple(10, 11, 12); - const static std::tuple<int, float> paired = std::make_tuple(10, 10.f); - sol::state lua; - lua.set_function("f", [] { - return std::make_tuple(10, 11, 12); - }); - int a = 0; - lua.set_function("h", []() { - return std::make_tuple(10, 10.0f); - }); - lua.script("function g() return 10, 11, 12 end\nx,y,z = g()"); - auto tcpp = lua.get<sol::function>("f").call<int, int, int>(); - auto tlua = lua.get<sol::function>("g").call<int, int, int>(); - auto tcpp2 = lua.get<sol::function>("h").call<int, float>(); - auto tluaget = lua.get<int, int, int>("x", "y", "z"); - REQUIRE(tcpp == triple); - REQUIRE(tlua == triple); - REQUIRE(tluaget == triple); - REQUIRE(tcpp2 == paired); -} - -TEST_CASE("functions/deducing-return-order-and-multi-get", "Check if return order is in the same reading order specified in Lua, with regular deducing calls") { - const static std::tuple<int, int, int> triple = std::make_tuple(10, 11, 12); - sol::state lua; - lua.set_function("f_string", []() { return "this is a string!"; }); - sol::function f_string = lua["f_string"]; - - // Make sure there are no overload collisions / compiler errors for automatic string conversions - std::string f_string_result = f_string(); - REQUIRE(f_string_result == "this is a string!"); - f_string_result = f_string(); - REQUIRE(f_string_result == "this is a string!"); - - lua.set_function("f", [] { - return std::make_tuple(10, 11, 12); - }); - lua.script("function g() return 10, 11, 12 end\nx,y,z = g()"); - std::tuple<int, int, int> tcpp = lua.get<sol::function>("f")(); - std::tuple<int, int, int> tlua = lua.get<sol::function>("g")(); - std::tuple<int, int, int> tluaget = lua.get<int, int, int>("x", "y", "z"); - INFO("cpp: " << std::get<0>(tcpp) << ',' << std::get<1>(tcpp) << ',' << std::get<2>(tcpp)); - INFO("lua: " << std::get<0>(tlua) << ',' << std::get<1>(tlua) << ',' << std::get<2>(tlua)); - INFO("lua xyz: " << lua.get<int>("x") << ',' << lua.get<int>("y") << ',' << lua.get<int>("z")); - REQUIRE(tcpp == triple); - REQUIRE(tlua == triple); - REQUIRE(tluaget == triple); -} - -TEST_CASE("functions/optional-values", "check if optionals can be passed in to be nil or otherwise") { - struct thing { - int v; - }; - sol::state lua; - lua.script(R"( function f (a) - return a -end )"); - - sol::function lua_bark = lua["f"]; - - sol::optional<int> testv = lua_bark(sol::optional<int>(29)); - sol::optional<int> testn = lua_bark(sol::nullopt); - REQUIRE((bool)testv); - REQUIRE_FALSE((bool)testn); - REQUIRE(testv.value() == 29); - sol::optional<thing> v = lua_bark(sol::optional<thing>(thing{ 29 })); - REQUIRE_NOTHROW(sol::nil_t n = lua_bark(sol::nullopt)); - REQUIRE(v->v == 29); -} - -TEST_CASE("functions/pair-and-tuple-and-proxy-tests", "Check if sol::reference and sol::proxy can be passed to functions as arguments") { - sol::state lua; - lua.new_usertype<A>("A", - "bark", &A::bark); - lua.script(R"( function f (num_value, a) - return num_value * 2, a:bark() -end -function h (num_value, a, b) - return num_value * 2, a:bark(), b * 3 -end -nested = { variables = { no = { problem = 10 } } } )"); - lua.set_function("g", bark); - - sol::function cpp_bark = lua["g"]; - sol::function lua_bark = lua["f"]; - sol::function lua_bark2 = lua["h"]; - - sol::reference lua_variable_x = lua["nested"]["variables"]["no"]["problem"]; - A cpp_variable_y; - - static const std::tuple<int, int> abdesired(20, 1); - static const std::pair<int, int> cddesired = { 20, 1 }; - static const std::tuple<int, int, int> abcdesired(20, 1, 3); - - std::tuple<int, int> ab = cpp_bark(lua_variable_x, cpp_variable_y); - std::pair<int, int> cd = lua_bark(lua["nested"]["variables"]["no"]["problem"], cpp_variable_y); - - REQUIRE(ab == abdesired); - REQUIRE(cd == cddesired); - - ab = cpp_bark(std::make_pair(lua_variable_x, cpp_variable_y)); - cd = lua_bark(std::make_pair(lua["nested"]["variables"]["no"]["problem"], cpp_variable_y)); - - REQUIRE(ab == abdesired); - REQUIRE(cd == cddesired); - - std::tuple<int, int, int> abc = lua_bark2(std::make_tuple(10, cpp_variable_y), sol::optional<int>(1)); - REQUIRE(abc == abcdesired); -} - -TEST_CASE("functions/sol::function-to-std::function", "check if conversion to std::function works properly and calls with correct arguments") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.set_function("testFunc", test_free_func); - lua.set_function("testFunc2", test_free_func2); - lua.script( - "testFunc(function() print(\"hello std::function\") end)" - ); - REQUIRE_NOTHROW(lua.script( - "function m(a)\n" - " print(\"hello std::function with arg \", a)\n" - " return a\n" - "end\n" - "\n" - "testFunc2(m, 1)" - )); -} - -TEST_CASE("functions/returning-functions-from-C++-and-gettin-in-lua", "check to see if returning a functor and getting a functor from lua is possible") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.set_function("makefn", makefn); - lua.set_function("takefn", takefn); - lua.script("afx = makefn()\n" - "print(afx())\n" - "takefn(afx)\n"); -} - -TEST_CASE("functions/function_result-protected_function_result", "Function result should be the beefy return type for sol::function that allows for error checking and error handlers") { - sol::state lua; - lua.open_libraries(sol::lib::base, sol::lib::debug); - static const char unhandlederrormessage[] = "true error message"; - static const char handlederrormessage[] = "doodle"; - static const std::string handlederrormessage_s = handlederrormessage; - - // Some function; just using a lambda to be cheap - auto doomfx = []() { - INFO("doomfx called"); - throw std::runtime_error(unhandlederrormessage); - }; - auto luadoomfx = [&lua]() { - INFO("luadoomfx called"); - // Does not bypass error function, will call it - luaL_error(lua.lua_state(), unhandlederrormessage); - }; - lua.set_function("doom", doomfx); - lua.set_function("luadoom", luadoomfx); - - auto cpphandlerfx = [](std::string x) { - INFO("c++ handler called with: " << x); - return handlederrormessage; - }; - lua.set_function("cpphandler", cpphandlerfx); - lua.script( - std::string("function luahandler ( message )") - + " print('lua handler called with: ' .. message)" - + " return '" + handlederrormessage + "'" - + "end" - ); - auto nontrampolinefx = [](lua_State*) -> int { throw "x"; }; - lua_CFunction c_nontrampolinefx = nontrampolinefx; - lua.set("nontrampoline", c_nontrampolinefx); - lua.set_function("bark", []() -> int {return 100; }); - - sol::function luahandler = lua["luahandler"]; - sol::function cpphandler = lua["cpphandler"]; - sol::protected_function doom(lua["doom"], luahandler); - sol::protected_function luadoom(lua["luadoom"]); - sol::protected_function nontrampoline = lua["nontrampoline"]; - sol::protected_function justfine = lua["bark"]; - sol::protected_function justfinewithhandler = lua["bark"]; - luadoom.error_handler = cpphandler; - nontrampoline.error_handler = cpphandler; - justfinewithhandler.error_handler = luahandler; - bool present = true; - { - sol::protected_function_result result = doom(); - REQUIRE_FALSE(result.valid()); - sol::optional<sol::error> operr = result; - sol::optional<int> opvalue = result; - present = (bool)operr; - REQUIRE(present); - present = (bool)opvalue; - REQUIRE_FALSE(present); - sol::error err = result; - REQUIRE(err.what() == handlederrormessage_s); - } - { - sol::protected_function_result result = luadoom(); - REQUIRE_FALSE(result.valid()); - sol::optional<sol::error> operr = result; - sol::optional<int> opvalue = result; - present = (bool)operr; - REQUIRE(present); - present = (bool)opvalue; - REQUIRE_FALSE(present); - sol::error err = result; - REQUIRE(err.what() == handlederrormessage_s); - } - { - sol::protected_function_result result = nontrampoline(); - REQUIRE_FALSE(result.valid()); - sol::optional<sol::error> operr = result; - sol::optional<int> opvalue = result; - present = (bool)operr; - REQUIRE(present); - present = (bool)opvalue; - REQUIRE_FALSE(present); - sol::error err = result; - REQUIRE(err.what() == handlederrormessage_s); - } - { - sol::protected_function_result result = justfine(); - REQUIRE(result.valid()); - sol::optional<sol::error> operr = result; - sol::optional<int> opvalue = result; - present = (bool)operr; - REQUIRE_FALSE(present); - present = (bool)opvalue; - REQUIRE(present); - int value = result; - REQUIRE(value == 100); - } - { - sol::protected_function_result result = justfinewithhandler(); - REQUIRE(result.valid()); - sol::optional<sol::error> operr = result; - sol::optional<int> opvalue = result; - present = (bool)operr; - REQUIRE_FALSE(present); - present = (bool)opvalue; - REQUIRE(present); - int value = result; - REQUIRE(value == 100); - } -} - -TEST_CASE("functions/destructor-tests", "Show that proper copies / destruction happens") { - static int created = 0; - static int destroyed = 0; - static void* last_call = nullptr; - static void* static_call = reinterpret_cast<void*>(0x01); - typedef void(*fptr)(); - struct x { - x() { ++created; } - x(const x&) { ++created; } - x(x&&) { ++created; } - x& operator=(const x&) { return *this; } - x& operator=(x&&) { return *this; } - void func() { last_call = static_cast<void*>(this); }; - ~x() { ++destroyed; } - }; - struct y { - y() { ++created; } - y(const x&) { ++created; } - y(x&&) { ++created; } - y& operator=(const x&) { return *this; } - y& operator=(x&&) { return *this; } - static void func() { last_call = static_call; }; - void operator()() { func(); } - operator fptr () { return func; } - ~y() { ++destroyed; } - }; - - // stateful functors/member functions should always copy unless specified - { - created = 0; - destroyed = 0; - last_call = nullptr; - { - sol::state lua; - x x1; - lua.set_function("x1copy", &x::func, x1); - lua.script("x1copy()"); - REQUIRE(created == 2); - REQUIRE(destroyed == 0); - REQUIRE_FALSE(last_call == &x1); - - lua.set_function("x1ref", &x::func, std::ref(x1)); - lua.script("x1ref()"); - REQUIRE(created == 2); - REQUIRE(destroyed == 0); - REQUIRE(last_call == &x1); - } - REQUIRE(created == 2); - REQUIRE(destroyed == 2); - } - - // things convertible to a static function should _never_ be forced to make copies - // therefore, pass through untouched - { - created = 0; - destroyed = 0; - last_call = nullptr; - { - sol::state lua; - y y1; - lua.set_function("y1copy", y1); - lua.script("y1copy()"); - REQUIRE(created == 1); - REQUIRE(destroyed == 0); - REQUIRE(last_call == static_call); - - last_call = nullptr; - lua.set_function("y1ref", std::ref(y1)); - lua.script("y1ref()"); - REQUIRE(created == 1); - REQUIRE(destroyed == 0); - REQUIRE(last_call == static_call); - } - REQUIRE(created == 1); - REQUIRE(destroyed == 1); - } -} - - -TEST_CASE("functions/all-kinds", "Register all kinds of functions, make sure they all compile and work") { - sol::state lua; - - struct test_1 { - int a = 0xA; - virtual int bark() { - return a; - } - - int bark_mem() { - return a; - } - - static std::tuple<int, int> x_bark(int num_value, test_1* a) { - return std::tuple<int, int>(num_value * 2, a->a); - } - }; - - struct test_2 { - int a = 0xC; - int bark() { - return 20; - } - }; - - struct inner { - const int z = 5653; - }; - - struct nested { - inner i; - }; - - auto a = []() { return 500; }; - auto b = [&]() { return 501; }; - auto c = [&]() { return 502; }; - auto d = []() { return 503; }; - - lua.new_usertype<test_1>("test_1", - "bark", sol::c_call<decltype(&test_1::bark_mem), &test_1::bark_mem> - ); - lua.new_usertype<test_2>("test_2", - "bark", sol::c_call<decltype(&test_2::bark), &test_2::bark> - ); - test_2 t2; - - lua.set_function("a", a); - lua.set_function("b", b); - lua.set_function("c", std::ref(c)); - lua.set_function("d", std::ref(d)); - lua.set_function("f", &test_1::bark); - lua.set_function("g", test_1::x_bark); - lua.set_function("h", sol::c_call<decltype(&test_1::bark_mem), &test_1::bark_mem>); - lua.set_function("i", &test_2::bark, test_2()); - lua.set_function("j", &test_2::a, test_2()); - lua.set_function("k", &test_2::a); - lua.set_function("l", sol::c_call<decltype(&test_1::a), &test_1::a>); - lua.set_function("m", &test_2::a, &t2); - lua.set_function("n", sol::c_call<decltype(&non_overloaded), &non_overloaded>); - - lua.script(R"( -o1 = test_1.new() -o2 = test_2.new() -)"); - - lua.script(R"( -ob = o1:bark() - -A = a() -B = b() -C = c() -D = d() -F = f(o1) -G0, G1 = g(2, o1) -H = h(o1) -I = i(o1) -I = i(o1) -)"); - - - lua.script(R"( -J0 = j() -j(24) -J1 = j() - )"); - - lua.script(R"( -K0 = k(o2) -k(o2, 1024) -K1 = k(o2) - )"); - - lua.script(R"( -L0 = l(o1) -l(o1, 678) -L1 = l(o1) - )"); - - - lua.script(R"( -M0 = m() -m(256) -M1 = m() - )"); - - lua.script(R"( -N = n(1, 2, 3) - )"); - int ob, A, B, C, D, F, G0, G1, H, I, J0, J1, K0, K1, L0, L1, M0, M1, N; - std::tie(ob, A, B, C, D, F, G0, G1, H, I, J0, J1, K0, K1, L0, L1, M0, M1, N) - = lua.get<int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int>( - "ob", "A", "B", "C", "D", "F", "G0", "G1", "H", "I", "J0", "J1", "K0", "K1", "L0", "L1", "M0", "M1", "N" - ); - - REQUIRE(ob == 0xA); - - REQUIRE(A == 500); - REQUIRE(B == 501); - REQUIRE(C == 502); - REQUIRE(D == 503); - - REQUIRE(F == 0xA); - REQUIRE(G0 == 4); - REQUIRE(G1 == 0xA); - REQUIRE(H == 0xA); - REQUIRE(I == 20); - - REQUIRE(J0 == 0xC); - REQUIRE(J1 == 24); - - REQUIRE(K0 == 0xC); - REQUIRE(K1 == 1024); - - REQUIRE(L0 == 0xA); - REQUIRE(L1 == 678); - - REQUIRE(M0 == 0xC); - REQUIRE(M1 == 256); - - REQUIRE(N == 13); - - sol::tie(ob, A, B, C, D, F, G0, G1, H, I, J0, J1, K0, K1, L0, L1, M0, M1, N) - = lua.get<int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int>( - "ob", "A", "B", "C", "D", "F", "G0", "G1", "H", "I", "J0", "J1", "K0", "K1", "L0", "L1", "M0", "M1", "N" - ); - - REQUIRE(ob == 0xA); - - REQUIRE(A == 500); - REQUIRE(B == 501); - REQUIRE(C == 502); - REQUIRE(D == 503); - - REQUIRE(F == 0xA); - REQUIRE(G0 == 4); - REQUIRE(G1 == 0xA); - REQUIRE(H == 0xA); - REQUIRE(I == 20); - - REQUIRE(J0 == 0xC); - REQUIRE(J1 == 24); - - REQUIRE(K0 == 0xC); - REQUIRE(K1 == 1024); - - REQUIRE(L0 == 0xA); - REQUIRE(L1 == 678); - - REQUIRE(M0 == 0xC); - REQUIRE(M1 == 256); - - REQUIRE(N == 13); - - // Work that compiler, WORK IT! - lua.set("o", &test_1::bark); - lua.set("p", test_1::x_bark); - lua.set("q", sol::c_call<decltype(&test_1::bark_mem), &test_1::bark_mem>); - lua.set("r", &test_2::a); - lua.set("s", sol::readonly(&test_2::a)); - lua.set_function("t", sol::readonly(&test_2::a), test_2()); - lua.set_function("u", &nested::i, nested()); - lua.set("v", &nested::i); - lua.set("nested", nested()); - lua.set("inner", inner()); - REQUIRE_THROWS(lua.script("s(o2, 2)")); - REQUIRE_THROWS(lua.script("t(2)")); - REQUIRE_THROWS(lua.script("u(inner)")); - REQUIRE_THROWS(lua.script("v(nested, inner)")); -} - -TEST_CASE("simple/call-with-parameters", "Lua function is called with a few parameters from C++") { - sol::state lua; - - REQUIRE_NOTHROW(lua.script("function my_add(i, j, k) return i + j + k end")); - auto f = lua.get<sol::function>("my_add"); - REQUIRE_NOTHROW(lua.script("function my_nothing(i, j, k) end")); - auto fvoid = lua.get<sol::function>("my_nothing"); - int a; - REQUIRE_NOTHROW(fvoid(1, 2, 3)); - REQUIRE_NOTHROW(a = f.call<int>(1, 2, 3)); - REQUIRE(a == 6); - REQUIRE_THROWS(a = f(1, 2, "arf")); -} - -TEST_CASE("simple/call-c++-function", "C++ function is called from lua") { - sol::state lua; - - lua.set_function("plop_xyz", sep::plop_xyz); - lua.script("x = plop_xyz(2, 6, 'hello')"); - - REQUIRE(lua.get<int>("x") == 11); -} - -TEST_CASE("simple/call-lambda", "A C++ lambda is exposed to lua and called") { - sol::state lua; - - int a = 0; - - lua.set_function("foo", [&a] { a = 1; }); - - lua.script("foo()"); - - REQUIRE(a == 1); -} - -TEST_CASE("advanced/get-and-call", "Checks for lambdas returning values after a get operation") { - const static std::string lol = "lol", str = "str"; - const static std::tuple<int, float, double, std::string> heh_tuple = std::make_tuple(1, 6.28f, 3.14, std::string("heh")); - sol::state lua; - - REQUIRE_NOTHROW(lua.set_function("a", [] { return 42; })); - REQUIRE(lua.get<sol::function>("a").call<int>() == 42); - - REQUIRE_NOTHROW(lua.set_function("b", [] { return 42u; })); - REQUIRE(lua.get<sol::function>("b").call<unsigned int>() == 42u); - - REQUIRE_NOTHROW(lua.set_function("c", [] { return 3.14; })); - REQUIRE(lua.get<sol::function>("c").call<double>() == 3.14); - - REQUIRE_NOTHROW(lua.set_function("d", [] { return 6.28f; })); - REQUIRE(lua.get<sol::function>("d").call<float>() == 6.28f); - - REQUIRE_NOTHROW(lua.set_function("e", [] { return "lol"; })); - REQUIRE(lua.get<sol::function>("e").call<std::string>() == lol); - - REQUIRE_NOTHROW(lua.set_function("f", [] { return true; })); - REQUIRE(lua.get<sol::function>("f").call<bool>()); - - REQUIRE_NOTHROW(lua.set_function("g", [] { return std::string("str"); })); - REQUIRE(lua.get<sol::function>("g").call<std::string>() == str); - - REQUIRE_NOTHROW(lua.set_function("h", [] {})); - REQUIRE_NOTHROW(lua.get<sol::function>("h").call()); - - REQUIRE_NOTHROW(lua.set_function("i", [] { return sol::nil; })); - REQUIRE(lua.get<sol::function>("i").call<sol::nil_t>() == sol::nil); - REQUIRE_NOTHROW(lua.set_function("j", [] { return std::make_tuple(1, 6.28f, 3.14, std::string("heh")); })); - REQUIRE((lua.get<sol::function>("j").call<int, float, double, std::string>() == heh_tuple)); -} - -TEST_CASE("advanced/operator[]-call", "Checks for lambdas returning values using operator[]") { - const static std::string lol = "lol", str = "str"; - const static std::tuple<int, float, double, std::string> heh_tuple = std::make_tuple(1, 6.28f, 3.14, std::string("heh")); - sol::state lua; - - REQUIRE_NOTHROW(lua.set_function("a", [] { return 42; })); - REQUIRE(lua["a"].call<int>() == 42); - - REQUIRE_NOTHROW(lua.set_function("b", [] { return 42u; })); - REQUIRE(lua["b"].call<unsigned int>() == 42u); - - REQUIRE_NOTHROW(lua.set_function("c", [] { return 3.14; })); - REQUIRE(lua["c"].call<double>() == 3.14); - - REQUIRE_NOTHROW(lua.set_function("d", [] { return 6.28f; })); - REQUIRE(lua["d"].call<float>() == 6.28f); - - REQUIRE_NOTHROW(lua.set_function("e", [] { return "lol"; })); - REQUIRE(lua["e"].call<std::string>() == lol); - - REQUIRE_NOTHROW(lua.set_function("f", [] { return true; })); - REQUIRE(lua["f"].call<bool>()); - - REQUIRE_NOTHROW(lua.set_function("g", [] { return std::string("str"); })); - REQUIRE(lua["g"].call<std::string>() == str); - - REQUIRE_NOTHROW(lua.set_function("h", [] {})); - REQUIRE_NOTHROW(lua["h"].call()); - - REQUIRE_NOTHROW(lua.set_function("i", [] { return sol::nil; })); - REQUIRE(lua["i"].call<sol::nil_t>() == sol::nil); - REQUIRE_NOTHROW(lua.set_function("j", [] { return std::make_tuple(1, 6.28f, 3.14, std::string("heh")); })); - REQUIRE((lua["j"].call<int, float, double, std::string>() == heh_tuple)); -} - -TEST_CASE("advanced/call-lambdas", "A C++ lambda is exposed to lua and called") { - sol::state lua; - - int x = 0; - lua.set_function("set_x", [&](int new_x) { - x = new_x; - return 0; - }); - - lua.script("set_x(9)"); - REQUIRE(x == 9); -} - -TEST_CASE("advanced/call-referenced_obj", "A C++ object is passed by pointer/reference_wrapper to lua and invoked") { - sol::state lua; - - int x = 0; - auto objx = [&](int new_x) { - x = new_x; - return 0; - }; - lua.set_function("set_x", std::ref(objx)); - - int y = 0; - auto objy = [&](int new_y) { - y = new_y; - return std::tuple<int, int>(0, 0); - }; - lua.set_function("set_y", &decltype(objy)::operator(), std::ref(objy)); - - lua.script("set_x(9)"); - lua.script("set_y(9)"); - REQUIRE(x == 9); - REQUIRE(y == 9); -} - -TEST_CASE("functions/tie", "make sure advanced syntax with 'tie' works") { - sol::state lua; - - lua.script(R"(function f () - return 1, 2, 3 -end)"); - sol::function f = lua["f"]; - - int a, b, c; - sol::tie(a, b, c) = f(); - REQUIRE(a == 1); - REQUIRE(b == 2); - REQUIRE(c == 3); -} - -TEST_CASE("functions/variadic_args", "Check to see we can receive multiple arguments through a variadic") { - struct structure { - int x; - bool b; - }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - lua.set_function("v", [](sol::this_state, sol::variadic_args va) -> structure { - int r = 0; - for (auto v : va) { - int value = v; - r += value; - } - return{ r, r > 200 }; - }); - - lua.script("x = v(25, 25)"); - lua.script("x2 = v(25, 25, 100, 50, 250, 150)"); - lua.script("x3 = v(1, 2, 3, 4, 5, 6)"); - - structure& lx = lua["x"]; - structure& lx2 = lua["x2"]; - structure& lx3 = lua["x3"]; - REQUIRE(lx.x == 50); - REQUIRE(lx2.x == 600); - REQUIRE(lx3.x == 21); - REQUIRE_FALSE(lx.b); - REQUIRE(lx2.b); - REQUIRE_FALSE(lx3.b); -} - -TEST_CASE("functions/required_and_variadic_args", "Check if a certain number of arguments can still be required even when using variadic_args") { - sol::state lua; - lua.set_function("v", - [](sol::this_state, sol::variadic_args, int, int) { - } - ); - REQUIRE_NOTHROW(lua.script("v(20, 25, 30)")); - REQUIRE_NOTHROW(lua.script("v(20, 25)")); -#ifndef SOL_LUAJIT - REQUIRE_THROWS(lua.script("v(20)")); -#endif // LuaJIT has problems with exceptions, as fucking usual -} - -TEST_CASE("functions/overloading", "Check if overloading works properly for regular set function syntax") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.set_function("func_1", func_1); - lua.set_function("func", sol::overload(func_2, func_3, func_1, func_1s)); - - const std::string string_bark = "string: bark"; - - REQUIRE_NOTHROW(lua.script( - "a = func(1)\n" - "b = func('bark')\n" - "c = func(1,2)\n" - "func(1,2,3)\n" - )); - - REQUIRE((lua["a"] == 1)); - REQUIRE((lua["b"] == string_bark)); - REQUIRE((lua["c"] == 2)); - - REQUIRE_THROWS(lua.script("func(1,2,'meow')")); -} - -TEST_CASE("overloading/c_call", "Make sure that overloading works with c_call functionality") { - sol::state lua; - lua.set("f", sol::c_call<sol::wrap<decltype(&f1), &f1>, sol::wrap<decltype(&f2), &f2>, sol::wrap<decltype(&fer::f3), &fer::f3>>); - lua.set("g", sol::c_call<sol::wrap<decltype(&f1), &f1>>); - lua.set("h", sol::c_call<decltype(&f2), &f2>); - lua.set("obj", fer()); - - lua.script("r1 = f(1)"); - lua.script("r2 = f(1, 2)"); - lua.script("r3 = f(obj, 1, 2)"); - lua.script("r4 = g(1)"); - lua.script("r5 = h(1, 2)"); - - int r1 = lua["r1"]; - int r2 = lua["r2"]; - double r3 = lua["r3"]; - int r4 = lua["r4"]; - int r5 = lua["r5"]; - - REQUIRE(r1 == 32); - REQUIRE(r2 == 1); - REQUIRE(r3 == 2.5); - REQUIRE(r4 == 32); - REQUIRE(r5 == 1); -} - -TEST_CASE("functions/stack-protect", "make sure functions don't impede on the stack") { - //setup sol/lua - sol::state lua; - lua.open_libraries(sol::lib::base, sol::lib::string); - - lua.script("function ErrorHandler(msg) print('Lua created error msg : ' .. msg) return msg end"); - lua.script("function stringtest(a) if a == nil then error('fuck') end print('Lua recieved content : ' .. a) return a end"); - - // test normal function - { - sol::stack_guard normalsg(lua); - std::string str = lua["stringtest"]("normal test"); - INFO("Back in C++, direct call result is : " << str); - } - - //test protected_function - sol::protected_function Stringtest(lua["stringtest"]); - Stringtest.error_handler = lua["ErrorHandler"]; - sol::stack_guard sg(lua); - { - sol::protected_function_result stringresult = Stringtest("protected test"); - REQUIRE(stringresult.valid()); - std::string s = stringresult; - INFO("Back in C++, protected result is : " << s); - } - REQUIRE(sg.check_stack()); - - //test optional - { - sol::stack_guard opsg(lua); - sol::optional<std::string> opt_result = Stringtest("optional test"); - REQUIRE(opsg.check_stack()); - if (opt_result) - { - std::string s = opt_result.value(); - INFO("Back in C++, opt_result is : " << s); - } - else - { - INFO("opt_result failed"); - } - } - REQUIRE(sg.check_stack()); - - { - sol::protected_function_result errresult = Stringtest(sol::nil); - REQUIRE_FALSE(errresult.valid()); - sol::error err = errresult; - std::string msg = err.what(); - INFO("error :" << msg); - } - REQUIRE(sg.check_stack()); -} - -TEST_CASE("functions/same-type-closures", "make sure destructions are per-object, not per-type, by destroying one type multiple times") { - static std::set<void*> last_my_closures; - static bool checking_closures = false; - static bool check_failed = false; - - struct my_closure { - int& n; - - my_closure(int& n) : n(n) {} - ~my_closure() noexcept(false) { - if (!checking_closures) - return; - void* addr = static_cast<void*>(this); - auto f = last_my_closures.find(addr); - if (f != last_my_closures.cend()) { - check_failed = true; - } - last_my_closures.insert(f, addr); - } - - int operator() () { - ++n; return n; - } - }; - - int n = 250; - my_closure a(n); - my_closure b(n); - { - sol::state lua; - - lua.set_function("f", a); - lua.set_function("g", b); - checking_closures = true; - } - REQUIRE_FALSE(check_failed); - REQUIRE(last_my_closures.size() == 2); -} - -TEST_CASE("functions/stack-multi-return", "Make sure the stack is protected after multi-returns") { - sol::state lua; - lua.script("function f () return 1, 2, 3, 4, 5 end"); - - { - sol::stack_guard sg(lua); - sol::stack::push(lua, double(256.78)); - { - int a, b, c, d, e; - sol::stack_guard sg2(lua); - sol::function f = lua["f"]; - sol::tie(a, b, c, d, e) = f(); - REQUIRE(a == 1); - REQUIRE(b == 2); - REQUIRE(c == 3); - REQUIRE(d == 4); - REQUIRE(e == 5); - } - double f = sol::stack::pop<double>(lua); - REQUIRE(f == 256.78); - } -} - -TEST_CASE("functions/protected-stack-multi-return", "Make sure the stack is protected after multi-returns") { - sol::state lua; - lua.script("function f () return 1, 2, 3, 4, 5 end"); - - { - sol::stack_guard sg(lua); - sol::stack::push(lua, double(256.78)); - { - int a, b, c, d, e; - sol::stack_guard sg2(lua); - sol::protected_function pf = lua["f"]; - sol::tie(a, b, c, d, e) = pf(); - REQUIRE(a == 1); - REQUIRE(b == 2); - REQUIRE(c == 3); - REQUIRE(d == 4); - REQUIRE(e == 5); - } - double f = sol::stack::pop<double>(lua); - REQUIRE(f == 256.78); - } -} - -TEST_CASE("functions/overloaded-variadic", "make sure variadics work to some degree with overloading") { - sol::state lua; - lua.open_libraries(); - - sol::table ssl = lua.create_named_table("ssl"); - ssl.set_function("test", sol::overload(&va_func<int>, &va_func<double>)); - - lua.script("a = ssl.test(1, 2, 3)"); - lua.script("b = ssl.test(1, 2)"); - lua.script("c = ssl.test(2.2)"); - - int a = lua["a"]; - int b = lua["b"]; - double c = lua["c"]; - REQUIRE(a == 6); - REQUIRE(b == 3); - REQUIRE(c == 2.2); -} |