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