?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download

  1. // https://github.com/vinniefalco/LuaBridge
  2. // Copyright 2020, Dmitry Tarakanov
  3. // SPDX-License-Identifier: MIT
  4.  
  5. #include "TestBase.h"
  6.  
  7. #include <functional>
  8.  
  9. struct NamespaceTests : TestBase
  10. {
  11.     template<class T>
  12.     T variable(const std::string& name)
  13.     {
  14.         runLua("result = " + name);
  15.         return result<T>();
  16.     }
  17. };
  18.  
  19. TEST_F(NamespaceTests, Variables)
  20. {
  21.     int int_ = -10;
  22.     auto any = luabridge::newTable(L);
  23.     any["a"] = 1;
  24.  
  25.     ASSERT_THROW(luabridge::getGlobalNamespace(L).addProperty("int", &int_), std::logic_error);
  26.  
  27.     runLua("result = int");
  28.     ASSERT_TRUE(result().isNil());
  29.  
  30.     luabridge::getGlobalNamespace(L)
  31.         .beginNamespace("ns")
  32.         .addProperty("int", &int_)
  33.         .addProperty("any", &any)
  34.         .endNamespace();
  35.  
  36.     ASSERT_EQ(-10, variable<int>("ns.int"));
  37.     ASSERT_EQ(any, variable<luabridge::LuaRef>("ns.any"));
  38.  
  39.     runLua("ns.int = -20");
  40.     ASSERT_EQ(-20, int_);
  41.  
  42.     runLua("ns.any = {b = 2}");
  43.     ASSERT_TRUE(any.isTable());
  44.     ASSERT_TRUE(any["b"].isNumber());
  45.     ASSERT_EQ(2, any["b"].cast<int>());
  46. }
  47.  
  48. TEST_F(NamespaceTests, ReadOnlyVariables)
  49. {
  50.     int int_ = -10;
  51.     auto any = luabridge::newTable(L);
  52.     any["a"] = 1;
  53.  
  54.     ASSERT_THROW(luabridge::getGlobalNamespace(L).addProperty("int", &int_), std::logic_error);
  55.  
  56.     runLua("result = int");
  57.     ASSERT_TRUE(result().isNil());
  58.  
  59.     luabridge::getGlobalNamespace(L)
  60.         .beginNamespace("ns")
  61.         .addProperty("int", &int_, false)
  62.         .addProperty("any", &any, false)
  63.         .endNamespace();
  64.  
  65.     ASSERT_EQ(-10, variable<int>("ns.int"));
  66.     ASSERT_EQ(any, variable<luabridge::LuaRef>("ns.any"));
  67.  
  68.     ASSERT_THROW(runLua("ns.int = -20"), std::runtime_error);
  69.     ASSERT_EQ(-10, variable<int>("ns.int"));
  70.  
  71.     ASSERT_THROW(runLua("ns.any = {b = 2}"), std::runtime_error);
  72.     ASSERT_EQ(any, variable<luabridge::LuaRef>("ns.any"));
  73. }
  74.  
  75. namespace {
  76.  
  77. template<class T>
  78. struct Property
  79. {
  80.     static T value;
  81. };
  82.  
  83. template<class T>
  84. T Property<T>::value;
  85.  
  86. template<class T>
  87. void setProperty(const T& value)
  88. {
  89.     Property<T>::value = value;
  90. }
  91.  
  92. template<class T>
  93. const T& getProperty()
  94. {
  95.     return Property<T>::value;
  96. }
  97.  
  98. } // namespace
  99.  
  100. TEST_F(NamespaceTests, Properties)
  101. {
  102.     setProperty<int>(-10);
  103.  
  104.     ASSERT_THROW(
  105.         luabridge::getGlobalNamespace(L).addProperty("int", &getProperty<int>, &setProperty<int>),
  106.         std::logic_error);
  107.  
  108.     runLua("result = int");
  109.     ASSERT_TRUE(result().isNil());
  110.  
  111.     luabridge::getGlobalNamespace(L)
  112.         .beginNamespace("ns")
  113.         .addProperty("int", &getProperty<int>, &setProperty<int>)
  114.         .endNamespace();
  115.  
  116.     ASSERT_EQ(-10, variable<int>("ns.int"));
  117.  
  118.     runLua("ns.int = -20");
  119.     ASSERT_EQ(-20, getProperty<int>());
  120. }
  121.  
  122. TEST_F(NamespaceTests, ReadOnlyProperties)
  123. {
  124.     setProperty<int>(-10);
  125.  
  126.     ASSERT_THROW(luabridge::getGlobalNamespace(L).addProperty("int", &getProperty<int>),
  127.                  std::logic_error);
  128.  
  129.     runLua("result = int");
  130.     ASSERT_TRUE(result().isNil());
  131.  
  132.     luabridge::getGlobalNamespace(L)
  133.         .beginNamespace("ns")
  134.         .addProperty("int", &getProperty<int>)
  135.         .endNamespace();
  136.  
  137.     ASSERT_EQ(-10, variable<int>("ns.int"));
  138.  
  139.     ASSERT_THROW(runLua("ns.int = -20"), std::runtime_error);
  140.     ASSERT_EQ(-10, getProperty<int>());
  141. }
  142.  
  143. namespace {
  144.  
  145. template<class T>
  146. struct Storage
  147. {
  148.     static T value;
  149. };
  150.  
  151. template<class T>
  152. T Storage<T>::value;
  153.  
  154. template<class T>
  155. int getDataC(lua_State* L)
  156. {
  157.     luabridge::Stack<T>::push(L, Storage<T>::value);
  158.     return 1;
  159. }
  160.  
  161. template<class T>
  162. int setDataC(lua_State* L)
  163. {
  164.     Storage<T>::value = luabridge::Stack<T>::get(L, -1);
  165.     return 0;
  166. }
  167.  
  168. } // namespace
  169.  
  170. TEST_F(NamespaceTests, Properties_ProxyCFunctions)
  171. {
  172.     luabridge::getGlobalNamespace(L)
  173.         .beginNamespace("ns")
  174.         .addProperty("value", &getDataC<int>, &setDataC<int>)
  175.         .endNamespace();
  176.  
  177.     Storage<int>::value = 1;
  178.     runLua("ns.value = 2");
  179.     ASSERT_EQ(2, Storage<int>::value);
  180.  
  181.     Storage<int>::value = 3;
  182.     runLua("result = ns.value");
  183.     ASSERT_TRUE(result().isNumber());
  184.     ASSERT_EQ(3, result().cast<int>());
  185. }
  186.  
  187. TEST_F(NamespaceTests, Properties_ProxyCFunctions_ReadOnly)
  188. {
  189.     luabridge::getGlobalNamespace(L)
  190.         .beginNamespace("ns")
  191.         .addProperty("value", &getDataC<int>)
  192.         .endNamespace();
  193.  
  194.     Storage<int>::value = 1;
  195.     ASSERT_THROW(runLua("ns.value = 2"), std::exception);
  196.     ASSERT_EQ(1, Storage<int>::value);
  197.  
  198.     Storage<int>::value = 3;
  199.     runLua("result = ns.value");
  200.     ASSERT_TRUE(result().isNumber());
  201.     ASSERT_EQ(3, result().cast<int>());
  202. }
  203.  
  204. namespace {
  205. struct Class
  206. {
  207. };
  208. } // namespace
  209.  
  210. TEST_F(NamespaceTests, LuaStackIntegrity)
  211. {
  212.     ASSERT_EQ(1, lua_gettop(L)); // Stack: ...
  213.  
  214.     {
  215.         auto ns2 =
  216.             luabridge::getGlobalNamespace(L).beginNamespace("namespace").beginNamespace("ns2");
  217.  
  218.         ASSERT_EQ(
  219.             4,
  220.             lua_gettop(L)); // Stack: ..., global namespace table (gns), namespace table (ns), ns2
  221.  
  222.         ns2.endNamespace(); // Stack: ...
  223.         ASSERT_EQ(1, lua_gettop(L)); // Stack: ...
  224.     }
  225.     ASSERT_EQ(1, lua_gettop(L)); // Stack: ...
  226.  
  227.     {
  228.         auto globalNs = luabridge::getGlobalNamespace(L);
  229.         ASSERT_EQ(2, lua_gettop(L)); // Stack: ..., gns
  230.  
  231.         {
  232.             auto ns = luabridge::getGlobalNamespace(L).beginNamespace("namespace");
  233.             // both globalNs an ns are active
  234.             ASSERT_EQ(4, lua_gettop(L)); // Stack: ..., gns, gns, ns
  235.         }
  236.         ASSERT_EQ(2, lua_gettop(L)); // Stack: ..., gns
  237.  
  238.         {
  239.             auto ns = globalNs.beginNamespace("namespace");
  240.             // globalNs became inactive
  241.             ASSERT_EQ(3, lua_gettop(L)); // Stack: ..., gns, ns
  242.         }
  243.         ASSERT_EQ(1, lua_gettop(L)); // Stack: ...
  244.  
  245.         ASSERT_THROW(globalNs.beginNamespace("namespace"), std::exception);
  246.  
  247.         ASSERT_THROW(globalNs.beginClass<Class>("Class"), std::exception);
  248.     }
  249.  
  250.     {
  251.         auto globalNs = luabridge::getGlobalNamespace(L).beginNamespace("namespace").endNamespace();
  252.         // globalNs is active
  253.         ASSERT_EQ(2, lua_gettop(L)); // Stack: ..., gns
  254.     }
  255.     ASSERT_EQ(1, lua_gettop(L)); // StacK: ...
  256.  
  257.     {
  258.         auto cls =
  259.             luabridge::getGlobalNamespace(L).beginNamespace("namespace").beginClass<Class>("Class");
  260.         ASSERT_EQ(6, lua_gettop(L)); // Stack: ..., gns, ns, const table, class table, static table
  261.         {
  262.             auto ns = cls.endClass();
  263.             ASSERT_EQ(3, lua_gettop(L)); // Stack: ..., gns, ns
  264.         }
  265.         ASSERT_EQ(1, lua_gettop(L)); // Stack: ...
  266.     }
  267.     ASSERT_EQ(1, lua_gettop(L)); // StacK: ...
  268.  
  269.     // Test class continuation
  270.     {
  271.         auto cls =
  272.             luabridge::getGlobalNamespace(L).beginNamespace("namespace").beginClass<Class>("Class");
  273.         ASSERT_EQ(6, lua_gettop(L)); // Stack: ..., gns, ns, const table, class table, static table
  274.     }
  275.     ASSERT_EQ(1, lua_gettop(L)); // Stack: ...
  276. }
  277.  
  278. namespace {
  279.  
  280. template<class T>
  281. T Function(T param)
  282. {
  283.     return param;
  284. }
  285.  
  286. } // namespace
  287.  
  288. TEST_F(NamespaceTests, Functions)
  289. {
  290.     luabridge::getGlobalNamespace(L).addFunction("Function", &Function<double>);
  291.  
  292.     runLua("result = Function (3.14)");
  293.     ASSERT_TRUE(result().isNumber());
  294.     ASSERT_EQ(3.14, result<double>());
  295. }
  296.  
  297. TEST_F(NamespaceTests, StdFunctions)
  298. {
  299.     luabridge::getGlobalNamespace(L).addFunction("Function",
  300.                                                  std::function<int(int)>(&Function<int>));
  301.  
  302.     runLua("result = Function (12)");
  303.     ASSERT_TRUE(result().isNumber());
  304.     ASSERT_EQ(12, result<int>());
  305. }
  306.  
  307. #ifdef _M_IX86 // Windows 32bit only
  308.  
  309. namespace {
  310.  
  311. int __stdcall StdCall(int i)
  312. {
  313.     return i + 10;
  314. }
  315.  
  316. } // namespace
  317.  
  318. TEST_F(NamespaceTests, StdCallFunctions)
  319. {
  320.     luabridge::getGlobalNamespace(L).addFunction("StdCall", &StdCall);
  321.  
  322.     runLua("result = StdCall (2)");
  323.     ASSERT_TRUE(result().isNumber());
  324.     ASSERT_EQ(12, result<int>());
  325. }
  326.  
  327. #endif // _M_IX86
  328.