diff --git a/.gitignore b/.gitignore index bfad8f2a..20a49466 100644 --- a/.gitignore +++ b/.gitignore @@ -113,3 +113,4 @@ desktop.ini # Miscellaneous external/ scratch/ +.idea/ diff --git a/docs/source/api/reference.rst b/docs/source/api/reference.rst index 9c927901..645001f6 100644 --- a/docs/source/api/reference.rst +++ b/docs/source/api/reference.rst @@ -22,6 +22,7 @@ members .. code-block:: cpp :caption: constructor: reference + :name: reference-constructor reference(lua_State* L, int index = -1); reference(lua_State* L, lua_nil_t); @@ -41,6 +42,8 @@ The first constructor creates a reference from the Lua stack at the specified in Note that the last constructor has ``lua_xmove`` safety built into it. You can pin an object to a certain thread (or the main thread) by initializing it with ``sol::reference pinned(state, other_reference_object);``. This ensures that ``other_reference_object`` will exist in the state/thread of ``state``. Also note that copy/move assignment operations will also use pinning semantics if it detects that the state of the object on the right is ``lua_xmove`` compatible. (But, the ``reference`` object on the left must have a valid state as well. You can have a nil ``reference`` with a valid state by using the ``sol::reference pinned(state, sol::lua_nil)`` constructor as well.) This applies for any ``sol::reference`` derived type. + You can un-pin and null the state by doing ``ref = sol::lua_nil;``. This applies to **all derived types**, including ``sol::(protected_)function``, ``sol::thread``, ``sol::object``, ``sol::table``, and similar. + .. code-block:: cpp :caption: function: push referred-to element from the stack @@ -82,7 +85,8 @@ non-members ----------- .. code-block:: cpp - :caption: functions: reference comparators + :caption: operators: reference comparators + :name: reference-operators-comparators bool operator==(const reference&, const reference&); bool operator!=(const reference&, const reference&); diff --git a/single/sol/sol.hpp b/single/sol/sol.hpp index 5dbdcc88..891160cc 100644 --- a/single/sol/sol.hpp +++ b/single/sol/sol.hpp @@ -20,8 +20,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // This file was generated with a script. -// Generated 2018-01-24 05:51:13.838328 UTC -// This header was generated with sol v2.19.0 (revision 83f4b4a) +// Generated 2018-01-29 03:18:59.612757 UTC +// This header was generated with sol v2.19.0 (revision 143c984) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_HPP @@ -189,6 +189,12 @@ #endif #endif // avoiding nil defines / keywords +#ifdef SOL_USE_BOOST +#ifndef SOL_UNORDERED_MAP_COMPATIBLE_HASH +#define SOL_UNORDERED_MAP_COMPATIBLE_HASH +#endif // SOL_UNORDERED_MAP_COMPATIBLE_HASH +#endif // Boost has unordered_map with Compatible Key and CompatibleHash + // end of sol/feature_test.hpp namespace sol { @@ -1485,10 +1491,11 @@ namespace sol { template using is_string_constructible = any< - std::is_same, const char*>, std::is_same, char>, std::is_same, std::string>, std::is_same, std::initializer_list> + meta::all>, std::is_same>>, char>>, + std::is_same, const char*>, + std::is_same, char>, std::is_same, std::string>, std::is_same, std::initializer_list> #ifdef SOL_CXX17_FEATURES - , - std::is_same, std::string_view> + , std::is_same, std::string_view> #endif >; @@ -4146,6 +4153,9 @@ namespace sol { #ifdef SOL_CXX17_FEATURES #endif // C++17 features +#ifdef SOL_USE_BOOST +#include +#endif namespace sol { #ifdef SOL_CXX17_FEATURES @@ -4153,6 +4163,7 @@ namespace sol { typedef std::wstring_view wstring_view; typedef std::u16string_view u16string_view; typedef std::u32string_view u32string_view; + typedef std::hash string_view_hash; #else template > struct basic_string_view { @@ -4208,12 +4219,16 @@ namespace sol { return size(); } + operator std::basic_string() const { + return std::basic_string(data(), size()); + } + bool operator==(const basic_string_view& r) const { return compare(p, s, r.data(), r.size()) == 0; } bool operator==(const Char* r) const { - return compare(r, std::char_traits::length(r), p, s) == 0; + return compare(r, Traits::length(r), p, s) == 0; } bool operator==(const std::basic_string& r) const { @@ -4233,10 +4248,50 @@ namespace sol { } }; + template > + struct basic_string_view_hash { + typedef basic_string_view argument_type; + typedef std::size_t result_type; + + template + result_type operator()(const std::basic_string& r) const { + return (*this)(basic_string_view(r.c_str(), r.size())); + } + + result_type operator()(const argument_type& r) const { +#ifdef SOL_USE_BOOST + return boost::hash_range(r.begin(), r.end()); +#else + // Modified, from libstdc++ + // An implementation attempt at Fowler No Voll, 1a. + // Supposedly, used in MSVC, + // GCC (libstdc++) uses MurmurHash of some sort for 64-bit though...? + // But, well. Can't win them all, right? + // This should normally only apply when NOT using boost, + // so this should almost never be tapped into... + std::size_t hash = 0; + const unsigned char* cptr = reinterpret_cast(r.data()); + for (std::size_t sz = r.size(); sz != 0; --sz) { + hash ^= static_cast(*cptr++); + hash *= static_cast(1099511628211ULL); + } + return hash; +#endif + } + }; +} // namespace sol + +namespace std { + template + struct hash< ::sol::basic_string_view > : ::sol::basic_string_view_hash {}; +} // namespace std + +namespace sol { using string_view = basic_string_view; using wstring_view = basic_string_view; using u16string_view = basic_string_view; using u32string_view = basic_string_view; + using string_view_hash = std::hash; #endif // C++17 Support } // namespace sol @@ -6231,6 +6286,7 @@ namespace sol { return; } if (r.ref == LUA_NOREF) { + luastate = r.luastate; ref = LUA_NOREF; return; } @@ -6254,6 +6310,7 @@ namespace sol { return; } if (r.ref == LUA_NOREF) { + luastate = r.luastate; ref = LUA_NOREF; return; } @@ -6412,6 +6469,15 @@ namespace sol { return *this; } + basic_reference& operator=(const lua_nil_t&) noexcept { + if (valid()) { + deref(); + } + luastate = nullptr; + ref = LUA_NOREF; + return *this; + } + template basic_reference& operator=(proxy_base&& r); @@ -10586,11 +10652,11 @@ namespace sol { return call_into_lua(returns_list(), args_list(), L, start, std::forward(fx), std::forward(fxargs)...); } - inline call_syntax get_call_syntax(lua_State* L, const std::string& key, int index) { + inline call_syntax get_call_syntax(lua_State* L, const string_view& key, int index) { if (lua_gettop(L) == 0) { return call_syntax::dot; } - luaL_getmetatable(L, key.c_str()); + luaL_getmetatable(L, key.data()); auto pn = pop_n(L, 1); if (lua_compare(L, -1, index, LUA_OPEQ) != 1) { return call_syntax::dot; @@ -11916,7 +11982,7 @@ namespace sol { inline int construct(lua_State* L) { static const auto& meta = usertype_traits::metatable(); int argcount = lua_gettop(L); - call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, &usertype_traits::user_metatable()[0], 1) : call_syntax::dot; + call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, usertype_traits::user_metatable(), 1) : call_syntax::dot; argcount -= static_cast(syntax); T* obj = detail::usertype_allocate(L); @@ -12215,7 +12281,7 @@ namespace sol { static int call(lua_State* L, F&) { const auto& metakey = usertype_traits::metatable(); int argcount = lua_gettop(L); - call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, &usertype_traits::user_metatable()[0], 1) : call_syntax::dot; + call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, usertype_traits::user_metatable(), 1) : call_syntax::dot; argcount -= static_cast(syntax); T* obj = detail::usertype_allocate(L); @@ -12264,7 +12330,7 @@ namespace sol { }; static int call(lua_State* L, F& f) { - call_syntax syntax = stack::get_call_syntax(L, &usertype_traits::user_metatable()[0], 1); + call_syntax syntax = stack::get_call_syntax(L, usertype_traits::user_metatable(), 1); int syntaxval = static_cast(syntax); int argcount = lua_gettop(L) - syntaxval; return construct_match>...>(onmatch(), L, argcount, 1 + syntaxval, f); @@ -13511,7 +13577,7 @@ namespace sol { using base_t::lua_state; basic_function() = default; - template , basic_function>>, meta::neg>, is_lua_reference>> = meta::enabler> + template , basic_function>>, meta::neg>, meta::neg>>, is_lua_reference>> = meta::enabler> basic_function(T&& r) noexcept : base_t(std::forward(r)) { #ifdef SOL_SAFE_REFERENCES @@ -13532,6 +13598,9 @@ namespace sol { basic_function(stack_reference&& r) : basic_function(r.lua_state(), r.stack_index()) { } + basic_function(lua_nil_t n) + : base_t(n) { + } template >> = meta::enabler> basic_function(lua_State* L, T&& r) : base_t(L, std::forward(r)) { @@ -13753,7 +13822,7 @@ namespace sol { handler_t error_handler; basic_protected_function() = default; - template , basic_protected_function>>, meta::neg>>, meta::neg>, is_lua_reference>> = meta::enabler> + template , basic_protected_function>>, meta::neg>>, meta::neg>, meta::neg>>, is_lua_reference>> = meta::enabler> basic_protected_function(T&& r) noexcept : base_t(std::forward(r)), error_handler(get_default_handler(r.lua_state())) { #ifdef SOL_SAFE_REFERENCES @@ -13819,6 +13888,10 @@ namespace sol { stack::check(lua_state(), -1, handler); #endif // Safety } + + basic_protected_function(lua_nil_t n) + : base_t(n), error_handler(n) { + } basic_protected_function(lua_State* L, int index = -1) : basic_protected_function(L, index, get_default_handler(L)) { @@ -16640,8 +16713,20 @@ namespace sol { #include #include +#ifdef SOL_USE_BOOST +#include +#endif // Using Boost + namespace sol { namespace usertype_detail { +#ifdef SOL_USE_BOOST + template , typename E = std::equal_to<>> + using map_t = boost::unordered_map; +#else + template , typename E = std::equal_to<>> + using map_t = std::unordered_map; +#endif // Boost map target + const int metatable_index = 2; const int metatable_core_index = 3; const int filler_index = 4; @@ -16666,8 +16751,8 @@ namespace sol { : index(index), new_index(newindex), runtime_target(runtimetarget) { } }; - - typedef std::unordered_map mapping_t; + + typedef map_t mapping_t; struct variable_wrapper { virtual int index(lua_State* L) = 0; @@ -16693,8 +16778,8 @@ namespace sol { } }; - typedef std::unordered_map> variable_map; - typedef std::unordered_map function_map; + typedef map_t> variable_map; + typedef map_t function_map; struct simple_map { const char* metakey; @@ -16815,8 +16900,8 @@ namespace sol { inline int indexing_fail(lua_State* L) { if (is_index) { #if 0 //def SOL_SAFE_USERTYPE - auto maybeaccessor = stack::get>(L, is_index ? -1 : -2); - string_detail::string_shim accessor = maybeaccessor.value_or(string_detail::string_shim("(unknown)")); + auto maybeaccessor = stack::get>(L, is_index ? -1 : -2); + string_view accessor = maybeaccessor.value_or(string_detail::string_shim("(unknown)")); return luaL_error(L, "sol: attempt to index (get) nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.data()); #else if (is_toplevel(L)) { @@ -16846,13 +16931,21 @@ namespace sol { if (is_simple) { simple_map& sm = stack::get>(L, upvalue_index(simple_metatable_index)); function_map& functions = sm.functions; - optional maybeaccessor = stack::get>(L, 2); + optional maybeaccessor = stack::get>(L, 2); if (!maybeaccessor) { return; } - std::string& accessor = maybeaccessor.value(); + string_view& accessor_view = maybeaccessor.value(); +#ifdef SOL_UNORDERED_MAP_COMPATIBLE_HASH + auto preexistingit = functions.find(accessor_view, string_view_hash(), std::equal_to()); +#else + std::string accessor(accessor_view.data(), accessor_view.size()); auto preexistingit = functions.find(accessor); +#endif if (preexistingit == functions.cend()) { +#ifdef SOL_UNORDERED_MAP_COMPATIBLE_HASH + std::string accessor(accessor_view.data(), accessor_view.size()); +#endif functions.emplace_hint(preexistingit, std::move(accessor), object(L, 3)); } else { @@ -16864,18 +16957,26 @@ namespace sol { bool mustindex = umc.mustindex; if (!mustindex) return; - optional maybeaccessor = stack::get>(L, 2); + optional maybeaccessor = stack::get>(L, 2); if (!maybeaccessor) { return; } - std::string& accessor = maybeaccessor.value(); + string_view& accessor_view = maybeaccessor.value(); mapping_t& mapping = umc.mapping; std::vector& runtime = umc.runtime; int target = static_cast(runtime.size()); +#ifdef SOL_UNORDERED_MAP_COMPATIBLE_HASH + auto preexistingit = mapping.find(accessor_view, string_view_hash(), std::equal_to()); +#else + std::string accessor(accessor_view.data(), accessor_view.size()); auto preexistingit = mapping.find(accessor); +#endif if (preexistingit == mapping.cend()) { +#ifdef SOL_UNORDERED_MAP_COMPATIBLE_HASH + std::string accessor(accessor_view.data(), accessor_view.size()); +#endif runtime.emplace_back(L, 3); - mapping.emplace_hint(mapping.cend(), accessor, call_information(&runtime_object_call, &runtime_new_index, target)); + mapping.emplace_hint(mapping.cend(), std::move(accessor), call_information(&runtime_object_call, &runtime_new_index, target)); } else { target = preexistingit->second.runtime_target; @@ -17158,8 +17259,13 @@ namespace sol { int runtime_target = 0; usertype_detail::member_search member = nullptr; { +#ifdef SOL_UNORDERED_MAP_COMPATIBLE_HASH + string_view name = stack::get(L, keyidx); + auto memberit = f.mapping.find(name, string_view_hash(), std::equal_to()); +#else std::string name = stack::get(L, keyidx); auto memberit = f.mapping.find(name); +#endif if (memberit != f.mapping.cend()) { const usertype_detail::call_information& ci = memberit->second; member = is_index ? ci.index : ci.new_index; @@ -17440,8 +17546,13 @@ namespace sol { string_view accessor = stack::get(L, keyidx); variable_wrapper* varwrap = nullptr; { +#ifdef SOL_UNORDERED_MAP_COMPATIBLE_HASH + string_view& accessorkey = accessor; + auto vit = variables.find(accessorkey, string_view_hash(), std::equal_to()); +#else std::string accessorkey(accessor.data(), accessor.size()); auto vit = variables.find(accessorkey); +#endif // Compatible Hash if (vit != variables.cend()) { varwrap = vit->second.get(); } @@ -17451,8 +17562,13 @@ namespace sol { } bool function_failed = false; { +#ifdef SOL_UNORDERED_MAP_COMPATIBLE_HASH + string_view& accessorkey = accessor; + auto fit = functions.find(accessorkey, string_view_hash(), std::equal_to()); +#else std::string accessorkey(accessor.data(), accessor.size()); auto fit = functions.find(accessorkey); +#endif // Compatible Hash if (fit != functions.cend()) { object& func = fit->second; if (is_index) { @@ -18344,13 +18460,16 @@ namespace sol { } protected: + basic_table_core(detail::no_safety_tag, lua_nil_t n) + : base_t(n) { + } basic_table_core(detail::no_safety_tag, lua_State* L, int index) : base_t(L, index) { } basic_table_core(detail::no_safety_tag, lua_State* L, ref_index index) : base_t(L, index) { } - template , basic_table_core>>, meta::neg>, is_lua_reference>> = meta::enabler> + template , basic_table_core>>, meta::neg>, meta::neg>>, is_lua_reference>> = meta::enabler> basic_table_core(detail::no_safety_tag, T&& r) noexcept : base_t(std::forward(r)) { } @@ -18406,7 +18525,7 @@ namespace sol { stack::check(lua_state(), -1, handler); #endif // Safety } - template , basic_table_core>>, meta::neg>, is_lua_reference>> = meta::enabler> + template , basic_table_core>>, meta::neg>, meta::neg>>, is_lua_reference>> = meta::enabler> basic_table_core(T&& r) noexcept : basic_table_core(detail::no_safety, std::forward(r)) { #ifdef SOL_SAFE_REFERENCES @@ -18417,6 +18536,9 @@ namespace sol { } #endif // Safety } + basic_table_core(lua_nil_t r) noexcept + : basic_table_core(detail::no_safety, r) { + } iterator begin() const { return iterator(*this); @@ -18849,7 +18971,7 @@ namespace sol { stack::check(L, -1, handler); #endif // Safety } - template , basic_environment>>, meta::neg>, is_lua_reference>> = meta::enabler> + template , basic_environment>>, meta::neg>, meta::neg>>, is_lua_reference>> = meta::enabler> basic_environment(T&& r) noexcept : base_t(detail::no_safety, std::forward(r)) { #ifdef SOL_SAFE_REFERENCES @@ -18860,6 +18982,10 @@ namespace sol { } #endif // Safety } + basic_environment(lua_nil_t r) noexcept + : base_t(detail::no_safety, r) { + } + template >> = meta::enabler> basic_environment(lua_State* L, T&& r) noexcept : base_t(detail::no_safety, L, std::forward(r)) { @@ -19141,14 +19267,14 @@ namespace sol { return result; } - inline protected_function_result script_default_on_error(lua_State* L, protected_function_result pfr) { - type t = type_of(L, pfr.stack_index()); + inline protected_function_result script_throw_on_error(lua_State*L, protected_function_result result) { + type t = type_of(L, result.stack_index()); std::string err = "sol: "; - err += to_string(pfr.status()); + err += to_string(result.status()); err += " error:"; if (t == type::string) { err += " "; - string_view serr = stack::get(L, pfr.stack_index()); + string_view serr = stack::get(L, result.stack_index()); err.append(serr.data(), serr.size()); } #ifdef SOL_NO_EXCEPTIONS @@ -19161,7 +19287,15 @@ namespace sol { // just throw our error throw error(detail::direct_error, err); #endif - return pfr; + return result; + } + + inline protected_function_result script_default_on_error(lua_State* L, protected_function_result pfr) { +#ifdef SOL_DEFAULT_PASS_ON_ERROR + return script_pass_on_error(L, std::move(pfr)); +#else + return script_throw_on_error(L, std::move(pfr)); +#endif } class state_view { @@ -19392,7 +19526,7 @@ namespace sol { return pf(); } - template >> = meta::enabler> + template >, meta::is_specialization_of>> = meta::enabler> protected_function_result safe_script(const string_view& code, Fx&& on_error, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { protected_function_result pfr = do_string(code, chunkname, mode); if (!pfr.valid()) { @@ -19419,7 +19553,7 @@ namespace sol { return safe_script(code, script_default_on_error, chunkname, mode); } - template >> = meta::enabler> + template >, meta::is_specialization_of>> = meta::enabler> protected_function_result safe_script_file(const std::string& filename, Fx&& on_error, load_mode mode = load_mode::any) { protected_function_result pfr = do_file(filename, mode); if (!pfr.valid()) { @@ -19494,12 +19628,12 @@ namespace sol { return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns); } - template >> = meta::enabler> + template >, meta::is_specialization_of>> = meta::enabler> protected_function_result script(const string_view& code, Fx&& on_error, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { return safe_script(code, std::forward(on_error), chunkname, mode); } - template >> = meta::enabler> + template >, meta::is_specialization_of>> = meta::enabler> protected_function_result script_file(const std::string& filename, Fx&& on_error, load_mode mode = load_mode::any) { return safe_script_file(filename, std::forward(on_error), mode); } diff --git a/single/sol/sol_forward.hpp b/single/sol/sol_forward.hpp index 6c525d36..94a23c51 100644 --- a/single/sol/sol_forward.hpp +++ b/single/sol/sol_forward.hpp @@ -20,8 +20,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // This file was generated with a script. -// Generated 2018-01-24 05:51:14.129707 UTC -// This header was generated with sol v2.19.0 (revision 83f4b4a) +// Generated 2018-01-29 03:18:59.904294 UTC +// This header was generated with sol v2.19.0 (revision 143c984) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP @@ -156,6 +156,12 @@ #endif #endif // avoiding nil defines / keywords +#ifdef SOL_USE_BOOST +#ifndef SOL_UNORDERED_MAP_COMPATIBLE_HASH +#define SOL_UNORDERED_MAP_COMPATIBLE_HASH +#endif // SOL_UNORDERED_MAP_COMPATIBLE_HASH +#endif // Boost has unordered_map with Compatible Key and CompatibleHash + // end of sol/feature_test.hpp namespace sol { diff --git a/sol/call.hpp b/sol/call.hpp index f48d2533..0c5de80d 100644 --- a/sol/call.hpp +++ b/sol/call.hpp @@ -210,7 +210,7 @@ namespace sol { inline int construct(lua_State* L) { static const auto& meta = usertype_traits::metatable(); int argcount = lua_gettop(L); - call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, &usertype_traits::user_metatable()[0], 1) : call_syntax::dot; + call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, usertype_traits::user_metatable(), 1) : call_syntax::dot; argcount -= static_cast(syntax); T* obj = detail::usertype_allocate(L); @@ -509,7 +509,7 @@ namespace sol { static int call(lua_State* L, F&) { const auto& metakey = usertype_traits::metatable(); int argcount = lua_gettop(L); - call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, &usertype_traits::user_metatable()[0], 1) : call_syntax::dot; + call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, usertype_traits::user_metatable(), 1) : call_syntax::dot; argcount -= static_cast(syntax); T* obj = detail::usertype_allocate(L); @@ -558,7 +558,7 @@ namespace sol { }; static int call(lua_State* L, F& f) { - call_syntax syntax = stack::get_call_syntax(L, &usertype_traits::user_metatable()[0], 1); + call_syntax syntax = stack::get_call_syntax(L, usertype_traits::user_metatable(), 1); int syntaxval = static_cast(syntax); int argcount = lua_gettop(L) - syntaxval; return construct_match>...>(onmatch(), L, argcount, 1 + syntaxval, f); diff --git a/sol/environment.hpp b/sol/environment.hpp index 0686367f..7820622a 100644 --- a/sol/environment.hpp +++ b/sol/environment.hpp @@ -92,7 +92,7 @@ namespace sol { stack::check(L, -1, handler); #endif // Safety } - template , basic_environment>>, meta::neg>, is_lua_reference>> = meta::enabler> + template , basic_environment>>, meta::neg>, meta::neg>>, is_lua_reference>> = meta::enabler> basic_environment(T&& r) noexcept : base_t(detail::no_safety, std::forward(r)) { #ifdef SOL_SAFE_REFERENCES @@ -103,6 +103,10 @@ namespace sol { } #endif // Safety } + basic_environment(lua_nil_t r) noexcept + : base_t(detail::no_safety, r) { + } + template >> = meta::enabler> basic_environment(lua_State* L, T&& r) noexcept : base_t(detail::no_safety, L, std::forward(r)) { diff --git a/sol/feature_test.hpp b/sol/feature_test.hpp index 9700f7fc..73f603e6 100644 --- a/sol/feature_test.hpp +++ b/sol/feature_test.hpp @@ -181,4 +181,10 @@ #endif #endif // avoiding nil defines / keywords +#ifdef SOL_USE_BOOST +#ifndef SOL_UNORDERED_MAP_COMPATIBLE_HASH +#define SOL_UNORDERED_MAP_COMPATIBLE_HASH +#endif // SOL_UNORDERED_MAP_COMPATIBLE_HASH +#endif // Boost has unordered_map with Compatible Key and CompatibleHash + #endif // SOL_FEATURE_TEST_HPP diff --git a/sol/protected_function.hpp b/sol/protected_function.hpp index 571634bd..aba83398 100644 --- a/sol/protected_function.hpp +++ b/sol/protected_function.hpp @@ -202,7 +202,7 @@ namespace sol { handler_t error_handler; basic_protected_function() = default; - template , basic_protected_function>>, meta::neg>>, meta::neg>, is_lua_reference>> = meta::enabler> + template , basic_protected_function>>, meta::neg>>, meta::neg>, meta::neg>>, is_lua_reference>> = meta::enabler> basic_protected_function(T&& r) noexcept : base_t(std::forward(r)), error_handler(get_default_handler(r.lua_state())) { #ifdef SOL_SAFE_REFERENCES @@ -268,6 +268,10 @@ namespace sol { stack::check(lua_state(), -1, handler); #endif // Safety } + + basic_protected_function(lua_nil_t n) + : base_t(n), error_handler(n) { + } basic_protected_function(lua_State* L, int index = -1) : basic_protected_function(L, index, get_default_handler(L)) { diff --git a/sol/reference.hpp b/sol/reference.hpp index e87e4e63..fefc07fd 100644 --- a/sol/reference.hpp +++ b/sol/reference.hpp @@ -199,6 +199,7 @@ namespace sol { return; } if (r.ref == LUA_NOREF) { + luastate = r.luastate; ref = LUA_NOREF; return; } @@ -222,6 +223,7 @@ namespace sol { return; } if (r.ref == LUA_NOREF) { + luastate = r.luastate; ref = LUA_NOREF; return; } @@ -380,6 +382,15 @@ namespace sol { return *this; } + basic_reference& operator=(const lua_nil_t&) noexcept { + if (valid()) { + deref(); + } + luastate = nullptr; + ref = LUA_NOREF; + return *this; + } + template basic_reference& operator=(proxy_base&& r); diff --git a/sol/simple_usertype_metatable.hpp b/sol/simple_usertype_metatable.hpp index 2a443c9d..9c893f1b 100644 --- a/sol/simple_usertype_metatable.hpp +++ b/sol/simple_usertype_metatable.hpp @@ -70,8 +70,13 @@ namespace sol { string_view accessor = stack::get(L, keyidx); variable_wrapper* varwrap = nullptr; { +#ifdef SOL_UNORDERED_MAP_COMPATIBLE_HASH + string_view& accessorkey = accessor; + auto vit = variables.find(accessorkey, string_view_hash(), std::equal_to()); +#else std::string accessorkey(accessor.data(), accessor.size()); auto vit = variables.find(accessorkey); +#endif // Compatible Hash if (vit != variables.cend()) { varwrap = vit->second.get(); } @@ -81,8 +86,13 @@ namespace sol { } bool function_failed = false; { +#ifdef SOL_UNORDERED_MAP_COMPATIBLE_HASH + string_view& accessorkey = accessor; + auto fit = functions.find(accessorkey, string_view_hash(), std::equal_to()); +#else std::string accessorkey(accessor.data(), accessor.size()); auto fit = functions.find(accessorkey); +#endif // Compatible Hash if (fit != functions.cend()) { object& func = fit->second; if (is_index) { diff --git a/sol/stack.hpp b/sol/stack.hpp index f63d919d..c49978a0 100644 --- a/sol/stack.hpp +++ b/sol/stack.hpp @@ -207,11 +207,11 @@ namespace sol { return call_into_lua(returns_list(), args_list(), L, start, std::forward(fx), std::forward(fxargs)...); } - inline call_syntax get_call_syntax(lua_State* L, const std::string& key, int index) { + inline call_syntax get_call_syntax(lua_State* L, const string_view& key, int index) { if (lua_gettop(L) == 0) { return call_syntax::dot; } - luaL_getmetatable(L, key.c_str()); + luaL_getmetatable(L, key.data()); auto pn = pop_n(L, 1); if (lua_compare(L, -1, index, LUA_OPEQ) != 1) { return call_syntax::dot; diff --git a/sol/state_view.hpp b/sol/state_view.hpp index 59b6f28e..83f09eeb 100644 --- a/sol/state_view.hpp +++ b/sol/state_view.hpp @@ -73,14 +73,14 @@ namespace sol { return result; } - inline protected_function_result script_default_on_error(lua_State* L, protected_function_result pfr) { - type t = type_of(L, pfr.stack_index()); + inline protected_function_result script_throw_on_error(lua_State*L, protected_function_result result) { + type t = type_of(L, result.stack_index()); std::string err = "sol: "; - err += to_string(pfr.status()); + err += to_string(result.status()); err += " error:"; if (t == type::string) { err += " "; - string_view serr = stack::get(L, pfr.stack_index()); + string_view serr = stack::get(L, result.stack_index()); err.append(serr.data(), serr.size()); } #ifdef SOL_NO_EXCEPTIONS @@ -93,7 +93,15 @@ namespace sol { // just throw our error throw error(detail::direct_error, err); #endif - return pfr; + return result; + } + + inline protected_function_result script_default_on_error(lua_State* L, protected_function_result pfr) { +#ifdef SOL_DEFAULT_PASS_ON_ERROR + return script_pass_on_error(L, std::move(pfr)); +#else + return script_throw_on_error(L, std::move(pfr)); +#endif } class state_view { @@ -324,7 +332,7 @@ namespace sol { return pf(); } - template >> = meta::enabler> + template >, meta::is_specialization_of>> = meta::enabler> protected_function_result safe_script(const string_view& code, Fx&& on_error, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { protected_function_result pfr = do_string(code, chunkname, mode); if (!pfr.valid()) { @@ -351,7 +359,7 @@ namespace sol { return safe_script(code, script_default_on_error, chunkname, mode); } - template >> = meta::enabler> + template >, meta::is_specialization_of>> = meta::enabler> protected_function_result safe_script_file(const std::string& filename, Fx&& on_error, load_mode mode = load_mode::any) { protected_function_result pfr = do_file(filename, mode); if (!pfr.valid()) { @@ -426,12 +434,12 @@ namespace sol { return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns); } - template >> = meta::enabler> + template >, meta::is_specialization_of>> = meta::enabler> protected_function_result script(const string_view& code, Fx&& on_error, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { return safe_script(code, std::forward(on_error), chunkname, mode); } - template >> = meta::enabler> + template >, meta::is_specialization_of>> = meta::enabler> protected_function_result script_file(const std::string& filename, Fx&& on_error, load_mode mode = load_mode::any) { return safe_script_file(filename, std::forward(on_error), mode); } diff --git a/sol/string_view.hpp b/sol/string_view.hpp index 4a83f549..794ad0b1 100644 --- a/sol/string_view.hpp +++ b/sol/string_view.hpp @@ -30,6 +30,10 @@ #ifdef SOL_CXX17_FEATURES #include #endif // C++17 features +#include +#ifdef SOL_USE_BOOST +#include +#endif namespace sol { #ifdef SOL_CXX17_FEATURES @@ -37,6 +41,7 @@ namespace sol { typedef std::wstring_view wstring_view; typedef std::u16string_view u16string_view; typedef std::u32string_view u32string_view; + typedef std::hash string_view_hash; #else template > struct basic_string_view { @@ -92,12 +97,16 @@ namespace sol { return size(); } + operator std::basic_string() const { + return std::basic_string(data(), size()); + } + bool operator==(const basic_string_view& r) const { return compare(p, s, r.data(), r.size()) == 0; } bool operator==(const Char* r) const { - return compare(r, std::char_traits::length(r), p, s) == 0; + return compare(r, Traits::length(r), p, s) == 0; } bool operator==(const std::basic_string& r) const { @@ -117,10 +126,50 @@ namespace sol { } }; + template > + struct basic_string_view_hash { + typedef basic_string_view argument_type; + typedef std::size_t result_type; + + template + result_type operator()(const std::basic_string& r) const { + return (*this)(basic_string_view(r.c_str(), r.size())); + } + + result_type operator()(const argument_type& r) const { +#ifdef SOL_USE_BOOST + return boost::hash_range(r.begin(), r.end()); +#else + // Modified, from libstdc++ + // An implementation attempt at Fowler No Voll, 1a. + // Supposedly, used in MSVC, + // GCC (libstdc++) uses MurmurHash of some sort for 64-bit though...? + // But, well. Can't win them all, right? + // This should normally only apply when NOT using boost, + // so this should almost never be tapped into... + std::size_t hash = 0; + const unsigned char* cptr = reinterpret_cast(r.data()); + for (std::size_t sz = r.size(); sz != 0; --sz) { + hash ^= static_cast(*cptr++); + hash *= static_cast(1099511628211ULL); + } + return hash; +#endif + } + }; +} // namespace sol + +namespace std { + template + struct hash< ::sol::basic_string_view > : ::sol::basic_string_view_hash {}; +} // namespace std + +namespace sol { using string_view = basic_string_view; using wstring_view = basic_string_view; using u16string_view = basic_string_view; using u32string_view = basic_string_view; + using string_view_hash = std::hash; #endif // C++17 Support } // namespace sol diff --git a/sol/table_core.hpp b/sol/table_core.hpp index b07d25ac..7cc93fb5 100644 --- a/sol/table_core.hpp +++ b/sol/table_core.hpp @@ -180,13 +180,16 @@ namespace sol { } protected: + basic_table_core(detail::no_safety_tag, lua_nil_t n) + : base_t(n) { + } basic_table_core(detail::no_safety_tag, lua_State* L, int index) : base_t(L, index) { } basic_table_core(detail::no_safety_tag, lua_State* L, ref_index index) : base_t(L, index) { } - template , basic_table_core>>, meta::neg>, is_lua_reference>> = meta::enabler> + template , basic_table_core>>, meta::neg>, meta::neg>>, is_lua_reference>> = meta::enabler> basic_table_core(detail::no_safety_tag, T&& r) noexcept : base_t(std::forward(r)) { } @@ -242,7 +245,7 @@ namespace sol { stack::check(lua_state(), -1, handler); #endif // Safety } - template , basic_table_core>>, meta::neg>, is_lua_reference>> = meta::enabler> + template , basic_table_core>>, meta::neg>, meta::neg>>, is_lua_reference>> = meta::enabler> basic_table_core(T&& r) noexcept : basic_table_core(detail::no_safety, std::forward(r)) { #ifdef SOL_SAFE_REFERENCES @@ -253,6 +256,9 @@ namespace sol { } #endif // Safety } + basic_table_core(lua_nil_t r) noexcept + : basic_table_core(detail::no_safety, r) { + } iterator begin() const { return iterator(*this); diff --git a/sol/traits.hpp b/sol/traits.hpp index 622b6114..76189f3b 100644 --- a/sol/traits.hpp +++ b/sol/traits.hpp @@ -555,10 +555,11 @@ namespace sol { template using is_string_constructible = any< - std::is_same, const char*>, std::is_same, char>, std::is_same, std::string>, std::is_same, std::initializer_list> + meta::all>, std::is_same>>, char>>, + std::is_same, const char*>, + std::is_same, char>, std::is_same, std::string>, std::is_same, std::initializer_list> #ifdef SOL_CXX17_FEATURES - , - std::is_same, std::string_view> + , std::is_same, std::string_view> #endif >; diff --git a/sol/unsafe_function.hpp b/sol/unsafe_function.hpp index 515c4bbb..9ce29cb6 100644 --- a/sol/unsafe_function.hpp +++ b/sol/unsafe_function.hpp @@ -68,7 +68,7 @@ namespace sol { using base_t::lua_state; basic_function() = default; - template , basic_function>>, meta::neg>, is_lua_reference>> = meta::enabler> + template , basic_function>>, meta::neg>, meta::neg>>, is_lua_reference>> = meta::enabler> basic_function(T&& r) noexcept : base_t(std::forward(r)) { #ifdef SOL_SAFE_REFERENCES @@ -89,6 +89,9 @@ namespace sol { basic_function(stack_reference&& r) : basic_function(r.lua_state(), r.stack_index()) { } + basic_function(lua_nil_t n) + : base_t(n) { + } template >> = meta::enabler> basic_function(lua_State* L, T&& r) : base_t(L, std::forward(r)) { diff --git a/sol/usertype_metatable.hpp b/sol/usertype_metatable.hpp index 379ffff5..3b3c7610 100644 --- a/sol/usertype_metatable.hpp +++ b/sol/usertype_metatable.hpp @@ -42,8 +42,20 @@ #include #include +#ifdef SOL_USE_BOOST +#include +#endif // Using Boost + namespace sol { namespace usertype_detail { +#ifdef SOL_USE_BOOST + template , typename E = std::equal_to<>> + using map_t = boost::unordered_map; +#else + template , typename E = std::equal_to<>> + using map_t = std::unordered_map; +#endif // Boost map target + const int metatable_index = 2; const int metatable_core_index = 3; const int filler_index = 4; @@ -68,8 +80,8 @@ namespace sol { : index(index), new_index(newindex), runtime_target(runtimetarget) { } }; - - typedef std::unordered_map mapping_t; + + typedef map_t mapping_t; struct variable_wrapper { virtual int index(lua_State* L) = 0; @@ -95,8 +107,8 @@ namespace sol { } }; - typedef std::unordered_map> variable_map; - typedef std::unordered_map function_map; + typedef map_t> variable_map; + typedef map_t function_map; struct simple_map { const char* metakey; @@ -217,8 +229,8 @@ namespace sol { inline int indexing_fail(lua_State* L) { if (is_index) { #if 0 //def SOL_SAFE_USERTYPE - auto maybeaccessor = stack::get>(L, is_index ? -1 : -2); - string_detail::string_shim accessor = maybeaccessor.value_or(string_detail::string_shim("(unknown)")); + auto maybeaccessor = stack::get>(L, is_index ? -1 : -2); + string_view accessor = maybeaccessor.value_or(string_detail::string_shim("(unknown)")); return luaL_error(L, "sol: attempt to index (get) nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.data()); #else if (is_toplevel(L)) { @@ -248,13 +260,21 @@ namespace sol { if (is_simple) { simple_map& sm = stack::get>(L, upvalue_index(simple_metatable_index)); function_map& functions = sm.functions; - optional maybeaccessor = stack::get>(L, 2); + optional maybeaccessor = stack::get>(L, 2); if (!maybeaccessor) { return; } - std::string& accessor = maybeaccessor.value(); + string_view& accessor_view = maybeaccessor.value(); +#ifdef SOL_UNORDERED_MAP_COMPATIBLE_HASH + auto preexistingit = functions.find(accessor_view, string_view_hash(), std::equal_to()); +#else + std::string accessor(accessor_view.data(), accessor_view.size()); auto preexistingit = functions.find(accessor); +#endif if (preexistingit == functions.cend()) { +#ifdef SOL_UNORDERED_MAP_COMPATIBLE_HASH + std::string accessor(accessor_view.data(), accessor_view.size()); +#endif functions.emplace_hint(preexistingit, std::move(accessor), object(L, 3)); } else { @@ -266,18 +286,26 @@ namespace sol { bool mustindex = umc.mustindex; if (!mustindex) return; - optional maybeaccessor = stack::get>(L, 2); + optional maybeaccessor = stack::get>(L, 2); if (!maybeaccessor) { return; } - std::string& accessor = maybeaccessor.value(); + string_view& accessor_view = maybeaccessor.value(); mapping_t& mapping = umc.mapping; std::vector& runtime = umc.runtime; int target = static_cast(runtime.size()); +#ifdef SOL_UNORDERED_MAP_COMPATIBLE_HASH + auto preexistingit = mapping.find(accessor_view, string_view_hash(), std::equal_to()); +#else + std::string accessor(accessor_view.data(), accessor_view.size()); auto preexistingit = mapping.find(accessor); +#endif if (preexistingit == mapping.cend()) { +#ifdef SOL_UNORDERED_MAP_COMPATIBLE_HASH + std::string accessor(accessor_view.data(), accessor_view.size()); +#endif runtime.emplace_back(L, 3); - mapping.emplace_hint(mapping.cend(), accessor, call_information(&runtime_object_call, &runtime_new_index, target)); + mapping.emplace_hint(mapping.cend(), std::move(accessor), call_information(&runtime_object_call, &runtime_new_index, target)); } else { target = preexistingit->second.runtime_target; @@ -560,8 +588,13 @@ namespace sol { int runtime_target = 0; usertype_detail::member_search member = nullptr; { +#ifdef SOL_UNORDERED_MAP_COMPATIBLE_HASH + string_view name = stack::get(L, keyidx); + auto memberit = f.mapping.find(name, string_view_hash(), std::equal_to()); +#else std::string name = stack::get(L, keyidx); auto memberit = f.mapping.find(name); +#endif if (memberit != f.mapping.cend()) { const usertype_detail::call_information& ci = memberit->second; member = is_index ? ci.index : ci.new_index; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 583c2089..f6a429d4 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -40,6 +40,8 @@ function(CREATE_TEST test_target_name test_name is_single) OUTPUT_NAME ${test_name}) if (is_single) target_link_libraries(${test_target_name} sol2_single) + target_compile_definitions(${test_target_name} + PRIVATE TEST_SINGLE) else() target_link_libraries(${test_target_name} sol2) endif() diff --git a/tests/test_container_semantics.cpp b/tests/test_container_semantics.cpp index 4f874893..f67cc7d7 100644 --- a/tests/test_container_semantics.cpp +++ b/tests/test_container_semantics.cpp @@ -21,13 +21,8 @@ // 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. -#define SOL_CHECK_ARGUMENTS 1 -#define SOL_ENABLE_INTEROP 1 +#include "test_sol.hpp" -#ifdef TEST_SINGLE -#include -#endif // Single -#include #include #include @@ -668,12 +663,13 @@ void associative_ordered_container_key_value_check(sol::state& lua, T& data, T& #if SOL_LUA_VERSION > 502 lua["val"] = data; - lua.script(R"( + auto r = lua.safe_script(R"( for k, v in pairs(val) do collect(k, v) end print() -)"); +)", sol::script_pass_on_error); + REQUIRE(r.valid()); #else reflect = data; #endif @@ -688,8 +684,7 @@ for i=1,#c do v = c[i] assert(v == (i + 10)) end - )", - sol::script_pass_on_error); + )", sol::script_pass_on_error); REQUIRE(r1.valid()); } { @@ -1077,7 +1072,7 @@ TEST_CASE("containers/auxiliary functions test", "make sure the manipulation fun sol::state lua; lua.open_libraries(); - lua.safe_script(R"( + auto result1 = lua.safe_script(R"( function g (x) x:add(20) end @@ -1094,8 +1089,8 @@ function sf (x,v) return x:find(v) end -)"); - +)", sol::script_pass_on_error); + REQUIRE(result1.valid()); // Have the function we // just defined in Lua sol::function g = lua["g"]; @@ -1146,13 +1141,12 @@ end REQUIRE(map.empty()); REQUIRE(set.empty()); - REQUIRE_NOTHROW([&]() { - lua.safe_script(R"( + auto result2 = lua.safe_script(R"( c_arr[1] = 7 c_arr[2] = 7 c_arr[3] = 7 -)"); - }()); +)", sol::script_pass_on_error); + REQUIRE(result2.valid()); } TEST_CASE("containers/indices test", "test indices on fixed array types") { @@ -1190,27 +1184,25 @@ TEST_CASE("containers/as_container reference", "test that we can force a contain }); #if SOL_LUA_VERSION > 501 - REQUIRE_NOTHROW([&]() { - lua.safe_script(R"( + auto result1 = lua.safe_script(R"( mop = my_object.new(20) for i, v in pairs(mop) do assert(i == v) end print(mop) - )"); - }()); + )", sol::script_pass_on_error); + REQUIRE(result1.valid()); REQUIRE_NOTHROW([&]() { my_object& mo = lua["mop"]; REQUIRE((&mo == my_object::last_printed)); }()); #endif - REQUIRE_NOTHROW([&]() { - lua.safe_script(R"( + auto result2 = lua.safe_script(R"( mo = my_object(10) c_mo = mo c_iterable = mo:iterable() -)"); - }()); +)", sol::script_pass_on_error); + REQUIRE(result2.valid()); REQUIRE_NOTHROW([&]() { my_object& mo = lua["c_mo"]; @@ -1219,14 +1211,13 @@ c_iterable = mo:iterable() REQUIRE(mo == mo_iterable); }()); - REQUIRE_NOTHROW([&]() { - lua.safe_script(R"( + auto result3 = lua.safe_script(R"( s1 = c_mo:size() s1_len = #c_mo s1_iterable = c_iterable:size() s1_iterable_len = #c_iterable )"); - }()); + REQUIRE(result3.valid()); REQUIRE_NOTHROW([&]() { std::size_t s1 = lua["s1"]; @@ -1239,17 +1230,15 @@ s1_iterable_len = #c_iterable REQUIRE(s1_iterable == s1_iterable_len); }()); - REQUIRE_NOTHROW([&]() { - lua.safe_script(R"( + auto result4 = lua.safe_script(R"( for i=1,#c_mo do v_iterable = c_iterable[i] assert(v_iterable == i) end -)"); - }()); +)", sol::script_pass_on_error); + REQUIRE(result4.valid()); - REQUIRE_NOTHROW([&]() { - lua.safe_script(R"( + auto result5 = lua.safe_script(R"( mo(5, 20) c_iterable:insert(1, 100) v1 = c_iterable[1] @@ -1258,25 +1247,22 @@ s2_len = #c_mo s2_iterable = c_iterable:size() s2_iterable_len = #c_iterable print(mo) - )"); - }()); + )", sol::script_pass_on_error); + REQUIRE(result5.valid()); - REQUIRE_NOTHROW([&]() { - int v1 = lua["v1"]; - std::size_t s2 = lua["s2"]; - std::size_t s2_len = lua["s2_len"]; - std::size_t s2_iterable = lua["s2_iterable"]; - std::size_t s2_iterable_len = lua["s2_iterable_len"]; - REQUIRE(v1 == 100); - REQUIRE(s2 == 16); - REQUIRE(s2 == s2_len); - REQUIRE(s2 == s2_iterable_len); - REQUIRE(s2_iterable == s2_iterable_len); - }()); - REQUIRE_NOTHROW([&]() { - my_object& mo = lua["mo"]; - REQUIRE(&mo == my_object::last_printed); - }()); + int v1 = lua["v1"]; + std::size_t s2 = lua["s2"]; + std::size_t s2_len = lua["s2_len"]; + std::size_t s2_iterable = lua["s2_iterable"]; + std::size_t s2_iterable_len = lua["s2_iterable_len"]; + REQUIRE(v1 == 100); + REQUIRE(s2 == 16); + REQUIRE(s2 == s2_len); + REQUIRE(s2 == s2_iterable_len); + REQUIRE(s2_iterable == s2_iterable_len); + + my_object& mo = lua["mo"]; + REQUIRE(&mo == my_object::last_printed); } TEST_CASE("containers/as_container", "test that we can force a container to be treated like one despite the trait being false using the proper marker") { @@ -1288,21 +1274,19 @@ TEST_CASE("containers/as_container", "test that we can force a container to be t }); #if SOL_LUA_VERSION > 501 - REQUIRE_NOTHROW([&]() { - lua.safe_script(R"( + auto result1 = lua.safe_script(R"( mop = f(20) for i, v in pairs(mop) do assert(i == v) end )"); - }()); + REQUIRE(result1.valid()); #endif - REQUIRE_NOTHROW([&]() { - lua.safe_script(R"( + auto result2 = lua.safe_script(R"( mo = f(10) c_iterable = mo )"); - }()); + REQUIRE(result2.valid()); { my_object& mo = lua["mo"]; @@ -1311,12 +1295,11 @@ c_iterable = mo REQUIRE(mo == mo_iterable); } - REQUIRE_NOTHROW([&]() { - lua.safe_script(R"( + auto result3 = lua.safe_script(R"( s1_iterable = c_iterable:size() s1_iterable_len = #c_iterable )"); - }()); + REQUIRE(result3.valid()); { std::size_t s1_iterable = lua["s1_iterable"]; @@ -1325,23 +1308,21 @@ s1_iterable_len = #c_iterable REQUIRE(s1_iterable == s1_iterable_len); } - REQUIRE_NOTHROW([&]() { - lua.safe_script(R"( + auto result4 = lua.safe_script(R"( for i=1,#c_iterable do v_iterable = c_iterable[i] assert(v_iterable == i) end )"); - }()); + REQUIRE(result4.valid()); - REQUIRE_NOTHROW([&]() { - lua.safe_script(R"( + auto result5 = lua.safe_script(R"( c_iterable:insert(1, 100) v1 = c_iterable:get(1) s2_iterable = c_iterable:size() s2_iterable_len = #c_iterable )"); - }()); + REQUIRE(result5.valid()); { int v1 = lua["v1"]; diff --git a/tests/test_containers.cpp b/tests/test_containers.cpp index 7766c593..6fc0636a 100644 --- a/tests/test_containers.cpp +++ b/tests/test_containers.cpp @@ -21,10 +21,8 @@ // 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. -#define SOL_CHECK_ARGUMENTS 1 -#define SOL_ENABLE_INTEROP 1 +#include "test_sol.hpp" -#include #include #include @@ -182,7 +180,8 @@ TEST_CASE("containers/returns", "make sure that even references to vectors are b lua.set_function("f", [&]() -> std::vector& { return v; }); - lua.safe_script("x = f()"); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); sol::object x = lua["x"]; sol::type xt = x.get_type(); REQUIRE(xt == sol::type::userdata); @@ -288,8 +287,10 @@ TEST_CASE("containers/table conversion", "test table conversions with as_table a return sol::as_nested(std::vector{ "bark", "woof" }); }); - lua.safe_script("v1 = bark()"); - lua.safe_script("v2 = woof()"); + auto result1 = lua.safe_script("v1 = bark()", sol::script_pass_on_error); + REQUIRE(result1.valid()); + auto result2 = lua.safe_script("v2 = woof()", sol::script_pass_on_error); + REQUIRE(result2.valid()); sol::as_table_t> as_table_strings = lua["v1"]; sol::nested> nested_strings = lua["v2"]; @@ -305,7 +306,8 @@ TEST_CASE("containers/vector roundtrip", "make sure vectors can be round-tripped lua.set_function("f", [&]() -> std::vector& { return v; }); - lua.safe_script("x = f()"); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); std::vector x = lua["x"]; bool areequal = x == v; REQUIRE(areequal); @@ -317,7 +319,8 @@ TEST_CASE("containers/deque roundtrip", "make sure deques can be round-tripped") lua.set_function("f", [&]() -> std::deque& { return v; }); - lua.safe_script("x = f()"); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); std::deque x = lua["x"]; bool areequal = x == v; REQUIRE(areequal); @@ -329,7 +332,8 @@ TEST_CASE("containers/array roundtrip", "make sure arrays can be round-tripped") lua.set_function("f", [&]() -> std::array& { return v; }); - lua.safe_script("x = f()"); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); std::array x = lua["x"]; bool areequal = x == v; REQUIRE(areequal); @@ -341,7 +345,8 @@ TEST_CASE("containers/list roundtrip", "make sure lists can be round-tripped") { lua.set_function("f", [&]() -> std::list& { return v; }); - lua.safe_script("x = f()"); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); std::list x = lua["x"]; bool areequal = x == v; REQUIRE(areequal); @@ -353,7 +358,8 @@ TEST_CASE("containers/forward_list roundtrip", "make sure forward_lists can be r lua.set_function("f", [&]() -> std::forward_list& { return v; }); - lua.safe_script("x = f()"); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); std::forward_list x = lua["x"]; bool areequal = x == v; REQUIRE(areequal); @@ -365,7 +371,8 @@ TEST_CASE("containers/map roundtrip", "make sure maps can be round-tripped") { lua.set_function("f", [&]() -> std::map& { return v; }); - lua.safe_script("x = f()"); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); std::map x = lua["x"]; bool areequal = x == v; REQUIRE(areequal); @@ -377,7 +384,8 @@ TEST_CASE("containers/unordered_map roundtrip", "make sure unordered_maps can be lua.set_function("f", [&]() -> std::unordered_map& { return v; }); - lua.safe_script("x = f()"); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); std::unordered_map x = lua["x"]; bool areequal = x == v; REQUIRE(areequal); @@ -389,7 +397,8 @@ TEST_CASE("containers/unordered_set roundtrip", "make sure unordered_sets can be lua.set_function("f", [&]() -> std::unordered_set& { return v; }); - lua.safe_script("x = f()"); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); std::unordered_set x = lua["x"]; bool areequal = x == v; REQUIRE(areequal); @@ -401,7 +410,8 @@ TEST_CASE("containers/set roundtrip", "make sure sets can be round-tripped") { lua.set_function("f", [&]() -> std::set& { return v; }); - lua.safe_script("x = f()"); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); std::set x = lua["x"]; bool areequal = x == v; REQUIRE(areequal); @@ -413,7 +423,8 @@ TEST_CASE("containers/vector table roundtrip", "make sure vectors can be round-t lua.set_function("f", [&]() { return sol::as_table(v); }); - lua.safe_script("x = f()"); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); sol::as_table_t> x = lua["x"]; bool areequal = x.source == v; REQUIRE(areequal); @@ -425,7 +436,8 @@ TEST_CASE("containers/deque table roundtrip", "make sure deques can be round-tri lua.set_function("f", [&]() { return sol::as_table(v); }); - lua.safe_script("x = f()"); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); sol::as_table_t> x = lua["x"]; bool areequal = x.source == v; REQUIRE(areequal); @@ -437,7 +449,8 @@ TEST_CASE("containers/array table roundtrip", "make sure arrays can be round-tri lua.set_function("f", [&]() { return sol::as_table(v); }); - lua.safe_script("x = f()"); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); sol::as_table_t> x = lua["x"]; bool areequal = x.source == v; REQUIRE(areequal); @@ -449,7 +462,8 @@ TEST_CASE("containers/list table roundtrip", "make sure lists can be round-tripp lua.set_function("f", [&]() { return sol::as_table(v); }); - lua.safe_script("x = f()"); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); sol::as_table_t> x = lua["x"]; bool areequal = x.source == v; REQUIRE(areequal); @@ -461,7 +475,8 @@ TEST_CASE("containers/forward_list table roundtrip", "make sure forward_lists ca lua.set_function("f", [&]() { return sol::as_table(v); }); - lua.safe_script("x = f()"); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); sol::as_table_t> x = lua["x"]; bool areequal = x.source == v; REQUIRE(areequal); @@ -473,7 +488,8 @@ TEST_CASE("containers/map table roundtrip", "make sure maps can be round-tripped lua.set_function("f", [&]() { return sol::as_table(v); }); - lua.safe_script("x = f()"); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); sol::as_table_t> x = lua["x"]; bool areequal = x.source == v; REQUIRE(areequal); @@ -485,7 +501,8 @@ TEST_CASE("containers/unordered_map table roundtrip", "make sure unordered_maps lua.set_function("f", [&]() { return sol::as_table(v); }); - lua.safe_script("x = f()"); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); sol::as_table_t> x = lua["x"]; bool areequal = x.source == v; REQUIRE(areequal); @@ -497,7 +514,8 @@ TEST_CASE("containers/unordered_set table roundtrip", "make sure unordered_sets lua.set_function("f", [&]() { return sol::as_table(v); }); - lua.safe_script("x = f()"); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); sol::as_table_t> x = lua["x"]; bool areequal = x.source == v; REQUIRE(areequal); @@ -509,7 +527,8 @@ TEST_CASE("containers/set table roundtrip", "make sure sets can be round-tripped lua.set_function("f", [&]() { return sol::as_table(v); }); - lua.safe_script("x = f()"); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); sol::as_table_t> x = lua["x"]; bool areequal = x.source == v; REQUIRE(areequal); @@ -530,7 +549,7 @@ TEST_CASE("containers/custom usertype", "make sure container usertype metatables { auto result0 = lua.safe_script("assert(a:at(24) == 50)", sol::script_pass_on_error); REQUIRE(result0.valid()); - auto result1 = lua.safe_script("a:something()"); + auto result1 = lua.safe_script("a:something()", sol::script_pass_on_error); REQUIRE(result1.valid()); } lua.set("a", obj); @@ -554,8 +573,8 @@ TEST_CASE("containers/const serialization kvp", "make sure const keys / values a lua.set("a", std::ref(obj)); auto result0 = lua.safe_script("assert(a[24] == 50)", sol::script_pass_on_error); REQUIRE(result0.valid()); - auto result = lua.safe_script("a[24] = 51", sol::script_pass_on_error); - REQUIRE_FALSE(result.valid()); + auto result1 = lua.safe_script("a[24] = 51", sol::script_pass_on_error); + REQUIRE_FALSE(result1.valid()); auto result2 = lua.safe_script("assert(a[24] == 50)", sol::script_pass_on_error); REQUIRE(result2.valid()); } @@ -652,19 +671,21 @@ TEST_CASE("containers/const correctness", "usertype metatable names should reaso std::vector bar; bar.push_back(&vec); - lua.safe_script(R"( + auto result0 = lua.safe_script(R"( func = function(vecs) for i = 1, #vecs do vec = vecs[i] print(i, ":", vec.x, vec.y, vec.z) end end -)"); +)", sol::script_pass_on_error); + REQUIRE(result0.valid()); - REQUIRE_NOTHROW([&] { - lua["func"](foo); - lua["func"](bar); - }()); + sol::protected_function f(lua["func"]); + auto pfr1 = f(foo); + REQUIRE(pfr1.valid()); + auto pfr2 = f(bar); + REQUIRE(pfr2.valid()); } TEST_CASE("containers/arbitrary creation", "userdata and tables should be usable from standard containers") { @@ -771,10 +792,11 @@ TEST_CASE("containers/usertype transparency", "Make sure containers pass their a lua.new_usertype("B", "a_list", &B::a_list); - lua.safe_script(R"( + auto result = lua.safe_script(R"( b = B.new() a_ref = b.a_list[2] -)"); +)", sol::script_pass_on_error); + REQUIRE(result.valid()); B& b = lua["b"]; A& a_ref = lua["a_ref"]; @@ -836,9 +858,10 @@ TEST_CASE("containers/is container", "make sure the is_container trait behaves p machine m; lua["machine"] = &m; - lua.safe_script(R"( - machine:opt():output_help() - )"); + auto result0 = lua.safe_script(R"( + machine:opt():output_help() + )", sol::script_pass_on_error); + REQUIRE(result0.valid()); REQUIRE(options::last == &m.opt); REQUIRE(options::livingcount == 1); @@ -865,12 +888,13 @@ TEST_CASE("containers/readonly", "make sure readonly members are stored appropri ); lua["value"] = std::list{ {}, {}, {} }; - lua.safe_script(R"( + auto result0 = lua.safe_script(R"( a = foo.new() x = a.seq a.seq = value y = a.readonly_seq -)"); +)", sol::script_pass_on_error); + REQUIRE(result0.valid()); std::list& seqrefx = lua["x"]; std::list& seqrefy = lua["y"]; REQUIRE(&seqrefx == &seqrefy); @@ -883,7 +907,8 @@ TEST_CASE("containers/to_args", "Test that the to_args abstractions works") { sol::state lua; lua.open_libraries(); - lua.safe_script("function f (a, b, c, d) print(a, b, c, d) return a, b, c, d end"); + auto result1 = lua.safe_script("function f (a, b, c, d) print(a, b, c, d) return a, b, c, d end", sol::script_pass_on_error); + REQUIRE(result1.valid()); sol::function f = lua["f"]; int a, b, c, d; @@ -922,18 +947,21 @@ TEST_CASE("containers/ipairs test", "ensure that abstractions roundtrip properly return std::vector(5, &t); }); - lua.safe_script(R"( + auto result1 = lua.safe_script(R"( c = f() -)"); +)", sol::script_pass_on_error); + REQUIRE(result1.valid()); - lua.safe_script(R"( + auto result2 = lua.safe_script(R"( check = {} local i = 1 while c[i] do check[i] = c[i] i = i + 1 end -)"); +)", sol::script_pass_on_error); + REQUIRE(result2.valid()); + sol::table c = lua["check"]; for (std::size_t i = 1; i < 6; ++i) { thing& ct = c[i]; @@ -945,7 +973,8 @@ end TEST_CASE("containers/append idiom", "ensure the append-idiom works as intended") { sol::state lua; lua.open_libraries(sol::lib::base); - lua.safe_script( + + auto result1 = lua.safe_script( R"( function f_fill(vec) print("#vec in lua: " .. #vec) @@ -961,6 +990,8 @@ function f_append(vec) print("#vec in lua: " .. #vec) end )"); + REQUIRE(result1.valid()); + std::vector fill_cmp{ 1, 2, 3 }; std::vector append_cmp{ -1, -1, -10456407, -54 }; @@ -1029,18 +1060,21 @@ TEST_CASE("containers/input iterators", "test shitty input iterators that are al not_really_a_container c; lua["c"] = &c; #if SOL_LUA_VERSION > 502 - lua.safe_script(R"lua( + auto result0 = lua.safe_script(R"lua( for k, v in pairs(c) do assert((k - 1) == v:val()) end -)lua"); +)lua", sol::script_pass_on_error); + REQUIRE(result0.valid()); + #endif - lua.safe_script(R"lua( + auto result1 = lua.safe_script(R"lua( for k=1,#c do v = c[k] assert((k - 1) == v:val()) end -)lua"); +)lua", sol::script_pass_on_error); + REQUIRE(result1.valid()); } TEST_CASE("containers/pairs", "test how well pairs work with the underlying system") { @@ -1061,10 +1095,14 @@ TEST_CASE("containers/pairs", "test how well pairs work with the underlying syst lua["c"] = std::ref(c); lua["d"] = &d; - lua.safe_script("av1, av2 = a:get(1)"); - lua.safe_script("bv1, bv2 = b:get(1)"); - lua.safe_script("cv1, cv2 = c:get(1)"); - lua.safe_script("dv1, dv2 = d:get(1)"); + auto result1 = lua.safe_script("av1, av2 = a:get(1)", sol::script_pass_on_error); + REQUIRE(result1.valid()); + auto result2 = lua.safe_script("bv1, bv2 = b:get(1)", sol::script_pass_on_error); + REQUIRE(result2.valid()); + auto result3 = lua.safe_script("cv1, cv2 = c:get(1)", sol::script_pass_on_error); + REQUIRE(result3.valid()); + auto result4 = lua.safe_script("dv1, dv2 = d:get(1)", sol::script_pass_on_error); + REQUIRE(result4.valid()); std::vector>& la = lua["a"]; std::array, 5>& lb = lua["b"]; @@ -1134,24 +1172,20 @@ TEST_CASE("containers/pointer types", "check that containers with unique usertyp std::vector v2; v2.push_back(&d1); v2.push_back(&d2); - REQUIRE_NOTHROW([&]() { - lua["c1"] = std::move(v1); - lua["c2"] = &v2; - }()); + lua["c1"] = std::move(v1); + lua["c2"] = &v2; + + auto result1 = lua.safe_script("b1 = c1[1]", sol::script_pass_on_error); + REQUIRE(result1.valid()); + base_t* b1 = lua["b1"]; + int val1 = b1->get(); + REQUIRE(val1 == 250); - REQUIRE_NOTHROW([&]() { - lua.safe_script("b1 = c1[1]"); - base_t* b1 = lua["b1"]; - int val1 = b1->get(); - REQUIRE(val1 == 250); - }()); - - REQUIRE_NOTHROW([&]() { - lua.safe_script("b2 = c2[2]"); - base_t* b2 = lua["b2"]; - int val2 = b2->get(); - REQUIRE(val2 == 500); - }()); + auto result2 = lua.safe_script("b2 = c2[2]", sol::script_pass_on_error); + REQUIRE(result2.valid()); + base_t* b2 = lua["b2"]; + int val2 = b2->get(); + REQUIRE(val2 == 500); } TEST_CASE("containers/initializer-list", "test initializer lists get pushed as tables directly rather than userdata") { @@ -1160,11 +1194,11 @@ TEST_CASE("containers/initializer-list", "test initializer lists get pushed as t lua.open_libraries(sol::lib::base, sol::lib::table); lua["c"] = { 1, 2, 3, 4, 5 }; - lua.safe_script(R"lua( + auto result1 = lua.safe_script(R"lua( for k, v in pairs(c) do assert(k == v) end -)lua"); +)lua", sol::script_pass_on_error); sol::as_table_t> t1vector = lua["c"]; sol::as_table_t> t1deque = lua["c"]; sol::as_table_t> t1list = lua["c"]; diff --git a/tests/test_coroutines.cpp b/tests/test_coroutines.cpp index 1b7397c0..0506f90a 100644 --- a/tests/test_coroutines.cpp +++ b/tests/test_coroutines.cpp @@ -21,11 +21,9 @@ // 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. -#define SOL_CHECK_ARGUMENTS 1 -#define SOL_ENABLE_INTEROP 1 +#include "test_sol.hpp" #include -#include TEST_CASE("coroutines/yielding", "ensure calling a coroutine works") { const auto& script = R"(counter = 20 @@ -42,22 +40,21 @@ end sol::state lua; lua.open_libraries(sol::lib::base, sol::lib::coroutine); - lua.safe_script(script); + auto result1 = lua.safe_script(script); + REQUIRE(result1.valid()); sol::coroutine cr = lua["loop"]; int counter; for (counter = 20; counter < 31 && cr; ++counter) { int value = cr(); - if (counter != value) { - throw std::logic_error("fuck"); - } + REQUIRE(counter == value); } counter -= 1; REQUIRE(counter == 30); } TEST_CASE("coroutines/new thread coroutines", "ensure calling a coroutine works when the work is put on a different thread") { - const auto& script = R"(counter = 20 + const auto& code = R"(counter = 20 function loop() while counter ~= 30 @@ -71,7 +68,8 @@ end sol::state lua; lua.open_libraries(sol::lib::base, sol::lib::coroutine); - lua.safe_script(script); + auto result = lua.safe_script(code, sol::script_pass_on_error); + REQUIRE(result.valid()); sol::thread runner = sol::thread::create(lua.lua_state()); sol::state_view runnerstate = runner.state(); sol::coroutine cr = runnerstate["loop"]; @@ -79,9 +77,7 @@ end int counter; for (counter = 20; counter < 31 && cr; ++counter) { int value = cr(); - if (counter != value) { - throw std::logic_error("fuck"); - } + REQUIRE(counter == value); } counter -= 1; REQUIRE(counter == 30); @@ -96,8 +92,8 @@ TEST_CASE("coroutines/transfer", "test that things created inside of a coroutine lua["f"] = [&lua, &f2](sol::object t) { f2 = sol::function(lua, t); }; - - lua.script(R"( + { + auto code = R"( i = 0 function INIT() co = coroutine.create( @@ -112,13 +108,24 @@ function INIT() co = nil collectgarbage() end -)"); +)"; + auto result = lua.safe_script(code, sol::script_pass_on_error); + REQUIRE(result.valid()); + } sol::function f3; sol::function f1; - lua.safe_script("INIT()"); + { + auto code = "INIT()"; + auto result = lua.safe_script(code, sol::script_pass_on_error); + REQUIRE(result.valid()); + } f2(); - sol::function update = lua.safe_script("return function() collectgarbage() end"); + auto updatecode = "return function() collectgarbage() end"; + auto pfr = lua.safe_script(updatecode); + REQUIRE(pfr.valid()); + + sol::function update = pfr; update(); f3 = f2; f3(); @@ -199,7 +206,7 @@ co = nil "copy_store", &co_test::copy_store, "get", &co_test::get); - auto r = lua.safe_script(code); + auto r = lua.safe_script(code, sol::script_pass_on_error); REQUIRE(r.valid()); co_test& ct = lua["x"]; @@ -283,7 +290,7 @@ co = nil "copy_store", &co_test_implicit::copy_store, "get", &co_test_implicit::get); - auto r = lua.safe_script(code); + auto r = lua.safe_script(code, sol::script_pass_on_error); REQUIRE(r.valid()); co_test_implicit& ct = lua["x"]; @@ -370,7 +377,7 @@ collectgarbage() "copy_store", &co_test_implicit::copy_store, "get", &co_test_implicit::get); - auto r = lua.safe_script(code); + auto r = lua.safe_script(code, sol::script_pass_on_error); REQUIRE(r.valid()); co_test_implicit& ct = lua["x"]; @@ -391,8 +398,7 @@ TEST_CASE("coroutines/coroutine.create protection", "ensure that a thread picked sol::state lua; lua.open_libraries(sol::lib::base, sol::lib::coroutine); - lua.script( - R"( + auto code = R"( function loop() local i = 0 while true do @@ -403,9 +409,10 @@ function loop() end end loop_th = coroutine.create(loop) -)" -); +)"; + auto r = lua.safe_script(code, sol::script_pass_on_error); + REQUIRE(r.valid()); sol::thread runner_thread = lua["loop_th"]; auto test_resume = [&runner_thread]() { @@ -419,8 +426,15 @@ loop_th = coroutine.create(loop) int v0 = test_resume(); int v1 = test_resume(); - int v2 = lua.script("return test_resume()"); - int v3 = lua.script("return test_resume()"); + int v2, v3; + { + auto r2 = lua.safe_script("return test_resume()", sol::script_pass_on_error); + REQUIRE(r2.valid()); + auto r3 = lua.safe_script("return test_resume()", sol::script_pass_on_error); + REQUIRE(r3.valid()); + v2 = r2; + v3 = r3; + } REQUIRE(v0 == 0); REQUIRE(v1 == 1); REQUIRE(v2 == 2); @@ -430,9 +444,8 @@ loop_th = coroutine.create(loop) TEST_CASE("coroutines/stack-check", "check that resumed functions consume the entire execution stack") { sol::state lua; lua.open_libraries(sol::lib::base, sol::lib::table, sol::lib::coroutine); - - lua.script( - R"( + { + auto code = R"( unpack = unpack or table.unpack function loop() @@ -449,8 +462,10 @@ loop_res = function(...) returns = { coroutine.resume(loop_th, ...) } return unpack(returns, 2) end -)" -); +)"; + auto result = lua.safe_script(code, sol::script_pass_on_error); + REQUIRE(result.valid()); + } // Resume from lua via thread and coroutine sol::thread runner_thread = lua["loop_th"]; @@ -478,13 +493,28 @@ end int s0 = runner_thread_state.stack_top(); int v1 = test_resume(); int s1 = runner_thread_state.stack_top(); - int v2 = lua.script("return test_resume()"); + int v2; + { + auto result = lua.safe_script("return test_resume()", sol::script_pass_on_error); + REQUIRE(result.valid()); + v2 = result; + } int s2 = runner_thread_state.stack_top(); - int v3 = lua.script("return test_resume()"); + int v3; + { + auto result = lua.safe_script("return test_resume()", sol::script_pass_on_error); + REQUIRE(result.valid()); + v3 = result; + } int s3 = runner_thread_state.stack_top(); int v4 = test_resume_lua(); int s4 = runner_thread_state.stack_top(); - int v5 = lua.script("return test_resume_func(loop_res)"); + int v5; + { + auto result = lua.safe_script("return test_resume_func(loop_res)", sol::script_pass_on_error); + REQUIRE(result.valid()); + v5 = result; + } int s5 = runner_thread_state.stack_top(); REQUIRE(v0 == 0); REQUIRE(v1 == 1); diff --git a/tests/test_customizations.cpp b/tests/test_customizations.cpp index b3f64946..d2dba8b1 100644 --- a/tests/test_customizations.cpp +++ b/tests/test_customizations.cpp @@ -21,11 +21,9 @@ // 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. -#define SOL_CHECK_ARGUMENTS 1 -#define SOL_ENABLE_INTEROP 1 +#include "test_sol.hpp" #include -#include #include #include @@ -127,7 +125,8 @@ TEST_CASE("customization/split struct", "using the newly documented customizatio sol::state lua; // Create a pass-through style of function - lua.safe_script("function f ( a, b, c ) return a + c, b end"); + auto result1 = lua.safe_script("function f ( a, b, c ) return a + c, b end"); + REQUIRE(result1.valid()); lua.set_function("g", [](int a, bool b, int c, double d) { return std::make_tuple(a + c, b, d + 2.5); }); @@ -152,15 +151,16 @@ TEST_CASE("customization/get_ check_usertype", "using the newly documented custo sol::state lua; // Create a pass-through style of function - lua.safe_script("function f ( a ) return a end"); + auto result1 = lua.safe_script("function f ( a ) return a end"); + REQUIRE(result1.valid()); lua.set_function("g", [](double a) { number_shim ns; ns.num = a; return ns; }); - auto result = lua.safe_script("vf = f(25) vg = g(35)", sol::script_pass_on_error); - REQUIRE(result.valid()); + auto result2 = lua.safe_script("vf = f(25) vg = g(35)", sol::script_pass_on_error); + REQUIRE(result2.valid()); number_shim thingsf = lua["vf"]; number_shim thingsg = lua["vg"]; diff --git a/tests/test_environments.cpp b/tests/test_environments.cpp index a9bfec75..970f1d31 100644 --- a/tests/test_environments.cpp +++ b/tests/test_environments.cpp @@ -21,21 +21,19 @@ // 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. -#define SOL_CHECK_ARGUMENTS 1 -#define SOL_ENABLE_INTEROP 1 - -#include +#include "test_sol.hpp" #include + #include -#include "test_stack_guard.hpp" TEST_CASE("environments/get", "Envronments can be taken out of things like Lua functions properly") { sol::state lua; sol::stack_guard luasg(lua); lua.open_libraries(sol::lib::base); - lua.safe_script("f = function() return test end"); + auto result1 = lua.safe_script("f = function() return test end", sol::script_pass_on_error); + REQUIRE(result1.valid()); sol::function f = lua["f"]; sol::environment env_f(lua, sol::create); @@ -45,7 +43,8 @@ TEST_CASE("environments/get", "Envronments can be taken out of things like Lua f int result = f(); REQUIRE(result == 31); - lua.safe_script("g = function() test = 5 end"); + auto result2 = lua.safe_script("g = function() test = 5 end", sol::script_pass_on_error); + REQUIRE(result2.valid()); sol::function g = lua["g"]; sol::environment env_g(lua, sol::create); env_g.set_on(g); @@ -58,7 +57,8 @@ TEST_CASE("environments/get", "Envronments can be taken out of things like Lua f sol::object global_test = lua["test"]; REQUIRE(!global_test.valid()); - lua.safe_script("h = function() end"); + auto result3 = lua.safe_script("h = function() end", sol::script_pass_on_error); + REQUIRE(result3.valid()); lua.set_function("check_f_env", [&lua, &env_f](sol::object target) { @@ -86,11 +86,12 @@ TEST_CASE("environments/get", "Envronments can be taken out of things like Lua f sol::environment target_env = sol::get_environment(target); }); - REQUIRE_NOTHROW([&lua]() { - lua.safe_script("check_f_env(f)"); - lua.safe_script("check_g_env(g)"); - lua.safe_script("check_h_env(h)"); - }()); + auto checkf = lua.safe_script("check_f_env(f)"); + REQUIRE(checkf.valid()); + auto checkg = lua.safe_script("check_g_env(g)"); + REQUIRE(checkg.valid()); + auto checkh = lua.safe_script("check_h_env(h)"); + REQUIRE(checkh.valid()); } TEST_CASE("environments/shadowing", "Environments can properly shadow and fallback on variables") { @@ -100,7 +101,8 @@ TEST_CASE("environments/shadowing", "Environments can properly shadow and fallba SECTION("no fallback") { sol::environment plain_env(lua, sol::create); - lua.safe_script("a = 24", plain_env); + auto result1 = lua.safe_script("a = 24", plain_env, sol::script_pass_on_error); + REQUIRE(result1.valid()); sol::optional maybe_env_a = plain_env["a"]; sol::optional maybe_global_a = lua["a"]; sol::optional maybe_env_b = plain_env["b"]; @@ -116,7 +118,8 @@ TEST_CASE("environments/shadowing", "Environments can properly shadow and fallba } SECTION("fallback") { sol::environment env_with_fallback(lua, sol::create, lua.globals()); - lua.safe_script("a = 56", env_with_fallback, sol::script_default_on_error); + auto result1 = lua.safe_script("a = 56", env_with_fallback, sol::script_pass_on_error); + REQUIRE(result1.valid()); sol::optional maybe_env_a = env_with_fallback["a"]; sol::optional maybe_global_a = lua["a"]; sol::optional maybe_env_b = env_with_fallback["b"]; @@ -135,7 +138,8 @@ TEST_CASE("environments/shadowing", "Environments can properly shadow and fallba sol::environment env_with_fallback(lua, sol::create, lua.globals()); lua["env"] = env_with_fallback; sol::environment env = lua["env"]; - lua.safe_script("a = 56", env, sol::script_default_on_error); + auto result1 = lua.safe_script("a = 56", env, sol::script_pass_on_error); + REQUIRE(result1.valid()); sol::optional maybe_env_a = env["a"]; sol::optional maybe_global_a = lua["a"]; sol::optional maybe_env_b = env["b"]; @@ -153,7 +157,9 @@ TEST_CASE("environments/shadowing", "Environments can properly shadow and fallba SECTION("name with newtable") { lua["blank_env"] = sol::new_table(0, 1); sol::environment plain_env = lua["blank_env"]; - lua.safe_script("a = 24", plain_env); + auto result1 = lua.safe_script("a = 24", plain_env, sol::script_pass_on_error); + REQUIRE(result1.valid()); + sol::optional maybe_env_a = plain_env["a"]; sol::optional maybe_global_a = lua["a"]; sol::optional maybe_env_b = plain_env["b"]; @@ -174,7 +180,8 @@ TEST_CASE("environments/functions", "see if environments on functions are workin SECTION("basic") { sol::state lua; - lua.safe_script("a = function() return 5 end"); + auto result1 = lua.safe_script("a = function() return 5 end", sol::script_pass_on_error); + REQUIRE(result1.valid()); sol::function a = lua["a"]; @@ -184,13 +191,14 @@ TEST_CASE("environments/functions", "see if environments on functions are workin sol::environment env(lua, sol::create); sol::set_environment(env, a); - int result1 = a(); - REQUIRE(result1 == 5); + int value = a(); + REQUIRE(value == 5); } SECTION("return environment value") { sol::state lua; - lua.safe_script("a = function() return test end"); + auto result1 = lua.safe_script("a = function() return test end", sol::script_pass_on_error); + REQUIRE(result1.valid()); sol::function a = lua["a"]; sol::environment env(lua, sol::create); @@ -204,7 +212,8 @@ TEST_CASE("environments/functions", "see if environments on functions are workin SECTION("set environment value") { sol::state lua; - lua.safe_script("a = function() test = 5 end"); + auto result1 = lua.safe_script("a = function() test = 5 end", sol::script_pass_on_error); + REQUIRE(result1.valid()); sol::function a = lua["a"]; sol::environment env(lua, sol::create); @@ -240,7 +249,9 @@ TEST_CASE("environments/this_environment", "test various situations of pulling o lua["x"] = 5; e["x"] = 20; SECTION("from Lua script") { - int value = lua.safe_script(code, e); + auto result1 = lua.safe_script(code, e, sol::script_pass_on_error); + REQUIRE(result1.valid()); + int value = result1; REQUIRE(value == 30); } SECTION("from C++") { diff --git a/tests/test_filters.cpp b/tests/test_filters.cpp index 243d80f2..991a8191 100644 --- a/tests/test_filters.cpp +++ b/tests/test_filters.cpp @@ -21,10 +21,8 @@ // 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. -#define SOL_CHECK_ARGUMENTS 1 -#define SOL_ENABLE_INTEROP 1 +#include "test_sol.hpp" -#include #include #include @@ -58,8 +56,8 @@ TEST_CASE("filters/self", "ensure we return a direct reference to the lua userda "x", &vec2::x, "y", &vec2::y, "normalize", sol::filters(&vec2::normalize, sol::returns_self())); - REQUIRE_NOTHROW([&]() { - lua.safe_script(R"( + + auto result1 = lua.safe_script(R"( v1 = vec2.new() print('v1:', v1.x, v1.y) v2 = v1:normalize() @@ -70,8 +68,8 @@ assert(rawequal(v1, v2)) v1 = nil collectgarbage() print(v2) -- v2 points to same, is not destroyed - )"); - }()); + )", sol::script_pass_on_error); + REQUIRE(result1.valid()); } TEST_CASE("filters/self_dependency", "ensure we can keep a userdata instance alive by attaching it to the lifetime of another userdata") { @@ -115,32 +113,36 @@ TEST_CASE("filters/self_dependency", "ensure we can keep a userdata instance ali return "{ d: { " + std::to_string(g.d.value) + " } }"; }); - lua.safe_script(R"( + auto result1 = lua.safe_script(R"( g = gc_test.new() d = g.d print("new gc_test, d = g.d") print("", g) -)"); +)", sol::script_pass_on_error); + REQUIRE(result1.valid()); REQUIRE(deps_destroyed.empty()); REQUIRE(gc_tests_destroyed.empty()); gc_test* g = lua["g"]; dep* d = lua["d"]; - lua.safe_script(R"( + auto result2 = lua.safe_script(R"( print("g = nil, collectgarbage") g = nil collectgarbage() print("", d) -)"); +)", sol::script_pass_on_error); + REQUIRE(result2.valid()); + REQUIRE(deps_destroyed.empty()); REQUIRE(gc_tests_destroyed.empty()); - lua.safe_script(R"( + auto result3 = lua.safe_script(R"( print("d = nil, collectgarbage") d = nil collectgarbage() -)"); +)", sol::script_pass_on_error); + REQUIRE(result3.valid()); REQUIRE(deps_destroyed.size() == 1); REQUIRE(gc_tests_destroyed.size() == 1); @@ -199,11 +201,12 @@ TEST_CASE("filters/stack_dependencies", "ensure we can take dependencies even to "new", sol::filters(sol::constructors(), sol::stack_dependencies(-1, 1)), "comp", &depends_on_reference::comp); - lua.safe_script(R"( + auto result1 = lua.safe_script(R"( h = holder.new() dor = depends_on_reference.new(h) c = dor.comp -)"); +)", sol::script_pass_on_error); + REQUIRE(result1.valid()); REQUIRE(composition_relateds_destroyed.empty()); REQUIRE(holders_destroyed.empty()); REQUIRE(depends_on_references_destroyed.empty()); @@ -215,27 +218,30 @@ c = dor.comp REQUIRE(h == &dor->href.get()); REQUIRE(c == &dor->comp); - lua.safe_script(R"( + auto result2 = lua.safe_script(R"( h = nil collectgarbage() )"); + REQUIRE(result2.valid()); REQUIRE(composition_relateds_destroyed.empty()); REQUIRE(holders_destroyed.empty()); REQUIRE(depends_on_references_destroyed.empty()); - lua.safe_script(R"( + auto result3 = lua.safe_script(R"( c = nil collectgarbage() -)"); +)", sol::script_pass_on_error); + REQUIRE(result3.valid()); REQUIRE(composition_relateds_destroyed.empty()); REQUIRE(holders_destroyed.empty()); REQUIRE(depends_on_references_destroyed.empty()); - lua.safe_script(R"( + auto result4 = lua.safe_script(R"( dor = nil collectgarbage() -)"); +)", sol::script_pass_on_error); + REQUIRE(result4.valid()); REQUIRE(composition_relateds_destroyed.size() == 1); REQUIRE(holders_destroyed.size() == 1); diff --git a/tests/test_functions.cpp b/tests/test_functions.cpp index b6c9eaa2..812d86ce 100644 --- a/tests/test_functions.cpp +++ b/tests/test_functions.cpp @@ -21,15 +21,12 @@ // 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. -#define SOL_CHECK_ARGUMENTS 1 -#define SOL_ENABLE_INTEROP 1 -#include +#include "test_sol.hpp" #include #include -#include "test_stack_guard.hpp" template T va_func(sol::variadic_args va, T first) { @@ -73,8 +70,7 @@ void test_free_func(std::function f) { void test_free_func2(std::function f, int arg1) { int val = f(arg1); - if (val != arg1) - throw sol::error("failed function call!"); + REQUIRE(val == arg1); } int overloaded(int x) { @@ -137,7 +133,8 @@ static int raw_noexcept_function(lua_State* L) noexcept { TEST_CASE("functions/tuple returns", "Make sure tuple returns are ordered properly") { sol::state lua; - lua.safe_script("function f() return '3', 4 end"); + auto result1 = lua.safe_script("function f() return '3', 4 end", sol::script_pass_on_error); + REQUIRE(result1.valid()); std::tuple result = lua["f"](); auto s = std::get<0>(result); @@ -197,7 +194,9 @@ TEST_CASE("functions/return order and multi get", "Check if return order is in t lua.set_function("h", []() { return std::make_tuple(10, 10.0f); }); - lua.safe_script("function g() return 10, 11, 12 end\nx,y,z = g()"); + auto result1 = lua.safe_script("function g() return 10, 11, 12 end\nx,y,z = g()", sol::script_pass_on_error); + REQUIRE(result1.valid()); + auto tcpp = lua.get("f").call(); auto tlua = lua.get("g").call(); auto tcpp2 = lua.get("h").call(); @@ -223,7 +222,9 @@ TEST_CASE("functions/deducing return order and multi get", "Check if return orde lua.set_function("f", [] { return std::make_tuple(10, 11, 12); }); - lua.safe_script("function g() return 10, 11, 12 end\nx,y,z = g()"); + auto result1 = lua.safe_script("function g() return 10, 11, 12 end\nx,y,z = g()", sol::script_pass_on_error); + REQUIRE(result1.valid()); + std::tuple tcpp = lua.get("f")(); std::tuple tlua = lua.get("g")(); std::tuple tluaget = lua.get("x", "y", "z"); @@ -240,9 +241,10 @@ TEST_CASE("functions/optional values", "check if optionals can be passed in to b int v; }; sol::state lua; - lua.safe_script(R"( function f (a) + auto result1 = lua.safe_script(R"( function f (a) return a -end )"); +end )", sol::script_pass_on_error); + REQUIRE(result1.valid()); sol::function lua_bark = lua["f"]; @@ -260,13 +262,15 @@ TEST_CASE("functions/pair and tuple and proxy tests", "Check if sol::reference a sol::state lua; lua.new_usertype("A", "bark", &A::bark); - lua.safe_script(R"( function f (num_value, a) + auto result1 = lua.safe_script(R"( function f (num_value, a) return num_value * 2, a:bark() end function h (num_value, a, b) return num_value * 2, a:bark(), b * 3 end -nested = { variables = { no = { problem = 10 } } } )"); +nested = { variables = { no = { problem = 10 } } } )", sol::script_pass_on_error); + REQUIRE(result1.valid()); + lua.set_function("g", bark); sol::function cpp_bark = lua["g"]; @@ -302,8 +306,8 @@ TEST_CASE("functions/sol::function to std::function", "check if conversion to st lua.set_function("testFunc", test_free_func); lua.set_function("testFunc2", test_free_func2); - lua.safe_script( - "testFunc(function() print(\"hello std::function\") end)"); + auto result1 = lua.safe_script("testFunc(function() print(\"hello std::function\") end)", sol::script_pass_on_error); + REQUIRE(result1.valid()); { auto result = lua.safe_script( "function m(a)\n" @@ -326,7 +330,7 @@ TEST_CASE("functions/returning functions from C++", "check to see if returning a auto result = lua.safe_script( "afx = makefn()\n" "print(afx())\n" - "takefn(afx)\n"); + "takefn(afx)\n", sol::script_pass_on_error); REQUIRE(result.valid()); } } @@ -357,11 +361,12 @@ TEST_CASE("functions/function_result and protected_function_result", "Function r return handlederrormessage; }; lua.set_function("cpphandler", cpphandlerfx); - lua.safe_script( + auto result1 = lua.safe_script( std::string("function luahandler ( message )") + " print('lua handler called with: ' .. message)" + " return '" + handlederrormessage + "'" - + "end"); + + "end", sol::script_pass_on_error); + REQUIRE(result1.valid()); auto nontrampolinefx = [](lua_State*) -> int { throw "x"; }; lua_CFunction c_nontrampolinefx = nontrampolinefx; lua.set("nontrampoline", c_nontrampolinefx); @@ -499,12 +504,13 @@ TEST_CASE("functions/all kinds", "Register all kinds of functions, make sure the lua.set_function("m", &test_2::a, &t2); lua.set_function("n", sol::c_call); - lua.safe_script(R"( + auto result1 = lua.safe_script(R"( o1 = test_1.new() o2 = test_2.new() -)"); +)", sol::script_pass_on_error); + REQUIRE(result1.valid()); - lua.safe_script(R"( + auto result2 = lua.safe_script(R"( ob = o1:bark() A = a() @@ -516,35 +522,42 @@ G0, G1 = g(2, o1) H = h(o1) I = i(o1) I = i(o1) -)"); +)", sol::script_pass_on_error); + REQUIRE(result2.valid()); - lua.safe_script(R"( + auto result3 = lua.safe_script(R"( J0 = j() j(24) J1 = j() - )"); + )", sol::script_pass_on_error); + REQUIRE(result3.valid()); - lua.safe_script(R"( + auto result4 = lua.safe_script(R"( K0 = k(o2) k(o2, 1024) K1 = k(o2) - )"); + )", sol::script_pass_on_error); + REQUIRE(result4.valid()); - lua.safe_script(R"( + auto result5 = lua.safe_script(R"( L0 = l(o1) l(o1, 678) L1 = l(o1) - )"); + )", sol::script_pass_on_error); + REQUIRE(result5.valid()); - lua.safe_script(R"( + auto result6 = lua.safe_script(R"( M0 = m() m(256) M1 = m() - )"); + )", sol::script_pass_on_error); + REQUIRE(result6.valid()); - lua.safe_script(R"( + auto result7 = lua.safe_script(R"( N = n(1, 2, 3) - )"); + )", sol::script_pass_on_error); + REQUIRE(result7.valid()); + int ob, A, B, C, D, F, G0, G1, H, I, J0, J1, K0, K1, L0, L1, M0, M1, N; std::tie(ob, A, B, C, D, F, G0, G1, H, I, J0, J1, K0, K1, L0, L1, M0, M1, N) = lua.get( @@ -668,7 +681,8 @@ TEST_CASE("simple/call c++ function", "C++ function is called from lua") { sol::state lua; lua.set_function("plop_xyz", sep::plop_xyz); - lua.safe_script("x = plop_xyz(2, 6, 'hello')"); + auto result1 = lua.safe_script("x = plop_xyz(2, 6, 'hello')", sol::script_pass_on_error); + REQUIRE(result1.valid()); REQUIRE(lua.get("x") == 11); } @@ -680,7 +694,8 @@ TEST_CASE("simple/call lambda", "A C++ lambda is exposed to lua and called") { lua.set_function("foo", [&a] { a = 1; }); - lua.safe_script("foo()"); + auto result1 = lua.safe_script("foo()", sol::script_pass_on_error); + REQUIRE(result1.valid()); REQUIRE(a == 1); } @@ -764,7 +779,8 @@ TEST_CASE("advanced/call lambdas", "A C++ lambda is exposed to lua and called") return 0; }); - lua.safe_script("set_x(9)"); + auto result1 = lua.safe_script("set_x(9)", sol::script_pass_on_error); + REQUIRE(result1.valid()); REQUIRE(x == 9); } @@ -785,8 +801,11 @@ TEST_CASE("advanced/call referenced obj", "A C++ object is passed by pointer/ref }; lua.set_function("set_y", &decltype(objy)::operator(), std::ref(objy)); - lua.safe_script("set_x(9)"); - lua.safe_script("set_y(9)"); + auto result1 = lua.safe_script("set_x(9)", sol::script_pass_on_error); + REQUIRE(result1.valid()); + auto result2 = lua.safe_script("set_y(9)", sol::script_pass_on_error); + REQUIRE(result2.valid()); + REQUIRE(x == 9); REQUIRE(y == 9); } @@ -794,9 +813,10 @@ TEST_CASE("advanced/call referenced obj", "A C++ object is passed by pointer/ref TEST_CASE("functions/tie", "make sure advanced syntax with 'tie' works") { sol::state lua; - lua.safe_script(R"(function f () + auto result1 = lua.safe_script(R"(function f () return 1, 2, 3 -end)"); +end)", sol::script_pass_on_error); + REQUIRE(result1.valid()); sol::function f = lua["f"]; int a, b, c; diff --git a/tests/test_gc.cpp b/tests/test_gc.cpp index 302f785c..785879ef 100644 --- a/tests/test_gc.cpp +++ b/tests/test_gc.cpp @@ -21,10 +21,8 @@ // 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. -#define SOL_CHECK_ARGUMENTS 1 -#define SOL_ENABLE_INTEROP 1 +#include "test_sol.hpp" -#include #include #include @@ -148,16 +146,16 @@ end gc_entity e; target = &e; { - f(e); // same with std::ref(e)! - lua.collect_garbage(); // destroys e for some reason + f(e); + lua.collect_garbage(); } { - f(&e); // same with std::ref(e)! - lua.collect_garbage(); // destroys e for some reason + f(&e); + lua.collect_garbage(); } { - f(std::ref(e)); // same with std::ref(e)! - lua.collect_garbage(); // destroys e for some reason + f(std::ref(e)); + lua.collect_garbage(); } } REQUIRE(entities.size() == 1); @@ -293,13 +291,15 @@ TEST_CASE("gc/function storage", "show that proper copies / destruction happens sol::state lua; x x1; lua.set_function("x1copy", &x::func, x1); - lua.safe_script("x1copy()"); + auto result1 = lua.safe_script("x1copy()", sol::script_pass_on_error); + REQUIRE(result1.valid()); REQUIRE(created == 2); REQUIRE(destroyed == 0); REQUIRE_FALSE(last_call == &x1); lua.set_function("x1ref", &x::func, std::ref(x1)); - lua.safe_script("x1ref()"); + auto result2 = lua.safe_script("x1ref()", sol::script_pass_on_error); + REQUIRE(result2.valid()); REQUIRE(created == 2); REQUIRE(destroyed == 0); REQUIRE(last_call == &x1); @@ -318,14 +318,16 @@ TEST_CASE("gc/function storage", "show that proper copies / destruction happens sol::state lua; y y1; lua.set_function("y1copy", y1); - lua.safe_script("y1copy()"); + auto result1 = lua.safe_script("y1copy()", sol::script_pass_on_error); + REQUIRE(result1.valid()); REQUIRE(created == 1); REQUIRE(destroyed == 0); REQUIRE(last_call == static_call); last_call = nullptr; lua.set_function("y1ref", std::ref(y1)); - lua.safe_script("y1ref()"); + auto result2 = lua.safe_script("y1ref()", sol::script_pass_on_error); + REQUIRE(result2.valid()); REQUIRE(created == 1); REQUIRE(destroyed == 0); REQUIRE(last_call == static_call); @@ -483,11 +485,12 @@ TEST_CASE("gc/double-deletion tests", "make sure usertypes are properly destruct lua.new_usertype("CrashClass", sol::call_constructor, sol::constructors>()); - lua.safe_script(R"( + auto result1 = lua.safe_script(R"( function testCrash() local x = CrashClass() end - )"); + )", sol::script_pass_on_error); + REQUIRE(result1.valid()); for (int i = 0; i < 1000; ++i) { lua["testCrash"](); @@ -497,11 +500,12 @@ TEST_CASE("gc/double-deletion tests", "make sure usertypes are properly destruct lua.new_simple_usertype("CrashClass", sol::call_constructor, sol::constructors>()); - lua.safe_script(R"( + auto result1 = lua.safe_script(R"( function testCrash() local x = CrashClass() end - )"); + )", sol::script_pass_on_error); + REQUIRE(result1.valid()); for (int i = 0; i < 1000; ++i) { lua["testCrash"](); @@ -537,7 +541,8 @@ TEST_CASE("gc/shared_ptr regression", "metatables should not screw over unique u }); REQUIRE(created == 0); REQUIRE(destroyed == 0); - lua.safe_script("x = test.create()"); + auto result1 = lua.safe_script("x = test.create()", sol::script_pass_on_error); + REQUIRE(result1.valid()); REQUIRE(created == 1); REQUIRE(destroyed == 0); REQUIRE_FALSE(tests.empty()); @@ -564,7 +569,8 @@ TEST_CASE("gc/shared_ptr regression", "metatables should not screw over unique u }); REQUIRE(created == 0); REQUIRE(destroyed == 0); - lua.safe_script("x = test.create()"); + auto result1 = lua.safe_script("x = test.create()", sol::script_pass_on_error); + REQUIRE(result1.valid()); REQUIRE(created == 1); REQUIRE(destroyed == 0); REQUIRE_FALSE(tests.empty()); @@ -635,7 +641,10 @@ TEST_CASE("gc/alignment", "test that allocation is always on aligned boundaries, test obj{}; lua["obj"] = &obj; INFO("obj"); - lua.script("obj.callback()"); + { + auto r = lua.safe_script("obj.callback()", sol::script_pass_on_error); + REQUIRE(r.valid()); + } { // Do not check for stack-created object //test& lobj = lua["obj"]; @@ -644,7 +653,10 @@ TEST_CASE("gc/alignment", "test that allocation is always on aligned boundaries, lua["obj0"] = std::ref(obj); INFO("obj0"); - lua.script("obj0.callback()"); + { + auto r = lua.safe_script("obj0.callback()", sol::script_pass_on_error); + REQUIRE(r.valid()); + } { // Do not check for stack-created object //test& lobj = lua["obj0"]; @@ -653,7 +665,10 @@ TEST_CASE("gc/alignment", "test that allocation is always on aligned boundaries, lua["obj1"] = obj; INFO("obj1"); - lua.script("obj1.callback()"); + { + auto r = lua.safe_script("obj1.callback()", sol::script_pass_on_error); + REQUIRE(r.valid()); + } { test& lobj = lua["obj1"]; lobj.check_alignment(); @@ -661,7 +676,10 @@ TEST_CASE("gc/alignment", "test that allocation is always on aligned boundaries, lua["obj2"] = test{}; INFO("obj2"); - lua.script("obj2.callback()"); + { + auto r = lua.safe_script("obj2.callback()", sol::script_pass_on_error); + REQUIRE(r.valid()); + } { test& lobj = lua["obj2"]; lobj.check_alignment(); @@ -669,7 +687,10 @@ TEST_CASE("gc/alignment", "test that allocation is always on aligned boundaries, lua["obj3"] = std::make_unique(); INFO("obj3"); - lua.script("obj3.callback()"); + { + auto r = lua.safe_script("obj3.callback()", sol::script_pass_on_error); + REQUIRE(r.valid()); + } { test& lobj = lua["obj3"]; lobj.check_alignment(); @@ -677,7 +698,10 @@ TEST_CASE("gc/alignment", "test that allocation is always on aligned boundaries, lua["obj4"] = std::make_shared(); INFO("obj4"); - lua.script("obj4.callback()"); + { + auto r = lua.safe_script("obj4.callback()", sol::script_pass_on_error); + REQUIRE(r.valid()); + } { test& lobj = lua["obj4"]; lobj.check_alignment(); diff --git a/tests/test_inheritance.cpp b/tests/test_inheritance.cpp index da97bc17..c3919395 100644 --- a/tests/test_inheritance.cpp +++ b/tests/test_inheritance.cpp @@ -21,10 +21,8 @@ // 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. -#define SOL_CHECK_ARGUMENTS 1 -#define SOL_ENABLE_INTEROP 1 +#include "test_sol.hpp" -#include #include #include @@ -62,14 +60,19 @@ TEST_CASE("inheritance/basic", "test that metatables are properly inherited") { "d", &D::d, sol::base_classes, sol::bases()); - lua.safe_script("obj = D.new()"); - lua.safe_script("d = obj:d()"); + auto result1 = lua.safe_script("obj = D.new()", sol::script_pass_on_error); + REQUIRE(result1.valid()); + auto result2 = lua.safe_script("d = obj:d()", sol::script_pass_on_error); + REQUIRE(result2.valid()); bool d = lua["d"]; - lua.safe_script("c = obj.c"); + auto result3 = lua.safe_script("c = obj.c", sol::script_pass_on_error); + REQUIRE(result3.valid()); double c = lua["c"]; - lua.safe_script("b = obj:b()"); + auto result4 = lua.safe_script("b = obj:b()", sol::script_pass_on_error); + REQUIRE(result4.valid()); int b = lua["b"]; - lua.safe_script("a = obj.a"); + auto result5 = lua.safe_script("a = obj.a", sol::script_pass_on_error); + REQUIRE(result5.valid()); int a = lua["a"]; REQUIRE(d); @@ -160,21 +163,13 @@ TEST_CASE("inheritance/multi base", "test that multiple bases all work and overl lua.set_usertype("TestClass03", s_TestUsertype03); - lua.safe_script(R"( + auto result1 = lua.safe_script(R"( tc0 = TestClass00() -)"); - - lua.safe_script(R"( tc2 = TestClass02(tc0) -)"); - - lua.safe_script(R"( tc1 = TestClass01() -)"); - - lua.safe_script(R"( tc3 = TestClass03(tc1) -)"); +)", sol::script_pass_on_error); + REQUIRE(result1.valid()); TestClass00& tc0 = lua["tc0"]; TestClass01& tc1 = lua["tc1"]; @@ -271,22 +266,13 @@ TEST_CASE("inheritance/simple multi base", "test that multiple bases all work an lua.set_usertype("TestClass03", s_TestUsertype03); - lua.safe_script(R"( + auto result1 = lua.safe_script(R"( tc0 = TestClass00() -)"); - - lua.safe_script(R"( tc2 = TestClass02(tc0) -)"); - - lua.safe_script(R"( tc1 = TestClass01() -)"); - - lua.safe_script(R"( tc3 = TestClass03(tc1) -)"); - +)", sol::script_pass_on_error); + REQUIRE(result1.valid()); TestClass00& tc0 = lua["tc0"]; TestClass01& tc1 = lua["tc1"]; TestClass02& tc2 = lua["tc2"]; diff --git a/tests/test_large_integer.cpp b/tests/test_large_integer.cpp index c8c37adb..fe4ac06a 100644 --- a/tests/test_large_integer.cpp +++ b/tests/test_large_integer.cpp @@ -21,10 +21,7 @@ // 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. -#define SOL_CHECK_ARGUMENTS 1 -#define SOL_ENABLE_INTEROP 1 - -#include +#include "test_sol.hpp" #include @@ -38,8 +35,9 @@ TEST_CASE("large_integer/bool", "pass bool integral value to and from lua") { REQUIRE(num == true); return num; }); - lua.safe_script("x = f(true)"); - lua.safe_script("assert(x == true)"); + auto result1 = lua.safe_script("x = f(true)\n" + "assert(x == true)", sol::script_pass_on_error); + REQUIRE(result1.valid()); sol::object x = lua["x"]; REQUIRE(x.is()); REQUIRE(x.as() == true); @@ -58,8 +56,9 @@ TEST_CASE("large_integers/unsigned32", "pass large unsigned 32bit values to and REQUIRE(num == 0xFFFFFFFF); return num; }); - lua.safe_script("x = f(0xFFFFFFFF)"); - lua.safe_script("assert(x == 0xFFFFFFFF)"); + auto result1 = lua.safe_script("x = f(0xFFFFFFFF)\n" + "assert(x == 0xFFFFFFFF)", sol::script_pass_on_error); + REQUIRE(result1.valid()); sol::object x = lua["x"]; REQUIRE(x.is()); REQUIRE(x.as() == 0xFFFFFFFF); @@ -73,8 +72,9 @@ TEST_CASE("large_integer/unsigned53", "pass large unsigned 53bit value to and fr REQUIRE(num == 0x1FFFFFFFFFFFFFull); return num; }); - lua.safe_script("x = f(0x1FFFFFFFFFFFFF)"); - lua.safe_script("assert(x == 0x1FFFFFFFFFFFFF)"); + auto result1 = lua.safe_script("x = f(0x1FFFFFFFFFFFFF)\n" + "assert(x == 0x1FFFFFFFFFFFFF)"); + REQUIRE(result1.valid()); sol::object x = lua["x"]; REQUIRE(x.is()); REQUIRE(x.as() == 0x1FFFFFFFFFFFFFull); @@ -107,38 +107,50 @@ TEST_CASE("large_integer/double", "pass negative and large positive values as si lua.set_function("u64", [&](std::uint64_t num) { return num; }); - //signed 32bit - REQUIRE_NOTHROW([&lua]() { - lua.safe_script("x = s32(-1)"); - lua.safe_script("assert(x == -1)"); - lua.safe_script("x = s32(0xFFFFFFFF)"); - lua.safe_script("assert(x == -1)"); + { + //signed 32bit + auto result1 = lua.safe_script("x = s32(-1)", sol::script_pass_on_error); + REQUIRE(result1.valid()); + auto result2 = lua.safe_script("assert(x == -1)", sol::script_pass_on_error); + REQUIRE(result2.valid()); + auto result3 = lua.safe_script("x = s32(0xFFFFFFFF)", sol::script_pass_on_error); + REQUIRE(result3.valid()); + auto result4 = lua.safe_script("assert(x == -1)", sol::script_pass_on_error); + REQUIRE(result4.valid()); + sol::object x = lua["x"]; REQUIRE(x.is()); REQUIRE(x.as() == -1); REQUIRE(x.is()); REQUIRE(x.as() == 0xFFFFFFFF); - }()); + } + //unsigned 32bit - REQUIRE_NOTHROW([&lua]() { - lua.safe_script("x = u32(0xFFFFFFFF)"); - lua.safe_script("assert(x == 0xFFFFFFFF)"); - lua.safe_script("x = u32(-1)"); - lua.safe_script("assert(x == 0xFFFFFFFF)"); + { + auto result1 = lua.safe_script("x = u32(0xFFFFFFFF)", sol::script_pass_on_error); + REQUIRE(result1.valid()); + auto result2 = lua.safe_script("assert(x == 0xFFFFFFFF)", sol::script_pass_on_error); + REQUIRE(result2.valid()); + auto result3 = lua.safe_script("x = u32(-1)", sol::script_pass_on_error); + REQUIRE(result3.valid()); + auto result4 = lua.safe_script("assert(x == 0xFFFFFFFF)", sol::script_pass_on_error); + REQUIRE(result4.valid()); sol::object x = lua["x"]; REQUIRE(x.is()); REQUIRE(x.as() == -1); REQUIRE(x.is()); REQUIRE(x.as() == 0xFFFFFFFF); - }()); + } //signed 64bit - REQUIRE_NOTHROW([&lua]() { - lua.safe_script("x = s64(-1)"); - lua.safe_script("assert(x == -1)"); + { + auto result1 = lua.safe_script("x = s64(-1)", sol::script_pass_on_error); + REQUIRE(result1.valid()); + auto result2 = lua.safe_script("assert(x == -1)", sol::script_pass_on_error); + REQUIRE(result2.valid()); sol::object x = lua["x"]; REQUIRE(x.is()); REQUIRE(x.as() == -1); REQUIRE(x.is()); REQUIRE(x.as() == 0xFFFFFFFFFFFFFFFFull); - }()); + } } diff --git a/tests/test_operators.cpp b/tests/test_operators.cpp index fdcbac8d..2fa9959b 100644 --- a/tests/test_operators.cpp +++ b/tests/test_operators.cpp @@ -21,10 +21,7 @@ // 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. -#define SOL_CHECK_ARGUMENTS 1 -#define SOL_ENABLE_INTEROP 1 - -#include +#include "test_sol.hpp" #include @@ -77,40 +74,46 @@ TEST_CASE("operators/default", "test that generic equality operators and all sor SECTION("plain") { // Can only compare identity here - REQUIRE_NOTHROW([&] { - lua.safe_script("assert(t1 == t1)"); - lua.safe_script("assert(t2 == t2)"); - lua.safe_script("assert(t3 == t3)"); - }()); - REQUIRE_NOTHROW([&] { - lua.safe_script("assert(t1 == t2)"); - lua.safe_script("assert(not (t1 == t3))"); - lua.safe_script("assert(not (t2 == t3))"); - }()); + { + auto result1 = lua.safe_script("assert(t1 == t1)" + "assert(t2 == t2)" + "assert(t3 == t3)", sol::script_pass_on_error); + REQUIRE(result1.valid()); + } + { + auto result1 = lua.safe_script("assert(t1 == t2)" + "assert(not (t1 == t3))" + "assert(not (t2 == t3))", sol::script_pass_on_error); + REQUIRE(result1.valid()); + } // Object should compare equal to themselves // (and not invoke operator==; pointer test should be sufficient) - REQUIRE_NOTHROW([&] { - lua.safe_script("assert(u1 == u1)"); - lua.safe_script("assert(u2 == u2)"); - lua.safe_script("assert(u3 == u3)"); - }()); - REQUIRE_NOTHROW([&] { - lua.safe_script("assert(not (u1 == u2))"); - lua.safe_script("assert(u1 == u3)"); - lua.safe_script("assert(not (u2 == u3))"); - }()); + { + auto result1 = lua.safe_script("assert(u1 == u1)" + "assert(u2 == u2)" + "assert(u3 == u3)", sol::script_pass_on_error); + REQUIRE(result1.valid()); + } + { + auto result1 = lua.safe_script("assert(not (u1 == u2))" + "assert(u1 == u3)" + "assert(not (u2 == u3))", sol::script_pass_on_error); + REQUIRE(result1.valid()); + } // Object should compare equal to themselves // (and not invoke operator==; pointer test should be sufficient) - REQUIRE_NOTHROW([&] { - lua.safe_script("assert(v1 == v1)"); - lua.safe_script("assert(v2 == v2)"); - lua.safe_script("assert(v3 == v3)"); - }()); - REQUIRE_NOTHROW([&] { - lua.safe_script("assert(not (v1 == v2))"); - lua.safe_script("assert(v1 == v3)"); - lua.safe_script("assert(not (v2 == v3))"); - }()); + { + auto result1 = lua.safe_script("assert(v1 == v1)" + "assert(v2 == v2)" + "assert(v3 == v3)", sol::script_pass_on_error); + REQUIRE(result1.valid()); + } + { + auto result1 = lua.safe_script("assert(not (v1 == v2))" + "assert(v1 == v3)" + "assert(not (v2 == v3))", sol::script_pass_on_error); + REQUIRE(result1.valid()); + } } SECTION("regular") { lua.new_usertype("T"); @@ -118,40 +121,46 @@ TEST_CASE("operators/default", "test that generic equality operators and all sor lua.new_usertype("V"); // Can only compare identity here - REQUIRE_NOTHROW([&] { - lua.safe_script("assert(t1 == t1)"); - lua.safe_script("assert(t2 == t2)"); - lua.safe_script("assert(t3 == t3)"); - }()); - REQUIRE_NOTHROW([&] { - lua.safe_script("assert(t1 == t2)"); - lua.safe_script("assert(not (t1 == t3))"); - lua.safe_script("assert(not (t2 == t3))"); - }()); + { + auto result1 = lua.safe_script("assert(t1 == t1)" + "assert(t2 == t2)" + "assert(t3 == t3)", sol::script_pass_on_error); + REQUIRE(result1.valid()); + } + { + auto result1 = lua.safe_script("assert(t1 == t2)" + "assert(not (t1 == t3))" + "assert(not (t2 == t3))", sol::script_pass_on_error); + REQUIRE(result1.valid()); + } // Object should compare equal to themselves // (and not invoke operator==; pointer test should be sufficient) - REQUIRE_NOTHROW([&] { - lua.safe_script("assert(u1 == u1)"); - lua.safe_script("assert(u2 == u2)"); - lua.safe_script("assert(u3 == u3)"); - }()); - REQUIRE_NOTHROW([&] { - lua.safe_script("assert(not (u1 == u2))"); - lua.safe_script("assert(u1 == u3)"); - lua.safe_script("assert(not (u2 == u3))"); - }()); + { + auto result1 = lua.safe_script("assert(u1 == u1)" + "assert(u2 == u2)" + "assert(u3 == u3)", sol::script_pass_on_error); + REQUIRE(result1.valid()); + } + { + auto result1 = lua.safe_script("assert(not (u1 == u2))" + "assert(u1 == u3)" + "assert(not (u2 == u3))", sol::script_pass_on_error); + REQUIRE(result1.valid()); + } // Object should compare equal to themselves // (and not invoke operator==; pointer test should be sufficient) - REQUIRE_NOTHROW([&] { - lua.safe_script("assert(v1 == v1)"); - lua.safe_script("assert(v2 == v2)"); - lua.safe_script("assert(v3 == v3)"); - }()); - REQUIRE_NOTHROW([&] { - lua.safe_script("assert(not (v1 == v2))"); - lua.safe_script("assert(v1 == v3)"); - lua.safe_script("assert(not (v2 == v3))"); - }()); + { + auto result1 = lua.safe_script("assert(v1 == v1)" + "assert(v2 == v2)" + "assert(v3 == v3)", sol::script_pass_on_error); + REQUIRE(result1.valid()); + } + { + auto result1 = lua.safe_script("assert(not (v1 == v2))" + "assert(v1 == v3)" + "assert(not (v2 == v3))", sol::script_pass_on_error); + REQUIRE(result1.valid()); + } } SECTION("simple") { lua.new_simple_usertype("T"); @@ -159,40 +168,46 @@ TEST_CASE("operators/default", "test that generic equality operators and all sor lua.new_simple_usertype("V"); // Can only compare identity here - REQUIRE_NOTHROW([&] { - lua.safe_script("assert(t1 == t1)"); - lua.safe_script("assert(t2 == t2)"); - lua.safe_script("assert(t3 == t3)"); - }()); - REQUIRE_NOTHROW([&] { - lua.safe_script("assert(t1 == t2)"); - lua.safe_script("assert(not (t1 == t3))"); - lua.safe_script("assert(not (t2 == t3))"); - }()); + { + auto result1 = lua.safe_script("assert(t1 == t1)" + "assert(t2 == t2)" + "assert(t3 == t3)", sol::script_pass_on_error); + REQUIRE(result1.valid()); + } + { + auto result1 = lua.safe_script("assert(t1 == t2)" + "assert(not (t1 == t3))" + "assert(not (t2 == t3))", sol::script_pass_on_error); + REQUIRE(result1.valid()); + } // Object should compare equal to themselves // (and not invoke operator==; pointer test should be sufficient) - REQUIRE_NOTHROW([&] { - lua.safe_script("assert(u1 == u1)"); - lua.safe_script("assert(u2 == u2)"); - lua.safe_script("assert(u3 == u3)"); - }()); - REQUIRE_NOTHROW([&] { - lua.safe_script("assert(not (u1 == u2))"); - lua.safe_script("assert(u1 == u3)"); - lua.safe_script("assert(not (u2 == u3))"); - }()); + { + auto result1 = lua.safe_script("assert(u1 == u1)" + "assert(u2 == u2)" + "assert(u3 == u3)", sol::script_pass_on_error); + REQUIRE(result1.valid()); + } + { + auto result1 = lua.safe_script("assert(not (u1 == u2))" + "assert(u1 == u3)" + "assert(not (u2 == u3))", sol::script_pass_on_error); + REQUIRE(result1.valid()); + } // Object should compare equal to themselves // (and not invoke operator==; pointer test should be sufficient) - REQUIRE_NOTHROW([&] { - lua.safe_script("assert(v1 == v1)"); - lua.safe_script("assert(v2 == v2)"); - lua.safe_script("assert(v3 == v3)"); - }()); - REQUIRE_NOTHROW([&] { - lua.safe_script("assert(not (v1 == v2))"); - lua.safe_script("assert(v1 == v3)"); - lua.safe_script("assert(not (v2 == v3))"); - }()); + { + auto result1 = lua.safe_script("assert(v1 == v1)" + "assert(v2 == v2)" + "assert(v3 == v3)", sol::script_pass_on_error); + REQUIRE(result1.valid()); + } + { + auto result1 = lua.safe_script("assert(not (v1 == v2))" + "assert(v1 == v3)" + "assert(not (v2 == v3))", sol::script_pass_on_error); + REQUIRE(result1.valid()); + } } } @@ -209,7 +224,8 @@ TEST_CASE("operators/call", "test call operator generation") { SECTION("plain") { { lua.set("obj", callable()); - lua.safe_script("v = obj(2, 'bark woof')"); + auto result1 = lua.safe_script("v = obj(2, 'bark woof')", sol::script_pass_on_error); + REQUIRE(result1.valid()); int v = lua["v"]; REQUIRE(v == 11); } @@ -217,8 +233,9 @@ TEST_CASE("operators/call", "test call operator generation") { SECTION("regular") { lua.new_usertype("callable"); { - lua.safe_script("obj = callable.new()"); - lua.safe_script("v = obj(2, 'bark woof')"); + auto result1 = lua.safe_script("obj = callable.new()\n" + "v = obj(2, 'bark woof')", sol::script_pass_on_error); + REQUIRE(result1.valid()); int v = lua["v"]; REQUIRE(v == 11); } @@ -283,7 +300,8 @@ TEST_CASE("operators/stringable", "test std::ostream stringability") { SECTION("plain") { { lua["obj"] = stringable(); - lua.safe_script("print(obj)"); + auto result1 = lua.safe_script("print(obj)", sol::script_pass_on_error); + REQUIRE(result1.valid()); stringable& obj = lua["obj"]; REQUIRE(stringable::last_print_ptr == &obj); } @@ -291,8 +309,9 @@ TEST_CASE("operators/stringable", "test std::ostream stringability") { SECTION("regular") { lua.new_usertype("stringable"); { - lua.safe_script("obj = stringable.new()"); - lua.safe_script("print(obj)"); + auto result1 = lua.safe_script(R"(obj = stringable.new() + print(obj) )", sol::script_pass_on_error); + REQUIRE(result1.valid()); stringable& obj = lua["obj"]; REQUIRE(stringable::last_print_ptr == &obj); } @@ -300,8 +319,9 @@ TEST_CASE("operators/stringable", "test std::ostream stringability") { SECTION("simple") { lua.new_simple_usertype("stringable"); { - lua.safe_script("obj = stringable.new()"); - lua.safe_script("print(obj)"); + auto result1 = lua.safe_script(R"(obj = stringable.new() + print(obj))", sol::script_pass_on_error); + REQUIRE(result1.valid()); stringable& obj = lua["obj"]; REQUIRE(stringable::last_print_ptr == &obj); } diff --git a/tests/test_overflow.cpp b/tests/test_overflow.cpp index ce59848c..b8c34066 100644 --- a/tests/test_overflow.cpp +++ b/tests/test_overflow.cpp @@ -21,10 +21,7 @@ // 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. -#define SOL_CHECK_ARGUMENTS 1 -#define SOL_ENABLE_INTEROP 1 - -#include +#include "test_sol.hpp" #include diff --git a/tests/test_proxies.cpp b/tests/test_proxies.cpp index 2a374279..1fcb75ca 100644 --- a/tests/test_proxies.cpp +++ b/tests/test_proxies.cpp @@ -21,15 +21,11 @@ // 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. -#define SOL_CHECK_ARGUMENTS 1 -#define SOL_ENABLE_INTEROP 1 - -#include +#include "test_sol.hpp" #include #include -#include "test_stack_guard.hpp" TEST_CASE("proxy/function results", "make sure that function results return proper proxies and can be indexed nicely") { sol::state lua; diff --git a/tests/test_simple_usertypes.cpp b/tests/test_simple_usertypes.cpp index aebd44d0..503d2cda 100644 --- a/tests/test_simple_usertypes.cpp +++ b/tests/test_simple_usertypes.cpp @@ -21,10 +21,7 @@ // 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. -#define SOL_CHECK_ARGUMENTS 1 -#define SOL_ENABLE_INTEROP 1 - -#include +#include "test_sol.hpp" #include diff --git a/tests/test_stack_guard.hpp b/tests/test_sol.hpp similarity index 69% rename from tests/test_stack_guard.hpp rename to tests/test_sol.hpp index 79b996a1..c366f6f4 100644 --- a/tests/test_stack_guard.hpp +++ b/tests/test_sol.hpp @@ -23,14 +23,39 @@ #pragma once +#ifndef SOL_CHECK_ARGUMENTS +#define SOL_CHECK_ARGUMENTS 1 +#endif // SOL_CHECK_ARGUMENTS +#ifndef SOL_ENABLE_INTEROP +#define SOL_ENABLE_INTEROP 1 +#endif // SOL_ENABLE_INTEROP +// Can't activate until all script/safe_script calls are vetted... +/*#ifndef SOL_DEFAULT_PASS_ON_ERROR +#define SOL_DEFAULT_PASS_ON_ERROR 1 +#endif // SOL_DEFAULT_PASS_ON_ERROR +*/ + +#ifdef TEST_SINGLE +#include +#endif // Single +#include +#include + +#define CHECK_VALID ( x ) { auto r = x; REQUIRE(r.valid()); } + struct test_stack_guard { lua_State* L; int& begintop; int& endtop; test_stack_guard(lua_State* L, int& begintop, int& endtop) - : L(L), begintop(begintop), endtop(endtop) { + : L(L), begintop(begintop), endtop(endtop) { begintop = lua_gettop(L); } + + void check() { + REQUIRE(begintop == endtop); + } + ~test_stack_guard() { endtop = lua_gettop(L); } diff --git a/tests/test_state.cpp b/tests/test_state.cpp index c2677bbb..5b821a97 100644 --- a/tests/test_state.cpp +++ b/tests/test_state.cpp @@ -21,10 +21,7 @@ // 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. -#define SOL_CHECK_ARGUMENTS 1 -#define SOL_ENABLE_INTEROP 1 - -#include +#include "test_sol.hpp" #include @@ -35,8 +32,6 @@ #include #include -#include "test_stack_guard.hpp" - template void write_file_attempt(Name&& filename, Data&& data) { bool success = false; diff --git a/tests/test_storage.cpp b/tests/test_storage.cpp index 3dce8779..f228a3a4 100644 --- a/tests/test_storage.cpp +++ b/tests/test_storage.cpp @@ -36,7 +36,10 @@ end )"; sol::state lua; - lua.script(code); + { + auto r = lua.safe_script(code, sol::script_pass_on_error); + REQUIRE(r.valid()); + } sol::function f = lua["f"]; sol::reference r = lua["f"]; sol::function regf(lua, f); diff --git a/tests/test_strings.cpp b/tests/test_strings.cpp index fd17e1e6..dfcf3b9a 100644 --- a/tests/test_strings.cpp +++ b/tests/test_strings.cpp @@ -21,10 +21,7 @@ // 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. -#define SOL_CHECK_ARGUMENTS 1 -#define SOL_ENABLE_INTEROP 1 - -#include +#include "test_sol.hpp" #include @@ -43,6 +40,7 @@ namespace muh_namespace { } // namespace muh_namespace // There isn't a single library roundtripping which codecvt works on. We'll do the nitty-gritty of it later... +#if (defined(_MSC_VER) || defined(__clang__) || defined(__MINGW64__)) TEST_CASE("stack/strings", "test that strings can be roundtripped") { sol::state lua; @@ -124,6 +122,7 @@ TEST_CASE("stack/strings", "test that strings can be roundtripped") { REQUIRE(wide_to_char32 == utf32str[0]); #endif // codecvt support } +#endif // MinGW fails with codecvt TEST_CASE("detail/demangling", "test some basic demangling cases") { std::string teststr = sol::detail::short_demangle(); diff --git a/tests/test_tables.cpp b/tests/test_tables.cpp index 8b38ba15..e0700260 100644 --- a/tests/test_tables.cpp +++ b/tests/test_tables.cpp @@ -21,10 +21,7 @@ // 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. -#define SOL_CHECK_ARGUMENTS 1 -#define SOL_ENABLE_INTEROP 1 - -#include +#include "test_sol.hpp" #include @@ -33,8 +30,6 @@ #include #include -#include "test_stack_guard.hpp" - std::string free_function() { INFO("free_function()"); return "test"; diff --git a/tests/test_usertypes.cpp b/tests/test_usertypes.cpp index e1c55aac..51d8a3ea 100644 --- a/tests/test_usertypes.cpp +++ b/tests/test_usertypes.cpp @@ -21,10 +21,7 @@ // 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. -#define SOL_CHECK_ARGUMENTS 1 -#define SOL_ENABLE_INTEROP 1 - -#include +#include "test_sol.hpp" #include @@ -441,10 +438,11 @@ TEST_CASE("usertype/self-referential usertype", "usertype classes must play nice lua.new_usertype("test", "g", &self_test::g, "f", &self_test::f); - lua.safe_script( + auto result = lua.safe_script( "local a = test.new()\n" "a:g(\"woof\")\n" - "a:f(a)\n"); + "a:f(a)\n", sol::script_pass_on_error); + REQUIRE(result.valid()); } TEST_CASE("usertype/issue-number-twenty-five", "Using pointers and references from C++ classes in Lua") { @@ -525,12 +523,18 @@ TEST_CASE("usertype/issue-number-thirty-five", "using value types created from l sol::usertype udata(ctor, "normalized", &Vec::normalized, "length", &Vec::length); lua.set_usertype(udata); - REQUIRE_NOTHROW(lua.safe_script( + { + auto result = lua.safe_script( "v = Vec.new(1, 2, 3)\n" - "print(v:length())")); - REQUIRE_NOTHROW(lua.safe_script( + "print(v:length())"); + REQUIRE(result.valid()); + } + { + auto result = lua.safe_script( "v = Vec.new(1, 2, 3)\n" - "print(v:normalized():length())")); + "print(v:normalized():length())"); + REQUIRE(result.valid()); + } } TEST_CASE("usertype/lua-stored-usertype", "ensure usertype values can be stored without keeping usertype object alive") { @@ -547,14 +551,20 @@ TEST_CASE("usertype/lua-stored-usertype", "ensure usertype values can be stored // usertype dies, but still usable in lua! } - REQUIRE_NOTHROW(lua.safe_script( - "collectgarbage()\n" - "v = Vec.new(1, 2, 3)\n" - "print(v:length())")); + { + auto result = lua.safe_script( + "collectgarbage()\n" + "v = Vec.new(1, 2, 3)\n" + "print(v:length())"); + REQUIRE(result.valid()); + } - REQUIRE_NOTHROW(lua.safe_script( - "v = Vec.new(1, 2, 3)\n" - "print(v:normalized():length())")); + { + auto result = lua.safe_script( + "v = Vec.new(1, 2, 3)\n" + "print(v:normalized():length())"); + REQUIRE(result.valid()); + } } TEST_CASE("usertype/member-variables", "allow table-like accessors to behave as member variables for usertype") { @@ -669,14 +679,18 @@ TEST_CASE("regressions/one", "issue number 48") { sol::state lua; lua.new_usertype("vars", "boop", &vars::boop); - REQUIRE_NOTHROW(lua.safe_script( - "beep = vars.new()\n" - "beep.boop = 1")); + auto code = "beep = vars.new()\n" + "beep.boop = 1"; + auto result1 = lua.safe_script(code, sol::script_pass_on_error); + REQUIRE(result1.valid()); // test for segfault auto my_var = lua.get("beep"); + auto& my_var_ref = lua.get("beep"); + auto* my_var_ptr = lua.get("beep"); REQUIRE(my_var.boop == 1); - auto* ptr = &my_var; - REQUIRE(ptr->boop == 1); + REQUIRE(my_var_ref.boop == 1); + REQUIRE(my_var_ptr->boop == 1); + REQUIRE(std::addressof(my_var_ref) == my_var_ptr); } TEST_CASE("usertype/get-set-references", "properly get and set with std::ref semantics. Note that to get, we must not use Unqualified on the type...") { @@ -726,9 +740,10 @@ TEST_CASE("usertype/private-constructible", "Check to make sure special snowflak REQUIRE(result.valid()); } - REQUIRE_NOTHROW(lua.safe_script( - "local fresh_f = factory_test:new()\n" - "assert(fresh_f.a == true_a)\n")); + auto code1 = "local fresh_f = factory_test:new()\n" + "assert(fresh_f.a == true_a)\n"; + auto result1 = lua.safe_script(code1, sol::script_pass_on_error); + REQUIRE(result1.valid()); } int expectednumsaved = numsaved + 1; int expectednumkilled = numkilled + 1; diff --git a/tests/test_utility.cpp b/tests/test_utility.cpp index 4d317f8c..3e1cb1a3 100644 --- a/tests/test_utility.cpp +++ b/tests/test_utility.cpp @@ -21,10 +21,7 @@ // 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. -#define SOL_CHECK_ARGUMENTS 1 -#define SOL_ENABLE_INTEROP 1 - -#include +#include "test_sol.hpp" #include diff --git a/tests/test_variadics.cpp b/tests/test_variadics.cpp index be6f1779..4a51eeb6 100644 --- a/tests/test_variadics.cpp +++ b/tests/test_variadics.cpp @@ -21,10 +21,7 @@ // 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. -#define SOL_CHECK_ARGUMENTS 1 -#define SOL_ENABLE_INTEROP 1 - -#include +#include "test_sol.hpp" #include diff --git a/tests/tests.cpp b/tests/tests.cpp index 0b7732a9..78a0c534 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -21,11 +21,9 @@ // 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. -#define SOL_CHECK_ARGUMENTS 1 -#define SOL_ENABLE_INTEROP 1 #define CATCH_CONFIG_MAIN 1 -#include +#include "test_sol.hpp" #include @@ -35,8 +33,6 @@ #include #include -#include "test_stack_guard.hpp" - bool func_opt_ret_bool(sol::optional i) { if (i) { INFO(i.value());