blob: fffffdecefaee7e99516dd7ae0b84e01fca915ed [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
44class ManagedHandleTest : public ::testing::Test
45{
46 protected:
47 void SetUp()
48 {
49 dropped.clear();
50 }
51
52 void TearDown()
53 {
54 EXPECT_TRUE(dropped.empty());
55 }
56};
57
58TEST_F(ManagedHandleTest, EmptyNoStorage)
59{
William A. Kennington III7910ae02019-11-11 12:13:25 -080060 SimpleHandleOld h(std::nullopt);
William A. Kennington III7a5e2322018-11-02 17:28:35 -070061 EXPECT_FALSE(h);
62 EXPECT_THROW(h.value(), std::bad_optional_access);
William A. Kennington III079cba72019-07-01 17:28:32 -070063 EXPECT_THROW((void)h.release(), std::bad_optional_access);
William A. Kennington III7a5e2322018-11-02 17:28:35 -070064 h.reset();
65 EXPECT_FALSE(h.has_value());
66 EXPECT_THROW(h.value(), std::bad_optional_access);
William A. Kennington III079cba72019-07-01 17:28:32 -070067 EXPECT_THROW((void)h.release(), std::bad_optional_access);
William A. Kennington III7a5e2322018-11-02 17:28:35 -070068 EXPECT_EQ(std::nullopt, h.maybe_value());
William A. Kennington III079cba72019-07-01 17:28:32 -070069 EXPECT_EQ(std::nullopt, h.maybe_release());
William A. Kennington III7a5e2322018-11-02 17:28:35 -070070}
71
72TEST_F(ManagedHandleTest, EmptyWithStorage)
73{
74 StoreHandle h(std::nullopt, "str", 5);
75 EXPECT_FALSE(h);
76 EXPECT_THROW(h.value(), std::bad_optional_access);
77 h.reset(std::nullopt);
78 EXPECT_FALSE(h);
79 EXPECT_THROW(h.value(), std::bad_optional_access);
80
81 StoreHandle h2(std::nullopt, std::make_tuple<std::string, int>("str", 5));
82 EXPECT_FALSE(h2);
83 EXPECT_THROW(h2.value(), std::bad_optional_access);
84}
85
86TEST_F(ManagedHandleTest, SimplePopulated)
87{
88 constexpr int expected = 3;
89 {
90 int val = expected;
91 SimpleHandle h(std::move(val));
92 EXPECT_TRUE(h.has_value());
93 EXPECT_EQ(expected, *h);
94 EXPECT_EQ(expected, h.value());
95 EXPECT_EQ(expected, h.maybe_value());
96 EXPECT_TRUE(dropped.empty());
97 }
98 EXPECT_EQ(std::vector{expected}, dropped);
99 dropped.clear();
100}
101
102TEST_F(ManagedHandleTest, OptionalPopulated)
103{
104 constexpr int expected = 3;
105 {
106 std::optional<int> maybeVal{expected};
107 SimpleHandle h(std::move(maybeVal));
108 EXPECT_TRUE(h);
109 EXPECT_EQ(expected, *h);
110 EXPECT_EQ(expected, h.value());
111 EXPECT_TRUE(dropped.empty());
112 }
113 EXPECT_EQ(std::vector{expected}, dropped);
114 dropped.clear();
115}
116
117TEST_F(ManagedHandleTest, SimplePopulatedWithStorage)
118{
119 constexpr int expected = 3;
120 {
121 StoreHandle h(int{expected}, std::make_tuple(std::string{"str"}, 5));
122 EXPECT_TRUE(h);
123 EXPECT_EQ(expected, *h);
124 EXPECT_EQ(expected, h.value());
125 EXPECT_TRUE(dropped.empty());
126 }
127 EXPECT_EQ(5, stored);
128 EXPECT_EQ(std::vector{expected}, dropped);
129 dropped.clear();
130}
131
132TEST_F(ManagedHandleTest, ResetPopulatedWithStorage)
133{
134 constexpr int expected = 3;
135 const std::string s{"str"};
136 StoreHandle h(int{expected}, s, 5);
137 EXPECT_TRUE(dropped.empty());
138 h.reset(std::nullopt);
139 EXPECT_FALSE(h);
140 EXPECT_THROW(h.value(), std::bad_optional_access);
141 EXPECT_EQ(5, stored);
142 EXPECT_EQ(std::vector{expected}, dropped);
143 dropped.clear();
144}
145
146TEST_F(ManagedHandleTest, ResetNewPopulated)
147{
148 constexpr int expected = 3, expected2 = 10;
149 {
150 SimpleHandle h(int{expected});
151 EXPECT_TRUE(dropped.empty());
152 h.reset(int{expected2});
153 EXPECT_TRUE(h);
154 EXPECT_EQ(expected2, *h);
155 EXPECT_EQ(expected2, h.value());
156 EXPECT_EQ(std::vector{expected}, dropped);
157 dropped.clear();
158 }
159 EXPECT_EQ(std::vector{expected2}, dropped);
160 dropped.clear();
161}
162
163TEST_F(ManagedHandleTest, ResetNewPopulatedWithStorage)
164{
165 constexpr int expected = 3, expected2 = 10;
166 {
167 StoreHandle h(int{expected}, "str", 5);
168 EXPECT_TRUE(dropped.empty());
169 h.reset(int{expected2});
170 EXPECT_TRUE(h);
171 EXPECT_EQ(expected2, *h);
172 EXPECT_EQ(expected2, h.value());
173 EXPECT_EQ(5, stored);
174 EXPECT_EQ(std::vector{expected}, dropped);
175 dropped.clear();
176 }
177 EXPECT_EQ(6, stored);
178 EXPECT_EQ(std::vector{expected2}, dropped);
179 dropped.clear();
180}
181
William A. Kennington III079cba72019-07-01 17:28:32 -0700182TEST_F(ManagedHandleTest, Release)
183{
184 constexpr int expected = 3;
185 int val = expected;
186 SimpleHandle h(std::move(val));
187 EXPECT_EQ(expected, h.release());
188 EXPECT_FALSE(h);
189}
190
191TEST_F(ManagedHandleTest, MaybeRelease)
192{
193 constexpr int expected = 3;
194 int val = expected;
195 SimpleHandle h(std::move(val));
196 EXPECT_EQ(expected, h.maybe_release());
197 EXPECT_FALSE(h);
198}
199
William A. Kennington III7a5e2322018-11-02 17:28:35 -0700200TEST_F(ManagedHandleTest, MoveConstructWithStorage)
201{
202 constexpr int expected = 3;
203 StoreHandle h1(int{expected}, "str", 5);
204 {
205 StoreHandle h2(std::move(h1));
206 EXPECT_TRUE(dropped.empty());
207 EXPECT_FALSE(h1);
208 EXPECT_THROW(h1.value(), std::bad_optional_access);
209 EXPECT_TRUE(h2);
210 EXPECT_EQ(expected, *h2);
211 EXPECT_EQ(expected, h2.value());
212 }
213 EXPECT_EQ(5, stored);
214 EXPECT_EQ(std::vector{expected}, dropped);
215 dropped.clear();
216}
217
218TEST_F(ManagedHandleTest, MoveAssignWithStorage)
219{
220 constexpr int expected = 3, expected2 = 10;
221 {
222 StoreHandle h1(int{expected}, "str", 5);
223 StoreHandle h2(int{expected2}, "str", 10);
224 EXPECT_TRUE(dropped.empty());
225
226 h2 = std::move(h1);
227 EXPECT_EQ(10, stored);
228 EXPECT_EQ(std::vector{expected2}, dropped);
229 dropped.clear();
230 EXPECT_FALSE(h1);
231 EXPECT_THROW(h1.value(), std::bad_optional_access);
232 EXPECT_TRUE(h2);
233 EXPECT_EQ(expected, *h2);
234 EXPECT_EQ(expected, h2.value());
235 }
236 EXPECT_EQ(5, stored);
237 EXPECT_EQ(std::vector{expected}, dropped);
238 dropped.clear();
239}
240
241} // namespace
242} // namespace stdplus