summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorWilliam A. Kennington III <wak@google.com>2018-11-02 17:28:35 -0700
committerWilliam A. Kennington III <wak@google.com>2019-03-29 21:14:57 +0000
commit7a5e23259a696bf240a14200535680b42c445096 (patch)
tree9553542506b77601755b0f548c2fe48031198a62 /test
parent1937ef65b505b1d856c74074d6042bdb336728af (diff)
downloadstdplus-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.am5
-rw-r--r--test/handle/managed.cpp209
-rw-r--r--test/meson.build1
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
OpenPOWER on IntegriCloud