blob: 7332ba023f0e05ef64c4e406c29d18c2bfb4463b [file] [log] [blame]
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001#include "tinyxml2.h"
2
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -07003#include <cstdlib>
4#include <cstring>
5#include <ctime>
U-Lama\Leee13c3e62011-12-28 14:36:55 -08006
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08007#if defined( _MSC_VER )
Lee Thomason1ff38e02012-02-14 18:18:16 -08008 #include <crtdbg.h>
Lee Thomason6f381b72012-03-02 12:59:39 -08009 #define WIN32_LEAN_AND_MEAN
10 #include <windows.h>
Lee Thomason1ff38e02012-02-14 18:18:16 -080011 _CrtMemState startMemState;
12 _CrtMemState endMemState;
13#endif
Lee Thomasone9ecdab2012-02-13 18:11:20 -080014
U-Lama\Leee13c3e62011-12-28 14:36:55 -080015using namespace tinyxml2;
Lee Thomasonec5a7b42012-02-13 18:16:52 -080016int gPass = 0;
17int gFail = 0;
18
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -080019
U-Stream\Lee09a11c52012-02-17 08:31:16 -080020bool XMLTest (const char* testString, const char* expected, const char* found, bool echo=true )
Lee Thomason1ff38e02012-02-14 18:18:16 -080021{
22 bool pass = !strcmp( expected, found );
23 if ( pass )
24 printf ("[pass]");
25 else
26 printf ("[fail]");
27
U-Stream\Lee09a11c52012-02-17 08:31:16 -080028 if ( !echo )
Lee Thomason1ff38e02012-02-14 18:18:16 -080029 printf (" %s\n", testString);
30 else
31 printf (" %s [%s][%s]\n", testString, expected, found);
32
33 if ( pass )
34 ++gPass;
35 else
36 ++gFail;
37 return pass;
38}
39
40
U-Stream\Lee09a11c52012-02-17 08:31:16 -080041bool XMLTest( const char* testString, int expected, int found, bool echo=true )
Lee Thomason1ff38e02012-02-14 18:18:16 -080042{
43 bool pass = ( expected == found );
44 if ( pass )
45 printf ("[pass]");
46 else
47 printf ("[fail]");
48
U-Stream\Lee09a11c52012-02-17 08:31:16 -080049 if ( !echo )
Lee Thomason1ff38e02012-02-14 18:18:16 -080050 printf (" %s\n", testString);
51 else
52 printf (" %s [%d][%d]\n", testString, expected, found);
53
54 if ( pass )
55 ++gPass;
56 else
57 ++gFail;
58 return pass;
59}
Lee Thomasonec5a7b42012-02-13 18:16:52 -080060
U-Lama\Leee13c3e62011-12-28 14:36:55 -080061
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -080062void NullLineEndings( char* p )
63{
64 while( p && *p ) {
65 if ( *p == '\n' || *p == '\r' ) {
66 *p = 0;
67 return;
68 }
69 ++p;
70 }
71}
72
73
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -070074int main( int /*argc*/, const char ** /*argv*/ )
U-Lama\Leee13c3e62011-12-28 14:36:55 -080075{
Lee Thomason (grinliz)0a4df402012-02-27 20:50:52 -080076 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason1ff38e02012-02-14 18:18:16 -080077 _CrtMemCheckpoint( &startMemState );
78 #endif
Lee Thomason8a5dfee2012-01-18 17:43:40 -080079
Lee Thomason8a5dfee2012-01-18 17:43:40 -080080 {
Lee Thomason43f59302012-02-06 18:18:11 -080081 static const char* test[] = { "<element />",
82 "<element></element>",
83 "<element><subelement/></element>",
84 "<element><subelement></subelement></element>",
85 "<element><subelement><subsub/></subelement></element>",
86 "<!--comment beside elements--><element><subelement></subelement></element>",
87 "<!--comment beside elements, this time with spaces--> \n <element> <subelement> \n </subelement> </element>",
88 "<element attrib1='foo' attrib2=\"bar\" ></element>",
89 "<element attrib1='foo' attrib2=\"bar\" ><subelement attrib3='yeehaa' /></element>",
90 "<element>Text inside element.</element>",
91 "<element><b></b></element>",
92 "<element>Text inside and <b>bolded</b> in the element.</element>",
93 "<outer><element>Text inside and <b>bolded</b> in the element.</element></outer>",
Lee Thomason8ee79892012-01-25 17:44:30 -080094 "<element>This &amp; That.</element>",
Lee Thomason18d68bd2012-01-26 18:17:26 -080095 "<element attrib='This&lt;That' />",
Lee Thomasondadcdfa2012-01-18 17:55:48 -080096 0
97 };
Lee Thomason6ee99fc2012-01-21 18:45:16 -080098 for( int i=0; test[i]; ++i ) {
Lee Thomasondadcdfa2012-01-18 17:55:48 -080099 XMLDocument doc;
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800100 doc.Parse( test[i] );
Lee Thomason5cae8972012-01-24 18:03:07 -0800101 doc.Print();
Lee Thomasonec975ce2012-01-23 11:42:06 -0800102 printf( "----------------------------------------------\n" );
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800103 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800104 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800105#if 1
Lee Thomasond6277762012-02-22 16:00:12 -0800106 {
107 static const char* test = "<!--hello world\n"
108 " line 2\r"
109 " line 3\r\n"
110 " line 4\n\r"
111 " line 5\r-->";
112
113 XMLDocument doc;
114 doc.Parse( test );
115 doc.Print();
116 }
117
Lee Thomason2c85a712012-01-31 08:24:24 -0800118 {
119 static const char* test = "<element>Text before.</element>";
120 XMLDocument doc;
121 doc.Parse( test );
122 XMLElement* root = doc.FirstChildElement();
123 XMLElement* newElement = doc.NewElement( "Subelement" );
124 root->InsertEndChild( newElement );
125 doc.Print();
126 }
Lee Thomasond1983222012-02-06 08:41:24 -0800127 {
128 XMLDocument* doc = new XMLDocument();
129 static const char* test = "<element><sub/></element>";
130 doc->Parse( test );
131 delete doc;
132 }
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800133 {
Lee Thomason1ff38e02012-02-14 18:18:16 -0800134 // Test: Programmatic DOM
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800135 // Build:
136 // <element>
137 // <!--comment-->
138 // <sub attrib="1" />
139 // <sub attrib="2" />
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800140 // <sub attrib="3" >& Text!</sub>
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800141 // <element>
142
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800143 XMLDocument* doc = new XMLDocument();
Lee Thomason1ff38e02012-02-14 18:18:16 -0800144 XMLNode* element = doc->InsertEndChild( doc->NewElement( "element" ) );
145
146 XMLElement* sub[3] = { doc->NewElement( "sub" ), doc->NewElement( "sub" ), doc->NewElement( "sub" ) };
147 for( int i=0; i<3; ++i ) {
148 sub[i]->SetAttribute( "attrib", i );
149 }
150 element->InsertEndChild( sub[2] );
151 XMLNode* comment = element->InsertFirstChild( doc->NewComment( "comment" ) );
152 element->InsertAfterChild( comment, sub[0] );
153 element->InsertAfterChild( sub[0], sub[1] );
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800154 sub[2]->InsertFirstChild( doc->NewText( "& Text!" ));
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800155 doc->Print();
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800156 XMLTest( "Programmatic DOM", "comment", doc->FirstChildElement( "element" )->FirstChild()->Value() );
157 XMLTest( "Programmatic DOM", "0", doc->FirstChildElement( "element" )->FirstChildElement()->Attribute( "attrib" ) );
158 XMLTest( "Programmatic DOM", 2, doc->FirstChildElement()->LastChildElement( "sub" )->IntAttribute( "attrib" ) );
159 XMLTest( "Programmatic DOM", "& Text!",
160 doc->FirstChildElement()->LastChildElement( "sub" )->FirstChild()->ToText()->Value() );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800161
162 // And now deletion:
163 element->DeleteChild( sub[2] );
164 doc->DeleteNode( comment );
165
166 element->FirstChildElement()->SetAttribute( "attrib", true );
167 element->LastChildElement()->DeleteAttribute( "attrib" );
168
169 XMLTest( "Programmatic DOM", true, doc->FirstChildElement()->FirstChildElement()->BoolAttribute( "attrib" ) );
170 int value = 10;
171 int result = doc->FirstChildElement()->LastChildElement()->QueryIntAttribute( "attrib", &value );
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700172 XMLTest( "Programmatic DOM", result, XML_NO_ATTRIBUTE );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800173 XMLTest( "Programmatic DOM", value, 10 );
174
175 doc->Print();
176
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800177 XMLPrinter streamer;
U-Stream\Leeae25a442012-02-17 17:48:16 -0800178 doc->Print( &streamer );
179 printf( "%s", streamer.CStr() );
180
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800181 delete doc;
182 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800183 {
184 // Test: Dream
185 // XML1 : 1,187,569 bytes in 31,209 allocations
186 // XML2 : 469,073 bytes in 323 allocations
187 //int newStart = gNew;
188 XMLDocument doc;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800189 doc.LoadFile( "dream.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800190
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800191 doc.SaveFile( "dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800192 doc.PrintError();
193
194 XMLTest( "Dream", "xml version=\"1.0\"",
195 doc.FirstChild()->ToDeclaration()->Value() );
196 XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() ? true : false );
197 XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
198 doc.FirstChild()->NextSibling()->ToUnknown()->Value() );
199 XMLTest( "Dream", "And Robin shall restore amends.",
200 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
201 XMLTest( "Dream", "And Robin shall restore amends.",
202 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
203
204 XMLDocument doc2;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800205 doc2.LoadFile( "dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800206 XMLTest( "Dream-out", "xml version=\"1.0\"",
207 doc2.FirstChild()->ToDeclaration()->Value() );
208 XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() ? true : false );
209 XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
210 doc2.FirstChild()->NextSibling()->ToUnknown()->Value() );
211 XMLTest( "Dream-out", "And Robin shall restore amends.",
212 doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
213
214 //gNewTotal = gNew - newStart;
215 }
Lee Thomason6f381b72012-03-02 12:59:39 -0800216
217
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800218 {
219 const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n"
220 "<passages count=\"006\" formatversion=\"20020620\">\n"
221 " <wrong error>\n"
222 "</passages>";
223
224 XMLDocument doc;
225 doc.Parse( error );
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700226 XMLTest( "Bad XML", doc.ErrorID(), XML_ERROR_PARSING_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800227 }
228
229 {
230 const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
231
232 XMLDocument doc;
233 doc.Parse( str );
234
235 XMLElement* ele = doc.FirstChildElement();
236
237 int iVal, result;
238 double dVal;
239
240 result = ele->QueryDoubleAttribute( "attr0", &dVal );
241 XMLTest( "Query attribute: int as double", result, XML_NO_ERROR );
242 XMLTest( "Query attribute: int as double", (int)dVal, 1 );
243 result = ele->QueryDoubleAttribute( "attr1", &dVal );
244 XMLTest( "Query attribute: double as double", (int)dVal, 2 );
245 result = ele->QueryIntAttribute( "attr1", &iVal );
246 XMLTest( "Query attribute: double as int", result, XML_NO_ERROR );
247 XMLTest( "Query attribute: double as int", iVal, 2 );
248 result = ele->QueryIntAttribute( "attr2", &iVal );
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700249 XMLTest( "Query attribute: not a number", result, XML_WRONG_ATTRIBUTE_TYPE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800250 result = ele->QueryIntAttribute( "bar", &iVal );
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700251 XMLTest( "Query attribute: does not exist", result, XML_NO_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800252 }
253
254 {
255 const char* str = "<doc/>";
256
257 XMLDocument doc;
258 doc.Parse( str );
259
260 XMLElement* ele = doc.FirstChildElement();
261
262 int iVal;
263 double dVal;
264
265 ele->SetAttribute( "str", "strValue" );
266 ele->SetAttribute( "int", 1 );
267 ele->SetAttribute( "double", -1.0 );
268
269 const char* cStr = ele->Attribute( "str" );
270 ele->QueryIntAttribute( "int", &iVal );
271 ele->QueryDoubleAttribute( "double", &dVal );
272
273 XMLTest( "Attribute round trip. c-string.", "strValue", cStr );
274 XMLTest( "Attribute round trip. int.", 1, iVal );
275 XMLTest( "Attribute round trip. double.", -1, (int)dVal );
276 }
277
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800278 {
279 XMLDocument doc;
280 doc.LoadFile( "utf8test.xml" );
281
282 // Get the attribute "value" from the "Russian" element and check it.
283 XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" );
284 const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
285 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
286
287 XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) );
288
289 const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U,
290 0xd1U, 0x81U, 0xd1U, 0x81U,
291 0xd0U, 0xbaU, 0xd0U, 0xb8U,
292 0xd0U, 0xb9U, 0 };
293 const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
294
295 XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText();
296 XMLTest( "UTF-8: Browsing russian element name.",
297 russianText,
298 text->Value() );
299
300 // Now try for a round trip.
301 doc.SaveFile( "utf8testout.xml" );
302
303 // Check the round trip.
304 char savedBuf[256];
305 char verifyBuf[256];
306 int okay = 0;
307
Lee Thomason (grinliz)5ce4d972012-02-26 21:14:23 -0800308
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800309#if defined(_MSC_VER)
Lee Thomason (grinliz)5ce4d972012-02-26 21:14:23 -0800310#pragma warning ( push )
311#pragma warning ( disable : 4996 ) // Fail to see a compelling reason why this should be deprecated.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800312#endif
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800313 FILE* saved = fopen( "utf8testout.xml", "r" );
314 FILE* verify = fopen( "utf8testverify.xml", "r" );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800315#if defined(_MSC_VER)
Lee Thomason (grinliz)5ce4d972012-02-26 21:14:23 -0800316#pragma warning ( pop )
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800317#endif
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800318
319 if ( saved && verify )
320 {
321 okay = 1;
322 while ( fgets( verifyBuf, 256, verify ) )
323 {
324 fgets( savedBuf, 256, saved );
325 NullLineEndings( verifyBuf );
326 NullLineEndings( savedBuf );
327
328 if ( strcmp( verifyBuf, savedBuf ) )
329 {
330 printf( "verify:%s<\n", verifyBuf );
331 printf( "saved :%s<\n", savedBuf );
332 okay = 0;
333 break;
334 }
335 }
336 }
337 if ( saved )
338 fclose( saved );
339 if ( verify )
340 fclose( verify );
341 XMLTest( "UTF-8: Verified multi-language round trip.", 1, okay );
342 }
343
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800344 // --------GetText()-----------
345 {
346 const char* str = "<foo>This is text</foo>";
347 XMLDocument doc;
348 doc.Parse( str );
349 const XMLElement* element = doc.RootElement();
350
351 XMLTest( "GetText() normal use.", "This is text", element->GetText() );
352
353 str = "<foo><b>This is text</b></foo>";
354 doc.Parse( str );
355 element = doc.RootElement();
356
357 XMLTest( "GetText() contained element.", element->GetText() == 0, true );
358 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800359
Lee Thomasond6277762012-02-22 16:00:12 -0800360
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800361 // ---------- CDATA ---------------
362 {
363 const char* str = "<xmlElement>"
364 "<![CDATA["
365 "I am > the rules!\n"
366 "...since I make symbolic puns"
367 "]]>"
368 "</xmlElement>";
369 XMLDocument doc;
370 doc.Parse( str );
371 doc.Print();
Lee Thomasond6277762012-02-22 16:00:12 -0800372
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800373 XMLTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(),
374 "I am > the rules!\n...since I make symbolic puns",
Lee Thomasond6277762012-02-22 16:00:12 -0800375 false );
376 }
377
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800378 // ----------- CDATA -------------
379 {
380 const char* str = "<xmlElement>"
381 "<![CDATA["
382 "<b>I am > the rules!</b>\n"
383 "...since I make symbolic puns"
384 "]]>"
385 "</xmlElement>";
386 XMLDocument doc;
387 doc.Parse( str );
388 doc.Print();
389
390 XMLTest( "CDATA parse. [ tixml1:1480107 ]", doc.FirstChildElement()->FirstChild()->Value(),
391 "<b>I am > the rules!</b>\n...since I make symbolic puns",
392 false );
393 }
394
395 // InsertAfterChild causes crash.
396 {
397 // InsertBeforeChild and InsertAfterChild causes crash.
398 XMLDocument doc;
399 XMLElement* parent = doc.NewElement( "Parent" );
400 doc.InsertFirstChild( parent );
401
402 XMLElement* childText0 = doc.NewElement( "childText0" );
403 XMLElement* childText1 = doc.NewElement( "childText1" );
404
405 XMLNode* childNode0 = parent->InsertEndChild( childText0 );
406 XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 );
407
408 XMLTest( "Test InsertAfterChild on empty node. ", ( childNode1 == parent->LastChild() ), true );
409 }
Lee Thomasond6277762012-02-22 16:00:12 -0800410
411 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800412 // Entities not being written correctly.
413 // From Lynn Allen
Lee Thomasond6277762012-02-22 16:00:12 -0800414
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800415 const char* passages =
416 "<?xml version=\"1.0\" standalone=\"no\" ?>"
417 "<passages count=\"006\" formatversion=\"20020620\">"
418 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
419 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
420 "</passages>";
Lee Thomasond6277762012-02-22 16:00:12 -0800421
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800422 XMLDocument doc;
423 doc.Parse( passages );
424 XMLElement* psg = doc.RootElement()->FirstChildElement();
425 const char* context = psg->Attribute( "context" );
426 const char* expected = "Line 5 has \"quotation marks\" and 'apostrophe marks'. It also has <, >, and &, as well as a fake copyright \xC2\xA9.";
Lee Thomasond6277762012-02-22 16:00:12 -0800427
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800428 XMLTest( "Entity transformation: read. ", expected, context, true );
Lee Thomasond6277762012-02-22 16:00:12 -0800429
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800430#if defined(_MSC_VER)
Lee Thomason (grinliz)5ce4d972012-02-26 21:14:23 -0800431#pragma warning ( push )
432#pragma warning ( disable : 4996 ) // Fail to see a compelling reason why this should be deprecated.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800433#endif
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800434 FILE* textfile = fopen( "textfile.txt", "w" );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800435#if defined(_MSC_VER)
Lee Thomason (grinliz)5ce4d972012-02-26 21:14:23 -0800436#pragma warning ( pop )
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800437#endif
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800438 if ( textfile )
439 {
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800440 XMLPrinter streamer( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800441 psg->Accept( &streamer );
442 fclose( textfile );
443 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800444#if defined(_MSC_VER)
Lee Thomason (grinliz)5ce4d972012-02-26 21:14:23 -0800445#pragma warning ( push )
446#pragma warning ( disable : 4996 ) // Fail to see a compelling reason why this should be deprecated.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800447#endif
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800448 textfile = fopen( "textfile.txt", "r" );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800449#if defined(_MSC_VER)
Lee Thomason (grinliz)5ce4d972012-02-26 21:14:23 -0800450#pragma warning ( pop )
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800451#endif
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800452 TIXMLASSERT( textfile );
453 if ( textfile )
454 {
455 char buf[ 1024 ];
456 fgets( buf, 1024, textfile );
457 XMLTest( "Entity transformation: write. ",
458 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
459 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.\"/>\n",
460 buf, false );
461 }
462 fclose( textfile );
463 }
464
465 {
Lee Thomason6f381b72012-03-02 12:59:39 -0800466 // Suppress entities.
467 const char* passages =
468 "<?xml version=\"1.0\" standalone=\"no\" ?>"
469 "<passages count=\"006\" formatversion=\"20020620\">"
470 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
471 "</passages>";
472
473 XMLDocument doc( false );
474 doc.Parse( passages );
475
476 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ),
477 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;." );
478 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value(),
479 "Crazy &ttk;" );
480 doc.Print();
481 }
482
483 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800484 const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
485
486 XMLDocument doc;
487 doc.Parse( test );
488 XMLTest( "dot in names", doc.Error(), 0);
489 XMLTest( "dot in names", doc.FirstChildElement()->Name(), "a.elem" );
490 XMLTest( "dot in names", doc.FirstChildElement()->Attribute( "xmi.version" ), "2.0" );
491 }
492
493 {
494 const char* test = "<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>";
495
496 XMLDocument doc;
497 doc.Parse( test );
498
499 XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
500 XMLTest( "Entity with one digit.",
501 text->Value(), "1.1 Start easy ignore fin thickness\n",
502 false );
503 }
504
505 {
506 // DOCTYPE not preserved (950171)
507 //
508 const char* doctype =
509 "<?xml version=\"1.0\" ?>"
510 "<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
511 "<!ELEMENT title (#PCDATA)>"
512 "<!ELEMENT books (title,authors)>"
513 "<element />";
514
515 XMLDocument doc;
516 doc.Parse( doctype );
517 doc.SaveFile( "test7.xml" );
518 doc.DeleteChild( doc.RootElement() );
519 doc.LoadFile( "test7.xml" );
520 doc.Print();
521
522 const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown();
523 XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() );
524
525 }
526
527 {
528 // Comments do not stream out correctly.
529 const char* doctype =
530 "<!-- Somewhat<evil> -->";
531 XMLDocument doc;
532 doc.Parse( doctype );
533
534 XMLComment* comment = doc.FirstChild()->ToComment();
535
536 XMLTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
537 }
538 {
539 // Double attributes
540 const char* doctype = "<element attr='red' attr='blue' />";
541
542 XMLDocument doc;
543 doc.Parse( doctype );
544
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700545 XMLTest( "Parsing repeated attributes.", XML_ERROR_PARSING_ATTRIBUTE, doc.ErrorID() ); // is an error to tinyxml (didn't use to be, but caused issues)
Lee Thomason (grinliz)0a4df402012-02-27 20:50:52 -0800546 doc.PrintError();
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800547 }
548
549 {
550 // Embedded null in stream.
551 const char* doctype = "<element att\0r='red' attr='blue' />";
552
553 XMLDocument doc;
554 doc.Parse( doctype );
555 XMLTest( "Embedded null throws error.", true, doc.Error() );
556 }
557
558 {
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700559 // Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800560 const char* str = " ";
561 XMLDocument doc;
562 doc.Parse( str );
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700563 XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800564 }
565
566 {
567 // Low entities
568 XMLDocument doc;
569 doc.Parse( "<test>&#x0e;</test>" );
570 const char result[] = { 0x0e, 0 };
571 XMLTest( "Low entities.", doc.FirstChildElement()->GetText(), result );
572 doc.Print();
573 }
574
575 {
576 // Attribute values with trailing quotes not handled correctly
577 XMLDocument doc;
578 doc.Parse( "<foo attribute=bar\" />" );
579 XMLTest( "Throw error with bad end quotes.", doc.Error(), true );
580 }
581
582 {
583 // [ 1663758 ] Failure to report error on bad XML
584 XMLDocument xml;
585 xml.Parse("<x>");
586 XMLTest("Missing end tag at end of input", xml.Error(), true);
587 xml.Parse("<x> ");
588 XMLTest("Missing end tag with trailing whitespace", xml.Error(), true);
589 xml.Parse("<x></y>");
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700590 XMLTest("Mismatched tags", xml.ErrorID(), XML_ERROR_MISMATCHED_ELEMENT);
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800591 }
592
593
594 {
595 // [ 1475201 ] TinyXML parses entities in comments
596 XMLDocument xml;
597 xml.Parse("<!-- declarations for <head> & <body> -->"
598 "<!-- far &amp; away -->" );
599
600 XMLNode* e0 = xml.FirstChild();
601 XMLNode* e1 = e0->NextSibling();
602 XMLComment* c0 = e0->ToComment();
603 XMLComment* c1 = e1->ToComment();
604
605 XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
606 XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
607 }
608
609 {
610 XMLDocument xml;
611 xml.Parse( "<Parent>"
612 "<child1 att=''/>"
613 "<!-- With this comment, child2 will not be parsed! -->"
614 "<child2 att=''/>"
615 "</Parent>" );
616 xml.Print();
617
618 int count = 0;
619
620 for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
621 ele;
622 ele = ele->NextSibling() )
623 {
624 ++count;
625 }
626
627 XMLTest( "Comments iterate correctly.", 3, count );
628 }
629
630 {
631 // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
632 unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
633 buf[60] = 239;
634 buf[61] = 0;
635
636 XMLDocument doc;
637 doc.Parse( (const char*)buf);
638 }
639
640
641 {
642 // bug 1827248 Error while parsing a little bit malformed file
643 // Actually not malformed - should work.
644 XMLDocument xml;
645 xml.Parse( "<attributelist> </attributelist >" );
646 XMLTest( "Handle end tag whitespace", false, xml.Error() );
647 }
648
649 {
650 // This one must not result in an infinite loop
651 XMLDocument xml;
652 xml.Parse( "<infinite>loop" );
653 XMLTest( "Infinite loop test.", true, true );
654 }
655#endif
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800656 {
657 const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
658 XMLDocument doc;
659 doc.Parse( pub );
660
661 XMLDocument clone;
662 for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
663 XMLNode* copy = node->ShallowClone( &clone );
664 clone.InsertEndChild( copy );
665 }
666
667 clone.Print();
668
669 int count=0;
670 const XMLNode* a=clone.FirstChild();
671 const XMLNode* b=doc.FirstChild();
672 for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
673 ++count;
674 XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
675 }
676 XMLTest( "Clone and Equal", 4, count );
677 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800678
Lee Thomason6f381b72012-03-02 12:59:39 -0800679 // ----------- Performance tracking --------------
680 {
681#if defined( _MSC_VER )
682 __int64 start, end, freq;
683 QueryPerformanceFrequency( (LARGE_INTEGER*) &freq );
684#endif
685
686#if defined(_MSC_VER)
687#pragma warning ( push )
688#pragma warning ( disable : 4996 ) // Fail to see a compelling reason why this should be deprecated.
689#endif
690 FILE* fp = fopen( "dream.xml", "r" );
691#if defined(_MSC_VER)
692#pragma warning ( pop )
693#endif
694 fseek( fp, 0, SEEK_END );
695 long size = ftell( fp );
696 fseek( fp, 0, SEEK_SET );
697
698 char* mem = new char[size+1];
699 fread( mem, size, 1, fp );
700 fclose( fp );
701 mem[size] = 0;
702
703#if defined( _MSC_VER )
704 QueryPerformanceCounter( (LARGE_INTEGER*) &start );
705#else
706 clock_t cstart = clock();
707#endif
708 static const int COUNT = 10;
709 for( int i=0; i<COUNT; ++i ) {
710 XMLDocument doc;
711 doc.Parse( mem );
712 }
713#if defined( _MSC_VER )
714 QueryPerformanceCounter( (LARGE_INTEGER*) &end );
715#else
716 clock_t cend = clock();
717#endif
718
719 delete [] mem;
720
721 static const char* note =
722#ifdef DEBUG
723 "DEBUG";
724#else
725 "Release";
726#endif
727
728#if defined( _MSC_VER )
729 printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, 1000.0 * (double)(end-start) / ( (double)freq * (double)COUNT) );
730#else
731 printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, (double)(cend - cstart)/(double)COUNT );
732#endif
733 }
734
Lee Thomason (grinliz)7ca55582012-03-07 21:54:57 -0800735 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason1ff38e02012-02-14 18:18:16 -0800736 _CrtMemCheckpoint( &endMemState );
737 //_CrtMemDumpStatistics( &endMemState );
738
739 _CrtMemState diffMemState;
740 _CrtMemDifference( &diffMemState, &startMemState, &endMemState );
741 _CrtMemDumpStatistics( &diffMemState );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800742 //printf( "new total=%d\n", gNewTotal );
Lee Thomason1ff38e02012-02-14 18:18:16 -0800743 #endif
744
745 printf ("\nPass %d, Fail %d\n", gPass, gFail);
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800746 return 0;
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -0800747}