diff options
| author | William A. Kennington III <wak@google.com> | 2018-07-17 14:40:14 -0700 |
|---|---|---|
| committer | William A. Kennington III <wak@google.com> | 2018-07-17 14:40:14 -0700 |
| commit | feef68f751e09d8d5a4f2bf2f2f4cab27de1b73e (patch) | |
| tree | b1610bb958a43d3958b630525120501f768bc9fe | |
| parent | 2d943ead4b1c160a163f284fb5b639f1f076ce49 (diff) | |
| download | sdeventplus-feef68f751e09d8d5a4f2bf2f2f4cab27de1b73e.tar.gz sdeventplus-feef68f751e09d8d5a4f2bf2f2f4cab27de1b73e.zip | |
source/base: Refactor out callback routine
The callback mechanism will be used by other callback methods in the
same fashion, so we can template and re-use this functionality
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | src/sdeventplus/internal/utils.hpp | 35 | ||||
| -rw-r--r-- | src/sdeventplus/source/base.cpp | 31 | ||||
| -rw-r--r-- | src/sdeventplus/source/base.hpp | 2 | ||||
| -rw-r--r-- | test/Makefile.am | 5 | ||||
| -rw-r--r-- | test/internal/utils.cpp | 38 | ||||
| -rw-r--r-- | test/source/base.cpp | 44 |
7 files changed, 97 insertions, 59 deletions
@@ -46,4 +46,5 @@ Makefile.in /test/event /test/exception /test/internal_sdref +/test/internal_utils /test/source_base diff --git a/src/sdeventplus/internal/utils.hpp b/src/sdeventplus/internal/utils.hpp index 253e10d..c0b0e68 100644 --- a/src/sdeventplus/internal/utils.hpp +++ b/src/sdeventplus/internal/utils.hpp @@ -1,6 +1,11 @@ #pragma once +#include <cerrno> #include <chrono> +#include <cstdio> +#include <exception> +#include <sdeventplus/exception.hpp> +#include <stdexcept> namespace sdeventplus { @@ -9,4 +14,34 @@ namespace sdeventplus using SdEventDuration = std::chrono::duration<uint64_t, std::chrono::microseconds::period>; +namespace internal +{ + +// Helpers for sd_event callbacks to handle exceptions gracefully +template <typename Func, typename... Args> +static int performCallback(Func func, Args... args) +{ + try + { + func(args...); + return 0; + } + catch (const std::system_error& e) + { + fprintf(stderr, "sdeventplus: callback: %s\n", e.what()); + return -e.code().value(); + } + catch (const std::exception& e) + { + fprintf(stderr, "sdeventplus: callback: %s\n", e.what()); + return -ENOSYS; + } + catch (...) + { + fprintf(stderr, "sdeventplus: callback: Unknown error\n"); + return -ENOSYS; + } +} + +} // namespace internal } // namespace sdeventplus diff --git a/src/sdeventplus/source/base.cpp b/src/sdeventplus/source/base.cpp index 83908d1..5f202db 100644 --- a/src/sdeventplus/source/base.cpp +++ b/src/sdeventplus/source/base.cpp @@ -1,10 +1,10 @@ #include <cerrno> #include <cstdio> -#include <exception> +#include <functional> #include <sdeventplus/exception.hpp> #include <sdeventplus/internal/sdevent.hpp> +#include <sdeventplus/internal/utils.hpp> #include <sdeventplus/source/base.hpp> -#include <stdexcept> #include <type_traits> #include <utility> @@ -21,30 +21,6 @@ Base::~Base() } } -int Base::prepareCallback() -{ - try - { - prepare(*this); - return 0; - } - catch (const std::system_error& e) - { - fprintf(stderr, "sdeventplus: prepareCallback: %s\n", e.what()); - return -e.code().value(); - } - catch (const std::exception& e) - { - fprintf(stderr, "sdeventplus: prepareCallback: %s\n", e.what()); - return -ENOSYS; - } - catch (...) - { - fprintf(stderr, "sdeventplus: prepareCallback: Unknown error\n"); - return -ENOSYS; - } -} - sd_event_source* Base::get() const { return source.get(); @@ -84,7 +60,8 @@ static int prepare_callback(sd_event_source*, void* userdata) fprintf(stderr, "sdeventplus: prepare_callback: Missing userdata\n"); return -EINVAL; } - return reinterpret_cast<Base*>(userdata)->prepareCallback(); + Base* base = reinterpret_cast<Base*>(userdata); + return internal::performCallback(base->get_prepare(), std::ref(*base)); } void Base::set_prepare(Callback&& callback) diff --git a/src/sdeventplus/source/base.hpp b/src/sdeventplus/source/base.hpp index ed30016..9253b71 100644 --- a/src/sdeventplus/source/base.hpp +++ b/src/sdeventplus/source/base.hpp @@ -19,8 +19,6 @@ class Base virtual ~Base(); - int prepareCallback(); - sd_event_source* get() const; const Event& get_event() const; diff --git a/test/Makefile.am b/test/Makefile.am index d1923fa..4b94144 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -27,6 +27,11 @@ internal_sdref_SOURCES = internal/sdref.cpp internal_sdref_CPPFLAGS = $(gtest_cppflags) internal_sdref_LDADD = $(gtest_ldadd) +check_PROGRAMS += internal_utils +internal_utils_SOURCES = internal/utils.cpp +internal_utils_CPPFLAGS = $(gtest_cppflags) +internal_utils_LDADD = $(gtest_ldadd) + check_PROGRAMS += source_base source_base_SOURCES = source/base.cpp source_base_CPPFLAGS = $(gtest_cppflags) diff --git a/test/internal/utils.cpp b/test/internal/utils.cpp new file mode 100644 index 0000000..2a347ca --- /dev/null +++ b/test/internal/utils.cpp @@ -0,0 +1,38 @@ +#include <gtest/gtest.h> +#include <sdeventplus/internal/utils.hpp> +#include <stdexcept> +#include <system_error> + +namespace sdeventplus +{ +namespace internal +{ +namespace +{ + +TEST(UtilsTest, PerformCallbackSuccess) +{ + EXPECT_EQ(0, performCallback([]() {})); +} + +TEST(UtilsTest, SetPrepareSystemError) +{ + EXPECT_EQ(-EBUSY, performCallback([]() { + throw std::system_error(EBUSY, std::generic_category()); + })); +} + +TEST(UtilsTest, SetPrepareException) +{ + EXPECT_EQ(-ENOSYS, + performCallback([]() { throw std::runtime_error("Exception"); })); +} + +TEST(UtilsTest, SetPrepareUnknownException) +{ + EXPECT_EQ(-ENOSYS, performCallback([]() { throw static_cast<int>(1); })); +} + +} // namespace +} // namespace internal +} // namespace sdeventplus diff --git a/test/source/base.cpp b/test/source/base.cpp index 69ae8e2..435b6f2 100644 --- a/test/source/base.cpp +++ b/test/source/base.cpp @@ -8,7 +8,6 @@ #include <sdeventplus/source/base.hpp> #include <sdeventplus/test/sdevent.hpp> #include <string> -#include <system_error> #include <systemd/sd-event.h> #include <type_traits> #include <utility> @@ -322,47 +321,32 @@ TEST_F(BaseMethodTest, SetPrepareCallbackNoUserdata) EXPECT_EQ(-EINVAL, event_handler(nullptr, nullptr)); } -TEST_F(BaseMethodTest, SetPrepareNull) -{ - EXPECT_CALL(mock, sd_event_source_set_prepare(expected_source, nullptr)) - .WillOnce(Return(0)); - base->set_prepare(nullptr); - EXPECT_EQ(-ENOSYS, base->prepareCallback()); -} - -TEST_F(BaseMethodTest, SetPrepareSystemError) +TEST_F(BaseMethodTest, SetPrepareError) { - Base::Callback callback = [](Base&) { - throw std::system_error(EBUSY, std::generic_category()); - }; EXPECT_CALL(mock, sd_event_source_set_prepare(expected_source, testing::_)) .WillOnce(Return(0)); - base->set_prepare(std::move(callback)); + base->set_prepare(std::move([](Base&) {})); EXPECT_TRUE(base->get_prepare()); - EXPECT_FALSE(callback); - EXPECT_EQ(-EBUSY, base->prepareCallback()); + + Base::Callback callback = [](Base&) {}; + EXPECT_CALL(mock, sd_event_source_set_prepare(expected_source, testing::_)) + .WillOnce(Return(-EINVAL)); + EXPECT_THROW(base->set_prepare(std::move(callback)), SdEventError); + EXPECT_FALSE(base->get_prepare()); + EXPECT_TRUE(callback); } -TEST_F(BaseMethodTest, SetPrepareUnknownException) +TEST_F(BaseMethodTest, SetPrepareNull) { - Base::Callback callback = [](Base&) { throw static_cast<int>(1); }; EXPECT_CALL(mock, sd_event_source_set_prepare(expected_source, testing::_)) .WillOnce(Return(0)); - base->set_prepare(std::move(callback)); + base->set_prepare(std::move([](Base&) {})); EXPECT_TRUE(base->get_prepare()); - EXPECT_FALSE(callback); - EXPECT_EQ(-ENOSYS, base->prepareCallback()); -} -TEST_F(BaseMethodTest, SetPrepareError) -{ - Base::Callback callback = [](Base&) {}; - EXPECT_CALL(mock, sd_event_source_set_prepare(expected_source, testing::_)) - .WillOnce(Return(-EINVAL)); - EXPECT_THROW(base->set_prepare(std::move(callback)), SdEventError); + EXPECT_CALL(mock, sd_event_source_set_prepare(expected_source, nullptr)) + .WillOnce(Return(0)); + base->set_prepare(nullptr); EXPECT_FALSE(base->get_prepare()); - EXPECT_TRUE(callback); - EXPECT_EQ(-ENOSYS, base->prepareCallback()); } TEST_F(BaseMethodTest, GetPendingSuccess) |

