void LLTemplateMessageBuilderTestObject::test<20>()
		// block build order !-> binary order
	{
		U8 buffer1[MAX_BUFFER_SIZE];
		memset(buffer1, 0, MAX_BUFFER_SIZE);
		U8 buffer2[MAX_BUFFER_SIZE];
		memset(buffer2, 0, MAX_BUFFER_SIZE);
		U32 bufferSize1, bufferSize2;

		// build template: Test0 before Test1
		LLMessageTemplate messageTemplate = defaultTemplate();
		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, const_cast<char*>(_PREHASH_Test0));
		builder->addU32(_PREHASH_Test0, 0xaaaa);
		builder->nextBlock(_PREHASH_Test1);
		builder->addU32(_PREHASH_Test0, 0xbbbb);
		bufferSize1 = builder->buildMessage(buffer1, MAX_BUFFER_SIZE, 0);
		delete builder;

		// build message: 1st declared block var == 0xaaaa, 2nd declared block var == 0xbbbb
		builder = defaultBuilder(messageTemplate, const_cast<char*>(_PREHASH_Test1));
		builder->addU32(_PREHASH_Test0, 0xbbbb);
		builder->nextBlock(_PREHASH_Test0);
		builder->addU32(_PREHASH_Test0, 0xaaaa);
		bufferSize2 = builder->buildMessage(buffer2, MAX_BUFFER_SIZE, 0);
		delete builder;

		ensure_equals("Ensure Buffer Sizes Equal", bufferSize1, bufferSize2);
		ensure_equals("Ensure Buffer Contents Equal", memcmp(buffer1, buffer2, bufferSize1), 0);
	}
	void LLTemplateMessageBuilderTestObject::test<44>()
		// read variable block past end of message -> 0 repeats
	{
		// build message with single block
		LLMessageTemplate messageTemplate = defaultTemplate();
		messageTemplate.addBlock(defaultBlock(MVT_U32, 4, MBT_SINGLE));
		U32 outValue, outValue2, inValue = 0xbbbbbbbb;
		LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
		builder->addU32(_PREHASH_Test0, inValue);
		const U32 bufferSize = 1024;
		U8 buffer[bufferSize];
		memset(buffer, 0xaa, bufferSize);
		memset(buffer, 0, LL_PACKET_ID_SIZE);
		U32 builtSize = builder->buildMessage(buffer, bufferSize, 0);
		delete builder;

		// add variable block to reader template
		messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test1), MVT_U32, 4));

		// read message value and check block repeat count
		numberMap[1] = &messageTemplate;
		LLTemplateMessageReader* reader = 
			new LLTemplateMessageReader(numberMap);
		reader->validateMessage(buffer, builtSize, LLHost());
		reader->readMessage(buffer, LLHost());
		reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outValue);
		outValue2 = reader->getNumberOfBlocks(_PREHASH_Test1);
		ensure_equals("Ensure present value ", outValue, inValue);
		ensure_equals("Ensure 0 repeats ", outValue2, 0);
		delete reader;
	}
	void LLTemplateMessageBuilderTestObject::test<43>()
		// read past end of message -> default values (forward compatibility)
	{
		// build message with single block
		LLMessageTemplate messageTemplate = defaultTemplate();
		messageTemplate.addBlock(defaultBlock(MVT_U32, 4, MBT_SINGLE));
		U32 outValue, outValue2, inValue = 0xbbbbbbbb;
		LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
		builder->addU32(_PREHASH_Test0, inValue);
		const U32 bufferSize = 1024;
		U8 buffer[bufferSize];
		memset(buffer, 0xaa, bufferSize);
		memset(buffer, 0, LL_PACKET_ID_SIZE);
		U32 builtSize = builder->buildMessage(buffer, bufferSize, 0);
		delete builder;

		// add block to reader template
		messageTemplate.addBlock(createBlock(_PREHASH_Test1, MVT_U32, 4, MBT_SINGLE));

		// read message value and default value
		numberMap[1] = &messageTemplate;
		LLTemplateMessageReader* reader = 
			new LLTemplateMessageReader(numberMap);
		reader->validateMessage(buffer, builtSize, LLHost());
		reader->readMessage(buffer, LLHost());
		reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outValue);
		reader->getU32(_PREHASH_Test1, _PREHASH_Test0, outValue2);
		ensure_equals("Ensure present value ", outValue, inValue);
		ensure_equals("Ensure default value ", outValue2, 0);
		delete reader;
	}
	void LLTemplateMessageBuilderTestObject::test<8>()
		 // U32
	{
		LLMessageTemplate messageTemplate = defaultTemplate();
		messageTemplate.addBlock(defaultBlock(MVT_U32, 4));
		U32 outValue, inValue = 88;
		LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
		builder->addU32(_PREHASH_Test0, inValue);
		LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
		reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outValue);
		ensure_equals("Ensure U32", inValue, outValue);
		delete reader;
	}
	void LLTemplateMessageBuilderTestObject::test<22>()
		// repeated penultimate block (crashes when data in LLDynamicArrayIndexed)
	{
		U32 inTest00 = 0, inTest01 = 1, inTest1 = 2;
		U32 outTest00, outTest01, outTest1;
		LLMessageTemplate messageTemplate = defaultTemplate();
		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);
		builder->addU32(_PREHASH_Test0, inTest01);
		builder->nextBlock(_PREHASH_Test1);
		builder->addU32(_PREHASH_Test0, inTest1);
		LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
		reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outTest00, 0);
		reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outTest01, 1);
		reader->getU32(_PREHASH_Test1, _PREHASH_Test0, outTest1);
		ensure_equals("Ensure Test0[0]", inTest00, outTest00);
		ensure_equals("Ensure Test0[1]", inTest01, outTest01);
		ensure_equals("Ensure Test1", inTest1, outTest1);
		delete reader;
	}
	void LLTemplateMessageBuilderTestObject::test<21>()
		// block appended in declaration -> data appended in binary
	{
		U8 buffer1[MAX_BUFFER_SIZE];
		memset(buffer1, 0, MAX_BUFFER_SIZE);
		U8 buffer2[MAX_BUFFER_SIZE];
		memset(buffer2, 0, MAX_BUFFER_SIZE);
		U32 bufferSize1, bufferSize2;

		// Build template: Test0 only
		LLMessageTemplate messageTemplate = defaultTemplate();
		messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test0), MVT_U32, 4, MBT_SINGLE));

		// Build message
		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(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, const_cast<char*>(_PREHASH_Test0));
		builder->addU32(_PREHASH_Test0, 0xaaaa);
		builder->nextBlock(_PREHASH_Test1);
		builder->addU32(_PREHASH_Test0, 0xbbbb);
		bufferSize2 = builder->buildMessage(buffer2, MAX_BUFFER_SIZE, 0);
		delete builder;

		ensure_not_equals("Ensure Buffer Sizes Not Equal", bufferSize1, bufferSize2);
		ensure_equals("Ensure Buffer Prefix Equal", memcmp(buffer1, buffer2, bufferSize1), 0);
		ensure_not_equals("Ensure Buffer Contents Not Equal", memcmp(buffer1, buffer2, bufferSize2), 0);
	}
	void LLTemplateMessageBuilderTestObject::test<23>()
		// variable repeated block name never accessed
	{
		U32 inTest = 1, outTest;
		LLMessageTemplate messageTemplate = defaultTemplate();
		messageTemplate.addBlock(
			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(const_cast<char*>(_PREHASH_Test1));
		ensure_equals("Ensure block count", blockCount, 0);
		ensure_equals("Ensure Test0", inTest, outTest);
		delete reader;
	}
	void LLTemplateMessageBuilderTestObject::test<24>()
		// forwarding message
	{
		// build template
		LLMessageTemplate messageTemplate = defaultTemplate();
		messageTemplate.addBlock(createBlock(const_cast<char*>(_PREHASH_Test0), MVT_U32, 4));

		// build message
		LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
		builder->addU32(_PREHASH_Test0, 42);

		// read message
		LLTemplateMessageReader* reader = setReader(messageTemplate, builder);

		// forward message
		builder = defaultBuilder(messageTemplate);
		builder->newMessage(_PREHASH_TestMessage);
		reader->copyToBuilder(*builder);
		U8 buffer[MAX_BUFFER_SIZE];
		builder->buildMessage(buffer, MAX_BUFFER_SIZE, 0);

		delete builder;
		delete reader;
	}
	void LLTemplateMessageBuilderTestObject::test<45>()
		// read variable length data past end of message -> 0 length
	{
		// build message with single block
		LLMessageTemplate messageTemplate = defaultTemplate();
		messageTemplate.addBlock(defaultBlock(MVT_U32, 4, MBT_SINGLE));
		U32 outValue, outValue2, inValue = 0xbbbbbbbb;
		LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
		builder->addU32(_PREHASH_Test0, inValue);
		const U32 bufferSize = 1024;
		U8 buffer[bufferSize];
		memset(buffer, 0xaa, bufferSize);
		memset(buffer, 0, LL_PACKET_ID_SIZE);
		U32 builtSize = builder->buildMessage(buffer, bufferSize, 0);
		delete builder;

		// add variable block to reader template
		messageTemplate.addBlock(createBlock(_PREHASH_Test1, MVT_VARIABLE, 4, 
											 MBT_SINGLE));

		// read message value and default string
		numberMap[1] = &messageTemplate;
		LLTemplateMessageReader* reader = 
			new LLTemplateMessageReader(numberMap);
		reader->validateMessage(buffer, builtSize, LLHost());
		reader->readMessage(buffer, LLHost());
		reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outValue);
		char outBuffer[bufferSize];
		memset(buffer, 0xcc, bufferSize);
		reader->getString(_PREHASH_Test1, _PREHASH_Test0, bufferSize, 
						  outBuffer);
		outValue2 = reader->getNumberOfBlocks(_PREHASH_Test1);
		ensure_equals("Ensure present value ", outValue, inValue);
		ensure_equals("Ensure unchanged buffer ", strlen(outBuffer), 0);
		delete reader;
	}