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