usertypes.cpp 4.2 KB

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