summaryrefslogtreecommitdiff
path: root/indra/test/llevents_tut.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/test/llevents_tut.cpp')
-rw-r--r--indra/test/llevents_tut.cpp379
1 files changed, 83 insertions, 296 deletions
diff --git a/indra/test/llevents_tut.cpp b/indra/test/llevents_tut.cpp
index 16edab6282..17f64a4953 100644
--- a/indra/test/llevents_tut.cpp
+++ b/indra/test/llevents_tut.cpp
@@ -38,7 +38,6 @@
#define testable public
#include "llevents.h"
#undef testable
-#include "lllistenerwrapper.h"
// STL headers
// std headers
#include <iostream>
@@ -92,9 +91,7 @@ template<> template<>
void events_object::test<1>()
{
set_test_name("basic operations");
- // Now there's a static constructor in llevents.cpp that registers on
- // the "mainloop" pump to call LLEventPumps::flush().
- // Actually -- having to modify this to track the statically-
+ // Having to modify this to track the statically-
// constructed pumps in other TUT modules in this giant monolithic test
// executable isn't such a hot idea.
// ensure_equals("initial pump", pumps.mPumpMap.size(), 1);
@@ -134,17 +131,15 @@ void events_object::test<1>()
per_frame.post(4);
check_listener("re-blocked", listener0, 3);
} // unblock
- std::string threw;
- try
- {
- // NOTE: boost::bind() saves its arguments by VALUE! If you pass
- // an object instance rather than a pointer, you'll end up binding
- // to an internal copy of that instance! Use boost::ref() to
- // capture a reference instead.
- per_frame.listen(listener0.getName(), // note bug, dup name
- boost::bind(&Listener::call, boost::ref(listener1), _1));
- }
- CATCH_AND_STORE_WHAT_IN(threw, LLEventPump::DupListenerName)
+ std::string threw = catch_what<LLEventPump::DupListenerName>(
+ [&per_frame, this](){
+ // NOTE: boost::bind() saves its arguments by VALUE! If you pass
+ // an object instance rather than a pointer, you'll end up binding
+ // to an internal copy of that instance! Use boost::ref() to
+ // capture a reference instead.
+ per_frame.listen(listener0.getName(), // note bug, dup name
+ boost::bind(&Listener::call, boost::ref(listener1), _1));
+ });
ensure_equals(threw,
std::string("DupListenerName: "
"Attempt to register duplicate listener name '") +
@@ -213,43 +208,6 @@ bool chainEvents(Listener& someListener, const LLSD& event)
template<> template<>
void events_object::test<3>()
{
- set_test_name("LLEventQueue delayed action");
- // This access is NOT legal usage: we can do it only because we're
- // hacking private for test purposes. Normally we'd either compile in
- // a particular name, or (later) edit a config file.
- pumps.mQueueNames.insert("login");
- LLEventPump& login(pumps.obtain("login"));
- // The "mainloop" pump is special: posting on that implicitly calls
- // LLEventPumps::flush(), which in turn should flush our "login"
- // LLEventQueue.
- LLEventPump& mainloop(pumps.obtain("mainloop"));
- ensure("LLEventQueue leaf class", dynamic_cast<LLEventQueue*> (&login));
- listener0.listenTo(login);
- listener0.reset(0);
- login.post(1);
- check_listener("waiting for queued event", listener0, 0);
- mainloop.post(LLSD());
- check_listener("got queued event", listener0, 1);
- login.stopListening(listener0.getName());
- // Verify that when an event handler posts a new event on the same
- // LLEventQueue, it doesn't get processed in the same flush() call --
- // it waits until the next flush() call.
- listener0.reset(17);
- login.listen("chainEvents", boost::bind(chainEvents, boost::ref(listener0), _1));
- login.post(1);
- check_listener("chainEvents(1) not yet called", listener0, 17);
- mainloop.post(LLSD());
- check_listener("chainEvents(1) called", listener0, 1);
- mainloop.post(LLSD());
- check_listener("chainEvents(0) called", listener0, 0);
- mainloop.post(LLSD());
- check_listener("chainEvents(-1) not called", listener0, 0);
- login.stopListening("chainEvents");
-}
-
-template<> template<>
-void events_object::test<4>()
-{
set_test_name("explicitly-instantiated LLEventStream");
// Explicitly instantiate an LLEventStream, and verify that it
// self-registers with LLEventPumps
@@ -273,7 +231,7 @@ void events_object::test<4>()
}
template<> template<>
-void events_object::test<5>()
+void events_object::test<4>()
{
set_test_name("stopListening()");
LLEventPump& login(pumps.obtain("login"));
@@ -287,7 +245,7 @@ void events_object::test<5>()
}
template<> template<>
-void events_object::test<6>()
+void events_object::test<5>()
{
set_test_name("chaining LLEventPump instances");
LLEventPump& upstream(pumps.obtain("upstream"));
@@ -312,7 +270,7 @@ void events_object::test<6>()
}
template<> template<>
-void events_object::test<7>()
+void events_object::test<6>()
{
set_test_name("listener dependency order");
typedef LLEventPump::NameList NameList;
@@ -341,15 +299,13 @@ void events_object::test<7>()
ensure_equals(collector.result, make<StringVec>(list_of("Mary")("spot")("checked")));
collector.clear();
button.stopListening("spot");
- std::string threw;
- try
- {
- button.listen("spot",
- boost::bind(&Collect::add, boost::ref(collector), "spot", _1),
- // after "Mary" and "checked" -- whoops!
- make<NameList>(list_of("Mary")("checked")));
- }
- CATCH_AND_STORE_WHAT_IN(threw, LLEventPump::Cycle)
+ std::string threw = catch_what<LLEventPump::Cycle>(
+ [&button, &collector](){
+ button.listen("spot",
+ boost::bind(&Collect::add, boost::ref(collector), "spot", _1),
+ // after "Mary" and "checked" -- whoops!
+ make<NameList>(list_of("Mary")("checked")));
+ });
// Obviously the specific wording of the exception text can
// change; go ahead and change the test to match.
// Establish that it contains:
@@ -374,15 +330,13 @@ void events_object::test<7>()
button.post(3);
ensure_equals(collector.result, make<StringVec>(list_of("Mary")("checked")("yellow")("shoelaces")));
collector.clear();
- threw.clear();
- try
- {
- button.listen("of",
- boost::bind(&Collect::add, boost::ref(collector), "of", _1),
- make<NameList>(list_of("shoelaces")),
- make<NameList>(list_of("yellow")));
- }
- CATCH_AND_STORE_WHAT_IN(threw, LLEventPump::OrderChange)
+ threw = catch_what<LLEventPump::OrderChange>(
+ [&button, &collector](){
+ button.listen("of",
+ boost::bind(&Collect::add, boost::ref(collector), "of", _1),
+ make<NameList>(list_of("shoelaces")),
+ make<NameList>(list_of("yellow")));
+ });
// Same remarks about the specific wording of the exception. Just
// ensure that it contains enough information to clarify the
// problem and what must be done to resolve it.
@@ -398,19 +352,17 @@ void events_object::test<7>()
}
template<> template<>
-void events_object::test<8>()
+void events_object::test<7>()
{
set_test_name("tweaked and untweaked LLEventPump instance names");
{ // nested scope
// Hand-instantiate an LLEventStream...
LLEventStream bob("bob");
- std::string threw;
- try
- {
- // then another with a duplicate name.
- LLEventStream bob2("bob");
- }
- CATCH_AND_STORE_WHAT_IN(threw, LLEventPump::DupPumpName)
+ std::string threw = catch_what<LLEventPump::DupPumpName>(
+ [](){
+ // then another with a duplicate name.
+ LLEventStream bob2("bob");
+ });
ensure("Caught DupPumpName", !threw.empty());
} // delete first 'bob'
LLEventStream bob("bob"); // should work, previous one unregistered
@@ -432,7 +384,7 @@ void eventSource(const LLListenerOrPumpName& listener)
}
template<> template<>
-void events_object::test<9>()
+void events_object::test<8>()
{
set_test_name("LLListenerOrPumpName");
// Passing a boost::bind() expression to LLListenerOrPumpName
@@ -445,13 +397,11 @@ void events_object::test<9>()
listener0.listenTo(random);
eventSource("random");
check_listener("got by pump name", listener0, 17);
- std::string threw;
- try
- {
- LLListenerOrPumpName empty;
- empty(17);
- }
- CATCH_AND_STORE_WHAT_IN(threw, LLListenerOrPumpName::Empty)
+ std::string threw = catch_what<LLListenerOrPumpName::Empty>(
+ [](){
+ LLListenerOrPumpName empty;
+ empty(17);
+ });
ensure("threw Empty", !threw.empty());
}
@@ -475,7 +425,7 @@ private:
};
template<> template<>
-void events_object::test<10>()
+void events_object::test<9>()
{
set_test_name("listen(boost::bind(...TempListener...))");
// listen() can't do anything about a plain TempListener instance:
@@ -503,223 +453,60 @@ void events_object::test<10>()
heaptest.stopListening("temp");
}
-template<> template<>
-void events_object::test<11>()
-{
- set_test_name("listen(boost::bind(...weak_ptr...))");
- // listen() detecting weak_ptr<TempListener> in boost::bind() object
- bool live = false;
- LLEventPump& heaptest(pumps.obtain("heaptest"));
- LLBoundListener connection;
- ensure("default state", !connection.connected());
- {
- boost::shared_ptr<TempListener> newListener(new TempListener("heap", live));
- newListener->reset();
- ensure("TempListener constructed", live);
- connection = heaptest.listen(newListener->getName(),
- boost::bind(&Listener::call,
- weaken(newListener),
- _1));
- ensure("new connection", connection.connected());
- heaptest.post(1);
- check_listener("received", *newListener, 1);
- } // presumably this will make newListener go away?
- // verify that
- ensure("TempListener destroyed", !live);
- ensure("implicit disconnect", !connection.connected());
- // now just make sure we don't blow up trying to access a freed object!
- heaptest.post(2);
-}
-
-template<> template<>
-void events_object::test<12>()
-{
- set_test_name("listen(boost::bind(...shared_ptr...))");
- /*==========================================================================*|
- // DISABLED because I've made this case produce a compile error.
- // Following the error leads the disappointed dev to a comment
- // instructing her to use the weaken() function to bind a weak_ptr<T>
- // instead of binding a shared_ptr<T>, and explaining why. I know of
- // no way to use TUT to code a repeatable test in which the expected
- // outcome is a compile error. The interested reader is invited to
- // uncomment this block and build to see for herself.
-
- // listen() detecting shared_ptr<TempListener> in boost::bind() object
- bool live = false;
- LLEventPump& heaptest(pumps.obtain("heaptest"));
- LLBoundListener connection;
- std::string listenerName("heap");
- ensure("default state", !connection.connected());
- {
- boost::shared_ptr<TempListener> newListener(new TempListener(listenerName, live));
- ensure_equals("use_count", newListener.use_count(), 1);
- newListener->reset();
- ensure("TempListener constructed", live);
- connection = heaptest.listen(newListener->getName(),
- boost::bind(&Listener::call, newListener, _1));
- ensure("new connection", connection.connected());
- ensure_equals("use_count", newListener.use_count(), 2);
- heaptest.post(1);
- check_listener("received", *newListener, 1);
- } // this should make newListener go away...
- // Unfortunately, the fact that we've bound a shared_ptr by value into
- // our LLEventPump means that copy will keep the referenced object alive.
- ensure("TempListener still alive", live);
- ensure("still connected", connection.connected());
- // disconnecting explicitly should delete the TempListener...
- heaptest.stopListening(listenerName);
-#if 0 // however, in my experience, it does not. I don't know why not.
- // Ah: on 2009-02-19, Frank Mori Hess, author of the Boost.Signals2
- // library, stated on the boost-users mailing list:
- // http://www.nabble.com/Re%3A--signals2--review--The-review-of-the-signals2-library-(formerly-thread_safe_signals)-begins-today%2C-Nov-1st-p22102367.html
- // "It will get destroyed eventually. The signal cleans up its slot
- // list little by little during connect/invoke. It doesn't immediately
- // remove disconnected slots from the slot list since other threads
- // might be using the same slot list concurrently. It might be
- // possible to make it immediately reset the shared_ptr owning the
- // slot though, leaving an empty shared_ptr in the slot list, since
- // that wouldn't invalidate any iterators."
- ensure("TempListener destroyed", ! live);
- ensure("implicit disconnect", ! connection.connected());
-#endif // 0
- // now just make sure we don't blow up trying to access a freed object!
- heaptest.post(2);
-|*==========================================================================*/
-}
-
class TempTrackableListener: public TempListener, public LLEventTrackable
{
public:
-TempTrackableListener(const std::string& name, bool& liveFlag):
- TempListener(name, liveFlag)
-{}
+ TempTrackableListener(const std::string& name, bool& liveFlag):
+ TempListener(name, liveFlag)
+ {}
};
template<> template<>
-void events_object::test<13>()
-{
-set_test_name("listen(boost::bind(...TempTrackableListener ref...))");
-bool live = false;
-LLEventPump& heaptest(pumps.obtain("heaptest"));
-LLBoundListener connection;
-{
- TempTrackableListener tempListener("temp", live);
- ensure("TempTrackableListener constructed", live);
- connection = heaptest.listen(tempListener.getName(),
- boost::bind(&TempTrackableListener::call,
- boost::ref(tempListener), _1));
- heaptest.post(1);
- check_listener("received", tempListener, 1);
-} // presumably this will make tempListener go away?
-// verify that
-ensure("TempTrackableListener destroyed", ! live);
-ensure("implicit disconnect", ! connection.connected());
-// now just make sure we don't blow up trying to access a freed object!
-heaptest.post(2);
-}
-
-template<> template<>
-void events_object::test<14>()
-{
-set_test_name("listen(boost::bind(...TempTrackableListener pointer...))");
-bool live = false;
-LLEventPump& heaptest(pumps.obtain("heaptest"));
-LLBoundListener connection;
+void events_object::test<10>()
{
- TempTrackableListener* newListener(new TempTrackableListener("temp", live));
- ensure("TempTrackableListener constructed", live);
- connection = heaptest.listen(newListener->getName(),
- boost::bind(&TempTrackableListener::call,
- newListener, _1));
- heaptest.post(1);
- check_listener("received", *newListener, 1);
- // explicitly destroy newListener
- delete newListener;
-}
-// verify that
-ensure("TempTrackableListener destroyed", ! live);
-ensure("implicit disconnect", ! connection.connected());
-// now just make sure we don't blow up trying to access a freed object!
-heaptest.post(2);
+ set_test_name("listen(boost::bind(...TempTrackableListener ref...))");
+ bool live = false;
+ LLEventPump& heaptest(pumps.obtain("heaptest"));
+ LLBoundListener connection;
+ {
+ TempTrackableListener tempListener("temp", live);
+ ensure("TempTrackableListener constructed", live);
+ connection = heaptest.listen(tempListener.getName(),
+ boost::bind(&TempTrackableListener::call,
+ boost::ref(tempListener), _1));
+ heaptest.post(1);
+ check_listener("received", tempListener, 1);
+ } // presumably this will make tempListener go away?
+ // verify that
+ ensure("TempTrackableListener destroyed", ! live);
+ ensure("implicit disconnect", ! connection.connected());
+ // now just make sure we don't blow up trying to access a freed object!
+ heaptest.post(2);
}
template<> template<>
-void events_object::test<15>()
-{
-// This test ensures that using an LLListenerWrapper subclass doesn't
-// block Boost.Signals2 from recognizing a bound LLEventTrackable
-// subclass.
-set_test_name("listen(llwrap<LLLogListener>(boost::bind(...TempTrackableListener ref...)))");
-bool live = false;
-LLEventPump& heaptest(pumps.obtain("heaptest"));
-LLBoundListener connection;
+void events_object::test<11>()
{
- TempTrackableListener tempListener("temp", live);
- ensure("TempTrackableListener constructed", live);
- connection = heaptest.listen(tempListener.getName(),
- llwrap<LLLogListener>(
- boost::bind(&TempTrackableListener::call,
- boost::ref(tempListener), _1)));
- heaptest.post(1);
- check_listener("received", tempListener, 1);
-} // presumably this will make tempListener go away?
-// verify that
-ensure("TempTrackableListener destroyed", ! live);
-ensure("implicit disconnect", ! connection.connected());
-// now just make sure we don't blow up trying to access a freed object!
-heaptest.post(2);
+ set_test_name("listen(boost::bind(...TempTrackableListener pointer...))");
+ bool live = false;
+ LLEventPump& heaptest(pumps.obtain("heaptest"));
+ LLBoundListener connection;
+ {
+ TempTrackableListener* newListener(new TempTrackableListener("temp", live));
+ ensure("TempTrackableListener constructed", live);
+ connection = heaptest.listen(newListener->getName(),
+ boost::bind(&TempTrackableListener::call,
+ newListener, _1));
+ heaptest.post(1);
+ check_listener("received", *newListener, 1);
+ // explicitly destroy newListener
+ delete newListener;
+ }
+ // verify that
+ ensure("TempTrackableListener destroyed", ! live);
+ ensure("implicit disconnect", ! connection.connected());
+ // now just make sure we don't blow up trying to access a freed object!
+ heaptest.post(2);
}
-class TempSharedListener: public TempListener,
-public boost::enable_shared_from_this<TempSharedListener>
-{
-public:
-TempSharedListener(const std::string& name, bool& liveFlag):
- TempListener(name, liveFlag)
-{}
-};
-
-template<> template<>
-void events_object::test<16>()
-{
- set_test_name("listen(boost::bind(...TempSharedListener ref...))");
-#if 0
-bool live = false;
-LLEventPump& heaptest(pumps.obtain("heaptest"));
-LLBoundListener connection;
-{
- // We MUST have at least one shared_ptr to an
- // enable_shared_from_this subclass object before
- // shared_from_this() can work.
- boost::shared_ptr<TempSharedListener>
- tempListener(new TempSharedListener("temp", live));
- ensure("TempSharedListener constructed", live);
- // However, we're not passing either the shared_ptr or its
- // corresponding weak_ptr -- instead, we're passing a reference to
- // the TempSharedListener.
-/*==========================================================================*|
- std::cout << "Capturing const ref" << std::endl;
- const boost::enable_shared_from_this<TempSharedListener>& cref(*tempListener);
- std::cout << "Capturing const ptr" << std::endl;
- const boost::enable_shared_from_this<TempSharedListener>* cp(&cref);
- std::cout << "Capturing non-const ptr" << std::endl;
- boost::enable_shared_from_this<TempSharedListener>* p(const_cast<boost::enable_shared_from_this<TempSharedListener>*>(cp));
- std::cout << "Capturing shared_from_this()" << std::endl;
- boost::shared_ptr<TempSharedListener> sp(p->shared_from_this());
- std::cout << "Capturing weak_ptr" << std::endl;
- boost::weak_ptr<TempSharedListener> wp(weaken(sp));
- std::cout << "Binding weak_ptr" << std::endl;
-|*==========================================================================*/
- connection = heaptest.listen(tempListener->getName(),
- boost::bind(&TempSharedListener::call, *tempListener, _1));
- heaptest.post(1);
- check_listener("received", *tempListener, 1);
-} // presumably this will make tempListener go away?
-// verify that
-ensure("TempSharedListener destroyed", ! live);
-ensure("implicit disconnect", ! connection.connected());
-// now just make sure we don't blow up trying to access a freed object!
-heaptest.post(2);
-#endif // 0
-}
} // namespace tut