// https://github.com/vinniefalco/LuaBridge
// Copyright 2019, Dmitry Tarakanov
// SPDX-License-Identifier: MIT
#include "TestBase.h"
#include "LuaBridge/UnorderedMap.h"
#include <unordered_map>
struct UnorderedMapTests : TestBase
{
};
namespace {
struct Data
{
/* explicit */ Data(int i) : i(i) {}
int i;
};
} // namespace
namespace std {
template<>
struct hash<Data>
{
size_t operator()(const Data& value) const noexcept
{
return 0; // Don't care about hash collisions
}
};
template<>
struct hash<::luabridge::LuaRef>
{
size_t operator()(const ::luabridge::LuaRef& value) const
{
return 0; // Don't care about hash collisions
}
};
} // namespace std
TEST_F(UnorderedMapTests, LuaRef)
{
{
runLua("result = {[false] = true, a = 'abc', [1] = 5, [3.14] = -1.1}");
using Map = std::unordered_map<luabridge::LuaRef, luabridge::LuaRef>;
Map expected{
{luabridge::LuaRef(L, false), luabridge::LuaRef(L, true)},
{luabridge::LuaRef(L, 'a'), luabridge::LuaRef(L, "abc")},
{luabridge::LuaRef(L, 1), luabridge::LuaRef(L, 5)},
{luabridge::LuaRef(L, 3.14), luabridge::LuaRef(L, -1.1)},
};
Map actual = result();
ASSERT_EQ(expected, actual);
ASSERT_EQ(expected, result<Map>());
}
{
runLua("result = {'a', 'b', 'c'}");
using Int2Char = std::unordered_map<int, char>;
Int2Char expected{{1, 'a'}, {2, 'b'}, {3, 'c'}};
Int2Char actual = result();
ASSERT_EQ(expected, actual);
ASSERT_EQ(expected, result<Int2Char>());
}
}
TEST_F(UnorderedMapTests, PassToFunction)
{
runLua("function foo (map) "
" result = map "
"end");
auto foo = luabridge::getGlobal(L, "foo");
using Int2Bool = std::unordered_map<int, bool>;
resetResult();
Int2Bool lvalue{{10, false}, {20, true}, {30, true}};
foo(lvalue);
ASSERT_TRUE(result().isTable());
ASSERT_EQ(lvalue, result<Int2Bool>());
resetResult();
const Int2Bool constLvalue = lvalue;
foo(constLvalue);
ASSERT_TRUE(result().isTable());
ASSERT_EQ(constLvalue, result<Int2Bool>());
}
namespace {
bool operator==(const Data& lhs, const Data& rhs)
{
return lhs.i == rhs.i;
}
bool operator<(const Data& lhs, const Data& rhs)
{
return lhs.i < rhs.i;
}
std::ostream& operator<<(std::ostream& lhs, const Data& rhs)
{
lhs << "{" << rhs.i << "}";
return lhs;
}
std::unordered_map<Data, Data> processValues(const std::unordered_map<Data, Data>& data)
{
return data;
}
std::unordered_map<Data, Data> processPointers(const std::unordered_map<Data, const Data*>& data)
{
std::unordered_map<Data, Data> result;
for (const auto& item : data)
{
result.emplace(item.first, *item.second);
}
return result;
}
} // namespace
TEST_F(UnorderedMapTests, PassFromLua)
{
luabridge::getGlobalNamespace(L)
.beginClass<Data>("Data")
.addConstructor<void (*)(int)>()
.endClass()
.addFunction("processValues", &processValues)
.addFunction("processPointers", &processPointers);
{
resetResult();
runLua("result = processValues ({[Data (-1)] = Data (2)})");
std::unordered_map<Data, Data> expected{{Data(-1), Data(2)}};
const auto actual = result<std::unordered_map<Data, Data>>();
ASSERT_EQ(expected, actual);
}
{
resetResult();
runLua("result = processPointers ({[Data (3)] = Data (-4)})");
std::unordered_map<Data, Data> expected{{Data(3), Data(-4)}};
const auto actual = result<std::unordered_map<Data, Data>>();
ASSERT_EQ(expected, actual);
}
}