// TestValues.cpp : Test XML encoding and decoding of XmlRpcValues.



#define _CRTDBG_MAP_ALLOC

#include <stdlib.h>

#include <crtdbg.h>



#include "XmlRpcValue.h"





#include <assert.h>

#include <iostream>





using namespace XmlRpc;





void testBoolean()

{

  XmlRpcValue booleanFalse(false);

  XmlRpcValue booleanTrue(true);

  int offset = 0;

  XmlRpcValue booleanFalseXml("<value><boolean>0</boolean></value>", &offset);

  offset = 0;

  XmlRpcValue booleanTrueXml("<value><boolean>1</boolean></value>", &offset);

  assert(booleanFalse != booleanTrue);

  assert(booleanFalse == booleanFalseXml);

  assert(booleanFalse == booleanFalseXml);

  if (booleanFalse)

    assert(false);



  if (booleanTrue)

    assert( ! false);

  else

    assert(false);

}



// Int

void testInt()

{

  XmlRpcValue int0(0);

  XmlRpcValue int1(1);

  XmlRpcValue int10(10);

  XmlRpcValue int_1(-1);

  int offset = 0;

  XmlRpcValue int0Xml("<value><int>0</int></value>", &offset);

  offset = 0;

  XmlRpcValue int9Xml("<value><i4>9</i4></value>", &offset);

  assert(int0 == int0Xml);

  assert(int(int10) - int(int1) == int(int9Xml));

  assert(9 == int(int9Xml));

  assert(int(int10) + int(int_1) == int(int9Xml));

}



void testDouble()

{

  // Double

  XmlRpcValue d(43.7);

  int offset = 0;

  XmlRpcValue dXml("<value><double>56.3</double></value>", &offset);

  assert(double(d) + double(dXml) == 100.0);  // questionable practice...

}



void testString()

{

  // String

  XmlRpcValue s("Now is the time <&");

  char csxml[] = "<value><string>Now is the time &lt;&amp;</string></value>";

  std::string ssxml = csxml;

  int offset = 0;

  XmlRpcValue vscXml(csxml, &offset);

  offset = 0;

  XmlRpcValue vssXml(ssxml, &offset);

  assert(s == vscXml);

  assert(s == vssXml);

  offset = 0;

  XmlRpcValue fromXml(vssXml.toXml(), &offset);

  assert(s == fromXml);



  // Empty or blank strings with no <string> tags

  std::string emptyStringXml("<value></value>");

  offset = 0;

  XmlRpcValue emptyStringVal1(emptyStringXml, &offset);

  XmlRpcValue emptyStringVal2("");

  assert(emptyStringVal1 == emptyStringVal2);



  emptyStringXml = "<value>  </value>";

  offset = 0;

  XmlRpcValue blankStringVal(emptyStringXml, &offset);

  assert(std::string(blankStringVal) == "  ");

}





void testDateTime()

{

  // DateTime

  int offset = 0;

  XmlRpcValue dateTime("<value><dateTime.iso8601>19040101T03:12:35</dateTime.iso8601></value>", &offset);

  struct tm &t = dateTime;

  assert(t.tm_year == 1904 && t.tm_min == 12);

}





void testArray(XmlRpcValue const& d)

{

  // Array

  XmlRpcValue a;

  a.setSize(4);

  a[0] = 1;

  a[1] = std::string("two");

  a[2] = 43.7;

  a[3] = "four";

  assert(int(a[0]) == 1);

  assert(a[2] == d);



  char csaXml[] =

    "<value><array>\n"

    "  <data>\n"

    "    <value><i4>1</i4></value> \n"

    "    <value> <string>two</string></value>\n"

    "    <value><double>43.7</double></value>\n"

    "    <value>four</value>\n"

    "  </data>\n"

    "</array></value>";

    

  int offset = 0;

  XmlRpcValue aXml(csaXml, &offset);

  assert(a == aXml);

}



void testStruct()

{

  // Struct

  XmlRpcValue struct1;

  struct1["i4"] = 1;

  struct1["str"] = "two";

  struct1["d"] = 43.7;



  XmlRpcValue a;

  a.setSize(4);

  a[0] = 1;

  a[1] = std::string("two");

  a[2] = 43.7;

  a[3] = "four";



  assert(struct1["d"] == a[2]);



  char csStructXml[] =

    "<value><struct>\n"

    "  <member>\n"

    "    <name>i4</name> \n"

    "    <value><i4>1</i4></value> \n"

    "  </member>\n"

    "  <member>\n"

    "    <name>d</name> \n"

    "    <value><double>43.7</double></value>\n"

    "  </member>\n"

    "  <member>\n"

    "    <name>str</name> \n"

    "    <value> <string>two</string></value>\n"

    "  </member>\n"

    "</struct></value>";

    

  int offset = 0;

  XmlRpcValue structXml(csStructXml, &offset);

  assert(struct1 == structXml);



  XmlRpcValue astruct;

  astruct["array"] = a;

  assert(astruct["array"][2] == struct1["d"]);



  for (int i=0; i<10; i++) {

    XmlRpcValue Event;

    Event["Name"] = "string";



    Event.clear();



    const int NELMTS = 100;

    int ii;



    for (ii=0; ii< NELMTS; ++ii) {

      char buf[40];

      sprintf(buf,"%d", ii);

      Event[buf] = buf;

    }



    Event.clear();



    for (ii=0; ii< NELMTS; ++ii) {

      char buf[40];

      sprintf(buf,"%d", ii);

      if (ii != NELMTS/2)

        Event[buf] = ii;

      else

        for (int jj=0; jj< NELMTS; ++jj) {

          char bufj[40];

          sprintf(bufj,"%d", jj);

          Event[buf][bufj] = bufj;

        }

    }



    for (ii=0; ii< NELMTS; ++ii) {

      char buf[40];

      sprintf(buf,"%d", ii);

      if (ii != NELMTS/2)

        assert(Event[buf] == XmlRpcValue(ii));

      else

        assert(Event[buf].size() == NELMTS);

    }

  }

}







int main(int argc, char* argv[])

{

  _CrtDumpMemoryLeaks();

  _CrtCheckMemory( );



  testBoolean();

  _CrtDumpMemoryLeaks();

  _CrtCheckMemory( );



  testInt();

  _CrtDumpMemoryLeaks();

  _CrtCheckMemory( );





  testDouble();

  _CrtDumpMemoryLeaks();

  _CrtCheckMemory( );





  testString();

  _CrtDumpMemoryLeaks();

  _CrtCheckMemory( );





  testDateTime();

  _CrtDumpMemoryLeaks();

  _CrtCheckMemory( );





  testArray(43.7);

  _CrtDumpMemoryLeaks();

  _CrtCheckMemory( );





  testStruct();

  _CrtDumpMemoryLeaks();

  _CrtCheckMemory( );



  return 0;

}

