RTBKit  0.9
Open-source framework to create real-time ad bidding systems.
soa/sigslot/testing/signal_test.cc
00001 /* signal_test.cc
00002    Jeremy Barnes, 16 November 2010
00003    Copyright (c) 2010 Datacratic.  All rights reserved.
00004 
00005    Test of the signal functionality.
00006 */
00007 
00008 
00009 #define BOOST_TEST_MAIN
00010 #define BOOST_TEST_DYN_LINK
00011 
00012 #include <boost/test/unit_test.hpp>
00013 #include <iostream>
00014 #include "jml/arch/exception_handler.h"
00015 #include "jml/utils/vector_utils.h"
00016 #include "jml/utils/string_functions.h"
00017 
00018 #include "soa/sigslot/signal.h"
00019 #include "soa/sigslot/slot_impl_js.h"
00020 
00021 #include "soa/js/js_call.h"
00022 
00023 using namespace std;
00024 using namespace ML;
00025 using namespace Datacratic;
00026 
00027 
00028 struct ThingWithSignals {
00029 
00030     virtual ~ThingWithSignals()
00031     {
00032     }
00033 
00034     typedef void (Event1) (const std::string &);
00035 
00036     SlotDisconnector onEvent1(const boost::function<Event1> & fn,
00037                               int priority = 0)
00038     {
00039         return event1.connect(priority, fn);
00040     }
00041 
00042     boost::signals2::signal<Event1> event1;
00043 
00044     typedef void (Event2) (int i);
00045 
00046     virtual SlotDisconnector onEvent2(const boost::function<Event2> & fn,
00047                                       int priority = 0)
00048     {
00049         return event2.connect(priority, fn);
00050     }
00051     
00052     boost::signals2::signal<Event2> event2;
00053 
00054     static void addSignals()
00055     {
00056         signals.add<Event1, &ThingWithSignals::onEvent1>("event1");
00057         signals.add<Event2, &ThingWithSignals::onEvent2>("event2");
00058     }
00059 
00060     void on(const std::string & event, const Slot & slot, int priority = 0)
00061     {
00062         signals.on(event, this, slot, priority);
00063     }
00064 
00065     template<typename Fn, typename Fn2>
00066     void on(const std::string & event, const boost::function<Fn2> & fn,
00067             int priority = 0)
00068     {
00069         Slot n = Slot::fromF<Fn>(fn);
00070         on(event, n, priority);
00071     }
00072 
00073     template<typename Fn, typename Fn2>
00074     void on(const std::string & event, Fn2 fn, int priority = 0)
00075     {
00076         Slot n = Slot::fromF<Fn>(fn);
00077         on(event, n, priority);
00078     }
00079 
00080     static SignalRegistry<ThingWithSignals> signals;
00081     static DoRegisterSignals reg;
00082 };
00083 
00084 RegisterJsOps<ThingWithSignals::Event1> reg1;
00085 RegisterJsOps<ThingWithSignals::Event2> reg2;
00086 
00087 SignalRegistry<ThingWithSignals> ThingWithSignals::signals;
00088 DoRegisterSignals ThingWithSignals::reg(addSignals);
00089 
00090 
00091 BOOST_AUTO_TEST_CASE( test_signal_object )
00092 {
00093 
00094     using namespace v8;
00095 
00096     ThingWithSignals thing;
00097 
00098     BOOST_CHECK_EQUAL(thing.signals.size(), 2);
00099 
00100     vector<string> strs;
00101 
00102     auto fn = [&] (const std::string & str) { strs.push_back(str); }; 
00103     boost::function<void (const std::string &)> fn_ = fn;
00104     
00105     thing.on<void (const std::string &)>("event1", fn);
00106     thing.on<void (const std::string &)>("event1", fn_);
00107     
00108     thing.event1("hello");
00109 
00110     BOOST_CHECK_EQUAL(strs, vector<string>({"hello", "hello"}));
00111 
00112     int total = 0;
00113 
00114     auto fn2 = [&] (int i) { total += i; };
00115 
00116     thing.on<void (int i)>("event2", fn2);
00117 
00118     thing.event2(6);
00119 
00120     BOOST_CHECK_EQUAL(total, 6);
00121     
00122     {
00123         // Check that adding the wrong callback type throws
00124         JML_TRACE_EXCEPTIONS(false);
00125         BOOST_CHECK_THROW(thing.on<void (int i)>("event1", fn2), ML::Exception);
00126     }
00127 }
00128 
00129 struct DerivedThingWithSignals : public ThingWithSignals {
00130 
00131     virtual ~DerivedThingWithSignals()
00132     {
00133     }
00134 
00135     typedef void (Event3) (int i, const std::string & s);
00136 
00137     boost::signals2::signal<Event3> event3;
00138 
00139     SlotDisconnector onEvent3(const boost::function<Event3> & fn,
00140                               int priority = 0)
00141     {
00142         return event3.connect(priority, fn);
00143     }
00144 
00145     static void addSignals()
00146     {
00147         signals.inheritSignals(ThingWithSignals::signals);
00148         signals.add<Event3, &DerivedThingWithSignals::onEvent3>("event3");
00149     }
00150 
00151     void on(const std::string & event, const Slot & slot)
00152     {
00153         signals.on(event, this, slot);
00154     }
00155 
00156     template<typename Fn, typename Fn2>
00157     void on(const std::string & event, const boost::function<Fn2> & fn)
00158     {
00159         Slot n = Slot::fromF<Fn>(fn);
00160         on(event, n);
00161     }
00162 
00163     template<typename Fn, typename Fn2>
00164     void on(const std::string & event, Fn2 fn)
00165     {
00166         Slot n = Slot::fromF<Fn>(fn);
00167         on(event, n);
00168     }
00169 
00170     static SignalRegistry<DerivedThingWithSignals> signals;
00171     static DoRegisterSignals reg;
00172 };
00173 
00174 SignalRegistry<DerivedThingWithSignals> DerivedThingWithSignals::signals;
00175 DoRegisterSignals DerivedThingWithSignals::reg(addSignals);
00176 
00177 RegisterJsOps<DerivedThingWithSignals::Event3> reg3;
00178 
00179 BOOST_AUTO_TEST_CASE( test_signal_derived_object )
00180 {
00181 
00182     using namespace v8;
00183 
00184     DerivedThingWithSignals thing;
00185 
00186     BOOST_CHECK_EQUAL(thing.signals.size(), 3);
00187 
00188     vector<string> strs;
00189 
00190     auto fn = [&] (const std::string & str) { strs.push_back(str); }; 
00191     boost::function<void (const std::string &)> fn_ = fn;
00192     
00193     thing.on<void (const std::string &)>("event1", fn);
00194     thing.on<void (const std::string &)>("event1", fn_);
00195     
00196     thing.event1("hello");
00197 
00198     BOOST_CHECK_EQUAL(strs, vector<string>({"hello", "hello"}));
00199 
00200     int total = 0;
00201 
00202     auto fn2 = [&] (int i) { total += i; };
00203 
00204     thing.on<void (int i)>("event2", fn2);
00205 
00206     thing.event2(6);
00207 
00208     BOOST_CHECK_EQUAL(total, 6);
00209     
00210     {
00211         // Check that adding the wrong callback type throws
00212         JML_TRACE_EXCEPTIONS(false);
00213         BOOST_CHECK_THROW(thing.on<void (int i)>("event1", fn2), ML::Exception);
00214     }
00215 
00216     string str;
00217 
00218     auto fn3 = [&] (int i, string s)
00219         { str += ML::format("%s%i", s.c_str(), i); };
00220 
00221     thing.on<void (int, const std::string &)>("event3", fn3);
00222 
00223     thing.event3(4, "hello");
00224 
00225     BOOST_CHECK_EQUAL(str, "hello4");
00226 }
00227 
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator