/**
 * @file llsdmessagebuilder_tut.cpp
 * @date   February 2006
 * @brief LLSDMessageBuilder unit tests
 *
 * $LicenseInfo:firstyear=2006&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#include <tut/tut.hpp>

#include "linden_common.h"
#include "lltut.h"
#include "llmessagetemplate.h"
#include "llsdmessagebuilder.h"
#include "llsdmessagereader.h"
#include "llsdtraits.h"
#include "llmath.h"
#include "llquaternion.h"
#include "u64.h"
#include "v3dmath.h"
#include "v3math.h"
#include "v4math.h"
#include "llsdutil.h"
//#include "llsdutil.cpp"
#include "llsdutil_math.cpp"
#include "lltemplatemessagebuilder.h"

namespace tut
{
    static LLTemplateMessageBuilder::message_template_name_map_t templateNameMap;

    LLMsgData* messageData = NULL;
    LLMsgBlkData* messageBlockData = NULL;

    struct LLSDMessageBuilderTestData {

        LLSDMessageBuilderTestData()
        {
            messageData = new LLMsgData("testMessage");
            messageBlockData = new LLMsgBlkData("testBlock", 0);
        }

        static LLSDMessageBuilder defaultBuilder()
        {
            LLSDMessageBuilder builder;
            builder.newMessage("name");
            builder.nextBlock("block");
            return builder;
        }

        static LLSDMessageReader setReader(const LLSDMessageBuilder& builder)
        {
            LLSDMessageReader reader;
            reader.setMessage("name", builder.getMessage());
            return reader;
        }

        static void addValue(LLMsgBlkData* mbd, char* name, void* v, EMsgVariableType type, int size, int data_size = -1)
        {
            LLMsgVarData tmp(name, type);
            tmp.addData(v, size, type, data_size);
            mbd->mMemberVarData[name] = tmp;
        }


        static LLMessageBlock* defaultTemplateBlock(const EMsgVariableType type = MVT_NULL, const S32 size = 0, EMsgBlockType block = MBT_VARIABLE)
        {
            return createTemplateBlock(_PREHASH_Test0, type, size, block);
        }

        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(const_cast<char*>(_PREHASH_Test0), type, size);
            }
            return result;
        }

        static LLTemplateMessageBuilder* defaultTemplateBuilder(LLMessageTemplate& messageTemplate, char* name = const_cast<char*>(_PREHASH_Test0))
        {
            templateNameMap[_PREHASH_TestMessage] = &messageTemplate;
            LLTemplateMessageBuilder* builder = new LLTemplateMessageBuilder(templateNameMap);
            builder->newMessage(_PREHASH_TestMessage);
            builder->nextBlock(name);
            return builder;
        }

        static LLMessageTemplate defaultTemplate()
        {
            return LLMessageTemplate(_PREHASH_TestMessage, 1, MFT_HIGH);
        }
    };

    typedef test_group<LLSDMessageBuilderTestData>  LLSDMessageBuilderTestGroup;
    typedef LLSDMessageBuilderTestGroup::object     LLSDMessageBuilderTestObject;
    LLSDMessageBuilderTestGroup llsdMessageBuilderTestGroup("LLSDMessageBuilder");

    template<> template<>
    void LLSDMessageBuilderTestObject::test<1>()
        // construction and test of undefined
    {
      LLSDMessageBuilder builder = defaultBuilder();
      LLSDMessageReader reader = setReader(builder);
    }

    template<> template<>
    void LLSDMessageBuilderTestObject::test<2>()
         // bool
    {
      bool outValue, inValue = true;
      LLSDMessageBuilder builder = defaultBuilder();
      builder.addBOOL("var", inValue);
      LLSDMessageReader reader = setReader(builder);
      reader.getBOOL("block", "var", outValue);
      ensure_equals("Ensure bool", inValue, outValue);
    }

    template<> template<>
    void LLSDMessageBuilderTestObject::test<3>()
         // U8
    {
      U8 outValue, inValue = 2;
      LLSDMessageBuilder builder = defaultBuilder();
      builder.addU8("var", inValue);
      LLSDMessageReader reader = setReader(builder);
      reader.getU8("block", "var", outValue);
      ensure_equals("Ensure U8", inValue, outValue);
    }

    template<> template<>
    void LLSDMessageBuilderTestObject::test<4>()
         // S16
    {
      S16 outValue, inValue = 90;
      LLSDMessageBuilder builder = defaultBuilder();
      builder.addS16("var", inValue);
      LLSDMessageReader reader = setReader(builder);
      reader.getS16("block", "var", outValue);
      ensure_equals("Ensure S16", inValue, outValue);
    }

    template<> template<>
    void LLSDMessageBuilderTestObject::test<5>()
         // U16
    {
      U16 outValue, inValue = 3;
      LLSDMessageBuilder builder = defaultBuilder();
      builder.addU16("var", inValue);
      LLSDMessageReader reader = setReader(builder);
      reader.getU16("block", "var", outValue);
      ensure_equals("Ensure U16", inValue, outValue);
    }

    template<> template<>
    void LLSDMessageBuilderTestObject::test<6>()
         // S32
    {
      S32 outValue, inValue = 44;
      LLSDMessageBuilder builder = defaultBuilder();
      builder.addS32("var", inValue);
      LLSDMessageReader reader = setReader(builder);
      reader.getS32("block", "var", outValue);
      ensure_equals("Ensure S32", inValue, outValue);
    }

    template<> template<>
    void LLSDMessageBuilderTestObject::test<7>()
         // F32
    {
      F32 outValue, inValue = 121.44f;
      LLSDMessageBuilder builder = defaultBuilder();
      builder.addF32("var", inValue);
      LLSDMessageReader reader = setReader(builder);
      reader.getF32("block", "var", outValue);
      ensure_equals("Ensure F32", inValue, outValue);
    }

    template<> template<>
    void LLSDMessageBuilderTestObject::test<8>()
         // U32
    {
      U32 outValue, inValue = 88;
      LLSDMessageBuilder builder = defaultBuilder();
      builder.addU32("var", inValue);
      LLSDMessageReader reader = setReader(builder);
      reader.getU32("block", "var", outValue);
      ensure_equals("Ensure U32", inValue, outValue);
    }

    template<> template<>
    void LLSDMessageBuilderTestObject::test<9>()
         // U64
    {
      U64 outValue, inValue = 121;
      LLSDMessageBuilder builder = defaultBuilder();
      builder.addU64("var", inValue);
      LLSDMessageReader reader = setReader(builder);
      reader.getU64("block", "var", outValue);
      ensure_equals("Ensure U64", inValue, outValue);
    }

    template<> template<>
    void LLSDMessageBuilderTestObject::test<10>()
         // F64
    {
      F64 outValue, inValue = 3232143.33;
      LLSDMessageBuilder builder = defaultBuilder();
      builder.addF64("var", inValue);
      LLSDMessageReader reader = setReader(builder);
      reader.getF64("block", "var", outValue);
      ensure_equals("Ensure F64", inValue, outValue);
    }

    template<> template<>
    void LLSDMessageBuilderTestObject::test<11>()
         // Vector3
    {
      LLVector3 outValue, inValue = LLVector3(1,2,3);
      LLSDMessageBuilder builder = defaultBuilder();
      builder.addVector3("var", inValue);
      LLSDMessageReader reader = setReader(builder);
      reader.getVector3("block", "var", outValue);
      ensure_equals("Ensure Vector3", inValue, outValue);
    }

    template<> template<>
    void LLSDMessageBuilderTestObject::test<12>()
         // Vector4
    {
      LLVector4 outValue, inValue = LLVector4(1,2,3,4);
      LLSDMessageBuilder builder = defaultBuilder();
      builder.addVector4("var", inValue);
      LLSDMessageReader reader = setReader(builder);
      reader.getVector4("block", "var", outValue);
      ensure_equals("Ensure Vector4", inValue, outValue);
    }

    template<> template<>
    void LLSDMessageBuilderTestObject::test<13>()
         // Vector3d
    {
      LLVector3d outValue, inValue = LLVector3d(1,2,3);
      LLSDMessageBuilder builder = defaultBuilder();
      builder.addVector3d("var", inValue);
      LLSDMessageReader reader = setReader(builder);
      reader.getVector3d("block", "var", outValue);
      ensure_equals("Ensure Vector3d", inValue, outValue);
    }

    template<> template<>
    void LLSDMessageBuilderTestObject::test<14>()
         // Quaternion
    {
      LLQuaternion outValue, inValue = LLQuaternion(1,LLVector3(2,3,4));
      LLSDMessageBuilder builder = defaultBuilder();
      builder.addQuat("var", inValue);
      LLSDMessageReader reader = setReader(builder);
      reader.getQuat("block", "var", outValue);
      ensure_equals("Ensure Quaternion", inValue, outValue);
    }

    template<> template<>
    void LLSDMessageBuilderTestObject::test<15>()
         // UUID
    {
      LLUUID outValue, inValue;
      inValue.generate();
      LLSDMessageBuilder builder = defaultBuilder();
      builder.addUUID("var", inValue);
      LLSDMessageReader reader = setReader(builder);
      reader.getUUID("block", "var", outValue);
      ensure_equals("Ensure UUID", inValue, outValue);
    }

    template<> template<>
    void LLSDMessageBuilderTestObject::test<16>()
         // IPAddr
    {
      U32 outValue, inValue = 12344556;
      LLSDMessageBuilder builder = defaultBuilder();
      builder.addIPAddr("var", inValue);
      LLSDMessageReader reader = setReader(builder);
      reader.getIPAddr("block", "var", outValue);
      ensure_equals("Ensure IPAddr", inValue, outValue);
    }

     template<> template<>
    void LLSDMessageBuilderTestObject::test<17>()
         // IPPort
    {
         U16 outValue, inValue = 80;
      LLSDMessageBuilder builder = defaultBuilder();
      builder.addIPPort("var", inValue);
      LLSDMessageReader reader = setReader(builder);
      reader.getIPPort("block", "var", outValue);
      ensure_equals("Ensure IPPort", inValue, outValue);
    }

    template<> template<>
    void LLSDMessageBuilderTestObject::test<18>()
    {
         std::string outValue, inValue = "testing";
      LLSDMessageBuilder builder = defaultBuilder();
      builder.addString("var", inValue.c_str());
      LLSDMessageReader reader = setReader(builder);
      char buffer[MAX_STRING];
      reader.getString("block", "var", MAX_STRING, buffer);
      outValue = buffer;
      ensure_equals("Ensure String", inValue, outValue);
    }

    template<> template<>
    void LLSDMessageBuilderTestObject::test<19>()
    {
      LLMsgBlkData* mbd = new LLMsgBlkData("testBlock", 0);
      LLMsgData* md = new LLMsgData("testMessage");
      md->addBlock(mbd);
      LLSDMessageBuilder builder = defaultBuilder();

      builder.copyFromMessageData(*md);
      LLSD output = builder.getMessage();

      ensure("Ensure message block created when copied from legacy message to llsd", output["testBlock"].isDefined());
    }

    // MVT_FIXED
    template<> template<>
    void LLSDMessageBuilderTestObject::test<20>()
    {
      char binData[] = "abcdefghijklmnop";

      addValue(messageBlockData, (char *)"testBinData", &binData, MVT_FIXED, sizeof(binData));
      messageData->addBlock(messageBlockData);
      LLSDMessageBuilder builder = defaultBuilder();

      builder.copyFromMessageData(*messageData);
      LLSD output = builder.getMessage();

      std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
      ensure("Ensure MVT_S16Array data copied from legacy to llsd give a valid vector", v.size() > 0);

      ensure_memory_matches("Ensure fixed binary data works in a message copied from legacy to llsd",
          &v[0], sizeof(binData), binData, sizeof(binData));
    }

    // MVT_VARIABLE data_size 1 (U8's)
    template<> template<>
    void LLSDMessageBuilderTestObject::test<21>()
    {
     /* U8 binData[] = "abcdefghijklmnop";

      addValue(messageBlockData, "testBinData", &binData, MVT_VARIABLE, sizeof(binData), 1);
      messageData->addBlock(messageBlockData);
      LLSDMessageBuilder builder = defaultBuilder();

      builder.copyFromMessageData(*messageData);
      LLSD output = builder.getMessage();

      std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
      ensure("Ensure MVT_S16Array data copied from legacy to llsd give a valid vector", v.size() > 0);

      ensure_memory_matches("Ensure MVT_VARIABLE U8 binary data works in a message copied from legacy to llsd",
          &v[0], sizeof(binData), binData, sizeof(binData));*/
    }

    // MVT_VARIABLE data_size 2 (U16's)
    template<> template<>
    void LLSDMessageBuilderTestObject::test<22>()
    {
      U16 binData[] = {1,2,3,4,5,6,7,8,9}; //9 shorts

      addValue(messageBlockData, (char *)"testBinData", &binData, MVT_VARIABLE, sizeof(binData) >> 1, 2);
      messageData->addBlock(messageBlockData);
      LLSDMessageBuilder builder = defaultBuilder();

      builder.copyFromMessageData(*messageData);
      LLSD output = builder.getMessage();

      std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
      ensure("Ensure MVT_S16Array data copied from legacy to llsd give a valid vector", v.size() > 0);

      ensure_memory_matches("Ensure MVT_VARIABLE U16 binary data works in a message copied from legacy to llsd",
          &v[0], sizeof(binData) >> 1, binData, sizeof(binData) >> 1);
    }

    // MVT_VARIABLE data_size 4 (S32's)
    template<> template<>
    void LLSDMessageBuilderTestObject::test<23>()
    {
      U32 binData[] = {9,8,7,6,5,4,3,2,1};

      addValue(messageBlockData, (char *)"testBinData", &binData, MVT_VARIABLE, sizeof(binData) >> 2, 4);
      messageData->addBlock(messageBlockData);
      LLSDMessageBuilder builder = defaultBuilder();

      builder.copyFromMessageData(*messageData);
      LLSD output = builder.getMessage();

      std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
      ensure("Ensure MVT_S16Array data copied from legacy to llsd give a valid vector", v.size() > 0);

      ensure_memory_matches("Ensure MVT_VARIABLE S32 binary data works in a message copied from legacy to llsd",
          &v[0], sizeof(binData) >> 2, binData, sizeof(binData) >> 2);
    }

    // MVT_U8
    template<> template<>
    void LLSDMessageBuilderTestObject::test<24>()
    {
      U8 data = 0xa5;

      addValue(messageBlockData, (char *)"testBinData", &data, MVT_U8, sizeof(data));
      messageData->addBlock(messageBlockData);
      LLSDMessageBuilder builder = defaultBuilder();

      builder.copyFromMessageData(*messageData);
      LLSD output = builder.getMessage();

      ensure_equals("Ensure MVT_U8 data works in a message copied from legacy to llsd",
          output["testBlock"][0]["testBinData"].asInteger(), data);
    }

    // MVT_U16
    template<> template<>
    void LLSDMessageBuilderTestObject::test<25>()
    {
      U16 data = 0xa55a;

      addValue(messageBlockData, (char *)"testBinData", &data, MVT_U16, sizeof(data));
      messageData->addBlock(messageBlockData);
      LLSDMessageBuilder builder = defaultBuilder();

      builder.copyFromMessageData(*messageData);
      LLSD output = builder.getMessage();

      ensure_equals("Ensure MVT_U16 data works in a message copied from legacy to llsd",
          output["testBlock"][0]["testBinData"].asInteger(), data);
    }

    // MVT_U32
    template<> template<>
    void LLSDMessageBuilderTestObject::test<26>()
    {
      U32 data = 0xa55a7117;

      addValue(messageBlockData, (char *)"testBinData", &data, MVT_U32, sizeof(data));
      messageData->addBlock(messageBlockData);
      LLSDMessageBuilder builder = defaultBuilder();

      builder.copyFromMessageData(*messageData);
      LLSD output = builder.getMessage();

      ensure_equals("Ensure MVT_U32 data works in a message copied from legacy to llsd",
          ll_U32_from_sd(output["testBlock"][0]["testBinData"]), data);
    }

    // MVT_U64 - crush into an s32: LLSD does not support 64 bit values
    template<> template<>
    void LLSDMessageBuilderTestObject::test<27>()
    {
      U64 data = U64L(0xa55a711711223344);
      addValue(messageBlockData, (char *)"testBinData", &data, MVT_U64, sizeof(data));
      messageData->addBlock(messageBlockData);
      LLSDMessageBuilder builder = defaultBuilder();

      builder.copyFromMessageData(*messageData);
      LLSD output = builder.getMessage();

      ensure_equals("Ensure MVT_U64 data works in a message copied from legacy to llsd",
          ll_U64_from_sd(output["testBlock"][0]["testBinData"]), data);
    }

    // MVT_S8
    template<> template<>
    void LLSDMessageBuilderTestObject::test<28>()
    {
      S8 data = -31;

      addValue(messageBlockData, (char *)"testBinData", &data, MVT_S8, sizeof(data));
      messageData->addBlock(messageBlockData);
      LLSDMessageBuilder builder = defaultBuilder();

      builder.copyFromMessageData(*messageData);
      LLSD output = builder.getMessage();

      ensure_equals("Ensure MVT_S8 data works in a message copied from legacy to llsd",
          output["testBlock"][0]["testBinData"].asInteger(), data);
    }

    // MVT_S16
    template<> template<>
    void LLSDMessageBuilderTestObject::test<29>()
    {
      S16 data = -31;

      addValue(messageBlockData, (char *)"testBinData", &data, MVT_S16, sizeof(data));
      messageData->addBlock(messageBlockData);
      LLSDMessageBuilder builder = defaultBuilder();

      builder.copyFromMessageData(*messageData);
      LLSD output = builder.getMessage();

      ensure_equals("Ensure MVT_S16 data works in a message copied from legacy to llsd",
          output["testBlock"][0]["testBinData"].asInteger(), data);
    }

    // MVT_S32
    template<> template<>
    void LLSDMessageBuilderTestObject::test<30>()
    {
      S32 data = -3100;

      addValue(messageBlockData, (char *)"testBinData", &data, MVT_S32, sizeof(data));
      messageData->addBlock(messageBlockData);
      LLSDMessageBuilder builder = defaultBuilder();

      builder.copyFromMessageData(*messageData);
      LLSD output = builder.getMessage();

      ensure_equals("Ensure MVT_S32 data works in a message copied from legacy to llsd",
          output["testBlock"][0]["testBinData"].asInteger(), data);
    }

    // MVT_S64 - crush into an s32: LLSD does not support 64 bit values
    template<> template<>
    void LLSDMessageBuilderTestObject::test<31>()
    {
      S64 data = -31003100;

      addValue(messageBlockData, (char *)"testBinData", &data, MVT_S64, sizeof(data));
      messageData->addBlock(messageBlockData);
      LLSDMessageBuilder builder = defaultBuilder();

      builder.copyFromMessageData(*messageData);
      LLSD output = builder.getMessage();

      ensure_equals("Ensure MVT_S64 data works in a message copied from legacy to llsd",
          output["testBlock"][0]["testBinData"].asInteger(), (S32)data);
    }

    // MVT_F32
    template<> template<>
    void LLSDMessageBuilderTestObject::test<32>()
    {
      F32 data = 1234.1234f;

      addValue(messageBlockData, (char *)"testBinData", &data, MVT_F32, sizeof(data));
      messageData->addBlock(messageBlockData);
      LLSDMessageBuilder builder = defaultBuilder();

      builder.copyFromMessageData(*messageData);
      LLSD output = builder.getMessage();

      ensure_equals("Ensure MVT_F32 data works in a message copied from legacy to llsd",
          output["testBlock"][0]["testBinData"].asReal(), data);
    }

    // MVT_F64
    template<> template<>
    void LLSDMessageBuilderTestObject::test<33>()
    {
      F64 data = 1234.1234;

      addValue(messageBlockData, (char *)"testBinData", &data, MVT_F64, sizeof(data));
      messageData->addBlock(messageBlockData);
      LLSDMessageBuilder builder = defaultBuilder();

      builder.copyFromMessageData(*messageData);
      LLSD output = builder.getMessage();

      ensure_equals("Ensure MVT_F64 data works in a message copied from legacy to llsd",
          output["testBlock"][0]["testBinData"].asReal(), data);
    }

    // MVT_LLVector3
    template<> template<>
    void LLSDMessageBuilderTestObject::test<34>()
    {
      LLVector3 data(1,2,3);

      addValue(messageBlockData, (char *)"testBinData", &data, MVT_LLVector3, sizeof(data));
      messageData->addBlock(messageBlockData);
      LLSDMessageBuilder builder = defaultBuilder();

      builder.copyFromMessageData(*messageData);
      LLSD output = builder.getMessage();

      ensure_equals("Ensure MVT_LLVector3 data works in a message copied from legacy to llsd",
          ll_vector3_from_sd(output["testBlock"][0]["testBinData"]), data);
    }

    // MVT_LLVector3d
    template<> template<>
    void LLSDMessageBuilderTestObject::test<35>()
    {
      LLVector3d data(1,2,3);

      addValue(messageBlockData, (char *)"testBinData", &data, MVT_LLVector3d, sizeof(data));
      messageData->addBlock(messageBlockData);
      LLSDMessageBuilder builder = defaultBuilder();

      builder.copyFromMessageData(*messageData);
      LLSD output = builder.getMessage();

      ensure_equals("Ensure MVT_LLVector3 data works in a message copied from legacy to llsd",
          ll_vector3d_from_sd(output["testBlock"][0]["testBinData"]), data);
    }

    // MVT_LLVector4
    template<> template<>
    void LLSDMessageBuilderTestObject::test<36>()
    {
      LLVector4 data(1,2,3,4);
      LLSD v = ll_sd_from_vector4(data);

      addValue(messageBlockData, (char *)"testBinData", &data, MVT_LLVector4, sizeof(data));
      messageData->addBlock(messageBlockData);
      LLSDMessageBuilder builder = defaultBuilder();

      builder.copyFromMessageData(*messageData);
      LLSD output = builder.getMessage();

      ensure_equals("Ensure MVT_LLVector4 data works in a message copied from legacy to llsd",
          output["testBlock"][0]["testBinData"], v);
    }

    // MVT_LLQuaternion
    template<> template<>
    void LLSDMessageBuilderTestObject::test<37>()
    {
      LLQuaternion data(0.3713907f, 0.5570861f, 0.7427813f,0.0f);

      //we send a quaternion packed into a vec3 (w is infered) - so sizeof(vec) == 12 bytes not 16.
      LLVector3 vec = data.packToVector3();

      addValue(messageBlockData, (char *)"testBinData", &vec, MVT_LLQuaternion, sizeof(vec));
      messageData->addBlock(messageBlockData);
      LLSDMessageBuilder builder = defaultBuilder();

      builder.copyFromMessageData(*messageData);
      LLSD output = builder.getMessage();

      ensure_equals("Ensure MVT_LLQuaternion data works in a message copied from legacy to llsd",
          ll_quaternion_from_sd(output["testBlock"][0]["testBinData"]), data);
    }

    // MVT_LLUUID
    template<> template<>
    void LLSDMessageBuilderTestObject::test<38>()
    {
      LLUUID data("01234567-0123-0123-0123-234567abcdef");

      addValue(messageBlockData, (char *)"testBinData", &data, MVT_LLUUID, sizeof(data));
      messageData->addBlock(messageBlockData);
      LLSDMessageBuilder builder = defaultBuilder();

      builder.copyFromMessageData(*messageData);
      LLSD output = builder.getMessage();

      std::string v = output["testBlock"][0]["testBinData"].asUUID().asString();

      ensure_equals("Ensure MVT_LLUUID data works in a message copied from legacy to llsd",
          output["testBlock"][0]["testBinData"].asUUID(), data);
    }

    // MVT_BOOL
    template<> template<>
    void LLSDMessageBuilderTestObject::test<39>()
    {
      bool valueTrue = true;
      bool valueFalse = false;

      LLMsgData* md = new LLMsgData("testMessage");
      LLMsgBlkData* mbd = new LLMsgBlkData("testBlock", 0);
      addValue(mbd, (char *)"testBoolFalse", &valueFalse, MVT_BOOL, sizeof(bool));
      addValue(mbd, (char *)"testBoolTrue", &valueTrue, MVT_BOOL, sizeof(bool));
      md->addBlock(mbd);
      LLSDMessageBuilder builder = defaultBuilder();

      builder.copyFromMessageData(*md);
      LLSD output = builder.getMessage();

      ensure("Ensure bools work in a message copied from legacy to llsd",
          output["testBlock"][0]["testBoolTrue"].asBoolean() && !output["testBlock"][0]["testBoolFalse"].asBoolean());
    }

    // MVT_IP_ADDR
    template<> template<>
    void LLSDMessageBuilderTestObject::test<40>()
    {
      U32 data(0xff887766);
      LLSD v = ll_sd_from_ipaddr(data);

      addValue(messageBlockData, (char *)"testBinData", &data, MVT_IP_ADDR, sizeof(data));
      messageData->addBlock(messageBlockData);
      LLSDMessageBuilder builder = defaultBuilder();

      builder.copyFromMessageData(*messageData);
      LLSD output = builder.getMessage();

      ensure_equals("Ensure MVT_IP_ADDR data works in a message copied from legacy to llsd",
          output["testBlock"][0]["testBinData"], v);
    }

    // MVT_IP_PORT
    template<> template<>
    void LLSDMessageBuilderTestObject::test<41>()
    {
      U16 data = 0xff88;

      addValue(messageBlockData, (char *)"testBinData", &data, MVT_IP_PORT, sizeof(data));
      messageData->addBlock(messageBlockData);
      LLSDMessageBuilder builder = defaultBuilder();

      builder.copyFromMessageData(*messageData);
      LLSD output = builder.getMessage();

      ensure_equals("Ensure MVT_IP_PORT data works in a message copied from legacy to llsd",
          output["testBlock"][0]["testBinData"].asInteger(), data);
    }

    // MVT_U16Vec3
    template<> template<>
    void LLSDMessageBuilderTestObject::test<42>()
    {
      U16 data[3] = {0,1,2};

      addValue(messageBlockData, (char *)"testBinData", &data, MVT_U16Vec3, sizeof(data));
      messageData->addBlock(messageBlockData);
      LLSDMessageBuilder builder = defaultBuilder();

      builder.copyFromMessageData(*messageData);
      LLSD output = builder.getMessage();

      std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
      ensure("Ensure MVT_U16Vec3 data copied from legacy to llsd give a valid vector", v.size() > 0);

      ensure_memory_matches("Ensure MVT_U16Vec3 data works in a message copied from legacy to llsd",
          (U16*)&v[0], 6, data, 6);
    }

    // MVT_U16Quat
    template<> template<>
    void LLSDMessageBuilderTestObject::test<43>()
    {
      U16 data[4] = {0,1,2,4};

      addValue(messageBlockData, (char *)"testBinData", &data, MVT_U16Quat, sizeof(data));
      messageData->addBlock(messageBlockData);
      LLSDMessageBuilder builder = defaultBuilder();

      builder.copyFromMessageData(*messageData);
      LLSD output = builder.getMessage();

      std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
      ensure("Ensure MVT_U16Quat data copied from legacy to llsd give a valid vector", v.size() > 0);

      ensure_memory_matches("Ensure MVT_U16Quat data works in a message copied from legacy to llsd",
          (U16*)&v[0], 8, data, 8);
    }

    // MVT_S16Array
    template<> template<>
    void LLSDMessageBuilderTestObject::test<44>()
    {
      S16 data[19] = {0,-1,2,-4,5,-6,7,-8,9,-10,11,-12,13,-14,15,16,17,18};

      addValue(messageBlockData, (char *)"testBinData", &data, MVT_S16Array, sizeof(data));
      messageData->addBlock(messageBlockData);
      LLSDMessageBuilder builder = defaultBuilder();

      builder.copyFromMessageData(*messageData);
      LLSD output = builder.getMessage();

      std::vector<U8> v = output["testBlock"][0]["testBinData"].asBinary();
      ensure("Ensure MVT_S16Array data copied from legacy to llsd give a valid vector", v.size() > 0);

      ensure_memory_matches("Ensure MVT_S16Array data works in a message copied from legacy to llsd",
          (U16*)&v[0], 19, data, 19);
    }

    template<> template<>
    void LLSDMessageBuilderTestObject::test<45>()
    {
        LLMessageTemplate messageTemplate = defaultTemplate();
        messageTemplate.addBlock(defaultTemplateBlock(MVT_U8, 1));
        U8 inValue = 2;
        LLTemplateMessageBuilder* template_builder = defaultTemplateBuilder(messageTemplate);
        template_builder->addU8(_PREHASH_Test0, inValue);

        LLSDMessageBuilder builder;
        builder.copyFromMessageData(*template_builder->getCurrentMessage());
        LLSD output = builder.getMessage();

        ensure_equals(output["Test0"][0]["Test0"].asInteger(), 2);

    }

    template<> template<>
    void LLSDMessageBuilderTestObject::test<46>()
    {
        LLMessageTemplate messageTemplate = defaultTemplate();
        messageTemplate.addBlock(defaultTemplateBlock(MVT_VARIABLE, 1));
        std::string inValue = "testing";
        LLTemplateMessageBuilder* builder = defaultTemplateBuilder(messageTemplate);
        builder->addString(_PREHASH_Test0, inValue.c_str());

        LLSDMessageBuilder sd_builder;
        sd_builder.copyFromMessageData(*builder->getCurrentMessage());
        LLSD output = sd_builder.getMessage();

        ensure_equals(output["Test0"][0]["Test0"].asString(), std::string("testing"));
    }

}