summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/sol2/test_containers.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/sol2/test_containers.cpp')
-rw-r--r--3rdparty/sol2/test_containers.cpp310
1 files changed, 310 insertions, 0 deletions
diff --git a/3rdparty/sol2/test_containers.cpp b/3rdparty/sol2/test_containers.cpp
new file mode 100644
index 00000000000..015fbd20db0
--- /dev/null
+++ b/3rdparty/sol2/test_containers.cpp
@@ -0,0 +1,310 @@
+#define SOL_CHECK_ARGUMENTS
+
+#include <sol.hpp>
+#include <catch.hpp>
+
+#include <iterator>
+#include <vector>
+#include <list>
+#include <map>
+#include <unordered_map>
+#include <set>
+#include <unordered_set>
+
+std::vector<int> test_table_return_one() {
+ return{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+}
+
+std::vector<std::pair<std::string, int>> test_table_return_two() {
+ return{ { "one", 1 },{ "two", 2 },{ "three", 3 } };
+}
+
+std::map<std::string, std::string> test_table_return_three() {
+ return{ { "name", "Rapptz" },{ "friend", "ThePhD" },{ "project", "sol" } };
+}
+
+TEST_CASE("containers/returns", "make sure that even references to vectors are being serialized as tables") {
+ sol::state lua;
+ std::vector<int> v{ 1, 2, 3 };
+ lua.set_function("f", [&]() -> std::vector<int>& {
+ return v;
+ });
+ lua.script("x = f()");
+ sol::object x = lua["x"];
+ sol::type xt = x.get_type();
+ REQUIRE(xt == sol::type::userdata);
+ sol::table t = x;
+ bool matching;
+ matching = t[1] == 1;
+ REQUIRE(matching);
+ matching = t[2] == 2;
+ REQUIRE(matching);
+ matching = t[3] == 3;
+ REQUIRE(matching);
+}
+
+TEST_CASE("containers/vector_roundtrip", "make sure vectors can be round-tripped") {
+ sol::state lua;
+ std::vector<int> v{ 1, 2, 3 };
+ lua.set_function("f", [&]() -> std::vector<int>& {
+ return v;
+ });
+ lua.script("x = f()");
+ std::vector<int> x = lua["x"];
+ bool areequal = x == v;
+ REQUIRE(areequal);
+}
+
+TEST_CASE("containers/list_roundtrip", "make sure lists can be round-tripped") {
+ sol::state lua;
+ std::list<int> v{ 1, 2, 3 };
+ lua.set_function("f", [&]() -> std::list<int>& {
+ return v;
+ });
+ lua.script("x = f()");
+ std::list <int> x = lua["x"];
+ bool areequal = x == v;
+ REQUIRE(areequal);
+}
+
+TEST_CASE("containers/map_roundtrip", "make sure maps can be round-tripped") {
+ sol::state lua;
+ std::map<std::string, int> v{ { "a", 1 },{ "b", 2 },{ "c", 3 } };
+ lua.set_function("f", [&]() -> std::map<std::string, int>& {
+ return v;
+ });
+ lua.script("x = f()");
+ std::map<std::string, int> x = lua["x"];
+ bool areequal = x == v;
+ REQUIRE(areequal);
+}
+
+TEST_CASE("containers/unordered_map_roundtrip", "make sure unordered_maps can be round-tripped") {
+ sol::state lua;
+ std::unordered_map<std::string, int> v{ { "a", 1 },{ "b", 2 },{ "c", 3 } };
+ lua.set_function("f", [&]() -> std::unordered_map<std::string, int>& {
+ return v;
+ });
+ lua.script("x = f()");
+ std::unordered_map<std::string, int> x = lua["x"];
+ bool areequal = x == v;
+ REQUIRE(areequal);
+}
+
+TEST_CASE("containers/unordered_set_roundtrip", "make sure unordered_sets can be round-tripped") {
+ sol::state lua;
+ std::unordered_set<int> v{ 1, 2, 3 };
+ lua.set_function("f", [&]() -> std::unordered_set<int>& {
+ return v;
+ });
+ lua.script("x = f()");
+ std::unordered_set<int> x = lua["x"];
+ bool areequal = x == v;
+ REQUIRE(areequal);
+}
+
+TEST_CASE("containers/set_roundtrip", "make sure sets can be round-tripped") {
+ sol::state lua;
+ std::set<int> v{ 1, 2, 3 };
+ lua.set_function("f", [&]() -> std::set<int>& {
+ return v;
+ });
+ lua.script("x = f()");
+ std::set<int> x = lua["x"];
+ bool areequal = x == v;
+ REQUIRE(areequal);
+}
+
+TEST_CASE("containers/custom-usertype", "make sure container usertype metatables can be overridden") {
+ typedef std::unordered_map<int, int> bark;
+
+ sol::state lua;
+ lua.open_libraries();
+ lua.new_usertype<bark>("bark",
+ "something", [](const bark& b) {
+ INFO("It works: " << b.at(24));
+ },
+ "size", &bark::size,
+ "at", sol::resolve<const int&>(&bark::at),
+ "clear", &bark::clear
+ );
+ bark obj{ { 24, 50 } };
+ lua.set("a", &obj);
+ REQUIRE_NOTHROW(lua.script("assert(a:at(24) == 50)"));
+ REQUIRE_NOTHROW(lua.script("a:something()"));
+ lua.set("a", obj);
+ REQUIRE_NOTHROW(lua.script("assert(a:at(24) == 50)"));
+ REQUIRE_NOTHROW(lua.script("a:something()"));
+}
+
+TEST_CASE("containers/const-serialization-kvp", "make sure const keys / values are respected") {
+ typedef std::map<int, const int> bark;
+
+ sol::state lua;
+ lua.open_libraries();
+ bark obj{ { 24, 50 } };
+ lua.set("a", &obj);
+ REQUIRE_NOTHROW(lua.script("assert(a[24] == 50)"));
+ REQUIRE_THROWS(lua.script("a[24] = 51"));
+ REQUIRE_NOTHROW(lua.script("assert(a[24] == 50)"));
+}
+
+TEST_CASE("containers/basic-serialization", "make sure containers are turned into proper userdata and have basic hooks established") {
+ typedef std::vector<int> woof;
+ sol::state lua;
+ lua.open_libraries();
+ lua.set("b", woof{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 });
+ REQUIRE_NOTHROW(
+ lua.script("for k = 1, #b do assert(k == b[k]) end");
+ );
+ woof w{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 };
+ lua.set("b", w);
+ REQUIRE_NOTHROW(
+ lua.script("for k = 1, #b do assert(k == b[k]) end");
+ );
+ lua.set("b", &w);
+ REQUIRE_NOTHROW(
+ lua.script("for k = 1, #b do assert(k == b[k]) end");
+ );
+ lua.set("b", std::ref(w));
+ REQUIRE_NOTHROW(
+ lua.script("for k = 1, #b do assert(k == b[k]) end");
+ );
+}
+
+#if 0 // glibc is a fuccboi
+TEST_CASE("containers/const-serialization", "make sure containers are turned into proper userdata and the basic hooks respect const-ness") {
+ typedef std::vector<const int> woof;
+ sol::state lua;
+ lua.open_libraries();
+ lua.set("b", woof{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 });
+ REQUIRE_NOTHROW(
+ lua.script("for k, v in pairs(b) do assert(k == v) end");
+ );
+ REQUIRE_THROWS(lua.script("b[1] = 20"));
+}
+#endif // Fuck you, glibc
+
+TEST_CASE("containers/table-serialization", "ensure types can be serialized as tables still") {
+ typedef std::vector<int> woof;
+ sol::state lua;
+ lua.open_libraries();
+ lua.set("b", sol::as_table(woof{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 }));
+ REQUIRE_NOTHROW(
+ lua.script("for k, v in ipairs(b) do assert(k == v) end");
+ );
+ woof w{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 };
+ lua.set("b", sol::as_table(w));
+ REQUIRE_NOTHROW(
+ lua.script("for k, v in ipairs(b) do assert(k == v) end");
+ );
+ lua.set("b", sol::as_table(&w));
+ REQUIRE_NOTHROW(
+ lua.script("for k, v in ipairs(b) do assert(k == v) end");
+ );
+ lua.set("b", sol::as_table(std::ref(w)));
+ REQUIRE_NOTHROW(
+ lua.script("for k, v in ipairs(b) do assert(k == v) end");
+ );
+}
+
+TEST_CASE("containers/const-correctness", "usertype metatable names should reasonably ignore const attributes") {
+ struct Vec {
+ int x, y, z;
+ };
+
+ sol::state lua;
+ lua.open_libraries(sol::lib::base);
+ lua.new_usertype<Vec>("Vec", "x", &Vec::x, "y", &Vec::y, "z", &Vec::z);
+
+ Vec vec;
+ vec.x = 1;
+ vec.y = 2;
+ vec.z = -3;
+
+ std::vector<Vec> foo;
+ foo.push_back(vec);
+
+ std::vector<Vec const *> bar;
+ bar.push_back(&vec);
+
+ lua.script(R"(
+func = function(vecs)
+ for i = 1, #vecs do
+ vec = vecs[i]
+ print(i, ":", vec.x, vec.y, vec.z)
+ end
+end
+)");
+
+ REQUIRE_NOTHROW({
+ lua["func"](foo);
+ lua["func"](bar);
+ });
+}
+
+TEST_CASE("containers/arbitrary-creation", "userdata and tables should be usable 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')"));
+
+ sol::table a = lua.get<sol::table>("a");
+ sol::table b = lua.get<sol::table>("b");
+ sol::table c = lua.get<sol::table>("c");
+
+ REQUIRE(a.size() == 10ULL);
+ REQUIRE(a.get<int>(3) == 3);
+ REQUIRE(b.get<int>("one") == 1);
+ REQUIRE(b.get<int>("three") == 3);
+ REQUIRE(c.get<std::string>("name") == "Rapptz");
+ REQUIRE(c.get<std::string>("project") == "sol");
+}
+
+TEST_CASE("containers/usertype-transparency", "Make sure containers pass their arguments through transparently and push the results as references, not new values") {
+ class A {
+ public:
+ int a;
+ A(int b = 2) : a(b) {};
+
+ void func() { }
+ };
+
+ struct B {
+
+ B() {
+ for (std::size_t i = 0; i < 20; ++i) {
+ a_list.emplace_back(static_cast<int>(i));
+ }
+ }
+
+ std::vector<A> a_list;
+ };
+
+ sol::state lua;
+ lua.new_usertype<B>("B",
+ "a_list", &B::a_list
+ );
+
+ lua.script(R"(
+b = B.new()
+a_ref = b.a_list[2]
+)");
+
+ B& b = lua["b"];
+ A& a_ref = lua["a_ref"];
+ REQUIRE(&b.a_list[1] == &a_ref);
+ REQUIRE(b.a_list[1].a == a_ref.a);
+}