diff options
author | William A. Kennington III <wak@google.com> | 2018-11-02 17:28:35 -0700 |
---|---|---|
committer | William A. Kennington III <wak@google.com> | 2019-03-29 21:14:57 +0000 |
commit | 7a5e23259a696bf240a14200535680b42c445096 (patch) | |
tree | 9553542506b77601755b0f548c2fe48031198a62 /test | |
parent | 1937ef65b505b1d856c74074d6042bdb336728af (diff) | |
download | stdplus-7a5e23259a696bf240a14200535680b42c445096.tar.gz stdplus-7a5e23259a696bf240a14200535680b42c445096.zip |
handle/managed: Implement non-copyable handle
This is a generic handle type that holds a resource and uses RAII to
call a user defined function when the resource is destroyed. A future
change will implement a smart file descriptor based on this interface.
A follow up change will implement the copyable version.
Tested:
Built and run through unit tests.
Change-Id: Ia8da1d662319e8fb58380ed4979bcf1b74f66dfb
Signed-off-by: William A. Kennington III <wak@google.com>
Diffstat (limited to 'test')
-rw-r--r-- | test/Makefile.am | 5 | ||||
-rw-r--r-- | test/handle/managed.cpp | 209 | ||||
-rw-r--r-- | test/meson.build | 1 |
3 files changed, 215 insertions, 0 deletions
diff --git a/test/Makefile.am b/test/Makefile.am index 1c4a5a1..45f54f4 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -7,6 +7,11 @@ gtest_ldadd = $(STDPLUS_LIBS) $(GTEST_LIBS) $(GMOCK_LIBS) -lgmock_main check_PROGRAMS = TESTS = $(check_PROGRAMS) +check_PROGRAMS += handle/managed +handle_managed_SOURCES = handle/managed.cpp +handle_managed_CPPFLAGS = $(gtest_cppflags) +handle_managed_LDADD = $(gtest_ldadd) + check_PROGRAMS += signal signal_SOURCES = signal.cpp signal_CPPFLAGS = $(gtest_cppflags) diff --git a/test/handle/managed.cpp b/test/handle/managed.cpp new file mode 100644 index 0000000..b3ba6a6 --- /dev/null +++ b/test/handle/managed.cpp @@ -0,0 +1,209 @@ +#include <gtest/gtest.h> +#include <optional> +#include <stdplus/handle/managed.hpp> +#include <string> +#include <tuple> +#include <utility> +#include <vector> + +namespace stdplus +{ +namespace +{ + +static std::vector<int> dropped; +static int stored = 0; + +void drop(int&& i) +{ + dropped.push_back(std::move(i)); +} + +void drop(int&& i, std::string&, int& si) +{ + dropped.push_back(std::move(i)); + // Make sure we can update the stored data + stored = si++; +} + +using SimpleHandle = Managed<int>::Handle<drop>; +using StoreHandle = Managed<int, std::string, int>::Handle<drop>; + +class ManagedHandleTest : public ::testing::Test +{ + protected: + void SetUp() + { + dropped.clear(); + } + + void TearDown() + { + EXPECT_TRUE(dropped.empty()); + } +}; + +TEST_F(ManagedHandleTest, EmptyNoStorage) +{ + SimpleHandle h(std::nullopt); + EXPECT_FALSE(h); + EXPECT_THROW(h.value(), std::bad_optional_access); + h.reset(); + EXPECT_FALSE(h.has_value()); + EXPECT_THROW(h.value(), std::bad_optional_access); + EXPECT_EQ(std::nullopt, h.maybe_value()); +} + +TEST_F(ManagedHandleTest, EmptyWithStorage) +{ + StoreHandle h(std::nullopt, "str", 5); + EXPECT_FALSE(h); + EXPECT_THROW(h.value(), std::bad_optional_access); + h.reset(std::nullopt); + EXPECT_FALSE(h); + EXPECT_THROW(h.value(), std::bad_optional_access); + + StoreHandle h2(std::nullopt, std::make_tuple<std::string, int>("str", 5)); + EXPECT_FALSE(h2); + EXPECT_THROW(h2.value(), std::bad_optional_access); +} + +TEST_F(ManagedHandleTest, SimplePopulated) +{ + constexpr int expected = 3; + { + int val = expected; + SimpleHandle h(std::move(val)); + EXPECT_TRUE(h.has_value()); + EXPECT_EQ(expected, *h); + EXPECT_EQ(expected, h.value()); + EXPECT_EQ(expected, h.maybe_value()); + EXPECT_TRUE(dropped.empty()); + } + EXPECT_EQ(std::vector{expected}, dropped); + dropped.clear(); +} + +TEST_F(ManagedHandleTest, OptionalPopulated) +{ + constexpr int expected = 3; + { + std::optional<int> maybeVal{expected}; + SimpleHandle h(std::move(maybeVal)); + EXPECT_TRUE(h); + EXPECT_EQ(expected, *h); + EXPECT_EQ(expected, h.value()); + EXPECT_TRUE(dropped.empty()); + } + EXPECT_EQ(std::vector{expected}, dropped); + dropped.clear(); +} + +TEST_F(ManagedHandleTest, SimplePopulatedWithStorage) +{ + constexpr int expected = 3; + { + StoreHandle h(int{expected}, std::make_tuple(std::string{"str"}, 5)); + EXPECT_TRUE(h); + EXPECT_EQ(expected, *h); + EXPECT_EQ(expected, h.value()); + EXPECT_TRUE(dropped.empty()); + } + EXPECT_EQ(5, stored); + EXPECT_EQ(std::vector{expected}, dropped); + dropped.clear(); +} + +TEST_F(ManagedHandleTest, ResetPopulatedWithStorage) +{ + constexpr int expected = 3; + const std::string s{"str"}; + StoreHandle h(int{expected}, s, 5); + EXPECT_TRUE(dropped.empty()); + h.reset(std::nullopt); + EXPECT_FALSE(h); + EXPECT_THROW(h.value(), std::bad_optional_access); + EXPECT_EQ(5, stored); + EXPECT_EQ(std::vector{expected}, dropped); + dropped.clear(); +} + +TEST_F(ManagedHandleTest, ResetNewPopulated) +{ + constexpr int expected = 3, expected2 = 10; + { + SimpleHandle h(int{expected}); + EXPECT_TRUE(dropped.empty()); + h.reset(int{expected2}); + EXPECT_TRUE(h); + EXPECT_EQ(expected2, *h); + EXPECT_EQ(expected2, h.value()); + EXPECT_EQ(std::vector{expected}, dropped); + dropped.clear(); + } + EXPECT_EQ(std::vector{expected2}, dropped); + dropped.clear(); +} + +TEST_F(ManagedHandleTest, ResetNewPopulatedWithStorage) +{ + constexpr int expected = 3, expected2 = 10; + { + StoreHandle h(int{expected}, "str", 5); + EXPECT_TRUE(dropped.empty()); + h.reset(int{expected2}); + EXPECT_TRUE(h); + EXPECT_EQ(expected2, *h); + EXPECT_EQ(expected2, h.value()); + EXPECT_EQ(5, stored); + EXPECT_EQ(std::vector{expected}, dropped); + dropped.clear(); + } + EXPECT_EQ(6, stored); + EXPECT_EQ(std::vector{expected2}, dropped); + dropped.clear(); +} + +TEST_F(ManagedHandleTest, MoveConstructWithStorage) +{ + constexpr int expected = 3; + StoreHandle h1(int{expected}, "str", 5); + { + StoreHandle h2(std::move(h1)); + EXPECT_TRUE(dropped.empty()); + EXPECT_FALSE(h1); + EXPECT_THROW(h1.value(), std::bad_optional_access); + EXPECT_TRUE(h2); + EXPECT_EQ(expected, *h2); + EXPECT_EQ(expected, h2.value()); + } + EXPECT_EQ(5, stored); + EXPECT_EQ(std::vector{expected}, dropped); + dropped.clear(); +} + +TEST_F(ManagedHandleTest, MoveAssignWithStorage) +{ + constexpr int expected = 3, expected2 = 10; + { + StoreHandle h1(int{expected}, "str", 5); + StoreHandle h2(int{expected2}, "str", 10); + EXPECT_TRUE(dropped.empty()); + + h2 = std::move(h1); + EXPECT_EQ(10, stored); + EXPECT_EQ(std::vector{expected2}, dropped); + dropped.clear(); + EXPECT_FALSE(h1); + EXPECT_THROW(h1.value(), std::bad_optional_access); + EXPECT_TRUE(h2); + EXPECT_EQ(expected, *h2); + EXPECT_EQ(expected, h2.value()); + } + EXPECT_EQ(5, stored); + EXPECT_EQ(std::vector{expected}, dropped); + dropped.clear(); +} + +} // namespace +} // namespace stdplus diff --git a/test/meson.build b/test/meson.build index b918d5d..812de29 100644 --- a/test/meson.build +++ b/test/meson.build @@ -3,6 +3,7 @@ gmock = dependency('gmock', disabler: true, required: build_tests) tests = [ 'signal', + 'handle/managed', ] foreach t : tests |