diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt
index d1042d6e8693ff4692a105d24885081e6a4a233d..4b1bf49d07313f1656ba48eaf8f2373b5241b022 100644
--- a/indra/CMakeLists.txt
+++ b/indra/CMakeLists.txt
@@ -1,4 +1,3 @@
-
 # -*- cmake -*-
 
 # cmake_minimum_required should appear before any
@@ -70,6 +69,9 @@ if (VIEWER)
   add_subdirectory(${LIBS_OPEN_PREFIX}llxuixml)
   add_subdirectory(${LIBS_OPEN_PREFIX}viewer_components)
 
+  # Legacy C++ tests. Build always, run if LL_TESTS is true.
+  add_subdirectory(${VIEWER_PREFIX}test)
+
   # viewer media plugins
   add_subdirectory(${LIBS_OPEN_PREFIX}media_plugins)
 
diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt
index e9eb3c188447b73ed11313459a250a2d05bebada..328ab4ca518f51cfe5f0f42a3b32d957568c36bd 100644
--- a/indra/test/CMakeLists.txt
+++ b/indra/test/CMakeLists.txt
@@ -4,7 +4,6 @@ project (test)
 
 include(00-Common)
 include(LLCommon)
-include(LLDatabase)
 include(LLInventory)
 include(LLMath)
 include(LLMessage)
@@ -32,7 +31,7 @@ include_directories(
 
 set(test_SOURCE_FILES
     io.cpp
-#    llapp_tut.cpp                      # Temporarily removed until thread issues can be solved
+    llapp_tut.cpp
     llblowfish_tut.cpp
     llbuffer_tut.cpp
     lldoubledispatch_tut.cpp
@@ -53,8 +52,6 @@ set(test_SOURCE_FILES
     llservicebuilder_tut.cpp
     llstreamtools_tut.cpp
     lltemplatemessagebuilder_tut.cpp
-    lltimestampcache_tut.cpp
-    lltranscode_tut.cpp
     lltut.cpp
     lluuidhashmap_tut.cpp
     message_tut.cpp
@@ -76,12 +73,6 @@ if (NOT WINDOWS)
        )
 endif (NOT WINDOWS)
 
-if (NOT DARWIN)
-  list(APPEND test_SOURCE_FILES
-    lldatabase_tut.cpp
-    )
-endif (NOT DARWIN)
-
 set_source_files_properties(${test_HEADER_FILES}
                             PROPERTIES HEADER_FILE_ONLY TRUE)
 
@@ -100,7 +91,6 @@ target_link_libraries(test
     ${LLCOMMON_LIBRARIES}
     ${EXPAT_LIBRARIES}
     ${GOOGLEMOCK_LIBRARIES}
-    ${APRICONV_LIBRARIES}
     ${PTHREAD_LIBRARY}
     ${WINDOWS_LIBRARIES}
     ${BOOST_PROGRAM_OPTIONS_LIBRARY}
@@ -119,38 +109,28 @@ endif (WINDOWS)
 
 get_target_property(TEST_EXE test LOCATION)
 
-SET_TEST_PATH(LD_LIBRARY_PATH)
-LL_TEST_COMMAND(command "${LD_LIBRARY_PATH}"
-  "${TEST_EXE}" "--output=${CMAKE_CURRENT_BINARY_DIR}/cpp_test_results.txt" "--touch=${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt")
+SET_TEST_PATH(DYLD_LIBRARY_PATH)
+
+LL_TEST_COMMAND(command 
+  "${DYLD_LIBRARY_PATH}"
+  "${TEST_EXE}"
+  "--output=${CMAKE_CURRENT_BINARY_DIR}/cpp_test_results.txt" 
+  "--touch=${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt")
+
 ADD_CUSTOM_COMMAND(
   OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt
   COMMAND ${command}
   DEPENDS test
   WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
   COMMENT "C++ unit tests"
- )
+  )
 
 set(test_results ${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt)
 
-if (EXISTS /etc/debian_version_FAIL)
-  # The Python tests have all kinds of wacky non-portable assumptions
-  # built in.
-
-  add_custom_command(
-    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/py_tests_ok.txt
-    COMMAND ${PYTHON_EXECUTABLE}
-    ARGS
-      ${CMAKE_CURRENT_SOURCE_DIR}/test.py
-      --mode=static
-      --output=${CMAKE_CURRENT_BINARY_DIR}/py_test_results.txt
-      --touch=${CMAKE_CURRENT_BINARY_DIR}/py_tests_ok.txt
-      --mode=static
-    DEPENDS test.py
-    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-    COMMENT "Python unit tests"
-    )
-
-  list(APPEND test_results ${CMAKE_CURRENT_BINARY_DIR}/py_tests_ok.txt)
-endif (EXISTS /etc/debian_version_FAIL)
-    
-add_custom_target(tests_ok ALL DEPENDS ${test_results})
+# This should cause the test executable to be built, but not 
+# run if LL_TESTS is disabled. This will hopefully keep the
+# tests up to date with any code changes changes even if 
+# developers choose to disable LL_TESTS.
+if (LL_TESTS)  
+    add_custom_target(tests_ok ALL DEPENDS ${test_results})
+endif (LL_TESTS)
diff --git a/indra/test/io.cpp b/indra/test/io.cpp
index c06c1b153b205094f47997a0a5a9e1f1593b1d4a..ce747f667d2d53e0ed78b4d1640b5432877309cd 100644
--- a/indra/test/io.cpp
+++ b/indra/test/io.cpp
@@ -909,7 +909,7 @@ namespace tut
 		
 		pipe_and_pump_fitness()
 		{
-			LLFrameTimer::updateFrameTime();			
+			LLFrameTimer::updateFrameTime();
 			apr_pool_create(&mPool, NULL);
 			mPump = new LLPumpIO(mPool);
 			mSocket = LLSocket::create(
diff --git a/indra/test/llapp_tut.cpp b/indra/test/llapp_tut.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..aa5c0672e691eacfe7c6c096096d43a08ad966ff
--- /dev/null
+++ b/indra/test/llapp_tut.cpp
@@ -0,0 +1,162 @@
+/** 
+ * @file llapp_tut.cpp
+ * @author Phoenix
+ * @date 2006-09-12
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2006-2011, 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$
+ */
+
+#include <tut/tut.hpp>
+
+#include "linden_common.h"
+#include "llapp.h"
+#include "lltut.h"
+
+
+namespace tut
+{
+	struct application
+	{
+		class LLTestApp : public LLApp
+		{
+		public:
+			virtual bool init() { return true; }
+			virtual bool cleanup() { return true; }
+			virtual bool mainLoop() { return true; }
+		};
+		LLTestApp* mApp;
+		application()
+		{
+			mApp = new LLTestApp;
+		}
+		~application()
+		{
+			delete mApp;
+		}
+	};
+
+	typedef test_group<application> application_t;
+	typedef application_t::object application_object_t;
+	tut::application_t tut_application("application");
+
+	template<> template<>
+	void application_object_t::test<1>()
+	{
+		LLSD defaults;
+		defaults["template"] = "../../../scripts/messages/message_template.msg";
+		defaults["configdir"] = ".";
+		defaults["datadir"] = "data";
+		mApp->setOptionData(LLApp::PRIORITY_DEFAULT, defaults);
+
+		LLSD datadir_sd = mApp->getOption("datadir");
+		ensure_equals("data type", datadir_sd.type(), LLSD::TypeString);
+		ensure_equals(
+			"data value", datadir_sd.asString(), std::string("data"));
+	}
+
+	template<> template<>
+	void application_object_t::test<2>()
+	{
+		const int ARGC = 13;
+		const char* ARGV[ARGC] =
+		{
+			"", // argv[0] is usually the application name
+			"-crashcount",
+			"2",
+			"-space",
+			"spaceserver.grid.lindenlab.com",
+			"-db_host",
+			"localhost",
+			"--allowlslhttprequests",
+			"-asset-uri",
+			"http://test.lindenlab.com/assets",
+			"-data",
+			"127.0.0.1",
+			"--smtp"
+		};
+		bool ok = mApp->parseCommandOptions(ARGC, const_cast<char**>(ARGV));
+		ensure("command line parsed", ok);
+		ensure_equals(
+			"crashcount", mApp->getOption("crashcount").asInteger(), 2);
+		ensure_equals(
+			"space",
+			mApp->getOption("space").asString(),
+			std::string("spaceserver.grid.lindenlab.com"));
+		ensure_equals(
+			"db_host",
+			mApp->getOption("db_host").asString(),
+			std::string("localhost"));
+		ensure("allowlshlttprequests", mApp->getOption("smtp"));
+		ensure_equals(
+			"asset-uri",
+			mApp->getOption("asset-uri").asString(),
+			std::string("http://test.lindenlab.com/assets"));
+		ensure_equals(
+			"data",
+			mApp->getOption("data").asString(),
+			std::string("127.0.0.1"));
+		ensure("smtp", mApp->getOption("smtp"));
+	}
+
+	template<> template<>
+	void application_object_t::test<3>()
+	{
+		const int ARGC = 4;
+		const char* ARGV[ARGC] =
+		{
+			"", // argv[0] is usually the application name
+			"crashcount",
+			"2",
+			"--space"
+		};
+		bool ok = mApp->parseCommandOptions(ARGC, const_cast<char**>(ARGV));
+		ensure("command line parse failure", !ok);
+	}
+
+	template<> template<>
+	void application_object_t::test<4>()
+	{
+		const int ARGC = 4;
+		const char* ARGV[ARGC] =
+		{
+			"", // argv[0] is usually the application name
+			"--crashcount",
+			"2",
+			"space"
+		};
+		bool ok = mApp->parseCommandOptions(ARGC, const_cast<char**>(ARGV));
+		ensure("command line parse failure", !ok);
+	}
+
+
+	template<> template<>
+	void application_object_t::test<5>()
+	{
+		LLSD options;
+		options["boolean-test"] = true;
+		mApp->setOptionData(LLApp::PRIORITY_GENERAL_CONFIGURATION, options);
+		ensure("bool set", mApp->getOption("boolean-test").asBoolean());
+		options["boolean-test"] = false;
+		mApp->setOptionData(LLApp::PRIORITY_RUNTIME_OVERRIDE, options);
+		ensure("bool unset", !mApp->getOption("boolean-test").asBoolean());
+	}
+}
diff --git a/indra/test/llevents_tut.cpp b/indra/test/llevents_tut.cpp
index 57e22bbb564c7a6a442a55c3b4e8f5d799952916..4699bb1827199325dea86e9dfe2d1b1c296ad600 100644
--- a/indra/test/llevents_tut.cpp
+++ b/indra/test/llevents_tut.cpp
@@ -54,686 +54,730 @@
 
 using boost::assign::list_of;
 
+#ifdef LL_LINUX
+#define CATCH_MISSED_LINUX_EXCEPTION(exception, threw)										\
+catch (const std::runtime_error& ex)														\
+{																							\
+	/* This clause is needed on Linux, on the viewer side, because the	*/					\
+	/* exception isn't caught by the clause above. Warn the user...		*/					\
+	std::cerr << "Failed to catch " << typeid(ex).name() << std::endl;						\
+	/* But if the expected exception was thrown, allow the test to		*/					\
+	/* succeed anyway. Not sure how else to handle this odd case.		*/					\
+	/* This approach is also used in llsdmessage_test.cpp. 				*/					\
+	if (std::string(typeid(ex).name()) == typeid(exception).name())							\
+	{																						\
+		threw = ex.what();																	\
+		/*std::cout << ex.what() << std::endl;*/											\
+	}																						\
+	else																					\
+	{																						\
+		/* We don't even recognize this exception. Let it propagate		*/					\
+		/* out to TUT to fail the test.									*/					\
+		throw;																				\
+	}																						\
+}																							\
+catch (...)																					\
+{																							\
+	std::cerr << "Utterly failed to catch expected exception " << #exception << "!" <<		\
+	std::endl;																				\
+	/* This indicates a problem in the test that should be addressed.   */					\
+	throw;																					\
+}
+
+#else // LL_LINUX
+#define CATCH_MISSED_LINUX_EXCEPTION(exception, threw)										\
+	/* Not needed on other platforms */
+#endif // LL_LINUX
+
 template<typename T>
-T make(const T& value) { return value; }
+T make(const T& value)
+{
+	return value;
+}
 
 /*****************************************************************************
-*   tut test group
-*****************************************************************************/
+ *   tut test group
+ *****************************************************************************/
 namespace tut
 {
-    struct events_data
-    {
-        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);
-        }
-    };
-    typedef test_group<events_data> events_group;
-    typedef events_group::object events_object;
-    tut::events_group evgr("events");
-
-    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-
-        // 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
-        bool threw = false;
-        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 (const LLEventPump::DupListenerName& e)
-        {
-            threw = true;
-            ensure_equals(e.what(),
-                          std::string("DupListenerName: "
-                                      "Attempt to register duplicate listener name '") +
-                          listener0.getName() +
-                          "' on " + typeid(per_frame).name() + " '" + per_frame.getName() + "'");
-        }
-        ensure("threw DupListenerName", threw);
-        // 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);
-    }
-
-    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;
-    }
-
-    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
-        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<5>()
-    {
-        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<6>()
-    {
-        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<7>()
-    {
-        set_test_name("listener dependency order");
-        typedef LLEventPump::NameList NameList;
-        typedef Collect::StringList StringList;
-        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<StringList>(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<StringList>(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 (const LLEventPump::Cycle& e)
-        {
-            threw = e.what();
-//          std::cout << "Caught: " << e.what() << '\n';
-        }
-        // 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<StringList>(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 (const LLEventPump::OrderChange& e)
-        {
-            threw = e.what();
-//          std::cout << "Caught: " << e.what() << '\n';
-        }
-        // 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'");
-        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<StringList>(list_of("Mary")("checked")("yellow")("shoelaces")));
-    }
-
-    template<> template<>
-    void events_object::test<8>()
-    {
-        set_test_name("tweaked and untweaked LLEventPump instance names");
-        {   // nested scope
-            // Hand-instantiate an LLEventStream...
-            LLEventStream bob("bob");
-            bool threw = false;
-            try
-            {
-                // then another with a duplicate name.
-                LLEventStream bob2("bob");
-            }
-            catch (const LLEventPump::DupPumpName& /*e*/)
-            {
-                threw = true;
-//              std::cout << "Caught: " << e.what() << '\n';
-            }
-            ensure("Caught DupPumpName", threw);
-        }   // 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< boost::shared_ptr<LLEventStream> > streams;
-        for (int i = 2; i <= 10; ++i)
-        {
-            streams.push_back(boost::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);
-    }
-
-    template<> template<>
-    void events_object::test<9>()
-    {
-        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);
-        bool threw = false;
-        try
-        {
-            LLListenerOrPumpName empty;
-            empty(17);
-        }
-        catch (const LLListenerOrPumpName::Empty&)
-        {
-            threw = true;
-        }
-        ensure("threw Empty", threw);
-    }
-
-    class TempListener: public Listener
-    {
-    public:
-        TempListener(const std::string& name, bool& liveFlag):
-            Listener(name),
-            mLiveFlag(liveFlag)
-        {
-            mLiveFlag = true;
-        }
-
-        virtual ~TempListener()
-        {
-            mLiveFlag = false;
-        }
-
-    private:
-        bool& mLiveFlag;
-    };
-
-    template<> template<>
-    void events_object::test<10>()
-    {
-        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");
-    }
-
-    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);
+struct events_data
+{
+	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);
+	}
+};
+typedef test_group<events_data> events_group;
+typedef events_group::object events_object;
+tut::events_group evgr("events");
+
+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-
+	// 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;
+	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 (const LLEventPump::DupListenerName& e)
+	{
+		threw = e.what();
+	}
+	CATCH_MISSED_LINUX_EXCEPTION(LLEventPump::DupListenerName, threw)
+	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);
+}
+
+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;
+}
+
+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
+	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<5>()
+{
+	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<6>()
+{
+	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<7>()
+{
+	set_test_name("listener dependency order");
+	typedef LLEventPump::NameList NameList;
+	typedef Collect::StringList StringList;
+	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<StringList>(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<StringList>(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 (const LLEventPump::Cycle& e)
+	{
+		threw = e.what();
+		// std::cout << "Caught: " << e.what() << '\n';
+	}
+	CATCH_MISSED_LINUX_EXCEPTION(LLEventPump::Cycle, threw)
+	// 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<StringList>(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 (const LLEventPump::OrderChange& e)
+	{
+		threw = e.what();
+		// std::cout << "Caught: " << e.what() << '\n';
+	}
+	CATCH_MISSED_LINUX_EXCEPTION(LLEventPump::OrderChange, threw)
+	// 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<StringList>(list_of("Mary")("checked")("yellow")("shoelaces")));
+}
+
+template<> template<>
+void events_object::test<8>()
+{
+	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 (const LLEventPump::DupPumpName& e)
+		{
+			threw = e.what();
+			// std::cout << "Caught: " << e.what() << '\n';
+		}
+		CATCH_MISSED_LINUX_EXCEPTION(LLEventPump::DupPumpName, threw)
+		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<boost::shared_ptr<LLEventStream> > streams;
+	for (int i = 2; i <= 10; ++i)
+	{
+		streams.push_back(boost::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);
+}
+
+template<> template<>
+void events_object::test<9>()
+{
+	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;
+	try
+	{
+		LLListenerOrPumpName empty;
+		empty(17);
+	}
+	catch (const LLListenerOrPumpName::Empty& e)
+	{
+		threw = e.what();
+	}
+	CATCH_MISSED_LINUX_EXCEPTION(LLListenerOrPumpName::Empty, threw)
+
+	ensure("threw Empty", !threw.empty());
+}
+
+class TempListener: public Listener
+{
+public:
+	TempListener(const std::string& name, bool& liveFlag) :
+		Listener(name), mLiveFlag(liveFlag)
+	{
+		mLiveFlag = true;
+	}
+
+	virtual ~TempListener()
+	{
+		mLiveFlag = false;
+	}
+
+private:
+	bool& mLiveFlag;
+};
+
+template<> template<>
+void events_object::test<10>()
+{
+	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");
+}
+
+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());
+	// 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);
+	// 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)
-        {}
-    };
-
-    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;
-        {
-            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);
-    }
-
-    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;
-        {
-            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);
-    }
-
-    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...))");
+}
+
+class TempTrackableListener: public TempListener, public LLEventTrackable
+{
+public:
+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;
+{
+	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);
+}
+
+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;
+{
+	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);
+}
+
+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.
+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;
+	 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);
+	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
diff --git a/indra/test/llhttpclient_tut.cpp b/indra/test/llhttpclient_tut.cpp
index 03759001ae3b87ebc999765fabe813ae1e101234..4b4046632c4e3eb80a6b94300efa15d040491b01 100644
--- a/indra/test/llhttpclient_tut.cpp
+++ b/indra/test/llhttpclient_tut.cpp
@@ -40,6 +40,7 @@
 #include "llhttpclient.h"
 #include "llformat.h"
 #include "llpipeutil.h"
+#include "llproxy.h"
 #include "llpumpio.h"
 
 #include "llsdhttpserver.h"
@@ -85,9 +86,10 @@ namespace tut
 		HTTPClientTestData()
 		{
 			apr_pool_create(&mPool, NULL);
+			LLCurl::initClass(false);
 			mServerPump = new LLPumpIO(mPool);
 			mClientPump = new LLPumpIO(mPool);
-			
+
 			LLHTTPClient::setPump(*mClientPump);
 		}
 		
@@ -95,6 +97,7 @@ namespace tut
 		{
 			delete mServerPump;
 			delete mClientPump;
+			LLProxy::cleanupClass();
 			apr_pool_destroy(mPool);
 		}
 
diff --git a/indra/test/llsd_new_tut.cpp b/indra/test/llsd_new_tut.cpp
index dd93b36f041748b52fe2796bdeb6d290711a3a7e..b2fa54a6886a37b27af742eb0a6bd65738203617 100644
--- a/indra/test/llsd_new_tut.cpp
+++ b/indra/test/llsd_new_tut.cpp
@@ -5,7 +5,7 @@
  *
  * $LicenseInfo:firstyear=2006&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
+ * Copyright (C) 2006-2011, 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
@@ -32,6 +32,19 @@
 #include "llsdtraits.h"
 #include "llstring.h"
 
+#if LL_WINDOWS
+#include <float.h>
+namespace
+{
+	int fpclassify(double x)
+	{
+		return _fpclass(x);
+	}
+}
+#else
+using std::fpclassify;
+#endif
+
 namespace tut
 {
 	class SDCleanupCheck
@@ -218,19 +231,16 @@ namespace tut
 		}
 		else
 		{
-// TODO: Fix on windows....
-#ifndef LL_WINDOWS
-# if !defined(fpclassify) && __GNUC__ >= 3
-#   define FPCLASSIFY_NAMESPACE std::
-# else
-#   define FPCLASSIFY_NAMESPACE
-# endif
-			int left  = FPCLASSIFY_NAMESPACE fpclassify(v.asReal());
-			int right = FPCLASSIFY_NAMESPACE fpclassify(eReal);
+			int left  = fpclassify(v.asReal());
+			int right = fpclassify(eReal);
 
 			ensure_equals(s+" to real", 	left, 			right);
-			ensure_equals(s+" to string",	v.asString(),	eString);
-#endif
+			// ensure_equals(s+" to string", v.asString(), eString);
+			// I've commented this check out, since there doesn't
+			// seem to be uniform string representation for NaN on
+			// all platforms. For example, on my Ubuntu 8.10 laptop
+			// with libc 2.11.1, sqrt(-1.0) will return '-nan', not
+			// 'nan'.
 		}
 	}
 	
@@ -742,6 +752,42 @@ namespace tut
 			LLSD w = v;
 			w = "nice day";
 		}
+
+		{
+			SDAllocationCheck check("shared values test for threaded work", 9);
+
+			//U32 start_llsd_count = LLSD::outstandingCount();
+
+			LLSD m = LLSD::emptyMap();
+
+			m["one"] = 1;
+			m["two"] = 2;
+			m["one_copy"] = m["one"];			// 3 (m, "one" and "two")
+
+			m["undef_one"] = LLSD();
+			m["undef_two"] = LLSD();
+			m["undef_one_copy"] = m["undef_one"];
+
+			{	// Ensure first_array gets freed to avoid counting it
+				LLSD first_array = LLSD::emptyArray();
+				first_array.append(1.0f);
+				first_array.append(2.0f);			
+				first_array.append(3.0f);			// 7
+
+				m["array"] = first_array;
+				m["array_clone"] = first_array;
+				m["array_copy"] = m["array"];		// 7
+			}
+
+			m["string_one"] = "string one value";
+			m["string_two"] = "string two value";
+			m["string_one_copy"] = m["string_one"];		// 9
+
+			//U32 llsd_object_count = LLSD::outstandingCount();
+			//std::cout << "Using " << (llsd_object_count - start_llsd_count) << " LLSD objects" << std::endl;
+
+			//m.dumpStats();
+		}
 	}
 
 	template<> template<>
@@ -769,4 +815,3 @@ namespace tut
 		test serializations
 	*/
 }
-
diff --git a/indra/test/llsdmessagebuilder_tut.cpp b/indra/test/llsdmessagebuilder_tut.cpp
index cc6f78decdba98bf756278fb42dd543ef78181ae..be0692557a1d7579899515712662772fe2ade4c4 100644
--- a/indra/test/llsdmessagebuilder_tut.cpp
+++ b/indra/test/llsdmessagebuilder_tut.cpp
@@ -33,6 +33,7 @@
 #include "llsdmessagebuilder.h"
 #include "llsdmessagereader.h"
 #include "llsdtraits.h"
+#include "llmath.h"
 #include "llquaternion.h"
 #include "u64.h"
 #include "v3dmath.h"
@@ -86,17 +87,17 @@ namespace tut
 			return createTemplateBlock(_PREHASH_Test0, type, size, block);
 		}
 
-		static LLMessageBlock* createTemplateBlock(char* name, const EMsgVariableType type = MVT_NULL, const S32 size = 0, EMsgBlockType block = MBT_VARIABLE)
+		static LLMessageBlock* createTemplateBlock(const char* name, const EMsgVariableType type = MVT_NULL, const S32 size = 0, EMsgBlockType block = MBT_VARIABLE)
 		{
 			LLMessageBlock* result = new LLMessageBlock(name, block);
 			if(type != MVT_NULL)
 			{
-				result->addVariable(_PREHASH_Test0, type, size);
+				result->addVariable(const_cast<char*>(_PREHASH_Test0), type, size);
 			}
 			return result;
 		}
 
-		static LLTemplateMessageBuilder* defaultTemplateBuilder(LLMessageTemplate& messageTemplate, char* name = _PREHASH_Test0)
+		static LLTemplateMessageBuilder* defaultTemplateBuilder(LLMessageTemplate& messageTemplate, char* name = const_cast<char*>(_PREHASH_Test0))
 		{
 			templateNameMap[_PREHASH_TestMessage] = &messageTemplate;
 			LLTemplateMessageBuilder* builder = new LLTemplateMessageBuilder(templateNameMap);
diff --git a/indra/test/lltemplatemessagebuilder_tut.cpp b/indra/test/lltemplatemessagebuilder_tut.cpp
index 09beb53869d4afcefa164840ebdfb6cc3b210b5a..6e1c82bb2464949a99ef34854bade4aa8df3d25e 100644
--- a/indra/test/lltemplatemessagebuilder_tut.cpp
+++ b/indra/test/lltemplatemessagebuilder_tut.cpp
@@ -31,6 +31,7 @@
 
 #include "llapr.h"
 #include "llmessagetemplate.h"
+#include "llmath.h"
 #include "llquaternion.h"
 #include "lltemplatemessagebuilder.h"
 #include "lltemplatemessagereader.h"
@@ -75,7 +76,7 @@ namespace tut
 
 		static LLMessageBlock* defaultBlock(const EMsgVariableType type = MVT_NULL, const S32 size = 0, EMsgBlockType block = MBT_VARIABLE)
 		{
-			return createBlock(_PREHASH_Test0, type, size, block);
+			return createBlock(const_cast<char*>(_PREHASH_Test0), type, size, block);
 		}
 
 		static LLMessageBlock* createBlock(char* name, const EMsgVariableType type = MVT_NULL, const S32 size = 0, EMsgBlockType block = MBT_VARIABLE)
@@ -83,12 +84,12 @@ namespace tut
 			LLMessageBlock* result = new LLMessageBlock(name, block);
 			if(type != MVT_NULL)
 			{
-				result->addVariable(_PREHASH_Test0, type, size);
+				result->addVariable(const_cast<char*>(_PREHASH_Test0), type, size);
 			}
 			return result;
 		}
 
-		static LLTemplateMessageBuilder* defaultBuilder(LLMessageTemplate& messageTemplate, char* name = _PREHASH_Test0)
+		static LLTemplateMessageBuilder* defaultBuilder(LLMessageTemplate& messageTemplate, char* name = const_cast<char*>(_PREHASH_Test0))
 		{
 			nameMap[_PREHASH_TestMessage] = &messageTemplate;
 			LLTemplateMessageBuilder* builder = new LLTemplateMessageBuilder(nameMap);
@@ -403,11 +404,11 @@ namespace tut
 
 		// build template: Test0 before Test1
 		LLMessageTemplate messageTemplate = defaultTemplate();
-		messageTemplate.addBlock(createBlock(_PREHASH_Test0, MVT_U32, 4, MBT_SINGLE));
-		messageTemplate.addBlock(createBlock(_PREHASH_Test1, MVT_U32, 4, MBT_SINGLE));
+		messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test0), MVT_U32, 4, MBT_SINGLE));
+		messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_U32, 4, MBT_SINGLE));
 
 		// build message: 1st declared block var == 0xaaaa, 2nd declared block var == 0xbbbb
-		LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate, _PREHASH_Test0);
+		LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate, const_cast<char*>(_PREHASH_Test0));
 		builder->addU32(_PREHASH_Test0, 0xaaaa);
 		builder->nextBlock(_PREHASH_Test1);
 		builder->addU32(_PREHASH_Test0, 0xbbbb);
@@ -416,11 +417,11 @@ namespace tut
 
 		// build template: Test1 before Test0
 		messageTemplate = defaultTemplate();
-		messageTemplate.addBlock(createBlock(_PREHASH_Test1, MVT_U32, 4, MBT_SINGLE));
-		messageTemplate.addBlock(createBlock(_PREHASH_Test0, MVT_U32, 4, MBT_SINGLE));
+		messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_U32, 4, MBT_SINGLE));
+		messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test0), MVT_U32, 4, MBT_SINGLE));
 
 		// build message: 1st declared block var == 0xaaaa, 2nd declared block var == 0xbbbb
-		builder = defaultBuilder(messageTemplate, _PREHASH_Test1);
+		builder = defaultBuilder(messageTemplate, const_cast<char*>(_PREHASH_Test1));
 		builder->addU32(_PREHASH_Test0, 0xaaaa);
 		builder->nextBlock(_PREHASH_Test0);
 		builder->addU32(_PREHASH_Test0, 0xbbbb);
@@ -443,11 +444,11 @@ namespace tut
 
 		// build template: Test0 before Test1
 		LLMessageTemplate messageTemplate = defaultTemplate();
-		messageTemplate.addBlock(createBlock(_PREHASH_Test0, MVT_U32, 4, MBT_SINGLE));
-		messageTemplate.addBlock(createBlock(_PREHASH_Test1, MVT_U32, 4, MBT_SINGLE));
+		messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test0), MVT_U32, 4, MBT_SINGLE));
+		messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_U32, 4, MBT_SINGLE));
 
 		// build message: 1st declared block var == 0xaaaa, 2nd declared block var == 0xbbbb
-		LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate, _PREHASH_Test0);
+		LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate, const_cast<char*>(_PREHASH_Test0));
 		builder->addU32(_PREHASH_Test0, 0xaaaa);
 		builder->nextBlock(_PREHASH_Test1);
 		builder->addU32(_PREHASH_Test0, 0xbbbb);
@@ -455,7 +456,7 @@ namespace tut
 		delete builder;
 
 		// build message: 1st declared block var == 0xaaaa, 2nd declared block var == 0xbbbb
-		builder = defaultBuilder(messageTemplate, _PREHASH_Test1);
+		builder = defaultBuilder(messageTemplate, const_cast<char*>(_PREHASH_Test1));
 		builder->addU32(_PREHASH_Test0, 0xbbbb);
 		builder->nextBlock(_PREHASH_Test0);
 		builder->addU32(_PREHASH_Test0, 0xaaaa);
@@ -478,21 +479,21 @@ namespace tut
 
 		// Build template: Test0 only
 		LLMessageTemplate messageTemplate = defaultTemplate();
-		messageTemplate.addBlock(createBlock(_PREHASH_Test0, MVT_U32, 4, MBT_SINGLE));
+		messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test0), MVT_U32, 4, MBT_SINGLE));
 
 		// Build message
-		LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate, _PREHASH_Test0);
+		LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate, const_cast<char*>(_PREHASH_Test0));
 		builder->addU32(_PREHASH_Test0, 0xaaaa);
 		bufferSize1 = builder->buildMessage(buffer1, MAX_BUFFER_SIZE, 0);
 		delete builder;
 
 		// Build template: Test0 before Test1
 		messageTemplate = defaultTemplate();
-		messageTemplate.addBlock(createBlock(_PREHASH_Test0, MVT_U32, 4, MBT_SINGLE));
-		messageTemplate.addBlock(createBlock(_PREHASH_Test1, MVT_U32, 4, MBT_SINGLE));
+		messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test0), MVT_U32, 4, MBT_SINGLE));
+		messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_U32, 4, MBT_SINGLE));
 
 		// Build message
-		builder = defaultBuilder(messageTemplate, _PREHASH_Test0);
+		builder = defaultBuilder(messageTemplate, const_cast<char*>(_PREHASH_Test0));
 		builder->addU32(_PREHASH_Test0, 0xaaaa);
 		builder->nextBlock(_PREHASH_Test1);
 		builder->addU32(_PREHASH_Test0, 0xbbbb);
@@ -511,8 +512,8 @@ namespace tut
 		U32 inTest00 = 0, inTest01 = 1, inTest1 = 2;
 		U32 outTest00, outTest01, outTest1;
 		LLMessageTemplate messageTemplate = defaultTemplate();
-		messageTemplate.addBlock(createBlock(_PREHASH_Test0, MVT_U32, 4));
-		messageTemplate.addBlock(createBlock(_PREHASH_Test1, MVT_U32, 4));
+		messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test0), MVT_U32, 4));
+		messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_U32, 4));
 		LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
 		builder->addU32(_PREHASH_Test0, inTest00);
 		builder->nextBlock(_PREHASH_Test0);
@@ -536,15 +537,15 @@ namespace tut
 		U32 inTest = 1, outTest;
 		LLMessageTemplate messageTemplate = defaultTemplate();
 		messageTemplate.addBlock(
-			createBlock(_PREHASH_Test0, MVT_U32, 4, MBT_SINGLE));
-		messageTemplate.addBlock(createBlock(_PREHASH_Test1, MVT_U32, 4));
+			createBlock(const_cast<char*>(_PREHASH_Test0), MVT_U32, 4, MBT_SINGLE));
+		messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_U32, 4));
 
 		LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
 		builder->addU32(_PREHASH_Test0, inTest);
 
 		LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
 		reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outTest);
-		S32 blockCount = reader->getNumberOfBlocks(_PREHASH_Test1);
+		S32 blockCount = reader->getNumberOfBlocks(const_cast<char*>(_PREHASH_Test1));
 		ensure_equals("Ensure block count", blockCount, 0);
 		ensure_equals("Ensure Test0", inTest, outTest);
 		delete reader;
@@ -556,7 +557,7 @@ namespace tut
 	{
 		// build template
 		LLMessageTemplate messageTemplate = defaultTemplate();
-		messageTemplate.addBlock(createBlock(_PREHASH_Test0, MVT_U32, 4));
+		messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test0), MVT_U32, 4));
 
 		// build message
 		LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
@@ -881,7 +882,7 @@ namespace tut
 		delete builder;
 
 		// add block to reader template
-		messageTemplate.addBlock(createBlock(_PREHASH_Test1, MVT_U32, 4, MBT_SINGLE));
+		messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_U32, 4, MBT_SINGLE));
 
 		// read message value and default value
 		numberMap[1] = &messageTemplate;
@@ -914,7 +915,7 @@ namespace tut
 		delete builder;
 
 		// add variable block to reader template
-		messageTemplate.addBlock(createBlock(_PREHASH_Test1, MVT_U32, 4));
+		messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_U32, 4));
 
 		// read message value and check block repeat count
 		numberMap[1] = &messageTemplate;
@@ -947,7 +948,7 @@ namespace tut
 		delete builder;
 
 		// add variable block to reader template
-		messageTemplate.addBlock(createBlock(_PREHASH_Test1, MVT_VARIABLE, 4, 
+		messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_VARIABLE, 4,
 											 MBT_SINGLE));
 
 		// read message value and default string