diff options
Diffstat (limited to 'indra/test/llevents_tut.cpp')
-rw-r--r-- | indra/test/llevents_tut.cpp | 646 |
1 files changed, 323 insertions, 323 deletions
diff --git a/indra/test/llevents_tut.cpp b/indra/test/llevents_tut.cpp index a38de71e48..875ca9ad89 100644 --- a/indra/test/llevents_tut.cpp +++ b/indra/test/llevents_tut.cpp @@ -3,25 +3,25 @@ * @author Nat Goodspeed * @date 2008-09-12 * @brief Test of llevents.h - * + * * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -57,7 +57,7 @@ using boost::assign::list_of; template<typename T> T make(const T& value) { - return value; + return value; } /***************************************************************************** @@ -67,21 +67,21 @@ namespace tut { struct events_data { - events_data() : - pumps(LLEventPumps::instance()), - listener0("first"), - listener1("second") - { - } - LLEventPumps& pumps; - Listener listener0; - Listener listener1; + events_data() : + pumps(LLEventPumps::instance()), + listener0("first"), + listener1("second") + { + } + LLEventPumps& pumps; + Listener listener0; + Listener listener1; - void check_listener(const std::string& desc, const Listener& listener, LLSD::Integer got) - { - ensure_equals(STRINGIZE(listener << ' ' << desc), - listener.getLastEvent().asInteger(), got); - } + void check_listener(const std::string& desc, const Listener& listener, LLSD::Integer got) + { + ensure_equals(STRINGIZE(listener << ' ' << desc), + listener.getLastEvent().asInteger(), got); + } }; typedef test_group<events_data> events_group; typedef events_group::object events_object; @@ -90,367 +90,367 @@ tut::events_group evgr("events"); template<> template<> void events_object::test<1>() { - set_test_name("basic operations"); - // 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); - size_t initial_pumps(pumps.mPumpMap.size()); - LLEventPump& per_frame(pumps.obtain("per-frame")); - ensure_equals("first explicit pump", pumps.mPumpMap.size(), initial_pumps + 1); - // Verify that per_frame was instantiated as an LLEventStream. - ensure("LLEventStream leaf class", dynamic_cast<LLEventStream*> (&per_frame)); - ensure("enabled", per_frame.enabled()); - // Trivial test, but posting an event to an EventPump with no - // listeners should not blow up. The test is relevant because defining - // a boost::signal with a non-void return signature, using the default - // combiner, blows up if there are no listeners. This is because the - // default combiner is defined to return the value returned by the - // last listener, which is meaningless if there were no listeners. - per_frame.post(0); - LLBoundListener connection = listener0.listenTo(per_frame); - ensure("connected", connection.connected()); - ensure("not blocked", !connection.blocked()); - per_frame.post(1); - check_listener("received", listener0, 1); - { // block the connection - LLEventPump::Blocker block(connection); - ensure("blocked", connection.blocked()); - per_frame.post(2); - check_listener("not updated", listener0, 1); - } // unblock - ensure("unblocked", !connection.blocked()); - per_frame.post(3); - check_listener("unblocked", listener0, 3); - LLBoundListener sameConnection = per_frame.getListener(listener0.getName()); - ensure("still connected", sameConnection.connected()); - ensure("still not blocked", !sameConnection.blocked()); - { // block it again - LLEventPump::Blocker block(sameConnection); - ensure("re-blocked", sameConnection.blocked()); - per_frame.post(4); - check_listener("re-blocked", listener0, 3); - } // unblock - 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 '") + - listener0.getName() + "' on " + typeid(per_frame).name() + - " '" + per_frame.getName() + "'"); - // do it right this time - listener1.listenTo(per_frame); - per_frame.post(5); - check_listener("got", listener0, 5); - check_listener("got", listener1, 5); - per_frame.enable(false); - per_frame.post(6); - check_listener("didn't get", listener0, 5); - check_listener("didn't get", listener1, 5); - per_frame.enable(); - per_frame.post(7); - check_listener("got", listener0, 7); - check_listener("got", listener1, 7); - per_frame.stopListening(listener0.getName()); - ensure("disconnected 0", ! connection.connected()); - ensure("disconnected 1", ! sameConnection.connected()); - per_frame.post(8); - check_listener("disconnected", listener0, 7); - check_listener("still connected", listener1, 8); - per_frame.stopListening(listener1.getName()); - per_frame.post(9); - check_listener("disconnected", listener1, 8); + set_test_name("basic operations"); + // 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); + size_t initial_pumps(pumps.mPumpMap.size()); + LLEventPump& per_frame(pumps.obtain("per-frame")); + ensure_equals("first explicit pump", pumps.mPumpMap.size(), initial_pumps + 1); + // Verify that per_frame was instantiated as an LLEventStream. + ensure("LLEventStream leaf class", dynamic_cast<LLEventStream*> (&per_frame)); + ensure("enabled", per_frame.enabled()); + // Trivial test, but posting an event to an EventPump with no + // listeners should not blow up. The test is relevant because defining + // a boost::signal with a non-void return signature, using the default + // combiner, blows up if there are no listeners. This is because the + // default combiner is defined to return the value returned by the + // last listener, which is meaningless if there were no listeners. + per_frame.post(0); + LLBoundListener connection = listener0.listenTo(per_frame); + ensure("connected", connection.connected()); + ensure("not blocked", !connection.blocked()); + per_frame.post(1); + check_listener("received", listener0, 1); + { // block the connection + LLEventPump::Blocker block(connection); + ensure("blocked", connection.blocked()); + per_frame.post(2); + check_listener("not updated", listener0, 1); + } // unblock + ensure("unblocked", !connection.blocked()); + per_frame.post(3); + check_listener("unblocked", listener0, 3); + LLBoundListener sameConnection = per_frame.getListener(listener0.getName()); + ensure("still connected", sameConnection.connected()); + ensure("still not blocked", !sameConnection.blocked()); + { // block it again + LLEventPump::Blocker block(sameConnection); + ensure("re-blocked", sameConnection.blocked()); + per_frame.post(4); + check_listener("re-blocked", listener0, 3); + } // unblock + 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 '") + + listener0.getName() + "' on " + typeid(per_frame).name() + + " '" + per_frame.getName() + "'"); + // do it right this time + listener1.listenTo(per_frame); + per_frame.post(5); + check_listener("got", listener0, 5); + check_listener("got", listener1, 5); + per_frame.enable(false); + per_frame.post(6); + check_listener("didn't get", listener0, 5); + check_listener("didn't get", listener1, 5); + per_frame.enable(); + per_frame.post(7); + check_listener("got", listener0, 7); + check_listener("got", listener1, 7); + per_frame.stopListening(listener0.getName()); + ensure("disconnected 0", ! connection.connected()); + ensure("disconnected 1", ! sameConnection.connected()); + per_frame.post(8); + check_listener("disconnected", listener0, 7); + check_listener("still connected", listener1, 8); + per_frame.stopListening(listener1.getName()); + per_frame.post(9); + check_listener("disconnected", listener1, 8); } template<> template<> void events_object::test<2>() { - set_test_name("callstop() returning true"); - LLEventPump& per_frame(pumps.obtain("per-frame")); - listener0.reset(0); - listener1.reset(0); - LLBoundListener bound0 = listener0.listenTo(per_frame, &Listener::callstop); - LLBoundListener bound1 = listener1.listenTo(per_frame, &Listener::call, - // after listener0 - make<LLEventPump::NameList>(list_of(listener0.getName()))); - ensure("enabled", per_frame.enabled()); - ensure("connected 0", bound0.connected()); - ensure("unblocked 0", !bound0.blocked()); - ensure("connected 1", bound1.connected()); - ensure("unblocked 1", !bound1.blocked()); - per_frame.post(1); - check_listener("got", listener0, 1); - // Because listener0.callstop() returns true, control never reaches listener1.call(). - check_listener("got", listener1, 0); + set_test_name("callstop() returning true"); + LLEventPump& per_frame(pumps.obtain("per-frame")); + listener0.reset(0); + listener1.reset(0); + LLBoundListener bound0 = listener0.listenTo(per_frame, &Listener::callstop); + LLBoundListener bound1 = listener1.listenTo(per_frame, &Listener::call, + // after listener0 + make<LLEventPump::NameList>(list_of(listener0.getName()))); + ensure("enabled", per_frame.enabled()); + ensure("connected 0", bound0.connected()); + ensure("unblocked 0", !bound0.blocked()); + ensure("connected 1", bound1.connected()); + ensure("unblocked 1", !bound1.blocked()); + per_frame.post(1); + check_listener("got", listener0, 1); + // Because listener0.callstop() returns true, control never reaches listener1.call(). + check_listener("got", listener1, 0); } bool chainEvents(Listener& someListener, const LLSD& event) { - // Make this call so we can watch for side effects for test purposes. - someListener.call(event); - // This function represents a recursive event chain -- or some other - // scenario in which an event handler raises additional events. - int value = event.asInteger(); - if (value) - { - LLEventPumps::instance().obtain("login").post(value - 1); - } - return false; + // Make this call so we can watch for side effects for test purposes. + someListener.call(event); + // This function represents a recursive event chain -- or some other + // scenario in which an event handler raises additional events. + int value = event.asInteger(); + if (value) + { + LLEventPumps::instance().obtain("login").post(value - 1); + } + return false; } template<> template<> void events_object::test<3>() { - set_test_name("explicitly-instantiated LLEventStream"); - // Explicitly instantiate an LLEventStream, and verify that it - // self-registers with LLEventPumps - size_t registered = pumps.mPumpMap.size(); - size_t owned = pumps.mOurPumps.size(); - LLEventPump* localInstance; - { - LLEventStream myEventStream("stream"); - localInstance = &myEventStream; - LLEventPump& stream(pumps.obtain("stream")); - ensure("found named LLEventStream instance", &stream == localInstance); - ensure_equals("registered new instance", pumps.mPumpMap.size(), registered + 1); - ensure_equals("explicit instance not owned", pumps.mOurPumps.size(), owned); - } // destroy myEventStream -- should unregister - ensure_equals("destroyed instance unregistered", pumps.mPumpMap.size(), registered); - ensure_equals("destroyed instance not owned", pumps.mOurPumps.size(), owned); - LLEventPump& stream(pumps.obtain("stream")); - ensure("new LLEventStream instance", &stream != localInstance); - ensure_equals("obtain()ed instance registered", pumps.mPumpMap.size(), registered + 1); - ensure_equals("obtain()ed instance owned", pumps.mOurPumps.size(), owned + 1); + set_test_name("explicitly-instantiated LLEventStream"); + // Explicitly instantiate an LLEventStream, and verify that it + // self-registers with LLEventPumps + size_t registered = pumps.mPumpMap.size(); + size_t owned = pumps.mOurPumps.size(); + LLEventPump* localInstance; + { + LLEventStream myEventStream("stream"); + localInstance = &myEventStream; + LLEventPump& stream(pumps.obtain("stream")); + ensure("found named LLEventStream instance", &stream == localInstance); + ensure_equals("registered new instance", pumps.mPumpMap.size(), registered + 1); + ensure_equals("explicit instance not owned", pumps.mOurPumps.size(), owned); + } // destroy myEventStream -- should unregister + ensure_equals("destroyed instance unregistered", pumps.mPumpMap.size(), registered); + ensure_equals("destroyed instance not owned", pumps.mOurPumps.size(), owned); + LLEventPump& stream(pumps.obtain("stream")); + ensure("new LLEventStream instance", &stream != localInstance); + ensure_equals("obtain()ed instance registered", pumps.mPumpMap.size(), registered + 1); + ensure_equals("obtain()ed instance owned", pumps.mOurPumps.size(), owned + 1); } template<> template<> void events_object::test<4>() { - set_test_name("stopListening()"); - LLEventPump& login(pumps.obtain("login")); - listener0.listenTo(login); - login.stopListening(listener0.getName()); - // should not throw because stopListening() should have removed name - listener0.listenTo(login, &Listener::callstop); - LLBoundListener wrong = login.getListener("bogus"); - ensure("bogus connection disconnected", !wrong.connected()); - ensure("bogus connection blocked", wrong.blocked()); + set_test_name("stopListening()"); + LLEventPump& login(pumps.obtain("login")); + listener0.listenTo(login); + login.stopListening(listener0.getName()); + // should not throw because stopListening() should have removed name + listener0.listenTo(login, &Listener::callstop); + LLBoundListener wrong = login.getListener("bogus"); + ensure("bogus connection disconnected", !wrong.connected()); + ensure("bogus connection blocked", wrong.blocked()); } template<> template<> void events_object::test<5>() { - set_test_name("chaining LLEventPump instances"); - LLEventPump& upstream(pumps.obtain("upstream")); - // One potentially-useful construct is to chain LLEventPumps together. - // Among other things, this allows you to turn subsets of listeners on - // and off in groups. - LLEventPump& filter0(pumps.obtain("filter0")); - LLEventPump& filter1(pumps.obtain("filter1")); - upstream.listen(filter0.getName(), boost::bind(&LLEventPump::post, boost::ref(filter0), _1)); - upstream.listen(filter1.getName(), boost::bind(&LLEventPump::post, boost::ref(filter1), _1)); - listener0.listenTo(filter0); - listener1.listenTo(filter1); - listener0.reset(0); - listener1.reset(0); - upstream.post(1); - check_listener("got unfiltered", listener0, 1); - check_listener("got unfiltered", listener1, 1); - filter0.enable(false); - upstream.post(2); - check_listener("didn't get filtered", listener0, 1); - check_listener("got filtered", listener1, 2); + set_test_name("chaining LLEventPump instances"); + LLEventPump& upstream(pumps.obtain("upstream")); + // One potentially-useful construct is to chain LLEventPumps together. + // Among other things, this allows you to turn subsets of listeners on + // and off in groups. + LLEventPump& filter0(pumps.obtain("filter0")); + LLEventPump& filter1(pumps.obtain("filter1")); + upstream.listen(filter0.getName(), boost::bind(&LLEventPump::post, boost::ref(filter0), _1)); + upstream.listen(filter1.getName(), boost::bind(&LLEventPump::post, boost::ref(filter1), _1)); + listener0.listenTo(filter0); + listener1.listenTo(filter1); + listener0.reset(0); + listener1.reset(0); + upstream.post(1); + check_listener("got unfiltered", listener0, 1); + check_listener("got unfiltered", listener1, 1); + filter0.enable(false); + upstream.post(2); + check_listener("didn't get filtered", listener0, 1); + check_listener("got filtered", listener1, 2); } template<> template<> void events_object::test<6>() { - set_test_name("listener dependency order"); - typedef LLEventPump::NameList NameList; - LLEventPump& button(pumps.obtain("button")); - Collect collector; - button.listen("Mary", - boost::bind(&Collect::add, boost::ref(collector), "Mary", _1), - // state that "Mary" must come after "checked" - make<NameList> (list_of("checked"))); - button.listen("checked", - boost::bind(&Collect::add, boost::ref(collector), "checked", _1), - // "checked" must come after "spot" - make<NameList> (list_of("spot"))); - button.listen("spot", - boost::bind(&Collect::add, boost::ref(collector), "spot", _1)); - button.post(1); - ensure_equals(collector.result, make<StringVec>(list_of("spot")("checked")("Mary"))); - collector.clear(); - button.stopListening("Mary"); - button.listen("Mary", - boost::bind(&Collect::add, boost::ref(collector), "Mary", _1), - LLEventPump::empty, // no after dependencies - // now "Mary" must come before "spot" - make<NameList>(list_of("spot"))); - button.post(2); - ensure_equals(collector.result, make<StringVec>(list_of("Mary")("spot")("checked"))); - collector.clear(); - button.stopListening("spot"); - 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: - // - the name and runtime type of the LLEventPump - ensure_contains("LLEventPump type", threw, typeid(button).name()); - ensure_contains("LLEventPump name", threw, "'button'"); - // - the name of the new listener that caused the problem - ensure_contains("new listener name", threw, "'spot'"); - // - a synopsis of the problematic dependencies. - ensure_contains("cyclic dependencies", threw, - "\"Mary\" -> before (\"spot\")"); - ensure_contains("cyclic dependencies", threw, - "after (\"spot\") -> \"checked\""); - ensure_contains("cyclic dependencies", threw, - "after (\"Mary\", \"checked\") -> \"spot\""); - button.listen("yellow", - boost::bind(&Collect::add, boost::ref(collector), "yellow", _1), - make<NameList>(list_of("checked"))); - button.listen("shoelaces", - boost::bind(&Collect::add, boost::ref(collector), "shoelaces", _1), - make<NameList>(list_of("checked"))); - button.post(3); - ensure_equals(collector.result, make<StringVec>(list_of("Mary")("checked")("yellow")("shoelaces"))); - collector.clear(); - 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. - ensure_contains("LLEventPump type", threw, typeid(button).name()); - ensure_contains("LLEventPump name", threw, "'button'"); - ensure_contains("new listener name", threw, "'of'"); - ensure_contains("prev listener name", threw, "'yellow'"); - // std::cout << "Thrown Exception: " << threw << std::endl; - ensure_contains("old order", threw, "was: Mary, checked, yellow, shoelaces"); - ensure_contains("new order", threw, "now: Mary, checked, shoelaces, of, yellow"); - button.post(4); - ensure_equals(collector.result, make<StringVec>(list_of("Mary")("checked")("yellow")("shoelaces"))); + set_test_name("listener dependency order"); + typedef LLEventPump::NameList NameList; + LLEventPump& button(pumps.obtain("button")); + Collect collector; + button.listen("Mary", + boost::bind(&Collect::add, boost::ref(collector), "Mary", _1), + // state that "Mary" must come after "checked" + make<NameList> (list_of("checked"))); + button.listen("checked", + boost::bind(&Collect::add, boost::ref(collector), "checked", _1), + // "checked" must come after "spot" + make<NameList> (list_of("spot"))); + button.listen("spot", + boost::bind(&Collect::add, boost::ref(collector), "spot", _1)); + button.post(1); + ensure_equals(collector.result, make<StringVec>(list_of("spot")("checked")("Mary"))); + collector.clear(); + button.stopListening("Mary"); + button.listen("Mary", + boost::bind(&Collect::add, boost::ref(collector), "Mary", _1), + LLEventPump::empty, // no after dependencies + // now "Mary" must come before "spot" + make<NameList>(list_of("spot"))); + button.post(2); + ensure_equals(collector.result, make<StringVec>(list_of("Mary")("spot")("checked"))); + collector.clear(); + button.stopListening("spot"); + 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: + // - the name and runtime type of the LLEventPump + ensure_contains("LLEventPump type", threw, typeid(button).name()); + ensure_contains("LLEventPump name", threw, "'button'"); + // - the name of the new listener that caused the problem + ensure_contains("new listener name", threw, "'spot'"); + // - a synopsis of the problematic dependencies. + ensure_contains("cyclic dependencies", threw, + "\"Mary\" -> before (\"spot\")"); + ensure_contains("cyclic dependencies", threw, + "after (\"spot\") -> \"checked\""); + ensure_contains("cyclic dependencies", threw, + "after (\"Mary\", \"checked\") -> \"spot\""); + button.listen("yellow", + boost::bind(&Collect::add, boost::ref(collector), "yellow", _1), + make<NameList>(list_of("checked"))); + button.listen("shoelaces", + boost::bind(&Collect::add, boost::ref(collector), "shoelaces", _1), + make<NameList>(list_of("checked"))); + button.post(3); + ensure_equals(collector.result, make<StringVec>(list_of("Mary")("checked")("yellow")("shoelaces"))); + collector.clear(); + 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. + ensure_contains("LLEventPump type", threw, typeid(button).name()); + ensure_contains("LLEventPump name", threw, "'button'"); + ensure_contains("new listener name", threw, "'of'"); + ensure_contains("prev listener name", threw, "'yellow'"); + // std::cout << "Thrown Exception: " << threw << std::endl; + ensure_contains("old order", threw, "was: Mary, checked, yellow, shoelaces"); + ensure_contains("new order", threw, "now: Mary, checked, shoelaces, of, yellow"); + button.post(4); + ensure_equals(collector.result, make<StringVec>(list_of("Mary")("checked")("yellow")("shoelaces"))); } template<> template<> 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 = 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 - LLEventStream bob1("bob", true);// allowed to tweak name - ensure_equals("tweaked LLEventStream name", bob1.getName(), "bob1"); - std::vector<std::shared_ptr<LLEventStream> > streams; - for (int i = 2; i <= 10; ++i) - { - streams.push_back(std::shared_ptr<LLEventStream>(new LLEventStream("bob", true))); - } - ensure_equals("last tweaked LLEventStream name", streams.back()->getName(), "bob10"); + set_test_name("tweaked and untweaked LLEventPump instance names"); + { // nested scope + // Hand-instantiate an LLEventStream... + LLEventStream bob("bob"); + 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 + LLEventStream bob1("bob", true);// allowed to tweak name + ensure_equals("tweaked LLEventStream name", bob1.getName(), "bob1"); + std::vector<std::shared_ptr<LLEventStream> > streams; + for (int i = 2; i <= 10; ++i) + { + streams.push_back(std::shared_ptr<LLEventStream>(new LLEventStream("bob", true))); + } + ensure_equals("last tweaked LLEventStream name", streams.back()->getName(), "bob10"); } // Define a function that accepts an LLListenerOrPumpName void eventSource(const LLListenerOrPumpName& listener) { - // Pretend that some time has elapsed. Call listener immediately. - listener(17); + // Pretend that some time has elapsed. Call listener immediately. + listener(17); } template<> template<> void events_object::test<8>() { - set_test_name("LLListenerOrPumpName"); - // Passing a boost::bind() expression to LLListenerOrPumpName - listener0.reset(0); - eventSource(boost::bind(&Listener::call, boost::ref(listener0), _1)); - check_listener("got by listener", listener0, 17); - // Passing a string LLEventPump name to LLListenerOrPumpName - listener0.reset(0); - LLEventStream random("random"); - listener0.listenTo(random); - eventSource("random"); - check_listener("got by pump name", listener0, 17); - std::string threw = catch_what<LLListenerOrPumpName::Empty>( - [](){ - LLListenerOrPumpName empty; - empty(17); - }); + set_test_name("LLListenerOrPumpName"); + // Passing a boost::bind() expression to LLListenerOrPumpName + listener0.reset(0); + eventSource(boost::bind(&Listener::call, boost::ref(listener0), _1)); + check_listener("got by listener", listener0, 17); + // Passing a string LLEventPump name to LLListenerOrPumpName + listener0.reset(0); + LLEventStream random("random"); + listener0.listenTo(random); + eventSource("random"); + check_listener("got by pump name", listener0, 17); + std::string threw = catch_what<LLListenerOrPumpName::Empty>( + [](){ + LLListenerOrPumpName empty; + empty(17); + }); - ensure("threw Empty", !threw.empty()); + ensure("threw Empty", !threw.empty()); } class TempListener: public Listener { public: - TempListener(const std::string& name, bool& liveFlag) : - Listener(name), mLiveFlag(liveFlag) - { - mLiveFlag = true; - } + TempListener(const std::string& name, bool& liveFlag) : + Listener(name), mLiveFlag(liveFlag) + { + mLiveFlag = true; + } - virtual ~TempListener() - { - mLiveFlag = false; - } + virtual ~TempListener() + { + mLiveFlag = false; + } private: - bool& mLiveFlag; + bool& mLiveFlag; }; template<> template<> void events_object::test<9>() { - set_test_name("listen(boost::bind(...TempListener...))"); - // listen() can't do anything about a plain TempListener instance: - // it's not managed with shared_ptr, nor is it an LLEventTrackable subclass - bool live = false; - LLEventPump& heaptest(pumps.obtain("heaptest")); - LLBoundListener connection; - { - TempListener tempListener("temp", live); - ensure("TempListener constructed", live); - connection = heaptest.listen(tempListener.getName(), - boost::bind(&Listener::call, - boost::ref(tempListener), - _1)); - heaptest.post(1); - check_listener("received", tempListener, 1); - } // presumably this will make newListener go away? - // verify that - ensure("TempListener destroyed", !live); - // This is the case against which we can't defend. Don't even try to - // post to heaptest -- that would engage Undefined Behavior. - // Cautiously inspect connection... - ensure("misleadingly connected", connection.connected()); - // then disconnect by hand. - heaptest.stopListening("temp"); + set_test_name("listen(boost::bind(...TempListener...))"); + // listen() can't do anything about a plain TempListener instance: + // it's not managed with shared_ptr, nor is it an LLEventTrackable subclass + bool live = false; + LLEventPump& heaptest(pumps.obtain("heaptest")); + LLBoundListener connection; + { + TempListener tempListener("temp", live); + ensure("TempListener constructed", live); + connection = heaptest.listen(tempListener.getName(), + boost::bind(&Listener::call, + boost::ref(tempListener), + _1)); + heaptest.post(1); + check_listener("received", tempListener, 1); + } // presumably this will make newListener go away? + // verify that + ensure("TempListener destroyed", !live); + // This is the case against which we can't defend. Don't even try to + // post to heaptest -- that would engage Undefined Behavior. + // Cautiously inspect connection... + ensure("misleadingly connected", connection.connected()); + // then disconnect by hand. + heaptest.stopListening("temp"); } class TempTrackableListener: public TempListener, public LLEventTrackable |