1 // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
2 
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #include <boost/leaf/detail/config.hpp>
7 #include <boost/leaf/detail/optional.hpp>
8 #include "lightweight_test.hpp"
9 
10 namespace leaf = boost::leaf;
11 
12 int object_count=0;
13 int value_count=0;
14 
15 class my_info
16 {
17     my_info & operator=( my_info const & ) = delete;
18 
19 public:
20 
21     int value;
22 
my_info(int value)23     explicit my_info( int value ):
24         value(value)
25     {
26         BOOST_TEST(++object_count>0);
27         BOOST_TEST(++value_count>0);
28     }
29 
my_info(my_info const & x)30     my_info( my_info const & x ):
31         value(x.value)
32     {
33         BOOST_TEST(++object_count>0);
34         BOOST_TEST(++value_count>0);
35     }
36 
my_info(my_info && x)37     my_info( my_info && x ):
38         value(x.value)
39     {
40         x.value=-1;
41         BOOST_TEST(++object_count>0);
42     }
~my_info()43     ~my_info()
44     {
45         BOOST_TEST(--object_count>=0);
46         if( value!=-1 )
47             BOOST_TEST(--value_count>=0);
48     }
49 };
50 
51 #ifndef BOOST_LEAF_NO_EXCEPTIONS
52 class throws_on_copy
53 {
54     throws_on_copy & operator=( throws_on_copy const & )=delete;
55 
56 public:
57 
58     int value;
59 
throws_on_copy()60     throws_on_copy()
61     {
62         BOOST_TEST(++object_count>0);
63     }
64 
throws_on_copy(throws_on_copy const &)65     throws_on_copy( throws_on_copy const & )
66     {
67         throw std::exception();
68     }
69 
throws_on_copy(throws_on_copy &&)70     throws_on_copy( throws_on_copy && )
71     {
72         BOOST_TEST(++object_count>0);
73     }
74 
~throws_on_copy()75     ~throws_on_copy()
76     {
77         BOOST_TEST(--object_count>=0);
78     }
79 };
80 #endif
81 
run_tests()82 void run_tests()
83 {
84     using leaf::leaf_detail::optional;
85     {
86         optional<my_info> x;
87         BOOST_TEST(x.empty());
88     }
89     BOOST_TEST(!object_count);
90     BOOST_TEST(!value_count);
91     {
92         my_info a(42);
93         BOOST_TEST_EQ(object_count, 1);
94         BOOST_TEST_EQ(value_count, 1);
95         optional<my_info> x(10, a);
96         BOOST_TEST_EQ(object_count, 2);
97         BOOST_TEST_EQ(value_count, 2);
98         BOOST_TEST(!x.empty());
99         BOOST_TEST(x.has_value(10));
100         BOOST_TEST(!x.has_value(11));
101         BOOST_TEST_EQ(x.value(10).value, 42);
102     }
103     BOOST_TEST(!object_count);
104     BOOST_TEST(!value_count);
105 #ifndef BOOST_LEAF_NO_EXCEPTIONS
106     {
107         throws_on_copy a;
108         BOOST_TEST_EQ(object_count, 1);
109         try
110         {
111             optional<throws_on_copy> x(10, a);
112             BOOST_TEST(false);
113         }
114         catch( std::exception & )
115         {
116         }
117     }
118 #endif
119     BOOST_TEST(!object_count);
120     BOOST_TEST(!value_count);
121     {
122         my_info a(42);
123         BOOST_TEST_EQ(object_count, 1);
124         BOOST_TEST_EQ(value_count, 1);
125         optional<my_info> x(10, std::move(a));
126         BOOST_TEST_EQ(object_count, 2);
127         BOOST_TEST_EQ(value_count, 1);
128         BOOST_TEST(!x.empty());
129         BOOST_TEST(x.has_value(10));
130         BOOST_TEST(!x.has_value(11));
131         BOOST_TEST_EQ(x.value(10).value, 42);
132     }
133     BOOST_TEST(!object_count);
134     BOOST_TEST(!value_count);
135     {
136         optional<my_info> x(10, my_info(42));
137         BOOST_TEST_EQ(object_count, 1);
138         BOOST_TEST_EQ(value_count, 1);
139         BOOST_TEST(!x.empty());
140         BOOST_TEST(x.has_value(10));
141         BOOST_TEST(!x.has_value(11));
142         BOOST_TEST_EQ(x.value(10).value, 42);
143         optional<my_info> y(x);
144         BOOST_TEST_EQ(object_count, 2);
145         BOOST_TEST_EQ(value_count, 2);
146         BOOST_TEST(!x.empty());
147         BOOST_TEST(x.has_value(10));
148         BOOST_TEST(!x.has_value(11));
149         BOOST_TEST_EQ(x.value(10).value, 42);
150         BOOST_TEST(!y.empty());
151         BOOST_TEST(y.has_value(10));
152         BOOST_TEST(!y.has_value(11));
153         BOOST_TEST_EQ(y.value(10).value, 42);
154     }
155     BOOST_TEST(!object_count);
156     BOOST_TEST(!value_count);
157     {
158         optional<my_info> x(10, my_info(42));
159         BOOST_TEST_EQ(object_count, 1);
160         BOOST_TEST_EQ(value_count, 1);
161         BOOST_TEST(!x.empty());
162         BOOST_TEST(x.has_value(10));
163         BOOST_TEST(!x.has_value(11));
164         BOOST_TEST_EQ(x.value(10).value, 42);
165         optional<my_info> y(std::move(x));
166         BOOST_TEST_EQ(object_count, 1);
167         BOOST_TEST_EQ(value_count, 1);
168         BOOST_TEST(x.empty());
169         BOOST_TEST(!x.has_value(10));
170         BOOST_TEST(!y.empty());
171         BOOST_TEST(y.has_value(10));
172         BOOST_TEST(!y.has_value(11));
173         BOOST_TEST_EQ(y.value(10).value, 42);
174     }
175     BOOST_TEST(!object_count);
176     BOOST_TEST(!value_count);
177     {
178         optional<my_info> x(10, my_info(42));
179         BOOST_TEST_EQ(object_count, 1);
180         BOOST_TEST_EQ(value_count, 1);
181         BOOST_TEST(!x.empty());
182         BOOST_TEST(x.has_value(10));
183         BOOST_TEST(!x.has_value(11));
184         BOOST_TEST_EQ(x.value(10).value, 42);
185         optional<my_info> y;
186         BOOST_TEST(y.empty());
187         BOOST_TEST_EQ(&(y=x), &y);
188         BOOST_TEST_EQ(object_count, 2);
189         BOOST_TEST_EQ(value_count, 2);
190         BOOST_TEST(!x.empty());
191         BOOST_TEST(x.has_value(10));
192         BOOST_TEST(!x.has_value(11));
193         BOOST_TEST_EQ(x.value(10).value, 42);
194         BOOST_TEST(!y.empty());
195         BOOST_TEST(y.has_value(10));
196         BOOST_TEST(!y.has_value(11));
197         BOOST_TEST_EQ(y.value(10).value, 42);
198     }
199     BOOST_TEST(!object_count);
200     BOOST_TEST(!value_count);
201     {
202         optional<my_info> x(10, my_info(42));
203         BOOST_TEST_EQ(object_count, 1);
204         BOOST_TEST_EQ(value_count, 1);
205         BOOST_TEST(!x.empty());
206         BOOST_TEST(x.has_value(10));
207         BOOST_TEST(!x.has_value(11));
208         BOOST_TEST_EQ(x.value(10).value, 42);
209         optional<my_info> y(11, my_info(43));
210         BOOST_TEST_EQ(object_count, 2);
211         BOOST_TEST_EQ(value_count, 2);
212         BOOST_TEST(!y.empty());
213         BOOST_TEST_EQ(&(y=x), &y);
214         BOOST_TEST_EQ(object_count, 2);
215         BOOST_TEST_EQ(value_count, 2);
216         BOOST_TEST(!x.empty());
217         BOOST_TEST(x.has_value(10));
218         BOOST_TEST(!x.has_value(11));
219         BOOST_TEST_EQ(x.value(10).value, 42);
220         BOOST_TEST(!y.empty());
221         BOOST_TEST(y.has_value(10));
222         BOOST_TEST(!y.has_value(11));
223         BOOST_TEST_EQ(y.value(10).value, 42);
224     }
225     BOOST_TEST(!object_count);
226     BOOST_TEST(!value_count);
227 #ifndef BOOST_LEAF_NO_EXCEPTIONS
228     {
229         optional<throws_on_copy> x(10, throws_on_copy());
230         BOOST_TEST_EQ(object_count, 1);
231         BOOST_TEST(!x.empty());
232         BOOST_TEST(x.has_value(10));
233         BOOST_TEST(!x.has_value(11));
234         optional<throws_on_copy> y;
235         try
236         {
237             (void) (y=x);
238         }
239         catch( std::exception & )
240         {
241         }
242         BOOST_TEST_EQ(object_count, 1);
243         BOOST_TEST(!x.empty());
244         BOOST_TEST(x.has_value(10));
245         BOOST_TEST(!x.has_value(11));
246         BOOST_TEST(y.empty());
247         BOOST_TEST(!y.has_value(10));
248     }
249 #endif
250     BOOST_TEST(!object_count);
251     BOOST_TEST(!value_count);
252     {
253         optional<my_info> x(10, my_info(42));
254         BOOST_TEST_EQ(object_count, 1);
255         BOOST_TEST_EQ(value_count, 1);
256         BOOST_TEST(!x.empty());
257         BOOST_TEST(x.has_value(10));
258         BOOST_TEST_EQ(x.value(10).value, 42);
259         optional<my_info> y;
260         BOOST_TEST_EQ(&(y=std::move(x)), &y);
261         BOOST_TEST_EQ(object_count, 1);
262         BOOST_TEST_EQ(value_count, 1);
263         BOOST_TEST(x.empty());
264         BOOST_TEST(!x.has_value(10));
265         BOOST_TEST(!y.empty());
266         BOOST_TEST(y.has_value(10));
267         BOOST_TEST(!y.has_value(11));
268         BOOST_TEST_EQ(y.value(10).value, 42);
269     }
270     BOOST_TEST(!object_count);
271     BOOST_TEST(!value_count);
272     {
273         optional<my_info> x(10, my_info(42));
274         BOOST_TEST_EQ(object_count, 1);
275         BOOST_TEST_EQ(value_count, 1);
276         BOOST_TEST(!x.empty());
277         BOOST_TEST(x.has_value(10));
278         BOOST_TEST(!x.has_value(11));
279         BOOST_TEST_EQ(x.value(10).value, 42);
280         optional<my_info> y(11, my_info(43));
281         BOOST_TEST_EQ(object_count, 2);
282         BOOST_TEST_EQ(value_count, 2);
283         BOOST_TEST(!y.empty());
284         BOOST_TEST_EQ(&(y=std::move(x)), &y);
285         BOOST_TEST_EQ(object_count, 1);
286         BOOST_TEST_EQ(value_count, 1);
287         BOOST_TEST(x.empty());
288         BOOST_TEST(!x.has_value(10));
289         BOOST_TEST(!y.empty());
290         BOOST_TEST(y.has_value(10));
291         BOOST_TEST(!y.has_value(11));
292         BOOST_TEST_EQ(y.value(10).value, 42);
293     }
294     BOOST_TEST(!object_count);
295     BOOST_TEST(!value_count);
296     {
297         optional<my_info> x;
298         my_info a(42);
299         x.put(10, a);
300         BOOST_TEST_EQ(object_count, 2);
301         BOOST_TEST_EQ(value_count, 2);
302         BOOST_TEST(!x.empty());
303         BOOST_TEST(x.has_value(10));
304         BOOST_TEST(!x.has_value(11));
305         BOOST_TEST_EQ(x.value(10).value, 42);
306     }
307     BOOST_TEST(!object_count);
308     BOOST_TEST(!value_count);
309     {
310         optional<my_info> x(10, my_info(43));
311         BOOST_TEST(!x.empty());
312         BOOST_TEST_EQ(object_count, 1);
313         BOOST_TEST_EQ(value_count, 1);
314         my_info a(42);
315         x.put(10, a);
316         BOOST_TEST_EQ(object_count, 2);
317         BOOST_TEST_EQ(value_count, 2);
318         BOOST_TEST(!x.empty());
319         BOOST_TEST(x.has_value(10));
320         BOOST_TEST(!x.has_value(11));
321         BOOST_TEST_EQ(x.value(10).value, 42);
322     }
323     BOOST_TEST(!object_count);
324     BOOST_TEST(!value_count);
325     {
326         optional<my_info> x;
327         BOOST_TEST(x.empty());
328         x.put(10, my_info(42));
329         BOOST_TEST_EQ(object_count, 1);
330         BOOST_TEST_EQ(value_count, 1);
331         BOOST_TEST(!x.empty());
332         BOOST_TEST(x.has_value(10));
333         BOOST_TEST(!x.has_value(11));
334         BOOST_TEST_EQ(x.value(10).value, 42);
335     }
336     BOOST_TEST(!object_count);
337     BOOST_TEST(!value_count);
338     {
339         optional<my_info> x(11, my_info(43));
340         BOOST_TEST(!x.empty());
341         BOOST_TEST_EQ(object_count, 1);
342         BOOST_TEST_EQ(value_count, 1);
343         x.put(10, my_info(42));
344         BOOST_TEST(!x.empty());
345         BOOST_TEST_EQ(object_count, 1);
346         BOOST_TEST_EQ(value_count, 1);
347         BOOST_TEST(x.has_value(10));
348         BOOST_TEST(!x.has_value(11));
349         BOOST_TEST_EQ(x.value(10).value, 42);
350     }
351     BOOST_TEST(!object_count);
352     BOOST_TEST(!value_count);
353     {
354         optional<my_info> x(10, my_info(42));
355         BOOST_TEST_EQ(object_count, 1);
356         BOOST_TEST_EQ(value_count, 1);
357         BOOST_TEST(!x.empty());
358         my_info a = std::move(x).value(10);
359         BOOST_TEST_EQ(object_count, 1);
360         BOOST_TEST_EQ(value_count, 1);
361         BOOST_TEST(x.empty());
362         BOOST_TEST(!x.has_value(10));
363         BOOST_TEST_EQ(a.value, 42);
364     }
365     BOOST_TEST(!object_count);
366     BOOST_TEST(!value_count);
367     {
368         optional<my_info> x(10, my_info(42));
369         BOOST_TEST_EQ(object_count, 1);
370         BOOST_TEST_EQ(value_count, 1);
371         BOOST_TEST(!x.empty());
372         BOOST_TEST(x.has_value(10));
373         BOOST_TEST(!x.has_value(11));
374         x.reset();
375         BOOST_TEST(x.empty());
376         BOOST_TEST(!x.has_value(10));
377     }
378     BOOST_TEST(!object_count);
379     BOOST_TEST(!value_count);
380 }
381 
main()382 int main()
383 {
384     run_tests();
385     return boost::report_errors();
386 }
387