From 7af3fc4ffaae3cb9d756ba1de13d37eb1d9a0cfe Mon Sep 17 00:00:00 2001 From: ThePhD Date: Wed, 30 Mar 2016 16:52:51 -0400 Subject: [PATCH] Added nullopt pushing, optional pushing, improved tests --- sol/stack_check.hpp | 3 + sol/stack_get.hpp | 9 +- sol/stack_push.hpp | 19 ++ test_functions.cpp | 192 +++++++++++++- test_stack_guard.hpp | 11 + test_tables.cpp | 455 ++++++++++++++++++++++++++++++++ tests.cpp | 613 +------------------------------------------ 7 files changed, 690 insertions(+), 612 deletions(-) create mode 100644 test_stack_guard.hpp create mode 100644 test_tables.cpp diff --git a/sol/stack_check.hpp b/sol/stack_check.hpp index 2315ddba..eac0630a 100644 --- a/sol/stack_check.hpp +++ b/sol/stack_check.hpp @@ -118,6 +118,9 @@ struct checker { } }; +template +struct checker : checker {}; + template struct checker { template diff --git a/sol/stack_get.hpp b/sol/stack_get.hpp index f97dd76d..5143f025 100644 --- a/sol/stack_get.hpp +++ b/sol/stack_get.hpp @@ -116,7 +116,14 @@ struct getter { template<> struct getter { static nil_t get(lua_State*, int = -1) { - return nil_t{ }; + return nil; + } +}; + +template<> +struct getter { + static nullopt_t get(lua_State*, int = -1) { + return nullopt; } }; diff --git a/sol/stack_push.hpp b/sol/stack_push.hpp index fe464402..7538ab31 100644 --- a/sol/stack_push.hpp +++ b/sol/stack_push.hpp @@ -24,6 +24,7 @@ #include "stack_core.hpp" #include "raii.hpp" +#include "optional.hpp" #include namespace sol { @@ -291,6 +292,24 @@ struct pusher> { return pushcount; } }; + +template +struct pusher> { + template + static int push(lua_State* L, T&& t) { + if (t == nullopt) { + return stack::push(L, nullopt); + } + return stack::push(L, t.value()); + } +}; + +template<> +struct pusher { + static int push(lua_State* L, nullopt_t) { + return stack::push(L, nil); + } +}; } // stack } // sol diff --git a/test_functions.cpp b/test_functions.cpp index f3ec53c1..bc705908 100644 --- a/test_functions.cpp +++ b/test_functions.cpp @@ -3,6 +3,7 @@ #include #include #include +#include "test_stack_guard.hpp" std::function makefn() { auto fx = []() -> int { @@ -54,6 +55,13 @@ int non_overloaded(int x, int y, int z) { return 13; } +namespace sep { +int plop_xyz(int x, int y, std::string z) { + std::cout << x << " " << y << " " << z << std::endl; + return 11; +} +} + TEST_CASE("functions/overload-resolution", "Check if overloaded function resolution templates compile/work") { sol::state lua; lua.open_libraries(sol::lib::base); @@ -132,6 +140,24 @@ TEST_CASE("functions/deducing-return-order-and-multi-get", "Check if return orde REQUIRE(tluaget == triple); } +TEST_CASE("functions/optional-values", "check if optionals can be passed in to be nil or otherwise") { + sol::state lua; + lua.script(R"( function f (a) + return a +end )"); + + sol::function lua_bark = lua["f"]; + + sol::optional testv = lua_bark(sol::optional(29)); + sol::optional testn = lua_bark(sol::nullopt); + REQUIRE((bool)testv); + REQUIRE_FALSE((bool)testn); + REQUIRE(testv.value() == 29); + int v = lua_bark(sol::optional(29)); + REQUIRE_NOTHROW(sol::nil_t n = lua_bark(sol::nullopt)); + REQUIRE(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", @@ -139,22 +165,37 @@ TEST_CASE("functions/pair-and-tuple-and-proxy-tests", "Check if sol::reference a 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 abdesired(20, 1); + static const std::pair cddesired = { 20, 1 }; + static const std::tuple abcdesired(20, 1, 3); + std::tuple ab = cpp_bark(lua_variable_x, cpp_variable_y); std::pair cd = lua_bark(lua["nested"]["variables"]["no"]["problem"], cpp_variable_y); - - static const std::tuple abdesired( 20, 1 ); - static const std::pair cddesired = { 20, 1 }; + 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 abc = lua_bark2(std::make_tuple(10, cpp_variable_y), sol::optional(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") { @@ -166,14 +207,14 @@ TEST_CASE("functions/sol::function-to-std::function", "check if conversion to st lua.script( "testFunc(function() print(\"hello std::function\") end)" ); - lua.script( + 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") { @@ -444,3 +485,144 @@ M1 = m() REQUIRE( M0 == 0xC ); REQUIRE( M1 == 256 ); } + +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("my_add"); + REQUIRE_NOTHROW(lua.script("function my_nothing(i, j, k) end")); + auto fvoid = lua.get("my_nothing"); + int a; + REQUIRE_NOTHROW(fvoid(1, 2, 3)); + REQUIRE_NOTHROW(a = f.call(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("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 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("a").call() == 42); + + REQUIRE_NOTHROW(lua.set_function("b", [] { return 42u; })); + REQUIRE(lua.get("b").call() == 42u); + + REQUIRE_NOTHROW(lua.set_function("c", [] { return 3.14; })); + REQUIRE(lua.get("c").call() == 3.14); + + REQUIRE_NOTHROW(lua.set_function("d", [] { return 6.28f; })); + REQUIRE(lua.get("d").call() == 6.28f); + + REQUIRE_NOTHROW(lua.set_function("e", [] { return "lol"; })); + REQUIRE(lua.get("e").call() == lol); + + REQUIRE_NOTHROW(lua.set_function("f", [] { return true; })); + REQUIRE(lua.get("f").call()); + + REQUIRE_NOTHROW(lua.set_function("g", [] { return std::string("str"); })); + REQUIRE(lua.get("g").call() == str); + + REQUIRE_NOTHROW(lua.set_function("h", [] { })); + REQUIRE_NOTHROW(lua.get("h").call()); + + REQUIRE_NOTHROW(lua.set_function("i", [] { return sol::nil; })); + REQUIRE(lua.get("i").call() == sol::nil); + REQUIRE_NOTHROW(lua.set_function("j", [] { return std::make_tuple(1, 6.28f, 3.14, std::string("heh")); })); + REQUIRE((lua.get("j").call() == 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 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() == 42); + + REQUIRE_NOTHROW(lua.set_function("b", [] { return 42u; })); + REQUIRE(lua["b"].call() == 42u); + + REQUIRE_NOTHROW(lua.set_function("c", [] { return 3.14; })); + REQUIRE(lua["c"].call() == 3.14); + + REQUIRE_NOTHROW(lua.set_function("d", [] { return 6.28f; })); + REQUIRE(lua["d"].call() == 6.28f); + + REQUIRE_NOTHROW(lua.set_function("e", [] { return "lol"; })); + REQUIRE(lua["e"].call() == lol); + + REQUIRE_NOTHROW(lua.set_function("f", [] { return true; })); + REQUIRE(lua["f"].call()); + + REQUIRE_NOTHROW(lua.set_function("g", [] { return std::string("str"); })); + REQUIRE(lua["g"].call() == 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); + REQUIRE_NOTHROW(lua.set_function("j", [] { return std::make_tuple(1, 6.28f, 3.14, std::string("heh")); })); + REQUIRE((lua["j"].call() == 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(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); +} diff --git a/test_stack_guard.hpp b/test_stack_guard.hpp new file mode 100644 index 00000000..06b4fe43 --- /dev/null +++ b/test_stack_guard.hpp @@ -0,0 +1,11 @@ +#pragma once + +struct stack_guard { + lua_State* L; + int& begintop; + int& endtop; + stack_guard(lua_State* L, int& begintop, int& endtop) : L(L), begintop(begintop), endtop(endtop) { + begintop = lua_gettop(L); + } + ~stack_guard() { endtop = lua_gettop(L); } +}; diff --git a/test_tables.cpp b/test_tables.cpp new file mode 100644 index 00000000..82f10c72 --- /dev/null +++ b/test_tables.cpp @@ -0,0 +1,455 @@ +#define SOL_CHECK_ARGUMENTS + +#include +#include +#include +#include "test_stack_guard.hpp" + +std::string free_function() { + std::cout << "free_function()" << std::endl; + return "test"; +} + +std::vector test_table_return_one() { + return{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; +} + +std::vector> test_table_return_two() { + return{ { "one", 1 },{ "two", 2 },{ "three", 3 } }; +} + +std::map test_table_return_three() { + return{ { "name", "Rapptz" },{ "friend", "ThePhD" },{ "project", "sol" } }; +} + +struct object { + std::string operator() () { + std::cout << "member_test()" << std::endl; + return "test"; + } +}; + +int plop_xyz(int x, int y, std::string z) { + std::cout << x << " " << y << " " << z << std::endl; + return 11; +} + +TEST_CASE("tables/for-each", "Testing the use of for_each to get values from a lua table") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.script("arr = {\n" + "[0] = \"Hi\",\n" + "[1] = 123.45,\n" + "[2] = \"String value\",\n" + // Does nothing + //"[3] = nil,\n" + //"[nil] = 3,\n" + "[\"WOOF\"] = 123,\n" + "}"); + sol::table tbl = lua[ "arr" ]; + std::size_t tablesize = 4; + std::size_t iterations = 0; + auto fx = [&iterations](sol::object key, sol::object value) { + ++iterations; + sol::type keytype = key.get_type(); + switch (keytype) { + case sol::type::number: + switch (key.as()) { + case 0: + REQUIRE((value.as() == "Hi")); + break; + case 1: + REQUIRE((value.as() == 123.45)); + break; + case 2: + REQUIRE((value.as() == "String value")); + break; + case 3: + REQUIRE((value.is())); + break; + } + break; + case sol::type::string: + if (key.as() == "WOOF") { + REQUIRE((value.as() == 123)); + } + break; + case sol::type::nil: + REQUIRE((value.as() == 3)); + break; + default: + break; + } + }; + auto fxpair = [&fx](std::pair kvp) { fx(kvp.first, kvp.second); }; + tbl.for_each( fx ); + REQUIRE(iterations == tablesize); + + iterations = 0; + tbl.for_each( fxpair ); + REQUIRE(iterations == tablesize); +} + +TEST_CASE("tables/for-each-empty", "empty tables should not crash") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.script("arr = {}"); + sol::table tbl = lua[ "arr" ]; + REQUIRE(tbl.empty()); + std::size_t tablesize = 0; + std::size_t iterations = 0; + auto fx = [&iterations](sol::object key, sol::object value) { + ++iterations; + sol::type keytype = key.get_type(); + switch (keytype) { + case sol::type::number: + switch (key.as()) { + case 0: + REQUIRE((value.as() == "Hi")); + break; + case 1: + REQUIRE((value.as() == 123.45)); + break; + case 2: + REQUIRE((value.as() == "String value")); + break; + case 3: + REQUIRE((value.is())); + break; + } + break; + case sol::type::string: + if (key.as() == "WOOF") { + REQUIRE((value.as() == 123)); + } + break; + case sol::type::nil: + REQUIRE((value.as() == 3)); + break; + default: + break; + } + }; + auto fxpair = [&fx](std::pair kvp) { fx(kvp.first, kvp.second); }; + tbl.for_each( fx ); + REQUIRE(iterations == tablesize); + + iterations = 0; + tbl.for_each( fxpair ); + REQUIRE(iterations == tablesize); + + iterations = 0; + for (const auto& kvp : tbl) { + fxpair(kvp); + ++iterations; + } + REQUIRE(iterations == tablesize); +} + +TEST_CASE("tables/iterators", "Testing the use of iteratrs to get values from a lua table") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.script("arr = {\n" + "[0] = \"Hi\",\n" + "[1] = 123.45,\n" + "[2] = \"String value\",\n" + // Does nothing + //"[3] = nil,\n" + //"[nil] = 3,\n" + "[\"WOOF\"] = 123,\n" + "}"); + sol::table tbl = lua[ "arr" ]; + std::size_t tablesize = 4; + std::size_t iterations = 0; + + int begintop = 0; + int endtop = 0; + { + stack_guard s(lua.lua_state(), begintop, endtop); + for (auto& kvp : tbl) { + [&iterations](sol::object key, sol::object value) { + ++iterations; + sol::type keytype = key.get_type(); + switch (keytype) { + case sol::type::number: + switch (key.as()) { + case 0: + REQUIRE((value.as() == "Hi")); + break; + case 1: + REQUIRE((value.as() == 123.45)); + break; + case 2: + REQUIRE((value.as() == "String value")); + break; + case 3: + REQUIRE((value.is())); + break; + } + break; + case sol::type::string: + if (key.as() == "WOOF") { + REQUIRE((value.as() == 123)); + } + break; + case sol::type::nil: + REQUIRE((value.as() == 3)); + break; + default: + break; + } + }(kvp.first, kvp.second); + } + } REQUIRE(begintop == endtop); + REQUIRE(iterations == tablesize); +} + +TEST_CASE("tables/arbitrary-creation", "tables should be created from standard containers") { + sol::state lua; + lua.open_libraries(sol::lib::base); + lua.set_function("test_one", test_table_return_one); + lua.set_function("test_two", test_table_return_two); + lua.set_function("test_three", test_table_return_three); + + REQUIRE_NOTHROW(lua.script("a = test_one()")); + REQUIRE_NOTHROW(lua.script("b = test_two()")); + REQUIRE_NOTHROW(lua.script("c = test_three()")); + + REQUIRE_NOTHROW(lua.script("assert(#a == 10, 'error')")); + REQUIRE_NOTHROW(lua.script("assert(a[3] == 3, 'error')")); + REQUIRE_NOTHROW(lua.script("assert(b.one == 1, 'error')")); + REQUIRE_NOTHROW(lua.script("assert(b.three == 3, 'error')")); + REQUIRE_NOTHROW(lua.script("assert(c.name == 'Rapptz', 'error')")); + REQUIRE_NOTHROW(lua.script("assert(c.project == 'sol', 'error')")); + + auto&& a = lua.get("a"); + auto&& b = lua.get("b"); + auto&& c = lua.get("c"); + + REQUIRE(a.size() == 10ULL); + REQUIRE(a.get(3) == 3); + REQUIRE(b.get("one") == 1); + REQUIRE(b.get("three") == 3); + REQUIRE(c.get("name") == "Rapptz"); + REQUIRE(c.get("project") == "sol"); +} + + +TEST_CASE("tables/variables", "Check if tables and variables work as intended") { + sol::state lua; + lua.open_libraries(sol::lib::base, sol::lib::os); + lua.get("os").set("name", "windows"); + REQUIRE_NOTHROW(lua.script("assert(os.name == \"windows\")")); +} + +TEST_CASE("tables/create", "Check if creating a table is kosher") { + sol::state lua; + lua["testtable"] = sol::table::create(lua.lua_state(), 0, 0, "Woof", "Bark", 1, 2, 3, 4); + sol::object testobj = lua["testtable"]; + REQUIRE(testobj.is()); + sol::table testtable = testobj.as(); + REQUIRE((testtable["Woof"] == std::string("Bark"))); + REQUIRE((testtable[1] == 2)); + REQUIRE((testtable[3] == 4)); +} + +TEST_CASE("tables/create-local", "Check if creating a table is kosher") { + sol::state lua; + lua["testtable"] = lua.create_table(0, 0, "Woof", "Bark", 1, 2, 3, 4); + sol::object testobj = lua["testtable"]; + REQUIRE(testobj.is()); + sol::table testtable = testobj.as(); + REQUIRE((testtable["Woof"] == std::string("Bark"))); + REQUIRE((testtable[1] == 2)); + REQUIRE((testtable[3] == 4)); +} + +TEST_CASE("tables/create-local-named", "Check if creating a table is kosher") { + sol::state lua; + sol::table testtable = lua.create_table("testtable", 0, 0, "Woof", "Bark", 1, 2, 3, 4); + sol::object testobj = lua["testtable"]; + REQUIRE(testobj.is()); + REQUIRE((testtable["Woof"] == std::string("Bark"))); + REQUIRE((testtable[1] == 2)); + REQUIRE((testtable[3] == 4)); +} + +TEST_CASE("tables/create-with-local", "Check if creating a table is kosher") { + sol::state lua; + lua["testtable"] = lua.create_table_with("Woof", "Bark", 1, 2, 3, 4); + sol::object testobj = lua["testtable"]; + REQUIRE(testobj.is()); + sol::table testtable = testobj.as(); + REQUIRE((testtable["Woof"] == std::string("Bark"))); + REQUIRE((testtable[1] == 2)); + REQUIRE((testtable[3] == 4)); +} + +TEST_CASE("tables/functions-variables", "Check if tables and function calls work as intended") { + sol::state lua; + lua.open_libraries(sol::lib::base, sol::lib::os); + auto run_script = [] (sol::state& lua) -> void { + lua.script("assert(os.fun() == \"test\")"); + }; + + lua.get("os").set_function("fun", + [] () { + std::cout << "stateless lambda()" << std::endl; + return "test"; + } + ); + REQUIRE_NOTHROW(run_script(lua)); + + lua.get("os").set_function("fun", &free_function); + REQUIRE_NOTHROW(run_script(lua)); + + // l-value, canNOT optimise + // prefer value semantics unless wrapped with std::reference_wrapper + { + auto lval = object(); + lua.get("os").set_function("fun", &object::operator(), lval); + } + REQUIRE_NOTHROW(run_script(lua)); + + auto reflval = object(); + lua.get("os").set_function("fun", &object::operator(), std::ref(reflval)); + REQUIRE_NOTHROW(run_script(lua)); + + + // stateful lambda: non-convertible, cannot be optimised + int breakit = 50; + lua.get("os").set_function("fun", + [&breakit] () { + std::cout << "stateful lambda()" << std::endl; + return "test"; + } + ); + REQUIRE_NOTHROW(run_script(lua)); + + // r-value, cannot optimise + lua.get("os").set_function("fun", &object::operator(), object()); + REQUIRE_NOTHROW(run_script(lua)); + + // r-value, cannot optimise + auto rval = object(); + lua.get("os").set_function("fun", &object::operator(), std::move(rval)); + REQUIRE_NOTHROW(run_script(lua)); +} + +TEST_CASE("tables/operator[]", "Check if operator[] retrieval and setting works properly") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.script("foo = 20\nbar = \"hello world\""); + // basic retrieval + std::string bar = lua["bar"]; + int foo = lua["foo"]; + REQUIRE(bar == "hello world"); + REQUIRE(foo == 20); + // test operator= for stringification + // errors due to ambiguous operators + bar = lua["bar"]; + + // basic setting + lua["bar"] = 20.4; + lua["foo"] = "goodbye"; + + // doesn't modify the actual values obviously. + REQUIRE(bar == "hello world"); + REQUIRE(foo == 20); + + // function setting + lua["test"] = plop_xyz; + REQUIRE_NOTHROW(lua.script("assert(test(10, 11, \"hello\") == 11)")); + + // function retrieval + sol::function test = lua["test"]; + REQUIRE(test.call(10, 11, "hello") == 11); + + // setting a lambda + lua["lamb"] = [](int x) { + return x * 2; + }; + + REQUIRE_NOTHROW(lua.script("assert(lamb(220) == 440)")); + + // function retrieval of a lambda + sol::function lamb = lua["lamb"]; + REQUIRE(lamb.call(220) == 440); + + // test const table retrieval + auto assert1 = [](const sol::table& t) { + std::string a = t["foo"]; + double b = t["bar"]; + REQUIRE(a == "goodbye"); + REQUIRE(b == 20.4); + }; + + REQUIRE_NOTHROW(assert1(lua.globals())); +} + +TEST_CASE("tables/operator[]-valid", "Test if proxies on tables can lazily evaluate validity") { + sol::state lua; + bool isFullScreen = false; + auto fullscreennopers = lua["fullscreen"]["nopers"]; + auto fullscreen = lua["fullscreen"]; + REQUIRE_FALSE(fullscreennopers.valid()); + REQUIRE_FALSE(fullscreen.valid()); + + lua["fullscreen"] = true; + + REQUIRE_FALSE(fullscreennopers.valid()); + REQUIRE(fullscreen.valid()); + isFullScreen = lua["fullscreen"]; + REQUIRE(isFullScreen); + + lua["fullscreen"] = false; + REQUIRE_FALSE(fullscreennopers.valid()); + REQUIRE(fullscreen.valid()); + isFullScreen = lua["fullscreen"]; + REQUIRE_FALSE(isFullScreen); +} + +TEST_CASE("tables/operator[]-optional", "Test if proxies on tables can lazily evaluate validity") { + sol::state lua; + + sol::optional test1 = lua["no_exist_yet"]; + bool present = (bool)test1; + REQUIRE_FALSE(present); + + lua["no_exist_yet"] = 262; + sol::optional test2 = lua["no_exist_yet"]; + present = (bool)test2; + REQUIRE(present); + REQUIRE(test2.value() == 262); + + sol::optional nope = lua["nope"]["kek"]["hah"]; + auto nope2 = lua.get>(std::make_tuple("nope", "kek", "hah")); + present = (bool)nope; + REQUIRE_FALSE(present); + present = (bool)nope2; + REQUIRE_FALSE(present); + lua.create_named_table("nope", "kek", lua.create_table_with("hah", 1)); + sol::optional non_nope = lua["nope"]["kek"]["hah"].get>(); + sol::optional non_nope2 = lua.get>(std::make_tuple("nope", "kek", "hah")); + present = (bool)non_nope; + REQUIRE(present); + present = (bool)non_nope2; + REQUIRE(present); + REQUIRE(non_nope.value() == 1); + REQUIRE(non_nope2.value() == 1); + + std::cout << "Keys: nope, kek, hah" << std::endl; + lua.set(std::make_tuple("nope", "kek", "hah"), 35); + sol::optional non_nope3 = lua["nope"]["kek"]["hah"].get>(); + sol::optional non_nope4 = lua.get>(std::make_tuple("nope", "kek", "hah")); + present = (bool)non_nope3; + REQUIRE(present); + present = (bool)non_nope4; + REQUIRE(present); + REQUIRE(non_nope3.value() == 35); + REQUIRE(non_nope4.value() == 35); +} \ No newline at end of file diff --git a/tests.cpp b/tests.cpp index b7f4d9da..dac2b9d2 100644 --- a/tests.cpp +++ b/tests.cpp @@ -5,33 +5,7 @@ #include #include #include - -struct stack_guard { - lua_State* L; - int& begintop; - int& endtop; - stack_guard(lua_State* L, int& begintop, int& endtop) : L(L), begintop(begintop), endtop(endtop) { - begintop = lua_gettop(L); - } - ~stack_guard() { endtop = lua_gettop(L); } -}; - -std::string free_function() { - std::cout << "free_function()" << std::endl; - return "test"; -} - -std::vector test_table_return_one() { - return { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; -} - -std::vector> test_table_return_two() { - return {{ "one", 1 }, { "two", 2 }, { "three", 3 }}; -} - -std::map test_table_return_three() { - return {{ "name", "Rapptz" }, { "friend", "ThePhD" }, { "project", "sol" }}; -} +#include "test_stack_guard.hpp" struct self_test { int bark; @@ -82,13 +56,6 @@ struct vars { } }; -struct object { - std::string operator() () { - std::cout << "member_test()" << std::endl; - return "test"; - } -}; - struct fuser { int x; fuser() : x(0) {} @@ -120,11 +87,6 @@ struct fuser { }; } // crapola -int plop_xyz(int x, int y, std::string z) { - std::cout << x << " " << y << " " << z << std::endl; - return 11; -} - class Base { public: Base(int a_num) : m_num(a_num) { } @@ -365,147 +327,6 @@ TEST_CASE("simple/if", "check if if statements work through lua") { REQUIRE((f == lua["f"])); } -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("my_add"); - REQUIRE_NOTHROW(lua.script("function my_nothing(i, j, k) end")); - auto fvoid = lua.get("my_nothing"); - int a; - REQUIRE_NOTHROW(fvoid(1, 2, 3)); - REQUIRE_NOTHROW(a = f.call(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", plop_xyz); - lua.script("x = plop_xyz(2, 6, 'hello')"); - - REQUIRE(lua.get("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 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("a").call() == 42); - - REQUIRE_NOTHROW(lua.set_function("b", [] { return 42u; })); - REQUIRE(lua.get("b").call() == 42u); - - REQUIRE_NOTHROW(lua.set_function("c", [] { return 3.14; })); - REQUIRE(lua.get("c").call() == 3.14); - - REQUIRE_NOTHROW(lua.set_function("d", [] { return 6.28f; })); - REQUIRE(lua.get("d").call() == 6.28f); - - REQUIRE_NOTHROW(lua.set_function("e", [] { return "lol"; })); - REQUIRE(lua.get("e").call() == lol); - - REQUIRE_NOTHROW(lua.set_function("f", [] { return true; })); - REQUIRE(lua.get("f").call()); - - REQUIRE_NOTHROW(lua.set_function("g", [] { return std::string("str"); })); - REQUIRE(lua.get("g").call() == str); - - REQUIRE_NOTHROW(lua.set_function("h", [] { })); - REQUIRE_NOTHROW(lua.get("h").call()); - - REQUIRE_NOTHROW(lua.set_function("i", [] { return sol::nil; })); - REQUIRE(lua.get("i").call() == sol::nil); - REQUIRE_NOTHROW(lua.set_function("j", [] { return std::make_tuple(1, 6.28f, 3.14, std::string("heh")); })); - REQUIRE((lua.get("j").call() == 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 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() == 42); - - REQUIRE_NOTHROW(lua.set_function("b", [] { return 42u; })); - REQUIRE(lua["b"].call() == 42u); - - REQUIRE_NOTHROW(lua.set_function("c", [] { return 3.14; })); - REQUIRE(lua["c"].call() == 3.14); - - REQUIRE_NOTHROW(lua.set_function("d", [] { return 6.28f; })); - REQUIRE(lua["d"].call() == 6.28f); - - REQUIRE_NOTHROW(lua.set_function("e", [] { return "lol"; })); - REQUIRE(lua["e"].call() == lol); - - REQUIRE_NOTHROW(lua.set_function("f", [] { return true; })); - REQUIRE(lua["f"].call()); - - REQUIRE_NOTHROW(lua.set_function("g", [] { return std::string("str"); })); - REQUIRE(lua["g"].call() == 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); - REQUIRE_NOTHROW(lua.set_function("j", [] { return std::make_tuple(1, 6.28f, 3.14, std::string("heh")); })); - REQUIRE((lua["j"].call() == 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(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("negative/basic_errors", "Check if error handling works correctly") { sol::state lua; @@ -517,224 +338,7 @@ TEST_CASE("libraries", "Check if we can open libraries") { REQUIRE_NOTHROW(lua.open_libraries(sol::lib::base, sol::lib::os)); } -TEST_CASE("tables/variables", "Check if tables and variables work as intended") { - sol::state lua; - lua.open_libraries(sol::lib::base, sol::lib::os); - lua.get("os").set("name", "windows"); - REQUIRE_NOTHROW(lua.script("assert(os.name == \"windows\")")); -} - -TEST_CASE("tables/create", "Check if creating a table is kosher") { - sol::state lua; - lua["testtable"] = sol::table::create(lua.lua_state(), 0, 0, "Woof", "Bark", 1, 2, 3, 4); - sol::object testobj = lua["testtable"]; - REQUIRE(testobj.is()); - sol::table testtable = testobj.as(); - REQUIRE((testtable["Woof"] == std::string("Bark"))); - REQUIRE((testtable[1] == 2)); - REQUIRE((testtable[3] == 4)); -} - -TEST_CASE("tables/create-local", "Check if creating a table is kosher") { - sol::state lua; - lua["testtable"] = lua.create_table(0, 0, "Woof", "Bark", 1, 2, 3, 4); - sol::object testobj = lua["testtable"]; - REQUIRE(testobj.is()); - sol::table testtable = testobj.as(); - REQUIRE((testtable["Woof"] == std::string("Bark"))); - REQUIRE((testtable[1] == 2)); - REQUIRE((testtable[3] == 4)); -} - -TEST_CASE("tables/create-local-named", "Check if creating a table is kosher") { - sol::state lua; - sol::table testtable = lua.create_table("testtable", 0, 0, "Woof", "Bark", 1, 2, 3, 4); - sol::object testobj = lua["testtable"]; - REQUIRE(testobj.is()); - REQUIRE((testtable["Woof"] == std::string("Bark"))); - REQUIRE((testtable[1] == 2)); - REQUIRE((testtable[3] == 4)); -} - -TEST_CASE("tables/create-with-local", "Check if creating a table is kosher") { - sol::state lua; - lua["testtable"] = lua.create_table_with("Woof", "Bark", 1, 2, 3, 4); - sol::object testobj = lua["testtable"]; - REQUIRE(testobj.is()); - sol::table testtable = testobj.as(); - REQUIRE((testtable["Woof"] == std::string("Bark"))); - REQUIRE((testtable[1] == 2)); - REQUIRE((testtable[3] == 4)); -} - -TEST_CASE("tables/functions-variables", "Check if tables and function calls work as intended") { - sol::state lua; - lua.open_libraries(sol::lib::base, sol::lib::os); - auto run_script = [] (sol::state& lua) -> void { - lua.script("assert(os.fun() == \"test\")"); - }; - - lua.get("os").set_function("fun", - [] () { - std::cout << "stateless lambda()" << std::endl; - return "test"; - } - ); - REQUIRE_NOTHROW(run_script(lua)); - - lua.get("os").set_function("fun", &free_function); - REQUIRE_NOTHROW(run_script(lua)); - - // l-value, canNOT optimise - // prefer value semantics unless wrapped with std::reference_wrapper - { - auto lval = object(); - lua.get("os").set_function("fun", &object::operator(), lval); - } - REQUIRE_NOTHROW(run_script(lua)); - - auto reflval = object(); - lua.get("os").set_function("fun", &object::operator(), std::ref(reflval)); - REQUIRE_NOTHROW(run_script(lua)); - - - // stateful lambda: non-convertible, cannot be optimised - int breakit = 50; - lua.get("os").set_function("fun", - [&breakit] () { - std::cout << "stateful lambda()" << std::endl; - return "test"; - } - ); - REQUIRE_NOTHROW(run_script(lua)); - - // r-value, cannot optimise - lua.get("os").set_function("fun", &object::operator(), object()); - REQUIRE_NOTHROW(run_script(lua)); - - // r-value, cannot optimise - auto rval = object(); - lua.get("os").set_function("fun", &object::operator(), std::move(rval)); - REQUIRE_NOTHROW(run_script(lua)); -} - -TEST_CASE("tables/operator[]", "Check if operator[] retrieval and setting works properly") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.script("foo = 20\nbar = \"hello world\""); - // basic retrieval - std::string bar = lua["bar"]; - int foo = lua["foo"]; - REQUIRE(bar == "hello world"); - REQUIRE(foo == 20); - // test operator= for stringification - // errors due to ambiguous operators - bar = lua["bar"]; - - // basic setting - lua["bar"] = 20.4; - lua["foo"] = "goodbye"; - - // doesn't modify the actual values obviously. - REQUIRE(bar == "hello world"); - REQUIRE(foo == 20); - - // function setting - lua["test"] = plop_xyz; - REQUIRE_NOTHROW(lua.script("assert(test(10, 11, \"hello\") == 11)")); - - // function retrieval - sol::function test = lua["test"]; - REQUIRE(test.call(10, 11, "hello") == 11); - - // setting a lambda - lua["lamb"] = [](int x) { - return x * 2; - }; - - REQUIRE_NOTHROW(lua.script("assert(lamb(220) == 440)")); - - // function retrieval of a lambda - sol::function lamb = lua["lamb"]; - REQUIRE(lamb.call(220) == 440); - - // test const table retrieval - auto assert1 = [](const sol::table& t) { - std::string a = t["foo"]; - double b = t["bar"]; - REQUIRE(a == "goodbye"); - REQUIRE(b == 20.4); - }; - - REQUIRE_NOTHROW(assert1(lua.globals())); -} - -TEST_CASE("tables/operator[]-valid", "Test if proxies on tables can lazily evaluate validity") { - sol::state lua; - bool isFullScreen = false; - auto fullscreennopers = lua["fullscreen"]["nopers"]; - auto fullscreen = lua["fullscreen"]; - REQUIRE_FALSE(fullscreennopers.valid()); - REQUIRE_FALSE(fullscreen.valid()); - - lua["fullscreen"] = true; - - REQUIRE_FALSE(fullscreennopers.valid()); - REQUIRE(fullscreen.valid()); - isFullScreen = lua["fullscreen"]; - REQUIRE(isFullScreen); - - lua["fullscreen"] = false; - REQUIRE_FALSE(fullscreennopers.valid()); - REQUIRE(fullscreen.valid()); - isFullScreen = lua["fullscreen"]; - REQUIRE_FALSE(isFullScreen); -} - -TEST_CASE("tables/operator[]-optional", "Test if proxies on tables can lazily evaluate validity") { - sol::state lua; - - sol::optional test1 = lua["no_exist_yet"]; - bool present = (bool)test1; - REQUIRE_FALSE(present); - - lua["no_exist_yet"] = 262; - sol::optional test2 = lua["no_exist_yet"]; - present = (bool)test2; - REQUIRE(present); - REQUIRE(test2.value() == 262); - - sol::optional nope = lua["nope"]["kek"]["hah"]; - auto nope2 = lua.get>(std::make_tuple("nope", "kek", "hah")); - present = (bool)nope; - REQUIRE_FALSE(present); - present = (bool)nope2; - REQUIRE_FALSE(present); - lua.create_named_table("nope", "kek", lua.create_table_with("hah", 1)); - sol::optional non_nope = lua["nope"]["kek"]["hah"].get>(); - sol::optional non_nope2 = lua.get>(std::make_tuple("nope", "kek", "hah")); - present = (bool)non_nope; - REQUIRE(present); - present = (bool)non_nope2; - REQUIRE(present); - REQUIRE(non_nope.value() == 1); - REQUIRE(non_nope2.value() == 1); - - std::cout << "Keys: nope, kek, hah" << std::endl; - lua.set(std::make_tuple("nope", "kek", "hah"), 35); - sol::optional non_nope3 = lua["nope"]["kek"]["hah"].get>(); - sol::optional non_nope4 = lua.get>(std::make_tuple("nope", "kek", "hah")); - present = (bool)non_nope3; - REQUIRE(present); - present = (bool)non_nope4; - REQUIRE(present); - REQUIRE(non_nope3.value() == 35); - REQUIRE(non_nope4.value() == 35); -} - -TEST_CASE("tables/usertype", "Show that we can create classes from usertype and use them") { - +TEST_CASE("usertype/usertype", "Show that we can create classes from usertype and use them") { sol::state lua; sol::usertype lc{ "add", &fuser::add, "add2", &fuser::add2 }; @@ -760,7 +364,7 @@ TEST_CASE("tables/usertype", "Show that we can create classes from usertype and REQUIRE(cresult == 3); } -TEST_CASE("tables/usertype-constructors", "Show that we can create classes from usertype and use them with multiple constructors") { +TEST_CASE("usertype/usertype-constructors", "Show that we can create classes from usertype and use them with multiple constructors") { sol::state lua; @@ -803,7 +407,7 @@ TEST_CASE("tables/usertype-constructors", "Show that we can create classes from REQUIRE((z.as() == 9)); } -TEST_CASE("tables/usertype-utility", "Show internal management of classes registered through new_usertype") { +TEST_CASE("usertype/usertype-utility", "Show internal management of classes registered through new_usertype") { sol::state lua; lua.new_usertype("fuser", "add", &fuser::add, "add2", &fuser::add2); @@ -828,7 +432,7 @@ TEST_CASE("tables/usertype-utility", "Show internal management of classes regist REQUIRE(cresult == 3); } -TEST_CASE("tables/usertype-utility-derived", "usertype classes must play nice when a derived class does not overload a publically visible base function") { +TEST_CASE("usertype/usertype-utility-derived", "usertype classes must play nice when a derived class does not overload a publically visible base function") { sol::state lua; lua.open_libraries(sol::lib::base); sol::constructors> basector; @@ -858,7 +462,7 @@ TEST_CASE("tables/usertype-utility-derived", "usertype classes must play nice wh REQUIRE((lua.get("dgn") == 7)); } -TEST_CASE("tables/self-referential usertype", "usertype classes must play nice when C++ object types are requested for C++ code") { +TEST_CASE("usertype/self-referential usertype", "usertype classes must play nice when C++ object types are requested for C++ code") { sol::state lua; lua.open_libraries(sol::lib::base); @@ -871,210 +475,7 @@ TEST_CASE("tables/self-referential usertype", "usertype classes must play nice w ); } -TEST_CASE("tables/arbitrary-creation", "tables should be created from standard containers") { - sol::state lua; - lua.open_libraries(sol::lib::base); - lua.set_function("test_one", test_table_return_one); - lua.set_function("test_two", test_table_return_two); - lua.set_function("test_three", test_table_return_three); - - REQUIRE_NOTHROW(lua.script("a = test_one()")); - REQUIRE_NOTHROW(lua.script("b = test_two()")); - REQUIRE_NOTHROW(lua.script("c = test_three()")); - - REQUIRE_NOTHROW(lua.script("assert(#a == 10, 'error')")); - REQUIRE_NOTHROW(lua.script("assert(a[3] == 3, 'error')")); - REQUIRE_NOTHROW(lua.script("assert(b.one == 1, 'error')")); - REQUIRE_NOTHROW(lua.script("assert(b.three == 3, 'error')")); - REQUIRE_NOTHROW(lua.script("assert(c.name == 'Rapptz', 'error')")); - REQUIRE_NOTHROW(lua.script("assert(c.project == 'sol', 'error')")); - - auto&& a = lua.get("a"); - auto&& b = lua.get("b"); - auto&& c = lua.get("c"); - - REQUIRE(a.size() == 10ULL); - REQUIRE(a.get(3) == 3); - REQUIRE(b.get("one") == 1); - REQUIRE(b.get("three") == 3); - REQUIRE(c.get("name") == "Rapptz"); - REQUIRE(c.get("project") == "sol"); -} - -TEST_CASE("tables/for-each", "Testing the use of for_each to get values from a lua table") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.script("arr = {\n" - "[0] = \"Hi\",\n" - "[1] = 123.45,\n" - "[2] = \"String value\",\n" - // Does nothing - //"[3] = nil,\n" - //"[nil] = 3,\n" - "[\"WOOF\"] = 123,\n" - "}"); - sol::table tbl = lua[ "arr" ]; - std::size_t tablesize = 4; - std::size_t iterations = 0; - auto fx = [&iterations](sol::object key, sol::object value) { - ++iterations; - sol::type keytype = key.get_type(); - switch (keytype) { - case sol::type::number: - switch (key.as()) { - case 0: - REQUIRE((value.as() == "Hi")); - break; - case 1: - REQUIRE((value.as() == 123.45)); - break; - case 2: - REQUIRE((value.as() == "String value")); - break; - case 3: - REQUIRE((value.is())); - break; - } - break; - case sol::type::string: - if (key.as() == "WOOF") { - REQUIRE((value.as() == 123)); - } - break; - case sol::type::nil: - REQUIRE((value.as() == 3)); - break; - default: - break; - } - }; - auto fxpair = [&fx](std::pair kvp) { fx(kvp.first, kvp.second); }; - tbl.for_each( fx ); - REQUIRE(iterations == tablesize); - - iterations = 0; - tbl.for_each( fxpair ); - REQUIRE(iterations == tablesize); -} - -TEST_CASE("tables/for-each-empty", "empty tables should not crash") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.script("arr = {}"); - sol::table tbl = lua[ "arr" ]; - REQUIRE(tbl.empty()); - std::size_t tablesize = 0; - std::size_t iterations = 0; - auto fx = [&iterations](sol::object key, sol::object value) { - ++iterations; - sol::type keytype = key.get_type(); - switch (keytype) { - case sol::type::number: - switch (key.as()) { - case 0: - REQUIRE((value.as() == "Hi")); - break; - case 1: - REQUIRE((value.as() == 123.45)); - break; - case 2: - REQUIRE((value.as() == "String value")); - break; - case 3: - REQUIRE((value.is())); - break; - } - break; - case sol::type::string: - if (key.as() == "WOOF") { - REQUIRE((value.as() == 123)); - } - break; - case sol::type::nil: - REQUIRE((value.as() == 3)); - break; - default: - break; - } - }; - auto fxpair = [&fx](std::pair kvp) { fx(kvp.first, kvp.second); }; - tbl.for_each( fx ); - REQUIRE(iterations == tablesize); - - iterations = 0; - tbl.for_each( fxpair ); - REQUIRE(iterations == tablesize); - - iterations = 0; - for (const auto& kvp : tbl) { - fxpair(kvp); - ++iterations; - } - REQUIRE(iterations == tablesize); -} - -TEST_CASE("tables/iterators", "Testing the use of iteratrs to get values from a lua table") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.script("arr = {\n" - "[0] = \"Hi\",\n" - "[1] = 123.45,\n" - "[2] = \"String value\",\n" - // Does nothing - //"[3] = nil,\n" - //"[nil] = 3,\n" - "[\"WOOF\"] = 123,\n" - "}"); - sol::table tbl = lua[ "arr" ]; - std::size_t tablesize = 4; - std::size_t iterations = 0; - - int begintop = 0; - int endtop = 0; - { - stack_guard s(lua.lua_state(), begintop, endtop); - for (auto& kvp : tbl) { - [&iterations](sol::object key, sol::object value) { - ++iterations; - sol::type keytype = key.get_type(); - switch (keytype) { - case sol::type::number: - switch (key.as()) { - case 0: - REQUIRE((value.as() == "Hi")); - break; - case 1: - REQUIRE((value.as() == 123.45)); - break; - case 2: - REQUIRE((value.as() == "String value")); - break; - case 3: - REQUIRE((value.is())); - break; - } - break; - case sol::type::string: - if (key.as() == "WOOF") { - REQUIRE((value.as() == 123)); - } - break; - case sol::type::nil: - REQUIRE((value.as() == 3)); - break; - default: - break; - } - }(kvp.first, kvp.second); - } - } REQUIRE(begintop == endtop); - REQUIRE(iterations == tablesize); -} - -TEST_CASE("tables/issue-number-twenty-five", "Using pointers and references from C++ classes in Lua") { +TEST_CASE("usertype/issue-number-twenty-five", "Using pointers and references from C++ classes in Lua") { struct test { int x = 0; test& set() {