65d6e583b9b9fb6363b59d7a68249d577124f5a6
[platform/upstream/boost.git] / libs / function / test / function_test.cpp
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
10 #include <boost/test/minimal.hpp>
11 #include <boost/function.hpp>
12 #include <functional>
13 #include <string>
14 #include <utility>
15
16 using boost::function;
17 using std::string;
18
19 int global_int;
20
21 struct write_five_obj { void operator()() const { global_int = 5; } };
22 struct write_three_obj { int operator()() const { global_int = 3; return 7; }};
23 static void write_five() { global_int = 5; }
24 static void write_three() { global_int = 3; }
25 struct generate_five_obj { int operator()() const { return 5; } };
26 struct generate_three_obj { int operator()() const { return 3; } };
27 static int generate_five() { return 5; }
28 static int generate_three() { return 3; }
29 static string identity_str(const string& s) { return s; }
30 static string string_cat(const string& s1, const string& s2) { return s1+s2; }
31 static int sum_ints(int x, int y) { return x+y; }
32
33 struct write_const_1_nonconst_2
34 {
35   void operator()() { global_int = 2; }
36   void operator()() const { global_int = 1; }
37 };
38
39 struct 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
48 static void
49 test_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
525 static void
526 test_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
547 static void
548 test_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
557 static void
558 test_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
572 struct 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
581 static void
582 test_member_functions()
583 {
584   boost::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   boost::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   boost::function<int (X&, int)> f2(&X::plus);
599   BOOST_CHECK(f2(one, 3) == 4);
600   BOOST_CHECK(f2(five, 4) == 9);
601 }
602
603 struct 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
619 static void
620 test_ref()
621 {
622   add_with_throw_on_copy atc;
623   try {
624     boost::function<int (int, int)> f(boost::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
632 static void dummy() {}
633
634 static void test_empty_ref()
635 {
636   boost::function<void()> f1;
637   boost::function<void()> f2(boost::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
656 static void test_exception()
657 {
658   boost::function<int (int, int)> f;
659   try {
660     f(5, 4);
661     BOOST_CHECK(false);
662   }
663   catch(boost::bad_function_call) {
664     // okay
665   }
666 }
667
668 typedef boost::function< void * (void * reader) > reader_type;
669 typedef std::pair<int, reader_type> mapped_type;
670
671 static void test_implicit()
672 {
673   mapped_type m;
674   m = mapped_type();
675 }
676
677 static void test_call_obj(boost::function<int (int, int)> f)
678 {
679   BOOST_CHECK(!f.empty());
680 }
681
682 static void test_call_cref(const boost::function<int (int, int)>& f)
683 {
684   BOOST_CHECK(!f.empty());
685 }
686
687 static void test_call()
688 {
689   test_call_obj(std::plus<int>());
690   test_call_cref(std::plus<int>());
691 }
692
693 int test_main(int, char* [])
694 {
695   test_zero_args();
696   test_one_arg();
697   test_two_args();
698   test_emptiness();
699   test_member_functions();
700   test_ref();
701   test_empty_ref();
702   test_exception();
703   test_implicit();
704   test_call();
705
706   return 0;
707 }