blob: 6ce210f059e550d8f2baa591ed56662e9d76c363 [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
18int ref(const int& i)
19{
20 reffed.push_back(i);
21 return i + 1;
22}
23
24void drop(int&& i)
25{
26 dropped.push_back(std::move(i));
27}
28
29int ref(const int& i, std::string&, int& si)
30{
31 reffed.push_back(i);
32 // Make sure we can update the stored data
33 stored_ref = si++;
34 return i + 1;
35}
36
37void drop(int&& i, std::string&, int& si)
38{
39 dropped.push_back(std::move(i));
40 // Make sure we can update the stored data
41 stored_drop = si++;
42}
43
44using SimpleHandle = Copyable<int>::Handle<drop, ref>;
45using StoreHandle = Copyable<int, std::string, int>::Handle<drop, ref>;
46
47class CopyableHandleTest : public ::testing::Test
48{
49 protected:
50 void SetUp()
51 {
52 reffed.clear();
53 dropped.clear();
54 }
55
56 void TearDown()
57 {
58 EXPECT_TRUE(reffed.empty());
59 EXPECT_TRUE(dropped.empty());
60 }
61};
62
63TEST_F(CopyableHandleTest, EmptyNoStorage)
64{
65 SimpleHandle h(std::nullopt);
66 EXPECT_FALSE(h);
67 EXPECT_THROW(h.value(), std::bad_optional_access);
68 h.reset();
69 EXPECT_FALSE(h);
70 EXPECT_THROW(h.value(), std::bad_optional_access);
71}
72
73TEST_F(CopyableHandleTest, EmptyWithStorage)
74{
75 auto maybeV = std::nullopt;
76 StoreHandle h(maybeV, "str", 5);
77 EXPECT_FALSE(h);
78 EXPECT_THROW(h.value(), std::bad_optional_access);
79 h.reset(maybeV);
80 EXPECT_FALSE(h);
81 EXPECT_THROW(h.value(), std::bad_optional_access);
82}
83
84TEST_F(CopyableHandleTest, SimplePopulated)
85{
86 constexpr int expected = 3;
87 {
88 int val = expected;
89 SimpleHandle h(std::move(val));
90 EXPECT_TRUE(h);
91 EXPECT_EQ(expected, *h);
92 EXPECT_EQ(expected, h.value());
93 EXPECT_TRUE(dropped.empty());
94 }
95 EXPECT_EQ(std::vector{expected}, dropped);
96 dropped.clear();
97}
98
99TEST_F(CopyableHandleTest, OptionalPopulated)
100{
101 constexpr int expected = 3;
102 {
103 std::optional<int> maybeVal{expected};
104 SimpleHandle h(std::move(maybeVal));
105 EXPECT_TRUE(h);
106 EXPECT_EQ(expected, *h);
107 EXPECT_EQ(expected, h.value());
108 EXPECT_TRUE(dropped.empty());
109 }
110 EXPECT_TRUE(reffed.empty());
111 EXPECT_EQ(std::vector{expected}, dropped);
112 dropped.clear();
113 {
114 const std::optional<int> maybeVal{expected};
115 SimpleHandle h(maybeVal);
116 EXPECT_TRUE(h);
117 EXPECT_EQ(expected + 1, *h);
118 EXPECT_EQ(expected + 1, h.value());
119 EXPECT_EQ(std::vector{expected}, reffed);
120 reffed.clear();
121 EXPECT_TRUE(dropped.empty());
122 }
123 EXPECT_EQ(std::vector{expected + 1}, dropped);
124 dropped.clear();
125}
126
127TEST_F(CopyableHandleTest, SimplePopulatedWithStorage)
128{
129 constexpr int expected = 3;
130 {
131 StoreHandle h(expected, std::string{"str"}, 5);
132 EXPECT_TRUE(h);
133 EXPECT_EQ(expected + 1, *h);
134 EXPECT_EQ(expected + 1, h.value());
135 EXPECT_EQ(5, stored_ref);
136 EXPECT_EQ(std::vector{expected}, reffed);
137 reffed.clear();
138 EXPECT_TRUE(dropped.empty());
139 }
140 EXPECT_EQ(6, stored_drop);
141 EXPECT_EQ(std::vector{expected + 1}, dropped);
142 dropped.clear();
143}
144
145TEST_F(CopyableHandleTest, ResetPopulatedWithStorage)
146{
147 constexpr int expected = 3;
148 const std::string s{"str"};
149 StoreHandle h(int{expected}, s, 5);
150 EXPECT_TRUE(dropped.empty());
151 h.reset(std::nullopt);
152 EXPECT_FALSE(h);
153 EXPECT_THROW(h.value(), std::bad_optional_access);
154 EXPECT_EQ(5, stored_drop);
155 EXPECT_EQ(std::vector{expected}, dropped);
156 dropped.clear();
157}
158
159TEST_F(CopyableHandleTest, ResetNewPopulated)
160{
161 constexpr int expected = 3, expected2 = 10;
162 {
163 SimpleHandle h(int{expected});
164 EXPECT_TRUE(dropped.empty());
165 h.reset(int{expected2});
166 EXPECT_TRUE(h);
167 EXPECT_EQ(expected2, *h);
168 EXPECT_EQ(expected2, h.value());
169 EXPECT_EQ(std::vector{expected}, dropped);
170 dropped.clear();
171 }
172 EXPECT_EQ(std::vector{expected2}, dropped);
173 dropped.clear();
174}
175
176TEST_F(CopyableHandleTest, ResetCopyPopulated)
177{
178 constexpr int expected = 3, expected2 = 10;
179 {
180 SimpleHandle h(int{expected});
181 EXPECT_TRUE(reffed.empty());
182 EXPECT_TRUE(dropped.empty());
183 const std::optional<int> maybe2{expected2};
184 h.reset(maybe2);
185 EXPECT_TRUE(h);
186 EXPECT_EQ(expected2 + 1, *h);
187 EXPECT_EQ(expected2 + 1, h.value());
188 EXPECT_EQ(std::vector{expected2}, reffed);
189 reffed.clear();
190 EXPECT_EQ(std::vector{expected}, dropped);
191 dropped.clear();
192 }
193 EXPECT_EQ(std::vector{expected2 + 1}, dropped);
194 dropped.clear();
195}
196
197TEST_F(CopyableHandleTest, ResetCopyPopulatedWithStorage)
198{
199 constexpr int expected = 3, expected2 = 10;
200 {
201 StoreHandle h(int{expected}, "str", 5);
202 EXPECT_TRUE(dropped.empty());
203 h.reset(expected2);
204 EXPECT_TRUE(h);
205 EXPECT_EQ(expected2 + 1, *h);
206 EXPECT_EQ(expected2 + 1, h.value());
207 EXPECT_EQ(5, stored_ref);
208 EXPECT_EQ(std::vector{expected2}, reffed);
209 reffed.clear();
210 EXPECT_EQ(6, stored_drop);
211 EXPECT_EQ(std::vector{expected}, dropped);
212 dropped.clear();
213 }
214 EXPECT_EQ(7, stored_drop);
215 EXPECT_EQ(std::vector{expected2 + 1}, dropped);
216 dropped.clear();
217}
218
219TEST_F(CopyableHandleTest, MoveConstructWithStorage)
220{
221 constexpr int expected = 3;
222 StoreHandle h1(int{expected}, "str", 5);
223 {
224 StoreHandle h2(std::move(h1));
225 EXPECT_TRUE(dropped.empty());
226 EXPECT_FALSE(h1);
227 EXPECT_THROW(h1.value(), std::bad_optional_access);
228 EXPECT_TRUE(h2);
229 EXPECT_EQ(expected, *h2);
230 EXPECT_EQ(expected, h2.value());
231 }
232 EXPECT_EQ(5, stored_drop);
233 EXPECT_EQ(std::vector{expected}, dropped);
234 dropped.clear();
235}
236
237TEST_F(CopyableHandleTest, MoveAssignWithStorage)
238{
239 constexpr int expected = 3, expected2 = 10;
240 {
241 StoreHandle h1(int{expected}, "str", 5);
242 StoreHandle h2(int{expected2}, "str", 10);
243 EXPECT_TRUE(dropped.empty());
244
245 h2 = std::move(h1);
246 EXPECT_EQ(10, stored_drop);
247 EXPECT_EQ(std::vector{expected2}, dropped);
248 dropped.clear();
249 EXPECT_FALSE(h1);
250 EXPECT_THROW(h1.value(), std::bad_optional_access);
251 EXPECT_TRUE(h2);
252 EXPECT_EQ(expected, *h2);
253 EXPECT_EQ(expected, h2.value());
254 }
255 EXPECT_EQ(5, stored_drop);
256 EXPECT_EQ(std::vector{expected}, dropped);
257 dropped.clear();
258}
259
260TEST_F(CopyableHandleTest, CopyConstructSrcEmptyWithStorage)
261{
262 StoreHandle h1(std::nullopt, "str", 5);
263 StoreHandle h2(h1);
264}
265
266TEST_F(CopyableHandleTest, CopyConstructWithStorage)
267{
268 constexpr int expected = 3;
269 StoreHandle h1(int{expected}, "str", 5);
270 StoreHandle h2(h1);
271 EXPECT_EQ(5, stored_ref);
272 EXPECT_EQ(std::vector{expected}, reffed);
273 reffed.clear();
274
275 h1.reset();
276 EXPECT_EQ(5, stored_drop);
277 EXPECT_EQ(std::vector{expected}, dropped);
278 dropped.clear();
279 h2.reset();
280 EXPECT_EQ(6, stored_drop);
281 EXPECT_EQ(std::vector{expected + 1}, dropped);
282 dropped.clear();
283}
284
285TEST_F(CopyableHandleTest, CopyAssignBothEmptyWithStorage)
286{
287 StoreHandle h1(std::nullopt, "str", 5);
288 StoreHandle h2(std::nullopt, "str", 10);
289 h2 = h1;
290}
291
292TEST_F(CopyableHandleTest, CopyAssignSrcEmptyWithStorage)
293{
294 constexpr int expected = 3;
295 StoreHandle h1(std::nullopt, "str", 5);
296 StoreHandle h2(int{expected}, "str", 10);
297 h2 = h1;
298 EXPECT_EQ(10, stored_drop);
299 EXPECT_EQ(std::vector{expected}, dropped);
300 dropped.clear();
301}
302
303TEST_F(CopyableHandleTest, CopyAssignDstEmptyWithStorage)
304{
305 constexpr int expected = 3;
306 StoreHandle h1(int{expected}, "str", 5);
307 StoreHandle h2(std::nullopt, "str", 10);
308 h2 = h1;
309 EXPECT_EQ(5, stored_ref);
310 EXPECT_EQ(std::vector{expected}, reffed);
311 reffed.clear();
312
313 h1.reset();
314 EXPECT_EQ(5, stored_drop);
315 EXPECT_EQ(std::vector{expected}, dropped);
316 dropped.clear();
317 h2.reset();
318 EXPECT_EQ(6, stored_drop);
319 EXPECT_EQ(std::vector{expected + 1}, dropped);
320 dropped.clear();
321}
322
323TEST_F(CopyableHandleTest, CopyAssignWithStorage)
324{
325 constexpr int expected = 3, expected2 = 15;
326 StoreHandle h1(int{expected}, "str", 5);
327 StoreHandle h2(int{expected2}, "str", 10);
328 h2 = h1;
329 EXPECT_EQ(10, stored_drop);
330 EXPECT_EQ(std::vector{expected2}, dropped);
331 dropped.clear();
332 EXPECT_EQ(5, stored_ref);
333 EXPECT_EQ(std::vector{expected}, reffed);
334 reffed.clear();
335
336 h1.reset();
337 EXPECT_EQ(5, stored_drop);
338 EXPECT_EQ(std::vector{expected}, dropped);
339 dropped.clear();
340 h2.reset();
341 EXPECT_EQ(6, stored_drop);
342 EXPECT_EQ(std::vector{expected + 1}, dropped);
343 dropped.clear();
344}
345
346} // namespace
347} // namespace stdplus