![]() |
RTBKit
0.9
Open-source framework to create real-time ad bidding systems.
|
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