// https://github.com/vinniefalco/LuaBridge
// Copyright 2019, Dmitry Tarakanov
// SPDX-License-Identifier: MIT
#include "TestBase.h"
struct IssueTests : TestBase
{
};
struct AbstractClass
{
virtual int sum(int a, int b) = 0;
};
struct ConcreteClass : AbstractClass
{
int sum(int a, int b) override { return a + b; }
static AbstractClass& get()
{
static ConcreteClass instance;
return instance;
}
};
TEST_F(IssueTests, Issue87)
{
luabridge::getGlobalNamespace(L)
.beginClass<AbstractClass>("Class")
.addFunction("sum", &AbstractClass::sum)
.endClass()
.addFunction("getAbstractClass", &ConcreteClass::get);
runLua("result = getAbstractClass ():sum (1, 2)");
ASSERT_TRUE(result().isNumber());
ASSERT_EQ(3, result<int>());
}
TEST_F(IssueTests, Issue121)
{
runLua(R"(
first = {
second = {
actual = "data"
}
}
)");
auto first = luabridge::getGlobal(L, "first");
ASSERT_TRUE(first.isTable());
ASSERT_EQ(0, first.length());
ASSERT_TRUE(first["second"].isTable());
ASSERT_EQ(0, first["second"].length());
}
void pushArgs(lua_State*)
{
}
template<class Arg, class... Args>
void pushArgs(lua_State* L, Arg arg, Args... args)
{
luabridge::Stack<Arg>::push(L, arg);
pushArgs(L, args...);
}
template<class... Args>
std::vector<luabridge::LuaRef> callFunction(const luabridge::LuaRef& function, Args... args)
{
assert(function.isFunction());
lua_State* L = function.state();
int originalTop = lua_gettop(L);
function.push(L);
pushArgs(L, args...);
luabridge::LuaException::pcall(L, sizeof...(args), LUA_MULTRET);
std::vector<luabridge::LuaRef> results;
int top = lua_gettop(L);
results.reserve(top - originalTop);
for (int i = originalTop + 1; i <= top; ++i)
{
results.push_back(luabridge::LuaRef::fromStack(L, i));
}
return results;
}
TEST_F(IssueTests, Issue160)
{
runLua("function isConnected (arg1, arg2) "
" return 1, 'srvname', 'ip:10.0.0.1', arg1, arg2 "
"end");
luabridge::LuaRef f_isConnected = luabridge::getGlobal(L, "isConnected");
auto v = callFunction(f_isConnected, 2, "abc");
ASSERT_EQ(5u, v.size());
ASSERT_EQ(1, v[0].cast<int>());
ASSERT_EQ("srvname", v[1].cast<std::string>());
ASSERT_EQ("ip:10.0.0.1", v[2].cast<std::string>());
ASSERT_EQ(2, v[3].cast<int>());
ASSERT_EQ("abc", v[4].cast<std::string>());
}
struct Vector
{
float getX() const { return x; }
float x = 0;
};
struct WideVector : Vector
{
WideVector(float, float, float, float w) { x = w; }
};
TEST_F(IssueTests, Issue178)
{
luabridge::getGlobalNamespace(L)
.beginClass<Vector>("Vector")
.addFunction("getX", &Vector::getX)
.addProperty("X", &Vector::getX)
.addData("x", &Vector::x, true)
.endClass()
.deriveClass<WideVector, Vector>("WideVector")
.addConstructor<void (*)(float, float, float, float)>()
.endClass();
runLua("result = WideVector (0, 1, 2, 3).x");
ASSERT_TRUE(result().isNumber());
ASSERT_EQ(3.f, result<float>());
}
enum class MyEnum
{
VALUE0,
VALUE1,
};
template<typename T>
struct EnumWrapper
{
static typename std::enable_if<std::is_enum<T>::value, void>::type push(lua_State* L, T value)
{
lua_pushnumber(L, static_cast<std::size_t>(value));
}
static typename std::enable_if<std::is_enum<T>::value, T>::type get(lua_State* L, int index)
{
return static_cast<T>(lua_tointeger(L, index));
}
};
namespace luabridge {
template<>
struct Stack<MyEnum> : EnumWrapper<MyEnum>
{
};
} // namespace luabridge
TEST_F(IssueTests, Issue127)
{
runLua("result = 1");
ASSERT_EQ(MyEnum::VALUE1, result<MyEnum>());
}