blob: b55b216848db7e45a8f8643cc61dd3485b0f5b0f [file] [log] [blame]
William A. Kennington IIIe847ef82018-11-02 17:29:15 -07001#include <gtest/gtest.h>
2#include <optional>
3#include <stdplus/handle/copyable.hpp>
4#include <string>
5#include <utility>
6#include <vector>
7
8namespace stdplus
9{
10namespace
11{
12
13static std::vector<int> reffed;
14static int stored_ref = 0;
15static std::vector<int> dropped;
16static int stored_drop = 0;
17
William A. Kennington III7910ae02019-11-11 12:13:25 -080018struct SimpleRef
19{
20 int operator()(const int& i) noexcept
21 {
22 reffed.push_back(i);
23 return i + 1;
24 }
25};
26
William A. Kennington IIIe847ef82018-11-02 17:29:15 -070027int ref(const int& i)
28{
William A. Kennington III7910ae02019-11-11 12:13:25 -080029 return SimpleRef()(i);
William A. Kennington IIIe847ef82018-11-02 17:29:15 -070030}
31
William A. Kennington III7910ae02019-11-11 12:13:25 -080032struct SimpleDrop
33{
34 void operator()(int&& i) noexcept
35 {
36 dropped.push_back(std::move(i));
37 }
38};
39
William A. Kennington IIIe847ef82018-11-02 17:29:15 -070040void drop(int&& i)
41{
William A. Kennington III7910ae02019-11-11 12:13:25 -080042 SimpleDrop()(std::move(i));
William A. Kennington IIIe847ef82018-11-02 17:29:15 -070043}
44
William A. Kennington III7910ae02019-11-11 12:13:25 -080045struct StoreRef
William A. Kennington IIIe847ef82018-11-02 17:29:15 -070046{
William A. Kennington III7910ae02019-11-11 12:13:25 -080047 int operator()(const int& i, std::string&, int& si)
48 {
49 reffed.push_back(i);
50 // Make sure we can update the stored data
51 stored_ref = si++;
52 return i + 1;
53 }
54};
William A. Kennington IIIe847ef82018-11-02 17:29:15 -070055
William A. Kennington III7910ae02019-11-11 12:13:25 -080056struct StoreDrop
William A. Kennington IIIe847ef82018-11-02 17:29:15 -070057{
William A. Kennington III7910ae02019-11-11 12:13:25 -080058 void operator()(int&& i, std::string&, int& si)
59 {
60 dropped.push_back(std::move(i));
61 // Make sure we can update the stored data
62 stored_drop = si++;
63 }
64};
William A. Kennington IIIe847ef82018-11-02 17:29:15 -070065
William A. Kennington III7910ae02019-11-11 12:13:25 -080066using SimpleHandleOld = Copyable<int>::Handle<drop, ref>;
67using SimpleHandle = Copyable<int>::HandleF<SimpleDrop, SimpleRef>;
68using StoreHandle =
69 Copyable<int, std::string, int>::HandleF<StoreDrop, StoreRef>;
William A. Kennington IIIe847ef82018-11-02 17:29:15 -070070
71class CopyableHandleTest : public ::testing::Test
72{
73 protected:
74 void SetUp()
75 {
76 reffed.clear();
77 dropped.clear();
78 }
79
80 void TearDown()
81 {
82 EXPECT_TRUE(reffed.empty());
83 EXPECT_TRUE(dropped.empty());
84 }
85};
86
87TEST_F(CopyableHandleTest, EmptyNoStorage)
88{
William A. Kennington III7910ae02019-11-11 12:13:25 -080089 SimpleHandleOld h(std::nullopt);
William A. Kennington IIIe847ef82018-11-02 17:29:15 -070090 EXPECT_FALSE(h);
91 EXPECT_THROW(h.value(), std::bad_optional_access);
92 h.reset();
93 EXPECT_FALSE(h);
94 EXPECT_THROW(h.value(), std::bad_optional_access);
95}
96
97TEST_F(CopyableHandleTest, EmptyWithStorage)
98{
99 auto maybeV = std::nullopt;
100 StoreHandle h(maybeV, "str", 5);
101 EXPECT_FALSE(h);
102 EXPECT_THROW(h.value(), std::bad_optional_access);
103 h.reset(maybeV);
104 EXPECT_FALSE(h);
105 EXPECT_THROW(h.value(), std::bad_optional_access);
106}
107
108TEST_F(CopyableHandleTest, SimplePopulated)
109{
110 constexpr int expected = 3;
111 {
112 int val = expected;
113 SimpleHandle h(std::move(val));
114 EXPECT_TRUE(h);
115 EXPECT_EQ(expected, *h);
116 EXPECT_EQ(expected, h.value());
117 EXPECT_TRUE(dropped.empty());
118 }
119 EXPECT_EQ(std::vector{expected}, dropped);
120 dropped.clear();
121}
122
123TEST_F(CopyableHandleTest, OptionalPopulated)
124{
125 constexpr int expected = 3;
126 {
127 std::optional<int> maybeVal{expected};
128 SimpleHandle h(std::move(maybeVal));
129 EXPECT_TRUE(h);
130 EXPECT_EQ(expected, *h);
131 EXPECT_EQ(expected, h.value());
132 EXPECT_TRUE(dropped.empty());
133 }
134 EXPECT_TRUE(reffed.empty());
135 EXPECT_EQ(std::vector{expected}, dropped);
136 dropped.clear();
137 {
138 const std::optional<int> maybeVal{expected};
139 SimpleHandle h(maybeVal);
140 EXPECT_TRUE(h);
141 EXPECT_EQ(expected + 1, *h);
142 EXPECT_EQ(expected + 1, h.value());
143 EXPECT_EQ(std::vector{expected}, reffed);
144 reffed.clear();
145 EXPECT_TRUE(dropped.empty());
146 }
147 EXPECT_EQ(std::vector{expected + 1}, dropped);
148 dropped.clear();
149}
150
151TEST_F(CopyableHandleTest, SimplePopulatedWithStorage)
152{
153 constexpr int expected = 3;
154 {
155 StoreHandle h(expected, std::string{"str"}, 5);
156 EXPECT_TRUE(h);
157 EXPECT_EQ(expected + 1, *h);
158 EXPECT_EQ(expected + 1, h.value());
159 EXPECT_EQ(5, stored_ref);
160 EXPECT_EQ(std::vector{expected}, reffed);
161 reffed.clear();
162 EXPECT_TRUE(dropped.empty());
163 }
164 EXPECT_EQ(6, stored_drop);
165 EXPECT_EQ(std::vector{expected + 1}, dropped);
166 dropped.clear();
167}
168
169TEST_F(CopyableHandleTest, ResetPopulatedWithStorage)
170{
171 constexpr int expected = 3;
172 const std::string s{"str"};
173 StoreHandle h(int{expected}, s, 5);
174 EXPECT_TRUE(dropped.empty());
175 h.reset(std::nullopt);
176 EXPECT_FALSE(h);
177 EXPECT_THROW(h.value(), std::bad_optional_access);
178 EXPECT_EQ(5, stored_drop);
179 EXPECT_EQ(std::vector{expected}, dropped);
180 dropped.clear();
181}
182
183TEST_F(CopyableHandleTest, ResetNewPopulated)
184{
185 constexpr int expected = 3, expected2 = 10;
186 {
187 SimpleHandle h(int{expected});
188 EXPECT_TRUE(dropped.empty());
189 h.reset(int{expected2});
190 EXPECT_TRUE(h);
191 EXPECT_EQ(expected2, *h);
192 EXPECT_EQ(expected2, h.value());
193 EXPECT_EQ(std::vector{expected}, dropped);
194 dropped.clear();
195 }
196 EXPECT_EQ(std::vector{expected2}, dropped);
197 dropped.clear();
198}
199
200TEST_F(CopyableHandleTest, ResetCopyPopulated)
201{
202 constexpr int expected = 3, expected2 = 10;
203 {
204 SimpleHandle h(int{expected});
205 EXPECT_TRUE(reffed.empty());
206 EXPECT_TRUE(dropped.empty());
207 const std::optional<int> maybe2{expected2};
208 h.reset(maybe2);
209 EXPECT_TRUE(h);
210 EXPECT_EQ(expected2 + 1, *h);
211 EXPECT_EQ(expected2 + 1, h.value());
212 EXPECT_EQ(std::vector{expected2}, reffed);
213 reffed.clear();
214 EXPECT_EQ(std::vector{expected}, dropped);
215 dropped.clear();
216 }
217 EXPECT_EQ(std::vector{expected2 + 1}, dropped);
218 dropped.clear();
219}
220
221TEST_F(CopyableHandleTest, ResetCopyPopulatedWithStorage)
222{
223 constexpr int expected = 3, expected2 = 10;
224 {
225 StoreHandle h(int{expected}, "str", 5);
226 EXPECT_TRUE(dropped.empty());
227 h.reset(expected2);
228 EXPECT_TRUE(h);
229 EXPECT_EQ(expected2 + 1, *h);
230 EXPECT_EQ(expected2 + 1, h.value());
231 EXPECT_EQ(5, stored_ref);
232 EXPECT_EQ(std::vector{expected2}, reffed);
233 reffed.clear();
234 EXPECT_EQ(6, stored_drop);
235 EXPECT_EQ(std::vector{expected}, dropped);
236 dropped.clear();
237 }
238 EXPECT_EQ(7, stored_drop);
239 EXPECT_EQ(std::vector{expected2 + 1}, dropped);
240 dropped.clear();
241}
242
243TEST_F(CopyableHandleTest, MoveConstructWithStorage)
244{
245 constexpr int expected = 3;
246 StoreHandle h1(int{expected}, "str", 5);
247 {
248 StoreHandle h2(std::move(h1));
249 EXPECT_TRUE(dropped.empty());
250 EXPECT_FALSE(h1);
251 EXPECT_THROW(h1.value(), std::bad_optional_access);
252 EXPECT_TRUE(h2);
253 EXPECT_EQ(expected, *h2);
254 EXPECT_EQ(expected, h2.value());
255 }
256 EXPECT_EQ(5, stored_drop);
257 EXPECT_EQ(std::vector{expected}, dropped);
258 dropped.clear();
259}
260
261TEST_F(CopyableHandleTest, MoveAssignWithStorage)
262{
263 constexpr int expected = 3, expected2 = 10;
264 {
265 StoreHandle h1(int{expected}, "str", 5);
266 StoreHandle h2(int{expected2}, "str", 10);
267 EXPECT_TRUE(dropped.empty());
268
269 h2 = std::move(h1);
270 EXPECT_EQ(10, stored_drop);
271 EXPECT_EQ(std::vector{expected2}, dropped);
272 dropped.clear();
273 EXPECT_FALSE(h1);
274 EXPECT_THROW(h1.value(), std::bad_optional_access);
275 EXPECT_TRUE(h2);
276 EXPECT_EQ(expected, *h2);
277 EXPECT_EQ(expected, h2.value());
278 }
279 EXPECT_EQ(5, stored_drop);
280 EXPECT_EQ(std::vector{expected}, dropped);
281 dropped.clear();
282}
283
284TEST_F(CopyableHandleTest, CopyConstructSrcEmptyWithStorage)
285{
286 StoreHandle h1(std::nullopt, "str", 5);
287 StoreHandle h2(h1);
288}
289
290TEST_F(CopyableHandleTest, CopyConstructWithStorage)
291{
292 constexpr int expected = 3;
293 StoreHandle h1(int{expected}, "str", 5);
294 StoreHandle h2(h1);
295 EXPECT_EQ(5, stored_ref);
296 EXPECT_EQ(std::vector{expected}, reffed);
297 reffed.clear();
298
299 h1.reset();
300 EXPECT_EQ(5, stored_drop);
301 EXPECT_EQ(std::vector{expected}, dropped);
302 dropped.clear();
303 h2.reset();
304 EXPECT_EQ(6, stored_drop);
305 EXPECT_EQ(std::vector{expected + 1}, dropped);
306 dropped.clear();
307}
308
309TEST_F(CopyableHandleTest, CopyAssignBothEmptyWithStorage)
310{
311 StoreHandle h1(std::nullopt, "str", 5);
312 StoreHandle h2(std::nullopt, "str", 10);
313 h2 = h1;
314}
315
316TEST_F(CopyableHandleTest, CopyAssignSrcEmptyWithStorage)
317{
318 constexpr int expected = 3;
319 StoreHandle h1(std::nullopt, "str", 5);
320 StoreHandle h2(int{expected}, "str", 10);
321 h2 = h1;
322 EXPECT_EQ(10, stored_drop);
323 EXPECT_EQ(std::vector{expected}, dropped);
324 dropped.clear();
325}
326
327TEST_F(CopyableHandleTest, CopyAssignDstEmptyWithStorage)
328{
329 constexpr int expected = 3;
330 StoreHandle h1(int{expected}, "str", 5);
331 StoreHandle h2(std::nullopt, "str", 10);
332 h2 = h1;
333 EXPECT_EQ(5, stored_ref);
334 EXPECT_EQ(std::vector{expected}, reffed);
335 reffed.clear();
336
337 h1.reset();
338 EXPECT_EQ(5, stored_drop);
339 EXPECT_EQ(std::vector{expected}, dropped);
340 dropped.clear();
341 h2.reset();
342 EXPECT_EQ(6, stored_drop);
343 EXPECT_EQ(std::vector{expected + 1}, dropped);
344 dropped.clear();
345}
346
347TEST_F(CopyableHandleTest, CopyAssignWithStorage)
348{
349 constexpr int expected = 3, expected2 = 15;
350 StoreHandle h1(int{expected}, "str", 5);
351 StoreHandle h2(int{expected2}, "str", 10);
352 h2 = h1;
353 EXPECT_EQ(10, stored_drop);
354 EXPECT_EQ(std::vector{expected2}, dropped);
355 dropped.clear();
356 EXPECT_EQ(5, stored_ref);
357 EXPECT_EQ(std::vector{expected}, reffed);
358 reffed.clear();
359
360 h1.reset();
361 EXPECT_EQ(5, stored_drop);
362 EXPECT_EQ(std::vector{expected}, dropped);
363 dropped.clear();
364 h2.reset();
365 EXPECT_EQ(6, stored_drop);
366 EXPECT_EQ(std::vector{expected + 1}, dropped);
367 dropped.clear();
368}
369
370} // namespace
371} // namespace stdplus