summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/sol2/test_usertypes.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/sol2/test_usertypes.cpp')
-rw-r--r--3rdparty/sol2/test_usertypes.cpp1494
1 files changed, 0 insertions, 1494 deletions
diff --git a/3rdparty/sol2/test_usertypes.cpp b/3rdparty/sol2/test_usertypes.cpp
deleted file mode 100644
index 60adc73017c..00000000000
--- a/3rdparty/sol2/test_usertypes.cpp
+++ /dev/null
@@ -1,1494 +0,0 @@
-#define SOL_CHECK_ARGUMENTS
-
-#include <sol.hpp>
-#include <catch.hpp>
-
-#include <iostream>
-#include <list>
-#include <memory>
-#include <mutex>
-
-struct vars {
- vars() {
-
- }
-
- int boop = 0;
-
- ~vars() {
-
- }
-};
-
-struct fuser {
- int x;
- fuser() : x(0) {}
-
- fuser(int x) : x(x) {}
-
- int add(int y) {
- return x + y;
- }
-
- int add2(int y) {
- return x + y + 2;
- }
-};
-
-namespace crapola {
- struct fuser {
- int x;
- fuser() : x(0) {}
- fuser(int x) : x(x) {}
- fuser(int x, int x2) : x(x * x2) {}
-
- int add(int y) {
- return x + y;
- }
- int add2(int y) {
- return x + y + 2;
- }
- };
-} // crapola
-
-class Base {
-public:
- Base(int a_num) : m_num(a_num) { }
-
- int get_num() {
- return m_num;
- }
-
-protected:
- int m_num;
-};
-
-class Derived : public Base {
-public:
- Derived(int a_num) : Base(a_num) { }
-
- int get_num_10() {
- return 10 * m_num;
- }
-};
-
-class abstract_A {
-public:
- virtual void a() = 0;
-};
-
-class abstract_B : public abstract_A {
-public:
- virtual void a() override {
- INFO("overridden a() in B : public A - BARK");
- }
-};
-
-struct Vec {
- float x, y, z;
- Vec(float x, float y, float z) : x{ x }, y{ y }, z{ z } {}
- float length() {
- return sqrtf(x*x + y*y + z*z);
- }
- Vec normalized() {
- float invS = 1 / length();
- return{ x * invS, y * invS, z * invS };
- }
-};
-
-struct giver {
- int a = 0;
-
- giver() {
-
- }
-
- void gief() {
- a = 1;
- }
-
- static void stuff() {
-
- }
-
- static void gief_stuff(giver& t, int a) {
- t.a = a;
- }
-
- ~giver() {
-
- }
-
-};
-
-struct factory_test {
-private:
- factory_test() { a = true_a; }
- ~factory_test() { a = 0; }
-public:
- static int num_saved;
- static int num_killed;
-
- struct deleter {
- void operator()(factory_test* f) {
- f->~factory_test();
- }
- };
-
- static const int true_a;
- int a;
-
- static std::unique_ptr<factory_test, deleter> make() {
- return std::unique_ptr<factory_test, deleter>(new factory_test(), deleter());
- }
-
- static void save(factory_test& f) {
- new(&f)factory_test();
- ++num_saved;
- }
-
- static void kill(factory_test& f) {
- f.~factory_test();
- ++num_killed;
- }
-};
-
-int factory_test::num_saved = 0;
-int factory_test::num_killed = 0;
-const int factory_test::true_a = 156;
-
-bool something() {
- return true;
-}
-
-struct thing {
- int v = 100;
-
- thing() {}
- thing(int x) : v(x) {}
-};
-
-struct self_test {
- int bark;
-
- self_test() : bark(100) {
-
- }
-
- void g(const std::string& str) {
- std::cout << str << '\n';
- bark += 1;
- }
-
- void f(const self_test& t) {
- std::cout << "got test" << '\n';
- if (t.bark != bark)
- throw sol::error("bark values are not the same for self_test f function");
- if (&t != this)
- throw sol::error("call does not reference self for self_test f function");
- }
-};
-
-struct ext_getset {
-
- int bark = 24;
- const int meow = 56;
-
- ext_getset() = default;
- ext_getset(int v) : bark(v) {}
- ext_getset(ext_getset&&) = default;
- ext_getset(const ext_getset&) = delete;
- ext_getset& operator=(ext_getset&&) = default;
- ext_getset& operator=(const ext_getset&) = delete;
- ~ext_getset() {
-
- }
-
- std::string x() {
- return "bark bark bark";
- }
-
- int x2(std::string x) {
- return static_cast<int>(x.length());
- }
-
- void set(sol::variadic_args, sol::this_state, int x) {
- bark = x;
- }
-
- int get(sol::this_state, sol::variadic_args) {
- return bark;
- }
-
- static void s_set(int) {
-
- }
-
- static int s_get(int x) {
- return x + 20;
- }
-
-};
-
-template <typename T>
-void des(T& e) {
- e.~T();
-}
-
-struct matrix_xf {
- float a, b;
-
- static matrix_xf from_lua_table(sol::table t) {
- matrix_xf m;
- m.a = t[1][1];
- m.b = t[1][2];
- return m;
- }
-};
-
-struct matrix_xi {
- int a, b;
-
- static matrix_xi from_lua_table(sol::table t) {
- matrix_xi m;
- m.a = t[1][1];
- m.b = t[1][2];
- return m;
- }
-};
-
-TEST_CASE("usertype/usertype", "Show that we can create classes from usertype and use them") {
- sol::state lua;
-
- sol::usertype<fuser> lc{ "add", &fuser::add, "add2", &fuser::add2 };
- lua.set_usertype(lc);
-
- lua.script("a = fuser:new()\n"
- "b = a:add(1)\n"
- "c = a:add2(1)\n");
-
- sol::object a = lua.get<sol::object>("a");
- sol::object b = lua.get<sol::object>("b");
- sol::object c = lua.get<sol::object>("c");
- REQUIRE((a.is<sol::userdata_value>()));
- auto atype = a.get_type();
- auto btype = b.get_type();
- auto ctype = c.get_type();
- REQUIRE((atype == sol::type::userdata));
- REQUIRE((btype == sol::type::number));
- REQUIRE((ctype == sol::type::number));
- int bresult = b.as<int>();
- int cresult = c.as<int>();
- REQUIRE(bresult == 1);
- REQUIRE(cresult == 3);
-}
-
-TEST_CASE("usertype/usertype-constructors", "Show that we can create classes from usertype and use them with multiple constructors") {
-
- sol::state lua;
-
- sol::constructors<sol::types<>, sol::types<int>, sol::types<int, int>> con;
- sol::usertype<crapola::fuser> lc(con, "add", &crapola::fuser::add, "add2", &crapola::fuser::add2);
- lua.set_usertype(lc);
-
- lua.script(
- "a = fuser.new(2)\n"
- "u = a:add(1)\n"
- "v = a:add2(1)\n"
- "b = fuser:new()\n"
- "w = b:add(1)\n"
- "x = b:add2(1)\n"
- "c = fuser.new(2, 3)\n"
- "y = c:add(1)\n"
- "z = c:add2(1)\n");
- sol::object a = lua.get<sol::object>("a");
- auto atype = a.get_type();
- REQUIRE((atype == sol::type::userdata));
- sol::object u = lua.get<sol::object>("u");
- sol::object v = lua.get<sol::object>("v");
- REQUIRE((u.as<int>() == 3));
- REQUIRE((v.as<int>() == 5));
-
- sol::object b = lua.get<sol::object>("b");
- auto btype = b.get_type();
- REQUIRE((btype == sol::type::userdata));
- sol::object w = lua.get<sol::object>("w");
- sol::object x = lua.get<sol::object>("x");
- REQUIRE((w.as<int>() == 1));
- REQUIRE((x.as<int>() == 3));
-
- sol::object c = lua.get<sol::object>("c");
- auto ctype = c.get_type();
- REQUIRE((ctype == sol::type::userdata));
- sol::object y = lua.get<sol::object>("y");
- sol::object z = lua.get<sol::object>("z");
- REQUIRE((y.as<int>() == 7));
- REQUIRE((z.as<int>() == 9));
-}
-
-TEST_CASE("usertype/usertype-utility", "Show internal management of classes registered through new_usertype") {
- sol::state lua;
-
- lua.new_usertype<fuser>("fuser", "add", &fuser::add, "add2", &fuser::add2);
-
- lua.script("a = fuser.new()\n"
- "b = a:add(1)\n"
- "c = a:add2(1)\n");
-
- sol::object a = lua.get<sol::object>("a");
- sol::object b = lua.get<sol::object>("b");
- sol::object c = lua.get<sol::object>("c");
- REQUIRE((a.is<sol::userdata_value>()));
- auto atype = a.get_type();
- auto btype = b.get_type();
- auto ctype = c.get_type();
- REQUIRE((atype == sol::type::userdata));
- REQUIRE((btype == sol::type::number));
- REQUIRE((ctype == sol::type::number));
- int bresult = b.as<int>();
- int cresult = c.as<int>();
- REQUIRE(bresult == 1);
- REQUIRE(cresult == 3);
-}
-
-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<sol::types<int>> basector;
- sol::usertype<Base> baseusertype(basector, "get_num", &Base::get_num);
-
- lua.set_usertype(baseusertype);
-
- lua.script("base = Base.new(5)");
- REQUIRE_NOTHROW(lua.script("print(base:get_num())"));
-
- sol::constructors<sol::types<int>> derivedctor;
- sol::usertype<Derived> derivedusertype(derivedctor,
- "get_num_10", &Derived::get_num_10,
- "get_num", &Derived::get_num
- );
-
- lua.set_usertype(derivedusertype);
-
- lua.script("derived = Derived.new(7)");
- lua.script("dgn = derived:get_num()\n"
- "print(dgn)");
- lua.script("dgn10 = derived:get_num_10()\n"
- "print(dgn10)");
-
- REQUIRE((lua.get<int>("dgn10") == 70));
- REQUIRE((lua.get<int>("dgn") == 7));
-}
-
-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);
-
- lua.new_usertype<self_test>("test", "g", &self_test::g, "f", &self_test::f);
-
- lua.script(
- "local a = test.new()\n"
- "a:g(\"woof\")\n"
- "a:f(a)\n"
- );
-}
-
-TEST_CASE("usertype/issue-number-twenty-five", "Using pointers and references from C++ classes in Lua") {
- struct test {
- int x = 0;
- test& set() {
- x = 10;
- return *this;
- }
-
- int get() {
- return x;
- }
-
- test* pget() {
- return this;
- }
-
- test create_get() {
- return *this;
- }
-
- int fun(int xa) {
- return xa * 10;
- }
- };
-
- sol::state lua;
- lua.open_libraries(sol::lib::base);
- lua.new_usertype<test>("test", "set", &test::set, "get", &test::get, "pointer_get", &test::pget, "fun", &test::fun, "create_get", &test::create_get);
- REQUIRE_NOTHROW(lua.script("x = test.new()"));
- REQUIRE_NOTHROW(lua.script("assert(x:set():get() == 10)"));
- REQUIRE_NOTHROW(lua.script("y = x:pointer_get()"));
- REQUIRE_NOTHROW(lua.script("y:set():get()"));
- REQUIRE_NOTHROW(lua.script("y:fun(10)"));
- REQUIRE_NOTHROW(lua.script("x:fun(10)"));
- REQUIRE_NOTHROW(lua.script("assert(y:fun(10) == x:fun(10), '...')"));
- REQUIRE_NOTHROW(lua.script("assert(y:fun(10) == 100, '...')"));
- REQUIRE_NOTHROW(lua.script("assert(y:set():get() == y:set():get(), '...')"));
- REQUIRE_NOTHROW(lua.script("assert(y:set():get() == 10, '...')"));
-}
-
-TEST_CASE("usertype/issue-number-thirty-five", "using value types created from lua-called C++ code, fixing user-defined types with constructors") {
- sol::state lua;
- lua.open_libraries(sol::lib::base);
-
- sol::constructors<sol::types<float, float, float>> ctor;
- sol::usertype<Vec> udata(ctor, "normalized", &Vec::normalized, "length", &Vec::length);
- lua.set_usertype(udata);
-
- REQUIRE_NOTHROW(lua.script("v = Vec.new(1, 2, 3)\n"
- "print(v:length())"));
- REQUIRE_NOTHROW(lua.script("v = Vec.new(1, 2, 3)\n"
- "print(v:normalized():length())"));
-}
-
-TEST_CASE("usertype/lua-stored-usertype", "ensure usertype values can be stored without keeping usertype object alive") {
- sol::state lua;
- lua.open_libraries(sol::lib::base);
-
- {
- sol::constructors<sol::types<float, float, float>> ctor;
- sol::usertype<Vec> udata(ctor,
- "normalized", &Vec::normalized,
- "length", &Vec::length);
-
- lua.set_usertype(udata);
- // usertype dies, but still usable in lua!
- }
-
- REQUIRE_NOTHROW(lua.script("collectgarbage()\n"
- "v = Vec.new(1, 2, 3)\n"
- "print(v:length())"));
-
- REQUIRE_NOTHROW(lua.script("v = Vec.new(1, 2, 3)\n"
- "print(v:normalized():length())"));
-}
-
-TEST_CASE("usertype/member-variables", "allow table-like accessors to behave as member variables for usertype") {
- sol::state lua;
- lua.open_libraries(sol::lib::base);
- sol::constructors<sol::types<float, float, float>> ctor;
- sol::usertype<Vec> udata(ctor,
- "x", &Vec::x,
- "y", &Vec::y,
- "z", &Vec::z,
- "normalized", &Vec::normalized,
- "length", &Vec::length);
- lua.set_usertype(udata);
-
- REQUIRE_NOTHROW(lua.script("v = Vec.new(1, 2, 3)\n"
- "v2 = Vec.new(0, 1, 0)\n"
- "print(v:length())\n"
- ));
- REQUIRE_NOTHROW(lua.script("v.x = 2\n"
- "v2.y = 2\n"
- "print(v.x, v.y, v.z)\n"
- "print(v2.x, v2.y, v2.z)\n"
- ));
- REQUIRE_NOTHROW(lua.script("assert(v.x == 2)\n"
- "assert(v2.x == 0)\n"
- "assert(v2.y == 2)\n"
- ));
- REQUIRE_NOTHROW(lua.script("v.x = 3\n"
- "local x = v.x\n"
- "assert(x == 3)\n"
- ));
-
- struct breaks {
- sol::function f;
- };
-
- lua.open_libraries(sol::lib::base);
- lua.set("b", breaks());
- lua.new_usertype<breaks>("breaks",
- "f", &breaks::f
- );
-
- breaks& b = lua["b"];
- REQUIRE_NOTHROW(lua.script("b.f = function () print('BARK!') end"));
- REQUIRE_NOTHROW(lua.script("b.f()"));
- REQUIRE_NOTHROW(b.f());
-}
-
-TEST_CASE("usertype/nonmember-functions", "let users set non-member functions that take unqualified T as first parameter to usertype") {
- sol::state lua;
- lua.open_libraries(sol::lib::base);
-
- lua.new_usertype<giver>("giver",
- "gief_stuff", giver::gief_stuff,
- "gief", &giver::gief,
- "__tostring", [](const giver& t) {
- return std::to_string(t.a) + ": giving value";
- }
- ).get<sol::table>("giver")
- .set_function("stuff", giver::stuff);
-
- REQUIRE_NOTHROW(lua.script("giver.stuff()"));
- REQUIRE_NOTHROW(lua.script("t = giver.new()\n"
- "print(tostring(t))\n"
- "t:gief()\n"
- "t:gief_stuff(20)\n"));
- giver& g = lua.get<giver>("t");
- REQUIRE(g.a == 20);
-}
-
-TEST_CASE("usertype/unique-shared-ptr", "manage the conversion and use of unique and shared pointers ('unique usertypes')") {
- const int64_t unique_value = 0x7125679355635963;
- auto uniqueint = std::make_unique<int64_t>(unique_value);
- auto sharedint = std::make_shared<int64_t>(unique_value);
- long preusecount = sharedint.use_count();
- { sol::state lua;
- lua.open_libraries(sol::lib::base);
- lua.set("uniqueint", std::move(uniqueint));
- lua.set("sharedint", sharedint);
- std::unique_ptr<int64_t>& uniqueintref = lua["uniqueint"];
- std::shared_ptr<int64_t>& sharedintref = lua["sharedint"];
- int64_t* rawuniqueintref = lua["uniqueint"];
- int64_t* rawsharedintref = lua["sharedint"];
- int siusecount = sharedintref.use_count();
- REQUIRE((uniqueintref.get() == rawuniqueintref && sharedintref.get() == rawsharedintref));
- REQUIRE((uniqueintref != nullptr && sharedintref != nullptr && rawuniqueintref != nullptr && rawsharedintref != nullptr));
- REQUIRE((unique_value == *uniqueintref.get() && unique_value == *sharedintref.get()));
- REQUIRE((unique_value == *rawuniqueintref && unique_value == *rawsharedintref));
- REQUIRE(siusecount == sharedint.use_count());
- std::shared_ptr<int64_t> moreref = sharedint;
- REQUIRE(unique_value == *moreref.get());
- REQUIRE(moreref.use_count() == sharedint.use_count());
- REQUIRE(moreref.use_count() == sharedintref.use_count());
- }
- REQUIRE(preusecount == sharedint.use_count());
-}
-
-TEST_CASE("regressions/one", "issue number 48") {
- sol::state lua;
- lua.new_usertype<vars>("vars",
- "boop", &vars::boop);
- REQUIRE_NOTHROW(lua.script("beep = vars.new()\n"
- "beep.boop = 1"));
- // test for segfault
- auto my_var = lua.get<vars>("beep");
- REQUIRE(my_var.boop == 1);
- auto* ptr = &my_var;
- REQUIRE(ptr->boop == 1);
-}
-
-TEST_CASE("usertype/get-set-references", "properly get and set with std::ref semantics. Note that to get, we must not use Unqualified<T> on the type...") {
- sol::state lua;
-
- lua.new_usertype<vars>("vars",
- "boop", &vars::boop);
- vars var{};
- vars rvar{};
- lua.set("beep", var);
- lua.set("rbeep", std::ref(rvar));
- auto& my_var = lua.get<vars>("beep");
- auto& ref_var = lua.get<std::reference_wrapper<vars>>("rbeep");
- vars& proxy_my_var = lua["beep"];
- std::reference_wrapper<vars> proxy_ref_var = lua["rbeep"];
- var.boop = 2;
- rvar.boop = 5;
-
- // Was return as a value: var must be diferent from "beep"
- REQUIRE_FALSE(std::addressof(var) == std::addressof(my_var));
- REQUIRE_FALSE(std::addressof(proxy_my_var) == std::addressof(var));
- REQUIRE((my_var.boop == 0));
- REQUIRE(var.boop != my_var.boop);
-
- REQUIRE(std::addressof(ref_var) == std::addressof(rvar));
- REQUIRE(std::addressof(proxy_ref_var.get()) == std::addressof(rvar));
- REQUIRE(rvar.boop == 5);
- REQUIRE(rvar.boop == ref_var.boop);
-}
-
-TEST_CASE("usertype/destructor-tests", "Show that proper copies / destruction happens") {
- static int created = 0;
- static int destroyed = 0;
- static void* last_call = nullptr;
- struct x {
- x() { ++created; }
- x(const x&) { ++created; }
- x(x&&) { ++created; }
- x& operator=(const x&) { return *this; }
- x& operator=(x&&) { return *this; }
- ~x() { ++destroyed; }
- };
- {
- sol::state lua;
- lua.new_usertype<x>("x");
- x x1;
- x x2;
- lua.set("x1copy", x1, "x2copy", x2, "x1ref", std::ref(x1));
- x& x1copyref = lua["x1copy"];
- x& x2copyref = lua["x2copy"];
- x& x1ref = lua["x1ref"];
- REQUIRE(created == 4);
- REQUIRE(destroyed == 0);
- REQUIRE(std::addressof(x1) == std::addressof(x1ref));
- REQUIRE(std::addressof(x1copyref) != std::addressof(x1));
- REQUIRE(std::addressof(x2copyref) != std::addressof(x2));
- }
- REQUIRE(created == 4);
- REQUIRE(destroyed == 4);
-}
-
-TEST_CASE("usertype/private-constructible", "Check to make sure special snowflake types from Enterprise thingamahjongs work properly.") {
- int numsaved = factory_test::num_saved;
- int numkilled = factory_test::num_killed;
- {
- sol::state lua;
- lua.open_libraries(sol::lib::base);
-
- lua.new_usertype<factory_test>("factory_test",
- "new", sol::initializers(factory_test::save),
- "__gc", sol::destructor(factory_test::kill),
- "a", &factory_test::a
- );
-
- std::unique_ptr<factory_test, factory_test::deleter> f = factory_test::make();
- lua.set("true_a", factory_test::true_a, "f", f.get());
- REQUIRE_NOTHROW(lua.script("assert(f.a == true_a)"));
-
- REQUIRE_NOTHROW(lua.script(
- "local fresh_f = factory_test:new()\n"
- "assert(fresh_f.a == true_a)\n"));
- }
- int expectednumsaved = numsaved + 1;
- int expectednumkilled = numkilled + 1;
- REQUIRE(expectednumsaved == factory_test::num_saved);
- REQUIRE(expectednumkilled == factory_test::num_killed);
-}
-
-TEST_CASE("usertype/const-pointer", "Make sure const pointers can be taken") {
- struct A { int x = 201; };
- struct B {
- int foo(const A* a) { return a->x; };
- };
-
- sol::state lua;
- lua.new_usertype<B>("B",
- "foo", &B::foo
- );
- lua.set("a", A());
- lua.set("b", B());
- lua.script("x = b:foo(a)");
- int x = lua["x"];
- REQUIRE(x == 201);
-}
-
-TEST_CASE("usertype/overloading", "Check if overloading works properly for usertypes") {
- struct woof {
- int var;
-
- int func(int x) {
- return var + x;
- }
-
- double func2(int x, int y) {
- return var + x + y + 0.5;
- }
-
- std::string func2s(int x, std::string y) {
- return y + " " + std::to_string(x);
- }
- };
- sol::state lua;
- lua.open_libraries(sol::lib::base);
-
- lua.new_usertype<woof>("woof",
- "var", &woof::var,
- "func", sol::overload(&woof::func, &woof::func2, &woof::func2s)
- );
-
- const std::string bark_58 = "bark 58";
-
- REQUIRE_NOTHROW(lua.script(
- "r = woof:new()\n"
- "a = r:func(1)\n"
- "b = r:func(1, 2)\n"
- "c = r:func(58, 'bark')\n"
- ));
- REQUIRE((lua["a"] == 1));
- REQUIRE((lua["b"] == 3.5));
- REQUIRE((lua["c"] == bark_58));
-
- REQUIRE_THROWS(lua.script("r:func(1,2,'meow')"));
-}
-
-TEST_CASE("usertype/overloading_values", "ensure overloads handle properly") {
- struct overloading_test {
- int print(int i) { INFO("Integer print: " << i); return 500 + i; }
- int print() { INFO("No param print."); return 500; }
- };
-
- sol::state lua;
- lua.new_usertype<overloading_test>("overloading_test", sol::constructors<>(),
- "print", sol::overload(static_cast<int (overloading_test::*)(int)>(&overloading_test::print), static_cast<int (overloading_test::*)()>(&overloading_test::print)),
- "print2", sol::overload(static_cast<int (overloading_test::*)()>(&overloading_test::print), static_cast<int (overloading_test::*)(int)>(&overloading_test::print))
- );
- lua.set("test", overloading_test());
-
- sol::function f0_0 = lua.load("return test:print()");
- sol::function f0_1 = lua.load("return test:print2()");
- sol::function f1_0 = lua.load("return test:print(24)");
- sol::function f1_1 = lua.load("return test:print2(24)");
- int res = f0_0();
- int res2 = f0_1();
- int res3 = f1_0();
- int res4 = f1_1();
-
- REQUIRE(res == 500);
- REQUIRE(res2 == 500);
-
- REQUIRE(res3 == 524);
- REQUIRE(res4 == 524);
-}
-
-TEST_CASE("usertype/reference-and-constness", "Make sure constness compiles properly and errors out at runtime") {
- struct bark {
- int var = 50;
- };
- struct woof {
- bark b;
- };
-
- struct nested {
- const int f = 25;
- };
-
- struct outer {
- nested n;
- };
-
- sol::state lua;
- lua.new_usertype<woof>("woof",
- "b", &woof::b);
- lua.new_usertype<bark>("bark",
- "var", &bark::var);
- lua.new_usertype<outer>("outer",
- "n", &outer::n);
- lua.set("w", woof());
- lua.set("n", nested());
- lua.set("o", outer());
- lua.set("f", sol::c_call<decltype(&nested::f), &nested::f>);
- lua.script(R"(
- x = w.b
- x.var = 20
- val = w.b.var == x.var
- v = f(n);
- )");
-
- woof& w = lua["w"];
- bark& x = lua["x"];
- nested& n = lua["n"];
- int v = lua["v"];
- bool val = lua["val"];
- // enforce reference semantics
- REQUIRE(std::addressof(w.b) == std::addressof(x));
- REQUIRE(n.f == 25);
- REQUIRE(v == 25);
- REQUIRE(val);
-
- REQUIRE_THROWS(lua.script("f(n, 50)"));
- REQUIRE_THROWS(lua.script("o.n = 25"));
-}
-
-TEST_CASE("usertype/readonly-and-static-functions", "Check if static functions can be called on userdata and from their originating (meta)tables") {
- struct bark {
- int var = 50;
-
- void func() {}
-
- static void oh_boy() {}
-
- static int oh_boy(std::string name) {
- return static_cast<int>(name.length());
- }
-
- int operator()(int x) {
- return x;
- }
- };
-
- sol::state lua;
- lua.open_libraries(sol::lib::base);
- lua.new_usertype<bark>("bark",
- "var", &bark::var,
- "var2", sol::readonly(&bark::var),
- "something", something,
- "something2", [](int x, int y) { return x + y; },
- "func", &bark::func,
- "oh_boy", sol::overload(sol::resolve<void()>(&bark::oh_boy), sol::resolve<int(std::string)>(&bark::oh_boy)),
- sol::meta_function::call_function, &bark::operator()
- );
-
- REQUIRE_NOTHROW(lua.script("assert(bark.oh_boy('woo') == 3)"));
- REQUIRE_NOTHROW(lua.script("bark.oh_boy()"));
-
- bark b;
- lua.set("b", &b);
-
- sol::table b_table = lua["b"];
- sol::function member_func = b_table["func"];
- sol::function s = b_table["something"];
- sol::function s2 = b_table["something2"];
-
- sol::table b_metatable = b_table[sol::metatable_key];
- bool isvalidmt = b_metatable.valid();
- REQUIRE(isvalidmt);
- sol::function b_call = b_metatable["__call"];
- sol::function b_as_function = lua["b"];
-
- int x = b_as_function(1);
- int y = b_call(b, 1);
- bool z = s();
- int w = s2(2, 3);
- REQUIRE(x == 1);
- REQUIRE(y == 1);
- REQUIRE(z);
- REQUIRE(w == 5);
-
- lua.script(R"(
-lx = b(1)
-ly = getmetatable(b).__call(b, 1)
-lz = b.something()
-lz2 = bark.something()
-lw = b.something2(2, 3)
-lw2 = bark.something2(2, 3)
- )");
-
- int lx = lua["lx"];
- int ly = lua["ly"];
- bool lz = lua["lz"];
- int lw = lua["lw"];
- bool lz2 = lua["lz2"];
- int lw2 = lua["lw2"];
- REQUIRE(lx == 1);
- REQUIRE(ly == 1);
- REQUIRE(lz);
- REQUIRE(lz2);
- REQUIRE(lw == 5);
- REQUIRE(lw2 == 5);
- REQUIRE(lx == ly);
- REQUIRE(lz == lz2);
- REQUIRE(lw == lw2);
-
- REQUIRE_THROWS(lua.script("b.var2 = 2"));
-}
-
-TEST_CASE("usertype/properties", "Check if member properties/variables work") {
- struct bark {
- int var = 50;
- int var2 = 25;
-
- int get_var2() const {
- return var2;
- }
-
- int get_var3() {
- return var2;
- }
-
- void set_var2(int x) {
- var2 = x;
- }
- };
-
- sol::state lua;
- lua.open_libraries(sol::lib::base);
- lua.new_usertype<bark>("bark",
- "var", &bark::var,
- "var2", sol::readonly(&bark::var2),
- "a", sol::property(&bark::get_var2, &bark::set_var2),
- "b", sol::property(&bark::get_var2),
- "c", sol::property(&bark::get_var3),
- "d", sol::property(&bark::set_var2)
- );
-
- bark b;
- lua.set("b", &b);
-
- lua.script("b.a = 59");
- lua.script("var2_0 = b.a");
- lua.script("var2_1 = b.b");
- lua.script("b.d = 1568");
- lua.script("var2_2 = b.c");
-
- int var2_0 = lua["var2_0"];
- int var2_1 = lua["var2_1"];
- int var2_2 = lua["var2_2"];
- REQUIRE(var2_0 == 59);
- REQUIRE(var2_1 == 59);
- REQUIRE(var2_2 == 1568);
-
- REQUIRE_THROWS(lua.script("b.var2 = 24"));
- REQUIRE_THROWS(lua.script("r = b.d"));
- REQUIRE_THROWS(lua.script("r = b.d"));
- REQUIRE_THROWS(lua.script("b.b = 25"));
- REQUIRE_THROWS(lua.script("b.c = 11"));
-}
-
-TEST_CASE("usertype/safety", "crash with an exception -- not a segfault -- on bad userdata calls") {
- class Test {
- public:
- void sayHello() { std::cout << "Hey\n"; }
- };
-
- sol::state lua;
- lua.new_usertype<Test>("Test", "sayHello", &Test::sayHello);
- static const std::string code = R"(
- local t = Test.new()
- t:sayHello() --Works fine
- t.sayHello() --Uh oh.
- )";
- REQUIRE_THROWS(lua.script(code));
-}
-
-TEST_CASE("usertype/call_constructor", "make sure lua types can be constructed with function call constructors") {
- sol::state lua;
- lua.open_libraries(sol::lib::base);
-
- lua.new_usertype<thing>("thing",
- "v", &thing::v
- , sol::call_constructor, sol::constructors<sol::types<>, sol::types<int>>()
- );
-
- lua.script(R"(
-t = thing(256)
-)");
-
- thing& y = lua["t"];
- INFO(y.v);
- REQUIRE(y.v == 256);
-}
-
-TEST_CASE("usertype/call_constructor-factories", "make sure tables can be passed to factory-based call constructors") {
- sol::state lua;
- lua.open_libraries();
-
- lua.new_usertype<matrix_xf>("mat",
- sol::call_constructor, sol::factories(&matrix_xf::from_lua_table)
- );
-
- lua.script("m = mat{ {1.1, 2.2} }");
-
- lua.new_usertype<matrix_xi>("mati",
- sol::call_constructor, sol::factories(&matrix_xi::from_lua_table)
- );
-
- lua.script("mi = mati{ {1, 2} }");
-
- matrix_xf& m = lua["m"];
- REQUIRE(m.a == 1.1f);
- REQUIRE(m.b == 2.2f);
- matrix_xi& mi = lua["mi"];
- REQUIRE(mi.a == 1);
- REQUIRE(mi.b == 2);
-}
-
-TEST_CASE("usertype/call_constructor_2", "prevent metatable regression") {
- class class01 {
- public:
- int x = 57;
- class01() {}
- };
-
- class class02 {
- public:
- int x = 50;
- class02() {}
- class02(const class01& other) : x(other.x) {}
- };
-
- sol::state lua;
-
- lua.new_usertype<class01>("class01",
- sol::call_constructor, sol::constructors<sol::types<>, sol::types<const class01&>>()
- );
-
- lua.new_usertype<class02>("class02",
- sol::call_constructor, sol::constructors<sol::types<>, sol::types<const class02&>, sol::types<const class01&>>()
- );
-
- REQUIRE_NOTHROW(lua.script(R"(
-x = class01()
-y = class02(x)
-)"));
- class02& y = lua["y"];
- REQUIRE(y.x == 57);
-}
-
-TEST_CASE("usertype/blank_constructor", "make sure lua types cannot be constructed if a blank / empty constructor is provided") {
- sol::state lua;
- lua.open_libraries(sol::lib::base);
-
- lua.new_usertype<thing>("thing",
- "v", &thing::v
- , sol::call_constructor, sol::constructors<>()
- );
-
- REQUIRE_THROWS(lua.script("t = thing(256)"));
-}
-
-
-TEST_CASE("usertype/no_constructor", "make sure lua types cannot be constructed if a blank / empty constructor is provided") {
- sol::state lua;
- lua.open_libraries(sol::lib::base);
-
- SECTION("order1")
- {
- lua.new_usertype<thing>("thing",
- "v", &thing::v
- , sol::call_constructor, sol::no_constructor
- );
- REQUIRE_THROWS(lua.script("t = thing.new()"));
- }
-
- SECTION("order2")
- {
- lua.new_usertype<thing>("thing"
- , sol::call_constructor, sol::no_constructor
- , "v", &thing::v
- );
- REQUIRE_THROWS(lua.script("t = thing.new()"));
- }
-
- REQUIRE_THROWS(lua.script("t = thing.new()"));
-}
-
-TEST_CASE("usertype/coverage", "try all the things") {
- sol::state lua;
- lua.open_libraries(sol::lib::base);
-
- lua.new_usertype<ext_getset>("ext_getset",
- sol::call_constructor, sol::constructors<sol::types<>, sol::types<int>>(),
- sol::meta_function::garbage_collect, sol::destructor(des<ext_getset>),
- "x", sol::overload(&ext_getset::x, &ext_getset::x2, [](ext_getset& m, std::string x, int y) {
- return m.meow + 50 + y + x.length();
- }),
- "bark", &ext_getset::bark,
- "meow", &ext_getset::meow,
- "readonlybark", sol::readonly(&ext_getset::bark),
- "set", &ext_getset::set,
- "get", &ext_getset::get,
- "sset", &ext_getset::s_set,
- "sget", &ext_getset::s_get,
- "propbark", sol::property(&ext_getset::set, &ext_getset::get),
- "readonlypropbark", sol::property(&ext_getset::get),
- "writeonlypropbark", sol::property(&ext_getset::set)
- );
-
- INFO("usertype created");
-
- lua.script(R"(
-e = ext_getset()
-w = e:x(e:x(), e:x(e:x()))
-print(w)
-)");
-
- int w = lua["w"];
- REQUIRE(w == (56 + 50 + 14 + 14));
-
- INFO("REQUIRE(w) successful");
-
- lua.script(R"(
-e:set(500)
-e.sset(24)
-x = e:get()
-y = e.sget(20)
-)");
-
- int x = lua["x"];
- int y = lua["y"];
- REQUIRE(x == 500);
- REQUIRE(y == 40);
-
- INFO("REQUIRE(x, y) successful");
-
- lua.script(R"(
-e.bark = 5001
-a = e:get()
-print(e.bark)
-print(a)
-
-e.propbark = 9700
-b = e:get()
-print(e.propbark)
-print(b)
-)");
- int a = lua["a"];
- int b = lua["b"];
-
- REQUIRE(a == 5001);
- REQUIRE(b == 9700);
-
- INFO("REQUIRE(a, b) successful");
-
- lua.script(R"(
-c = e.readonlybark
-d = e.meow
-print(e.readonlybark)
-print(c)
-print(e.meow)
-print(d)
-)");
-
- int c = lua["c"];
- int d = lua["d"];
- REQUIRE(c == 9700);
- REQUIRE(d == 56);
-
- INFO("REQUIRE(c, d) successful");
-
- lua.script(R"(
-e.writeonlypropbark = 500
-z = e.readonlypropbark
-print(e.readonlybark)
-print(e.bark)
-)");
-
- int z = lua["z"];
- REQUIRE(z == 500);
-
- INFO("REQUIRE(z) successful");
-
- REQUIRE_THROWS(lua.script("e.readonlybark = 24"));
- INFO("REQUIRE_THROWS 1 successful");
- REQUIRE_THROWS(lua.script("e.readonlypropbark = 500"));
- INFO("REQUIRE_THROWS 2 successful");
- REQUIRE_THROWS(lua.script("y = e.writeonlypropbark"));
- INFO("REQUIRE_THROWS 3 successful");
-
-}
-
-TEST_CASE("usertype/copyability", "make sure user can write to a class variable even if the class itself isn't copy-safe") {
- struct NoCopy {
- int get() const { return _you_can_copy_me; }
- void set(int val) { _you_can_copy_me = val; }
-
- int _you_can_copy_me;
- std::mutex _haha_you_cant_copy_me;
- };
-
- sol::state lua;
- lua.new_usertype<NoCopy>("NoCopy", "val", sol::property(&NoCopy::get, &NoCopy::set));
-
- REQUIRE_NOTHROW(
- lua.script(R"__(
-nocopy = NoCopy.new()
-nocopy.val = 5
- )__")
- );
-}
-
-TEST_CASE("usertype/protect", "users should be allowed to manually protect a function") {
- struct protect_me {
- int gen(int x) {
- return x;
- }
- };
-
- sol::state lua;
- lua.open_libraries(sol::lib::base);
- lua.new_usertype<protect_me>("protect_me",
- "gen", sol::protect( &protect_me::gen )
- );
-
- REQUIRE_NOTHROW(
- lua.script(R"__(
-pm = protect_me.new()
-value = pcall(pm.gen,pm)
-)__");
- );
- bool value = lua["value"];
- REQUIRE_FALSE(value);
-}
-
-TEST_CASE("usertype/shared-ptr-regression", "usertype metatables should not screw over unique usertype metatables") {
- static int created = 0;
- static int destroyed = 0;
- struct test {
- test() {
- ++created;
- }
-
- ~test() {
- ++destroyed;
- }
- };
- {
- std::list<std::shared_ptr<test>> tests;
- sol::state lua;
- lua.open_libraries();
-
- lua.new_usertype<test>("test",
- "create", [&]() -> std::shared_ptr<test> {
- tests.push_back(std::make_shared<test>());
- return tests.back();
- }
- );
- REQUIRE(created == 0);
- REQUIRE(destroyed == 0);
- lua.script("x = test.create()");
- REQUIRE(created == 1);
- REQUIRE(destroyed == 0);
- REQUIRE_FALSE(tests.empty());
- std::shared_ptr<test>& x = lua["x"];
- std::size_t xuse = x.use_count();
- std::size_t tuse = tests.back().use_count();
- REQUIRE(xuse == tuse);
- }
- REQUIRE(created == 1);
- REQUIRE(destroyed == 1);
-}
-
-TEST_CASE("usertype/double-deleter-guards", "usertype metatables internally must not rely on internal ") {
- struct c_a { int x; };
- struct c_b { int y; };
- REQUIRE_NOTHROW( {
- sol::state lua;
- lua.new_usertype<c_a>("c_a", "x", &c_a::x);
- lua.new_usertype<c_b>("c_b", "y", &c_b::y);
- lua = sol::state();
- lua.new_usertype<c_a>("c_a", "x", &c_a::x);
- lua.new_usertype<c_b>("c_b", "y", &c_b::y);
- lua = sol::state();
- });
-}
-
-TEST_CASE("usertype/vars", "usertype vars can bind various class items") {
- static int muh_variable = 25;
- static int through_variable = 10;
-
- sol::state lua;
- lua.open_libraries();
- struct test {};
- lua.new_usertype<test>("test",
- "straight", sol::var(2),
- "global", sol::var(muh_variable),
- "ref_global", sol::var(std::ref(muh_variable)),
- "global2", sol::var(through_variable),
- "ref_global2", sol::var(std::ref(through_variable))
- );
-
- int prets = lua["test"]["straight"];
- int pretg = lua["test"]["global"];
- int pretrg = lua["test"]["ref_global"];
- int pretg2 = lua["test"]["global2"];
- int pretrg2 = lua["test"]["ref_global2"];
-
- REQUIRE(prets == 2);
- REQUIRE(pretg == 25);
- REQUIRE(pretrg == 25);
- REQUIRE(pretg2 == 10);
- REQUIRE(pretrg2 == 10);
-
- lua.script(R"(
-print(test.straight)
-test.straight = 50
-print(test.straight)
-)");
- int s = lua["test"]["straight"];
- REQUIRE(s == 50);
-
- lua.script(R"(
-t = test.new()
-print(t.global)
-t.global = 50
-print(t.global)
-)");
- int mv = lua["test"]["global"];
- REQUIRE(mv == 50);
- REQUIRE(muh_variable == 25);
-
-
- lua.script(R"(
-print(t.ref_global)
-t.ref_global = 50
-print(t.ref_global)
-)");
- int rmv = lua["test"]["ref_global"];
- REQUIRE(rmv == 50);
- REQUIRE(muh_variable == 50);
-
- REQUIRE(through_variable == 10);
- lua.script(R"(
-print(test.global2)
-test.global2 = 35
-print(test.global2)
-)");
- int tv = lua["test"]["global2"];
- REQUIRE(through_variable == 10);
- REQUIRE(tv == 35);
-
- lua.script(R"(
-print(test.ref_global2)
-test.ref_global2 = 35
-print(test.ref_global2)
-)");
- int rtv = lua["test"]["ref_global2"];
- REQUIRE(rtv == 35);
- REQUIRE(through_variable == 35);
-}
-
-TEST_CASE("usertypes/var-and-property", "make sure const vars are readonly and properties can handle lambdas") {
- const static int arf = 20;
-
- struct test {
- int value = 10;
- };
-
- sol::state lua;
- lua.open_libraries();
-
- lua.new_usertype<test>("test",
- "prop", sol::property(
- [](test& t) {
- return t.value;
- },
- [](test& t, int x) {
- t.value = x;
- }
- ),
- "global", sol::var(std::ref(arf))
- );
-
- lua.script(R"(
-t = test.new()
-print(t.prop)
-t.prop = 50
-print(t.prop)
- )");
-
- test& t = lua["t"];
- REQUIRE(t.value == 50);
-
-
- REQUIRE_THROWS(
- lua.script(R"(
-t = test.new()
-print(t.global)
-t.global = 20
-print(t.global)
- )"));
-}
-
-TEST_CASE("usertype/unique_usertype-check", "make sure unique usertypes don't get pushed as references with function calls and the like") {
- class Entity {
- public:
- std::string GetName() {
- return "Charmander";
- }
- };
-
- sol::state lua;
- lua.open_libraries(sol::lib::base, sol::lib::math, sol::lib::string, sol::lib::io);
-
- lua.new_usertype<Entity>("Entity",
- "new", sol::no_constructor,
- "get_name", &Entity::GetName
- );
-
- lua.script(R"(
- function my_func(entity)
- print("INSIDE LUA")
- print(entity:get_name())
- end
-)");
-
- sol::function my_func = lua["my_func"];
- REQUIRE_NOTHROW({
- auto ent = std::make_shared<Entity>();
- my_func(ent);
- Entity ent2;
- my_func(ent2);
- my_func(std::make_shared<Entity>());
- });
-}
-
-TEST_CASE("usertype/abstract-base-class", "Ensure that abstract base classes and such can be registered") {
- sol::state lua;
- lua.new_usertype<abstract_A>("A", "a", &abstract_A::a);
- lua.new_usertype<abstract_B>("B", sol::base_classes, sol::bases<abstract_A>());
- lua.script(R"(local b = B.new()
-b:a()
-)");
-}
-
-TEST_CASE("usertype/as_function", "Ensure that variables can be turned into functions by as_function") {
- class B {
- public:
- int bvar = 24;
- };
-
- sol::state lua;
- lua.open_libraries();
- lua.new_usertype<B>("B", "b", &B::bvar, "f", sol::as_function(&B::bvar));
-
- B b;
- lua.set("b", &b);
- lua.script("x = b:f()");
- lua.script("y = b.b");
- int x = lua["x"];
- int y = lua["y"];
- REQUIRE(x == 24);
- REQUIRE(y == 24);
-}
-
-TEST_CASE("usertype/destruction-test", "make sure usertypes are properly destructed and don't double-delete memory or segfault") {
- sol::state lua;
-
- class CrashClass {
- public:
- CrashClass() {
- }
-
- ~CrashClass() {
- a = 10; // This will cause a crash.
- }
-
- private:
- int a;
- };
-
- lua.new_usertype<CrashClass>("CrashClass",
- sol::call_constructor, sol::constructors<sol::types<>>()
- );
-
- lua.script(R"(
- function testCrash()
- local x = CrashClass()
- end
- )");
-
- for (int i = 0; i < 1000; ++i) {
- lua["testCrash"]();
- }
-}
-
-TEST_CASE("usertype/call-initializers", "Ensure call constructors with initializers work well") {
- struct A {
- double f = 25.5;
-
- static void init(A& x, double f) {
- x.f = f;
- }
- };
-
- sol::state lua;
- lua.open_libraries();
-
- lua.new_usertype<A>("A",
- sol::call_constructor, sol::initializers(&A::init)
- );
-
- lua.script(R"(
-a = A(24.3)
-)");
- A& a = lua["a"];
- REQUIRE(a.f == 24.3);
-}