diff options
Diffstat (limited to 'src/boost/libs/function/test/function_n_test.cpp')
-rw-r--r-- | src/boost/libs/function/test/function_n_test.cpp | 699 |
1 files changed, 699 insertions, 0 deletions
diff --git a/src/boost/libs/function/test/function_n_test.cpp b/src/boost/libs/function/test/function_n_test.cpp new file mode 100644 index 00000000..418c46fd --- /dev/null +++ b/src/boost/libs/function/test/function_n_test.cpp @@ -0,0 +1,699 @@ +// Boost.Function library + +// Copyright Douglas Gregor 2001-2003. Use, modification and +// distribution is subject to the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +#include <boost/function.hpp> +#include <boost/core/lightweight_test.hpp> +#include <functional> +#include <cassert> +#include <string> + +#define BOOST_CHECK BOOST_TEST + +using namespace boost; +using std::string; +using std::negate; + +int global_int; + +struct write_five_obj { void operator()() const { global_int = 5; } }; +struct write_three_obj { int operator()() const { global_int = 3; return 7; }}; +static void write_five() { global_int = 5; } +static void write_three() { global_int = 3; } +struct generate_five_obj { int operator()() const { return 5; } }; +struct generate_three_obj { int operator()() const { return 3; } }; +static int generate_five() { return 5; } +static int generate_three() { return 3; } +static string identity_str(const string& s) { return s; } +static string string_cat(const string& s1, const string& s2) { return s1+s2; } +static int sum_ints(int x, int y) { return x+y; } + +struct write_const_1_nonconst_2 +{ + void operator()() { global_int = 2; } + void operator()() const { global_int = 1; } +}; + +struct add_to_obj +{ + add_to_obj(int v) : value(v) {} + + int operator()(int x) const { return value + x; } + + int value; +}; + +static void +test_zero_args() +{ + typedef function0<void> func_void_type; + + write_five_obj five = write_five_obj(); // Initialization for Borland C++ 5.5 + write_three_obj three = write_three_obj(); // Ditto + + // Default construction + func_void_type v1; + BOOST_CHECK(v1.empty()); + + // Assignment to an empty function + v1 = five; + BOOST_CHECK(!v1.empty()); + + // Invocation of a function + global_int = 0; + v1(); + BOOST_CHECK(global_int == 5); + + // clear() method + v1.clear(); + BOOST_CHECK(!v1); + + // Assignment to an empty function + v1 = three; + BOOST_CHECK(!v1.empty()); + + // Invocation and self-assignment + global_int = 0; + v1 = v1; + v1(); + BOOST_CHECK(global_int == 3); + + // Assignment to a non-empty function + v1 = five; + + // Invocation and self-assignment + global_int = 0; + v1 = (v1); + v1(); + BOOST_CHECK(global_int == 5); + + // clear + v1 = 0; + BOOST_CHECK(v1.empty()); + + // Assignment to an empty function from a free function + v1 = &write_five; + BOOST_CHECK(!v1.empty()); + + // Invocation + global_int = 0; + v1(); + BOOST_CHECK(global_int == 5); + + // Assignment to a non-empty function from a free function + v1 = &write_three; + BOOST_CHECK(!v1.empty()); + + // Invocation + global_int = 0; + v1(); + BOOST_CHECK(global_int == 3); + + // Assignment + v1 = five; + BOOST_CHECK(!v1.empty()); + + // Invocation + global_int = 0; + v1(); + BOOST_CHECK(global_int == 5); + + // Assignment to a non-empty function from a free function + v1 = write_three; + BOOST_CHECK(!v1.empty()); + + // Invocation + global_int = 0; + v1(); + BOOST_CHECK(global_int == 3); + + // Construction from another function (that is empty) + v1.clear(); + func_void_type v2(v1); + BOOST_CHECK(!v2? true : false); + + // Assignment to an empty function + v2 = three; + BOOST_CHECK(!v2.empty()); + + // Invocation + global_int = 0; + v2(); + BOOST_CHECK(global_int == 3); + + // Assignment to a non-empty function + v2 = (five); + + // Invocation + global_int = 0; + v2(); + BOOST_CHECK(global_int == 5); + + v2.clear(); + BOOST_CHECK(v2.empty()); + + // Assignment to an empty function from a free function + v2 = (&write_five); + BOOST_CHECK(v2? true : false); + + // Invocation + global_int = 0; + v2(); + BOOST_CHECK(global_int == 5); + + // Assignment to a non-empty function from a free function + v2 = &write_three; + BOOST_CHECK(!v2.empty()); + + // Invocation + global_int = 0; + v2(); + BOOST_CHECK(global_int == 3); + + // Swapping + v1 = five; + swap(v1, v2); + v2(); + BOOST_CHECK(global_int == 5); + v1(); + BOOST_CHECK(global_int == 3); + swap(v1, v2); + v1.clear(); + + // Assignment + v2 = five; + BOOST_CHECK(!v2.empty()); + + // Invocation + global_int = 0; + v2(); + BOOST_CHECK(global_int == 5); + + // Assignment to a non-empty function from a free function + v2 = &write_three; + BOOST_CHECK(!v2.empty()); + + // Invocation + global_int = 0; + v2(); + BOOST_CHECK(global_int == 3); + + // Assignment to a function from an empty function + v2 = v1; + BOOST_CHECK(v2.empty()); + + // Assignment to a function from a function with a functor + v1 = three; + v2 = v1; + BOOST_CHECK(!v1.empty()); + BOOST_CHECK(!v2.empty()); + + // Invocation + global_int = 0; + v1(); + BOOST_CHECK(global_int == 3); + global_int = 0; + v2(); + BOOST_CHECK(global_int == 3); + + // Assign to a function from a function with a function + v2 = &write_five; + v1 = v2; + BOOST_CHECK(!v1.empty()); + BOOST_CHECK(!v2.empty()); + global_int = 0; + v1(); + BOOST_CHECK(global_int == 5); + global_int = 0; + v2(); + BOOST_CHECK(global_int == 5); + + // Construct a function given another function containing a function + func_void_type v3(v1); + + // Invocation of a function + global_int = 0; + v3(); + BOOST_CHECK(global_int == 5); + + // clear() method + v3.clear(); + BOOST_CHECK(!v3? true : false); + + // Assignment to an empty function + v3 = three; + BOOST_CHECK(!v3.empty()); + + // Invocation + global_int = 0; + v3(); + BOOST_CHECK(global_int == 3); + + // Assignment to a non-empty function + v3 = five; + + // Invocation + global_int = 0; + v3(); + BOOST_CHECK(global_int == 5); + + // clear() + v3.clear(); + BOOST_CHECK(v3.empty()); + + // Assignment to an empty function from a free function + v3 = &write_five; + BOOST_CHECK(!v3.empty()); + + // Invocation + global_int = 0; + v3(); + BOOST_CHECK(global_int == 5); + + // Assignment to a non-empty function from a free function + v3 = &write_three; + BOOST_CHECK(!v3.empty()); + + // Invocation + global_int = 0; + v3(); + BOOST_CHECK(global_int == 3); + + // Assignment + v3 = five; + BOOST_CHECK(!v3.empty()); + + // Invocation + global_int = 0; + v3(); + BOOST_CHECK(global_int == 5); + + // Construction of a function from a function containing a functor + func_void_type v4(v3); + + // Invocation of a function + global_int = 0; + v4(); + BOOST_CHECK(global_int == 5); + + // clear() method + v4.clear(); + BOOST_CHECK(v4.empty()); + + // Assignment to an empty function + v4 = three; + BOOST_CHECK(!v4.empty()); + + // Invocation + global_int = 0; + v4(); + BOOST_CHECK(global_int == 3); + + // Assignment to a non-empty function + v4 = five; + + // Invocation + global_int = 0; + v4(); + BOOST_CHECK(global_int == 5); + + // clear() + v4.clear(); + BOOST_CHECK(v4.empty()); + + // Assignment to an empty function from a free function + v4 = &write_five; + BOOST_CHECK(!v4.empty()); + + // Invocation + global_int = 0; + v4(); + BOOST_CHECK(global_int == 5); + + // Assignment to a non-empty function from a free function + v4 = &write_three; + BOOST_CHECK(!v4.empty()); + + // Invocation + global_int = 0; + v4(); + BOOST_CHECK(global_int == 3); + + // Assignment + v4 = five; + BOOST_CHECK(!v4.empty()); + + // Invocation + global_int = 0; + v4(); + BOOST_CHECK(global_int == 5); + + // Construction of a function from a functor + func_void_type v5(five); + + // Invocation of a function + global_int = 0; + v5(); + BOOST_CHECK(global_int == 5); + + // clear() method + v5.clear(); + BOOST_CHECK(v5.empty()); + + // Assignment to an empty function + v5 = three; + BOOST_CHECK(!v5.empty()); + + // Invocation + global_int = 0; + v5(); + BOOST_CHECK(global_int == 3); + + // Assignment to a non-empty function + v5 = five; + + // Invocation + global_int = 0; + v5(); + BOOST_CHECK(global_int == 5); + + // clear() + v5.clear(); + BOOST_CHECK(v5.empty()); + + // Assignment to an empty function from a free function + v5 = &write_five; + BOOST_CHECK(!v5.empty()); + + // Invocation + global_int = 0; + v5(); + BOOST_CHECK(global_int == 5); + + // Assignment to a non-empty function from a free function + v5 = &write_three; + BOOST_CHECK(!v5.empty()); + + // Invocation + global_int = 0; + v5(); + BOOST_CHECK(global_int == 3); + + // Assignment + v5 = five; + BOOST_CHECK(!v5.empty()); + + // Invocation + global_int = 0; + v5(); + BOOST_CHECK(global_int == 5); + + // Construction of a function from a function + func_void_type v6(&write_five); + + // Invocation of a function + global_int = 0; + v6(); + BOOST_CHECK(global_int == 5); + + // clear() method + v6.clear(); + BOOST_CHECK(v6.empty()); + + // Assignment to an empty function + v6 = three; + BOOST_CHECK(!v6.empty()); + + // Invocation + global_int = 0; + v6(); + BOOST_CHECK(global_int == 3); + + // Assignment to a non-empty function + v6 = five; + + // Invocation + global_int = 0; + v6(); + BOOST_CHECK(global_int == 5); + + // clear() + v6.clear(); + BOOST_CHECK(v6.empty()); + + // Assignment to an empty function from a free function + v6 = &write_five; + BOOST_CHECK(!v6.empty()); + + // Invocation + global_int = 0; + v6(); + BOOST_CHECK(global_int == 5); + + // Assignment to a non-empty function from a free function + v6 = &write_three; + BOOST_CHECK(!v6.empty()); + + // Invocation + global_int = 0; + v6(); + BOOST_CHECK(global_int == 3); + + // Assignment + v6 = five; + BOOST_CHECK(!v6.empty()); + + // Invocation + global_int = 0; + v6(); + BOOST_CHECK(global_int == 5); + + // Const vs. non-const + // Initialization for Borland C++ 5.5 + write_const_1_nonconst_2 one_or_two = write_const_1_nonconst_2(); + const function0<void> v7(one_or_two); + function0<void> v8(one_or_two); + + global_int = 0; + v7(); + BOOST_CHECK(global_int == 2); + + global_int = 0; + v8(); + BOOST_CHECK(global_int == 2); + + // Test construction from 0 and comparison to 0 + func_void_type v9(0); + BOOST_CHECK(v9 == 0); +# if !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540 || defined(BOOST_STRICT_CONFIG) + BOOST_CHECK(0 == v9); +#else + BOOST_CHECK(v9.empty()); +#endif + + // Test return values + typedef function0<int> func_int_type; + // Initialization for Borland C++ 5.5 + generate_five_obj gen_five = generate_five_obj(); + generate_three_obj gen_three = generate_three_obj(); + func_int_type i0(gen_five); + + BOOST_CHECK(i0() == 5); + i0 = gen_three; + BOOST_CHECK(i0() == 3); + i0 = &generate_five; + BOOST_CHECK(i0() == 5); + i0 = &generate_three; + BOOST_CHECK(i0() == 3); + BOOST_CHECK(i0? true : false); + i0.clear(); + BOOST_CHECK(!i0? true : false); + + // Test return values with compatible types + typedef function0<long> func_long_type; + func_long_type i1(gen_five); + + BOOST_CHECK(i1() == 5); + i1 = gen_three; + BOOST_CHECK(i1() == 3); + i1 = &generate_five; + BOOST_CHECK(i1() == 5); + i1 = &generate_three; + BOOST_CHECK(i1() == 3); + BOOST_CHECK(i1? true : false); + i1.clear(); + BOOST_CHECK(!i1? true : false); +} + +static void +test_one_arg() +{ + negate<int> neg = negate<int>(); // Initialization for Borland C++ 5.5 + + function1<int, int> f1(neg); + BOOST_CHECK(f1(5) == -5); + + function1<string, string> id(&identity_str); + BOOST_CHECK(id("str") == "str"); + + function1<std::string, const char*> id2(&identity_str); + BOOST_CHECK(id2("foo") == "foo"); + + add_to_obj add_to(5); + function1<int, int> f2(add_to); + BOOST_CHECK(f2(3) == 8); + + const function1<int, int> cf2(add_to); + BOOST_CHECK(cf2(3) == 8); +} + +static void +test_two_args() +{ + function2<string, const string&, const string&> cat(&string_cat); + BOOST_CHECK(cat("str", "ing") == "string"); + + function2<int, short, short> sum(&sum_ints); + BOOST_CHECK(sum(2, 3) == 5); +} + +static void +test_emptiness() +{ + function0<float> f1; + BOOST_CHECK(f1.empty()); + + function0<float> f2; + f2 = f1; + BOOST_CHECK(f2.empty()); + + function0<double> f3; + f3 = f2; + BOOST_CHECK(f3.empty()); +} + +struct X { + X(int v) : value(v) {} + + int twice() const { return 2*value; } + int plus(int v) { return value + v; } + + int value; +}; + +static void +test_member_functions() +{ + + boost::function1<int, X*> f1(&X::twice); + + X one(1); + X five(5); + + BOOST_CHECK(f1(&one) == 2); + BOOST_CHECK(f1(&five) == 10); + + boost::function1<int, X*> f1_2; + f1_2 = &X::twice; + + BOOST_CHECK(f1_2(&one) == 2); + BOOST_CHECK(f1_2(&five) == 10); + + boost::function2<int, X&, int> f2(&X::plus); + BOOST_CHECK(f2(one, 3) == 4); + BOOST_CHECK(f2(five, 4) == 9); +} + +struct add_with_throw_on_copy { + int operator()(int x, int y) const { return x+y; } + + add_with_throw_on_copy() {} + + add_with_throw_on_copy(const add_with_throw_on_copy&) + { + throw std::runtime_error("But this CAN'T throw"); + } + + add_with_throw_on_copy& operator=(const add_with_throw_on_copy&) + { + throw std::runtime_error("But this CAN'T throw"); + } +}; + +static void +test_ref() +{ + add_with_throw_on_copy atc; + try { + boost::function2<int, int, int> f(ref(atc)); + BOOST_CHECK(f(1, 3) == 4); + } + catch(std::runtime_error const&) { + BOOST_ERROR("Nonthrowing constructor threw an exception"); + } +} + +static unsigned construction_count = 0; +static unsigned destruction_count = 0; + +struct MySmallFunctor { + MySmallFunctor() { ++construction_count; } + MySmallFunctor(const MySmallFunctor &) { ++construction_count; } + ~MySmallFunctor() { ++destruction_count; } + int operator()() { return 0; } + }; + +struct MyLargeFunctor { + MyLargeFunctor() { ++construction_count; } + MyLargeFunctor(const MyLargeFunctor &) { ++construction_count; } + ~MyLargeFunctor() { ++destruction_count; } + int operator()() { return 0; } + + float data[128]; + }; + +void test_construct_destroy_count() +{ + { + boost::function0<int> f; + boost::function0<int> g; + f = MySmallFunctor(); + g = MySmallFunctor(); + f.swap(g); + } + + // MySmallFunctor objects should be constructed as many times as + // they are destroyed. + BOOST_CHECK(construction_count == destruction_count); + + construction_count = 0; + destruction_count = 0; + { + boost::function0<int> f; + boost::function0<int> g; + f = MyLargeFunctor(); + g = MyLargeFunctor(); + f.swap(g); + } + + // MyLargeFunctor objects should be constructed as many times as + // they are destroyed. + BOOST_CHECK(construction_count == destruction_count); +} + +int main() +{ + test_zero_args(); + test_one_arg(); + test_two_args(); + test_emptiness(); + test_member_functions(); + test_ref(); + test_construct_destroy_count(); + return boost::report_errors(); +} |