summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/signals2/test/signal_n_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/signals2/test/signal_n_test.cpp')
-rw-r--r--src/boost/libs/signals2/test/signal_n_test.cpp352
1 files changed, 352 insertions, 0 deletions
diff --git a/src/boost/libs/signals2/test/signal_n_test.cpp b/src/boost/libs/signals2/test/signal_n_test.cpp
new file mode 100644
index 000000000..c1c2b4027
--- /dev/null
+++ b/src/boost/libs/signals2/test/signal_n_test.cpp
@@ -0,0 +1,352 @@
+// Boost.Signals 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/bind/bind.hpp>
+#include <boost/config.hpp>
+#define BOOST_TEST_MODULE signal_n_test
+#include <boost/test/included/unit_test.hpp>
+
+using namespace boost::placeholders;
+
+#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES
+BOOST_AUTO_TEST_CASE(test_main)
+{
+}
+#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
+#include <boost/optional.hpp>
+#include <boost/ref.hpp>
+#include <boost/signals2.hpp>
+#include <functional>
+
+template<typename T>
+struct max_or_default {
+ typedef T result_type;
+ template<typename InputIterator>
+ typename InputIterator::value_type
+ operator()(InputIterator first, InputIterator last) const
+ {
+ boost::optional<T> max;
+ for (; first != last; ++first)
+ {
+ try
+ {
+ if(!max) max = *first;
+ else max = (*first > max.get())? *first : max;
+ }
+ catch(const boost::bad_weak_ptr &)
+ {}
+ }
+ if(max) return max.get();
+ return T();
+ }
+};
+
+struct make_int {
+ make_int(int n, int cn) : N(n), CN(n) {}
+ int operator()() { return N; }
+ int operator()() const { return CN; }
+
+ int N;
+ int CN;
+};
+
+template<int N>
+struct make_increasing_int {
+ make_increasing_int() : n(N) {}
+
+ int operator()() const { return n++; }
+
+ mutable int n;
+};
+
+int get_37() { return 37; }
+
+static void
+test_zero_args()
+{
+ make_int i42(42, 41);
+ make_int i2(2, 1);
+ make_int i72(72, 71);
+ make_int i63(63, 63);
+ make_int i62(62, 61);
+
+ {
+ boost::signals2::signal0<int, max_or_default<int>, std::string> s0;
+ boost::signals2::connection c2 = s0.connect(i2);
+ boost::signals2::connection c72 = s0.connect("72", i72);
+ boost::signals2::connection c62 = s0.connect("6x", i62);
+ boost::signals2::connection c42 = s0.connect(i42);
+ boost::signals2::connection c37 = s0.connect(&get_37);
+
+ BOOST_CHECK(s0() == 72);
+
+ s0.disconnect("72");
+ BOOST_CHECK(s0() == 62);
+
+ c72.disconnect(); // Double-disconnect should be safe
+ BOOST_CHECK(s0() == 62);
+
+ s0.disconnect("72"); // Triple-disconect should be safe
+ BOOST_CHECK(s0() == 62);
+
+ // Also connect 63 in the same group as 62
+ s0.connect("6x", i63);
+ BOOST_CHECK(s0() == 63);
+
+ // Disconnect all of the 60's
+ s0.disconnect("6x");
+ BOOST_CHECK(s0() == 42);
+
+ c42.disconnect();
+ BOOST_CHECK(s0() == 37);
+
+ c37.disconnect();
+ BOOST_CHECK(s0() == 2);
+
+ c2.disconnect();
+ BOOST_CHECK(s0() == 0);
+ }
+
+ {
+ boost::signals2::signal0<int, max_or_default<int> > s0;
+ boost::signals2::connection c2 = s0.connect(i2);
+ boost::signals2::connection c72 = s0.connect(i72);
+ boost::signals2::connection c62 = s0.connect(i62);
+ boost::signals2::connection c42 = s0.connect(i42);
+
+ const boost::signals2::signal0<int, max_or_default<int> >& cs0 = s0;
+ BOOST_CHECK(cs0() == 72);
+ }
+
+ {
+ make_increasing_int<7> i7;
+ make_increasing_int<10> i10;
+
+ boost::signals2::signal0<int, max_or_default<int> > s0;
+ boost::signals2::connection c7 = s0.connect(i7);
+ boost::signals2::connection c10 = s0.connect(i10);
+
+ BOOST_CHECK(s0() == 10);
+ BOOST_CHECK(s0() == 11);
+ }
+}
+
+static void
+test_one_arg()
+{
+ boost::signals2::signal1<int, int, max_or_default<int> > s1;
+
+ s1.connect(std::negate<int>());
+ s1.connect(boost::bind(std::multiplies<int>(), 2, _1));
+
+ BOOST_CHECK(s1(1) == 2);
+ BOOST_CHECK(s1(-1) == 1);
+}
+
+static void
+test_signal_signal_connect()
+{
+ typedef boost::signals2::signal1<int, int, max_or_default<int> > signal_type;
+ signal_type s1;
+
+ s1.connect(std::negate<int>());
+
+ BOOST_CHECK(s1(3) == -3);
+
+ {
+ signal_type s2;
+ s1.connect(s2);
+ s2.connect(boost::bind(std::multiplies<int>(), 2, _1));
+ s2.connect(boost::bind(std::multiplies<int>(), -3, _1));
+
+ BOOST_CHECK(s2(-3) == 9);
+ BOOST_CHECK(s1(3) == 6);
+ } // s2 goes out of scope and disconnects
+
+ BOOST_CHECK(s1(3) == -3);
+
+ // test auto-track of signal wrapped in a reference_wrapper
+ {
+ signal_type s2;
+ s1.connect(boost::cref(s2));
+ s2.connect(boost::bind(std::multiplies<int>(), 2, _1));
+ s2.connect(boost::bind(std::multiplies<int>(), -3, _1));
+
+ BOOST_CHECK(s2(-3) == 9);
+ BOOST_CHECK(s1(3) == 6);
+ } // s2 goes out of scope and disconnects
+
+ BOOST_CHECK(s1(3) == -3);
+}
+
+struct EventCounter
+{
+ EventCounter() : count(0) {}
+
+ void operator()()
+ {
+ ++count;
+ }
+
+ int count;
+};
+
+static void
+test_ref()
+{
+ EventCounter ec;
+ boost::signals2::signal0<void> s;
+
+ {
+ boost::signals2::scoped_connection c(s.connect(boost::ref(ec)));
+ BOOST_CHECK(ec.count == 0);
+ s();
+ BOOST_CHECK(ec.count == 1);
+ }
+ s();
+ BOOST_CHECK(ec.count == 1);
+}
+
+static void test_default_combiner()
+{
+ boost::signals2::signal0<int> sig;
+ boost::optional<int> result;
+ result = sig();
+ BOOST_CHECK(!result);
+
+ sig.connect(make_int(0, 0));
+ result = sig();
+ BOOST_CHECK(result);
+ BOOST_CHECK(*result == 0);
+
+ sig.connect(make_int(1, 1));
+ result = sig();
+ BOOST_CHECK(result);
+ BOOST_CHECK(*result == 1);
+}
+
+template<typename ResultType>
+ ResultType disconnecting_slot(const boost::signals2::connection &conn, int)
+{
+ conn.disconnect();
+ return ResultType();
+}
+
+#ifdef BOOST_NO_VOID_RETURNS
+template<>
+ void disconnecting_slot<void>(const boost::signals2::connection &conn, int)
+{
+ conn.disconnect();
+ return;
+}
+#endif
+
+template<typename ResultType>
+ void test_extended_slot()
+{
+ {
+ typedef boost::signals2::signal1<ResultType, int> signal_type;
+ typedef typename signal_type::extended_slot_type slot_type;
+ signal_type sig;
+ // attempting to work around msvc 7.1 bug by explicitly assigning to a function pointer
+ ResultType (*fp)(const boost::signals2::connection &conn, int) = &disconnecting_slot<ResultType>;
+ slot_type myslot(fp);
+ sig.connect_extended(myslot);
+ BOOST_CHECK(sig.num_slots() == 1);
+ sig(0);
+ BOOST_CHECK(sig.num_slots() == 0);
+ }
+ { // test 0 arg signal
+ typedef boost::signals2::signal0<ResultType> signal_type;
+ typedef typename signal_type::extended_slot_type slot_type;
+ signal_type sig;
+ // attempting to work around msvc 7.1 bug by explicitly assigning to a function pointer
+ ResultType (*fp)(const boost::signals2::connection &conn, int) = &disconnecting_slot<ResultType>;
+ slot_type myslot(fp, _1, 0);
+ sig.connect_extended(myslot);
+ BOOST_CHECK(sig.num_slots() == 1);
+ sig();
+ BOOST_CHECK(sig.num_slots() == 0);
+ }
+ // test disconnection by slot
+ {
+ typedef boost::signals2::signal1<ResultType, int> signal_type;
+ typedef typename signal_type::extended_slot_type slot_type;
+ signal_type sig;
+ // attempting to work around msvc 7.1 bug by explicitly assigning to a function pointer
+ ResultType (*fp)(const boost::signals2::connection &conn, int) = &disconnecting_slot<ResultType>;
+ slot_type myslot(fp);
+ sig.connect_extended(myslot);
+ BOOST_CHECK(sig.num_slots() == 1);
+ sig.disconnect(fp);
+ BOOST_CHECK(sig.num_slots() == 0);
+ }
+}
+class dummy_combiner
+{
+public:
+ typedef int result_type;
+
+ dummy_combiner(result_type return_value): _return_value(return_value)
+ {}
+ template<typename SlotIterator>
+ result_type operator()(SlotIterator, SlotIterator)
+ {
+ return _return_value;
+ }
+private:
+ result_type _return_value;
+};
+
+static void
+test_set_combiner()
+{
+ typedef boost::signals2::signal0<int, dummy_combiner> signal_type;
+ signal_type sig(dummy_combiner(0));
+ BOOST_CHECK(sig() == 0);
+ BOOST_CHECK(sig.combiner()(0,0) == 0);
+ sig.set_combiner(dummy_combiner(1));
+ BOOST_CHECK(sig() == 1);
+ BOOST_CHECK(sig.combiner()(0,0) == 1);
+}
+
+static void
+test_swap()
+{
+ typedef boost::signals2::signal0<int, dummy_combiner> signal_type;
+ signal_type sig1(dummy_combiner(1));
+ BOOST_CHECK(sig1() == 1);
+ signal_type sig2(dummy_combiner(2));
+ BOOST_CHECK(sig2() == 2);
+
+ sig1.swap(sig2);
+ BOOST_CHECK(sig1() == 2);
+ BOOST_CHECK(sig2() == 1);
+
+ using std::swap;
+ swap(sig1, sig2);
+ BOOST_CHECK(sig1() == 1);
+ BOOST_CHECK(sig2() == 2);
+}
+
+BOOST_AUTO_TEST_CASE(test_main)
+{
+ test_zero_args();
+ test_one_arg();
+ test_signal_signal_connect();
+ test_ref();
+ test_default_combiner();
+ test_extended_slot<void>();
+ test_extended_slot<int>();
+ test_set_combiner();
+ test_swap();
+}
+
+#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES