• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

test/XmlTest.cpp

00001 /*
00002  *   This file is part of the Standard Portable Library (SPL).
00003  *
00004  *   SPL is free software: you can redistribute it and/or modify
00005  *   it under the terms of the GNU General Public License as published by
00006  *   the Free Software Foundation, either version 3 of the License, or
00007  *   (at your option) any later version.
00008  *
00009  *   SPL is distributed in the hope that it will be useful,
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *   GNU General Public License for more details.
00013  *
00014  *   You should have received a copy of the GNU General Public License
00015  *   along with SPL.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 /*
00018    Test program for TinyXML.
00019 */
00020 
00021 #include <stdio.h>
00022 #include <spl/Debug.h>
00023 #include <spl/Double.h>
00024 #include <spl/Int32.h>
00025 #include <spl/Log.h>
00026 #include <spl/xml/XmlAttribute.h>
00027 #include <spl/xml/XmlComment.h>
00028 #include <spl/xml/XmlDeclaration.h>
00029 #include <spl/xml/XmlDocument.h>
00030 #include <spl/xml/XmlElement.h>
00031 #include <spl/xml/XmlNode.h>
00032 #include <spl/xml/XmlText.h>
00033 #include <spl/xml/XmlUnknown.h>
00034 
00035 #ifdef DEBUG
00036 
00037 bool XmlTest (const char* testString, const char* expected, const String& found, bool noEcho = false)
00038 {
00039         bool pass = !strcmp( expected, found.GetChars() );
00040         UNIT_ASSERT(testString, pass);
00041         return pass;
00042 }
00043 
00044 bool XmlTest (const char* testString, const char* expected, StringPtr found, bool noEcho = false)
00045 {
00046         bool pass = !strcmp( expected, found->GetChars() );
00047         UNIT_ASSERT(testString, pass);
00048         return pass;
00049 }
00050 
00051 bool XmlTest (const char* testString, const char* expected, const char *found, bool noEcho = false)
00052 {
00053         bool pass = !strcmp( expected, found );
00054         UNIT_ASSERT(testString, pass);
00055         return pass;
00056 }
00057 
00058 bool XmlTest( const char* testString, int expected, int found, bool noEcho = false )
00059 {
00060         bool pass = ( expected == found );
00061         UNIT_ASSERT(testString, pass);
00062         return pass;
00063 }
00064 
00065 //
00066 // We start with the 'demoStart' todo list. Process it. And
00067 // should hopefully end up with the todo list as illustrated.
00068 //
00069 static const char* _demoStart =
00070         "<?xml version=\"1.0\"  standalone='no' >\n"
00071         "<!-- Our to do list data -->"
00072         "<ToDo>\n"
00073         "<!-- Do I need a secure PDA? -->\n"
00074         "<Item priority=\"1\" distance='close'> Go to the <bold>Toy store!</bold></Item>"
00075         "<Item priority=\"2\" distance='none'> Do bills   </Item>"
00076         "<Item priority=\"2\" distance='far &amp; back'> Look for Evil Dinosaurs! </Item>"
00077         "</ToDo>";
00078 
00079 /*      What the todo list should look like after processing.
00080         In stream (no formatting) representation. */
00081 static const char* _demoEnd =
00082         "<?xml version=\"1.0\" standalone=\"no\" ?>"
00083         "<!-- Our to do list data -->"
00084         "<ToDo>"
00085         "<!-- Do I need a secure PDA? -->"
00086         "<Item priority=\"2\" distance=\"close\">Go to the"
00087         "<bold>Toy store!"
00088         "</bold>"
00089         "</Item>"
00090         "<Item priority=\"1\" distance=\"far\">Talk to:"
00091         "<Meeting where=\"School\">"
00092         "<Attendee name=\"Marple\" position=\"teacher\" />"
00093         "<Attendee name=\"Voel\" position=\"counselor\" />"
00094         "</Meeting>"
00095         "<Meeting where=\"Lunch\" />"
00096         "</Item>"
00097         "<Item priority=\"2\" distance=\"here\">Do bills"
00098         "</Item>"
00099         "</ToDo>";
00100 //
00101 // This file demonstrates some basic functionality of TinyXml.
00102 // Note that the example is very contrived. It presumes you know
00103 // what is in the XML file. But it does test the basic operations,
00104 // and show how to add and remove nodes.
00105 //
00106 
00107 void _TestTinyXml()
00108 {
00109         int count = 0;
00110         XmlElementPtr element;
00111         XmlNodePtr node;
00112 
00113         {
00114                 // The example parses from the character string (above):
00115                 {
00116                         // Write to a file and read it back, to check file I/O.
00117 
00118                         XmlDocumentPtr doc = XmlDocument::ParseXml(_demoStart);
00119                         doc.ValidateMem();
00120 
00121                         DEBUG_CLEAR_MEM_CHECK_POINTS();
00122                         doc.CheckMem();
00123                         DEBUG_DUMP_MEM_LEAKS();
00124                         UNIT_ASSERT_MEM_NOTED("TinyXML 0");
00125 
00126                         doc->Write("demotest.xml");
00127                         UNIT_ASSERT( "demotest.xml should exist", File::Exists("demotest.xml"));
00128 
00129                         DEBUG_CLEAR_MEM_CHECK_POINTS();
00130                         doc.CheckMem();
00131                         DEBUG_DUMP_MEM_LEAKS();
00132                         UNIT_ASSERT_MEM_NOTED("TinyXML 1");
00133                 }
00134                 DEBUG_CLEAR_MEM_CHECK_POINTS();
00135                 DEBUG_DUMP_MEM_LEAKS();
00136                 UNIT_ASSERT_MEM_NOTED("TinyXML 2");
00137 
00138                 XmlDocumentPtr doc = XmlDocument::Parse( "demotest.xml" );
00139 
00140                 // Walk all the top level nodes of the document.
00141                 count = 0;
00142                 for( node = doc->FirstChild(); node.IsNotNull(); node = node->NextSibling() )
00143                 {
00144                         count++;
00145                 }
00146                 XmlTest( "Top level nodes, using First / Next.", 3, count );
00147                 
00148                 //printf( "** Demo doc read from disk: ** \n\n" );
00149                 //printf( "** Printing via doc.Print **\n" );
00150                 //doc.Print( stdout );
00151 
00152                 {
00153                         //printf( "** Printing via TiXmlPrinter **\n" );
00154                         //TiXmlPrinter printer;
00155                         //doc.Accept( &printer );
00156                         //fprintf( stdout, "%s", printer.CStr() );
00157                 }
00158                 XmlElementPtr todoElement;
00159                 XmlElementPtr itemElement;
00160 
00161                 // --------------------------------------------------------
00162                 // An example of changing existing attributes, and removing
00163                 // an element from the document.
00164                 // --------------------------------------------------------
00165 
00166                 // Get the "ToDo" element.
00167                 // It is a child of the document, and can be selected by name.
00168                 node = doc->FirstChild( "ToDo" );
00169                 ASSERT( node.IsNotNull() );
00170                 todoElement = node->ToElement();
00171                 ASSERT( todoElement.IsNotNull()  );
00172 
00173                 // Going to the toy store is now our second priority...
00174                 // So set the "priority" attribute of the first item in the list.
00175                 node = todoElement->FirstChildElement();        // This skips the "PDA" comment.
00176                 ASSERT( node.IsNotNull() );
00177                 itemElement = node->ToElement();
00178                 ASSERT( itemElement.IsNotNull()  );
00179                 itemElement->SetAttribute( "priority", 2 );
00180 
00181                 // Change the distance to "doing bills" from
00182                 // "none" to "here". It's the next sibling element.
00183                 itemElement = itemElement->NextSiblingElement();
00184                 ASSERT( itemElement.IsNotNull() );
00185                 itemElement->SetAttribute( "distance", "here" );
00186 
00187                 // Remove the "Look for Evil Dinosaurs!" item.
00188                 // It is 1 more sibling away. We ask the parent to remove
00189                 // a particular child.
00190                 itemElement = itemElement->NextSiblingElement();
00191                 todoElement->RemoveChild( itemElement );
00192 
00193                 itemElement.Release();
00194 
00195                 // --------------------------------------------------------
00196                 // What follows is an example of created elements and text
00197                 // nodes and adding them to the document.
00198                 // --------------------------------------------------------
00199 
00200                 // Add some meetings.
00201                 XmlElementPtr item = XmlElement::CreateElement( "Item" );
00202                 item->SetAttribute( "priority", "1" );
00203                 item->SetAttribute( "distance", "far" );
00204 
00205                 XmlTextPtr text = XmlText::CreateText( "Talk to:" );
00206 
00207                 XmlElementPtr meeting1 = XmlElement::CreateElement( "Meeting" );
00208                 meeting1->SetAttribute( "where", "School" );
00209 
00210                 XmlElementPtr meeting2 = XmlElement::CreateElement( "Meeting" );
00211                 meeting2->SetAttribute( "where", "Lunch" );
00212 
00213                 XmlElementPtr attendee1 = XmlElement::CreateElement( "Attendee" );
00214                 attendee1->SetAttribute( "name", "Marple" );
00215                 attendee1->SetAttribute( "position", "teacher" );
00216 
00217                 XmlElementPtr attendee2 = XmlElement::CreateElement( "Attendee" );
00218                 attendee2->SetAttribute( "name", "Voel" );
00219                 attendee2->SetAttribute( "position", "counselor" );
00220 
00221                 // Assemble the nodes we've created:
00222                 meeting1->AppendChild( attendee1 );
00223                 meeting1->AppendChild( attendee2 );
00224 
00225                 item->AppendChild( text );
00226                 item->AppendChild( meeting1 );
00227                 item->AppendChild( meeting2 );
00228 
00229                 // And add the node to the existing list after the first child.
00230                 node = todoElement->FirstChild( "Item" );
00231                 ASSERT( node.IsNotNull() );
00232                 itemElement = node->ToElement();
00233                 ASSERT( itemElement.IsNotNull() );
00234 
00235                 todoElement->InsertAfter( itemElement, item );
00236 
00237                 //printf( "\n** Demo doc processed: ** \n\n" );
00238                 //doc.Print( stdout );
00239 
00240                 // --------------------------------------------------------
00241                 // Different tests...do we have what we expect?
00242                 // --------------------------------------------------------
00243 
00245 
00246                 node = doc->RootElement();
00247                 node.ValidateMem();
00248                 ASSERT( node.IsNotNull() );
00249                 XmlTest( "Root element exists.", true, ( node.IsNotNull() && node->IsElement() ) );
00250                 XmlTest ( "Root element value is 'ToDo'.", "ToDo",  node->Name().GetChars());
00251 
00252                 node = node->FirstChild();
00253                 XmlTest( "First child exists & is a comment.", true, ( node.IsNotNull() && node->IsComment() ) );
00254                 node = node->NextSibling();
00255                 XmlTest( "Sibling element exists & is an element.", true, ( node.IsNotNull() && node->IsElement() ) );
00256                 XmlTest ( "Value is 'Item'.", "Item", node->Name().GetChars() );
00257 
00258                 node = node->FirstChild();
00259                 XmlTest ( "First child exists.", true, ( node.IsNotNull() && node->IsText() ) );
00260                 XmlTest ( "Value is 'Go to the'.", "Go to the", node->Value()->GetChars() );
00261 
00262                 doc.ValidateMem();
00263                 
00264                 // Walk all the top level nodes of the document.
00265                 count = 0;
00266                 for( node = doc->FirstChild(); node.IsNotNull(); node = node->NextSibling() )
00267                 {
00268                         count++;
00269                 }
00270                 XmlTest( "Top level nodes, using First / Next.", 3, count );
00271 
00272                 count = 0;
00273                 for( node = doc->LastChild();
00274                          node.IsNotNull();
00275                          node = node->PreviousSibling() )
00276                 {
00277                         count++;
00278                 }
00279                 XmlTest( "Top level nodes, using Last / Previous.", 3, count );
00280 
00281                 // Walk all the top level nodes of the document,
00282                 // using a different syntax.
00283                 //count = 0;
00284                 //for( node = doc.IterateChildren( 0 );
00285                 //       node;
00286                 //       node = doc.IterateChildren( node ) )
00287                 //{
00288                 //      count++;
00289                 //}
00290                 //XmlTest( "Top level nodes, using IterateChildren.", 3, count );
00291 
00292                 // Walk all the elements in a node.
00293                 count = 0;
00294                 for( element = todoElement->FirstChildElement();
00295                          element.IsNotNull();
00296                          element = element->NextSiblingElement() )
00297                 {
00298                         count++;
00299                 }
00300                 XmlTest( "Children of the 'ToDo' element, using First / Next.", 3, count );
00301 
00302                 // Walk all the elements in a node by value.
00303                 count = 0;
00304                 for( node = todoElement->FirstChild( "Item" ); node.IsNotNull(); node = node->NextSibling( "Item" ) )
00305                 {
00306                         count++;
00307                 }
00308                 XmlTest( "'Item' children of the 'ToDo' element, using First/Next.", 3, count );
00309 
00310                 count = 0;
00311                 for( node = todoElement->LastChild( "Item" );
00312                          node.IsNotNull();
00313                          node = node->PreviousSibling( "Item" ) )
00314                 {
00315                         count++;
00316                 }
00317                 XmlTest( "'Item' children of the 'ToDo' element, using Last/Previous.", 3, count );
00318 
00319                 {
00320                         XmlDocumentPtr doc = XmlDocument::ParseXml( "<Element0 attribute0='foo0' attribute1= noquotes attribute2 = '&gt;' />" );
00321                         XmlElementPtr element0 = (XmlElementPtr)doc->FirstChild();
00322                         UNIT_ASSERT("Should be an element", element0->NodeType() == XmlNode::ELEMENT);
00323                         
00324                         XmlTest ( "Element parsed, value is 'Element0'.", "Element0", element0->Name() );
00325                         XmlTest ( "Reads attribute 'attribute0=\"foo0\"'.", "foo0", element0->Attribute( "attribute0" )->Value()->GetChars());
00326                         XmlTest ( "Reads incorrectly formatted 'attribute1=noquotes'.", "noquotes", element0->Attribute( "attribute1" )->Value()->GetChars() );
00327                         XmlTest ( "Read attribute with entity value '>'.", ">", element0->Attribute( "attribute2" )->Value()->GetChars() );
00328                 }
00329 
00330                 {
00331                         const char* error =     "<?xml version=\"1.0\" standalone=\"no\" ?>\n"
00332                                                                 "<passages count=\"006\" formatversion=\"20020620\">\n"
00333                                                                 "    <wrong error>\n"
00334                                                                 "</passages>";
00335 
00336                         XmlDocumentPtr docTest;
00337                         try
00338                         {
00339                                 docTest = XmlDocument::ParseXml( error );
00340                                 UNIT_ASSERT("should throw an error", false);
00341                         }
00342                         catch ( XmlException *xex )
00343                         {
00344                                 XmlTest( "Error row", xex->Row(), 3 );
00345                                 XmlTest( "Error column", xex->Col(), 12 );
00346                                 delete xex;
00347                         }
00348                 }
00349         }
00350         DEBUG_CLEAR_MEM_CHECK_POINTS();
00351         DEBUG_DUMP_MEM_LEAKS();
00352         UNIT_ASSERT_MEM_NOTED("TinyXML 3");
00353         Log::SWriteOkFail( "TinyXML 1" );
00354         
00355         {
00356                 const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
00357 
00358                 XmlDocumentPtr doc = XmlDocument::ParseXml( str );
00359 
00360                 XmlElementPtr ele = doc->FirstChildElement();
00361 
00362                 int iVal;
00363                 XmlAttributePtr result;
00364                 double dVal;
00365 
00366                 dVal = Double::Parse(*ele->Attribute( "attr0" )->Value());
00367                 XmlTest( "Query attribute: int as double", (int)dVal, 1 );
00368                 dVal = Double::Parse(*ele->Attribute( "attr1" )->Value());
00369                 XmlTest( "Query attribute: double as double", (int)dVal, 2 );
00370                 iVal = Int32::Parse(*ele->Attribute( "attr1" )->Value());
00371                 XmlTest( "Query attribute: double as int", iVal, 2 );
00372                 result = ele->Attribute( "attr2" );
00373                 XmlTest( "Query attribute: not a number", Int32::IsInt(*result->Value()), false );
00374                 result = ele->Attribute( "bar" );
00375                 XmlTest( "Query attribute: does not exist", result.IsNotNull(), false );
00376         }
00377         DEBUG_CLEAR_MEM_CHECK_POINTS();
00378         DEBUG_DUMP_MEM_LEAKS();
00379         UNIT_ASSERT_MEM_NOTED("TinyXML 4");
00380         Log::SWriteOkFail( "TinyXML 2 attribute types" );
00381         
00382         {
00383                 const char* str =       "\t<?xml version=\"1.0\" standalone=\"no\" ?>\t<room doors='2'>\n"
00384                                                         "</room>";
00385 
00386 
00387                 XmlParsingData dt(str, 8, 0, 0, true);
00388                 XmlDocumentPtr doc = XmlDocument::ParseXml(str, &dt);
00389                 //XmlDocument doc;
00390                 //doc.SetTabSize( 8 );
00391                 //doc.LoadXml( str );
00392 
00393                 XmlElementPtr roomHandle = doc->FirstChildElement( "room" );
00394 
00395                 XmlElementPtr room = roomHandle->ToElement();
00396                 ASSERT( room.IsNotNull() );
00397                 XmlAttributePtr doors = room->Attribute(0);
00398                 ASSERT( doors.IsNotNull() );
00399 
00400                 XmlTest( "Location tracking: Tab 8: room row", room->Row(), 1 );
00401                 XmlTest( "Location tracking: Tab 8: room col", room->Column(), 49 );
00402                 XmlTest( "Location tracking: Tab 8: doors row", doors->Row(), 1 );
00403                 XmlTest( "Location tracking: Tab 8: doors col", doors->Column(), 55 );
00404         }
00405         DEBUG_CLEAR_MEM_CHECK_POINTS();
00406         DEBUG_DUMP_MEM_LEAKS();
00407         UNIT_ASSERT_MEM_NOTED("TinyXML 5");
00408         Log::SWriteOkFail( "TinyXML 3 row column" );
00409         
00410         {
00411                 const char* str =       "\t<?xml version=\"1.0\" standalone=\"no\" ?>\t<room doors='2'>\n"
00412                                                         "  <!-- Silly example -->\n"
00413                                                         "    <door wall='north'>A great door!</door>\n"
00414                                                         "\t<door wall='east'/>"
00415                                                         "</room>";
00416 
00417                 XmlDocumentPtr doc = XmlDocument::ParseXml( str );
00418 
00419                 XmlElementPtr roomHandle = doc->FirstChildElement( "room" );
00420                 XmlElementPtr commentHandle = (XmlElementPtr)doc->FirstChildElement( "room" )->FirstChild();
00421                 XmlElementPtr textHandle = (XmlElementPtr)doc->FirstChildElement( "room" )->ChildElement( "door", 0 )->FirstChild();
00422                 XmlElementPtr door0Handle = doc->FirstChildElement( "room" )->ChildElement( 0 );
00423                 XmlElementPtr door1Handle = doc->FirstChildElement( "room" )->ChildElement( 1 );
00424                 ASSERT(door0Handle.IsNotNull() && door1Handle.IsNotNull());
00425 
00426                 UNIT_ASSERT("element", roomHandle->IsElement() );
00427                 UNIT_ASSERT("text", textHandle->IsText() );
00428                 UNIT_ASSERT("elemetn", door0Handle->IsElement() );
00429                 UNIT_ASSERT("element", door1Handle->IsElement() );
00430 
00431                 XmlDeclarationPtr declaration = doc->FirstChild()->ToDeclaration();
00432                 assert( declaration.IsNotNull() );
00433                 XmlElementPtr room = roomHandle->ToElement();
00434                 ASSERT( room.IsNotNull() );
00435                 XmlAttributePtr doors = room->Attribute(0);
00436                 ASSERT( doors.IsNotNull() );
00437                 XmlTextPtr text = textHandle->ToText();
00438                 XmlCommentPtr comment = commentHandle->ToComment();
00439                 ASSERT( comment.IsNotNull() );
00440                 XmlElementPtr door0 = door0Handle->ToElement();
00441                 XmlElementPtr door1 = door1Handle->ToElement();
00442 
00443                 XmlTest( "Location tracking: Declaration row", declaration->Row(), 1 );
00444                 XmlTest( "Location tracking: Declaration col", declaration->Column(), 5 );
00445                 XmlTest( "Location tracking: room row", room->Row(), 1 );
00446                 XmlTest( "Location tracking: room col", room->Column(), 45 );
00447                 XmlTest( "Location tracking: doors row", doors->Row(), 1 );
00448                 XmlTest( "Location tracking: doors col", doors->Column(), 51 );
00449                 XmlTest( "Location tracking: Comment row", comment->Row(), 2 );
00450                 XmlTest( "Location tracking: Comment col", comment->Column(), 3 );
00451                 XmlTest( "Location tracking: text row", text->Row(), 3 ); 
00452                 XmlTest( "Location tracking: text col", text->Column(), 24 );
00453                 XmlTest( "Location tracking: door0 row", door0->Row(), 3 );
00454                 XmlTest( "Location tracking: door0 col", door0->Column(), 5 );
00455                 XmlTest( "Location tracking: door1 row", door1->Row(), 4 );
00456                 XmlTest( "Location tracking: door1 col", door1->Column(), 5 );
00457         }
00458         DEBUG_CLEAR_MEM_CHECK_POINTS();
00459         DEBUG_DUMP_MEM_LEAKS();
00460         UNIT_ASSERT_MEM_NOTED("TinyXML 6");
00461         Log::SWriteOkFail( "TinyXML 4"  );
00462         
00463         if ( File::Exists("test/utf8test.xml"))
00464         {
00465                 // --------------------------------------------------------
00466                 // UTF-8 testing. It is important to test:
00467                 //      1. Making sure name, value, and text read correctly
00468                 //      2. Row, Col functionality
00469                 //      3. Correct output
00470                 // --------------------------------------------------------
00471                 //printf ("\n** UTF-8 **\n");
00472                 {
00473                         XmlDocumentPtr doc = XmlDocument::Parse( "test/utf8test.xml" );
00474 
00475                         // Get the attribute "value" from the "Russian" element and check it.
00476                         XmlElementPtr element = doc->FirstChildElement( "document" )->FirstChildElement( "Russian" )->ToElement();
00477                         const unsigned char correctValue[] = {  0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU, 
00478                                                                                                         0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
00479 
00480                         XmlTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" )->Value(), true );
00481                         XmlTest( "UTF-8: Russian value row.", 4, element->Row() );
00482                         XmlTest( "UTF-8: Russian value column.", 5, element->Column() );
00483 
00484                         const unsigned char russianElementName[] = {    0xd0U, 0xa0U, 0xd1U, 0x83U,
00485                                                                                                                         0xd1U, 0x81U, 0xd1U, 0x81U,
00486                                                                                                                         0xd0U, 0xbaU, 0xd0U, 0xb8U,
00487                                                                                                                         0xd0U, 0xb9U, 0 };
00488                         const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
00489 
00490                         XmlTextPtr text = doc->FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->Child( 0 )->ToText();
00491                         XmlTest( "UTF-8: Browsing russian element name.",
00492                                          russianText,
00493                                          text->Value(),
00494                                          true );
00495                         XmlTest( "UTF-8: Russian element name row.", 7, text->Row() );
00496                         XmlTest( "UTF-8: Russian element name column.", 47, text->Column() );
00497 
00498                         XmlDeclarationPtr dec = doc->Child( 0 )->ToDeclaration();
00499                         XmlTest( "UTF-8: Declaration column.", 1, dec->Column() );
00500                         XmlTest( "UTF-8: Document column.", 1, doc->Column() );
00501 
00502                         // Now try for a round trip.
00503                         doc->Write( "utf8testout.xml" );
00504 
00505                         // This test doesnt' work -- utf8testverify.xml is never created.
00506 
00507                         // Check the round trip.
00508                         //char savedBuf[256];
00509                         //char verifyBuf[256];
00510                         //int okay = 1;
00511 
00512                         //FILE* saved  = fopen( "utf8testout.xml", "r" );
00513                         //FILE* verify = fopen( "utf8testverify.xml", "r" );
00514                         //if ( saved && verify )
00515                         //{
00516                         //      while ( fgets( verifyBuf, 256, verify ) )
00517                         //      {
00518                         //              fgets( savedBuf, 256, saved );
00519                         //              if ( strcmp( verifyBuf, savedBuf ) )
00520                         //              {
00521                         //                      okay = 0;
00522                         //                      break;
00523                         //              }
00524                         //      }
00525                         //      fclose( saved );
00526                         //      fclose( verify );
00527                         //}
00528                         //XmlTest( "UTF-8: Verified multi-language round trip.", 1, okay );
00529 
00530                         // On most Western machines, this is an element that contains
00531                         // the word "resume" with the correct accents, in a latin encoding.
00532                         // It will be something else completely on non-wester machines,
00533                         // which is why TinyXml is switching to UTF-8.
00534                         const char latin[] = "<element>r\x82sum\x82</element>";
00535 
00536                         XmlDocumentPtr latinDoc = XmlDocument::ParseXml( latin, NULL, TIXML_ENCODING_LEGACY );
00537                         text = latinDoc->FirstChildElement()->FirstChild()->ToText();
00538                         XmlTest( "Legacy encoding: Verify text element.", "r\x82sum\x82", text->Value() );
00539                 }               
00540                 DEBUG_CLEAR_MEM_CHECK_POINTS();
00541                 DEBUG_DUMP_MEM_LEAKS();
00542                 UNIT_ASSERT_MEM_NOTED("TinyXML 7");
00543                 Log::SWriteOkFail( "TinyXML UTF-8" );
00544         }
00545 
00547         // Copy and assignment
00549         //printf ("\n** Copy and Assignment **\n");
00550         {
00551                 XmlElementPtr element = XmlElement::CreateElement( "foo" );
00552                 element.ValidateMem();
00553                 element->_Parse( "<element name='value' />", NULL, TIXML_ENCODING_UNKNOWN );
00554 
00555                 XmlElementPtr elementCopy = XmlElement::CreateElement( "" );
00556                 *elementCopy = *element;
00557                 XmlElementPtr elementAssign = XmlElement::CreateElement( "foo" );
00558                 elementAssign->_Parse( "<incorrect foo='bar'/>", 0, TIXML_ENCODING_UNKNOWN );
00559                 *elementAssign = *element;
00560 
00561                 XmlTest( "Copy/Assign: element copy #1.", "element", elementCopy->Name() );
00562                 XmlTest( "Copy/Assign: element copy #2.", "value", elementCopy->Attribute( "name" )->Value() );
00563                 XmlTest( "Copy/Assign: element assign #1.", "element", elementAssign->Name() );
00564                 XmlTest( "Copy/Assign: element assign #2.", "value", elementAssign->Attribute( "name" )->Value() );
00565                 XmlTest( "Copy/Assign: element assign #3.", true, ( elementAssign->Attribute( "foo" ).IsNotNull()) );
00566 
00567                 XmlComment comment;
00568                 comment._Parse( "<!--comment-->", 0, TIXML_ENCODING_UNKNOWN );
00569                 XmlComment commentCopy( comment );
00570                 XmlComment commentAssign;
00571                 commentAssign = commentCopy;
00572                 XmlTest( "Copy/Assign: comment copy.", "comment", commentCopy.Value() );
00573                 XmlTest( "Copy/Assign: comment assign.", "comment", commentAssign.Value() );
00574 
00575                 XmlUnknownPtr unknown = XmlUnknown::CreateUnknown();
00576                 unknown->_Parse( "<[unknown]>", 0, TIXML_ENCODING_UNKNOWN );
00577                 XmlUnknownPtr unknownCopy = XmlUnknown::CreateUnknown();
00578                 *unknownCopy = *unknown;
00579                 XmlUnknownPtr unknownAssign = XmlUnknown::CreateUnknown();
00580                 unknownAssign->_Parse( "<hi/>", 0, TIXML_ENCODING_UNKNOWN );
00581                 *unknownAssign = *unknownCopy;
00582                 XmlTest( "Copy/Assign: unknown copy.", "[unknown]", unknownCopy->Value() );
00583                 XmlTest( "Copy/Assign: unknown assign.", "[unknown]", unknownAssign->Value() );
00584                 
00585                 XmlText text( "TextNode" );
00586                 XmlText textCopy( text );
00587                 XmlText textAssign( "incorrect" );
00588                 textAssign = text;
00589                 XmlTest( "Copy/Assign: text copy.", "TextNode", textCopy.Value() );
00590                 XmlTest( "Copy/Assign: text assign.", "TextNode", textAssign.Value() );
00591 
00592                 XmlDeclaration dec;
00593                 dec._Parse( "<?xml version='1.0' encoding='UTF-8'?>", 0, TIXML_ENCODING_UNKNOWN );
00594                 XmlDeclaration decCopy( dec );
00595                 XmlDeclaration decAssign;
00596                 decAssign = dec;
00597 
00598                 XmlTest( "Copy/Assign: declaration copy.", "UTF-8", decCopy.Encoding() );
00599                 XmlTest( "Copy/Assign: text assign.", "UTF-8", decAssign.Encoding() );
00600 
00601                 //XmlDocument doc;
00602                 //elementCopy.AppendChild( textCopy );
00603                 //doc.AppendChild( decAssign );
00604                 //doc.AppendChild( elementCopy );
00605                 //doc.AppendChild( unknownAssign );
00606 
00607                 //XmlDocument docCopy( doc );
00608                 //XmlDocument docAssign;
00609                 //docAssign = docCopy;
00610         }       
00611         DEBUG_CLEAR_MEM_CHECK_POINTS();
00612         DEBUG_DUMP_MEM_LEAKS();
00613         UNIT_ASSERT_MEM_NOTED("TinyXML 8");
00614         Log::SWriteOkFail( "TinyXML copy and assignment" );
00615         
00617         {
00618         const char *xmlcp = "<text><start>This  is    \ntext</start></text>";
00619         XmlParsingData conf(xmlcp, 3, 0, 0, false);
00620         
00621                 XmlDocumentPtr doc = XmlDocument::ParseXml( "<text><start>This  is    \ntext</start></text>", &conf );
00622                 UNIT_ASSERT("should be element", doc->FirstChild()->NodeType() == XmlNode::ELEMENT);
00623                 XmlElementPtr text = (XmlElementPtr)doc->FirstChild();
00624                 UNIT_ASSERT("should be element", text->FirstChild()->NodeType() == XmlNode::ELEMENT);
00625                 XmlElementPtr start = (XmlElementPtr)text->FirstChild();
00626                 UNIT_ASSERT("should be element", start->FirstChild()->NodeType() == XmlNode::TEXT);
00627                 XmlElementPtr content = (XmlElementPtr)start->FirstChild();
00628                 
00629                 XmlTest ( "Condense white space OFF.", "This  is    \ntext",
00630                                         content->Value(),
00631                                         true );
00632         }
00633         DEBUG_CLEAR_MEM_CHECK_POINTS();
00634         DEBUG_DUMP_MEM_LEAKS();
00635         UNIT_ASSERT_MEM_NOTED("TinyXML 9");
00636         Log::SWriteOkFail( "TinyXML no condense white space" );
00637         
00639         // GetText();
00640         {
00641                 const char* str = "<foo>This is text</foo>";
00642                 XmlDocumentPtr doc = XmlDocument::ParseXml(str);
00643                 XmlElementPtr element = doc->RootElement();
00644 
00645                 XmlTest( "InnerText() normal use.", "This is text", element->InnerText() );
00646 
00647                 str = "<foo><b>This is text</b></foo>";
00648                 doc = XmlDocument::ParseXml( str );
00649                 element = doc->RootElement();
00650 
00651                 XmlTest( "InnerText() contained element.", "This is text", element->InnerText() );
00652 
00653                 str = "<foo>This is <b>text</b></foo>";
00654                 XmlDocument::SetCondenseWhiteSpace( false );
00655                 doc = XmlDocument::ParseXml( str );
00656                 XmlDocument::SetCondenseWhiteSpace( true );
00657                 element = doc->RootElement();
00658 
00659                 XmlTest( "InnerText() partial.", "This is text", element->InnerText() );
00660         }
00661         DEBUG_CLEAR_MEM_CHECK_POINTS();
00662         DEBUG_DUMP_MEM_LEAKS();
00663         UNIT_ASSERT_MEM_NOTED("TinyXML 10");
00664         Log::SWriteOkFail( "TinyXML InnerText()" );
00665         
00667         // CDATA
00668         {
00669                 const char* str =       "<xmlElement>"
00670                                                                 "<![CDATA["
00671                                                                         "I am > the rules!\n"
00672                                                                         "...since I make symbolic puns"
00673                                                                 "]]>"
00674                                                         "</xmlElement>";
00675                 XmlDocumentPtr doc = XmlDocument::ParseXml( str );
00676                 //doc.Print();
00677                 XmlTest( "CDATA copy.", "I am > the rules!\n...since I make symbolic puns", doc->FirstChildElement()->FirstChild()->Value(), true );
00678 
00679                 //XmlTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(), 
00680                 //                                               "I am > the rules!\n...since I make symbolic puns",
00681                 //                                               true );
00682 
00683                 XmlDocumentPtr doc1 = doc->Clone();
00684                 //doc.Print();
00685 
00686                 XmlTest( "CDATA copy.", "I am > the rules!\n...since I make symbolic puns", doc1->FirstChildElement()->FirstChild()->Value(), true );
00687         }
00688         DEBUG_CLEAR_MEM_CHECK_POINTS();
00689         DEBUG_DUMP_MEM_LEAKS();
00690         UNIT_ASSERT_MEM_NOTED("TinyXML 11");
00691         Log::SWriteOkFail( "TinyXML CDATA" );
00692         
00693         {
00694                 // [ 1482728 ] Wrong wide char parsing
00695                 char buf[256];
00696                 buf[255] = 0;
00697                 for( int i=0; i<255; ++i ) 
00698                 {
00699                         buf[i] = (char)((i>=32) ? i : 32);
00700                 }
00701                 String str( "<xmlElement><![CDATA[" );
00702                 str = str + buf;
00703                 str = str + "]]></xmlElement>";
00704 
00705                 XmlDocumentPtr doc = XmlDocument::ParseXml( str.GetChars() );
00706 
00707                 //XmlPrinter printer;
00708                 //printer.SetStreamPrinting();
00709                 //doc.Accept( &printer );
00710 
00711                 //XmlTest( "CDATA with all bytes #1.", str.c_str(), printer.CStr(), true );
00712         }
00713         DEBUG_CLEAR_MEM_CHECK_POINTS();
00714         DEBUG_DUMP_MEM_LEAKS();
00715         UNIT_ASSERT_MEM_NOTED("TinyXML 12");
00716         Log::SWriteOkFail( "TinyXML 1482728" );
00717         
00718         {
00719                 // [ 1480107 ] Bug-fix for STL-streaming of CDATA that contains tags
00720                 // CDATA streaming had a couple of bugs, that this tests for.
00721                 const char* str =       "<xmlElement>"
00722                                                                 "<![CDATA["
00723                                                                         "<b>I am > the rules!</b>\n"
00724                                                                         "...since I make symbolic puns"
00725                                                                 "]]>"
00726                                                         "</xmlElement>";
00727                 XmlDocumentPtr doc = XmlDocument::ParseXml(str);
00728 
00729                 XmlTest( "CDATA parse. [ 1480107 ]", 
00730                                 "<b>I am > the rules!</b>\n...since I make symbolic puns",
00731                                 doc->FirstChildElement()->FirstChild()->Value(),
00732                                 true );
00733 
00734                 XmlDocumentPtr doc1 = doc->Clone();
00735                 //doc.Print();
00736 
00737                 XmlTest( "CDATA copy. [ 1480107 ]", 
00738                                                                  "<b>I am > the rules!</b>\n...since I make symbolic puns",
00739                                 doc1->FirstChildElement()->FirstChild()->Value(),
00740                                                                  true );
00741         }
00742         DEBUG_CLEAR_MEM_CHECK_POINTS();
00743         DEBUG_DUMP_MEM_LEAKS();
00744         UNIT_ASSERT_MEM_NOTED("TinyXML 12");
00745         Log::SWriteOkFail( "TinyXML 1480107" );
00746         
00748 
00749         const int FUZZ_ITERATION = 200;
00750 
00751         // The only goal is not to crash on bad input.
00752         int len = (int) strlen( _demoStart );
00753         for( int i = 0; i < FUZZ_ITERATION; ++i ) 
00754         {
00755                 char* demoCopy = new char[ len+1 ];
00756                 ASSERT_MEM( demoCopy, len+1 );
00757 
00758                 strcpy( demoCopy, _demoStart );
00759 
00760                 demoCopy[ i%len ] = (char)((i+1)*3);
00761                 demoCopy[ (i*7)%len ] = '>';
00762                 demoCopy[ (i*11)%len ] = '<';
00763                 ASSERT_MEM( demoCopy, len+1 );
00764 
00765                 XmlDocumentPtr xml;
00766                 try
00767                 {
00768                         xml = XmlDocument::ParseXml( demoCopy );
00769                 }
00770                 catch ( XmlException *xex )
00771                 {
00772                         delete xex;
00773                 }
00774                 ASSERT_MEM( demoCopy, len+1 );
00775                 DEBUG_CLEAR_MEM_CHECK_POINTS();
00776                 xml.CheckMem();
00777                 DEBUG_NOTE_MEM(demoCopy);
00778                 DEBUG_DUMP_MEM_LEAKS();
00779                 UNIT_ASSERT_MEM_NOTED("TinyXML 12a");
00780 
00781                 delete [] demoCopy;
00782 
00783                 DEBUG_VALIDATE();
00784         }
00785         DEBUG_CLEAR_MEM_CHECK_POINTS();
00786         DEBUG_DUMP_MEM_LEAKS();
00787         UNIT_ASSERT_MEM_NOTED("TinyXML 13");
00788         Log::SWriteOkFail( "TinyXML Fuzzing" );
00789         
00791 
00792         // InsertBeforeChild and InsertAfterChild causes crash.
00793         {
00794                 XmlElementPtr parent = XmlElement::CreateElement( "Parent" );
00795                 XmlElementPtr childText0 = XmlElement::CreateElement( "childText0" );
00796                 XmlElementPtr childText1 = XmlElement::CreateElement( "childText1" );
00797                 parent->AppendChild( childText0 );
00798                 parent->InsertBefore( childText0, childText1 );
00799 
00800                 XmlTest( "Test InsertBeforeChild on empty node.", ( childText1.Get() == parent->FirstChild().Get() ), true );
00801         }
00802         DEBUG_CLEAR_MEM_CHECK_POINTS();
00803         DEBUG_DUMP_MEM_LEAKS();
00804         UNIT_ASSERT_MEM_NOTED("TinyXML 14");
00805         Log::SWriteOkFail( "TinyXML InsertBeforeChild and InsertAfterChild" );
00806         
00807         {
00808                 // InsertBeforeChild and InsertAfterChild causes crash.
00809                 XmlElementPtr parent = XmlElement::CreateElement( "Parent" );
00810                 XmlElementPtr childText0 = XmlElement::CreateElement( "childText0" );
00811                 XmlElementPtr childText1 = XmlElement::CreateElement( "childText1" );
00812                 parent->AppendChild( childText0 );
00813                 parent->InsertAfter( childText0, childText1 );
00814 
00815                 XmlTest( "Test InsertAfterChild on empty node. ", ( childText1.Get() == parent->LastChild().Get() ), true );
00816         }
00817         DEBUG_CLEAR_MEM_CHECK_POINTS();
00818         DEBUG_DUMP_MEM_LEAKS();
00819         UNIT_ASSERT_MEM_NOTED("TinyXML 15");
00820         Log::SWriteOkFail( "TinyXML InsertBeforeChild and InsertAfterChild 2" );
00821         
00822         // Reports of missing constructors, irregular string problems.
00823         {
00824                         // verifying some basic string functions:
00825                         String a;
00826                         String b( "Hello" );
00827                         String c( "ooga" );
00828 
00829                         c = " World!";
00830                         a = b;
00831                         a = a + c;
00832                         a = a;
00833 
00834                         XmlTest( "Basic TiXmlString test. ", "Hello World!", a );
00835         }
00836         DEBUG_CLEAR_MEM_CHECK_POINTS();
00837         DEBUG_DUMP_MEM_LEAKS();
00838         UNIT_ASSERT_MEM_NOTED("TinyXML 16");
00839         Log::SWriteOkFail( "TinyXML missing constructors, irregular string problems" );
00840         
00841         if ( File::Exists("test/midsummerNightsDreamWithAVeryLongFilenameToConfuseTheStringHandlingRoutines.xml"))
00842         {
00843                 {
00844                         XmlDocumentPtr doc = XmlDocument::Parse( "test/midsummerNightsDreamWithAVeryLongFilenameToConfuseTheStringHandlingRoutines.xml" );
00845                         doc.ValidateMem();
00846                         DEBUG_CLEAR_MEM_CHECK_POINTS();
00847                         doc.CheckMem();
00848                         DEBUG_DUMP_MEM_LEAKS();
00849                         UNIT_ASSERT_MEM_NOTED("TinyXML 17-1");
00850 
00851                 }
00852                 DEBUG_CLEAR_MEM_CHECK_POINTS();
00853                 DEBUG_DUMP_MEM_LEAKS();
00854                 UNIT_ASSERT_MEM_NOTED("TinyXML 17");
00855                 Log::SWriteOkFail( "TinyXML Long filenames" );
00856         }
00857 
00858         {
00859                 // Entities not being written correctly.
00860                 // From Lynn Allen
00861 
00862                 const char* passages =
00863                         "<?xml version=\"1.0\" standalone=\"no\" ?>"
00864                         "<passages count=\"006\" formatversion=\"20020620\">"
00865                                 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
00866                                 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
00867                         "</passages>";
00868 
00869                 XmlDocumentPtr doc = XmlDocument::ParseXml( passages );
00870                 XmlElementPtr psg = doc->RootElement()->FirstChildElement();
00871                 ASSERT( psg->Attribute( "context" ).IsNotNull() );
00872                 StringPtr context = psg->Attribute( "context" )->Value();
00873                 const char* expected = "Line 5 has \"quotation marks\" and 'apostrophe marks'. It also has <, >, and &, as well as a fake copyright \xC2\xA9.";
00874 
00875                 XmlTest( "Entity transformation: read. ", expected, context->GetChars(), true );
00876 
00877                 FILE* textfile = fopen( "textfile.txt", "w" );
00878                 if ( textfile )
00879                 {
00880                         fputs( psg->ToString()->GetChars(), textfile );
00881                         fclose( textfile );
00882                 }
00883                 textfile = fopen( "textfile.txt", "r" );
00884                 ASSERT( textfile );
00885                 if ( textfile )
00886                 {
00887                         char buf[ 1024 ];
00888                         fgets( buf, 1024, textfile );
00889                         XmlTest( "Entity transformation: write. ",
00890                                          "<psg context=\'Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
00891                                          " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.' />",
00892                                          buf,
00893                                          true );
00894                 }
00895                 fclose( textfile );
00896                 File::Delete("textfile.txt");
00897         }
00898         DEBUG_CLEAR_MEM_CHECK_POINTS();
00899         DEBUG_DUMP_MEM_LEAKS();
00900         UNIT_ASSERT_MEM_NOTED("TinyXML 18");
00901         Log::SWriteOkFail( "TinyXML Entities written correctly" );
00902         
00903     {
00904                 FILE* textfile = fopen( "test5.xml", "w" );
00905                 if ( textfile )
00906                 {
00907             fputs("<?xml version='1.0'?><a.elem xmi.version='2.0'/>", textfile);
00908             fclose(textfile);
00909 
00910                         XmlDocumentPtr doc = XmlDocument::Parse( "test5.xml" );
00911                 }
00912     }
00913         DEBUG_CLEAR_MEM_CHECK_POINTS();
00914         DEBUG_DUMP_MEM_LEAKS();
00915         UNIT_ASSERT_MEM_NOTED("TinyXML 19");
00916         Log::SWriteOkFail( "TinyXML 5" );
00917         
00918         {
00919                 FILE* textfile = fopen( "test6.xml", "w" );
00920                 if ( textfile )
00921                 {
00922             fputs("<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>", textfile );
00923             fclose(textfile);
00924 
00925             XmlDocumentPtr doc = XmlDocument::Parse( "test6.xml" );
00926 
00927                         XmlTextPtr text = doc->FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
00928                         XmlTest( "Entity with one digit.",
00929                                                 text->Value()->GetChars(), "1.1 Start easy ignore fin thickness\n" );
00930                 }
00931     }
00932         DEBUG_CLEAR_MEM_CHECK_POINTS();
00933         DEBUG_DUMP_MEM_LEAKS();
00934         UNIT_ASSERT_MEM_NOTED("TinyXML 20");
00935         Log::SWriteOkFail( "TinyXML 6" );
00936         
00937         {
00938                 // DOCTYPE not preserved (950171)
00939                 // 
00940                 const char* doctype =
00941                         "<?xml version=\"1.0\" ?>"
00942                         "<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
00943                         "<!ELEMENT title (#PCDATA)>"
00944                         "<!ELEMENT books (title,authors)>"
00945                         "<element />";
00946 
00947                 XmlDocumentPtr doc = XmlDocument::ParseXml( doctype );
00948                 doc->Write( "test7.xml" );
00949                 doc = XmlDocument::Parse( "test7.xml" );
00950                 
00951                 XmlUnknownPtr unknown = doc->Child( 1 )->ToUnknown();
00952                 XmlTest( "Correct value of unknown.", "!DOCTYPE PLAY SYSTEM 'play.dtd'", unknown->Value() );
00953         }
00954         DEBUG_CLEAR_MEM_CHECK_POINTS();
00955         DEBUG_DUMP_MEM_LEAKS();
00956         UNIT_ASSERT_MEM_NOTED("TinyXML 20");
00957         Log::SWriteOkFail( "TinyXML 950171" );
00958         
00959         {
00960                 // [ 791411 ] Formatting bug
00961                 // Comments do not stream out correctly.
00962                 const char* doctype = 
00963                         "<!-- Somewhat<evil> -->";
00964                 XmlDocumentPtr doc = XmlDocument::ParseXml( doctype );
00965 
00966                 XmlCommentPtr comment = doc->Child( 0 )->ToComment();
00967 
00968                 XmlTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
00969                 #ifdef TIXML_USE_STL
00970                 std::string str;
00971                 str << (*comment);
00972                 XmlTest( "Comment streaming.", "<!-- Somewhat<evil> -->", str.c_str() );
00973                 #endif
00974         }
00975         DEBUG_CLEAR_MEM_CHECK_POINTS();
00976         DEBUG_DUMP_MEM_LEAKS();
00977         UNIT_ASSERT_MEM_NOTED("TinyXML 21");
00978         Log::SWriteOkFail( "TinyXML 791411" );
00979         
00980         {
00981                 // [ 870502 ] White space issues
00982                 XmlDocumentPtr doc;
00983                 XmlTextPtr text;
00984         
00985                 const char* doctype0 = "<element> This has leading and trailing space </element>";
00986                 const char* doctype1 = "<element>This has  internal space</element>";
00987                 const char* doctype2 = "<element> This has leading, trailing, and  internal space </element>";
00988 
00989                 XmlDocument::SetCondenseWhiteSpace( false );
00990                 doc = XmlDocument::ParseXml( doctype0 );
00991                 text = doc->FirstChildElement( "element" )->Child( 0 )->ToText();
00992                 XmlTest( "White space kept.", " This has leading and trailing space ", text->Value()->GetChars() );
00993 
00994                 doc = XmlDocument::ParseXml( doctype1 );
00995                 text = doc->FirstChildElement( "element" )->Child( 0 )->ToText();
00996                 XmlTest( "White space kept.", "This has  internal space", text->Value() );
00997 
00998                 doc = XmlDocument::ParseXml( doctype2 );
00999                 text = doc->FirstChildElement( "element" )->Child( 0 )->ToText();
01000                 XmlTest( "White space kept.", " This has leading, trailing, and  internal space ", text->Value()->GetChars() );
01001 
01002                 XmlDocument::SetCondenseWhiteSpace( true );
01003                 doc = XmlDocument::ParseXml( doctype0 );
01004                 text = doc->FirstChildElement( "element" )->Child( 0 )->ToText();
01005                 XmlTest( "White space condensed.", "This has leading and trailing space", text->Value() );
01006 
01007                 doc = XmlDocument::ParseXml( doctype1 );
01008                 text = doc->FirstChildElement( "element" )->Child( 0 )->ToText();
01009                 XmlTest( "White space condensed.", "This has internal space", text->Value() );
01010 
01011                 doc = XmlDocument::ParseXml( doctype2 );
01012                 text = doc->FirstChildElement( "element" )->Child( 0 )->ToText();
01013                 XmlTest( "White space condensed.", "This has leading, trailing, and internal space", text->Value() );
01014         }
01015         DEBUG_CLEAR_MEM_CHECK_POINTS();
01016         DEBUG_DUMP_MEM_LEAKS();
01017         UNIT_ASSERT_MEM_NOTED("TinyXML 21");
01018         Log::SWriteOkFail( "TinyXML 870502" );
01019         
01020         {
01021                 // Double attributes
01022                 const char* doctype = "<element attr='red' attr='blue' />";
01023 
01024                 XmlDocumentPtr doc = XmlDocument::ParseXml( doctype );
01025                 
01026                 XmlTest( "Parsing repeated attributes.", "blue", doc->FirstChildElement( "element" )->Attribute( "attr" )->Value() );
01027         }
01028         DEBUG_CLEAR_MEM_CHECK_POINTS();
01029         DEBUG_DUMP_MEM_LEAKS();
01030         UNIT_ASSERT_MEM_NOTED("TinyXML 22");
01031         Log::SWriteOkFail( "TinyXML Double attributes" );
01032         
01033         {
01034                 // Embedded null in stream.
01035                 const char* doctype = "<element att\0r='red' attr='blue' />";
01036 
01037                 XmlDocumentPtr doc;
01038                 try
01039                 {
01040                         doc = XmlDocument::ParseXml( doctype );
01041                         UNIT_ASSERT("Should have thrown an error", false);
01042                 }
01043                 catch ( XmlException *ex )
01044                 {
01045                         delete ex;
01046                 }
01047         }
01048         DEBUG_CLEAR_MEM_CHECK_POINTS();
01049         DEBUG_DUMP_MEM_LEAKS();
01050         UNIT_ASSERT_MEM_NOTED("TinyXML 23");
01051         Log::SWriteOkFail( "TinyXML Embedded null in stream" );
01052         
01053     {
01054             // Legacy mode test. (This test may only pass on a western system)
01055             const char* str =
01056                         "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>"
01057                         "<ä>"
01058                         "CöntäntßäöüÄÖÜ"
01059                         "</ä>";
01060 
01061             XmlDocumentPtr doc = XmlDocument::ParseXml( str );
01062 
01063             XmlElementPtr aHandle = doc->FirstChildElement( "ä" );
01064             XmlNodePtr tHandle = aHandle->Child( 0 );
01065             ASSERT( aHandle->IsElement() );
01066             ASSERT( tHandle->IsText() );
01067             XmlTest( "ISO-8859-1 Parsing.", "CöntäntßäöüÄÖÜ", tHandle->ToText()->Value() );
01068     }
01069         DEBUG_CLEAR_MEM_CHECK_POINTS();
01070         DEBUG_DUMP_MEM_LEAKS();
01071         UNIT_ASSERT_MEM_NOTED("TinyXML 24");
01072         Log::SWriteOkFail( "TinyXML Legacy mode" );
01073         
01074         {
01075                 // Empty documents should return TIXML_ERROR_PARSING_EMPTY, bug 1070717
01076                 const char* str = "    ";
01077                 XmlDocumentPtr doc;
01078                 try
01079                 {
01080                         doc = XmlDocument::ParseXml( str );
01081                         UNIT_ASSERT("Should have thrown an error", false);
01082                 }
01083                 catch ( XmlException *xex )
01084                 {
01085                         delete xex;
01086                 }
01087         }
01088         DEBUG_CLEAR_MEM_CHECK_POINTS();
01089         DEBUG_DUMP_MEM_LEAKS();
01090         UNIT_ASSERT_MEM_NOTED("TinyXML 25");
01091         Log::SWriteOkFail( "TinyXML 1070717" );
01092         
01093         {
01094                 // String equality. [ 1006409 ] string operator==/!= no worky in all cases
01095                 String temp;
01096                 XmlTest( "Empty tinyxml string compare equal", ( temp == "" ), true );
01097 
01098                 String    foo;
01099                 String    bar( "" );
01100                 XmlTest( "Empty tinyxml string compare equal", ( foo == bar ), true );
01101         }
01102         DEBUG_CLEAR_MEM_CHECK_POINTS();
01103         DEBUG_DUMP_MEM_LEAKS();
01104         UNIT_ASSERT_MEM_NOTED("TinyXML 26");
01105         Log::SWriteOkFail( "TinyXML 1006409" );
01106         
01107         {
01108                 // Bug [ 1195696 ] from marlonism
01109                 XmlDocument::SetCondenseWhiteSpace(false); 
01110                 XmlDocumentPtr xml = XmlDocument::ParseXml("<text><break/>This hangs</text>"); 
01111         }
01112         DEBUG_CLEAR_MEM_CHECK_POINTS();
01113         DEBUG_DUMP_MEM_LEAKS();
01114         UNIT_ASSERT_MEM_NOTED("TinyXML 26");
01115         Log::SWriteOkFail( "TinyXML 1195696" );
01116         
01117         {
01118                 // Bug [ 1243992 ] - another infinite loop
01119                 XmlDocument::SetCondenseWhiteSpace(false);
01120                 XmlDocumentPtr doc = XmlDocument::ParseXml("<p><pb></pb>test</p>");
01121         } 
01122         DEBUG_CLEAR_MEM_CHECK_POINTS();
01123         DEBUG_DUMP_MEM_LEAKS();
01124         UNIT_ASSERT_MEM_NOTED("TinyXML 27");
01125         Log::SWriteOkFail( "TinyXML 1243992" );
01126         
01127         {
01128                 // Low entities
01129                 XmlDocumentPtr xml = XmlDocument::ParseXml( "<test>&#x0e;</test>" );
01130                 const char result[] = { 0x0e, 0 };
01131                 XmlTest( "Low entities.", xml->FirstChildElement()->InnerText()->GetChars(), result );
01132                 //xml.Print();
01133         }
01134         DEBUG_CLEAR_MEM_CHECK_POINTS();
01135         DEBUG_DUMP_MEM_LEAKS();
01136         UNIT_ASSERT_MEM_NOTED("TinyXML 28");
01137         Log::SWriteOkFail( "TinyXML Low entities" );
01138         
01139         {
01140                 // Bug [ 1451649 ] Attribute values with trailing quotes not handled correctly
01141                 XmlDocumentPtr xml;
01142                 try
01143                 {
01144                         xml = XmlDocument::ParseXml( "<foo attribute=bar\" />" );
01145                         UNIT_ASSERT("Should have thrown an error", false);
01146                 }
01147                 catch ( XmlException *xex )
01148                 {
01149                         delete xex;
01150                 }
01151         }
01152         DEBUG_CLEAR_MEM_CHECK_POINTS();
01153         DEBUG_DUMP_MEM_LEAKS();
01154         UNIT_ASSERT_MEM_NOTED("TinyXML 29");
01155         Log::SWriteOkFail( "TinyXML 1451649" );
01156         
01157         #ifdef TIXML_USE_STL
01158         {
01159                 // Bug [ 1449463 ] Consider generic query
01160                 XmlDocumentPtr xml = XmlDocument::ParseXml( "<foo bar='3' barStr='a string'/>" );
01161 
01162                 XmlElement* ele = xml->FirstChildElement();
01163                 double d;
01164                 int i;
01165                 float f;
01166                 bool b;
01167                 //std::string str;
01168 
01169                 XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &d ), TIXML_SUCCESS );
01170                 XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &i ), TIXML_SUCCESS );
01171                 XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &f ), TIXML_SUCCESS );
01172                 XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &b ), TIXML_WRONG_TYPE );
01173                 XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "nobar", &b ), TIXML_NO_ATTRIBUTE );
01174                 //XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "barStr", &str ), TIXML_SUCCESS );
01175 
01176                 XmlTest( "QueryValueAttribute", (d==3.0), true );
01177                 XmlTest( "QueryValueAttribute", (i==3), true );
01178                 XmlTest( "QueryValueAttribute", (f==3.0f), true );
01179                 //XmlTest( "QueryValueAttribute", (str==std::string( "a string" )), true );
01180         }
01181         #endif
01182         DEBUG_CLEAR_MEM_CHECK_POINTS();
01183         DEBUG_DUMP_MEM_LEAKS();
01184         UNIT_ASSERT_MEM_NOTED("TinyXML 30");
01185         Log::SWriteOkFail( "TinyXML 1449463" );
01186         
01187         #ifdef TIXML_USE_STL
01188         {
01189                 // [ 1505267 ] redundant malloc in TiXmlElement::Attribute
01190                 XmlDocumentPtr xml = XmlDocument::ParseXml( "<foo bar='3' />" );
01191                 XmlElement* ele = xml->FirstChildElement();
01192                 double d;
01193                 int i;
01194 
01195                 std::string bar = "bar";
01196 
01197                 const std::string* atrrib = ele->Attribute( bar );
01198                 ele->Attribute( bar, &d );
01199                 ele->Attribute( bar, &i );
01200 
01201                 XmlTest( "Attribute", atrrib->empty(), false );
01202                 XmlTest( "Attribute", (d==3.0), true );
01203                 XmlTest( "Attribute", (i==3), true );
01204         }
01205         #endif
01206         DEBUG_CLEAR_MEM_CHECK_POINTS();
01207         DEBUG_DUMP_MEM_LEAKS();
01208         UNIT_ASSERT_MEM_NOTED("TinyXML 31");
01209         Log::SWriteOkFail( "TinyXML 1505267" );
01210         
01211         {
01212                 // [ 1356059 ] Allow TiXMLDocument to only be at the top level
01213                 XmlDocumentPtr xml = XmlDocument::ParseXml("<hi/>");
01214                 XmlDocumentPtr xml2 = XmlDocument::ParseXml("<hi/>");
01215                 try
01216                 {
01217                         xml->AppendChild( xml2 );
01218                         XmlTest( "Document only at top level.", false, true );
01219                 }
01220                 catch (XmlException *xec)
01221                 {
01222                         delete xec;
01223                 }
01224         }
01225         DEBUG_CLEAR_MEM_CHECK_POINTS();
01226         DEBUG_DUMP_MEM_LEAKS();
01227         UNIT_ASSERT_MEM_NOTED("TinyXML 32");
01228         Log::SWriteOkFail( "TinyXML 1356059" );
01229         
01230         {
01231                 // [ 1663758 ] Failure to report error on bad XML
01232                 XmlDocumentPtr xml;
01233                 try
01234                 {
01235                         xml = XmlDocument::ParseXml("<x>");
01236                         UNIT_ASSERT("Should have thrown an error", false);
01237                 }
01238                 catch ( XmlException *xex )
01239                 {
01240                         delete xex;
01241                 }
01242                 try
01243                 {
01244                         xml = XmlDocument::ParseXml("<x> ");
01245                         UNIT_ASSERT("Should have thrown an error", false);
01246                 }
01247                 catch ( XmlException *xex )
01248                 {
01249                         delete xex;
01250                 }
01251         } 
01252         DEBUG_CLEAR_MEM_CHECK_POINTS();
01253         DEBUG_DUMP_MEM_LEAKS();
01254         UNIT_ASSERT_MEM_NOTED("TinyXML 33");
01255         Log::SWriteOkFail( "TinyXML 1663758" );
01256         
01257         //Log::WriteCheck( "TinyXML 1635701" );
01258         //{
01259         //      // [ 1635701 ] fail to parse files with a tag separated into two lines
01260         //      // I'm not sure this is a bug. Marked 'pending' for feedback.
01261         //      XmlDocument xml;
01262         //      xml.LoadXml( "<title><p>text</p\n><title>" );
01263         //      //xml.Print();
01264         //      //XmlTest( "Tag split by newline", xml.Error(), false );
01265         //}
01266         //DEBUG_CLEAR_MEM_CHECK_POINTS();
01267         //DEBUG_DUMP_MEM_LEAKS();
01268         //UNIT_ASSERT_MEM_NOTED("TinyXML 34");
01269         //Log::WriteOkFail(  );
01270         
01271         //Log::WriteCheck( "TinyXML 1475201" );
01272         //{
01273         //      // [ 1475201 ] TinyXML parses entities in comments
01274         //      XmlDocument xml;
01275         //      istringstream parse1( "<!-- declarations for <head> & <body> -->"
01276         //                                            "<!-- far &amp; away -->" );
01277         //      parse1 >> xml;
01278         //
01279         //      XmlNode* e0 = xml.FirstChild();
01280         //      XmlNode* e1 = e0->NextSibling();
01281         //      XmlComment* c0 = e0->ToComment();
01282         //      XmlComment* c1 = e1->ToComment();
01283         //
01284         //      XmlTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
01285         //      XmlTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
01286         //}
01287         //DEBUG_CLEAR_MEM_CHECK_POINTS();
01288         //DEBUG_DUMP_MEM_LEAKS();
01289         //UNIT_ASSERT_MEM_NOTED("TinyXML 35");
01290         //Log::WriteOkFail(  );
01291         
01292         {
01293                 // [ 1475201 ] TinyXML parses entities in comments
01294                 XmlDocumentPtr xml = XmlDocument::ParseXml("<!-- declarations for <head> & <body> -->"
01295                                   "<!-- far &amp; away -->" );
01296 
01297                 XmlNodePtr e0 = xml->FirstChild();
01298                 XmlNodePtr e1 = e0->NextSibling();
01299                 XmlCommentPtr c0 = e0->ToComment();
01300                 XmlCommentPtr c1 = e1->ToComment();
01301 
01302                 XmlTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
01303                 XmlTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
01304         }
01305         DEBUG_CLEAR_MEM_CHECK_POINTS();
01306         DEBUG_DUMP_MEM_LEAKS();
01307         UNIT_ASSERT_MEM_NOTED("TinyXML 35");
01308         Log::SWriteOkFail( "TinyXML 1475201" );
01309 
01310         File::Delete("test5.xml");
01311         File::Delete("test6.xml");
01312         File::Delete("test7.xml");
01313         File::Delete("utf8testout.xml");
01314         File::Delete("demotest.xml");
01315 }
01316 
01317 void _TestXml()
01318 {
01319         _TestTinyXml();
01320         DEBUG_CLEAR_MEM_CHECK_POINTS();
01321         DEBUG_DUMP_MEM_LEAKS();
01322 }
01323 
01324 #endif