From 57681ab4cdc7ee834362662c047f61834d8b9357 Mon Sep 17 00:00:00 2001 From: ThePhD Date: Sun, 28 Jan 2018 22:21:13 -0500 Subject: [PATCH] This attempts to be more thorough with the validations of the test, avoiding throws wherever possible to help reduce the error surface for debugging x86 builds (which, strangely enough, are not erroring in the same places that appveyor is erroring in...) Need to begin wrok to fix wstring_convert and replace it with some decent UTF conversion algos. It's surprisingly difficult tof ind such... Fixes #572 Fixes #569 Fixes #567 --- .gitignore | 1 + docs/source/api/reference.rst | 6 +- single/sol/sol.hpp | 206 ++++++++++++++--- single/sol/sol_forward.hpp | 10 +- sol/call.hpp | 6 +- sol/environment.hpp | 6 +- sol/feature_test.hpp | 6 + sol/protected_function.hpp | 6 +- sol/reference.hpp | 11 + sol/simple_usertype_metatable.hpp | 10 + sol/stack.hpp | 4 +- sol/state_view.hpp | 26 ++- sol/string_view.hpp | 51 ++++- sol/table_core.hpp | 10 +- sol/traits.hpp | 7 +- sol/unsafe_function.hpp | 5 +- sol/usertype_metatable.hpp | 55 ++++- tests/CMakeLists.txt | 2 + tests/test_container_semantics.cpp | 115 ++++------ tests/test_containers.cpp | 180 +++++++++------ tests/test_coroutines.cpp | 98 +++++--- tests/test_customizations.cpp | 14 +- tests/test_environments.cpp | 57 +++-- tests/test_filters.cpp | 46 ++-- tests/test_functions.cpp | 98 ++++---- tests/test_gc.cpp | 74 +++--- tests/test_inheritance.cpp | 48 ++-- tests/test_large_integer.cpp | 66 +++--- tests/test_operators.cpp | 224 ++++++++++--------- tests/test_overflow.cpp | 5 +- tests/test_proxies.cpp | 6 +- tests/test_simple_usertypes.cpp | 5 +- tests/{test_stack_guard.hpp => test_sol.hpp} | 27 ++- tests/test_state.cpp | 7 +- tests/test_storage.cpp | 5 +- tests/test_strings.cpp | 7 +- tests/test_tables.cpp | 7 +- tests/test_usertypes.cpp | 65 +++--- tests/test_utility.cpp | 5 +- tests/test_variadics.cpp | 5 +- tests/tests.cpp | 6 +- 41 files changed, 1008 insertions(+), 590 deletions(-) rename tests/{test_stack_guard.hpp => test_sol.hpp} (69%) 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());