usertypes.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. #include "catch.hpp"
  2. #include <lua.hpp>
  3. #include <luwra.hpp>
  4. #include <memory>
  5. struct A {
  6. int a;
  7. A() {}
  8. };
  9. TEST_CASE("usertypes_registration") {
  10. lua_State* state = luaL_newstate();
  11. REQUIRE(luwra::internal::user_type_id<A> == (void*) INTPTR_MAX);
  12. luwra::register_user_type<A>(state, {});
  13. REQUIRE(luwra::internal::user_type_id<A> != (void*) INTPTR_MAX);
  14. A* instance = new A;
  15. luwra::Value<A*>::push(state, instance);
  16. REQUIRE(luwra::internal::get_user_type_id(state, -1) == luwra::internal::user_type_id<A>);
  17. REQUIRE(luwra::internal::check_user_type<A>(state, -1) == instance);
  18. REQUIRE(luwra::Value<A*>::read(state, -1) == instance);
  19. lua_close(state);
  20. delete instance;
  21. }
  22. struct B {
  23. int n;
  24. const int cn;
  25. volatile int vn;
  26. const volatile int cvn;
  27. B(int val):
  28. n(val),
  29. cn(val),
  30. vn(val),
  31. cvn(val)
  32. {}
  33. };
  34. TEST_CASE("usertypes_wrap_fields") {
  35. lua_State* state = luaL_newstate();
  36. luwra::register_user_type<B>(
  37. state,
  38. {
  39. {"n", luwra::wrap_field<B, int, &B::n>},
  40. {"cn", luwra::wrap_field<B, const int, &B::cn>},
  41. {"vn", luwra::wrap_field<B, volatile int, &B::vn>},
  42. {"cvn", luwra::wrap_field<B, const volatile int, &B::cvn>}
  43. }
  44. );
  45. B value(1338);
  46. luwra::register_global(state, "val", &value);
  47. // Unqualified get
  48. REQUIRE(luaL_dostring(state, "return val:n()") == 0);
  49. REQUIRE(luwra::read<int>(state, -1) == value.n);
  50. // Unqualified set
  51. REQUIRE(luaL_dostring(state, "val:n(42)") == 0);
  52. REQUIRE(value.n == 42);
  53. // 'const'-qualified get
  54. REQUIRE(luaL_dostring(state, "return val:cn()") == 0);
  55. REQUIRE(luwra::read<int>(state, -1) == value.cn);
  56. // 'const'-qualified set
  57. REQUIRE(luaL_dostring(state, "val:cn(42)") == 0);
  58. REQUIRE(value.cn == 1338);
  59. // 'volatile' get
  60. REQUIRE(luaL_dostring(state, "return val:vn()") == 0);
  61. REQUIRE(luwra::read<int>(state, -1) == value.vn);
  62. // 'volatile' set
  63. REQUIRE(luaL_dostring(state, "val:vn(42)") == 0);
  64. REQUIRE(value.vn == 42);
  65. // 'const volatile'-qualified get
  66. REQUIRE(luaL_dostring(state, "return val:cvn()") == 0);
  67. REQUIRE(luwra::read<int>(state, -1) == value.cvn);
  68. // 'const volatile'-qualified set
  69. REQUIRE(luaL_dostring(state, "val:cvn(42)") == 0);
  70. REQUIRE(value.cvn == 1338);
  71. lua_close(state);
  72. }
  73. struct C {
  74. int prop;
  75. C(int val):
  76. prop(val)
  77. {}
  78. int foo1(int x) {
  79. return prop += x;
  80. }
  81. int foo2(int x) const {
  82. return prop + x;
  83. }
  84. int foo3(int x) volatile {
  85. return prop -= x;
  86. }
  87. int foo4(int x) const volatile {
  88. return prop - x;
  89. }
  90. };
  91. TEST_CASE("usertypes_wrap_methods") {
  92. lua_State* state = luaL_newstate();
  93. luwra::register_user_type<C>(
  94. state,
  95. {
  96. {"foo1", luwra::wrap_method<C, int(int), &C::foo1>},
  97. {"foo2", luwra::wrap_method<const C, int(int), &C::foo2>},
  98. {"foo3", luwra::wrap_method<volatile C, int(int), &C::foo3>},
  99. {"foo4", luwra::wrap_method<const volatile C, int(int), &C::foo4>}
  100. }
  101. );
  102. C value(1337);
  103. luwra::register_global(state, "value", &value);
  104. // Unqualified method
  105. REQUIRE(luaL_dostring(state, "return value:foo1(63)") == 0);
  106. REQUIRE(value.prop == 1400);
  107. REQUIRE(luwra::read<int>(state, -1) == value.prop);
  108. // 'const'-qualified method
  109. REQUIRE(luaL_dostring(state, "return value:foo2(44)") == 0);
  110. REQUIRE(value.prop == 1400);
  111. REQUIRE(luwra::read<int>(state, -1) == 1444);
  112. // 'volatile'-qualified method
  113. REQUIRE(luaL_dostring(state, "return value:foo3(400)") == 0);
  114. REQUIRE(value.prop == 1000);
  115. REQUIRE(luwra::read<int>(state, -1) == value.prop);
  116. // 'const volatile'-qualified method
  117. REQUIRE(luaL_dostring(state, "return value:foo4(334)") == 0);
  118. REQUIRE(value.prop == 1000);
  119. REQUIRE(luwra::read<int>(state, -1) == 666);
  120. lua_close(state);
  121. }
  122. TEST_CASE("usertypes_gchook_tref") {
  123. lua_State* state = luaL_newstate();
  124. luwra::register_user_type<std::shared_ptr<int>>(state, {});
  125. std::shared_ptr<int> shared_var = std::make_shared<int>(1337);
  126. REQUIRE(shared_var.use_count() == 1);
  127. // Copy construction
  128. luwra::push<std::shared_ptr<int>&>(state, shared_var);
  129. REQUIRE(shared_var.use_count() == 2);
  130. // Garbage collection
  131. lua_close(state);
  132. REQUIRE(shared_var.use_count() == 1);
  133. }
  134. TEST_CASE("usertypes_gchook_tptr") {
  135. lua_State* state = luaL_newstate();
  136. luwra::register_user_type<std::shared_ptr<int>>(state, {});
  137. std::shared_ptr<int> shared_var = std::make_shared<int>(1337);
  138. REQUIRE(shared_var.use_count() == 1);
  139. // Reference
  140. luwra::push(state, &shared_var);
  141. REQUIRE(shared_var.use_count() == 1);
  142. // Garbage collection
  143. lua_close(state);
  144. REQUIRE(shared_var.use_count() == 1);
  145. }