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
This commit is contained in:
ThePhD 2018-01-28 22:21:13 -05:00
parent 143c98450a
commit 57681ab4cd
41 changed files with 1008 additions and 590 deletions

1
.gitignore vendored
View File

@ -113,3 +113,4 @@ desktop.ini
# Miscellaneous
external/
scratch/
.idea/

View File

@ -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&);

View File

@ -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 <typename T>
using is_string_constructible = any<
std::is_same<unqualified_t<T>, const char*>, std::is_same<unqualified_t<T>, char>, std::is_same<unqualified_t<T>, std::string>, std::is_same<unqualified_t<T>, std::initializer_list<char>>
meta::all<std::is_array<unqualified_t<T>>, std::is_same<meta::unqualified_t<std::remove_all_extents_t<meta::unqualified_t<T>>>, char>>,
std::is_same<unqualified_t<T>, const char*>,
std::is_same<unqualified_t<T>, char>, std::is_same<unqualified_t<T>, std::string>, std::is_same<unqualified_t<T>, std::initializer_list<char>>
#ifdef SOL_CXX17_FEATURES
,
std::is_same<unqualified_t<T>, std::string_view>
, std::is_same<unqualified_t<T>, std::string_view>
#endif
>;
@ -4146,6 +4153,9 @@ namespace sol {
#ifdef SOL_CXX17_FEATURES
#endif // C++17 features
#ifdef SOL_USE_BOOST
#include <boost/functional/hash.hpp>
#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<std::string_view> string_view_hash;
#else
template <typename Char, typename Traits = std::char_traits<Char>>
struct basic_string_view {
@ -4208,12 +4219,16 @@ namespace sol {
return size();
}
operator std::basic_string<Char, Traits>() const {
return std::basic_string<Ch, Tr>(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<char>::length(r), p, s) == 0;
return compare(r, Traits::length(r), p, s) == 0;
}
bool operator==(const std::basic_string<Char, Traits>& r) const {
@ -4233,10 +4248,50 @@ namespace sol {
}
};
template <typename Ch, typename Tr = std::char_traits<Tr>>
struct basic_string_view_hash {
typedef basic_string_view<Ch, Tr> argument_type;
typedef std::size_t result_type;
template <typename Al>
result_type operator()(const std::basic_string<Ch, Tr, Al>& r) const {
return (*this)(basic_string_view<Ch>(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<const unsigned char*>(r.data());
for (std::size_t sz = r.size(); sz != 0; --sz) {
hash ^= static_cast<size_t>(*cptr++);
hash *= static_cast<size_t>(1099511628211ULL);
}
return hash;
#endif
}
};
} // namespace sol
namespace std {
template <typename Ch, typename Tr>
struct hash< ::sol::basic_string_view<Ch, Tr> > : ::sol::basic_string_view_hash<Ch, Tr> {};
} // namespace std
namespace sol {
using string_view = basic_string_view<char>;
using wstring_view = basic_string_view<wchar_t>;
using u16string_view = basic_string_view<char16_t>;
using u32string_view = basic_string_view<char32_t>;
using string_view_hash = std::hash<string_view>;
#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 <typename Super>
basic_reference& operator=(proxy_base<Super>&& r);
@ -10586,11 +10652,11 @@ namespace sol {
return call_into_lua<check_args, clean_stack>(returns_list(), args_list(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(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<T>::metatable();
int argcount = lua_gettop(L);
call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, &usertype_traits<T>::user_metatable()[0], 1) : call_syntax::dot;
call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, usertype_traits<T>::user_metatable(), 1) : call_syntax::dot;
argcount -= static_cast<int>(syntax);
T* obj = detail::usertype_allocate<T>(L);
@ -12215,7 +12281,7 @@ namespace sol {
static int call(lua_State* L, F&) {
const auto& metakey = usertype_traits<T>::metatable();
int argcount = lua_gettop(L);
call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, &usertype_traits<T>::user_metatable()[0], 1) : call_syntax::dot;
call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, usertype_traits<T>::user_metatable(), 1) : call_syntax::dot;
argcount -= static_cast<int>(syntax);
T* obj = detail::usertype_allocate<T>(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<T>::user_metatable()[0], 1);
call_syntax syntax = stack::get_call_syntax(L, usertype_traits<T>::user_metatable(), 1);
int syntaxval = static_cast<int>(syntax);
int argcount = lua_gettop(L) - syntaxval;
return construct_match<T, meta::pop_front_type_t<meta::function_args_t<Cxs>>...>(onmatch(), L, argcount, 1 + syntaxval, f);
@ -13511,7 +13577,7 @@ namespace sol {
using base_t::lua_state;
basic_function() = default;
template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_function>>, meta::neg<std::is_same<base_t, stack_reference>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_function>>, meta::neg<std::is_same<base_t, stack_reference>>, meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_function(T&& r) noexcept
: base_t(std::forward<T>(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 <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_function(lua_State* L, T&& r)
: base_t(L, std::forward<T>(r)) {
@ -13753,7 +13822,7 @@ namespace sol {
handler_t error_handler;
basic_protected_function() = default;
template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_protected_function>>, meta::neg<std::is_base_of<proxy_base_tag, meta::unqualified_t<T>>>, meta::neg<std::is_same<base_t, stack_reference>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_protected_function>>, meta::neg<std::is_base_of<proxy_base_tag, meta::unqualified_t<T>>>, meta::neg<std::is_same<base_t, stack_reference>>, meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_protected_function(T&& r) noexcept
: base_t(std::forward<T>(r)), error_handler(get_default_handler(r.lua_state())) {
#ifdef SOL_SAFE_REFERENCES
@ -13820,6 +13889,10 @@ namespace sol {
#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 <cstdio>
#include <bitset>
#ifdef SOL_USE_BOOST
#include <boost/unordered_map.hpp>
#endif // Using Boost
namespace sol {
namespace usertype_detail {
#ifdef SOL_USE_BOOST
template <typename K, typename V, typename H = std::hash<K>, typename E = std::equal_to<>>
using map_t = boost::unordered_map<K, V, H, E>;
#else
template <typename K, typename V, typename H = std::hash<K>, typename E = std::equal_to<>>
using map_t = std::unordered_map<K, V, H, E>;
#endif // Boost map target
const int metatable_index = 2;
const int metatable_core_index = 3;
const int filler_index = 4;
@ -16667,7 +16752,7 @@ namespace sol {
}
};
typedef std::unordered_map<std::string, call_information> mapping_t;
typedef map_t<std::string, call_information> mapping_t;
struct variable_wrapper {
virtual int index(lua_State* L) = 0;
@ -16693,8 +16778,8 @@ namespace sol {
}
};
typedef std::unordered_map<std::string, std::unique_ptr<variable_wrapper>> variable_map;
typedef std::unordered_map<std::string, object> function_map;
typedef map_t<std::string, std::unique_ptr<variable_wrapper>> variable_map;
typedef map_t<std::string, object> 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<optional<string_detail::string_shim>>(L, is_index ? -1 : -2);
string_detail::string_shim accessor = maybeaccessor.value_or(string_detail::string_shim("(unknown)"));
auto maybeaccessor = stack::get<optional<string_view>>(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<user<simple_map>>(L, upvalue_index(simple_metatable_index));
function_map& functions = sm.functions;
optional<std::string> maybeaccessor = stack::get<optional<std::string>>(L, 2);
optional<string_view> maybeaccessor = stack::get<optional<string_view>>(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<string_view>());
#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<std::string> maybeaccessor = stack::get<optional<std::string>>(L, 2);
optional<string_view> maybeaccessor = stack::get<optional<string_view>>(L, 2);
if (!maybeaccessor) {
return;
}
std::string& accessor = maybeaccessor.value();
string_view& accessor_view = maybeaccessor.value();
mapping_t& mapping = umc.mapping;
std::vector<object>& runtime = umc.runtime;
int target = static_cast<int>(runtime.size());
#ifdef SOL_UNORDERED_MAP_COMPATIBLE_HASH
auto preexistingit = mapping.find(accessor_view, string_view_hash(), std::equal_to<string_view>());
#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<string_view>(L, keyidx);
auto memberit = f.mapping.find(name, string_view_hash(), std::equal_to<string_view>());
#else
std::string name = stack::get<std::string>(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<string_view>(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<string_view>());
#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<string_view>());
#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 <typename T, meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_table_core>>, meta::neg<std::is_same<base_type, stack_reference>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
template <typename T, meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_table_core>>, meta::neg<std::is_same<base_type, stack_reference>>, meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_table_core(detail::no_safety_tag, T&& r) noexcept
: base_t(std::forward<T>(r)) {
}
@ -18406,7 +18525,7 @@ namespace sol {
stack::check<basic_table_core>(lua_state(), -1, handler);
#endif // Safety
}
template <typename T, meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_table_core>>, meta::neg<std::is_same<base_type, stack_reference>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
template <typename T, meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_table_core>>, meta::neg<std::is_same<base_type, stack_reference>>, meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_table_core(T&& r) noexcept
: basic_table_core(detail::no_safety, std::forward<T>(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<basic_environment>(L, -1, handler);
#endif // Safety
}
template <typename T, meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_environment>>, meta::neg<std::is_same<base_type, stack_reference>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
template <typename T, meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_environment>>, meta::neg<std::is_same<base_type, stack_reference>>, meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_environment(T&& r) noexcept
: base_t(detail::no_safety, std::forward<T>(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 <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_environment(lua_State* L, T&& r) noexcept
: base_t(detail::no_safety, L, std::forward<T>(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<string_view>(L, pfr.stack_index());
string_view serr = stack::get<string_view>(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 <typename Fx, meta::disable<meta::is_specialization_of<basic_environment, meta::unqualified_t<Fx>>> = meta::enabler>
template <typename Fx, meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>, meta::is_specialization_of<basic_environment, meta::unqualified_t<Fx>>> = 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 <typename Fx, meta::disable<meta::is_specialization_of<basic_environment, meta::unqualified_t<Fx>>> = meta::enabler>
template <typename Fx, meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>, meta::is_specialization_of<basic_environment, meta::unqualified_t<Fx>>> = 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 <typename Fx, meta::disable<meta::is_specialization_of<basic_environment, meta::unqualified_t<Fx>>> = meta::enabler>
template <typename Fx, meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>, meta::is_specialization_of<basic_environment, meta::unqualified_t<Fx>>> = 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<Fx>(on_error), chunkname, mode);
}
template <typename Fx, meta::disable<meta::is_specialization_of<basic_environment, meta::unqualified_t<Fx>>> = meta::enabler>
template <typename Fx, meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>, meta::is_specialization_of<basic_environment, meta::unqualified_t<Fx>>> = 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<Fx>(on_error), mode);
}

View File

@ -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 {

View File

@ -210,7 +210,7 @@ namespace sol {
inline int construct(lua_State* L) {
static const auto& meta = usertype_traits<T>::metatable();
int argcount = lua_gettop(L);
call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, &usertype_traits<T>::user_metatable()[0], 1) : call_syntax::dot;
call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, usertype_traits<T>::user_metatable(), 1) : call_syntax::dot;
argcount -= static_cast<int>(syntax);
T* obj = detail::usertype_allocate<T>(L);
@ -509,7 +509,7 @@ namespace sol {
static int call(lua_State* L, F&) {
const auto& metakey = usertype_traits<T>::metatable();
int argcount = lua_gettop(L);
call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, &usertype_traits<T>::user_metatable()[0], 1) : call_syntax::dot;
call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, usertype_traits<T>::user_metatable(), 1) : call_syntax::dot;
argcount -= static_cast<int>(syntax);
T* obj = detail::usertype_allocate<T>(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<T>::user_metatable()[0], 1);
call_syntax syntax = stack::get_call_syntax(L, usertype_traits<T>::user_metatable(), 1);
int syntaxval = static_cast<int>(syntax);
int argcount = lua_gettop(L) - syntaxval;
return construct_match<T, meta::pop_front_type_t<meta::function_args_t<Cxs>>...>(onmatch(), L, argcount, 1 + syntaxval, f);

View File

@ -92,7 +92,7 @@ namespace sol {
stack::check<basic_environment>(L, -1, handler);
#endif // Safety
}
template <typename T, meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_environment>>, meta::neg<std::is_same<base_type, stack_reference>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
template <typename T, meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_environment>>, meta::neg<std::is_same<base_type, stack_reference>>, meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_environment(T&& r) noexcept
: base_t(detail::no_safety, std::forward<T>(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 <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_environment(lua_State* L, T&& r) noexcept
: base_t(detail::no_safety, L, std::forward<T>(r)) {

View File

@ -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

View File

@ -202,7 +202,7 @@ namespace sol {
handler_t error_handler;
basic_protected_function() = default;
template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_protected_function>>, meta::neg<std::is_base_of<proxy_base_tag, meta::unqualified_t<T>>>, meta::neg<std::is_same<base_t, stack_reference>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_protected_function>>, meta::neg<std::is_base_of<proxy_base_tag, meta::unqualified_t<T>>>, meta::neg<std::is_same<base_t, stack_reference>>, meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_protected_function(T&& r) noexcept
: base_t(std::forward<T>(r)), error_handler(get_default_handler(r.lua_state())) {
#ifdef SOL_SAFE_REFERENCES
@ -269,6 +269,10 @@ namespace sol {
#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)) {
}

View File

@ -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 <typename Super>
basic_reference& operator=(proxy_base<Super>&& r);

View File

@ -70,8 +70,13 @@ namespace sol {
string_view accessor = stack::get<string_view>(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<string_view>());
#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<string_view>());
#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) {

View File

@ -207,11 +207,11 @@ namespace sol {
return call_into_lua<check_args, clean_stack>(returns_list(), args_list(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(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;

View File

@ -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<string_view>(L, pfr.stack_index());
string_view serr = stack::get<string_view>(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 <typename Fx, meta::disable<meta::is_specialization_of<basic_environment, meta::unqualified_t<Fx>>> = meta::enabler>
template <typename Fx, meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>, meta::is_specialization_of<basic_environment, meta::unqualified_t<Fx>>> = 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 <typename Fx, meta::disable<meta::is_specialization_of<basic_environment, meta::unqualified_t<Fx>>> = meta::enabler>
template <typename Fx, meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>, meta::is_specialization_of<basic_environment, meta::unqualified_t<Fx>>> = 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 <typename Fx, meta::disable<meta::is_specialization_of<basic_environment, meta::unqualified_t<Fx>>> = meta::enabler>
template <typename Fx, meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>, meta::is_specialization_of<basic_environment, meta::unqualified_t<Fx>>> = 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<Fx>(on_error), chunkname, mode);
}
template <typename Fx, meta::disable<meta::is_specialization_of<basic_environment, meta::unqualified_t<Fx>>> = meta::enabler>
template <typename Fx, meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>, meta::is_specialization_of<basic_environment, meta::unqualified_t<Fx>>> = 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<Fx>(on_error), mode);
}

View File

@ -30,6 +30,10 @@
#ifdef SOL_CXX17_FEATURES
#include <string_view>
#endif // C++17 features
#include <functional>
#ifdef SOL_USE_BOOST
#include <boost/functional/hash.hpp>
#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<std::string_view> string_view_hash;
#else
template <typename Char, typename Traits = std::char_traits<Char>>
struct basic_string_view {
@ -92,12 +97,16 @@ namespace sol {
return size();
}
operator std::basic_string<Char, Traits>() const {
return std::basic_string<Ch, Tr>(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<char>::length(r), p, s) == 0;
return compare(r, Traits::length(r), p, s) == 0;
}
bool operator==(const std::basic_string<Char, Traits>& r) const {
@ -117,10 +126,50 @@ namespace sol {
}
};
template <typename Ch, typename Tr = std::char_traits<Tr>>
struct basic_string_view_hash {
typedef basic_string_view<Ch, Tr> argument_type;
typedef std::size_t result_type;
template <typename Al>
result_type operator()(const std::basic_string<Ch, Tr, Al>& r) const {
return (*this)(basic_string_view<Ch>(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<const unsigned char*>(r.data());
for (std::size_t sz = r.size(); sz != 0; --sz) {
hash ^= static_cast<size_t>(*cptr++);
hash *= static_cast<size_t>(1099511628211ULL);
}
return hash;
#endif
}
};
} // namespace sol
namespace std {
template <typename Ch, typename Tr>
struct hash< ::sol::basic_string_view<Ch, Tr> > : ::sol::basic_string_view_hash<Ch, Tr> {};
} // namespace std
namespace sol {
using string_view = basic_string_view<char>;
using wstring_view = basic_string_view<wchar_t>;
using u16string_view = basic_string_view<char16_t>;
using u32string_view = basic_string_view<char32_t>;
using string_view_hash = std::hash<string_view>;
#endif // C++17 Support
} // namespace sol

View File

@ -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 <typename T, meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_table_core>>, meta::neg<std::is_same<base_type, stack_reference>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
template <typename T, meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_table_core>>, meta::neg<std::is_same<base_type, stack_reference>>, meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_table_core(detail::no_safety_tag, T&& r) noexcept
: base_t(std::forward<T>(r)) {
}
@ -242,7 +245,7 @@ namespace sol {
stack::check<basic_table_core>(lua_state(), -1, handler);
#endif // Safety
}
template <typename T, meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_table_core>>, meta::neg<std::is_same<base_type, stack_reference>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
template <typename T, meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_table_core>>, meta::neg<std::is_same<base_type, stack_reference>>, meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_table_core(T&& r) noexcept
: basic_table_core(detail::no_safety, std::forward<T>(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);

View File

@ -555,10 +555,11 @@ namespace sol {
template <typename T>
using is_string_constructible = any<
std::is_same<unqualified_t<T>, const char*>, std::is_same<unqualified_t<T>, char>, std::is_same<unqualified_t<T>, std::string>, std::is_same<unqualified_t<T>, std::initializer_list<char>>
meta::all<std::is_array<unqualified_t<T>>, std::is_same<meta::unqualified_t<std::remove_all_extents_t<meta::unqualified_t<T>>>, char>>,
std::is_same<unqualified_t<T>, const char*>,
std::is_same<unqualified_t<T>, char>, std::is_same<unqualified_t<T>, std::string>, std::is_same<unqualified_t<T>, std::initializer_list<char>>
#ifdef SOL_CXX17_FEATURES
,
std::is_same<unqualified_t<T>, std::string_view>
, std::is_same<unqualified_t<T>, std::string_view>
#endif
>;

View File

@ -68,7 +68,7 @@ namespace sol {
using base_t::lua_state;
basic_function() = default;
template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_function>>, meta::neg<std::is_same<base_t, stack_reference>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_function>>, meta::neg<std::is_same<base_t, stack_reference>>, meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_function(T&& r) noexcept
: base_t(std::forward<T>(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 <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler>
basic_function(lua_State* L, T&& r)
: base_t(L, std::forward<T>(r)) {

View File

@ -42,8 +42,20 @@
#include <cassert>
#include <bitset>
#ifdef SOL_USE_BOOST
#include <boost/unordered_map.hpp>
#endif // Using Boost
namespace sol {
namespace usertype_detail {
#ifdef SOL_USE_BOOST
template <typename K, typename V, typename H = std::hash<K>, typename E = std::equal_to<>>
using map_t = boost::unordered_map<K, V, H, E>;
#else
template <typename K, typename V, typename H = std::hash<K>, typename E = std::equal_to<>>
using map_t = std::unordered_map<K, V, H, E>;
#endif // Boost map target
const int metatable_index = 2;
const int metatable_core_index = 3;
const int filler_index = 4;
@ -69,7 +81,7 @@ namespace sol {
}
};
typedef std::unordered_map<std::string, call_information> mapping_t;
typedef map_t<std::string, call_information> mapping_t;
struct variable_wrapper {
virtual int index(lua_State* L) = 0;
@ -95,8 +107,8 @@ namespace sol {
}
};
typedef std::unordered_map<std::string, std::unique_ptr<variable_wrapper>> variable_map;
typedef std::unordered_map<std::string, object> function_map;
typedef map_t<std::string, std::unique_ptr<variable_wrapper>> variable_map;
typedef map_t<std::string, object> 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<optional<string_detail::string_shim>>(L, is_index ? -1 : -2);
string_detail::string_shim accessor = maybeaccessor.value_or(string_detail::string_shim("(unknown)"));
auto maybeaccessor = stack::get<optional<string_view>>(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<user<simple_map>>(L, upvalue_index(simple_metatable_index));
function_map& functions = sm.functions;
optional<std::string> maybeaccessor = stack::get<optional<std::string>>(L, 2);
optional<string_view> maybeaccessor = stack::get<optional<string_view>>(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<string_view>());
#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<std::string> maybeaccessor = stack::get<optional<std::string>>(L, 2);
optional<string_view> maybeaccessor = stack::get<optional<string_view>>(L, 2);
if (!maybeaccessor) {
return;
}
std::string& accessor = maybeaccessor.value();
string_view& accessor_view = maybeaccessor.value();
mapping_t& mapping = umc.mapping;
std::vector<object>& runtime = umc.runtime;
int target = static_cast<int>(runtime.size());
#ifdef SOL_UNORDERED_MAP_COMPATIBLE_HASH
auto preexistingit = mapping.find(accessor_view, string_view_hash(), std::equal_to<string_view>());
#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<string_view>(L, keyidx);
auto memberit = f.mapping.find(name, string_view_hash(), std::equal_to<string_view>());
#else
std::string name = stack::get<std::string>(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;

View File

@ -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()

View File

@ -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 <sol_forward.hpp>
#endif // Single
#include <sol.hpp>
#include <catch.hpp>
#include <iterator>
@ -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,10 +1247,9 @@ 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"];
@ -1272,11 +1260,9 @@ print(mo)
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);
}());
}
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"];

View File

@ -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 <sol.hpp>
#include <catch.hpp>
#include <iterator>
@ -182,7 +180,8 @@ TEST_CASE("containers/returns", "make sure that even references to vectors are b
lua.set_function("f", [&]() -> std::vector<int>& {
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<std::string>{ "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<std::vector<std::string>> as_table_strings = lua["v1"];
sol::nested<std::vector<std::string>> 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<int>& {
return v;
});
lua.safe_script("x = f()");
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
REQUIRE(result1.valid());
std::vector<int> 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<int>& {
return v;
});
lua.safe_script("x = f()");
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
REQUIRE(result1.valid());
std::deque<int> 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<int, 3>& {
return v;
});
lua.safe_script("x = f()");
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
REQUIRE(result1.valid());
std::array<int, 3> 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<int>& {
return v;
});
lua.safe_script("x = f()");
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
REQUIRE(result1.valid());
std::list<int> 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<int>& {
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<int> 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<std::string, int>& {
return v;
});
lua.safe_script("x = f()");
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
REQUIRE(result1.valid());
std::map<std::string, int> 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<std::string, int>& {
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<std::string, int> 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<int>& {
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<int> 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<int>& {
return v;
});
lua.safe_script("x = f()");
auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error);
REQUIRE(result1.valid());
std::set<int> 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<std::vector<int>> 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<std::deque<int>> 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<std::array<int, 3>> 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<std::list<int>> 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<std::forward_list<int>> 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<std::map<std::string, int>> 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<std::unordered_map<std::string, int>> 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<std::unordered_set<int>> 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<std::set<int>> 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<Vec const*> 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>("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"(
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<bar>{ {}, {}, {} };
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<bar>& seqrefx = lua["x"];
std::list<bar>& 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<thing*>(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<int> fill_cmp{ 1, 2, 3 };
std::vector<int> 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<std::pair<std::string, int>>& la = lua["a"];
std::array<std::pair<std::string, int>, 5>& lb = lua["b"];
@ -1134,24 +1172,20 @@ TEST_CASE("containers/pointer types", "check that containers with unique usertyp
std::vector<base_t*> v2;
v2.push_back(&d1);
v2.push_back(&d2);
REQUIRE_NOTHROW([&]() {
lua["c1"] = std::move(v1);
lua["c2"] = &v2;
}());
REQUIRE_NOTHROW([&]() {
lua.safe_script("b1 = c1[1]");
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("b2 = c2[2]");
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<std::vector<int>> t1vector = lua["c"];
sol::as_table_t<std::deque<int>> t1deque = lua["c"];
sol::as_table_t<std::list<int>> t1list = lua["c"];

View File

@ -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 <catch.hpp>
#include <sol.hpp>
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);

View File

@ -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 <catch.hpp>
#include <sol.hpp>
#include <unordered_map>
#include <vector>
@ -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"];

View File

@ -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 <sol.hpp>
#include "test_sol.hpp"
#include <catch.hpp>
#include <iostream>
#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<int> maybe_env_a = plain_env["a"];
sol::optional<int> maybe_global_a = lua["a"];
sol::optional<int> 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<int> maybe_env_a = env_with_fallback["a"];
sol::optional<int> maybe_global_a = lua["a"];
sol::optional<int> 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<int> maybe_env_a = env["a"];
sol::optional<int> maybe_global_a = lua["a"];
sol::optional<int> 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<int> maybe_env_a = plain_env["a"];
sol::optional<int> maybe_global_a = lua["a"];
sol::optional<int> 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++") {

View File

@ -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 <sol.hpp>
#include <catch.hpp>
#include <iostream>
@ -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<depends_on_reference(holder&)>(), 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);

View File

@ -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 <sol.hpp>
#include "test_sol.hpp"
#include <catch.hpp>
#include <iostream>
#include "test_stack_guard.hpp"
template <typename T>
T va_func(sol::variadic_args va, T first) {
@ -73,8 +70,7 @@ void test_free_func(std::function<void()> f) {
void test_free_func2(std::function<int(int)> 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<std::string, int> 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<sol::function>("f").call<int, int, int>();
auto tlua = lua.get<sol::function>("g").call<int, int, int>();
auto tcpp2 = lua.get<sol::function>("h").call<int, float>();
@ -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<int, int, int> tcpp = lua.get<sol::function>("f")();
std::tuple<int, int, int> tlua = lua.get<sol::function>("g")();
std::tuple<int, int, int> tluaget = lua.get<int, int, int>("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>("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<decltype(&non_overloaded), &non_overloaded>);
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<int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int>(
@ -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<int>("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;

View File

@ -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 <sol.hpp>
#include <catch.hpp>
#include <iostream>
@ -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<crash_class>("CrashClass",
sol::call_constructor, sol::constructors<sol::types<>>());
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<crash_class>("CrashClass",
sol::call_constructor, sol::constructors<sol::types<>>());
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<test>();
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<test>();
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();

View File

@ -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 <sol.hpp>
#include <catch.hpp>
#include <iostream>
@ -62,14 +60,19 @@ TEST_CASE("inheritance/basic", "test that metatables are properly inherited") {
"d", &D::d,
sol::base_classes, sol::bases<C, B, A>());
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"];

View File

@ -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 <sol.hpp>
#include "test_sol.hpp"
#include <catch.hpp>
@ -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<bool>());
REQUIRE(x.as<bool>() == 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<T>());
REQUIRE(x.as<T>() == 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<T>());
REQUIRE(x.as<T>() == 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)");
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<std::int32_t>());
REQUIRE(x.as<std::int32_t>() == -1);
REQUIRE(x.is<std::uint32_t>());
REQUIRE(x.as<std::uint32_t>() == 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<std::int32_t>());
REQUIRE(x.as<std::int32_t>() == -1);
REQUIRE(x.is<std::uint32_t>());
REQUIRE(x.as<std::uint32_t>() == 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<std::int64_t>());
REQUIRE(x.as<std::int64_t>() == -1);
REQUIRE(x.is<std::uint64_t>());
REQUIRE(x.as<std::uint64_t>() == 0xFFFFFFFFFFFFFFFFull);
}());
}
}

View File

@ -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 <sol.hpp>
#include "test_sol.hpp"
#include <catch.hpp>
@ -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>("T");
@ -118,40 +121,46 @@ TEST_CASE("operators/default", "test that generic equality operators and all sor
lua.new_usertype<V>("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>("T");
@ -159,40 +168,46 @@ TEST_CASE("operators/default", "test that generic equality operators and all sor
lua.new_simple_usertype<V>("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>("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>("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>("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);
}

View File

@ -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 <sol.hpp>
#include "test_sol.hpp"
#include <catch.hpp>

View File

@ -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 <sol.hpp>
#include "test_sol.hpp"
#include <catch.hpp>
#include <iostream>
#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;

View File

@ -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 <sol.hpp>
#include "test_sol.hpp"
#include <catch.hpp>

View File

@ -23,6 +23,26 @@
#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 <sol_forward.hpp>
#endif // Single
#include <sol.hpp>
#include <catch.hpp>
#define CHECK_VALID ( x ) { auto r = x; REQUIRE(r.valid()); }
struct test_stack_guard {
lua_State* L;
int& begintop;
@ -31,6 +51,11 @@ struct test_stack_guard {
: L(L), begintop(begintop), endtop(endtop) {
begintop = lua_gettop(L);
}
void check() {
REQUIRE(begintop == endtop);
}
~test_stack_guard() {
endtop = lua_gettop(L);
}

View File

@ -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 <sol.hpp>
#include "test_sol.hpp"
#include <catch.hpp>
@ -35,8 +32,6 @@
#include <mutex>
#include <atomic>
#include "test_stack_guard.hpp"
template <typename Name, typename Data>
void write_file_attempt(Name&& filename, Data&& data) {
bool success = false;

View File

@ -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);

View File

@ -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 <sol.hpp>
#include "test_sol.hpp"
#include <catch.hpp>
@ -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<test>();

View File

@ -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 <sol.hpp>
#include "test_sol.hpp"
#include <catch.hpp>
@ -33,8 +30,6 @@
#include <numeric>
#include <vector>
#include "test_stack_guard.hpp"
std::string free_function() {
INFO("free_function()");
return "test";

View File

@ -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 <sol.hpp>
#include "test_sol.hpp"
#include <catch.hpp>
@ -441,10 +438,11 @@ TEST_CASE("usertype/self-referential usertype", "usertype classes must play nice
lua.new_usertype<self_test>("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<Vec> 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(
{
auto result = lua.safe_script(
"collectgarbage()\n"
"v = Vec.new(1, 2, 3)\n"
"print(v:length())"));
"print(v:length())");
REQUIRE(result.valid());
}
REQUIRE_NOTHROW(lua.safe_script(
{
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/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>("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<vars>("beep");
auto& my_var_ref = lua.get<vars>("beep");
auto* my_var_ptr = lua.get<vars*>("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<T> 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;

View File

@ -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 <sol.hpp>
#include "test_sol.hpp"
#include <catch.hpp>

View File

@ -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 <sol.hpp>
#include "test_sol.hpp"
#include <catch.hpp>

View File

@ -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 <sol.hpp>
#include "test_sol.hpp"
#include <catch.hpp>
@ -35,8 +33,6 @@
#include <unordered_map>
#include <vector>
#include "test_stack_guard.hpp"
bool func_opt_ret_bool(sol::optional<int> i) {
if (i) {
INFO(i.value());