From 661b30b395d72a6c7754128c69ff95e480bc76f5 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 1 Jan 2020 03:26:41 +0700 Subject: [PATCH] add finally method https://github.com/BlackMATov/promise.hpp/issues/33 --- headers/promise.hpp/promise.hpp | 29 ++++++++ untests/promise_tests.cpp | 126 ++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+) diff --git a/headers/promise.hpp/promise.hpp b/headers/promise.hpp/promise.hpp index 778729a..284bd16 100644 --- a/headers/promise.hpp/promise.hpp +++ b/headers/promise.hpp/promise.hpp @@ -416,6 +416,21 @@ namespace promise_hpp [](auto&& v) { return std::forward(v); }, std::forward(on_reject)); } + + // + // finally + // + + template < typename FinallyF > + promise finally(FinallyF&& on_finally) { + return then([f = on_finally](auto&& v) { + std::invoke(std::move(f)); + return std::forward(v); + }, [f = on_finally](std::exception_ptr e) -> T { + std::invoke(std::move(f)); + std::rethrow_exception(e); + }); + } private: class state; std::shared_ptr state_; @@ -837,6 +852,20 @@ namespace promise_hpp [](){}, std::forward(on_reject)); } + + // + // finally + // + + template < typename FinallyF > + promise finally(FinallyF&& on_finally) { + return then([f = on_finally]() { + std::invoke(std::move(f)); + }, [f = on_finally](std::exception_ptr e) { + std::invoke(std::move(f)); + std::rethrow_exception(e); + }); + } private: class state; std::shared_ptr state_; diff --git a/untests/promise_tests.cpp b/untests/promise_tests.cpp index abd2fe7..2bcda50 100644 --- a/untests/promise_tests.cpp +++ b/untests/promise_tests.cpp @@ -310,6 +310,132 @@ TEST_CASE("promise") { REQUIRE(call_fail_with_logic_error); } } + SECTION("finally") { + { + bool all_is_ok = false; + auto p = pr::promise(); + p.finally([&all_is_ok](){ + all_is_ok = true; + }); + REQUIRE_FALSE(all_is_ok); + p.resolve(1); + REQUIRE(all_is_ok); + } + { + bool all_is_ok = false; + auto p = pr::promise(); + p.finally([&all_is_ok](){ + all_is_ok = true; + }); + REQUIRE_FALSE(all_is_ok); + p.reject(std::make_exception_ptr(std::logic_error("hello fail"))); + REQUIRE(all_is_ok); + } + { + bool all_is_ok = false; + pr::make_resolved_promise(1) + .finally([&all_is_ok](){ + all_is_ok = true; + }); + REQUIRE(all_is_ok); + } + { + bool all_is_ok = false; + pr::make_rejected_promise(std::logic_error("hello fail")) + .finally([&all_is_ok](){ + all_is_ok = true; + }); + REQUIRE(all_is_ok); + } + } + SECTION("after_finally") { + { + int check_84_int = 0; + auto p = pr::promise<>(); + p.finally([&check_84_int](){ + check_84_int = 42; + return 100500; + }).then([&check_84_int](){ + check_84_int *= 2; + }); + REQUIRE(check_84_int == 0); + p.resolve(); + REQUIRE(check_84_int == 84); + } + { + int check_84_int = 0; + auto p = pr::promise<>(); + p.finally([&check_84_int](){ + check_84_int = 42; + return 100500; + }).except([&check_84_int](std::exception_ptr){ + check_84_int *= 2; + }); + REQUIRE(check_84_int == 0); + p.reject(std::make_exception_ptr(std::logic_error("hello fail"))); + REQUIRE(check_84_int == 84); + } + } + SECTION("failed_finally") { + { + int check_84_int = 0; + auto p = pr::promise<>(); + p.finally([&check_84_int](){ + check_84_int += 42; + throw std::logic_error("hello fail"); + }).except([&check_84_int](std::exception_ptr e){ + if ( check_hello_fail_exception(e) ) { + check_84_int += 42; + } + }); + p.resolve(); + REQUIRE(check_84_int == 84); + } + { + int check_84_int = 0; + auto p = pr::promise<>(); + p.finally([&check_84_int](){ + check_84_int += 42; + throw std::logic_error("hello fail"); + }).except([&check_84_int](std::exception_ptr e){ + if ( check_hello_fail_exception(e) ) { + check_84_int += 42; + } + }); + p.reject(std::make_exception_ptr(std::logic_error("hello"))); + REQUIRE(check_84_int == 84); + } + { + int check_84_int = 0; + auto p = pr::promise(); + p.finally([&check_84_int](){ + check_84_int += 42; + throw std::logic_error("hello fail"); + }).except([&check_84_int](std::exception_ptr e) -> int { + if ( check_hello_fail_exception(e) ) { + check_84_int += 42; + } + return 0; + }); + p.resolve(1); + REQUIRE(check_84_int == 84); + } + { + int check_84_int = 0; + auto p = pr::promise(); + p.finally([&check_84_int](){ + check_84_int += 42; + throw std::logic_error("hello fail"); + }).except([&check_84_int](std::exception_ptr e) -> int { + if ( check_hello_fail_exception(e) ) { + check_84_int += 42; + } + return 0; + }); + p.reject(std::make_exception_ptr(std::logic_error("hello"))); + REQUIRE(check_84_int == 84); + } + } SECTION("make_promise") { { int check_84_int = 0;