#include #include #include #include class LuaClass_Test { public: LuaClass_Test() = default; LuaClass_Test(const LuaClass_Test& other) = default; LuaClass_Test& operator=(const LuaClass_Test& other) = default; virtual ~LuaClass_Test() = default; LuaClass_Test(int i, bool j = false) : m_i(i), m_j(j) { } virtual int GetI() const { return m_i; } bool GetJ() const { return m_j; } int GetDefault(int defaultValue = 0) { return defaultValue; } static int StaticMethodWithArguments(int a, int b) { return a + b; } private: int m_i; bool m_j; }; class LuaClass_InheritTest : public LuaClass_Test { public: LuaClass_InheritTest() : LuaClass_Test(5, true) { } int GetI() const override { return LuaClass_Test::GetI() + 3; } }; class LuaClass_TestWithHandle : public Nz::HandledObject { public: int GetI() const { return m_i; } int GetDefault(int defaultValue = 0) { return defaultValue; } private: int m_i = 8; }; inline unsigned int LuaImplQueryArg(const Nz::LuaState& instance, int index, LuaClass_Test* arg, Nz::TypeTag) { REQUIRE(instance.IsOfType(index, "Test")); *arg = *static_cast(instance.ToUserdata(index)); return 1; } inline unsigned int LuaImplQueryArg(const Nz::LuaState& instance, int index, Nz::ObjectHandle* arg, Nz::TypeTag>) { REQUIRE(instance.IsOfType(index, "TestWithHandle")); *arg = *static_cast*>(instance.ToUserdata(index)); return 1; } inline unsigned int LuaImplQueryArg(const Nz::LuaState& instance, int index, LuaClass_InheritTest* arg, Nz::TypeTag) { REQUIRE(instance.IsOfType(index, "InheritTest")); *arg = *static_cast(instance.ToUserdata(index)); return 1; } SCENARIO("LuaClass", "[LUA][LUACLASS]") { GIVEN("One lua class for our Test class") { Nz::LuaInstance luaInstance; Nz::LuaClass test; Nz::LuaClass inheritTest; using TestHandle = Nz::ObjectHandle; Nz::LuaClass testHandle; WHEN("We bind the methods") { test.Reset("Test"); test.BindDefaultConstructor(); test.SetConstructor([] (Nz::LuaState& lua, LuaClass_Test* instance, std::size_t argumentCount) { std::size_t argCount = std::min(argumentCount, 2U); int argIndex = 1; switch (argCount) { case 1: { int iValue = lua.Check(&argIndex, 0); Nz::PlacementNew(instance, iValue); return true; } case 2: { int iValue = lua.Check(&argIndex, 0); bool j = lua.Check(&argIndex, false); Nz::PlacementNew(instance, iValue, j); return true; } } lua.Error("No matching overload for Test constructor"); return false; }); test.BindMethod("GetI", &LuaClass_Test::GetI); test.BindMethod("GetJ", &LuaClass_Test::GetJ); test.BindMethod("GetDefault", &LuaClass_Test::GetDefault, 0); test.BindStaticMethod("StaticMethodWithArguments", [] (Nz::LuaState& state) -> int { int argIndex = 1; int result = LuaClass_Test::StaticMethodWithArguments(state.Check(&argIndex), state.Check(&argIndex)); state.Push(result); return 1; }); test.Register(luaInstance); THEN("We should be able to call them") { int value = 1; int staticResult = value + value; luaInstance.PushFunction([=](Nz::LuaState& state) -> int { int argIndex = 1; LuaClass_Test result = state.Check(&argIndex); CHECK(result.GetI() == value); CHECK_FALSE(result.GetJ()); return 1; }); luaInstance.SetGlobal("CheckTest"); luaInstance.PushFunction([=](Nz::LuaState& state) -> int { int argIndex = 1; int result = state.Check(&argIndex); CHECK(result == staticResult); return 1; }); luaInstance.SetGlobal("CheckStatic"); luaInstance.PushFunction([=](Nz::LuaState& state) -> int { int argIndex = 1; LuaClass_Test result = state.Check(&argIndex); CHECK(result.GetI() == staticResult); CHECK(result.GetJ()); return 1; }); luaInstance.SetGlobal("CheckFinalTest"); REQUIRE(luaInstance.ExecuteFromFile("resources/Engine/Lua/LuaClass.lua")); REQUIRE(luaInstance.GetGlobal("test_Test") == Nz::LuaType_Function); luaInstance.Call(0); } AND_THEN("With a subclass") { inheritTest.Reset("InheritTest"); inheritTest.Inherit(test); inheritTest.BindDefaultConstructor(); inheritTest.Register(luaInstance); luaInstance.PushFunction([=](Nz::LuaState& state) -> int { int argIndex = 1; LuaClass_InheritTest result = state.Check(&argIndex); CHECK(result.GetI() == 8); CHECK(result.GetJ()); return 1; }); luaInstance.SetGlobal("CheckInheritTest"); REQUIRE(luaInstance.ExecuteFromFile("resources/Engine/Lua/LuaClass.lua")); REQUIRE(luaInstance.GetGlobal("test_InheritTest") == Nz::LuaType_Function); luaInstance.Call(0); } } WHEN("We bind the object with Handle") { int defaultValue = 5; testHandle.Reset("TestHandle"); testHandle.BindMethod("IsValid", &TestHandle::IsValid); testHandle.BindMethod("GetI", &LuaClass_TestWithHandle::GetI); testHandle.BindMethod("GetDefault", &LuaClass_TestWithHandle::GetDefault, defaultValue); testHandle.Register(luaInstance); THEN("We can ensure the following properties") { luaInstance.PushFunction([=](Nz::LuaState& state) -> int { int argIndex = 1; TestHandle result = state.Check(&argIndex); CHECK(result->GetI() == 8); CHECK(result->GetDefault() == defaultValue); return 1; }); luaInstance.SetGlobal("CheckTestHandle"); REQUIRE(luaInstance.ExecuteFromFile("resources/Engine/Lua/LuaClass.lua")); REQUIRE(luaInstance.GetGlobal("test_TestHandle") == Nz::LuaType_Function); luaInstance.Call(0); } } } }