variables (fixes #118).main
TEST_CASE("exit function called on destruction", "[ScopeExit]") | TEST_CASE("exit function called on destruction", "[ScopeExit]") | ||||
{ | { | ||||
REQUIRE_CALL(m, deleter()); | REQUIRE_CALL(m, deleter()); | ||||
auto guard = sr::scope_exit{deleter}; | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = sr::scope_exit{deleter}; | |||||
} | } | ||||
TEST_CASE("exit function lambda called on destruction", "[ScopeExit]") | TEST_CASE("exit function lambda called on destruction", "[ScopeExit]") | ||||
{ | { | ||||
CallMock cm; | CallMock cm; | ||||
REQUIRE_CALL(cm, deleter()); | REQUIRE_CALL(cm, deleter()); | ||||
auto guard = sr::scope_exit{[&cm] { cm.deleter(); }}; | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = sr::scope_exit{[&cm] { cm.deleter(); }}; | |||||
} | } | ||||
TEST_CASE("exit function called and rethrow on copy exception", "[ScopeExit]") | TEST_CASE("exit function called and rethrow on copy exception", "[ScopeExit]") | ||||
{ | { | ||||
REQUIRE_CALL(m, deleter()); | REQUIRE_CALL(m, deleter()); | ||||
auto movedFrom = sr::scope_exit{deleter}; | auto movedFrom = sr::scope_exit{deleter}; | ||||
auto guard = std::move(movedFrom); | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = std::move(movedFrom); | |||||
} | } | ||||
TEST_CASE("move with copy init releases moved-from object", "[ScopeExit]") | TEST_CASE("move with copy init releases moved-from object", "[ScopeExit]") | ||||
{ | { | ||||
REQUIRE_CALL(m, deleter()); | REQUIRE_CALL(m, deleter()); | ||||
auto movedFrom = sr::scope_exit{deleter}; | auto movedFrom = sr::scope_exit{deleter}; | ||||
auto guard = std::move(movedFrom); | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = std::move(movedFrom); | |||||
} | } | ||||
TEST_CASE("move transfers state if released", "[ScopeExit]") | TEST_CASE("move transfers state if released", "[ScopeExit]") | ||||
REQUIRE_CALL(m, deleter()).TIMES(0); | REQUIRE_CALL(m, deleter()).TIMES(0); | ||||
auto movedFrom = sr::scope_exit{deleter}; | auto movedFrom = sr::scope_exit{deleter}; | ||||
movedFrom.release(); | movedFrom.release(); | ||||
auto guard = std::move(movedFrom); | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = std::move(movedFrom); | |||||
} | } | ||||
TEST_CASE("exit function called on destruction", "[ScopeFail]") | TEST_CASE("exit function called on destruction", "[ScopeFail]") | ||||
{ | { | ||||
REQUIRE_CALL(m, deleter()).TIMES(0); | REQUIRE_CALL(m, deleter()).TIMES(0); | ||||
auto guard = sr::scope_fail{deleter}; | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = sr::scope_fail{deleter}; | |||||
} | } | ||||
TEST_CASE("exit function lambda called on destruction", "[ScopeFail]") | TEST_CASE("exit function lambda called on destruction", "[ScopeFail]") | ||||
{ | { | ||||
CallMock cm; | CallMock cm; | ||||
REQUIRE_CALL(cm, deleter()).TIMES(0); | REQUIRE_CALL(cm, deleter()).TIMES(0); | ||||
auto guard = sr::scope_fail{[&cm] { cm.deleter(); }}; | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = sr::scope_fail{[&cm] { cm.deleter(); }}; | |||||
} | } | ||||
TEST_CASE("exit function called and rethrow on copy exception", "[ScopeFail]") | TEST_CASE("exit function called and rethrow on copy exception", "[ScopeFail]") | ||||
{ | { | ||||
REQUIRE_CALL(m, deleter()).TIMES(0); | REQUIRE_CALL(m, deleter()).TIMES(0); | ||||
auto movedFrom = sr::scope_fail{deleter}; | auto movedFrom = sr::scope_fail{deleter}; | ||||
auto guard = std::move(movedFrom); | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = std::move(movedFrom); | |||||
} | } | ||||
TEST_CASE("move with copy init releases moved-from object", "[ScopeFail]") | TEST_CASE("move with copy init releases moved-from object", "[ScopeFail]") | ||||
{ | { | ||||
REQUIRE_CALL(m, deleter()).TIMES(0); | REQUIRE_CALL(m, deleter()).TIMES(0); | ||||
auto movedFrom = sr::scope_fail{deleter}; | auto movedFrom = sr::scope_fail{deleter}; | ||||
auto guard = std::move(movedFrom); | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = std::move(movedFrom); | |||||
} | } | ||||
TEST_CASE("move transfers state if released", "[ScopeFail]") | TEST_CASE("move transfers state if released", "[ScopeFail]") | ||||
REQUIRE_CALL(m, deleter()).TIMES(0); | REQUIRE_CALL(m, deleter()).TIMES(0); | ||||
auto movedFrom = sr::scope_fail{deleter}; | auto movedFrom = sr::scope_fail{deleter}; | ||||
movedFrom.release(); | movedFrom.release(); | ||||
auto guard = std::move(movedFrom); | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = std::move(movedFrom); | |||||
} | } | ||||
TEST_CASE("exit function called on exception", "[ScopeFail]") | TEST_CASE("exit function called on exception", "[ScopeFail]") | ||||
try | try | ||||
{ | { | ||||
REQUIRE_CALL(m, deleter()); | REQUIRE_CALL(m, deleter()); | ||||
auto guard = sr::scope_fail{deleter}; | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = sr::scope_fail{deleter}; | |||||
throw 3; | throw 3; | ||||
} | } | ||||
catch( ... ) | catch( ... ) | ||||
} | } | ||||
catch( ... ) | catch( ... ) | ||||
{ | { | ||||
auto guard = sr::scope_fail{deleter}; | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = sr::scope_fail{deleter}; | |||||
} | } | ||||
} | } | ||||
TEST_CASE("exit function called on destruction", "[ScopeSuccess]") | TEST_CASE("exit function called on destruction", "[ScopeSuccess]") | ||||
{ | { | ||||
REQUIRE_CALL(m, deleter()); | REQUIRE_CALL(m, deleter()); | ||||
auto guard = sr::scope_success{deleter}; | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = sr::scope_success{deleter}; | |||||
} | } | ||||
TEST_CASE("exit function lambda called on destruction", "[ScopeSuccess]") | TEST_CASE("exit function lambda called on destruction", "[ScopeSuccess]") | ||||
{ | { | ||||
CallMock cm; | CallMock cm; | ||||
REQUIRE_CALL(cm, deleter()); | REQUIRE_CALL(cm, deleter()); | ||||
auto guard = sr::scope_success{[&cm] { cm.deleter(); }}; | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = sr::scope_success{[&cm] { cm.deleter(); }}; | |||||
} | } | ||||
TEST_CASE("exit function not called and rethrow on copy exception", "[ScopeSuccess]") | TEST_CASE("exit function not called and rethrow on copy exception", "[ScopeSuccess]") | ||||
{ | { | ||||
REQUIRE_CALL(m, deleter()); | REQUIRE_CALL(m, deleter()); | ||||
auto movedFrom = sr::scope_success{deleter}; | auto movedFrom = sr::scope_success{deleter}; | ||||
auto guard = std::move(movedFrom); | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = std::move(movedFrom); | |||||
} | } | ||||
TEST_CASE("move with copy init releases moved-from object", "[ScopeSuccess]") | TEST_CASE("move with copy init releases moved-from object", "[ScopeSuccess]") | ||||
const NotNothrowMoveMock notNothrow{&mock}; | const NotNothrowMoveMock notNothrow{&mock}; | ||||
REQUIRE_CALL(mock, deleter()); | REQUIRE_CALL(mock, deleter()); | ||||
sr::scope_success movedFrom{notNothrow}; | sr::scope_success movedFrom{notNothrow}; | ||||
auto guard = std::move(movedFrom); | |||||
[[maybe_unused]] auto guard = std::move(movedFrom); | |||||
} | } | ||||
TEST_CASE("move transfers state", "[ScopeSuccess]") | TEST_CASE("move transfers state", "[ScopeSuccess]") | ||||
{ | { | ||||
REQUIRE_CALL(m, deleter()); | REQUIRE_CALL(m, deleter()); | ||||
auto movedFrom = sr::scope_success{deleter}; | auto movedFrom = sr::scope_success{deleter}; | ||||
auto guard = std::move(movedFrom); | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = std::move(movedFrom); | |||||
} | } | ||||
TEST_CASE("move transfers state if released", "[ScopeSuccess]") | TEST_CASE("move transfers state if released", "[ScopeSuccess]") | ||||
REQUIRE_CALL(m, deleter()).TIMES(0); | REQUIRE_CALL(m, deleter()).TIMES(0); | ||||
auto movedFrom = sr::scope_success{deleter}; | auto movedFrom = sr::scope_success{deleter}; | ||||
movedFrom.release(); | movedFrom.release(); | ||||
auto guard = std::move(movedFrom); | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = std::move(movedFrom); | |||||
} | } | ||||
TEST_CASE("exit function not called on exception", "[ScopeFail]") | TEST_CASE("exit function not called on exception", "[ScopeFail]") | ||||
{ | { | ||||
try | try | ||||
{ | { | ||||
auto guard = sr::scope_success{deleter}; | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = sr::scope_success{deleter}; | |||||
throw 3; | throw 3; | ||||
} | } | ||||
catch( ... ) | catch( ... ) | ||||
catch( ... ) | catch( ... ) | ||||
{ | { | ||||
REQUIRE_CALL(m, deleter()); | REQUIRE_CALL(m, deleter()); | ||||
auto guard = sr::scope_success{deleter}; | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = sr::scope_success{deleter}; | |||||
} | } | ||||
} | } | ||||
TEST_CASE("construction with move", "[UniqueResource]") | TEST_CASE("construction with move", "[UniqueResource]") | ||||
{ | { | ||||
REQUIRE_CALL(m, deleter(3)); | REQUIRE_CALL(m, deleter(3)); | ||||
auto guard = sr::unique_resource{Handle{3}, deleter}; | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = sr::unique_resource{Handle{3}, deleter}; | |||||
} | } | ||||
TEST_CASE("construction with copy", "[UniqueResource]") | TEST_CASE("construction with copy", "[UniqueResource]") | ||||
REQUIRE_CALL(m, deleter(3)); | REQUIRE_CALL(m, deleter(3)); | ||||
const Handle h{3}; | const Handle h{3}; | ||||
const auto d = [](auto v) { m.deleter(v); }; | const auto d = [](auto v) { m.deleter(v); }; | ||||
auto guard = sr::unique_resource{h, d}; | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = sr::unique_resource{h, d}; | |||||
} | } | ||||
TEST_CASE("construction with copy calls deleter and rethrows on failed copy", "[UniqueResource]") | TEST_CASE("construction with copy calls deleter and rethrows on failed copy", "[UniqueResource]") | ||||
const auto d = [](const auto&) { m.deleter(3); }; | const auto d = [](const auto&) { m.deleter(3); }; | ||||
REQUIRE_CALL(m, deleter(3)); | REQUIRE_CALL(m, deleter(3)); | ||||
sr::unique_resource guard{noMove, d}; | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] sr::unique_resource guard{noMove, d}; | |||||
}()); | }()); | ||||
} | } | ||||
const CopyMock copyMock; | const CopyMock copyMock; | ||||
sr::unique_resource movedFrom{copyMock, d}; | sr::unique_resource movedFrom{copyMock, d}; | ||||
auto guard = std::move(movedFrom); | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = std::move(movedFrom); | |||||
} | } | ||||
TEST_CASE("move assignment calls deleter", "[UniqueResource]") | TEST_CASE("move assignment calls deleter", "[UniqueResource]") | ||||
TEST_CASE("deleter called on destruction", "[UniqueResource]") | TEST_CASE("deleter called on destruction", "[UniqueResource]") | ||||
{ | { | ||||
REQUIRE_CALL(m, deleter(3)); | REQUIRE_CALL(m, deleter(3)); | ||||
auto guard = sr::unique_resource{Handle{3}, deleter}; | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = sr::unique_resource{Handle{3}, deleter}; | |||||
} | } | ||||
TEST_CASE("reset calls deleter", "[UniqueResource]") | TEST_CASE("reset calls deleter", "[UniqueResource]") | ||||
TEST_CASE("make unique resource", "[UniqueResource]") | TEST_CASE("make unique resource", "[UniqueResource]") | ||||
{ | { | ||||
REQUIRE_CALL(m, deleter(7)); | REQUIRE_CALL(m, deleter(7)); | ||||
auto guard = sr::unique_resource{Handle{7}, deleter}; | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = sr::unique_resource{Handle{7}, deleter}; | |||||
} | } | ||||
TEST_CASE("make unique resource with reference wrapper", "[UniqueResource]") | TEST_CASE("make unique resource with reference wrapper", "[UniqueResource]") | ||||
{ | { | ||||
REQUIRE_CALL(m, deleter(3)); | REQUIRE_CALL(m, deleter(3)); | ||||
Handle h{3}; | Handle h{3}; | ||||
auto guard = sr::unique_resource{std::ref(h), deleter}; | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = sr::unique_resource{std::ref(h), deleter}; | |||||
} | } | ||||
TEST_CASE("make unique resource checked", "[UniqueResource]") | TEST_CASE("make unique resource checked", "[UniqueResource]") | ||||
{ | { | ||||
REQUIRE_CALL(m, deleter(4)); | REQUIRE_CALL(m, deleter(4)); | ||||
auto guard = sr::make_unique_resource_checked(Handle{4}, Handle{-1}, deleter); | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = sr::make_unique_resource_checked(Handle{4}, Handle{-1}, deleter); | |||||
} | } | ||||
TEST_CASE("make unique resource checked releases if invalid", "[UniqueResource]") | TEST_CASE("make unique resource checked releases if invalid", "[UniqueResource]") | ||||
{ | { | ||||
auto guard = sr::make_unique_resource_checked(Handle{-1}, Handle{-1}, deleter); | |||||
static_cast<void>(guard); | |||||
[[maybe_unused]] auto guard = sr::make_unique_resource_checked(Handle{-1}, Handle{-1}, deleter); | |||||
} | } | ||||