1 //
2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 
8 // Test that header file is self-contained.
9 #include <boost/beast/core/detail/variant.hpp>
10 
11 #include <boost/beast/_experimental/unit_test/suite.hpp>
12 #include <exception>
13 #include <string>
14 
15 namespace boost {
16 namespace beast {
17 namespace detail {
18 
19 class variant_test : public beast::unit_test::suite
20 {
21 public:
22     template<unsigned char I>
23     struct Q
24     {
25         static
26         unsigned char&
countboost::beast::detail::variant_test::Q27         count()
28         {
29             static unsigned char n = 0;
30             return n;
31         }
32 
33         int value = 0;
34         bool move = false;
35         bool copy = false;
36 
37         Q& operator=(Q&& q) = delete;
38         Q& operator=(Q const& q) = delete;
39 
~Qboost::beast::detail::variant_test::Q40         ~Q()
41         {
42             --count();
43         }
44 
Qboost::beast::detail::variant_test::Q45         Q()
46         {
47             ++count();
48         }
49 
Qboost::beast::detail::variant_test::Q50         Q(Q&& q)
51         {
52             if(q.value < 0)
53                 throw std::exception{};
54             ++count();
55             move = true;
56         }
57 
Qboost::beast::detail::variant_test::Q58         Q(Q const& q)
59         {
60             if(q.value < 0)
61                 throw std::exception{};
62             ++count();
63             copy = true;
64         }
65 
Qboost::beast::detail::variant_test::Q66         explicit Q(int value_)
67             : value(value_)
68         {
69             ++count();
70         }
71     };
72 
73     void
testVariant()74     testVariant()
75     {
76         // Default Constructor
77         // Destructor
78         {
79             variant<int> v;
80             BEAST_EXPECT(v.index() == 0);
81         }
82         // emplace
83         {
84             variant<int> v;
85             BEAST_EXPECT(v.index() == 0);
86             v.emplace<1>(10);
87             BEAST_EXPECT(v.index() == 1);
88             BEAST_EXPECT(v.get<1>() == 10);
89             v.emplace<1>(20);
90             BEAST_EXPECT(v.index() == 1);
91             BEAST_EXPECT(v.get<1>() == 20);
92         }
93         {
94             variant<std::string> v;
95             v.emplace<1>("Hello, world!");
96             BEAST_EXPECT(v.index() == 1);
97             BEAST_EXPECT(v.get<1>() == "Hello, world!");
98         }
99         {
100             variant<Q<1>> v;
101             BEAST_EXPECT(Q<1>::count() == 0);
102             v.emplace<1>();
103             BEAST_EXPECT(Q<1>::count() == 1);
104             BEAST_EXPECT(v.get<1>().value == 0);
105             v.emplace<1>(42);
106             BEAST_EXPECT(Q<1>::count() == 1);
107             BEAST_EXPECT(v.get<1>().value == 42);
108             v.reset();
109             BEAST_EXPECT(Q<1>::count() == 0);
110         }
111         BEAST_EXPECT(Q<1>::count() == 0);
112         {
113             variant<Q<1>, Q<2>, Q<3>> v;
114             BEAST_EXPECT(Q<1>::count() == 0);
115             BEAST_EXPECT(Q<2>::count() == 0);
116             BEAST_EXPECT(Q<3>::count() == 0);
117             v.emplace<1>();
118             BEAST_EXPECT(Q<1>::count() == 1);
119             BEAST_EXPECT(Q<2>::count() == 0);
120             BEAST_EXPECT(Q<3>::count() == 0);
121             v.emplace<2>();
122             BEAST_EXPECT(Q<1>::count() == 0);
123             BEAST_EXPECT(Q<2>::count() == 1);
124             BEAST_EXPECT(Q<3>::count() == 0);
125             v.emplace<3>();
126             BEAST_EXPECT(Q<1>::count() == 0);
127             BEAST_EXPECT(Q<2>::count() == 0);
128             BEAST_EXPECT(Q<3>::count() == 1);
129             v.reset();
130             BEAST_EXPECT(Q<1>::count() == 0);
131             BEAST_EXPECT(Q<2>::count() == 0);
132             BEAST_EXPECT(Q<3>::count() == 0);
133         }
134         BEAST_EXPECT(Q<1>::count() == 0);
135         BEAST_EXPECT(Q<2>::count() == 0);
136         BEAST_EXPECT(Q<3>::count() == 0);
137         // move
138         {
139             variant<std::string> v1;
140             BEAST_EXPECT(v1.index() == 0);
141             variant<std::string> v2{std::move(v1)};
142             BEAST_EXPECT(v1.index() == 0);
143             BEAST_EXPECT(v2.index() == 0);
144             v2.emplace<1>("Hello");
145             BEAST_EXPECT(v2.get<1>() == "Hello");
146             variant<std::string> v3{std::move(v2)};
147             BEAST_EXPECT(v2.index() == 0);
148             BEAST_EXPECT(v3.get<1>() == "Hello");
149         }
150         {
151             variant<Q<1>> v1;
152             BEAST_EXPECT(Q<1>::count() == 0);
153             v1.emplace<1>();
154             BEAST_EXPECT(Q<1>::count() == 1);
155             BEAST_EXPECT(! v1.get<1>().move);
156             variant<Q<1>> v2{std::move(v1)};
157             BEAST_EXPECT(v1.index() == 0);
158             BEAST_EXPECT(Q<1>::count() == 1);
159             BEAST_EXPECT(v2.get<1>().move);
160         }
161         BEAST_EXPECT(Q<1>::count() == 0);
162         {
163             variant<Q<1>, Q<2>, Q<3>> v1;
164             BEAST_EXPECT(Q<1>::count() == 0);
165             BEAST_EXPECT(Q<2>::count() == 0);
166             BEAST_EXPECT(Q<3>::count() == 0);
167             v1.emplace<2>();
168             BEAST_EXPECT(Q<1>::count() == 0);
169             BEAST_EXPECT(Q<2>::count() == 1);
170             BEAST_EXPECT(Q<3>::count() == 0);
171             variant<Q<1>, Q<2>, Q<3>> v2{std::move(v1)};
172             BEAST_EXPECT(Q<1>::count() == 0);
173             BEAST_EXPECT(Q<2>::count() == 1);
174             BEAST_EXPECT(Q<3>::count() == 0);
175             BEAST_EXPECT(v2.get<2>().move);
176         }
177         BEAST_EXPECT(Q<1>::count() == 0);
178         BEAST_EXPECT(Q<2>::count() == 0);
179         BEAST_EXPECT(Q<3>::count() == 0);
180         // copy
181         {
182             variant<std::string> v1;
183             BEAST_EXPECT(v1.index() == 0);
184             variant<std::string> v2{v1};
185             BEAST_EXPECT(v1.index() == 0);
186             BEAST_EXPECT(v2.index() == 0);
187             v2.emplace<1>("Hello");
188             BEAST_EXPECT(v2.get<1>() == "Hello");
189             variant<std::string> v3{v2};
190             BEAST_EXPECT(v2.get<1>() == "Hello");
191             BEAST_EXPECT(v3.get<1>() == "Hello");
192         }
193         {
194             variant<Q<1>> v1;
195             BEAST_EXPECT(Q<1>::count() == 0);
196             v1.emplace<1>();
197             BEAST_EXPECT(Q<1>::count() == 1);
198             BEAST_EXPECT(! v1.get<1>().copy);
199             variant<Q<1>> v2{v1};
200             BEAST_EXPECT(v1.index() == 1);
201             BEAST_EXPECT(Q<1>::count() == 2);
202             BEAST_EXPECT(v2.get<1>().copy);
203         }
204         BEAST_EXPECT(Q<1>::count() == 0);
205         {
206             variant<Q<1>, Q<2>, Q<3>> v1;
207             BEAST_EXPECT(Q<1>::count() == 0);
208             BEAST_EXPECT(Q<2>::count() == 0);
209             BEAST_EXPECT(Q<3>::count() == 0);
210             v1.emplace<2>();
211             BEAST_EXPECT(Q<1>::count() == 0);
212             BEAST_EXPECT(Q<2>::count() == 1);
213             BEAST_EXPECT(Q<3>::count() == 0);
214             variant<Q<1>, Q<2>, Q<3>> v2{v1};
215             BEAST_EXPECT(Q<1>::count() == 0);
216             BEAST_EXPECT(Q<2>::count() == 2);
217             BEAST_EXPECT(Q<3>::count() == 0);
218             BEAST_EXPECT(v2.get<2>().copy);
219         }
220         BEAST_EXPECT(Q<1>::count() == 0);
221         BEAST_EXPECT(Q<2>::count() == 0);
222         BEAST_EXPECT(Q<3>::count() == 0);
223         // move assign
224         {
225             variant<std::string> v1;
226             BEAST_EXPECT(v1.index() == 0);
227             variant<std::string> v2;
228             v2 = std::move(v1);
229             BEAST_EXPECT(v1.index() == 0);
230             BEAST_EXPECT(v2.index() == 0);
231             v2.emplace<1>("Hello");
232             BEAST_EXPECT(v2.get<1>() == "Hello");
233             variant<std::string> v3;
234             v3 = std::move(v2);
235             BEAST_EXPECT(v2.index() == 0);
236             BEAST_EXPECT(v3.get<1>() == "Hello");
237         }
238         {
239             variant<Q<1>, Q<2>> v1;
240             variant<Q<1>, Q<2>> v2;
241             v1.emplace<1>();
242             BEAST_EXPECT(v1.index() == 1);
243             BEAST_EXPECT(Q<1>::count() == 1);
244             v2.emplace<2>();
245             BEAST_EXPECT(v2.index() == 2);
246             BEAST_EXPECT(Q<2>::count() == 1);
247             v2 = std::move(v1);
248             BEAST_EXPECT(v1.index() == 0);
249             BEAST_EXPECT(v2.index() == 1);
250             BEAST_EXPECT(Q<1>::count() == 1);
251             BEAST_EXPECT(Q<2>::count() == 0);
252         }
253         BEAST_EXPECT(Q<1>::count() == 0);
254         BEAST_EXPECT(Q<2>::count() == 0);
255         {
256             variant<Q<1>> v1;
257             v1.emplace<1>();
258             BEAST_EXPECT(Q<1>::count() == 1);
259             variant<Q<1>> v2;
260             v2.emplace<1>();
261             BEAST_EXPECT(Q<1>::count() == 2);
262             v2 = std::move(v1);
263             BEAST_EXPECT(v1.index() == 0);
264             BEAST_EXPECT(v2.index() == 1);
265             BEAST_EXPECT(v2.get<1>().move);
266             BEAST_EXPECT(Q<1>::count() == 1);
267         }
268         BEAST_EXPECT(Q<1>::count() == 0);
269         {
270             variant<Q<1>, Q<2>, Q<3>> v1;
271             v1.emplace<2>();
272             BEAST_EXPECT(Q<1>::count() == 0);
273             BEAST_EXPECT(Q<2>::count() == 1);
274             BEAST_EXPECT(Q<3>::count() == 0);
275             variant<Q<1>, Q<2>, Q<3>> v2;
276             v2.emplace<2>();
277             BEAST_EXPECT(Q<1>::count() == 0);
278             BEAST_EXPECT(Q<2>::count() == 2);
279             BEAST_EXPECT(Q<3>::count() == 0);
280             v2 = std::move(v1);
281             BEAST_EXPECT(v1.index() == 0);
282             BEAST_EXPECT(v2.index() == 2);
283             BEAST_EXPECT(v2.get<2>().move);
284             BEAST_EXPECT(Q<1>::count() == 0);
285             BEAST_EXPECT(Q<2>::count() == 1);
286             BEAST_EXPECT(Q<3>::count() == 0);
287         }
288         BEAST_EXPECT(Q<1>::count() == 0);
289         BEAST_EXPECT(Q<2>::count() == 0);
290         BEAST_EXPECT(Q<3>::count() == 0);
291         // copy assign
292         {
293             variant<std::string> v1;
294             BEAST_EXPECT(v1.index() == 0);
295             variant<std::string> v2;
296             v2 = v1;
297             BEAST_EXPECT(v1.index() == 0);
298             BEAST_EXPECT(v2.index() == 0);
299             v2.emplace<1>("Hello");
300             BEAST_EXPECT(v2.get<1>() == "Hello");
301             variant<std::string> v3;
302             v3 = v2;
303             BEAST_EXPECT(v2.get<1>() == "Hello");
304             BEAST_EXPECT(v3.get<1>() == "Hello");
305         }
306         {
307             variant<Q<1>, Q<2>> v1;
308             variant<Q<1>, Q<2>> v2;
309             v1.emplace<1>();
310             BEAST_EXPECT(v1.index() == 1);
311             BEAST_EXPECT(Q<1>::count() == 1);
312             v2.emplace<2>();
313             BEAST_EXPECT(v2.index() == 2);
314             BEAST_EXPECT(Q<2>::count() == 1);
315             v2 = v1;
316             BEAST_EXPECT(v1.index() == 1);
317             BEAST_EXPECT(v2.index() == 1);
318             BEAST_EXPECT(Q<1>::count() == 2);
319             BEAST_EXPECT(Q<2>::count() == 0);
320         }
321         {
322             variant<Q<1>> v1;
323             v1.emplace<1>();
324             BEAST_EXPECT(Q<1>::count() == 1);
325             variant<Q<1>> v2;
326             v2.emplace<1>();
327             BEAST_EXPECT(Q<1>::count() == 2);
328             v2 = v1;
329             BEAST_EXPECT(v1.index() == 1);
330             BEAST_EXPECT(v2.index() == 1);
331             BEAST_EXPECT(v2.get<1>().copy);
332             BEAST_EXPECT(Q<1>::count() == 2);
333         }
334         BEAST_EXPECT(Q<1>::count() == 0);
335         {
336             variant<Q<1>, Q<2>, Q<3>> v1;
337             v1.emplace<2>();
338             BEAST_EXPECT(Q<1>::count() == 0);
339             BEAST_EXPECT(Q<2>::count() == 1);
340             BEAST_EXPECT(Q<3>::count() == 0);
341             variant<Q<1>, Q<2>, Q<3>> v2;
342             v2.emplace<2>();
343             BEAST_EXPECT(Q<1>::count() == 0);
344             BEAST_EXPECT(Q<2>::count() == 2);
345             BEAST_EXPECT(Q<3>::count() == 0);
346             v2 = v1;
347             BEAST_EXPECT(v1.index() == 2);
348             BEAST_EXPECT(v2.index() == 2);
349             BEAST_EXPECT(v2.get<2>().copy);
350             BEAST_EXPECT(Q<1>::count() == 0);
351             BEAST_EXPECT(Q<2>::count() == 2);
352             BEAST_EXPECT(Q<3>::count() == 0);
353         }
354         BEAST_EXPECT(Q<1>::count() == 0);
355         BEAST_EXPECT(Q<2>::count() == 0);
356         BEAST_EXPECT(Q<3>::count() == 0);
357         // get
358         {
359             variant<std::string> v;
360             v.emplace<1>("Hello");
361             v.get<1>() = "World!";
362             BEAST_EXPECT(v.get<1>() == "World!");
363         }
364         // reset
365         {
366             variant<std::string> v;
367             v.emplace<1>("Hello");
368             v.reset();
369             BEAST_EXPECT(v.index() == 0);
370         }
371         {
372             variant<Q<1>> v;
373             BEAST_EXPECT(Q<1>::count() == 0);
374             v.emplace<1>();
375             BEAST_EXPECT(Q<1>::count() == 1);
376             v.reset();
377             BEAST_EXPECT(Q<1>::count() == 0);
378             BEAST_EXPECT(v.index() == 0);
379         }
380         {
381             variant<Q<1>, Q<2>, Q<3>> v;
382             BEAST_EXPECT(Q<1>::count() == 0);
383             BEAST_EXPECT(Q<2>::count() == 0);
384             BEAST_EXPECT(Q<3>::count() == 0);
385             v.emplace<2>();
386             BEAST_EXPECT(Q<1>::count() == 0);
387             BEAST_EXPECT(Q<2>::count() == 1);
388             BEAST_EXPECT(Q<3>::count() == 0);
389             v.reset();
390             BEAST_EXPECT(Q<1>::count() == 0);
391             BEAST_EXPECT(Q<2>::count() == 0);
392             BEAST_EXPECT(Q<3>::count() == 0);
393             BEAST_EXPECT(v.index() == 0);
394         }
395         BEAST_EXPECT(Q<1>::count() == 0);
396         BEAST_EXPECT(Q<2>::count() == 0);
397         BEAST_EXPECT(Q<3>::count() == 0);
398 
399         // basic guarantee
400         {
401             // move
402             variant<Q<1>> v1;
403             v1.emplace<1>();
404             BEAST_EXPECT(Q<1>::count() == 1);
405             variant<Q<1>> v2;
406             v2.emplace<1>(-1);
407             BEAST_EXPECT(Q<1>::count() == 2);
408             try
409             {
410                 v1 = std::move(v2);
411                 fail();
412             }
413             catch(std::exception const&)
414             {
415                 BEAST_EXPECT(v1.index() == 0);
416                 BEAST_EXPECT(Q<1>::count() == 1);
417             }
418         }
419         BEAST_EXPECT(Q<1>::count() == 0);
420         {
421             // copy
422             variant<Q<1>> v1;
423             v1.emplace<1>();
424             BEAST_EXPECT(Q<1>::count() == 1);
425             variant<Q<1>> v2;
426             v2.emplace<1>(-1);
427             BEAST_EXPECT(Q<1>::count() == 2);
428             try
429             {
430                 v1 = v2;
431                 fail();
432             }
433             catch(std::exception const&)
434             {
435                 BEAST_EXPECT(v1.index() == 0);
436                 BEAST_EXPECT(Q<1>::count() == 1);
437             }
438         }
439         BEAST_EXPECT(Q<1>::count() == 0);
440     }
441 
442     void
run()443     run()
444     {
445         testVariant();
446     }
447 };
448 
449 BEAST_DEFINE_TESTSUITE(beast,core,variant);
450 
451 } // detail
452 } // beast
453 } // boost
454