blob: fb89195c31eca451978cf636ab5772cecae33a48 [file] [log] [blame]
William A. Kennington III7a5e2322018-11-02 17:28:35 -07001#include <gtest/gtest.h>
2#include <optional>
3#include <stdplus/handle/managed.hpp>
4#include <string>
5#include <tuple>
6#include <utility>
7#include <vector>
8
9namespace stdplus
10{
11namespace
12{
13
14static std::vector<int> dropped;
15static int stored = 0;
16
William A. Kennington III7910ae02019-11-11 12:13:25 -080017struct SimpleDrop
18{
19 void operator()(int&& i) noexcept
20 {
21 dropped.push_back(std::move(i));
22 }
23};
24
William A. Kennington III7a5e2322018-11-02 17:28:35 -070025void drop(int&& i)
26{
William A. Kennington III7910ae02019-11-11 12:13:25 -080027 SimpleDrop()(std::move(i));
William A. Kennington III7a5e2322018-11-02 17:28:35 -070028}
29
William A. Kennington III7910ae02019-11-11 12:13:25 -080030struct StoreDrop
William A. Kennington III7a5e2322018-11-02 17:28:35 -070031{
William A. Kennington III7910ae02019-11-11 12:13:25 -080032 void operator()(int&& i, std::string&, int& si)
33 {
34 dropped.push_back(std::move(i));
35 // Make sure we can update the stored data
36 stored = si++;
37 }
38};
William A. Kennington III7a5e2322018-11-02 17:28:35 -070039
William A. Kennington III7910ae02019-11-11 12:13:25 -080040using SimpleHandleOld = Managed<int>::Handle<drop>;
41using SimpleHandle = Managed<int>::HandleF<SimpleDrop>;
42using StoreHandle = Managed<int, std::string, int>::HandleF<StoreDrop>;
William A. Kennington III7a5e2322018-11-02 17:28:35 -070043
William A. Kennington III1007be92019-11-11 12:18:37 -080044static_assert(std::is_nothrow_move_constructible_v<SimpleHandle>);
45static_assert(std::is_nothrow_move_assignable_v<SimpleHandle>);
46static_assert(std::is_nothrow_destructible_v<SimpleHandle>);
47static_assert(noexcept(std::declval<SimpleHandle>().reset()));
48// http://cplusplus.github.io/LWG/lwg-active.html#2116
49// static_assert(std::is_nothrow_move_constructible_v<StoreHandle>);
50static_assert(!std::is_nothrow_move_assignable_v<StoreHandle>);
51static_assert(!std::is_nothrow_destructible_v<StoreHandle>);
52static_assert(!noexcept(std::declval<StoreHandle>().reset()));
53
William A. Kennington III7a5e2322018-11-02 17:28:35 -070054class ManagedHandleTest : public ::testing::Test
55{
56 protected:
57 void SetUp()
58 {
59 dropped.clear();
60 }
61
62 void TearDown()
63 {
64 EXPECT_TRUE(dropped.empty());
65 }
66};
67
68TEST_F(ManagedHandleTest, EmptyNoStorage)
69{
William A. Kennington III7910ae02019-11-11 12:13:25 -080070 SimpleHandleOld h(std::nullopt);
William A. Kennington III7a5e2322018-11-02 17:28:35 -070071 EXPECT_FALSE(h);
72 EXPECT_THROW(h.value(), std::bad_optional_access);
William A. Kennington III079cba72019-07-01 17:28:32 -070073 EXPECT_THROW((void)h.release(), std::bad_optional_access);
William A. Kennington III7a5e2322018-11-02 17:28:35 -070074 h.reset();
75 EXPECT_FALSE(h.has_value());
76 EXPECT_THROW(h.value(), std::bad_optional_access);
William A. Kennington III079cba72019-07-01 17:28:32 -070077 EXPECT_THROW((void)h.release(), std::bad_optional_access);
William A. Kennington III7a5e2322018-11-02 17:28:35 -070078 EXPECT_EQ(std::nullopt, h.maybe_value());
William A. Kennington III079cba72019-07-01 17:28:32 -070079 EXPECT_EQ(std::nullopt, h.maybe_release());
William A. Kennington III7a5e2322018-11-02 17:28:35 -070080}
81
82TEST_F(ManagedHandleTest, EmptyWithStorage)
83{
84 StoreHandle h(std::nullopt, "str", 5);
85 EXPECT_FALSE(h);
86 EXPECT_THROW(h.value(), std::bad_optional_access);
87 h.reset(std::nullopt);
88 EXPECT_FALSE(h);
89 EXPECT_THROW(h.value(), std::bad_optional_access);
90
91 StoreHandle h2(std::nullopt, std::make_tuple<std::string, int>("str", 5));
92 EXPECT_FALSE(h2);
93 EXPECT_THROW(h2.value(), std::bad_optional_access);
94}
95
96TEST_F(ManagedHandleTest, SimplePopulated)
97{
98 constexpr int expected = 3;
99 {
100 int val = expected;
101 SimpleHandle h(std::move(val));
102 EXPECT_TRUE(h.has_value());
103 EXPECT_EQ(expected, *h);
104 EXPECT_EQ(expected, h.value());
105 EXPECT_EQ(expected, h.maybe_value());
106 EXPECT_TRUE(dropped.empty());
107 }
108 EXPECT_EQ(std::vector{expected}, dropped);
109 dropped.clear();
110}
111
112TEST_F(ManagedHandleTest, OptionalPopulated)
113{
114 constexpr int expected = 3;
115 {
116 std::optional<int> maybeVal{expected};
117 SimpleHandle h(std::move(maybeVal));
118 EXPECT_TRUE(h);
119 EXPECT_EQ(expected, *h);
120 EXPECT_EQ(expected, h.value());
121 EXPECT_TRUE(dropped.empty());
122 }
123 EXPECT_EQ(std::vector{expected}, dropped);
124 dropped.clear();
125}
126
127TEST_F(ManagedHandleTest, SimplePopulatedWithStorage)
128{
129 constexpr int expected = 3;
130 {
131 StoreHandle h(int{expected}, std::make_tuple(std::string{"str"}, 5));
132 EXPECT_TRUE(h);
133 EXPECT_EQ(expected, *h);
134 EXPECT_EQ(expected, h.value());
135 EXPECT_TRUE(dropped.empty());
136 }
137 EXPECT_EQ(5, stored);
138 EXPECT_EQ(std::vector{expected}, dropped);
139 dropped.clear();
140}
141
142TEST_F(ManagedHandleTest, ResetPopulatedWithStorage)
143{
144 constexpr int expected = 3;
145 const std::string s{"str"};
146 StoreHandle h(int{expected}, s, 5);
147 EXPECT_TRUE(dropped.empty());
148 h.reset(std::nullopt);
149 EXPECT_FALSE(h);
150 EXPECT_THROW(h.value(), std::bad_optional_access);
151 EXPECT_EQ(5, stored);
152 EXPECT_EQ(std::vector{expected}, dropped);
153 dropped.clear();
154}
155
156TEST_F(ManagedHandleTest, ResetNewPopulated)
157{
158 constexpr int expected = 3, expected2 = 10;
159 {
160 SimpleHandle h(int{expected});
161 EXPECT_TRUE(dropped.empty());
162 h.reset(int{expected2});
163 EXPECT_TRUE(h);
164 EXPECT_EQ(expected2, *h);
165 EXPECT_EQ(expected2, h.value());
166 EXPECT_EQ(std::vector{expected}, dropped);
167 dropped.clear();
168 }
169 EXPECT_EQ(std::vector{expected2}, dropped);
170 dropped.clear();
171}
172
173TEST_F(ManagedHandleTest, ResetNewPopulatedWithStorage)
174{
175 constexpr int expected = 3, expected2 = 10;
176 {
177 StoreHandle h(int{expected}, "str", 5);
178 EXPECT_TRUE(dropped.empty());
179 h.reset(int{expected2});
180 EXPECT_TRUE(h);
181 EXPECT_EQ(expected2, *h);
182 EXPECT_EQ(expected2, h.value());
183 EXPECT_EQ(5, stored);
184 EXPECT_EQ(std::vector{expected}, dropped);
185 dropped.clear();
186 }
187 EXPECT_EQ(6, stored);
188 EXPECT_EQ(std::vector{expected2}, dropped);
189 dropped.clear();
190}
191
William A. Kennington III079cba72019-07-01 17:28:32 -0700192TEST_F(ManagedHandleTest, Release)
193{
194 constexpr int expected = 3;
195 int val = expected;
196 SimpleHandle h(std::move(val));
197 EXPECT_EQ(expected, h.release());
198 EXPECT_FALSE(h);
199}
200
201TEST_F(ManagedHandleTest, MaybeRelease)
202{
203 constexpr int expected = 3;
204 int val = expected;
205 SimpleHandle h(std::move(val));
206 EXPECT_EQ(expected, h.maybe_release());
207 EXPECT_FALSE(h);
208}
209
William A. Kennington III7a5e2322018-11-02 17:28:35 -0700210TEST_F(ManagedHandleTest, MoveConstructWithStorage)
211{
212 constexpr int expected = 3;
213 StoreHandle h1(int{expected}, "str", 5);
214 {
215 StoreHandle h2(std::move(h1));
216 EXPECT_TRUE(dropped.empty());
217 EXPECT_FALSE(h1);
218 EXPECT_THROW(h1.value(), std::bad_optional_access);
219 EXPECT_TRUE(h2);
220 EXPECT_EQ(expected, *h2);
221 EXPECT_EQ(expected, h2.value());
222 }
223 EXPECT_EQ(5, stored);
224 EXPECT_EQ(std::vector{expected}, dropped);
225 dropped.clear();
226}
227
228TEST_F(ManagedHandleTest, MoveAssignWithStorage)
229{
230 constexpr int expected = 3, expected2 = 10;
231 {
232 StoreHandle h1(int{expected}, "str", 5);
233 StoreHandle h2(int{expected2}, "str", 10);
234 EXPECT_TRUE(dropped.empty());
235
236 h2 = std::move(h1);
237 EXPECT_EQ(10, stored);
238 EXPECT_EQ(std::vector{expected2}, dropped);
239 dropped.clear();
240 EXPECT_FALSE(h1);
241 EXPECT_THROW(h1.value(), std::bad_optional_access);
242 EXPECT_TRUE(h2);
243 EXPECT_EQ(expected, *h2);
244 EXPECT_EQ(expected, h2.value());
245 }
246 EXPECT_EQ(5, stored);
247 EXPECT_EQ(std::vector{expected}, dropped);
248 dropped.clear();
249}
250
251} // namespace
252} // namespace stdplus