]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/function/test/function_test.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / function / test / function_test.cpp
CommitLineData
7c673cae
FG
1// Boost.Function library
2
3// Copyright Douglas Gregor 2001-2003. Use, modification and
4// distribution is subject to the Boost Software License, Version
5// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6// http://www.boost.org/LICENSE_1_0.txt)
7
8// For more information, see http://www.boost.org
9
7c673cae 10#include <boost/function.hpp>
92f5a8d4 11#include <boost/core/lightweight_test.hpp>
7c673cae
FG
12#include <functional>
13#include <string>
14#include <utility>
15
92f5a8d4
TL
16#define BOOST_CHECK BOOST_TEST
17
7c673cae
FG
18using boost::function;
19using std::string;
20
21int global_int;
22
23struct write_five_obj { void operator()() const { global_int = 5; } };
24struct write_three_obj { int operator()() const { global_int = 3; return 7; }};
25static void write_five() { global_int = 5; }
26static void write_three() { global_int = 3; }
27struct generate_five_obj { int operator()() const { return 5; } };
28struct generate_three_obj { int operator()() const { return 3; } };
29static int generate_five() { return 5; }
30static int generate_three() { return 3; }
31static string identity_str(const string& s) { return s; }
32static string string_cat(const string& s1, const string& s2) { return s1+s2; }
33static int sum_ints(int x, int y) { return x+y; }
34
35struct write_const_1_nonconst_2
36{
37 void operator()() { global_int = 2; }
38 void operator()() const { global_int = 1; }
39};
40
41struct add_to_obj
42{
43 add_to_obj(int v) : value(v) {}
44
45 int operator()(int x) const { return value + x; }
46
47 int value;
48};
49
50static void
51test_zero_args()
52{
53 typedef function<void ()> func_void_type;
54
55 write_five_obj five;
56 write_three_obj three;
57
58 // Default construction
59 func_void_type v1;
60 BOOST_CHECK(v1.empty());
61
62 // Assignment to an empty function
63 v1 = five;
64 BOOST_CHECK(v1 != 0);
65
66 // Invocation of a function
67 global_int = 0;
68 v1();
69 BOOST_CHECK(global_int == 5);
70
71 // clear() method
72 v1.clear();
73 BOOST_CHECK(v1 == 0);
74
75 // Assignment to an empty function
76 v1 = three;
77 BOOST_CHECK(!v1.empty());
78
79 // Invocation and self-assignment
80 global_int = 0;
81 v1 = v1;
82 v1();
83 BOOST_CHECK(global_int == 3);
84
85 // Assignment to a non-empty function
86 v1 = five;
87
88 // Invocation and self-assignment
89 global_int = 0;
90 v1 = (v1);
91 v1();
92 BOOST_CHECK(global_int == 5);
93
94 // clear
95 v1 = 0;
96 BOOST_CHECK(0 == v1);
97
98 // Assignment to an empty function from a free function
99 v1 = BOOST_FUNCTION_TARGET_FIX(&) write_five;
100 BOOST_CHECK(0 != v1);
101
102 // Invocation
103 global_int = 0;
104 v1();
105 BOOST_CHECK(global_int == 5);
106
107 // Assignment to a non-empty function from a free function
108 v1 = BOOST_FUNCTION_TARGET_FIX(&) write_three;
109 BOOST_CHECK(!v1.empty());
110
111 // Invocation
112 global_int = 0;
113 v1();
114 BOOST_CHECK(global_int == 3);
115
116 // Assignment
117 v1 = five;
118 BOOST_CHECK(!v1.empty());
119
120 // Invocation
121 global_int = 0;
122 v1();
123 BOOST_CHECK(global_int == 5);
124
125 // Assignment to a non-empty function from a free function
126 v1 = &write_three;
127 BOOST_CHECK(!v1.empty());
128
129 // Invocation
130 global_int = 0;
131 v1();
132 BOOST_CHECK(global_int == 3);
133
134 // Construction from another function (that is empty)
135 v1.clear();
136 func_void_type v2(v1);
137 BOOST_CHECK(!v2? true : false);
138
139 // Assignment to an empty function
140 v2 = three;
141 BOOST_CHECK(!v2.empty());
142
143 // Invocation
144 global_int = 0;
145 v2();
146 BOOST_CHECK(global_int == 3);
147
148 // Assignment to a non-empty function
149 v2 = (five);
150
151 // Invocation
152 global_int = 0;
153 v2();
154 BOOST_CHECK(global_int == 5);
155
156 v2.clear();
157 BOOST_CHECK(v2.empty());
158
159 // Assignment to an empty function from a free function
160 v2 = (BOOST_FUNCTION_TARGET_FIX(&) write_five);
161 BOOST_CHECK(v2? true : false);
162
163 // Invocation
164 global_int = 0;
165 v2();
166 BOOST_CHECK(global_int == 5);
167
168 // Assignment to a non-empty function from a free function
169 v2 = BOOST_FUNCTION_TARGET_FIX(&) write_three;
170 BOOST_CHECK(!v2.empty());
171
172 // Invocation
173 global_int = 0;
174 v2();
175 BOOST_CHECK(global_int == 3);
176
177 // Swapping
178 v1 = five;
179 swap(v1, v2);
180 v2();
181 BOOST_CHECK(global_int == 5);
182 v1();
183 BOOST_CHECK(global_int == 3);
184 swap(v1, v2);
185 v1.clear();
186
187 // Assignment
188 v2 = five;
189 BOOST_CHECK(!v2.empty());
190
191 // Invocation
192 global_int = 0;
193 v2();
194 BOOST_CHECK(global_int == 5);
195
196 // Assignment to a non-empty function from a free function
197 v2 = &write_three;
198 BOOST_CHECK(!v2.empty());
199
200 // Invocation
201 global_int = 0;
202 v2();
203 BOOST_CHECK(global_int == 3);
204
205 // Assignment to a function from an empty function
206 v2 = v1;
207 BOOST_CHECK(v2.empty());
208
209 // Assignment to a function from a function with a functor
210 v1 = three;
211 v2 = v1;
212 BOOST_CHECK(!v1.empty());
213 BOOST_CHECK(!v2.empty());
214
215 // Invocation
216 global_int = 0;
217 v1();
218 BOOST_CHECK(global_int == 3);
219 global_int = 0;
220 v2();
221 BOOST_CHECK(global_int == 3);
222
223 // Assign to a function from a function with a function
224 v2 = BOOST_FUNCTION_TARGET_FIX(&) write_five;
225 v1 = v2;
226 BOOST_CHECK(!v1.empty());
227 BOOST_CHECK(!v2.empty());
228 global_int = 0;
229 v1();
230 BOOST_CHECK(global_int == 5);
231 global_int = 0;
232 v2();
233 BOOST_CHECK(global_int == 5);
234
235 // Construct a function given another function containing a function
236 func_void_type v3(v1);
237
238 // Invocation of a function
239 global_int = 0;
240 v3();
241 BOOST_CHECK(global_int == 5);
242
243 // clear() method
244 v3.clear();
245 BOOST_CHECK(!v3? true : false);
246
247 // Assignment to an empty function
248 v3 = three;
249 BOOST_CHECK(!v3.empty());
250
251 // Invocation
252 global_int = 0;
253 v3();
254 BOOST_CHECK(global_int == 3);
255
256 // Assignment to a non-empty function
257 v3 = five;
258
259 // Invocation
260 global_int = 0;
261 v3();
262 BOOST_CHECK(global_int == 5);
263
264 // clear()
265 v3.clear();
266 BOOST_CHECK(v3.empty());
267
268 // Assignment to an empty function from a free function
269 v3 = &write_five;
270 BOOST_CHECK(!v3.empty());
271
272 // Invocation
273 global_int = 0;
274 v3();
275 BOOST_CHECK(global_int == 5);
276
277 // Assignment to a non-empty function from a free function
278 v3 = &write_three;
279 BOOST_CHECK(!v3.empty());
280
281 // Invocation
282 global_int = 0;
283 v3();
284 BOOST_CHECK(global_int == 3);
285
286 // Assignment
287 v3 = five;
288 BOOST_CHECK(!v3.empty());
289
290 // Invocation
291 global_int = 0;
292 v3();
293 BOOST_CHECK(global_int == 5);
294
295 // Construction of a function from a function containing a functor
296 func_void_type v4(v3);
297
298 // Invocation of a function
299 global_int = 0;
300 v4();
301 BOOST_CHECK(global_int == 5);
302
303 // clear() method
304 v4.clear();
305 BOOST_CHECK(v4.empty());
306
307 // Assignment to an empty function
308 v4 = three;
309 BOOST_CHECK(!v4.empty());
310
311 // Invocation
312 global_int = 0;
313 v4();
314 BOOST_CHECK(global_int == 3);
315
316 // Assignment to a non-empty function
317 v4 = five;
318
319 // Invocation
320 global_int = 0;
321 v4();
322 BOOST_CHECK(global_int == 5);
323
324 // clear()
325 v4.clear();
326 BOOST_CHECK(v4.empty());
327
328 // Assignment to an empty function from a free function
329 v4 = &write_five;
330 BOOST_CHECK(!v4.empty());
331
332 // Invocation
333 global_int = 0;
334 v4();
335 BOOST_CHECK(global_int == 5);
336
337 // Assignment to a non-empty function from a free function
338 v4 = &write_three;
339 BOOST_CHECK(!v4.empty());
340
341 // Invocation
342 global_int = 0;
343 v4();
344 BOOST_CHECK(global_int == 3);
345
346 // Assignment
347 v4 = five;
348 BOOST_CHECK(!v4.empty());
349
350 // Invocation
351 global_int = 0;
352 v4();
353 BOOST_CHECK(global_int == 5);
354
355 // Construction of a function from a functor
356 func_void_type v5(five);
357
358 // Invocation of a function
359 global_int = 0;
360 v5();
361 BOOST_CHECK(global_int == 5);
362
363 // clear() method
364 v5.clear();
365 BOOST_CHECK(v5.empty());
366
367 // Assignment to an empty function
368 v5 = three;
369 BOOST_CHECK(!v5.empty());
370
371 // Invocation
372 global_int = 0;
373 v5();
374 BOOST_CHECK(global_int == 3);
375
376 // Assignment to a non-empty function
377 v5 = five;
378
379 // Invocation
380 global_int = 0;
381 v5();
382 BOOST_CHECK(global_int == 5);
383
384 // clear()
385 v5.clear();
386 BOOST_CHECK(v5.empty());
387
388 // Assignment to an empty function from a free function
389 v5 = &write_five;
390 BOOST_CHECK(!v5.empty());
391
392 // Invocation
393 global_int = 0;
394 v5();
395 BOOST_CHECK(global_int == 5);
396
397 // Assignment to a non-empty function from a free function
398 v5 = &write_three;
399 BOOST_CHECK(!v5.empty());
400
401 // Invocation
402 global_int = 0;
403 v5();
404 BOOST_CHECK(global_int == 3);
405
406 // Assignment
407 v5 = five;
408 BOOST_CHECK(!v5.empty());
409
410 // Invocation
411 global_int = 0;
412 v5();
413 BOOST_CHECK(global_int == 5);
414
415 // Construction of a function from a function
416 func_void_type v6(&write_five);
417
418 // Invocation of a function
419 global_int = 0;
420 v6();
421 BOOST_CHECK(global_int == 5);
422
423 // clear() method
424 v6.clear();
425 BOOST_CHECK(v6.empty());
426
427 // Assignment to an empty function
428 v6 = three;
429 BOOST_CHECK(!v6.empty());
430
431 // Invocation
432 global_int = 0;
433 v6();
434 BOOST_CHECK(global_int == 3);
435
436 // Assignment to a non-empty function
437 v6 = five;
438
439 // Invocation
440 global_int = 0;
441 v6();
442 BOOST_CHECK(global_int == 5);
443
444 // clear()
445 v6.clear();
446 BOOST_CHECK(v6.empty());
447
448 // Assignment to an empty function from a free function
449 v6 = &write_five;
450 BOOST_CHECK(!v6.empty());
451
452 // Invocation
453 global_int = 0;
454 v6();
455 BOOST_CHECK(global_int == 5);
456
457 // Assignment to a non-empty function from a free function
458 v6 = &write_three;
459 BOOST_CHECK(!v6.empty());
460
461 // Invocation
462 global_int = 0;
463 v6();
464 BOOST_CHECK(global_int == 3);
465
466 // Assignment
467 v6 = five;
468 BOOST_CHECK(!v6.empty());
469
470 // Invocation
471 global_int = 0;
472 v6();
473 BOOST_CHECK(global_int == 5);
474
475 // Const vs. non-const
476 write_const_1_nonconst_2 one_or_two;
477 const function<void ()> v7(one_or_two);
478 function<void ()> v8(one_or_two);
479
480 global_int = 0;
481 v7();
482 BOOST_CHECK(global_int == 2);
483
484 global_int = 0;
485 v8();
486 BOOST_CHECK(global_int == 2);
487
488 // Test construction from 0 and comparison to 0
489 func_void_type v9(0);
490 BOOST_CHECK(v9 == 0);
491 BOOST_CHECK(0 == v9);
492
493 // Test return values
494 typedef function<int ()> func_int_type;
495 generate_five_obj gen_five;
496 generate_three_obj gen_three;
497
498 func_int_type i0(gen_five);
499
500 BOOST_CHECK(i0() == 5);
501 i0 = gen_three;
502 BOOST_CHECK(i0() == 3);
503 i0 = &generate_five;
504 BOOST_CHECK(i0() == 5);
505 i0 = &generate_three;
506 BOOST_CHECK(i0() == 3);
507 BOOST_CHECK(i0? true : false);
508 i0.clear();
509 BOOST_CHECK(!i0? true : false);
510
511 // Test return values with compatible types
512 typedef function<long ()> func_long_type;
513 func_long_type i1(gen_five);
514
515 BOOST_CHECK(i1() == 5);
516 i1 = gen_three;
517 BOOST_CHECK(i1() == 3);
518 i1 = &generate_five;
519 BOOST_CHECK(i1() == 5);
520 i1 = &generate_three;
521 BOOST_CHECK(i1() == 3);
522 BOOST_CHECK(i1? true : false);
523 i1.clear();
524 BOOST_CHECK(!i1? true : false);
525}
526
527static void
528test_one_arg()
529{
530 std::negate<int> neg;
531
532 function<int (int)> f1(neg);
533 BOOST_CHECK(f1(5) == -5);
534
535 function<string (string)> id(&identity_str);
536 BOOST_CHECK(id("str") == "str");
537
538 function<string (const char*)> id2(&identity_str);
539 BOOST_CHECK(id2("foo") == "foo");
540
541 add_to_obj add_to(5);
542 function<int (int)> f2(add_to);
543 BOOST_CHECK(f2(3) == 8);
544
545 const function<int (int)> cf2(add_to);
546 BOOST_CHECK(cf2(3) == 8);
547}
548
549static void
550test_two_args()
551{
552 function<string (const string&, const string&)> cat(&string_cat);
553 BOOST_CHECK(cat("str", "ing") == "string");
554
555 function<int (short, short)> sum(&sum_ints);
556 BOOST_CHECK(sum(2, 3) == 5);
557}
558
559static void
560test_emptiness()
561{
562 function<float ()> f1;
563 BOOST_CHECK(f1.empty());
564
565 function<float ()> f2;
566 f2 = f1;
567 BOOST_CHECK(f2.empty());
568
569 function<double ()> f3;
570 f3 = f2;
571 BOOST_CHECK(f3.empty());
572}
573
574struct X {
575 X(int v) : value(v) {}
576
577 int twice() const { return 2*value; }
578 int plus(int v) { return value + v; }
579
580 int value;
581};
582
583static void
584test_member_functions()
585{
586 boost::function<int (X*)> f1(&X::twice);
587
588 X one(1);
589 X five(5);
590
591 BOOST_CHECK(f1(&one) == 2);
592 BOOST_CHECK(f1(&five) == 10);
593
594 boost::function<int (X*)> f1_2;
595 f1_2 = &X::twice;
596
597 BOOST_CHECK(f1_2(&one) == 2);
598 BOOST_CHECK(f1_2(&five) == 10);
599
600 boost::function<int (X&, int)> f2(&X::plus);
601 BOOST_CHECK(f2(one, 3) == 4);
602 BOOST_CHECK(f2(five, 4) == 9);
603}
604
605struct add_with_throw_on_copy {
606 int operator()(int x, int y) const { return x+y; }
607
608 add_with_throw_on_copy() {}
609
610 add_with_throw_on_copy(const add_with_throw_on_copy&)
611 {
612 throw std::runtime_error("But this CAN'T throw");
613 }
614
615 add_with_throw_on_copy& operator=(const add_with_throw_on_copy&)
616 {
617 throw std::runtime_error("But this CAN'T throw");
618 }
619};
620
621static void
622test_ref()
623{
624 add_with_throw_on_copy atc;
625 try {
626 boost::function<int (int, int)> f(boost::ref(atc));
627 BOOST_CHECK(f(1, 3) == 4);
628 }
92f5a8d4 629 catch(std::runtime_error const&) {
7c673cae
FG
630 BOOST_ERROR("Nonthrowing constructor threw an exception");
631 }
632}
633
11fdf7f2
TL
634#if BOOST_WORKAROUND(BOOST_GCC, >= 70000 && BOOST_GCC < 80000) && __cplusplus >= 201700
635
636// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81311
637#pragma message("Skipping test_empty_ref on g++ 7 -std=c++17")
638
639static void test_empty_ref()
640{
641}
642
643#else
644
7c673cae
FG
645static void dummy() {}
646
647static void test_empty_ref()
648{
649 boost::function<void()> f1;
650 boost::function<void()> f2(boost::ref(f1));
651
652 try {
653 f2();
654 BOOST_ERROR("Exception didn't throw for reference to empty function.");
655 }
92f5a8d4 656 catch(std::runtime_error const&) {}
7c673cae
FG
657
658 f1 = dummy;
659
660 try {
661 f2();
662 }
92f5a8d4 663 catch(std::runtime_error const&) {
7c673cae
FG
664 BOOST_ERROR("Error calling referenced function.");
665 }
666}
667
11fdf7f2
TL
668#endif
669
7c673cae
FG
670
671static void test_exception()
672{
673 boost::function<int (int, int)> f;
674 try {
675 f(5, 4);
676 BOOST_CHECK(false);
677 }
92f5a8d4 678 catch(boost::bad_function_call const&) {
7c673cae
FG
679 // okay
680 }
681}
682
683typedef boost::function< void * (void * reader) > reader_type;
684typedef std::pair<int, reader_type> mapped_type;
685
686static void test_implicit()
687{
688 mapped_type m;
689 m = mapped_type();
690}
691
692static void test_call_obj(boost::function<int (int, int)> f)
693{
694 BOOST_CHECK(!f.empty());
695}
696
697static void test_call_cref(const boost::function<int (int, int)>& f)
698{
699 BOOST_CHECK(!f.empty());
700}
701
702static void test_call()
703{
704 test_call_obj(std::plus<int>());
705 test_call_cref(std::plus<int>());
706}
707
708struct big_aggregating_structure {
709 int disable_small_objects_optimizations[32];
710
711 big_aggregating_structure()
712 {
713 ++ global_int;
714 }
715
716 big_aggregating_structure(const big_aggregating_structure&)
717 {
718 ++ global_int;
719 }
720
721 ~big_aggregating_structure()
722 {
723 -- global_int;
724 }
725
726 void operator()()
727 {
728 ++ global_int;
729 }
730
731 void operator()(int)
732 {
733 ++ global_int;
734 }
735};
736
737template <class FunctionT>
738static void test_move_semantics()
739{
740 typedef FunctionT f1_type;
741
742 big_aggregating_structure obj;
743
744 f1_type f1 = obj;
745 global_int = 0;
746 f1();
747
748 BOOST_CHECK(!f1.empty());
749 BOOST_CHECK(global_int == 1);
750
751#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
752 // Testing rvalue constructors
753 f1_type f2(static_cast<f1_type&&>(f1));
754 BOOST_CHECK(f1.empty());
755 BOOST_CHECK(!f2.empty());
756 BOOST_CHECK(global_int == 1);
757 f2();
758 BOOST_CHECK(global_int == 2);
759
760 f1_type f3(static_cast<f1_type&&>(f2));
761 BOOST_CHECK(f1.empty());
762 BOOST_CHECK(f2.empty());
763 BOOST_CHECK(!f3.empty());
764 BOOST_CHECK(global_int == 2);
765 f3();
766 BOOST_CHECK(global_int == 3);
767
768 // Testing move assignment
769 f1_type f4;
770 BOOST_CHECK(f4.empty());
771 f4 = static_cast<f1_type&&>(f3);
772 BOOST_CHECK(f1.empty());
773 BOOST_CHECK(f2.empty());
774 BOOST_CHECK(f3.empty());
775 BOOST_CHECK(!f4.empty());
776 BOOST_CHECK(global_int == 3);
777 f4();
778 BOOST_CHECK(global_int == 4);
779
780 // Testing self move assignment
781 f4 = static_cast<f1_type&&>(f4);
782 BOOST_CHECK(!f4.empty());
783 BOOST_CHECK(global_int == 4);
784
785 // Testing, that no memory leaked when assigning to nonempty function
786 f4 = obj;
787 BOOST_CHECK(!f4.empty());
788 BOOST_CHECK(global_int == 4);
789 f1_type f5 = obj;
790 BOOST_CHECK(global_int == 5);
791 f4 = static_cast<f1_type&&>(f5);
792 BOOST_CHECK(global_int == 4);
793
794#endif
795}
796
92f5a8d4 797int main()
7c673cae
FG
798{
799 test_zero_args();
800 test_one_arg();
801 test_two_args();
802 test_emptiness();
803 test_member_functions();
804 test_ref();
805 test_empty_ref();
806 test_exception();
807 test_implicit();
808 test_call();
809 test_move_semantics<function<void()> >();
810 test_move_semantics<boost::function0<void> >();
811
92f5a8d4 812 return boost::report_errors();
7c673cae 813}