diff options
Diffstat (limited to 'deps/sol2/tests/runtime_tests/source/lua_value.cpp')
-rw-r--r-- | deps/sol2/tests/runtime_tests/source/lua_value.cpp | 401 |
1 files changed, 401 insertions, 0 deletions
diff --git a/deps/sol2/tests/runtime_tests/source/lua_value.cpp b/deps/sol2/tests/runtime_tests/source/lua_value.cpp new file mode 100644 index 0000000..5e3126f --- /dev/null +++ b/deps/sol2/tests/runtime_tests/source/lua_value.cpp @@ -0,0 +1,401 @@ +// sol3
+
+// The MIT License (MIT)
+
+// Copyright (c) 2013-2019 Rapptz, ThePhD and contributors
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+// the Software, and to permit persons to whom the Software is furnished to do so,
+// subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+#include "sol_test.hpp"
+
+#include <catch.hpp>
+
+#include <vector>
+#include <map>
+#include <thread>
+#include <mutex>
+#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES
+#include <string_view>
+#include <variant>
+#endif // C++17
+
+struct int_entry {
+ int value;
+
+ int_entry() : value(0) {
+ }
+
+ int_entry(int v) : value(v) {
+ }
+
+ bool operator==(const int_entry& e) const {
+ return value == e.value;
+ }
+};
+
+std::mutex lua_value_construct_require_mutex;
+
+void lua_value_construct_race() {
+ sol::state lua;
+ try {
+ lua.open_libraries();
+ lua["a"] = sol::lua_value(lua, 24);
+ int a = lua["a"];
+ {
+ std::lock_guard<std::mutex> lg(lua_value_construct_require_mutex);
+ REQUIRE(a == 24);
+ }
+ }
+ catch (const sol::error& e) {
+ std::lock_guard<std::mutex> lg(lua_value_construct_require_mutex);
+ INFO(e.what());
+ REQUIRE(false);
+ }
+ catch (...) {
+ std::lock_guard<std::mutex> lg(lua_value_construct_require_mutex);
+ REQUIRE(false);
+ }
+}
+
+TEST_CASE("lua_value/nested", "make nested values can be put in lua_value properly") {
+#if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT
+ using mixed_table_entry = std::variant<int, int_entry, std::string>;
+ using nested_entry = std::variant<int, int_entry, std::string, std::vector<mixed_table_entry>>;
+
+ const std::vector<std::variant<int, int_entry>> mixed_table_truth = { 1, int_entry(2), 3, int_entry(4), 5 };
+ const std::vector<nested_entry> mixed_nested_table_truth = { 1, int_entry(2), 3, int_entry(4), std::vector<mixed_table_entry>{ 5, 6, int_entry(7), "8" } };
+
+ sol::state lua;
+
+ sol::lua_value lv_mixed_table(lua, sol::array_value{ 1, int_entry(2), 3, int_entry(4), 5 });
+ sol::lua_value lv_mixed_nested_table(lua, sol::array_value{ 1, int_entry(2), 3, int_entry(4), sol::array_value{ 5, 6, int_entry(7), "8" } });
+
+ REQUIRE(lv_mixed_table.is<sol::table>());
+ REQUIRE(lv_mixed_nested_table.is<sol::table>());
+
+ std::vector<std::variant<int, int_entry>> mixed_table_value_lv = lv_mixed_table.as<std::vector<std::variant<int, int_entry>>>();
+ std::vector<nested_entry> mixed_nested_table_value_lv = lv_mixed_nested_table.as<std::vector<nested_entry>>();
+
+ REQUIRE(mixed_table_truth == mixed_table_value_lv);
+ REQUIRE(mixed_nested_table_truth == mixed_nested_table_value_lv);
+
+ SECTION("type check (object)") {
+ sol::object obj_mixed_table(lv_mixed_table.value());
+ sol::object obj_mixed_nested_table(lv_mixed_nested_table.value());
+
+ REQUIRE(obj_mixed_table.is<sol::table>());
+ REQUIRE(obj_mixed_nested_table.is<sol::table>());
+
+ std::vector<std::variant<int, int_entry>> mixed_table_value = obj_mixed_table.as<std::vector<std::variant<int, int_entry>>>();
+ std::vector<nested_entry> mixed_nested_table_value = obj_mixed_nested_table.as<std::vector<nested_entry>>();
+
+ REQUIRE(mixed_table_truth == mixed_table_value);
+ REQUIRE(mixed_nested_table_truth == mixed_nested_table_value);
+ }
+ SECTION("pushing/popping") {
+ lua["obj_mixed_table"] = lv_mixed_table;
+ lua["obj_mixed_nested_table"] = lv_mixed_nested_table;
+
+ sol::lua_value obj_mixed_table = lua["obj_mixed_table"];
+ sol::lua_value obj_mixed_nested_table = lua["obj_mixed_nested_table"];
+
+ REQUIRE(obj_mixed_table.is<sol::table>());
+ REQUIRE(obj_mixed_nested_table.is<sol::table>());
+
+ std::vector<std::variant<int, int_entry>> mixed_table_value = obj_mixed_table.as<std::vector<std::variant<int, int_entry>>>();
+ std::vector<nested_entry> mixed_nested_table_value = obj_mixed_nested_table.as<std::vector<nested_entry>>();
+
+ REQUIRE(mixed_table_truth == mixed_table_value);
+ REQUIRE(mixed_nested_table_truth == mixed_nested_table_value);
+ }
+ SECTION("pushing/popping (object)") {
+ lua["obj_mixed_table"] = lv_mixed_table;
+ lua["obj_mixed_nested_table"] = lv_mixed_nested_table;
+
+ sol::object obj_mixed_table = lua["obj_mixed_table"];
+ sol::object obj_mixed_nested_table = lua["obj_mixed_nested_table"];
+
+ REQUIRE(obj_mixed_table.is<sol::table>());
+ REQUIRE(obj_mixed_nested_table.is<sol::table>());
+
+ std::vector<std::variant<int, int_entry>> mixed_table_value = obj_mixed_table.as<std::vector<std::variant<int, int_entry>>>();
+ std::vector<nested_entry> mixed_nested_table_value = obj_mixed_nested_table.as<std::vector<nested_entry>>();
+
+ REQUIRE(mixed_table_truth == mixed_table_value);
+ REQUIRE(mixed_nested_table_truth == mixed_nested_table_value);
+ }
+#else
+ REQUIRE(true);
+#endif // C++17
+}
+
+TEST_CASE("lua_value/nested key value", "make nested values (key value) can be put in lua_value properly") {
+#if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT
+ using mixed_table_entry = std::variant<int, int_entry, std::string>;
+ using nested_entry = std::variant<int, int_entry, std::string, std::vector<mixed_table_entry>>;
+
+ const std::vector<std::variant<int, int_entry>> mixed_table_truth = { 1, int_entry(2), 3, int_entry(4), 5 };
+ const std::vector<nested_entry> mixed_nested_table_truth = { 1, int_entry(2), 3, int_entry(4), std::vector<mixed_table_entry>{ 5, 6, int_entry(7), "8" } };
+
+ sol::state lua;
+
+ sol::lua_value lv_mixed_table(lua, sol::array_value{ 1, int_entry(2), 3, int_entry(4), 5 });
+ sol::lua_value lv_mixed_nested_table(lua, sol::array_value{ 1, int_entry(2), 3, int_entry(4), sol::array_value{ 5, 6, int_entry(7), "8" } });
+
+ REQUIRE(lv_mixed_table.is<sol::table>());
+ REQUIRE(lv_mixed_nested_table.is<sol::table>());
+
+ std::vector<std::variant<int, int_entry>> mixed_table_value_lv = lv_mixed_table.as<std::vector<std::variant<int, int_entry>>>();
+ std::vector<nested_entry> mixed_nested_table_value_lv = lv_mixed_nested_table.as<std::vector<nested_entry>>();
+
+ REQUIRE(mixed_table_truth == mixed_table_value_lv);
+ REQUIRE(mixed_nested_table_truth == mixed_nested_table_value_lv);
+
+ SECTION("type check (object)") {
+ sol::object obj_mixed_table(lv_mixed_table.value());
+ sol::object obj_mixed_nested_table(lv_mixed_nested_table.value());
+
+ REQUIRE(obj_mixed_table.is<sol::table>());
+ REQUIRE(obj_mixed_nested_table.is<sol::table>());
+
+ std::vector<std::variant<int, int_entry>> mixed_table_value = obj_mixed_table.as<std::vector<std::variant<int, int_entry>>>();
+ std::vector<nested_entry> mixed_nested_table_value = obj_mixed_nested_table.as<std::vector<nested_entry>>();
+
+ REQUIRE(mixed_table_truth == mixed_table_value);
+ REQUIRE(mixed_nested_table_truth == mixed_nested_table_value);
+ }
+ SECTION("pushing/popping") {
+ lua["obj_mixed_table"] = lv_mixed_table;
+ lua["obj_mixed_nested_table"] = lv_mixed_nested_table;
+
+ sol::lua_value obj_mixed_table = lua["obj_mixed_table"];
+ sol::lua_value obj_mixed_nested_table = lua["obj_mixed_nested_table"];
+
+ REQUIRE(obj_mixed_table.is<sol::table>());
+ REQUIRE(obj_mixed_nested_table.is<sol::table>());
+
+ std::vector<std::variant<int, int_entry>> mixed_table_value = obj_mixed_table.as<std::vector<std::variant<int, int_entry>>>();
+ std::vector<nested_entry> mixed_nested_table_value = obj_mixed_nested_table.as<std::vector<nested_entry>>();
+
+ REQUIRE(mixed_table_truth == mixed_table_value);
+ REQUIRE(mixed_nested_table_truth == mixed_nested_table_value);
+ }
+ SECTION("pushing/popping (object)") {
+ lua["obj_mixed_table"] = lv_mixed_table;
+ lua["obj_mixed_nested_table"] = lv_mixed_nested_table;
+
+ sol::object obj_mixed_table = lua["obj_mixed_table"];
+ sol::object obj_mixed_nested_table = lua["obj_mixed_nested_table"];
+
+ REQUIRE(obj_mixed_table.is<sol::table>());
+ REQUIRE(obj_mixed_nested_table.is<sol::table>());
+
+ std::vector<std::variant<int, int_entry>> mixed_table_value = obj_mixed_table.as<std::vector<std::variant<int, int_entry>>>();
+ std::vector<nested_entry> mixed_nested_table_value = obj_mixed_nested_table.as<std::vector<nested_entry>>();
+
+ REQUIRE(mixed_table_truth == mixed_table_value);
+ REQUIRE(mixed_nested_table_truth == mixed_nested_table_value);
+ }
+#else
+ REQUIRE(true);
+#endif // C++17
+}
+
+TEST_CASE("lua_value/basic types", "make sure we can stick values and nested values in a lua_value and retrieve them") {
+ sol::state lua;
+
+ const int_entry userdata_truth = int_entry(3);
+ const std::vector<int> int_table_truth = { 1, 2, 3, 4, 5 };
+ const std::map<int, int> int_map_truth = { {1, 2}, {3, 4}, {5, 6} };
+
+ sol::lua_value lv_int(lua, 1);
+ sol::lua_value lv_double(lua, 2.0);
+ sol::lua_value lv_string(lua, "heyo");
+ sol::lua_value lv_lstring(lua, L"hiyo");
+ sol::lua_value lv_bool(lua, true);
+ sol::lua_value lv_nil(lua, sol::lua_nil);
+ sol::lua_value lv_userdata(lua, int_entry(3));
+ sol::lua_value lv_int_table(lua, { 1, 2, 3, 4, 5 });
+ sol::lua_value lv_int_map(lua, { {1, 2}, {3, 4}, {5, 6} });
+ REQUIRE(lv_int.is<int>());
+ REQUIRE(lv_double.is<double>());
+ REQUIRE(lv_string.is<std::string>());
+ REQUIRE(lv_lstring.is<std::string>());
+ REQUIRE(lv_bool.is<bool>());
+ REQUIRE(lv_nil.is<sol::lua_nil_t>());
+ REQUIRE(lv_userdata.is<sol::userdata>());
+ REQUIRE(lv_userdata.is<int_entry>());
+ REQUIRE(lv_int_table.is<sol::table>());
+ REQUIRE(lv_int_map.is<sol::table>());
+
+ REQUIRE(lv_int.as<int>() == 1);
+ REQUIRE(lv_double.as<double>() == 2.0);
+ REQUIRE(lv_string.as<std::string>() == "heyo");
+ REQUIRE(lv_lstring.as<std::string>() == "hiyo");
+ REQUIRE(lv_lstring.as<std::wstring>() == L"hiyo");
+ REQUIRE(lv_bool.as<bool>());
+ REQUIRE(lv_nil.as<sol::lua_nil_t>() == sol::lua_nil);
+ REQUIRE(lv_userdata.as<int_entry>() == userdata_truth);
+
+ std::vector<int> int_table_value_lv = lv_int_table.as<std::vector<int>>();
+ REQUIRE(int_table_truth == int_table_value_lv);
+ std::map<int, int> int_map_value_lv = lv_int_map.as<std::map<int, int>>();
+ REQUIRE(int_map_truth == int_map_value_lv);
+
+ SECTION("type check (object)") {
+ sol::object obj_int(lv_int.value());
+ sol::object obj_double(lv_double.value());
+ sol::object obj_string(lv_string.value());
+ sol::object obj_lstring(lv_lstring.value());
+ sol::object obj_bool(lv_bool.value());
+ sol::object obj_nil(lv_nil.value());
+ sol::object obj_userdata(lv_userdata.value());
+ sol::object obj_int_table(lv_int_table.value());
+ sol::object obj_int_map(lv_int_map.value());
+
+ REQUIRE(obj_int.is<int>());
+ REQUIRE(obj_double.is<double>());
+ REQUIRE(obj_string.is<std::string>());
+ REQUIRE(obj_lstring.is<std::string>());
+ REQUIRE(obj_bool.is<bool>());
+ REQUIRE(obj_nil.is<sol::lua_nil_t>());
+ REQUIRE(obj_userdata.is<sol::userdata>());
+ REQUIRE(obj_userdata.is<int_entry>());
+ REQUIRE(obj_int_table.is<sol::table>());
+ REQUIRE(obj_int_map.is<sol::table>());
+
+ REQUIRE(obj_int.as<int>() == 1);
+ REQUIRE(obj_double.as<double>() == 2.0);
+ REQUIRE(obj_string.as<std::string>() == "heyo");
+ REQUIRE(obj_lstring.as<std::string>() == "hiyo");
+ REQUIRE(obj_lstring.as<std::wstring>() == L"hiyo");
+ REQUIRE(obj_bool.as<bool>());
+ REQUIRE(obj_userdata.as<int_entry>() == userdata_truth);
+ REQUIRE(obj_nil.as<sol::lua_nil_t>() == sol::lua_nil);
+
+ std::vector<int> int_table_value = obj_int_table.as<std::vector<int>>();
+ REQUIRE(int_table_truth == int_table_value);
+ std::map<int, int> int_map_value = obj_int_map.as<std::map<int, int>>();
+ REQUIRE(int_map_truth == int_map_value);
+ }
+ SECTION("push/popping") {
+ lua["obj_int"] = lv_int;
+ lua["obj_double"] = lv_double;
+ lua["obj_string"] = lv_string;
+ lua["obj_lstring"] = lv_lstring;
+ lua["obj_bool"] = lv_bool;
+ lua["obj_nil"] = lv_nil;
+ lua["obj_userdata"] = lv_userdata;
+ lua["obj_int_table"] = lv_int_table;
+ lua["obj_int_map"] = lv_int_map;
+
+ // these all actually invoke the constructor
+ // so do one .get<> explicitly to ensure it's
+ // working correctl for a few cases...
+ // but it's nice to make sure it's all there now
+ sol::lua_value obj_int = lua["obj_int"].get<sol::lua_value>();
+ sol::lua_value obj_double = lua["obj_double"].get<sol::lua_value>();
+ sol::lua_value obj_string = lua["obj_string"].get<sol::lua_value>();
+ sol::lua_value obj_lstring = lua["obj_lstring"].get<sol::lua_value>();
+ sol::lua_value obj_bool = lua["obj_bool"].get<sol::lua_value>();
+ sol::lua_value obj_nil = lua["obj_nil"];
+ sol::lua_value obj_userdata = lua["obj_userdata"];
+ sol::lua_value obj_int_table = lua["obj_int_table"];
+ sol::lua_value obj_int_map = lua["obj_int_map"];
+
+ REQUIRE(obj_int.is<int>());
+ REQUIRE(obj_double.is<double>());
+ REQUIRE(obj_string.is<std::string>());
+ REQUIRE(obj_lstring.is<std::string>());
+ REQUIRE(obj_bool.is<bool>());
+ REQUIRE(obj_nil.is<sol::lua_nil_t>());
+ REQUIRE(obj_int_table.is<sol::table>());
+ REQUIRE(obj_int_map.is<sol::table>());
+
+ REQUIRE(obj_int.as<int>() == 1);
+ REQUIRE(obj_double.as<double>() == 2.0);
+ REQUIRE(obj_string.as<std::string>() == "heyo");
+ REQUIRE(obj_lstring.as<std::string>() == "hiyo");
+ REQUIRE(obj_lstring.as<std::wstring>() == L"hiyo");
+ REQUIRE(obj_bool.as<bool>());
+ REQUIRE(obj_nil.as<sol::lua_nil_t>() == sol::lua_nil);
+
+ std::vector<int> int_table_value = obj_int_table.as<std::vector<int>>();
+ REQUIRE(int_table_truth == int_table_value);
+ std::map<int, int> int_map_value = obj_int_map.as<std::map<int, int>>();
+ REQUIRE(int_map_truth == int_map_value);
+ }
+ SECTION("push/popping (object)") {
+ lua["obj_int"] = lv_int;
+ lua["obj_double"] = lv_double;
+ lua["obj_string"] = lv_string;
+ lua["obj_lstring"] = lv_lstring;
+ lua["obj_bool"] = lv_bool;
+ lua["obj_nil"] = lv_nil;
+ lua["obj_userdata"] = lv_userdata;
+ lua["obj_int_table"] = lv_int_table;
+ lua["obj_int_map"] = lv_int_map;
+
+ sol::object obj_int = lua["obj_int"];
+ sol::object obj_double = lua["obj_double"];
+ sol::object obj_string = lua["obj_string"];
+ sol::object obj_lstring = lua["obj_lstring"];
+ sol::object obj_bool = lua["obj_bool"];
+ sol::object obj_nil = lua["obj_nil"];
+ sol::object obj_userdata = lua["obj_userdata"];
+ sol::object obj_int_table = lua["obj_int_table"];
+ sol::object obj_int_map = lua["obj_int_map"];
+
+ REQUIRE(obj_int.is<int>());
+ REQUIRE(obj_double.is<double>());
+ REQUIRE(obj_string.is<std::string>());
+ REQUIRE(obj_lstring.is<std::string>());
+ REQUIRE(obj_bool.is<bool>());
+ REQUIRE(obj_nil.is<sol::lua_nil_t>());
+ REQUIRE(obj_userdata.is<sol::userdata>());
+ REQUIRE(obj_userdata.is<int_entry>());
+ REQUIRE(obj_int_table.is<sol::table>());
+
+ REQUIRE(obj_int.as<int>() == 1);
+ REQUIRE(obj_double.as<double>() == 2.0);
+ REQUIRE(obj_string.as<std::string>() == "heyo");
+ REQUIRE(obj_lstring.as<std::string>() == "hiyo");
+ REQUIRE(obj_lstring.as<std::wstring>() == L"hiyo");
+ REQUIRE(obj_bool.as<bool>());
+ REQUIRE(obj_nil.as<sol::lua_nil_t>() == sol::lua_nil);
+ REQUIRE(obj_userdata.as<int_entry>() == userdata_truth);
+
+ std::vector<int> int_table_value = obj_int_table.as<std::vector<int>>();
+ REQUIRE(int_table_truth == int_table_value);
+ std::map<int, int> int_map_value = obj_int_map.as<std::map<int, int>>();
+ REQUIRE(int_map_truth == int_map_value);
+ }
+}
+
+TEST_CASE("lua_value/threading", "test that thread_local in lua_value constructors do not race or clobber") {
+ REQUIRE_NOTHROW([]() {
+ std::thread thrds[24];
+ for (int i = 0; i < 24; i++) {
+ thrds[i] = std::thread(&lua_value_construct_race);
+ }
+
+ for (int i = 0; i < 24; i++) {
+ thrds[i].join();
+ }
+ }());
+}
|