sol2/tests/exceptions/source/functions.cpp
2021-05-07 03:17:24 -04:00

193 lines
7.1 KiB
C++

// sol2
// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <catch2/catch.hpp>
#include <sol/sol.hpp>
#include <stdexcept>
#include <string_view>
inline namespace sol2_tests_exceptions_functions {
inline constexpr const std::string_view special_string = "Whoopsie [expected]";
static void func_throw() {
throw std::runtime_error(special_string.data());
}
struct some_class {
void mem_func_throw() {
throw std::runtime_error(special_string.data());
}
};
} // namespace sol2_tests_exceptions_functions
TEST_CASE("exceptions/functions", "exercise the ability to throw exceptions many different function binding code paths") {
sol::state lua;
lua.open_libraries(sol::lib::base,
sol::lib::package,
sol::lib::coroutine,
sol::lib::string,
sol::lib::os,
sol::lib::math,
sol::lib::table,
sol::lib::io,
sol::lib::debug);
[[maybe_unused]] int a = 10;
some_class sc {};
auto throw_action = [](sol::state& lua, bool use_sc) {
if (use_sc) {
auto res = lua.safe_script("func_throw(sc)", sol::script_pass_on_error);
REQUIRE_FALSE(res.valid());
REQUIRE(res.status() == sol::call_status::runtime);
sol::error err = res.get<sol::error>();
std::string_view err_what(err.what());
REQUIRE(err_what.find(special_string) != std::string::npos);
}
else {
auto res = lua.safe_script("func_throw()", sol::script_pass_on_error);
REQUIRE_FALSE(res.valid());
REQUIRE(res.status() == sol::call_status::runtime);
sol::error err = res.get<sol::error>();
std::string_view err_what(err.what());
REQUIRE(err_what.find(special_string) != std::string::npos);
}
};
lua["sc"] = &sc;
SECTION("proxy") {
lua["func_throw"] = sol::property(&func_throw, &some_class::mem_func_throw);
REQUIRE_NOTHROW(throw_action(lua, false));
REQUIRE_NOTHROW(throw_action(lua, true));
lua["func_throw"] = sol::property(&some_class::mem_func_throw);
REQUIRE_NOTHROW(throw_action(lua, true));
lua["func_throw"] = sol::readonly_property(func_throw);
REQUIRE_NOTHROW(throw_action(lua, false));
lua["func_throw"] = sol::writeonly_property(&some_class::mem_func_throw);
REQUIRE_NOTHROW(throw_action(lua, true));
lua["func_throw"] = [f = &func_throw] { return f(); };
REQUIRE_NOTHROW(throw_action(lua, false));
lua["func_throw"] = &func_throw;
REQUIRE_NOTHROW(throw_action(lua, false));
lua["func_throw"] = [] { return func_throw(); };
REQUIRE_NOTHROW(throw_action(lua, false));
lua["func_throw"] = [a]() { (void)a; return func_throw(); };
REQUIRE_NOTHROW(throw_action(lua, false));
lua["func_throw"] = [&sc]() { return sc.mem_func_throw(); };
REQUIRE_NOTHROW(throw_action(lua, false));
lua["func_throw"] = &some_class::mem_func_throw;
REQUIRE_NOTHROW(throw_action(lua, true));
lua["func_throw"] = std::function<void()>([f = &func_throw] { return f(); });
REQUIRE_NOTHROW(throw_action(lua, false));
lua["func_throw"] = sol::overload(std::function<void()>([f = &func_throw] { return f(); }));
REQUIRE_NOTHROW(throw_action(lua, false));
lua["func_throw"] = std::function<void()>([] { return func_throw(); });
REQUIRE_NOTHROW(throw_action(lua, false));
lua["func_throw"] = std::function<void()>(&func_throw);
REQUIRE_NOTHROW(throw_action(lua, false));
lua["func_throw"] = std::function<void(some_class&)>(&some_class::mem_func_throw);
REQUIRE_NOTHROW(throw_action(lua, true));
}
SECTION("set_function") {
lua.set_function("func_throw", sol::property(&func_throw, &some_class::mem_func_throw));
REQUIRE_NOTHROW(throw_action(lua, false));
REQUIRE_NOTHROW(throw_action(lua, true));
lua.set_function("func_throw", sol::property(&some_class::mem_func_throw));
REQUIRE_NOTHROW(throw_action(lua, true));
lua.set_function("func_throw", sol::readonly_property(func_throw));
REQUIRE_NOTHROW(throw_action(lua, false));
// TODO: better handling of no_prop in this case here
// lua.set_function("func_throw", sol::writeonly_property(&some_class::mem_func_throw));
// REQUIRE_NOTHROW(throw_action(lua, true));
lua.set_function("func_throw", [f = &func_throw] { return f(); });
REQUIRE_NOTHROW(throw_action(lua, false));
lua.set_function("func_throw", &func_throw);
REQUIRE_NOTHROW(throw_action(lua, false));
lua.set_function("func_throw", [] { return func_throw(); });
REQUIRE_NOTHROW(throw_action(lua, false));
lua.set_function("func_throw", [a]() { (void)a; return func_throw(); });
REQUIRE_NOTHROW(throw_action(lua, false));
// TODO: this should work at some point, yeah?
/*
lua.set_function(
"func_throw", [](some_class& sc) { return sc.mem_func_throw(); }, sc);
REQUIRE_NOTHROW(throw_action(lua, false));
*/
lua.set_function("func_throw", [&sc]() { return sc.mem_func_throw(); });
REQUIRE_NOTHROW(throw_action(lua, false));
lua.set_function("func_throw", &some_class::mem_func_throw);
REQUIRE_NOTHROW(throw_action(lua, true));
lua.set_function("func_throw", std::function<void()>([f = &func_throw] { return f(); }));
REQUIRE_NOTHROW(throw_action(lua, false));
lua.set_function("func_throw", sol::overload(std::function<void()>([f = &func_throw] { return f(); })));
REQUIRE_NOTHROW(throw_action(lua, false));
lua.set_function("func_throw", std::function<void()>([] { return func_throw(); }));
REQUIRE_NOTHROW(throw_action(lua, false));
lua.set_function("func_throw", std::function<void()>(&func_throw));
REQUIRE_NOTHROW(throw_action(lua, false));
lua.set_function("func_throw", &some_class::mem_func_throw, &sc);
REQUIRE_NOTHROW(throw_action(lua, false));
lua.set_function("func_throw", &some_class::mem_func_throw, sc);
REQUIRE_NOTHROW(throw_action(lua, false));
lua.set_function("func_throw", &some_class::mem_func_throw, std::ref(sc));
REQUIRE_NOTHROW(throw_action(lua, false));
lua.set_function("func_throw", std::function<void(some_class&)>(&some_class::mem_func_throw));
REQUIRE_NOTHROW(throw_action(lua, true));
}
}