From 1b208c8ef055087daa1a5ba793cd38a1f9c705d0 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Fri, 5 Jun 2020 00:05:14 +0700 Subject: [PATCH] add tests and examples --- README.md | 52 ++++++++++++++- headers/defer.hpp/defer.hpp | 4 +- untests/defer_examples.cpp | 50 +++++++++++++-- untests/defer_tests.cpp | 123 ++++++++++++++++++++++++++++++++++++ 4 files changed, 222 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 37ea727..75a11c3 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,56 @@ target_link_libraries(your_project_target defer.hpp) ## Examples -TODO +### Basic Defer + +```cpp +if ( FILE *file = ::fopen("output.txt", "a") ) { + // defer will close the file after scope or on exception + DEFER([file]{ ::fclose(file); }); + + const char buffer[] = "hello world\n"; + if ( 12 != ::fwrite(buffer, sizeof(buffer[0]), ::strlen(buffer), file) ) { + throw std::runtime_error("some exception"); + } +} +``` + +### Error Defer + +```cpp +if ( FILE *file = ::fopen("output.txt", "a") ) { + // defer will close the file after scope or on exception + DEFER([file]{ ::fclose(file); }); + + // error defer will be called on exception + ERROR_DEFER([]{ + std::cerr << "there is something wrong" << std::endl; + }); + + const char buffer[] = "hello world\n"; + if ( 12 != ::fwrite(buffer, sizeof(buffer[0]), ::strlen(buffer), file) ) { + throw std::runtime_error("some exception"); + } +} +``` + +### Return Defer + +```cpp +if ( FILE *file = ::fopen("output.txt", "a") ) { + // defer will close the file after scope or on exception + DEFER([file]{ ::fclose(file); }); + + // return defer will be called on successful scope exit + RETURN_DEFER([]{ + std::cout << "all is ok!" << std::endl; + }); + + const char buffer[] = "hello world\n"; + if ( 12 != ::fwrite(buffer, sizeof(buffer[0]), ::strlen(buffer), file) ) { + throw std::runtime_error("some exception"); + } +} +``` ## [License (MIT)](./LICENSE.md) diff --git a/headers/defer.hpp/defer.hpp b/headers/defer.hpp/defer.hpp index c7bd702..fae4a72 100644 --- a/headers/defer.hpp/defer.hpp +++ b/headers/defer.hpp/defer.hpp @@ -57,7 +57,7 @@ namespace defer_hpp explicit error_defer_impl( UF&& f, std::tuple&& args) - : defer_impl(std::forward(f), std::move(args)) + : defer_impl(std::forward(f), std::move(args)) , exceptions_(std::uncaught_exceptions()) {} ~error_defer_impl() noexcept final { @@ -76,7 +76,7 @@ namespace defer_hpp explicit return_defer_impl( UF&& f, std::tuple&& args) - : defer_impl(std::forward(f), std::move(args)) + : defer_impl(std::forward(f), std::move(args)) , exceptions_(std::uncaught_exceptions()) {} ~return_defer_impl() noexcept final { diff --git a/untests/defer_examples.cpp b/untests/defer_examples.cpp index 53eb66d..e7e53bf 100644 --- a/untests/defer_examples.cpp +++ b/untests/defer_examples.cpp @@ -7,11 +7,53 @@ #define CATCH_CONFIG_FAST_COMPILE #include +#include #include -namespace -{ -} - TEST_CASE("examples") { + SECTION("basic_defer") { + if ( FILE *file = ::fopen("output.txt", "a") ) { + // defer will close the file after scope or on exception + DEFER([file]{ ::fclose(file); }); + + const char buffer[] = "hello world\n"; + if ( 12 != ::fwrite(buffer, sizeof(buffer[0]), ::strlen(buffer), file) ) { + throw std::runtime_error("some exception"); + } + } + } + + SECTION("error_defer") { + if ( FILE *file = ::fopen("output.txt", "a") ) { + // defer will close the file after scope or on exception + DEFER([file]{ ::fclose(file); }); + + // error defer will be called on exception + ERROR_DEFER([]{ + std::cerr << "there is something wrong" << std::endl; + }); + + const char buffer[] = "hello world\n"; + if ( 12 != ::fwrite(buffer, sizeof(buffer[0]), ::strlen(buffer), file) ) { + throw std::runtime_error("some exception"); + } + } + } + + SECTION("return_defer") { + if ( FILE *file = ::fopen("output.txt", "a") ) { + // defer will close the file after scope or on exception + DEFER([file]{ ::fclose(file); }); + + // return defer will be called on successful scope exit + RETURN_DEFER([]{ + std::cout << "all is ok!" << std::endl; + }); + + const char buffer[] = "hello world\n"; + if ( 12 != ::fwrite(buffer, sizeof(buffer[0]), ::strlen(buffer), file) ) { + throw std::runtime_error("some exception"); + } + } + } } diff --git a/untests/defer_tests.cpp b/untests/defer_tests.cpp index 1e0da85..7217e24 100644 --- a/untests/defer_tests.cpp +++ b/untests/defer_tests.cpp @@ -14,4 +14,127 @@ namespace } TEST_CASE("defer") { + SECTION("simple") { + int i = 0; + { + DEFER([&i]{ ++i; }); + REQUIRE(i == 0); + } + REQUIRE(i == 1); + } + + SECTION("simple_with_arg") { + int i = 0; + { + DEFER([](int& i){ ++i; }, std::ref(i)); + REQUIRE(i == 0); + } + REQUIRE(i == 1); + } + + SECTION("simple_with_args") { + int i = 0, j = 0; + { + DEFER([](int& i, int& j){ ++i; j += 2; }, std::ref(i), std::ref(j)); + REQUIRE(i == 0); + REQUIRE(j == 0); + } + REQUIRE(i == 1); + REQUIRE(j == 2); + } + + SECTION("simple_with_exception") { + int i = 0; + try { + DEFER([&i]{ ++i; }); + REQUIRE(i == 0); + throw std::exception(); + } catch (...) { + } + REQUIRE(i == 1); + } +} + +TEST_CASE("error_defer") { + SECTION("simple") { + int i = 0; + { + ERROR_DEFER([&i]{ ++i; }); + REQUIRE(i == 0); + } + REQUIRE(i == 0); + } + + SECTION("simple_with_arg") { + int i = 0; + { + ERROR_DEFER([](int& i){ ++i; }, std::ref(i)); + REQUIRE(i == 0); + } + REQUIRE(i == 0); + } + + SECTION("simple_with_args") { + int i = 0, j = 0; + { + ERROR_DEFER([](int& i, int& j){ ++i; j += 2; }, std::ref(i), std::ref(j)); + REQUIRE(i == 0); + REQUIRE(j == 0); + } + REQUIRE(i == 0); + REQUIRE(j == 0); + } + + SECTION("simple_with_exception") { + int i = 0; + try { + ERROR_DEFER([&i]{ ++i; }); + REQUIRE(i == 0); + throw std::exception(); + } catch (...) { + } + REQUIRE(i == 1); + } +} + +TEST_CASE("return_defer") { + SECTION("simple") { + int i = 0; + { + RETURN_DEFER([&i]{ ++i; }); + REQUIRE(i == 0); + } + REQUIRE(i == 1); + } + + SECTION("simple_with_arg") { + int i = 0; + { + RETURN_DEFER([](int& i){ ++i; }, std::ref(i)); + REQUIRE(i == 0); + } + REQUIRE(i == 1); + } + + SECTION("simple_with_args") { + int i = 0, j = 0; + { + RETURN_DEFER([](int& i, int& j){ ++i; j += 2; }, std::ref(i), std::ref(j)); + REQUIRE(i == 0); + REQUIRE(j == 0); + } + REQUIRE(i == 1); + REQUIRE(j == 2); + } + + SECTION("simple_with_exception") { + int i = 0; + try { + RETURN_DEFER([&i]{ ++i; }); + REQUIRE(i == 0); + throw std::exception(); + } catch (...) { + } + REQUIRE(i == 0); + } }