From b73e71ebdf4366b11d3fd43ac80e2a3dc7f30cb2 Mon Sep 17 00:00:00 2001
From: Adam Moss <moss@lindenlab.com>
Date: Mon, 12 Oct 2009 14:13:57 +0000
Subject: [PATCH] DEV-41174 more automated testing love * turn llnamevalue_tut
 into a llmessage unit test * turn llsdserialize_tut into a llcommon
 integration test * re-enable the (quite slow) llsdserialize test on win32 now
 that it doesn't have to run on every recompile * re-enable all llmessage unit
 tests on linux viewer builds

---
 indra/llcommon/CMakeLists.txt               |    5 +-
 indra/llcommon/tests/llsdserialize_test.cpp | 1432 +++++++++++++++++++
 indra/llmessage/CMakeLists.txt              |   60 +-
 indra/llmessage/tests/llnamevalue_test.cpp  |  412 ++++++
 indra/test/CMakeLists.txt                   |    2 -
 5 files changed, 1875 insertions(+), 36 deletions(-)
 create mode 100644 indra/llcommon/tests/llsdserialize_test.cpp
 create mode 100644 indra/llmessage/tests/llnamevalue_test.cpp

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 371786c44da..0861783df16 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -241,9 +241,10 @@ LL_ADD_PROJECT_UNIT_TESTS(llcommon "${llcommon_TEST_SOURCE_FILES}")
 
 #set(TEST_DEBUG on)
 set(test_libs llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
-LL_ADD_INTEGRATION_TEST(lllazy lllazy.cpp "${test_libs}")
-LL_ADD_INTEGRATION_TEST(llstring "llstring.cpp" "${test_libs}")
+LL_ADD_INTEGRATION_TEST(lllazy "lllazy.cpp" "${test_libs}")
 LL_ADD_INTEGRATION_TEST(llrand "llrand.cpp" "${test_libs}")
+LL_ADD_INTEGRATION_TEST(llsdserialize "llsdserialize.cpp" "${test_libs}")
+LL_ADD_INTEGRATION_TEST(llstring "llstring.cpp" "${test_libs}")
 
 # *TODO - reenable these once tcmalloc libs no longer break the build.
 #ADD_BUILD_TEST(llallocator llcommon)
diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp
new file mode 100644
index 00000000000..662b599c55e
--- /dev/null
+++ b/indra/llcommon/tests/llsdserialize_test.cpp
@@ -0,0 +1,1432 @@
+/** 
+ * @file llsdserialize_tut.cpp
+ * @date 2006-04
+ * @brief LLSDSerialize unit tests
+ *
+ * $LicenseInfo:firstyear=2006&license=viewergpl$
+ * 
+ * Copyright (c) 2006-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#if !LL_WINDOWS
+#include <netinet/in.h>
+#endif
+
+#include "linden_common.h"
+#include "../llsd.h"
+#include "../llsdserialize.h"
+#include "../llformat.h"
+
+#include "../test/lltut.h"
+
+
+#if LL_WINDOWS
+#include <winsock2.h>
+typedef U32 uint32_t;
+#endif
+
+namespace tut
+{
+	struct sd_xml_data
+	{
+		sd_xml_data()
+		{
+			mFormatter = new LLSDXMLFormatter;
+		}
+		LLSD mSD;
+		LLPointer<LLSDXMLFormatter> mFormatter;
+		void xml_test(const char* name, const std::string& expected)
+		{
+			std::ostringstream ostr;
+			mFormatter->format(mSD, ostr);
+			ensure_equals(name, ostr.str(), expected);
+		}
+	};
+
+	typedef test_group<sd_xml_data> sd_xml_test;
+	typedef sd_xml_test::object sd_xml_object;
+	tut::sd_xml_test sd_xml_stream("sd_xml_serialization");
+
+	template<> template<>
+	void sd_xml_object::test<1>()
+	{
+		// random atomic tests
+		std::string expected;
+
+		expected = "<llsd><undef /></llsd>\n";
+		xml_test("undef", expected);
+
+		mSD = 3463;
+		expected = "<llsd><integer>3463</integer></llsd>\n";
+		xml_test("integer", expected);
+
+		mSD = "";
+		expected = "<llsd><string /></llsd>\n";
+		xml_test("empty string", expected);
+
+		mSD = "foobar";
+		expected = "<llsd><string>foobar</string></llsd>\n";
+		xml_test("string", expected);
+
+		mSD = LLUUID::null;
+		expected = "<llsd><uuid /></llsd>\n";
+		xml_test("null uuid", expected);
+		
+		mSD = LLUUID("c96f9b1e-f589-4100-9774-d98643ce0bed");
+		expected = "<llsd><uuid>c96f9b1e-f589-4100-9774-d98643ce0bed</uuid></llsd>\n";
+		xml_test("uuid", expected);
+
+		mSD = LLURI("https://secondlife.com/login");
+		expected = "<llsd><uri>https://secondlife.com/login</uri></llsd>\n";
+		xml_test("uri", expected);
+
+		mSD = LLDate("2006-04-24T16:11:33Z");
+		expected = "<llsd><date>2006-04-24T16:11:33Z</date></llsd>\n";
+		xml_test("date", expected);
+
+		// *FIX: test binary
+	}
+	
+	template<> template<>
+	void sd_xml_object::test<2>()
+	{
+		// tests with boolean values.
+		std::string expected;
+
+		mFormatter->boolalpha(true);
+		mSD = true;
+		expected = "<llsd><boolean>true</boolean></llsd>\n";
+		xml_test("bool alpha true", expected);
+		mSD = false;
+		expected = "<llsd><boolean>false</boolean></llsd>\n";
+		xml_test("bool alpha false", expected);
+
+		mFormatter->boolalpha(false);
+		mSD = true;
+		expected = "<llsd><boolean>1</boolean></llsd>\n";
+		xml_test("bool true", expected);
+		mSD = false;
+		expected = "<llsd><boolean>0</boolean></llsd>\n";
+		xml_test("bool false", expected);
+	}
+
+
+	template<> template<>
+	void sd_xml_object::test<3>()
+	{
+		// tests with real values.
+		std::string expected;
+
+		mFormatter->realFormat("%.2f");
+		mSD = 1.0;
+		expected = "<llsd><real>1.00</real></llsd>\n";
+		xml_test("real 1", expected);
+
+		mSD = -34379.0438;
+		expected = "<llsd><real>-34379.04</real></llsd>\n";
+		xml_test("real reduced precision", expected);
+		mFormatter->realFormat("%.4f");
+		expected = "<llsd><real>-34379.0438</real></llsd>\n";
+		xml_test("higher precision", expected);
+
+		mFormatter->realFormat("%.0f");
+		mSD = 0.0;
+		expected = "<llsd><real>0</real></llsd>\n";
+		xml_test("no decimal 0", expected);
+		mSD = 3287.4387;
+		expected = "<llsd><real>3287</real></llsd>\n";
+		xml_test("no decimal real number", expected);
+	}
+
+	template<> template<>
+	void sd_xml_object::test<4>()
+	{
+		// tests with arrays
+		std::string expected;
+
+		mSD = LLSD::emptyArray();
+		expected = "<llsd><array /></llsd>\n";
+		xml_test("empty array", expected);
+
+		mSD.append(LLSD());
+		expected = "<llsd><array><undef /></array></llsd>\n";
+		xml_test("1 element array", expected);
+
+		mSD.append(1);
+		expected = "<llsd><array><undef /><integer>1</integer></array></llsd>\n";
+		xml_test("2 element array", expected);
+	}
+
+	template<> template<>
+	void sd_xml_object::test<5>()
+	{
+		// tests with arrays
+		std::string expected;
+
+		mSD = LLSD::emptyMap();
+		expected = "<llsd><map /></llsd>\n";
+		xml_test("empty map", expected);
+
+		mSD["foo"] = "bar";
+		expected = "<llsd><map><key>foo</key><string>bar</string></map></llsd>\n";
+		xml_test("1 element map", expected);
+
+		mSD["baz"] = LLSD();
+		expected = "<llsd><map><key>baz</key><undef /><key>foo</key><string>bar</string></map></llsd>\n";
+		xml_test("2 element map", expected);
+	}
+	
+	
+	class TestLLSDSerializeData
+	{
+	public:
+		TestLLSDSerializeData();
+		~TestLLSDSerializeData();
+
+		void doRoundTripTests(const std::string&);
+		void checkRoundTrip(const std::string&, const LLSD& v);
+		
+		LLPointer<LLSDFormatter> mFormatter;
+		LLPointer<LLSDParser> mParser;
+	};
+
+	TestLLSDSerializeData::TestLLSDSerializeData()
+	{
+	}
+
+	TestLLSDSerializeData::~TestLLSDSerializeData()
+	{
+	}
+
+	void TestLLSDSerializeData::checkRoundTrip(const std::string& msg, const LLSD& v)
+	{
+		std::stringstream stream;	
+		mFormatter->format(v, stream);
+		//llinfos << "checkRoundTrip: length " << stream.str().length() << llendl;
+		LLSD w;
+		mParser->reset();	// reset() call is needed since test code re-uses mParser
+		mParser->parse(stream, w, stream.str().size());
+		
+		try
+		{
+			ensure_equals(msg.c_str(), w, v);
+		}
+		catch (...)
+		{
+			std::cerr << "the serialized string was:" << std::endl;
+			std::cerr << stream.str() << std::endl;
+			throw;
+		}
+	}
+
+	static void fillmap(LLSD& root, U32 width, U32 depth)
+	{
+		if(depth == 0)
+		{
+			root["foo"] = "bar";
+			return;
+		}
+
+		for(U32 i = 0; i < width; ++i)
+		{
+			std::string key = llformat("child %d", i);
+			root[key] = LLSD::emptyMap();
+			fillmap(root[key], width, depth - 1);
+		}
+	}
+	
+	void TestLLSDSerializeData::doRoundTripTests(const std::string& msg)
+	{
+		LLSD v;
+		checkRoundTrip(msg + " undefined", v);
+		
+		v = true;
+		checkRoundTrip(msg + " true bool", v);
+		
+		v = false;
+		checkRoundTrip(msg + " false bool", v);
+		
+		v = 1;
+		checkRoundTrip(msg + " positive int", v);
+		
+		v = 0;
+		checkRoundTrip(msg + " zero int", v);
+		
+		v = -1;
+		checkRoundTrip(msg + " negative int", v);
+		
+		v = 1234.5f;
+		checkRoundTrip(msg + " positive float", v);
+		
+		v = 0.0f;
+		checkRoundTrip(msg + " zero float", v);
+		
+		v = -1234.5f;
+		checkRoundTrip(msg + " negative float", v);
+		
+		// FIXME: need a NaN test
+		
+		v = LLUUID::null;
+		checkRoundTrip(msg + " null uuid", v);
+		
+		LLUUID newUUID;
+		newUUID.generate();
+		v = newUUID;
+		checkRoundTrip(msg + " new uuid", v);
+		
+		v = "";
+		checkRoundTrip(msg + " empty string", v);
+		
+		v = "some string";
+		checkRoundTrip(msg + " non-empty string", v);
+		
+		v =
+"Second Life is a 3-D virtual world entirely built and owned by its residents. "
+"Since opening to the public in 2003, it has grown explosively and today is "
+"inhabited by nearly 100,000 people from around the globe.\n"
+"\n"
+"From the moment you enter the World you'll discover a vast digital continent, "
+"teeming with people, entertainment, experiences and opportunity. Once you've "
+"explored a bit, perhaps you'll find a perfect parcel of land to build your "
+"house or business.\n"
+"\n"
+"You'll also be surrounded by the Creations of your fellow residents. Because "
+"residents retain the rights to their digital creations, they can buy, sell "
+"and trade with other residents.\n"
+"\n"
+"The Marketplace currently supports millions of US dollars in monthly "
+"transactions. This commerce is handled with the in-world currency, the Linden "
+"dollar, which can be converted to US dollars at several thriving online "
+"currency exchanges.\n"
+"\n"
+"Welcome to Second Life. We look forward to seeing you in-world!\n"
+		;
+		checkRoundTrip(msg + " long string", v);
+
+		static const U32 block_size = 0x000020;
+		for (U32 block = 0x000000; block <= 0x10ffff; block += block_size)
+		{
+			std::ostringstream out;
+			
+			for (U32 c = block; c < block + block_size; ++c)
+			{
+				if (c <= 0x000001f
+					&& c != 0x000009
+					&& c != 0x00000a)
+				{
+					// see XML standard, sections 2.2 and 4.1
+					continue;
+				}
+				if (0x00d800 <= c  &&  c <= 0x00dfff) { continue; }
+				if (0x00fdd0 <= c  &&  c <= 0x00fdef) { continue; }
+				if ((c & 0x00fffe) == 0x00fffe) { continue; }		
+					// see Unicode standard, section 15.8 
+				
+				if (c <= 0x00007f)
+				{
+					out << (char)(c & 0x7f);
+				}
+				else if (c <= 0x0007ff)
+				{
+					out << (char)(0xc0 | ((c >> 6) & 0x1f));
+					out << (char)(0x80 | ((c >> 0) & 0x3f));
+				}
+				else if (c <= 0x00ffff)
+				{
+					out << (char)(0xe0 | ((c >> 12) & 0x0f));
+					out << (char)(0x80 | ((c >>  6) & 0x3f));
+					out << (char)(0x80 | ((c >>  0) & 0x3f));
+				}
+				else
+				{
+					out << (char)(0xf0 | ((c >> 18) & 0x07));
+					out << (char)(0x80 | ((c >> 12) & 0x3f));
+					out << (char)(0x80 | ((c >>  6) & 0x3f));
+					out << (char)(0x80 | ((c >>  0) & 0x3f));
+				}
+			}
+			
+			v = out.str();
+
+			std::ostringstream blockmsg;
+			blockmsg << msg << " unicode string block 0x" << std::hex << block; 
+			checkRoundTrip(blockmsg.str(), v);
+		}
+		
+		LLDate epoch;
+		v = epoch;
+		checkRoundTrip(msg + " epoch date", v);
+		
+		LLDate aDay("2002-12-07T05:07:15.00Z");
+		v = aDay;
+		checkRoundTrip(msg + " date", v);
+		
+		LLURI path("http://slurl.com/secondlife/Ambleside/57/104/26/");
+		v = path;
+		checkRoundTrip(msg + " url", v);
+		
+		const char source[] = "it must be a blue moon again";
+		std::vector<U8> data;
+		copy(&source[0], &source[sizeof(source)], back_inserter(data));
+		
+		v = data;
+		checkRoundTrip(msg + " binary", v);
+		
+		v = LLSD::emptyMap();
+		checkRoundTrip(msg + " empty map", v);
+		
+		v = LLSD::emptyMap();
+		v["name"] = "luke";		//v.insert("name", "luke");
+		v["age"] = 3;			//v.insert("age", 3);
+		checkRoundTrip(msg + " map", v);
+		
+		v.clear();
+		v["a"]["1"] = true;
+		v["b"]["0"] = false;
+		checkRoundTrip(msg + " nested maps", v);
+		
+		v = LLSD::emptyArray();
+		checkRoundTrip(msg + " empty array", v);
+		
+		v = LLSD::emptyArray();
+		v.append("ali");
+		v.append(28);
+		checkRoundTrip(msg + " array", v);
+		
+		v.clear();
+		v[0][0] = true;
+		v[1][0] = false;
+		checkRoundTrip(msg + " nested arrays", v);
+
+		v = LLSD::emptyMap();
+		fillmap(v, 10, 6); // 10^6 maps
+		checkRoundTrip(msg + " many nested maps", v);
+	}
+	
+	typedef tut::test_group<TestLLSDSerializeData> TestLLSDSerialzeGroup;
+	typedef TestLLSDSerialzeGroup::object TestLLSDSerializeObject;
+	TestLLSDSerialzeGroup gTestLLSDSerializeGroup("llsd serialization");
+
+	template<> template<> 
+	void TestLLSDSerializeObject::test<1>()
+	{
+		mFormatter = new LLSDNotationFormatter();
+		mParser = new LLSDNotationParser();
+		doRoundTripTests("notation serialization");
+	}
+	
+	template<> template<> 
+	void TestLLSDSerializeObject::test<2>()
+	{
+		mFormatter = new LLSDXMLFormatter();
+		mParser = new LLSDXMLParser();
+		doRoundTripTests("xml serialization");
+	}
+	
+	template<> template<> 
+	void TestLLSDSerializeObject::test<3>()
+	{
+		mFormatter = new LLSDBinaryFormatter();
+		mParser = new LLSDBinaryParser();
+		doRoundTripTests("binary serialization");
+	}
+
+
+	/**
+	 * @class TestLLSDParsing
+	 * @brief Base class for of a parse tester.
+	 */
+	template <class parser_t>
+	class TestLLSDParsing
+	{
+	public:
+		TestLLSDParsing()
+		{
+			mParser = new parser_t;
+		}
+
+		void ensureParse(
+			const std::string& msg,
+			const std::string& in,
+			const LLSD& expected_value,
+			S32 expected_count)
+		{
+			std::stringstream input;
+			input.str(in);
+
+			LLSD parsed_result;
+			mParser->reset();	// reset() call is needed since test code re-uses mParser
+			S32 parsed_count = mParser->parse(input, parsed_result, in.size());
+			ensure_equals(msg.c_str(), parsed_result, expected_value);
+
+			// This count check is really only useful for expected
+			// parse failures, since the ensures equal will already
+			// require eqality.
+			std::string count_msg(msg);
+			count_msg += " (count)";
+			ensure_equals(count_msg, parsed_count, expected_count);
+		}
+
+		LLPointer<parser_t> mParser;
+	};
+
+
+	/**
+	 * @class TestLLSDXMLParsing
+	 * @brief Concrete instance of a parse tester.
+	 */
+	class TestLLSDXMLParsing : public TestLLSDParsing<LLSDXMLParser>
+	{
+	public:
+		TestLLSDXMLParsing() {}
+	};
+	
+	typedef tut::test_group<TestLLSDXMLParsing> TestLLSDXMLParsingGroup;
+	typedef TestLLSDXMLParsingGroup::object TestLLSDXMLParsingObject;
+	TestLLSDXMLParsingGroup gTestLLSDXMLParsingGroup("llsd XML parsing");
+
+	template<> template<> 
+	void TestLLSDXMLParsingObject::test<1>()
+	{
+		// test handling of xml not recognized as llsd results in an
+		// LLSD Undefined
+		ensureParse(
+			"malformed xml",
+			"<llsd><string>ha ha</string>",
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+		ensureParse(
+			"not llsd",
+			"<html><body><p>ha ha</p></body></html>",
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+		ensureParse(
+			"value without llsd",
+			"<string>ha ha</string>",
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+		ensureParse(
+			"key without llsd",
+			"<key>ha ha</key>",
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+	}
+	
+	
+	template<> template<> 
+	void TestLLSDXMLParsingObject::test<2>()
+	{
+		// test handling of unrecognized or unparseable llsd values
+		LLSD v;
+		v["amy"] = 23;
+		v["bob"] = LLSD();
+		v["cam"] = 1.23;
+		
+		ensureParse(
+			"unknown data type",
+			"<llsd><map>"
+				"<key>amy</key><integer>23</integer>"
+				"<key>bob</key><bigint>99999999999999999</bigint>"
+				"<key>cam</key><real>1.23</real>"
+			"</map></llsd>",
+			v,
+			v.size() + 1);
+	}
+	
+	template<> template<> 
+	void TestLLSDXMLParsingObject::test<3>()
+	{
+		// test handling of nested bad data
+		
+		LLSD v;
+		v["amy"] = 23;
+		v["cam"] = 1.23;
+		
+		ensureParse(
+			"map with html",
+			"<llsd><map>"
+				"<key>amy</key><integer>23</integer>"
+				"<html><body>ha ha</body></html>"
+				"<key>cam</key><real>1.23</real>"
+			"</map></llsd>",
+			v,
+			v.size() + 1);
+			
+		v.clear();
+		v["amy"] = 23;
+		v["cam"] = 1.23;
+		ensureParse(
+			"map with value for key",
+			"<llsd><map>"
+				"<key>amy</key><integer>23</integer>"
+				"<string>ha ha</string>"
+				"<key>cam</key><real>1.23</real>"
+			"</map></llsd>",
+			v,
+			v.size() + 1);
+			
+		v.clear();
+		v["amy"] = 23;
+		v["bob"] = LLSD::emptyMap();
+		v["cam"] = 1.23;
+		ensureParse(
+			"map with map of html",
+			"<llsd><map>"
+				"<key>amy</key><integer>23</integer>"
+				"<key>bob</key>"
+				"<map>"
+					"<html><body>ha ha</body></html>"
+				"</map>"
+				"<key>cam</key><real>1.23</real>"
+			"</map></llsd>",
+			v,
+			v.size() + 1);
+
+		v.clear();
+		v[0] = 23;
+		v[1] = LLSD();
+		v[2] = 1.23;
+		
+		ensureParse(
+			"array value of html",
+			"<llsd><array>"
+				"<integer>23</integer>"
+				"<html><body>ha ha</body></html>"
+				"<real>1.23</real>"
+			"</array></llsd>",
+			v,
+			v.size() + 1);
+			
+		v.clear();
+		v[0] = 23;
+		v[1] = LLSD::emptyMap();
+		v[2] = 1.23;
+		ensureParse(
+			"array with map of html",
+			"<llsd><array>"
+				"<integer>23</integer>"
+				"<map>"
+					"<html><body>ha ha</body></html>"
+				"</map>"
+				"<real>1.23</real>"
+			"</array></llsd>",
+			v,
+			v.size() + 1);
+	}
+
+	/*
+	TODO:
+		test XML parsing
+			binary with unrecognized encoding
+			nested LLSD tags
+			multiple values inside an LLSD
+	*/
+
+
+	/**
+	 * @class TestLLSDNotationParsing
+	 * @brief Concrete instance of a parse tester.
+	 */
+	class TestLLSDNotationParsing : public TestLLSDParsing<LLSDNotationParser>
+	{
+	public:
+		TestLLSDNotationParsing() {}
+	};
+
+	typedef tut::test_group<TestLLSDNotationParsing> TestLLSDNotationParsingGroup;
+	typedef TestLLSDNotationParsingGroup::object TestLLSDNotationParsingObject;
+	TestLLSDNotationParsingGroup gTestLLSDNotationParsingGroup(
+		"llsd notation parsing");
+
+	template<> template<> 
+	void TestLLSDNotationParsingObject::test<1>()
+	{
+		// test handling of xml not recognized as llsd results in an
+		// LLSD Undefined
+		ensureParse(
+			"malformed notation map",
+			"{'ha ha'",
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+		ensureParse(
+			"malformed notation array",
+			"['ha ha'",
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+		ensureParse(
+			"malformed notation string",
+			"'ha ha",
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+		ensureParse(
+			"bad notation noise",
+			"g48ejlnfr",
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+	}
+
+	template<> template<> 
+	void TestLLSDNotationParsingObject::test<2>()
+	{
+		ensureParse("valid undef", "!", LLSD(), 1);
+	}
+
+	template<> template<> 
+	void TestLLSDNotationParsingObject::test<3>()
+	{
+		LLSD val = false;
+		ensureParse("valid boolean false 0", "false", val, 1);
+		ensureParse("valid boolean false 1", "f", val, 1);
+		ensureParse("valid boolean false 2", "0", val, 1);
+		ensureParse("valid boolean false 3", "F", val, 1);
+		ensureParse("valid boolean false 4", "FALSE", val, 1);
+		val = true;
+		ensureParse("valid boolean true 0", "true", val, 1);
+		ensureParse("valid boolean true 1", "t", val, 1);
+		ensureParse("valid boolean true 2", "1", val, 1);
+		ensureParse("valid boolean true 3", "T", val, 1);
+		ensureParse("valid boolean true 4", "TRUE", val, 1);
+
+		val.clear();
+		ensureParse("invalid true", "TR", val, LLSDParser::PARSE_FAILURE);
+		ensureParse("invalid false", "FAL", val, LLSDParser::PARSE_FAILURE);
+	}
+
+	template<> template<> 
+	void TestLLSDNotationParsingObject::test<4>()
+	{
+		LLSD val = 123;
+		ensureParse("valid integer", "i123", val, 1);
+		val.clear();
+		ensureParse("invalid integer", "421", val, LLSDParser::PARSE_FAILURE);
+	}
+
+	template<> template<> 
+	void TestLLSDNotationParsingObject::test<5>()
+	{
+		LLSD val = 456.7;
+		ensureParse("valid real", "r456.7", val, 1);
+		val.clear();
+		ensureParse("invalid real", "456.7", val, LLSDParser::PARSE_FAILURE);
+	}
+
+	template<> template<> 
+	void TestLLSDNotationParsingObject::test<6>()
+	{
+		LLUUID id;
+		LLSD val = id;
+		ensureParse(
+			"unparseable uuid",
+			"u123",
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+		id.generate();
+		val = id;
+		std::string uuid_str("u");
+		uuid_str += id.asString();
+		ensureParse("valid uuid", uuid_str.c_str(), val, 1);
+	}
+
+	template<> template<> 
+	void TestLLSDNotationParsingObject::test<7>()
+	{
+		LLSD val = std::string("foolish");
+		ensureParse("valid string 1", "\"foolish\"", val, 1);
+		val = std::string("g'day");
+		ensureParse("valid string 2", "\"g'day\"", val, 1);
+		val = std::string("have a \"nice\" day");
+		ensureParse("valid string 3", "'have a \"nice\" day'", val, 1);
+		val = std::string("whatever");
+		ensureParse("valid string 4", "s(8)\"whatever\"", val, 1);
+	}
+
+	template<> template<> 
+	void TestLLSDNotationParsingObject::test<8>()
+	{
+		ensureParse(
+			"invalid string 1",
+			"s(7)\"whatever\"",
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+		ensureParse(
+			"invalid string 2",
+			"s(9)\"whatever\"",
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+	}
+
+	template<> template<> 
+	void TestLLSDNotationParsingObject::test<9>()
+	{
+		LLSD val = LLURI("http://www.google.com");
+		ensureParse("valid uri", "l\"http://www.google.com\"", val, 1);
+	}
+
+	template<> template<> 
+	void TestLLSDNotationParsingObject::test<10>()
+	{
+		LLSD val = LLDate("2007-12-28T09:22:53.10Z");
+		ensureParse("valid date", "d\"2007-12-28T09:22:53.10Z\"", val, 1);
+	}
+
+	template<> template<> 
+	void TestLLSDNotationParsingObject::test<11>()
+	{
+		std::vector<U8> vec;
+		vec.push_back((U8)'a'); vec.push_back((U8)'b'); vec.push_back((U8)'c');
+		vec.push_back((U8)'3'); vec.push_back((U8)'2'); vec.push_back((U8)'1');
+		LLSD val = vec;
+		ensureParse("valid binary b64", "b64\"YWJjMzIx\"", val, 1);
+		ensureParse("valid bainry b16", "b16\"616263333231\"", val, 1);
+		ensureParse("valid bainry raw", "b(6)\"abc321\"", val, 1);
+	}
+
+	template<> template<> 
+	void TestLLSDNotationParsingObject::test<12>()
+	{
+		ensureParse(
+			"invalid -- binary length specified too long",
+			"b(7)\"abc321\"",
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+		ensureParse(
+			"invalid -- binary length specified way too long",
+			"b(1000000)\"abc321\"",
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+	}
+
+	template<> template<> 
+	void TestLLSDNotationParsingObject::test<13>()
+	{
+		LLSD val;
+		val["amy"] = 23;
+		val["bob"] = LLSD();
+		val["cam"] = 1.23;
+		ensureParse("simple map", "{'amy':i23,'bob':!,'cam':r1.23}", val, 4);
+
+		val["bob"] = LLSD::emptyMap();
+		val["bob"]["vehicle"] = std::string("bicycle");
+		ensureParse(
+			"nested map",
+			"{'amy':i23,'bob':{'vehicle':'bicycle'},'cam':r1.23}",
+			val,
+			5);
+	}
+
+	template<> template<> 
+	void TestLLSDNotationParsingObject::test<14>()
+	{
+		LLSD val;
+		val.append(23);
+		val.append(LLSD());
+		val.append(1.23);
+		ensureParse("simple array", "[i23,!,r1.23]", val, 4);
+		val[1] = LLSD::emptyArray();
+		val[1].append("bicycle");
+		ensureParse("nested array", "[i23,['bicycle'],r1.23]", val, 5);
+	}
+
+	template<> template<> 
+	void TestLLSDNotationParsingObject::test<15>()
+	{
+		LLSD val;
+		val["amy"] = 23;
+		val["bob"]["dogs"] = LLSD::emptyArray();
+		val["bob"]["dogs"].append(LLSD::emptyMap());
+		val["bob"]["dogs"][0]["name"] = std::string("groove");
+		val["bob"]["dogs"][0]["breed"] = std::string("samoyed");
+		val["bob"]["dogs"].append(LLSD::emptyMap());
+		val["bob"]["dogs"][1]["name"] = std::string("greyley");
+		val["bob"]["dogs"][1]["breed"] = std::string("chow/husky");
+		val["cam"] = 1.23;
+		ensureParse(
+			"nested notation",
+			"{'amy':i23,"
+			" 'bob':{'dogs':["
+			         "{'name':'groove', 'breed':'samoyed'},"
+			         "{'name':'greyley', 'breed':'chow/husky'}]},"
+			" 'cam':r1.23}",
+			val,
+			11);
+	}
+
+	template<> template<> 
+	void TestLLSDNotationParsingObject::test<16>()
+	{
+		// text to make sure that incorrect sizes bail because 
+		std::string bad_str("s(5)\"hi\"");
+		ensureParse(
+			"size longer than bytes left",
+			bad_str,
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+	}
+
+	template<> template<> 
+	void TestLLSDNotationParsingObject::test<17>()
+	{
+		// text to make sure that incorrect sizes bail because 
+		std::string bad_bin("b(5)\"hi\"");
+		ensureParse(
+			"size longer than bytes left",
+			bad_bin,
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+	}
+
+	/**
+	 * @class TestLLSDBinaryParsing
+	 * @brief Concrete instance of a parse tester.
+	 */
+	class TestLLSDBinaryParsing : public TestLLSDParsing<LLSDBinaryParser>
+	{
+	public:
+		TestLLSDBinaryParsing() {}
+	};
+
+	typedef tut::test_group<TestLLSDBinaryParsing> TestLLSDBinaryParsingGroup;
+	typedef TestLLSDBinaryParsingGroup::object TestLLSDBinaryParsingObject;
+	TestLLSDBinaryParsingGroup gTestLLSDBinaryParsingGroup(
+		"llsd binary parsing");
+
+	template<> template<> 
+	void TestLLSDBinaryParsingObject::test<1>()
+	{
+		std::vector<U8> vec;
+		vec.resize(6);
+		vec[0] = 'a'; vec[1] = 'b'; vec[2] = 'c';
+		vec[3] = '3'; vec[4] = '2'; vec[5] = '1';
+		std::string string_expected((char*)&vec[0], vec.size());
+		LLSD value = string_expected;
+
+		vec.resize(11);
+		vec[0] = 's'; // for string
+		vec[5] = 'a'; vec[6] = 'b'; vec[7] = 'c';
+		vec[8] = '3'; vec[9] = '2'; vec[10] = '1';
+
+		uint32_t size = htonl(6);
+		memcpy(&vec[1], &size, sizeof(uint32_t));
+		std::string str_good((char*)&vec[0], vec.size());
+		ensureParse("correct string parse", str_good, value, 1);
+
+		size = htonl(7);
+		memcpy(&vec[1], &size, sizeof(uint32_t));
+		std::string str_bad_1((char*)&vec[0], vec.size());
+		ensureParse(
+			"incorrect size string parse",
+			str_bad_1,
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+
+		size = htonl(100000);
+		memcpy(&vec[1], &size, sizeof(uint32_t));
+		std::string str_bad_2((char*)&vec[0], vec.size());
+		ensureParse(
+			"incorrect size string parse",
+			str_bad_2,
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+	}
+
+	template<> template<> 
+	void TestLLSDBinaryParsingObject::test<2>()
+	{
+		std::vector<U8> vec;
+		vec.resize(6);
+		vec[0] = 'a'; vec[1] = 'b'; vec[2] = 'c';
+		vec[3] = '3'; vec[4] = '2'; vec[5] = '1';
+		LLSD value = vec;
+		
+		vec.resize(11);
+		vec[0] = 'b';  // for binary
+		vec[5] = 'a'; vec[6] = 'b'; vec[7] = 'c';
+		vec[8] = '3'; vec[9] = '2'; vec[10] = '1';
+
+		uint32_t size = htonl(6);
+		memcpy(&vec[1], &size, sizeof(uint32_t));
+		std::string str_good((char*)&vec[0], vec.size());
+		ensureParse("correct binary parse", str_good, value, 1);
+
+		size = htonl(7);
+		memcpy(&vec[1], &size, sizeof(uint32_t));
+		std::string str_bad_1((char*)&vec[0], vec.size());
+		ensureParse(
+			"incorrect size binary parse 1",
+			str_bad_1,
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+
+		size = htonl(100000);
+		memcpy(&vec[1], &size, sizeof(uint32_t));
+		std::string str_bad_2((char*)&vec[0], vec.size());
+		ensureParse(
+			"incorrect size binary parse 2",
+			str_bad_2,
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+	}
+
+	template<> template<> 
+	void TestLLSDBinaryParsingObject::test<3>()
+	{
+		// test handling of xml not recognized as llsd results in an
+		// LLSD Undefined
+		ensureParse(
+			"malformed binary map",
+			"{'ha ha'",
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+		ensureParse(
+			"malformed binary array",
+			"['ha ha'",
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+		ensureParse(
+			"malformed binary string",
+			"'ha ha",
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+		ensureParse(
+			"bad noise",
+			"g48ejlnfr",
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+	}
+	template<> template<> 
+	void TestLLSDBinaryParsingObject::test<4>()
+	{
+		ensureParse("valid undef", "!", LLSD(), 1);
+	}
+
+	template<> template<> 
+	void TestLLSDBinaryParsingObject::test<5>()
+	{
+		LLSD val = false;
+		ensureParse("valid boolean false 2", "0", val, 1);
+		val = true;
+		ensureParse("valid boolean true 2", "1", val, 1);
+
+		val.clear();
+		ensureParse("invalid true", "t", val, LLSDParser::PARSE_FAILURE);
+		ensureParse("invalid false", "f", val, LLSDParser::PARSE_FAILURE);
+	}
+
+	template<> template<> 
+	void TestLLSDBinaryParsingObject::test<6>()
+	{
+		std::vector<U8> vec;
+		vec.push_back('{');
+		vec.resize(vec.size() + 4);
+		uint32_t size = htonl(1);
+		memcpy(&vec[1], &size, sizeof(uint32_t));
+		vec.push_back('k');
+		int key_size_loc = vec.size();
+		size = htonl(1); // 1 too short
+		vec.resize(vec.size() + 4);
+		memcpy(&vec[key_size_loc], &size, sizeof(uint32_t));
+		vec.push_back('a'); vec.push_back('m'); vec.push_back('y');
+		vec.push_back('i');
+		int integer_loc = vec.size();
+		vec.resize(vec.size() + 4);
+		uint32_t val_int = htonl(23);
+		memcpy(&vec[integer_loc], &val_int, sizeof(uint32_t));
+		std::string str_bad_1((char*)&vec[0], vec.size());
+		ensureParse(
+			"invalid key size",
+			str_bad_1,
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+
+		// check with correct size, but unterminated map (missing '}')
+		size = htonl(3); // correct size
+		memcpy(&vec[key_size_loc], &size, sizeof(uint32_t));
+		std::string str_bad_2((char*)&vec[0], vec.size());
+		ensureParse(
+			"valid key size, unterminated map",
+			str_bad_2,
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+
+		// check w/ correct size and correct map termination
+		LLSD val;
+		val["amy"] = 23;
+		vec.push_back('}');
+		std::string str_good((char*)&vec[0], vec.size());
+		ensureParse(
+			"valid map",
+			str_good,
+			val,
+			2);
+
+		// check w/ incorrect sizes and correct map termination
+		size = htonl(0); // 1 too few (for the map entry)
+		memcpy(&vec[1], &size, sizeof(uint32_t));
+		std::string str_bad_3((char*)&vec[0], vec.size());
+		ensureParse(
+			"invalid map too long",
+			str_bad_3,
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+
+		size = htonl(2); // 1 too many
+		memcpy(&vec[1], &size, sizeof(uint32_t));
+		std::string str_bad_4((char*)&vec[0], vec.size());
+		ensureParse(
+			"invalid map too short",
+			str_bad_4,
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+	}
+
+	template<> template<> 
+	void TestLLSDBinaryParsingObject::test<7>()
+	{
+		std::vector<U8> vec;
+		vec.push_back('[');
+		vec.resize(vec.size() + 4);
+		uint32_t size = htonl(1); // 1 too short
+		memcpy(&vec[1], &size, sizeof(uint32_t));
+		vec.push_back('"'); vec.push_back('a'); vec.push_back('m');
+		vec.push_back('y'); vec.push_back('"'); vec.push_back('i');
+		int integer_loc = vec.size();
+		vec.resize(vec.size() + 4);
+		uint32_t val_int = htonl(23);
+		memcpy(&vec[integer_loc], &val_int, sizeof(uint32_t));
+
+		std::string str_bad_1((char*)&vec[0], vec.size());
+		ensureParse(
+			"invalid array size",
+			str_bad_1,
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+
+		// check with correct size, but unterminated map (missing ']')
+		size = htonl(2); // correct size
+		memcpy(&vec[1], &size, sizeof(uint32_t));
+		std::string str_bad_2((char*)&vec[0], vec.size());
+		ensureParse(
+			"unterminated array",
+			str_bad_2,
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+
+		// check w/ correct size and correct map termination
+		LLSD val;
+		val.append("amy");
+		val.append(23);
+		vec.push_back(']');
+		std::string str_good((char*)&vec[0], vec.size());
+		ensureParse(
+			"valid array",
+			str_good,
+			val,
+			3);
+
+		// check with too many elements
+		size = htonl(3); // 1 too long
+		memcpy(&vec[1], &size, sizeof(uint32_t));
+		std::string str_bad_3((char*)&vec[0], vec.size());
+		ensureParse(
+			"array too short",
+			str_bad_3,
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+	}
+
+	template<> template<> 
+	void TestLLSDBinaryParsingObject::test<8>()
+	{
+		std::vector<U8> vec;
+		vec.push_back('{');
+		vec.resize(vec.size() + 4);
+		memset(&vec[1], 0, 4);
+		vec.push_back('}');
+		std::string str_good((char*)&vec[0], vec.size());
+		LLSD val = LLSD::emptyMap();
+		ensureParse(
+			"empty map",
+			str_good,
+			val,
+			1);
+	}
+
+	template<> template<> 
+	void TestLLSDBinaryParsingObject::test<9>()
+	{
+		std::vector<U8> vec;
+		vec.push_back('[');
+		vec.resize(vec.size() + 4);
+		memset(&vec[1], 0, 4);
+		vec.push_back(']');
+		std::string str_good((char*)&vec[0], vec.size());
+		LLSD val = LLSD::emptyArray();
+		ensureParse(
+			"empty array",
+			str_good,
+			val,
+			1);
+	}
+
+	template<> template<> 
+	void TestLLSDBinaryParsingObject::test<10>()
+	{
+		std::vector<U8> vec;
+		vec.push_back('l');
+		vec.resize(vec.size() + 4);
+		uint32_t size = htonl(14); // 1 too long
+		memcpy(&vec[1], &size, sizeof(uint32_t));
+		vec.push_back('h'); vec.push_back('t'); vec.push_back('t');
+		vec.push_back('p'); vec.push_back(':'); vec.push_back('/');
+		vec.push_back('/'); vec.push_back('s'); vec.push_back('l');
+		vec.push_back('.'); vec.push_back('c'); vec.push_back('o');
+		vec.push_back('m');
+		std::string str_bad((char*)&vec[0], vec.size());
+		ensureParse(
+			"invalid uri length size",
+			str_bad,
+			LLSD(),
+			LLSDParser::PARSE_FAILURE);
+
+		LLSD val;
+		val = LLURI("http://sl.com");
+		size = htonl(13); // correct length
+		memcpy(&vec[1], &size, sizeof(uint32_t));
+		std::string str_good((char*)&vec[0], vec.size());
+		ensureParse(
+			"valid key size",
+			str_good,
+			val,
+			1);
+	}
+
+/*
+	template<> template<> 
+	void TestLLSDBinaryParsingObject::test<11>()
+	{
+	}
+*/
+
+   /**
+	 * @class TestLLSDCrossCompatible
+	 * @brief Miscellaneous serialization and parsing tests
+	 */
+	class TestLLSDCrossCompatible
+	{
+	public:
+		TestLLSDCrossCompatible() {}
+
+		void ensureBinaryAndNotation(
+			const std::string& msg,
+			const LLSD& input)
+		{
+			// to binary, and back again
+			std::stringstream str1;
+			S32 count1 = LLSDSerialize::toBinary(input, str1);
+			LLSD actual_value_bin;
+			S32 count2 = LLSDSerialize::fromBinary(
+				actual_value_bin,
+				str1,
+				LLSDSerialize::SIZE_UNLIMITED);
+			ensure_equals(
+				"ensureBinaryAndNotation binary count",
+				count2,
+				count1);
+
+			// to notation and back again
+			std::stringstream str2;
+			S32 count3 = LLSDSerialize::toNotation(actual_value_bin, str2);
+			ensure_equals(
+				"ensureBinaryAndNotation notation count1",
+				count3,
+				count2);
+			LLSD actual_value_notation;
+			S32 count4 = LLSDSerialize::fromNotation(
+				actual_value_notation,
+				str2,
+				LLSDSerialize::SIZE_UNLIMITED);
+			ensure_equals(
+				"ensureBinaryAndNotation notation count2",
+				count4,
+				count3);
+			ensure_equals(
+				(msg + " (binaryandnotation)").c_str(),
+				actual_value_notation,
+				input);
+		}
+
+		void ensureBinaryAndXML(
+			const std::string& msg,
+			const LLSD& input)
+		{
+			// to binary, and back again
+			std::stringstream str1;
+			S32 count1 = LLSDSerialize::toBinary(input, str1);
+			LLSD actual_value_bin;
+			S32 count2 = LLSDSerialize::fromBinary(
+				actual_value_bin,
+				str1,
+				LLSDSerialize::SIZE_UNLIMITED);
+			ensure_equals(
+				"ensureBinaryAndXML binary count",
+				count2,
+				count1);
+
+			// to xml and back again
+			std::stringstream str2;
+			S32 count3 = LLSDSerialize::toXML(actual_value_bin, str2);
+			ensure_equals(
+				"ensureBinaryAndXML xml count1",
+				count3,
+				count2);
+			LLSD actual_value_xml;
+			S32 count4 = LLSDSerialize::fromXML(actual_value_xml, str2);
+			ensure_equals(
+				"ensureBinaryAndXML xml count2",
+				count4,
+				count3);
+			ensure_equals((msg + " (binaryandxml)").c_str(), actual_value_xml, input);
+		}
+	};
+
+	typedef tut::test_group<TestLLSDCrossCompatible> TestLLSDCompatibleGroup;
+	typedef TestLLSDCompatibleGroup::object TestLLSDCompatibleObject;
+	TestLLSDCompatibleGroup gTestLLSDCompatibleGroup(
+		"llsd serialize compatible");
+
+	template<> template<> 
+	void TestLLSDCompatibleObject::test<1>()
+	{
+		LLSD test;
+		ensureBinaryAndNotation("undef", test);
+		ensureBinaryAndXML("undef", test);
+		test = true;
+		ensureBinaryAndNotation("boolean true", test);
+		ensureBinaryAndXML("boolean true", test);
+		test = false;
+		ensureBinaryAndNotation("boolean false", test);
+		ensureBinaryAndXML("boolean false", test);
+		test = 0;
+		ensureBinaryAndNotation("integer zero", test);
+		ensureBinaryAndXML("integer zero", test);
+		test = 1;
+		ensureBinaryAndNotation("integer positive", test);
+		ensureBinaryAndXML("integer positive", test);
+		test = -234567;
+		ensureBinaryAndNotation("integer negative", test);
+		ensureBinaryAndXML("integer negative", test);
+		test = 0.0;
+		ensureBinaryAndNotation("real zero", test);
+		ensureBinaryAndXML("real zero", test);
+		test = 1.0;
+		ensureBinaryAndNotation("real positive", test);
+		ensureBinaryAndXML("real positive", test);
+		test = -1.0;
+		ensureBinaryAndNotation("real negative", test);
+		ensureBinaryAndXML("real negative", test);
+	}
+
+	template<> template<> 
+	void TestLLSDCompatibleObject::test<2>()
+	{
+		LLSD test;
+		test = "foobar";
+		ensureBinaryAndNotation("string", test);
+		ensureBinaryAndXML("string", test);
+	}
+
+	template<> template<> 
+	void TestLLSDCompatibleObject::test<3>()
+	{
+		LLSD test;
+		LLUUID id;
+		id.generate();
+		test = id;
+		ensureBinaryAndNotation("uuid", test);
+		ensureBinaryAndXML("uuid", test);
+	}
+
+	template<> template<> 
+	void TestLLSDCompatibleObject::test<4>()
+	{
+		LLSD test;
+		test = LLDate(12345.0);
+		ensureBinaryAndNotation("date", test);
+		ensureBinaryAndXML("date", test);
+	}
+
+	template<> template<> 
+	void TestLLSDCompatibleObject::test<5>()
+	{
+		LLSD test;
+		test = LLURI("http://www.secondlife.com/");
+		ensureBinaryAndNotation("uri", test);
+		ensureBinaryAndXML("uri", test);
+	}
+
+	template<> template<> 
+	void TestLLSDCompatibleObject::test<6>()
+	{
+		LLSD test;
+		typedef std::vector<U8> buf_t;
+		buf_t val;
+		for(int ii = 0; ii < 100; ++ii)
+		{
+			srand(ii);		/* Flawfinder: ignore */
+			S32 size = rand() % 100 + 10;
+			std::generate_n(
+				std::back_insert_iterator<buf_t>(val),
+				size,
+				rand);
+		}
+		test = val;
+		ensureBinaryAndNotation("binary", test);
+		ensureBinaryAndXML("binary", test);
+	}
+
+	template<> template<> 
+	void TestLLSDCompatibleObject::test<7>()
+	{
+		LLSD test;
+		test = LLSD::emptyArray();
+		test.append(1);
+		test.append("hello");
+		ensureBinaryAndNotation("array", test);
+		ensureBinaryAndXML("array", test);
+	}
+
+	template<> template<> 
+	void TestLLSDCompatibleObject::test<8>()
+	{
+		LLSD test;
+		test = LLSD::emptyArray();
+		test["foo"] = "bar";
+		test["baz"] = 100;
+		ensureBinaryAndNotation("map", test);
+		ensureBinaryAndXML("map", test);
+	}
+}
+
diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
index 1e8b5517e41..31ea747f526 100644
--- a/indra/llmessage/CMakeLists.txt
+++ b/indra/llmessage/CMakeLists.txt
@@ -205,39 +205,35 @@ list(APPEND llmessage_SOURCE_FILES ${llmessage_HEADER_FILES})
 
 add_library (llmessage ${llmessage_SOURCE_FILES})
 target_link_libraries(
-    llmessage
-    ${CURL_LIBRARIES}
-    ${CARES_LIBRARIES}
-    ${OPENSSL_LIBRARIES}
-    ${CRYPTO_LIBRARIES}
-    ${XMLRPCEPI_LIBRARIES}
-    )
+  llmessage
+  ${CURL_LIBRARIES}
+  ${CARES_LIBRARIES}
+  ${OPENSSL_LIBRARIES}
+  ${CRYPTO_LIBRARIES}
+  ${XMLRPCEPI_LIBRARIES}
+  )
 
-IF (NOT LINUX AND VIEWER)
-    # When building the viewer the tests links against the shared objects. 
-    # These can not be found when we try to run the tests, so we had to disable them, for the viewer build.
-    # TODO: Can someone with viewer knowledge figure out how to make these find the correct so.
-    SET(llmessage_TEST_SOURCE_FILES
-      # llhttpclientadapter.cpp
-      lltrustedmessageservice.cpp
-      lltemplatemessagedispatcher.cpp
-      )
+SET(llmessage_TEST_SOURCE_FILES
+  # llhttpclientadapter.cpp
+  llnamevalue.cpp
+  lltrustedmessageservice.cpp
+  lltemplatemessagedispatcher.cpp
+  )
 #    set(TEST_DEBUG on)
-    set(test_libs
-      ${LLMESSAGE_LIBRARIES}
-      ${WINDOWS_LIBRARIES}
-      ${LLVFS_LIBRARIES}
-      ${LLMATH_LIBRARIES}
-      ${LLCOMMON_LIBRARIES}
-      )
+set(test_libs
+  ${LLMESSAGE_LIBRARIES}
+  ${WINDOWS_LIBRARIES}
+  ${LLVFS_LIBRARIES}
+  ${LLMATH_LIBRARIES}
+  ${LLCOMMON_LIBRARIES}
+  )
 
-    LL_ADD_INTEGRATION_TEST(
-      llsdmessage
-      "llsdmessage.cpp"
-      "${test_libs}"
-      ${PYTHON_EXECUTABLE}
-      "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llsdmessage_peer.py"
-      )
+LL_ADD_INTEGRATION_TEST(
+  llsdmessage
+  "llsdmessage.cpp"
+  "${test_libs}"
+  ${PYTHON_EXECUTABLE}
+  "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llsdmessage_peer.py"
+  )
 
-    LL_ADD_PROJECT_UNIT_TESTS(llmessage "${llmessage_TEST_SOURCE_FILES}")
-ENDIF (NOT LINUX AND VIEWER)
+LL_ADD_PROJECT_UNIT_TESTS(llmessage "${llmessage_TEST_SOURCE_FILES}")
diff --git a/indra/llmessage/tests/llnamevalue_test.cpp b/indra/llmessage/tests/llnamevalue_test.cpp
new file mode 100644
index 00000000000..3146e7f979a
--- /dev/null
+++ b/indra/llmessage/tests/llnamevalue_test.cpp
@@ -0,0 +1,412 @@
+/** 
+ * @file llnamevalue_tut.cpp
+ * @author Adroit
+ * @date 2007-02
+ * @brief LLNameValue unit test
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ * 
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llsdserialize.h"
+
+#include "../llnamevalue.h"
+
+#include "../test/lltut.h"
+
+
+#if LL_WINDOWS
+// disable unreachable code warnings
+#pragma warning(disable: 4702)
+#endif
+
+namespace tut
+{
+	struct namevalue_test
+	{
+		namevalue_test() 
+		{			
+		}
+ 	};
+	typedef test_group<namevalue_test> namevalue_t;
+	typedef namevalue_t::object namevalue_object_t;
+	tut::namevalue_t tut_namevalue("namevalue_test");
+
+	
+	template<> template<>
+	void namevalue_object_t::test<1>()
+	{
+		// LLNameValue()
+		LLNameValue nValue;
+		ensure("mName should have been NULL", nValue.mName == NULL);
+		ensure("getTypeEnum failed",nValue.getTypeEnum() == NVT_NULL);
+		ensure("getClassEnum failed",nValue.getClassEnum() == NVC_NULL);
+		ensure("getSendtoEnum failed",nValue.getSendtoEnum() == NVS_NULL);
+
+		LLNameValue nValue1(" SecondLife ASSET RW SIM 232324343");
+
+	}
+
+	// LLNameValue(const char* data);
+	// 	LLNameValue(const char* name, const char* data, const char* type, const char* nvclass, const char* nvsendto, 
+	//				TNameValueCallback nvcb = NULL, void** user_data = NULL);
+	template<> template<>
+	void namevalue_object_t::test<2>()
+	{
+		LLNameValue nValue(" SecondLife ASSET RW S 232324343");
+		ensure("mName not set correctly", (0 == strcmp(nValue.mName,"SecondLife")));
+		ensure("getTypeEnum failed", nValue.getTypeEnum() == NVT_ASSET);
+		ensure("getClassEnum failed", nValue.getClassEnum() == NVC_READ_WRITE);
+		ensure("getSendtoEnum failed", nValue.getSendtoEnum() == NVS_SIM);
+		ensure("getString failed", (0==strcmp(nValue.getAsset(),"232324343")));
+		ensure("sendToData or sendToViewer failed", !nValue.sendToData() && !nValue.sendToViewer());
+		
+		LLNameValue nValue1("\n\r SecondLife_1 STRING READ_WRITE SIM 232324343");
+		ensure("1. mName not set correctly", (0 == strcmp(nValue1.mName,"SecondLife_1")));
+		ensure("1. getTypeEnum failed", nValue1.getTypeEnum() == NVT_STRING);
+		ensure("1. getClassEnum failed", nValue1.getClassEnum() == NVC_READ_WRITE);
+		ensure("1. getSendtoEnum failed", nValue1.getSendtoEnum() == NVS_SIM);
+		ensure("1. getString failed", (0==strcmp(nValue1.getString(),"232324343")));
+		ensure("1. sendToData or sendToViewer failed", !nValue1.sendToData() && !nValue1.sendToViewer());
+
+		LLNameValue nValue2("SecondLife", "23.5", "F32", "R", "DS");
+		ensure("2. getTypeEnum failed", nValue2.getTypeEnum() == NVT_F32);
+		ensure("2. getClassEnum failed", nValue2.getClassEnum() == NVC_READ_ONLY);
+		ensure("2. getSendtoEnum failed", nValue2.getSendtoEnum() == NVS_DATA_SIM);
+		ensure("2. getF32 failed", *nValue2.getF32() == 23.5f);
+		ensure("2. sendToData or sendToViewer failed", nValue2.sendToData() && !nValue2.sendToViewer());
+
+		LLNameValue nValue3("SecondLife", "-43456787", "S32", "READ_ONLY", "SIM_SPACE");
+		ensure("3. getTypeEnum failed", nValue3.getTypeEnum() == NVT_S32);
+		ensure("3. getClassEnum failed", nValue3.getClassEnum() == NVC_READ_ONLY);
+		ensure("3. getSendtoEnum failed", nValue3.getSendtoEnum() == NVS_DATA_SIM);
+		ensure("3. getS32 failed", *nValue3.getS32() == -43456787);
+		ensure("sendToData or sendToViewer failed", nValue3.sendToData() && !nValue3.sendToViewer());
+
+		LLNameValue nValue4("SecondLife", "<1.0, 2.0, 3.0>", "VEC3", "RW", "SV");
+		LLVector3 llvec4(1.0, 2.0, 3.0);
+		ensure("4. getTypeEnum failed", nValue4.getTypeEnum() == NVT_VEC3);
+		ensure("4. getClassEnum failed", nValue4.getClassEnum() == NVC_READ_WRITE);
+		ensure("4. getSendtoEnum failed", nValue4.getSendtoEnum() == NVS_SIM_VIEWER);
+		ensure("4. getVec3 failed", *nValue4.getVec3() == llvec4);
+		ensure("4. sendToData or sendToViewer failed", !nValue4.sendToData() && nValue4.sendToViewer());
+
+		LLNameValue nValue5("SecondLife", "-1.0, 2.4, 3", "VEC3", "RW", "SIM_VIEWER");
+		LLVector3 llvec5(-1.0f, 2.4f, 3);
+		ensure("5. getTypeEnum failed", nValue5.getTypeEnum() == NVT_VEC3);
+		ensure("5. getClassEnum failed", nValue5.getClassEnum() == NVC_READ_WRITE);
+		ensure("5. getSendtoEnum failed", nValue5.getSendtoEnum() == NVS_SIM_VIEWER);
+		ensure("5. getVec3 failed", *nValue5.getVec3() == llvec5);
+		ensure("5. sendToData or sendToViewer failed", !nValue5.sendToData() && nValue5.sendToViewer());
+
+		LLNameValue nValue6("SecondLife", "89764323", "U32", "RW", "DSV");
+		ensure("6. getTypeEnum failed", nValue6.getTypeEnum() == NVT_U32);
+		ensure("6. getClassEnum failed", nValue6.getClassEnum() == NVC_READ_WRITE);
+		ensure("6. getSendtoEnum failed", nValue6.getSendtoEnum() == NVS_DATA_SIM_VIEWER);
+		ensure("6. getU32 failed", *nValue6.getU32() == 89764323);
+		ensure("6. sendToData or sendToViewer failed", nValue6.sendToData() && nValue6.sendToViewer());
+
+		LLNameValue nValue7("SecondLife", "89764323323232", "U64", "RW", "SIM_SPACE_VIEWER");
+		U64 u64_7 = U64L(89764323323232);
+		ensure("7. getTypeEnum failed", nValue7.getTypeEnum() == NVT_U64);
+		ensure("7. getClassEnum failed", nValue7.getClassEnum() == NVC_READ_WRITE);
+		ensure("7. getSendtoEnum failed", nValue7.getSendtoEnum() == NVS_DATA_SIM_VIEWER);
+		ensure("7. getU32 failed", *nValue7.getU64() == u64_7);
+		ensure("7. sendToData or sendToViewer failed", nValue7.sendToData() && nValue7.sendToViewer());
+	}
+
+	// LLNameValue(const char* name, const char* data, const char* type, const char* nvclass, 
+	//				TNameValueCallback nvcb = NULL, void** user_data = NULL);
+	template<> template<>
+	void namevalue_object_t::test<3>()
+	{
+		LLNameValue nValue("SecondLife", "232324343", "ASSET", "READ_WRITE");
+		ensure("mName not set correctly", (0 == strcmp(nValue.mName,"SecondLife")));
+		ensure("getTypeEnum failed", nValue.getTypeEnum() == NVT_ASSET);
+		ensure("getClassEnum failed", nValue.getClassEnum() == NVC_READ_WRITE);
+		ensure("getSendtoEnum failed", nValue.getSendtoEnum() == NVS_SIM);
+		ensure("getString failed", (0==strcmp(nValue.getAsset(),"232324343")));
+
+		LLNameValue nValue1("SecondLife", "232324343", "STRING", "READ_WRITE");
+		ensure("1. mName not set correctly", (0 == strcmp(nValue1.mName,"SecondLife")));
+		ensure("1. getTypeEnum failed", nValue1.getTypeEnum() == NVT_STRING);
+		ensure("1. getClassEnum failed", nValue1.getClassEnum() == NVC_READ_WRITE);
+		ensure("1. getSendtoEnum failed", nValue1.getSendtoEnum() == NVS_SIM);
+		ensure("1. getString failed", (0==strcmp(nValue1.getString(),"232324343")));
+
+		LLNameValue nValue2("SecondLife", "23.5", "F32", "R");
+		ensure("2. getTypeEnum failed", nValue2.getTypeEnum() == NVT_F32);
+		ensure("2. getClassEnum failed", nValue2.getClassEnum() == NVC_READ_ONLY);
+		ensure("2. getSendtoEnum failed", nValue2.getSendtoEnum() == NVS_SIM);
+		ensure("2. getF32 failed", *nValue2.getF32() == 23.5f);
+
+		LLNameValue nValue3("SecondLife", "-43456787", "S32", "READ_ONLY");
+		ensure("3. getTypeEnum failed", nValue3.getTypeEnum() == NVT_S32);
+		ensure("3. getClassEnum failed", nValue3.getClassEnum() == NVC_READ_ONLY);
+		ensure("3. getSendtoEnum failed", nValue3.getSendtoEnum() == NVS_SIM);
+		ensure("3. getS32 failed", *nValue3.getS32() == -43456787);
+
+		LLNameValue nValue4("SecondLife", "<1.0, 2.0, 3.0>", "VEC3", "RW");
+		LLVector3 llvec4(1.0, 2.0, 3.0);
+		ensure("4. getTypeEnum failed", nValue4.getTypeEnum() == NVT_VEC3);
+		ensure("4. getClassEnum failed", nValue4.getClassEnum() == NVC_READ_WRITE);
+		ensure("4. getSendtoEnum failed", nValue4.getSendtoEnum() == NVS_SIM);
+		ensure("4. getVec3 failed", *nValue4.getVec3() == llvec4);
+
+		LLNameValue nValue5("SecondLife", "-1.0, 2.4, 3", "VEC3", "RW");
+		LLVector3 llvec5(-1.0f, 2.4f, 3);
+		ensure("5. getTypeEnum failed", nValue5.getTypeEnum() == NVT_VEC3);
+		ensure("5. getClassEnum failed", nValue5.getClassEnum() == NVC_READ_WRITE);
+		ensure("5. getSendtoEnum failed", nValue5.getSendtoEnum() == NVS_SIM);
+		ensure("5. getVec3 failed", *nValue5.getVec3() == llvec5);
+
+		LLNameValue nValue6("SecondLife", "89764323", "U32", "RW");
+		ensure("6. getTypeEnum failed", nValue6.getTypeEnum() == NVT_U32);
+		ensure("6. getClassEnum failed", nValue6.getClassEnum() == NVC_READ_WRITE);
+		ensure("6. getSendtoEnum failed", nValue6.getSendtoEnum() == NVS_SIM);
+		ensure("6. getU32 failed", *nValue6.getU32() == 89764323);
+
+		LLNameValue nValue7("SecondLife", "89764323323232", "U64", "RW");
+		U64 u64_7 = U64L(89764323323232);
+		ensure("7. getTypeEnum failed", nValue7.getTypeEnum() == NVT_U64);
+		ensure("7. getClassEnum failed", nValue7.getClassEnum() == NVC_READ_WRITE);
+		ensure("7. getSendtoEnum failed", nValue7.getSendtoEnum() == NVS_SIM);
+		ensure("7. getU32 failed", *nValue7.getU64() == u64_7);
+	}
+
+	// LLNameValue(const char* name, const char* type, const char* nvclass, 
+	//				TNameValueCallback nvcb = NULL, void** user_data = NULL);
+	template<> template<>
+	void namevalue_object_t::test<4>()
+	{
+		LLNameValue nValue("SecondLife",  "STRING", "READ_WRITE");
+		ensure("mName not set correctly", (0 == strcmp(nValue.mName,"SecondLife")));
+		ensure("getTypeEnum failed", nValue.getTypeEnum() == NVT_STRING);
+		ensure("getClassEnum failed", nValue.getClassEnum() == NVC_READ_WRITE);
+		ensure("getSendtoEnum failed", nValue.getSendtoEnum() == NVS_SIM);
+
+		LLNameValue nValue1("SecondLife",  "ASSET", "READ_WRITE");
+		ensure("1. mName not set correctly", (0 == strcmp(nValue1.mName,"SecondLife")));
+		ensure("1. getTypeEnum for RW failed", nValue1.getTypeEnum() == NVT_ASSET);
+		ensure("1. getClassEnum for RW failed", nValue1.getClassEnum() == NVC_READ_WRITE);
+		ensure("1. getSendtoEnum for RW failed", nValue1.getSendtoEnum() == NVS_SIM);
+
+		LLNameValue nValue2("SecondLife", "F32", "READ_ONLY");
+		ensure("2. getTypeEnum failed", nValue2.getTypeEnum() == NVT_F32);
+		ensure("2. getClassEnum failed", nValue2.getClassEnum() == NVC_READ_ONLY);
+		ensure("2. getSendtoEnum failed", nValue2.getSendtoEnum() == NVS_SIM);
+
+		LLNameValue nValue3("SecondLife", "S32", "READ_ONLY");
+		ensure("3. getTypeEnum failed", nValue3.getTypeEnum() == NVT_S32);
+		ensure("3. getClassEnum failed", nValue3.getClassEnum() == NVC_READ_ONLY);
+		ensure("3. getSendtoEnum failed", nValue3.getSendtoEnum() == NVS_SIM);
+
+		LLNameValue nValue4("SecondLife", "VEC3", "READ_WRITE");
+		ensure("4. getTypeEnum failed", nValue4.getTypeEnum() == NVT_VEC3);
+		ensure("4. getClassEnum failed", nValue4.getClassEnum() == NVC_READ_WRITE);
+		ensure("4. getSendtoEnum failed", nValue4.getSendtoEnum() == NVS_SIM);
+
+		LLNameValue nValue6("SecondLife", "U32", "READ_WRITE");
+		ensure("6. getTypeEnum failed", nValue6.getTypeEnum() == NVT_U32);
+		ensure("6. getClassEnum failed", nValue6.getClassEnum() == NVC_READ_WRITE);
+		ensure("6. getSendtoEnum failed", nValue6.getSendtoEnum() == NVS_SIM);
+
+		LLNameValue nValue7("SecondLife", "U64", "READ_WRITE");
+		ensure("7. getTypeEnum failed", nValue7.getTypeEnum() == NVT_U64);
+		ensure("7. getClassEnum failed", nValue7.getClassEnum() == NVC_READ_WRITE);
+		ensure("7. getSendtoEnum failed", nValue7.getSendtoEnum() == NVS_SIM);
+	}
+
+	template<> template<>
+	void namevalue_object_t::test<5>()
+	{
+		LLNameValue nValue("SecondLife", "This is a test", "STRING", "RW", "SIM");
+
+		ensure("getString failed", (0 == strcmp(nValue.getString(),"This is a test")));
+	}
+
+	template<> template<>
+	void namevalue_object_t::test<6>()
+	{
+		LLNameValue nValue("SecondLife", "This is a test", "ASSET", "RW", "S");
+		ensure("getAsset failed", (0 == strcmp(nValue.getAsset(),"This is a test")));
+	}
+         	
+	template<> template<>
+	void namevalue_object_t::test<7>()
+	{
+		LLNameValue nValue("SecondLife", "555555", "F32", "RW", "SIM");
+		
+		ensure("getF32 failed",*nValue.getF32() == 555555.f);
+	}
+
+	template<> template<>
+	void namevalue_object_t::test<8>()
+	{
+		LLNameValue nValue("SecondLife", "-5555", "S32", "RW", "SIM");
+
+		ensure("getS32 failed", *nValue.getS32() == -5555);
+
+		S32 sVal = 0x7FFFFFFF;
+		nValue.setS32(sVal);
+		ensure("getS32 failed", *nValue.getS32() == sVal);
+
+		sVal = -0x7FFFFFFF;
+		nValue.setS32(sVal);
+		ensure("getS32 failed", *nValue.getS32() == sVal);
+
+		sVal = 0;
+		nValue.setS32(sVal);
+		ensure("getS32 failed", *nValue.getS32() == sVal);
+	}
+	
+	template<> template<>
+	void namevalue_object_t::test<9>()
+	{
+		LLNameValue nValue("SecondLife", "<-3, 2, 1>", "VEC3", "RW", "SIM");
+		LLVector3 vecExpected(-3, 2, 1);
+		LLVector3 vec;
+		nValue.getVec3(vec);
+		ensure("getVec3 failed", vec == vecExpected);
+	}
+	
+	template<> template<>
+	void namevalue_object_t::test<10>()
+	{
+		LLNameValue nValue("SecondLife", "12345678", "U32", "RW", "SIM");
+
+		ensure("getU32 failed",*nValue.getU32() == 12345678);
+
+		U32 val = 0xFFFFFFFF;
+		nValue.setU32(val);
+		ensure("U32 max", *nValue.getU32() == val);
+
+		val = 0;
+		nValue.setU32(val);		
+		ensure("U32 min", *nValue.getU32() == val);
+	}
+	
+	template<> template<>
+	void namevalue_object_t::test<11>()
+	{
+		//skip_fail("incomplete support for U64.");
+		LLNameValue nValue("SecondLife", "44444444444", "U64", "RW", "SIM");
+
+		ensure("getU64 failed",*nValue.getU64() == U64L(44444444444));
+
+		// there is no LLNameValue::setU64()  
+	}
+	
+	
+	template<> template<>
+	void namevalue_object_t::test<12>()
+	{
+		//skip_fail("incomplete support for U64.");
+		LLNameValue nValue("SecondLife U64 RW DSV 44444444444");	
+		std::string ret_str = nValue.printNameValue();
+		
+		ensure_equals("1:printNameValue failed",ret_str,"SecondLife U64 RW DSV 44444444444");
+		
+		LLNameValue nValue1(ret_str.c_str());
+		ensure_equals("Serialization of printNameValue failed", *nValue.getU64(), *nValue1.getU64());		
+	}
+
+	template<> template<>
+	void namevalue_object_t::test<13>()
+	{
+		LLNameValue nValue("SecondLife STRING RW DSV 44444444444");	
+		std::string ret_str = nValue.printData();
+		ensure_equals("1:printData failed",ret_str,"44444444444");
+
+		LLNameValue nValue1("SecondLife S32 RW DSV 44444");	
+		ret_str = nValue1.printData();
+		ensure_equals("2:printData failed",ret_str,"44444");		
+	}
+	
+	template<> template<>
+	void namevalue_object_t::test<14>()
+	{
+		LLNameValue nValue("SecodLife STRING RW SIM 22222");
+		std::ostringstream stream1,stream2,stream3, stream4, stream5;
+		stream1 << nValue;
+		ensure_equals("STRING << failed",stream1.str(),"22222");
+
+		LLNameValue nValue1("SecodLife F32 RW SIM 22222");
+		stream2 << nValue1;
+		ensure_equals("F32 << failed",stream2.str(),"22222");
+
+		LLNameValue nValue2("SecodLife S32 RW SIM 22222");
+		stream3<< nValue2;
+		ensure_equals("S32 << failed",stream3.str(),"22222");
+
+		LLNameValue nValue3("SecodLife U32 RW SIM 122222");
+		stream4<< nValue3;
+		ensure_equals("U32 << failed",stream4.str(),"122222");
+
+		// I don't think we use U64 name value pairs.  JC
+		//skip_fail("incomplete support for U64.");
+		//LLNameValue nValue4("SecodLife U64 RW SIM 22222");
+		//stream5<< nValue4;
+		//ensure("U64 << failed",0 == strcmp((stream5.str()).c_str(),"22222"));
+	}
+
+	template<> template<>
+	void namevalue_object_t::test<15>()
+	{
+		LLNameValue nValue("SecondLife", "This is a test", "ASSET", "R", "S");
+
+		ensure("getAsset failed", (0 == strcmp(nValue.getAsset(),"This is a test")));
+		// this should not have updated as it is read only.
+		nValue.setAsset("New Value should not be updated");
+		ensure("setAsset on ReadOnly failed", (0 == strcmp(nValue.getAsset(),"This is a test")));
+
+		LLNameValue nValue1("SecondLife", "1234", "U32", "R", "S");
+		// this should not have updated as it is read only.
+		nValue1.setU32(4567);
+		ensure("setU32 on ReadOnly failed", *nValue1.getU32() == 1234);
+
+		LLNameValue nValue2("SecondLife", "1234", "S32", "R", "S");
+		// this should not have updated as it is read only.
+		nValue2.setS32(4567);
+		ensure("setS32 on ReadOnly failed", *nValue2.getS32() == 1234);
+
+		LLNameValue nValue3("SecondLife", "1234", "F32", "R", "S");
+		// this should not have updated as it is read only.
+		nValue3.setF32(4567);
+		ensure("setF32 on ReadOnly failed", *nValue3.getF32() == 1234);
+
+		LLNameValue nValue4("SecondLife", "<1,2,3>", "VEC3", "R", "S");
+		// this should not have updated as it is read only.
+		LLVector3 vec(4,5,6);
+		nValue3.setVec3(vec);
+		LLVector3 vec1(1,2,3);
+		ensure("setVec3 on ReadOnly failed", *nValue4.getVec3() == vec1);
+
+		// cant test for U64 as no set64 exists nor any operators support U64 type
+	}         
+}
diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt
index a842548980b..bb33f0956dd 100644
--- a/indra/test/CMakeLists.txt
+++ b/indra/test/CMakeLists.txt
@@ -49,7 +49,6 @@ set(test_SOURCE_FILES
     llmime_tut.cpp
     llmessageconfig_tut.cpp
     llmodularmath_tut.cpp
-    llnamevalue_tut.cpp
     llpermissions_tut.cpp
     llpipeutil.cpp
     llsaleinfo_tut.cpp
@@ -57,7 +56,6 @@ set(test_SOURCE_FILES
     llsdmessagebuilder_tut.cpp
     llsdmessagereader_tut.cpp
     llsd_new_tut.cpp
-    llsdserialize_tut.cpp
     llsdutil_tut.cpp
     llservicebuilder_tut.cpp
     llstreamtools_tut.cpp
-- 
GitLab