1 | // Copyright 2017, 2021 Peter Dimov. |
2 | // Distributed under the Boost Software License, Version 1.0. |
3 | // https://www.boost.org/LICENSE_1_0.txt |
4 | |
5 | #include <boost/system/result.hpp> |
6 | #include <boost/core/lightweight_test.hpp> |
7 | #include <boost/core/lightweight_test_trait.hpp> |
8 | #include <iosfwd> |
9 | #include <cerrno> |
10 | |
11 | using namespace boost::system; |
12 | |
13 | struct X |
14 | { |
15 | static int instances; |
16 | |
17 | int v_; |
18 | |
19 | explicit X( int v = 0 ): v_( v ) { ++instances; } |
20 | |
21 | X( X const& r ) = delete; |
22 | X( X&& r ): v_( r.v_ ) { r.v_ = 0; ++instances; } |
23 | |
24 | X& operator=( X const& ) = delete; |
25 | |
26 | X& operator=( X&& r ) |
27 | { |
28 | v_ = r.v_; |
29 | r.v_ = 0; |
30 | |
31 | return *this; |
32 | } |
33 | |
34 | ~X() { --instances; } |
35 | }; |
36 | |
37 | bool operator==( X const & x1, X const & x2 ) |
38 | { |
39 | return x1.v_ == x2.v_; |
40 | } |
41 | |
42 | std::ostream& operator<<( std::ostream& os, X const & x ) |
43 | { |
44 | os << "X:" << x.v_; |
45 | return os; |
46 | } |
47 | |
48 | int X::instances = 0; |
49 | |
50 | struct Y |
51 | { |
52 | static int instances; |
53 | |
54 | int v_; |
55 | |
56 | explicit Y( int v = 0 ): v_( v ) { ++instances; } |
57 | |
58 | Y( Y const& r ) noexcept: v_( r.v_ ) { ++instances; } |
59 | Y( Y&& r ) noexcept: v_( r.v_ ) { r.v_ = 0; ++instances; } |
60 | |
61 | Y& operator=( Y const& ) = default; |
62 | |
63 | Y& operator=( Y&& r ) |
64 | { |
65 | v_ = r.v_; |
66 | r.v_ = 0; |
67 | |
68 | return *this; |
69 | } |
70 | |
71 | ~Y() { --instances; } |
72 | }; |
73 | |
74 | bool operator==( Y const & y1, Y const & y2 ) |
75 | { |
76 | return y1.v_ == y2.v_; |
77 | } |
78 | |
79 | std::ostream& operator<<( std::ostream& os, Y const & y ) |
80 | { |
81 | os << "Y:" << y.v_; |
82 | return os; |
83 | } |
84 | |
85 | int Y::instances = 0; |
86 | |
87 | int main() |
88 | { |
89 | // default-initialized lhs |
90 | |
91 | { |
92 | result<int> r; |
93 | result<int> r2; |
94 | |
95 | r2 = std::move( r ); |
96 | |
97 | BOOST_TEST( r2.has_value() ); |
98 | BOOST_TEST( !r2.has_error() ); |
99 | |
100 | BOOST_TEST_EQ( r2.value(), 0 ); |
101 | } |
102 | |
103 | { |
104 | result<int> r2; |
105 | |
106 | r2 = result<int>(); |
107 | |
108 | BOOST_TEST( r2.has_value() ); |
109 | BOOST_TEST( !r2.has_error() ); |
110 | |
111 | BOOST_TEST_EQ( r2.value(), 0 ); |
112 | } |
113 | |
114 | { |
115 | result<int> r; |
116 | result<int> r2( 1 ); |
117 | |
118 | r2 = std::move( r ); |
119 | |
120 | BOOST_TEST( r2.has_value() ); |
121 | BOOST_TEST( !r2.has_error() ); |
122 | |
123 | BOOST_TEST_EQ( r2.value(), 0 ); |
124 | } |
125 | |
126 | { |
127 | result<int> r2( 1 ); |
128 | |
129 | r2 = result<int>(); |
130 | |
131 | BOOST_TEST( r2.has_value() ); |
132 | BOOST_TEST( !r2.has_error() ); |
133 | |
134 | BOOST_TEST_EQ( r2.value(), 0 ); |
135 | } |
136 | |
137 | { |
138 | result<int> r; |
139 | result<int> r2( ENOENT, generic_category() ); |
140 | |
141 | r2 = std::move( r ); |
142 | |
143 | BOOST_TEST( r2.has_value() ); |
144 | BOOST_TEST( !r2.has_error() ); |
145 | |
146 | BOOST_TEST_EQ( r2.value(), 0 ); |
147 | } |
148 | |
149 | { |
150 | result<int> r2( ENOENT, generic_category() ); |
151 | |
152 | r2 = result<int>(); |
153 | |
154 | BOOST_TEST( r2.has_value() ); |
155 | BOOST_TEST( !r2.has_error() ); |
156 | |
157 | BOOST_TEST_EQ( r2.value(), 0 ); |
158 | } |
159 | |
160 | BOOST_TEST_EQ( X::instances, 0 ); |
161 | |
162 | { |
163 | result<X> r; |
164 | result<X> r2; |
165 | |
166 | BOOST_TEST_EQ( X::instances, 2 ); |
167 | |
168 | r2 = std::move( r ); |
169 | |
170 | BOOST_TEST_EQ( X::instances, 2 ); |
171 | |
172 | BOOST_TEST( r2.has_value() ); |
173 | BOOST_TEST( !r2.has_error() ); |
174 | |
175 | BOOST_TEST_EQ( r2.value(), X() ); |
176 | } |
177 | |
178 | BOOST_TEST_EQ( X::instances, 0 ); |
179 | |
180 | { |
181 | result<X> r; |
182 | result<X> r2( 1 ); |
183 | |
184 | BOOST_TEST_EQ( X::instances, 2 ); |
185 | |
186 | r2 = std::move( r ); |
187 | |
188 | BOOST_TEST_EQ( X::instances, 2 ); |
189 | |
190 | BOOST_TEST( r2.has_value() ); |
191 | BOOST_TEST( !r2.has_error() ); |
192 | |
193 | BOOST_TEST_EQ( r2.value(), X() ); |
194 | } |
195 | |
196 | BOOST_TEST_EQ( X::instances, 0 ); |
197 | |
198 | { |
199 | result<X> r; |
200 | result<X> r2( ENOENT, generic_category() ); |
201 | |
202 | BOOST_TEST_EQ( X::instances, 1 ); |
203 | |
204 | r2 = std::move( r ); |
205 | |
206 | BOOST_TEST_EQ( X::instances, 2 ); |
207 | |
208 | BOOST_TEST( r2.has_value() ); |
209 | BOOST_TEST( !r2.has_error() ); |
210 | |
211 | BOOST_TEST_EQ( r2.value(), X() ); |
212 | } |
213 | |
214 | BOOST_TEST_EQ( X::instances, 0 ); |
215 | |
216 | // value lhs |
217 | |
218 | { |
219 | result<int> r( 1 ); |
220 | result<int> r2; |
221 | |
222 | r2 = std::move( r ); |
223 | |
224 | BOOST_TEST( r2.has_value() ); |
225 | BOOST_TEST( !r2.has_error() ); |
226 | |
227 | BOOST_TEST_EQ( r2.value(), 1 ); |
228 | |
229 | BOOST_TEST_EQ( r, r2 ); |
230 | } |
231 | |
232 | { |
233 | result<int> r( 1 ); |
234 | result<int> r2( 2 ); |
235 | |
236 | r2 = std::move( r ); |
237 | |
238 | BOOST_TEST( r2.has_value() ); |
239 | BOOST_TEST( !r2.has_error() ); |
240 | |
241 | BOOST_TEST_EQ( r2.value(), 1 ); |
242 | |
243 | BOOST_TEST_EQ( r, r2 ); |
244 | } |
245 | |
246 | { |
247 | result<int> r( 1 ); |
248 | result<int> r2( ENOENT, generic_category() ); |
249 | |
250 | r2 = std::move( r ); |
251 | |
252 | BOOST_TEST( r2.has_value() ); |
253 | BOOST_TEST( !r2.has_error() ); |
254 | |
255 | BOOST_TEST_EQ( r2.value(), 1 ); |
256 | |
257 | BOOST_TEST_EQ( r, r2 ); |
258 | } |
259 | |
260 | BOOST_TEST_EQ( X::instances, 0 ); |
261 | |
262 | { |
263 | result<X> r( 1 ); |
264 | result<X> r2; |
265 | |
266 | BOOST_TEST_EQ( X::instances, 2 ); |
267 | |
268 | r2 = std::move( r ); |
269 | |
270 | BOOST_TEST_EQ( X::instances, 2 ); |
271 | |
272 | BOOST_TEST( r2.has_value() ); |
273 | BOOST_TEST( !r2.has_error() ); |
274 | |
275 | BOOST_TEST_EQ( r2.value().v_, 1 ); |
276 | |
277 | BOOST_TEST_EQ( r.value().v_, 0 ); |
278 | } |
279 | |
280 | BOOST_TEST_EQ( X::instances, 0 ); |
281 | |
282 | { |
283 | result<X> r( 1 ); |
284 | result<X> r2( 2 ); |
285 | |
286 | BOOST_TEST_EQ( X::instances, 2 ); |
287 | |
288 | r2 = std::move( r ); |
289 | |
290 | BOOST_TEST_EQ( X::instances, 2 ); |
291 | |
292 | BOOST_TEST( r2.has_value() ); |
293 | BOOST_TEST( !r2.has_error() ); |
294 | |
295 | BOOST_TEST_EQ( r2.value().v_, 1 ); |
296 | |
297 | BOOST_TEST_EQ( r.value().v_, 0 ); |
298 | } |
299 | |
300 | BOOST_TEST_EQ( X::instances, 0 ); |
301 | |
302 | { |
303 | result<X> r( 1 ); |
304 | result<X> r2( ENOENT, generic_category() ); |
305 | |
306 | BOOST_TEST_EQ( X::instances, 1 ); |
307 | |
308 | r2 = std::move( r ); |
309 | |
310 | BOOST_TEST_EQ( X::instances, 2 ); |
311 | |
312 | BOOST_TEST( r2.has_value() ); |
313 | BOOST_TEST( !r2.has_error() ); |
314 | |
315 | BOOST_TEST_EQ( r2.value().v_, 1 ); |
316 | |
317 | BOOST_TEST_EQ( r.value().v_, 0 ); |
318 | } |
319 | |
320 | BOOST_TEST_EQ( X::instances, 0 ); |
321 | |
322 | // error lhs |
323 | |
324 | { |
325 | auto ec = make_error_code( e: errc::invalid_argument ); |
326 | |
327 | result<int> r( ec ); |
328 | result<int> r2; |
329 | |
330 | r2 = std::move( r ); |
331 | |
332 | BOOST_TEST( !r2.has_value() ); |
333 | BOOST_TEST( r2.has_error() ); |
334 | |
335 | BOOST_TEST_EQ( r2.error(), ec ); |
336 | } |
337 | |
338 | { |
339 | auto ec = make_error_code( e: errc::invalid_argument ); |
340 | |
341 | result<int> r2; |
342 | |
343 | r2 = result<int>( ec ); |
344 | |
345 | BOOST_TEST( !r2.has_value() ); |
346 | BOOST_TEST( r2.has_error() ); |
347 | |
348 | BOOST_TEST_EQ( r2.error(), ec ); |
349 | } |
350 | |
351 | { |
352 | auto ec = make_error_code( e: errc::invalid_argument ); |
353 | |
354 | result<int> r( ec ); |
355 | result<int> r2( 1 ); |
356 | |
357 | r2 = std::move( r ); |
358 | |
359 | BOOST_TEST( !r2.has_value() ); |
360 | BOOST_TEST( r2.has_error() ); |
361 | |
362 | BOOST_TEST_EQ( r2.error(), ec ); |
363 | } |
364 | |
365 | { |
366 | auto ec = make_error_code( e: errc::invalid_argument ); |
367 | |
368 | result<int> r2( 1 ); |
369 | |
370 | r2 = result<int>( ec ); |
371 | |
372 | BOOST_TEST( !r2.has_value() ); |
373 | BOOST_TEST( r2.has_error() ); |
374 | |
375 | BOOST_TEST_EQ( r2.error(), ec ); |
376 | } |
377 | |
378 | { |
379 | auto ec = make_error_code( e: errc::invalid_argument ); |
380 | |
381 | result<int> r( ec ); |
382 | result<int> r2( ENOENT, generic_category() ); |
383 | |
384 | r2 = std::move( r ); |
385 | |
386 | BOOST_TEST( !r2.has_value() ); |
387 | BOOST_TEST( r2.has_error() ); |
388 | |
389 | BOOST_TEST_EQ( r2.error(), ec ); |
390 | } |
391 | |
392 | { |
393 | auto ec = make_error_code( e: errc::invalid_argument ); |
394 | |
395 | result<int> r2( ENOENT, generic_category() ); |
396 | |
397 | r2 = result<int>( ec ); |
398 | |
399 | BOOST_TEST( !r2.has_value() ); |
400 | BOOST_TEST( r2.has_error() ); |
401 | |
402 | BOOST_TEST_EQ( r2.error(), ec ); |
403 | } |
404 | |
405 | BOOST_TEST_EQ( X::instances, 0 ); |
406 | |
407 | { |
408 | auto ec = make_error_code( e: errc::invalid_argument ); |
409 | |
410 | result<X> r( ec ); |
411 | result<X> r2; |
412 | |
413 | BOOST_TEST_EQ( X::instances, 1 ); |
414 | |
415 | r2 = std::move( r ); |
416 | |
417 | BOOST_TEST_EQ( X::instances, 0 ); |
418 | |
419 | BOOST_TEST( !r2.has_value() ); |
420 | BOOST_TEST( r2.has_error() ); |
421 | |
422 | BOOST_TEST_EQ( r2.error(), ec ); |
423 | } |
424 | |
425 | BOOST_TEST_EQ( X::instances, 0 ); |
426 | |
427 | { |
428 | auto ec = make_error_code( e: errc::invalid_argument ); |
429 | |
430 | result<X> r( ec ); |
431 | result<X> r2( 1 ); |
432 | |
433 | BOOST_TEST_EQ( X::instances, 1 ); |
434 | |
435 | r2 = std::move( r ); |
436 | |
437 | BOOST_TEST_EQ( X::instances, 0 ); |
438 | |
439 | BOOST_TEST( !r2.has_value() ); |
440 | BOOST_TEST( r2.has_error() ); |
441 | |
442 | BOOST_TEST_EQ( r2.error(), ec ); |
443 | } |
444 | |
445 | BOOST_TEST_EQ( X::instances, 0 ); |
446 | |
447 | { |
448 | auto ec = make_error_code( e: errc::invalid_argument ); |
449 | |
450 | result<X> r( ec ); |
451 | result<X> r2( ENOENT, generic_category() ); |
452 | |
453 | BOOST_TEST_EQ( X::instances, 0 ); |
454 | |
455 | r2 = std::move( r ); |
456 | |
457 | BOOST_TEST_EQ( X::instances, 0 ); |
458 | |
459 | BOOST_TEST( !r2.has_value() ); |
460 | BOOST_TEST( r2.has_error() ); |
461 | |
462 | BOOST_TEST_EQ( r2.error(), ec ); |
463 | } |
464 | |
465 | BOOST_TEST_EQ( X::instances, 0 ); |
466 | |
467 | // |
468 | |
469 | BOOST_TEST_EQ( Y::instances, 0 ); |
470 | |
471 | { |
472 | result<std::string, Y> r( 1 ); |
473 | result<std::string, Y> r2( 2 ); |
474 | |
475 | BOOST_TEST_EQ( Y::instances, 2 ); |
476 | |
477 | r2 = std::move( r ); |
478 | |
479 | BOOST_TEST_EQ( Y::instances, 2 ); |
480 | |
481 | BOOST_TEST( !r2.has_value() ); |
482 | BOOST_TEST( r2.has_error() ); |
483 | |
484 | BOOST_TEST_EQ( r2.error().v_, 1 ); |
485 | |
486 | BOOST_TEST_EQ( r.error().v_, 0 ); |
487 | } |
488 | |
489 | BOOST_TEST_EQ( Y::instances, 0 ); |
490 | |
491 | { |
492 | result<std::string, Y> r( 1 ); |
493 | result<std::string, Y> r2( "str" ); |
494 | |
495 | BOOST_TEST_EQ( Y::instances, 1 ); |
496 | |
497 | r2 = std::move( r ); |
498 | |
499 | BOOST_TEST_EQ( Y::instances, 2 ); |
500 | |
501 | BOOST_TEST( !r2.has_value() ); |
502 | BOOST_TEST( r2.has_error() ); |
503 | |
504 | BOOST_TEST_EQ( r2.error().v_, 1 ); |
505 | |
506 | BOOST_TEST_EQ( r.error().v_, 0 ); |
507 | } |
508 | |
509 | BOOST_TEST_EQ( Y::instances, 0 ); |
510 | |
511 | // |
512 | |
513 | { |
514 | result<void> r; |
515 | result<void> r2; |
516 | |
517 | r2 = std::move( r ); |
518 | |
519 | BOOST_TEST( r2.has_value() ); |
520 | BOOST_TEST( !r2.has_error() ); |
521 | } |
522 | |
523 | { |
524 | result<void> r2; |
525 | |
526 | r2 = result<void>(); |
527 | |
528 | BOOST_TEST( r2.has_value() ); |
529 | BOOST_TEST( !r2.has_error() ); |
530 | } |
531 | |
532 | { |
533 | result<void> r; |
534 | result<void> r2( ENOENT, generic_category() ); |
535 | |
536 | r2 = std::move( r ); |
537 | |
538 | BOOST_TEST( r2.has_value() ); |
539 | BOOST_TEST( !r2.has_error() ); |
540 | } |
541 | |
542 | { |
543 | result<void> r2( ENOENT, generic_category() ); |
544 | |
545 | r2 = result<void>(); |
546 | |
547 | BOOST_TEST( r2.has_value() ); |
548 | BOOST_TEST( !r2.has_error() ); |
549 | } |
550 | |
551 | { |
552 | auto ec = make_error_code( e: errc::invalid_argument ); |
553 | |
554 | result<void> r( ec ); |
555 | result<void> r2; |
556 | |
557 | r2 = std::move( r ); |
558 | |
559 | BOOST_TEST( !r2.has_value() ); |
560 | BOOST_TEST( r2.has_error() ); |
561 | |
562 | BOOST_TEST_EQ( r2.error(), ec ); |
563 | } |
564 | |
565 | { |
566 | auto ec = make_error_code( e: errc::invalid_argument ); |
567 | |
568 | result<void> r2; |
569 | |
570 | r2 = result<void>( ec ); |
571 | |
572 | BOOST_TEST( !r2.has_value() ); |
573 | BOOST_TEST( r2.has_error() ); |
574 | |
575 | BOOST_TEST_EQ( r2.error(), ec ); |
576 | } |
577 | |
578 | { |
579 | auto ec = make_error_code( e: errc::invalid_argument ); |
580 | |
581 | result<void> r( ec ); |
582 | result<void> r2( ENOENT, generic_category() ); |
583 | |
584 | r2 = std::move( r ); |
585 | |
586 | BOOST_TEST( !r2.has_value() ); |
587 | BOOST_TEST( r2.has_error() ); |
588 | |
589 | BOOST_TEST_EQ( r2.error(), ec ); |
590 | } |
591 | |
592 | { |
593 | auto ec = make_error_code( e: errc::invalid_argument ); |
594 | |
595 | result<void> r2( ENOENT, generic_category() ); |
596 | |
597 | r2 = result<void>( ec ); |
598 | |
599 | BOOST_TEST( !r2.has_value() ); |
600 | BOOST_TEST( r2.has_error() ); |
601 | |
602 | BOOST_TEST_EQ( r2.error(), ec ); |
603 | } |
604 | |
605 | // |
606 | |
607 | { |
608 | int x1 = 1; |
609 | int x2 = 2; |
610 | |
611 | result<int&> r1( x1 ); |
612 | result<int&> r2( x2 ); |
613 | |
614 | r2 = std::move( r1 ); |
615 | |
616 | BOOST_TEST_EQ( x1, 1 ); |
617 | BOOST_TEST_EQ( x2, 2 ); |
618 | |
619 | BOOST_TEST( r2.has_value() ); |
620 | BOOST_TEST( !r2.has_error() ); |
621 | |
622 | BOOST_TEST_EQ( r2.value(), 1 ); |
623 | |
624 | BOOST_TEST_EQ( r1, r2 ); |
625 | BOOST_TEST_EQ( &*r1, &*r2 ); |
626 | } |
627 | |
628 | { |
629 | int x1 = 1; |
630 | |
631 | result<int&> r1( x1 ); |
632 | result<int&> r2( ENOENT, generic_category() ); |
633 | |
634 | r2 = std::move( r1 ); |
635 | |
636 | BOOST_TEST_EQ( x1, 1 ); |
637 | |
638 | BOOST_TEST( r2.has_value() ); |
639 | BOOST_TEST( !r2.has_error() ); |
640 | |
641 | BOOST_TEST_EQ( r2.value(), 1 ); |
642 | |
643 | BOOST_TEST_EQ( r1, r2 ); |
644 | } |
645 | |
646 | { |
647 | int x1 = 1; |
648 | |
649 | auto ec = make_error_code( e: errc::invalid_argument ); |
650 | |
651 | result<int&> r1( ec ); |
652 | result<int&> r2( x1 ); |
653 | |
654 | r2 = std::move( r1 ); |
655 | |
656 | BOOST_TEST_EQ( x1, 1 ); |
657 | |
658 | BOOST_TEST( !r2.has_value() ); |
659 | BOOST_TEST( r2.has_error() ); |
660 | |
661 | BOOST_TEST_EQ( r2.error(), ec ); |
662 | } |
663 | |
664 | { |
665 | int x1 = 1; |
666 | |
667 | auto ec = make_error_code( e: errc::invalid_argument ); |
668 | |
669 | result<int&> r2( x1 ); |
670 | |
671 | r2 = result<int&>( ec ); |
672 | |
673 | BOOST_TEST_EQ( x1, 1 ); |
674 | |
675 | BOOST_TEST( !r2.has_value() ); |
676 | BOOST_TEST( r2.has_error() ); |
677 | |
678 | BOOST_TEST_EQ( r2.error(), ec ); |
679 | } |
680 | |
681 | { |
682 | auto ec = make_error_code( e: errc::invalid_argument ); |
683 | |
684 | result<int&> r1( ec ); |
685 | result<int&> r2( ENOENT, generic_category() ); |
686 | |
687 | r2 = std::move( r1 ); |
688 | |
689 | BOOST_TEST( !r2.has_value() ); |
690 | BOOST_TEST( r2.has_error() ); |
691 | |
692 | BOOST_TEST_EQ( r2.error(), ec ); |
693 | } |
694 | |
695 | { |
696 | auto ec = make_error_code( e: errc::invalid_argument ); |
697 | |
698 | result<int&> r2( ENOENT, generic_category() ); |
699 | |
700 | r2 = result<int&>( ec ); |
701 | |
702 | BOOST_TEST( !r2.has_value() ); |
703 | BOOST_TEST( r2.has_error() ); |
704 | |
705 | BOOST_TEST_EQ( r2.error(), ec ); |
706 | } |
707 | |
708 | // |
709 | |
710 | return boost::report_errors(); |
711 | } |
712 | |