xref: /aosp_15_r20/external/tinyxml2/xmltest.cpp (revision 7485b22521f577cf944e5687361548d8993d8d2c)
1 #if defined( _MSC_VER )
2 	#if !defined( _CRT_SECURE_NO_WARNINGS )
3 		#define _CRT_SECURE_NO_WARNINGS		// This test file is not intended to be secure.
4 	#endif
5 #endif
6 
7 #include "tinyxml2.h"
8 #include <cerrno>
9 #include <cstdlib>
10 #include <cstring>
11 #include <ctime>
12 
13 #if defined( _MSC_VER ) || defined (WIN32)
14 	#include <crtdbg.h>
15 	#define WIN32_LEAN_AND_MEAN
16 	#include <windows.h>
17 	_CrtMemState startMemState;
18 	_CrtMemState endMemState;
19 #else
20 	#include <sys/stat.h>
21 	#include <sys/types.h>
22 #endif
23 
24 using namespace tinyxml2;
25 using namespace std;
26 int gPass = 0;
27 int gFail = 0;
28 
29 
XMLTest(const char * testString,const char * expected,const char * found,bool echo=true,bool extraNL=false)30 bool XMLTest (const char* testString, const char* expected, const char* found, bool echo=true, bool extraNL=false )
31 {
32 	bool pass;
33 	if ( !expected && !found )
34 		pass = true;
35 	else if ( !expected || !found )
36 		pass = false;
37 	else
38 		pass = !strcmp( expected, found );
39 	if ( pass )
40 		printf ("[pass]");
41 	else
42 		printf ("[fail]");
43 
44 	if ( !echo ) {
45 		printf (" %s\n", testString);
46 	}
47 	else {
48 		if ( extraNL ) {
49 			printf( " %s\n", testString );
50 			printf( "%s\n", expected );
51 			printf( "%s\n", found );
52 		}
53 		else {
54 			printf (" %s [%s][%s]\n", testString, expected, found);
55 		}
56 	}
57 
58 	if ( pass )
59 		++gPass;
60 	else
61 		++gFail;
62 	return pass;
63 }
64 
XMLTest(const char * testString,XMLError expected,XMLError found,bool echo=true,bool extraNL=false)65 bool XMLTest(const char* testString, XMLError expected, XMLError found, bool echo = true, bool extraNL = false)
66 {
67     return XMLTest(testString, XMLDocument::ErrorIDToName(expected), XMLDocument::ErrorIDToName(found), echo, extraNL);
68 }
69 
XMLTest(const char * testString,bool expected,bool found,bool echo=true,bool extraNL=false)70 bool XMLTest(const char* testString, bool expected, bool found, bool echo = true, bool extraNL = false)
71 {
72     return XMLTest(testString, expected ? "true" : "false", found ? "true" : "false", echo, extraNL);
73 }
74 
XMLTest(const char * testString,T expected,T found,bool echo=true)75 template< class T > bool XMLTest( const char* testString, T expected, T found, bool echo=true )
76 {
77 	bool pass = ( expected == found );
78 	if ( pass )
79 		printf ("[pass]");
80 	else
81 		printf ("[fail]");
82 
83 	if ( !echo )
84 		printf (" %s\n", testString);
85 	else {
86 		char expectedAsString[64];
87 		XMLUtil::ToStr(expected, expectedAsString, sizeof(expectedAsString));
88 
89 		char foundAsString[64];
90 		XMLUtil::ToStr(found, foundAsString, sizeof(foundAsString));
91 
92 		printf (" %s [%s][%s]\n", testString, expectedAsString, foundAsString );
93 	}
94 
95 	if ( pass )
96 		++gPass;
97 	else
98 		++gFail;
99 	return pass;
100 }
101 
102 
NullLineEndings(char * p)103 void NullLineEndings( char* p )
104 {
105 	while( p && *p ) {
106 		if ( *p == '\n' || *p == '\r' ) {
107 			*p = 0;
108 			return;
109 		}
110 		++p;
111 	}
112 }
113 
114 
example_1()115 int example_1()
116 {
117 	XMLDocument doc;
118 	doc.LoadFile( "resources/dream.xml" );
119 
120 	return doc.ErrorID();
121 }
122 /** @page Example_1 Load an XML File
123  *  @dontinclude ./xmltest.cpp
124  *  Basic XML file loading.
125  *  The basic syntax to load an XML file from
126  *  disk and check for an error. (ErrorID()
127  *  will return 0 for no error.)
128  *  @skip example_1()
129  *  @until }
130  */
131 
132 
example_2()133 int example_2()
134 {
135 	static const char* xml = "<element/>";
136 	XMLDocument doc;
137 	doc.Parse( xml );
138 
139 	return doc.ErrorID();
140 }
141 /** @page Example_2 Parse an XML from char buffer
142  *  @dontinclude ./xmltest.cpp
143  *  Basic XML string parsing.
144  *  The basic syntax to parse an XML for
145  *  a char* and check for an error. (ErrorID()
146  *  will return 0 for no error.)
147  *  @skip example_2()
148  *  @until }
149  */
150 
151 
example_3()152 int example_3()
153 {
154 	static const char* xml =
155 		"<?xml version=\"1.0\"?>"
156 		"<!DOCTYPE PLAY SYSTEM \"play.dtd\">"
157 		"<PLAY>"
158 		"<TITLE>A Midsummer Night's Dream</TITLE>"
159 		"</PLAY>";
160 
161 	XMLDocument doc;
162 	doc.Parse( xml );
163 
164 	XMLElement* titleElement = doc.FirstChildElement( "PLAY" )->FirstChildElement( "TITLE" );
165 	const char* title = titleElement->GetText();
166 	printf( "Name of play (1): %s\n", title );
167 
168 	XMLText* textNode = titleElement->FirstChild()->ToText();
169 	title = textNode->Value();
170 	printf( "Name of play (2): %s\n", title );
171 
172 	return doc.ErrorID();
173 }
174 /** @page Example_3 Get information out of XML
175 	@dontinclude ./xmltest.cpp
176 	In this example, we navigate a simple XML
177 	file, and read some interesting text. Note
178 	that this example doesn't use error
179 	checking; working code should check for null
180 	pointers when walking an XML tree, or use
181 	XMLHandle.
182 
183 	(The XML is an excerpt from "dream.xml").
184 
185 	@skip example_3()
186 	@until </PLAY>";
187 
188 	The structure of the XML file is:
189 
190 	<ul>
191 		<li>(declaration)</li>
192 		<li>(dtd stuff)</li>
193 		<li>Element "PLAY"</li>
194 		<ul>
195 			<li>Element "TITLE"</li>
196 			<ul>
197 			    <li>Text "A Midsummer Night's Dream"</li>
198 			</ul>
199 		</ul>
200 	</ul>
201 
202 	For this example, we want to print out the
203 	title of the play. The text of the title (what
204 	we want) is child of the "TITLE" element which
205 	is a child of the "PLAY" element.
206 
207 	We want to skip the declaration and dtd, so the
208 	method FirstChildElement() is a good choice. The
209 	FirstChildElement() of the Document is the "PLAY"
210 	Element, the FirstChildElement() of the "PLAY" Element
211 	is the "TITLE" Element.
212 
213 	@until ( "TITLE" );
214 
215 	We can then use the convenience function GetText()
216 	to get the title of the play.
217 
218 	@until title );
219 
220 	Text is just another Node in the XML DOM. And in
221 	fact you should be a little cautious with it, as
222 	text nodes can contain elements.
223 
224 	@verbatim
225 	Consider: A Midsummer Night's <b>Dream</b>
226 	@endverbatim
227 
228 	It is more correct to actually query the Text Node
229 	if in doubt:
230 
231 	@until title );
232 
233 	Noting that here we use FirstChild() since we are
234 	looking for XMLText, not an element, and ToText()
235 	is a cast from a Node to a XMLText.
236 */
237 
238 
example_4()239 bool example_4()
240 {
241 	static const char* xml =
242 		"<information>"
243 		"	<attributeApproach v='2' />"
244 		"	<textApproach>"
245 		"		<v>2</v>"
246 		"	</textApproach>"
247 		"</information>";
248 
249 	XMLDocument doc;
250 	doc.Parse( xml );
251 
252 	int v0 = 0;
253 	int v1 = 0;
254 
255 	XMLElement* attributeApproachElement = doc.FirstChildElement()->FirstChildElement( "attributeApproach" );
256 	attributeApproachElement->QueryIntAttribute( "v", &v0 );
257 
258 	XMLElement* textApproachElement = doc.FirstChildElement()->FirstChildElement( "textApproach" );
259 	textApproachElement->FirstChildElement( "v" )->QueryIntText( &v1 );
260 
261 	printf( "Both values are the same: %d and %d\n", v0, v1 );
262 
263 	return !doc.Error() && ( v0 == v1 );
264 }
265 /** @page Example_4 Read attributes and text information.
266 	@dontinclude ./xmltest.cpp
267 
268 	There are fundamentally 2 ways of writing a key-value
269 	pair into an XML file. (Something that's always annoyed
270 	me about XML.) Either by using attributes, or by writing
271 	the key name into an element and the value into
272 	the text node wrapped by the element. Both approaches
273 	are illustrated in this example, which shows two ways
274 	to encode the value "2" into the key "v":
275 
276 	@skip example_4()
277 	@until "</information>";
278 
279 	TinyXML-2 has accessors for both approaches.
280 
281 	When using an attribute, you navigate to the XMLElement
282 	with that attribute and use the QueryIntAttribute()
283 	group of methods. (Also QueryFloatAttribute(), etc.)
284 
285 	@skip XMLElement* attributeApproachElement
286 	@until &v0 );
287 
288 	When using the text approach, you need to navigate
289 	down one more step to the XMLElement that contains
290 	the text. Note the extra FirstChildElement( "v" )
291 	in the code below. The value of the text can then
292 	be safely queried with the QueryIntText() group
293 	of methods. (Also QueryFloatText(), etc.)
294 
295 	@skip XMLElement* textApproachElement
296 	@until &v1 );
297 */
298 
299 
main(int argc,const char ** argv)300 int main( int argc, const char ** argv )
301 {
302 	#if defined( _MSC_VER ) && defined( TINYXML2_DEBUG )
303 		_CrtMemCheckpoint( &startMemState );
304 		// Enable MS Visual C++ debug heap memory leaks dump on exit
305 		_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
306 		{
307 			int leaksOnStart = _CrtDumpMemoryLeaks();
308 			XMLTest( "No leaks on start?", FALSE, leaksOnStart );
309 		}
310 	#endif
311 
312 	{
313 		TIXMLASSERT( true );
314 	}
315 
316 	if ( argc > 1 ) {
317 		XMLDocument* doc = new XMLDocument();
318 		clock_t startTime = clock();
319 		doc->LoadFile( argv[1] );
320  		clock_t loadTime = clock();
321 		int errorID = doc->ErrorID();
322 		delete doc; doc = 0;
323  		clock_t deleteTime = clock();
324 
325 		printf( "Test file '%s' loaded. ErrorID=%d\n", argv[1], errorID );
326 		if ( !errorID ) {
327 			printf( "Load time=%u\n",   (unsigned)(loadTime - startTime) );
328 			printf( "Delete time=%u\n", (unsigned)(deleteTime - loadTime) );
329 			printf( "Total time=%u\n",  (unsigned)(deleteTime - startTime) );
330 		}
331 		exit(0);
332 	}
333 
334 	FILE* fp = fopen( "resources/dream.xml", "r" );
335 	if ( !fp ) {
336 		printf( "Error opening test file 'dream.xml'.\n"
337 				"Is your working directory the same as where \n"
338 				"the xmltest.cpp and dream.xml file are?\n\n"
339 	#if defined( _MSC_VER )
340 				"In windows Visual Studio you may need to set\n"
341 				"Properties->Debugging->Working Directory to '..'\n"
342 	#endif
343 			  );
344 		exit( 1 );
345 	}
346 	fclose( fp );
347 
348 	XMLTest( "Example_1", 0, example_1() );
349 	XMLTest( "Example_2", 0, example_2() );
350 	XMLTest( "Example_3", 0, example_3() );
351 	XMLTest( "Example_4", true, example_4() );
352 
353 	/* ------ Example 2: Lookup information. ---- */
354 
355 	{
356 		static const char* test[] = {	"<element />",
357 										"<element></element>",
358 										"<element><subelement/></element>",
359 										"<element><subelement></subelement></element>",
360 										"<element><subelement><subsub/></subelement></element>",
361 										"<!--comment beside elements--><element><subelement></subelement></element>",
362 										"<!--comment beside elements, this time with spaces-->  \n <element>  <subelement> \n </subelement> </element>",
363 										"<element attrib1='foo' attrib2=\"bar\" ></element>",
364 										"<element attrib1='foo' attrib2=\"bar\" ><subelement attrib3='yeehaa' /></element>",
365 										"<element>Text inside element.</element>",
366 										"<element><b></b></element>",
367 										"<element>Text inside and <b>bolded</b> in the element.</element>",
368 										"<outer><element>Text inside and <b>bolded</b> in the element.</element></outer>",
369 										"<element>This &amp; That.</element>",
370 										"<element attrib='This&lt;That' />",
371 										0
372 		};
373 		for( int i=0; test[i]; ++i ) {
374 			XMLDocument doc;
375 			doc.Parse( test[i] );
376 			XMLTest( "Element test", false, doc.Error() );
377 			doc.Print();
378 			printf( "----------------------------------------------\n" );
379 		}
380 	}
381 #if 1
382 	{
383 		static const char* test = "<!--hello world\n"
384 								  "          line 2\r"
385 								  "          line 3\r\n"
386 								  "          line 4\n\r"
387 								  "          line 5\r-->";
388 
389 		XMLDocument doc;
390 		doc.Parse( test );
391 		XMLTest( "Hello world declaration", false, doc.Error() );
392 		doc.Print();
393 	}
394 
395 	{
396 		// This test is pre-test for the next one
397 		// (where Element1 is inserted "after itself".
398 		// This code didn't use to crash.
399 		XMLDocument doc;
400 		XMLElement* element1 = doc.NewElement("Element1");
401 		XMLElement* element2 = doc.NewElement("Element2");
402 		doc.InsertEndChild(element1);
403 		doc.InsertEndChild(element2);
404 		doc.InsertAfterChild(element2, element2);
405 		doc.InsertAfterChild(element2, element2);
406 	}
407 
408 	{
409 		XMLDocument doc;
410 		XMLElement* element1 = doc.NewElement("Element1");
411 		XMLElement* element2 = doc.NewElement("Element2");
412 		doc.InsertEndChild(element1);
413 		doc.InsertEndChild(element2);
414 
415 		// This insertion "after itself"
416 		// used to cause invalid memory access and crash
417 		doc.InsertAfterChild(element1, element1);
418 		doc.InsertAfterChild(element1, element1);
419 		doc.InsertAfterChild(element2, element2);
420 		doc.InsertAfterChild(element2, element2);
421 	}
422 
423 	{
424 		static const char* test = "<element>Text before.</element>";
425 		XMLDocument doc;
426 		doc.Parse( test );
427 		XMLTest( "Element text before", false, doc.Error() );
428 		XMLElement* root = doc.FirstChildElement();
429 		XMLElement* newElement = doc.NewElement( "Subelement" );
430 		root->InsertEndChild( newElement );
431 		doc.Print();
432 	}
433 	{
434 		XMLDocument* doc = new XMLDocument();
435 		static const char* test = "<element><sub/></element>";
436 		doc->Parse( test );
437 		XMLTest( "Element with sub element", false, doc->Error() );
438 		delete doc;
439 	}
440 	{
441 		// Test: Programmatic DOM nodes insertion return values
442 		XMLDocument doc;
443 
444 		XMLNode* first = doc.NewElement( "firstElement" );
445 		XMLTest( "New element", true, first != 0 );
446 		XMLNode* firstAfterInsertion = doc.InsertFirstChild( first );
447 		XMLTest( "New element inserted first", true, firstAfterInsertion == first );
448 
449 		XMLNode* last = doc.NewElement( "lastElement" );
450 		XMLTest( "New element", true, last != 0 );
451 		XMLNode* lastAfterInsertion = doc.InsertEndChild( last );
452 		XMLTest( "New element inserted last", true, lastAfterInsertion == last );
453 
454 		XMLNode* middle = doc.NewElement( "middleElement" );
455 		XMLTest( "New element", true, middle != 0 );
456 		XMLNode* middleAfterInsertion = doc.InsertAfterChild( first, middle );
457 		XMLTest( "New element inserted middle", true, middleAfterInsertion == middle );
458 	}
459 	{
460 		// Test: Programmatic DOM
461 		// Build:
462 		//		<element>
463 		//			<!--comment-->
464 		//			<sub attrib="0" />
465 		//			<sub attrib="1" />
466 		//			<sub attrib="2" >& Text!</sub>
467 		//		<element>
468 
469 		XMLDocument* doc = new XMLDocument();
470 		XMLNode* element = doc->InsertEndChild( doc->NewElement( "element" ) );
471 
472 		XMLElement* sub[3] = { doc->NewElement( "sub" ), doc->NewElement( "sub" ), doc->NewElement( "sub" ) };
473 		for( int i=0; i<3; ++i ) {
474 			sub[i]->SetAttribute( "attrib", i );
475 		}
476 		element->InsertEndChild( sub[2] );
477 
478 		const int dummyInitialValue = 1000;
479 		int dummyValue = dummyInitialValue;
480 
481 		XMLNode* comment = element->InsertFirstChild( doc->NewComment( "comment" ) );
482 		comment->SetUserData(&dummyValue);
483 		element->InsertAfterChild( comment, sub[0] );
484 		element->InsertAfterChild( sub[0], sub[1] );
485 		sub[2]->InsertFirstChild( doc->NewText( "& Text!" ));
486 		doc->Print();
487 		XMLTest( "Programmatic DOM", "comment", doc->FirstChildElement( "element" )->FirstChild()->Value() );
488 		XMLTest( "Programmatic DOM", "0", doc->FirstChildElement( "element" )->FirstChildElement()->Attribute( "attrib" ) );
489 		XMLTest( "Programmatic DOM", 2, doc->FirstChildElement()->LastChildElement( "sub" )->IntAttribute( "attrib" ) );
490 		XMLTest( "Programmatic DOM", "& Text!",
491 				 doc->FirstChildElement()->LastChildElement( "sub" )->FirstChild()->ToText()->Value() );
492 		XMLTest("User data - pointer", true, &dummyValue == comment->GetUserData(), false);
493 		XMLTest("User data - value behind pointer", dummyInitialValue, dummyValue, false);
494 
495 		// And now deletion:
496 		element->DeleteChild( sub[2] );
497 		doc->DeleteNode( comment );
498 
499 		element->FirstChildElement()->SetAttribute( "attrib", true );
500 		element->LastChildElement()->DeleteAttribute( "attrib" );
501 
502 		XMLTest( "Programmatic DOM", true, doc->FirstChildElement()->FirstChildElement()->BoolAttribute( "attrib" ) );
503 		const int defaultIntValue = 10;
504 		const int replacementIntValue = 20;
505 		int value1 = defaultIntValue;
506 		int value2 = doc->FirstChildElement()->LastChildElement()->IntAttribute( "attrib", replacementIntValue );
507 		XMLError result = doc->FirstChildElement()->LastChildElement()->QueryIntAttribute( "attrib", &value1 );
508 		XMLTest( "Programmatic DOM", XML_NO_ATTRIBUTE, result );
509 		XMLTest( "Programmatic DOM", defaultIntValue, value1 );
510 		XMLTest( "Programmatic DOM", replacementIntValue, value2 );
511 
512 		doc->Print();
513 
514 		{
515 			XMLPrinter streamer;
516 			doc->Print( &streamer );
517 			printf( "%s", streamer.CStr() );
518 		}
519 		{
520 			XMLPrinter streamer( 0, true );
521 			doc->Print( &streamer );
522 			XMLTest( "Compact mode", "<element><sub attrib=\"true\"/><sub/></element>", streamer.CStr(), false );
523 		}
524 		doc->SaveFile( "./resources/out/pretty.xml" );
525 		XMLTest( "Save pretty.xml", false, doc->Error() );
526 		doc->SaveFile( "./resources/out/compact.xml", true );
527 		XMLTest( "Save compact.xml", false, doc->Error() );
528 		delete doc;
529 	}
530 	{
531 		// Test: Dream
532 		// XML1 : 1,187,569 bytes	in 31,209 allocations
533 		// XML2 :   469,073	bytes	in    323 allocations
534 		//int newStart = gNew;
535 		XMLDocument doc;
536 		doc.LoadFile( "resources/dream.xml" );
537 		XMLTest( "Load dream.xml", false, doc.Error() );
538 
539 		doc.SaveFile( "resources/out/dreamout.xml" );
540 		XMLTest( "Save dreamout.xml", false, doc.Error() );
541 		doc.PrintError();
542 
543 		XMLTest( "Dream", "xml version=\"1.0\"",
544 						  doc.FirstChild()->ToDeclaration()->Value() );
545 		XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() != 0 );
546 		XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
547 						  doc.FirstChild()->NextSibling()->ToUnknown()->Value() );
548 		XMLTest( "Dream", "And Robin shall restore amends.",
549 						  doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
550 		XMLTest( "Dream", "And Robin shall restore amends.",
551 						  doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
552 
553 		XMLDocument doc2;
554 		doc2.LoadFile( "resources/out/dreamout.xml" );
555 		XMLTest( "Load dreamout.xml", false, doc2.Error() );
556 		XMLTest( "Dream-out", "xml version=\"1.0\"",
557 						  doc2.FirstChild()->ToDeclaration()->Value() );
558 		XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() != 0 );
559 		XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
560 						  doc2.FirstChild()->NextSibling()->ToUnknown()->Value() );
561 		XMLTest( "Dream-out", "And Robin shall restore amends.",
562 						  doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
563 
564 		//gNewTotal = gNew - newStart;
565 	}
566 
567 
568 	{
569 		const char* error =	"<?xml version=\"1.0\" standalone=\"no\" ?>\n"
570 							"<passages count=\"006\" formatversion=\"20020620\">\n"
571 							"    <wrong error>\n"
572 							"</passages>";
573 
574 		XMLDocument doc;
575 		doc.Parse( error );
576 		XMLTest( "Bad XML", XML_ERROR_PARSING_ATTRIBUTE, doc.ErrorID() );
577 		const char* errorStr = doc.ErrorStr();
578 		XMLTest("Formatted error string",
579 			"Error=XML_ERROR_PARSING_ATTRIBUTE ErrorID=7 (0x7) Line number=3: XMLElement name=wrong",
580 			errorStr);
581 	}
582 
583 	{
584 		const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
585 
586 		XMLDocument doc;
587 		doc.Parse( str );
588 		XMLTest( "Top level attributes", false, doc.Error() );
589 
590 		XMLElement* ele = doc.FirstChildElement();
591 
592 		int iVal;
593 		XMLError result;
594 		double dVal;
595 
596 		result = ele->QueryDoubleAttribute( "attr0", &dVal );
597 		XMLTest( "Query attribute: int as double", XML_SUCCESS, result);
598 		XMLTest( "Query attribute: int as double", 1, (int)dVal );
599 		XMLTest( "Query attribute: int as double", 1, (int)ele->DoubleAttribute("attr0"));
600 
601 		result = ele->QueryDoubleAttribute( "attr1", &dVal );
602 		XMLTest( "Query attribute: double as double", XML_SUCCESS, result);
603 		XMLTest( "Query attribute: double as double", 2.0, dVal );
604 		XMLTest( "Query attribute: double as double", 2.0, ele->DoubleAttribute("attr1") );
605 
606 		result = ele->QueryIntAttribute( "attr1", &iVal );
607 		XMLTest( "Query attribute: double as int", XML_SUCCESS, result);
608 		XMLTest( "Query attribute: double as int", 2, iVal );
609 
610 		result = ele->QueryIntAttribute( "attr2", &iVal );
611 		XMLTest( "Query attribute: not a number", XML_WRONG_ATTRIBUTE_TYPE, result );
612 		XMLTest( "Query attribute: not a number", 4.0, ele->DoubleAttribute("attr2", 4.0) );
613 
614 		result = ele->QueryIntAttribute( "bar", &iVal );
615 		XMLTest( "Query attribute: does not exist", XML_NO_ATTRIBUTE, result );
616 		XMLTest( "Query attribute: does not exist", true, ele->BoolAttribute("bar", true) );
617 	}
618 
619 	{
620 		const char* str = "<doc/>";
621 
622 		XMLDocument doc;
623 		doc.Parse( str );
624 		XMLTest( "Empty top element", false, doc.Error() );
625 
626 		XMLElement* ele = doc.FirstChildElement();
627 
628 		int iVal, iVal2;
629 		double dVal, dVal2;
630 
631 		ele->SetAttribute( "str", "strValue" );
632 		ele->SetAttribute( "int", 1 );
633 		ele->SetAttribute( "double", -1.0 );
634 
635 		const char* answer = 0;
636 		ele->QueryAttribute("str", &answer);
637 		XMLTest("Query char attribute", "strValue", answer);
638 
639 		const char* cStr = ele->Attribute( "str" );
640 		{
641 			XMLError queryResult = ele->QueryIntAttribute( "int", &iVal );
642 			XMLTest( "Query int attribute", XML_SUCCESS, queryResult);
643 		}
644 		{
645 			XMLError queryResult = ele->QueryDoubleAttribute( "double", &dVal );
646 			XMLTest( "Query double attribute", XML_SUCCESS, queryResult);
647 		}
648 
649 		{
650 			XMLError queryResult = ele->QueryAttribute( "int", &iVal2 );
651 			XMLTest( "Query int attribute generic", (int)XML_SUCCESS, queryResult);
652 		}
653 		{
654 			XMLError queryResult = ele->QueryAttribute( "double", &dVal2 );
655 			XMLTest( "Query double attribute generic", (int)XML_SUCCESS, queryResult);
656 		}
657 
658 		XMLTest( "Attribute match test", "strValue", ele->Attribute( "str", "strValue" ) );
659 		XMLTest( "Attribute round trip. c-string.", "strValue", cStr );
660 		XMLTest( "Attribute round trip. int.", 1, iVal );
661 		XMLTest( "Attribute round trip. double.", -1, (int)dVal );
662 		XMLTest( "Alternate query", true, iVal == iVal2 );
663 		XMLTest( "Alternate query", true, dVal == dVal2 );
664 		XMLTest( "Alternate query", true, iVal == ele->IntAttribute("int") );
665 		XMLTest( "Alternate query", true, dVal == ele->DoubleAttribute("double") );
666 	}
667 
668 	{
669 		XMLDocument doc;
670 		doc.LoadFile( "resources/utf8test.xml" );
671 		XMLTest( "Load utf8test.xml", false, doc.Error() );
672 
673 		// Get the attribute "value" from the "Russian" element and check it.
674 		XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" );
675 		const unsigned char correctValue[] = {	0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
676 												0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
677 
678 		XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) );
679 
680 		const unsigned char russianElementName[] = {	0xd0U, 0xa0U, 0xd1U, 0x83U,
681 														0xd1U, 0x81U, 0xd1U, 0x81U,
682 														0xd0U, 0xbaU, 0xd0U, 0xb8U,
683 														0xd0U, 0xb9U, 0 };
684 		const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
685 
686 		XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText();
687 		XMLTest( "UTF-8: Browsing russian element name.",
688 				 russianText,
689 				 text->Value() );
690 
691 		// Now try for a round trip.
692 		doc.SaveFile( "resources/out/utf8testout.xml" );
693 		XMLTest( "UTF-8: Save testout.xml", false, doc.Error() );
694 
695 		// Check the round trip.
696 		bool roundTripOkay = false;
697 
698 		FILE* saved  = fopen( "resources/out/utf8testout.xml", "r" );
699 		XMLTest( "UTF-8: Open utf8testout.xml", true, saved != 0 );
700 
701 		FILE* verify = fopen( "resources/utf8testverify.xml", "r" );
702 		XMLTest( "UTF-8: Open utf8testverify.xml", true, verify != 0 );
703 
704 		if ( saved && verify )
705 		{
706 			roundTripOkay = true;
707 			char verifyBuf[256];
708 			while ( fgets( verifyBuf, 256, verify ) )
709 			{
710 				char savedBuf[256];
711 				fgets( savedBuf, 256, saved );
712 				NullLineEndings( verifyBuf );
713 				NullLineEndings( savedBuf );
714 
715 				if ( strcmp( verifyBuf, savedBuf ) )
716 				{
717 					printf( "verify:%s<\n", verifyBuf );
718 					printf( "saved :%s<\n", savedBuf );
719 					roundTripOkay = false;
720 					break;
721 				}
722 			}
723 		}
724 		if ( saved )
725 			fclose( saved );
726 		if ( verify )
727 			fclose( verify );
728 		XMLTest( "UTF-8: Verified multi-language round trip.", true, roundTripOkay );
729 	}
730 
731 	// --------GetText()-----------
732 	{
733 		const char* str = "<foo>This is  text</foo>";
734 		XMLDocument doc;
735 		doc.Parse( str );
736 		XMLTest( "Double whitespace", false, doc.Error() );
737 		const XMLElement* element = doc.RootElement();
738 
739 		XMLTest( "GetText() normal use.", "This is  text", element->GetText() );
740 
741 		str = "<foo><b>This is text</b></foo>";
742 		doc.Parse( str );
743 		XMLTest( "Bold text simulation", false, doc.Error() );
744 		element = doc.RootElement();
745 
746 		XMLTest( "GetText() contained element.", element->GetText() == 0, true );
747 	}
748 
749 
750 	// --------SetText()-----------
751 	{
752 		const char* str = "<foo></foo>";
753 		XMLDocument doc;
754 		doc.Parse( str );
755 		XMLTest( "Empty closed element", false, doc.Error() );
756 		XMLElement* element = doc.RootElement();
757 
758 		element->SetText("darkness.");
759 		XMLTest( "SetText() normal use (open/close).", "darkness.", element->GetText() );
760 
761 		element->SetText("blue flame.");
762 		XMLTest( "SetText() replace.", "blue flame.", element->GetText() );
763 
764 		str = "<foo/>";
765 		doc.Parse( str );
766 		XMLTest( "Empty self-closed element", false, doc.Error() );
767 		element = doc.RootElement();
768 
769 		element->SetText("The driver");
770 		XMLTest( "SetText() normal use. (self-closing)", "The driver", element->GetText() );
771 
772 		element->SetText("<b>horses</b>");
773 		XMLTest( "SetText() replace with tag-like text.", "<b>horses</b>", element->GetText() );
774 		//doc.Print();
775 
776 		str = "<foo><bar>Text in nested element</bar></foo>";
777 		doc.Parse( str );
778 		XMLTest( "Text in nested element", false, doc.Error() );
779 		element = doc.RootElement();
780 
781 		element->SetText("wolves");
782 		XMLTest( "SetText() prefix to nested non-text children.", "wolves", element->GetText() );
783 
784 		str = "<foo/>";
785 		doc.Parse( str );
786 		XMLTest( "Empty self-closed element round 2", false, doc.Error() );
787 		element = doc.RootElement();
788 
789 		element->SetText( "str" );
790 		XMLTest( "SetText types", "str", element->GetText() );
791 
792 		element->SetText( 1 );
793 		XMLTest( "SetText types", "1", element->GetText() );
794 
795 		element->SetText( 1U );
796 		XMLTest( "SetText types", "1", element->GetText() );
797 
798 		element->SetText( true );
799 		XMLTest( "SetText types", "true", element->GetText() );
800 
801 		element->SetText( 1.5f );
802 		XMLTest( "SetText types", "1.5", element->GetText() );
803 
804 		element->SetText( 1.5 );
805 		XMLTest( "SetText types", "1.5", element->GetText() );
806 	}
807 
808 	// ---------- Attributes ---------
809 	{
810 		static const int64_t BIG = -123456789012345678;
811         static const uint64_t BIG_POS = 123456789012345678;
812 		XMLDocument doc;
813 		XMLElement* element = doc.NewElement("element");
814 		doc.InsertFirstChild(element);
815 
816 		{
817 			element->SetAttribute("attrib", int(-100));
818 			{
819 				int v = 0;
820 				XMLError queryResult = element->QueryIntAttribute("attrib", &v);
821 				XMLTest("Attribute: int", XML_SUCCESS, queryResult, true);
822 				XMLTest("Attribute: int", -100, v, true);
823 			}
824 			{
825 				int v = 0;
826 				XMLError queryResult = element->QueryAttribute("attrib", &v);
827 				XMLTest("Attribute: int", (int)XML_SUCCESS, queryResult, true);
828 				XMLTest("Attribute: int", -100, v, true);
829 			}
830 			XMLTest("Attribute: int", -100, element->IntAttribute("attrib"), true);
831 		}
832 		{
833 			element->SetAttribute("attrib", unsigned(100));
834 			{
835 				unsigned v = 0;
836 				XMLError queryResult = element->QueryUnsignedAttribute("attrib", &v);
837 				XMLTest("Attribute: unsigned", XML_SUCCESS, queryResult, true);
838 				XMLTest("Attribute: unsigned", unsigned(100), v, true);
839 			}
840 			{
841 				unsigned v = 0;
842 				XMLError queryResult = element->QueryAttribute("attrib", &v);
843 				XMLTest("Attribute: unsigned", (int)XML_SUCCESS, queryResult, true);
844 				XMLTest("Attribute: unsigned", unsigned(100), v, true);
845 			}
846 			{
847 				const char* v = "failed";
848 				XMLError queryResult = element->QueryStringAttribute("not-attrib", &v);
849 				XMLTest("Attribute: string default", false, queryResult == XML_SUCCESS);
850 				queryResult = element->QueryStringAttribute("attrib", &v);
851 				XMLTest("Attribute: string", XML_SUCCESS, queryResult, true);
852 				XMLTest("Attribute: string", "100", v);
853 			}
854 			XMLTest("Attribute: unsigned", unsigned(100), element->UnsignedAttribute("attrib"), true);
855 		}
856 		{
857 			element->SetAttribute("attrib", BIG);
858 			{
859 				int64_t v = 0;
860 				XMLError queryResult = element->QueryInt64Attribute("attrib", &v);
861 				XMLTest("Attribute: int64_t", XML_SUCCESS, queryResult, true);
862 				XMLTest("Attribute: int64_t", BIG, v, true);
863 			}
864 			{
865 				int64_t v = 0;
866 				XMLError queryResult = element->QueryAttribute("attrib", &v);
867 				XMLTest("Attribute: int64_t", (int)XML_SUCCESS, queryResult, true);
868 				XMLTest("Attribute: int64_t", BIG, v, true);
869 			}
870 			XMLTest("Attribute: int64_t", BIG, element->Int64Attribute("attrib"), true);
871 		}
872         {
873             element->SetAttribute("attrib", BIG_POS);
874             {
875                 uint64_t v = 0;
876                 XMLError queryResult = element->QueryUnsigned64Attribute("attrib", &v);
877                 XMLTest("Attribute: uint64_t", XML_SUCCESS, queryResult, true);
878                 XMLTest("Attribute: uint64_t", BIG_POS, v, true);
879             }
880             {
881                 uint64_t v = 0;
882 				XMLError queryResult = element->QueryAttribute("attrib", &v);
883                 XMLTest("Attribute: uint64_t", (int)XML_SUCCESS, queryResult, true);
884                 XMLTest("Attribute: uint64_t", BIG_POS, v, true);
885             }
886             XMLTest("Attribute: uint64_t", BIG_POS, element->Unsigned64Attribute("attrib"), true);
887         }
888         {
889 			element->SetAttribute("attrib", true);
890 			{
891 				bool v = false;
892 				XMLError queryResult = element->QueryBoolAttribute("attrib", &v);
893 				XMLTest("Attribute: bool", XML_SUCCESS, queryResult, true);
894 				XMLTest("Attribute: bool", true, v, true);
895 			}
896 			{
897 				bool v = false;
898 				XMLError queryResult = element->QueryAttribute("attrib", &v);
899 				XMLTest("Attribute: bool", (int)XML_SUCCESS, queryResult, true);
900 				XMLTest("Attribute: bool", true, v, true);
901 			}
902 			XMLTest("Attribute: bool", true, element->BoolAttribute("attrib"), true);
903 		}
904 		{
905 			element->SetAttribute("attrib", true);
906 			const char* result = element->Attribute("attrib");
907 			XMLTest("Bool true is 'true'", "true", result);
908 
909 			XMLUtil::SetBoolSerialization("1", "0");
910 			element->SetAttribute("attrib", true);
911 			result = element->Attribute("attrib");
912 			XMLTest("Bool true is '1'", "1", result);
913 
914 			XMLUtil::SetBoolSerialization(0, 0);
915 		}
916 		{
917 			element->SetAttribute("attrib", 100.0);
918 			{
919 				double v = 0;
920 				XMLError queryResult = element->QueryDoubleAttribute("attrib", &v);
921 				XMLTest("Attribute: double", XML_SUCCESS, queryResult, true);
922 				XMLTest("Attribute: double", 100.0, v, true);
923 			}
924 			{
925 				double v = 0;
926 				XMLError queryResult = element->QueryAttribute("attrib", &v);
927 				XMLTest("Attribute: bool", (int)XML_SUCCESS, queryResult, true);
928 				XMLTest("Attribute: double", 100.0, v, true);
929 			}
930 			XMLTest("Attribute: double", 100.0, element->DoubleAttribute("attrib"), true);
931 		}
932 		{
933 			element->SetAttribute("attrib", 100.0f);
934 			{
935 				float v = 0;
936 				XMLError queryResult = element->QueryFloatAttribute("attrib", &v);
937 				XMLTest("Attribute: float", XML_SUCCESS, queryResult, true);
938 				XMLTest("Attribute: float", 100.0f, v, true);
939 			}
940 			{
941 				float v = 0;
942 				XMLError queryResult = element->QueryAttribute("attrib", &v);
943 				XMLTest("Attribute: float", (int)XML_SUCCESS, queryResult, true);
944 				XMLTest("Attribute: float", 100.0f, v, true);
945 			}
946 			XMLTest("Attribute: float", 100.0f, element->FloatAttribute("attrib"), true);
947 		}
948 		{
949 			element->SetText(BIG);
950 			int64_t v = 0;
951 			XMLError queryResult = element->QueryInt64Text(&v);
952 			XMLTest("Element: int64_t", XML_SUCCESS, queryResult, true);
953 			XMLTest("Element: int64_t", BIG, v, true);
954 		}
955         {
956             element->SetText(BIG_POS);
957             uint64_t v = 0;
958             XMLError queryResult = element->QueryUnsigned64Text(&v);
959             XMLTest("Element: uint64_t", XML_SUCCESS, queryResult, true);
960             XMLTest("Element: uint64_t", BIG_POS, v, true);
961         }
962     }
963 
964 	// ---------- XMLPrinter stream mode ------
965 	{
966 		{
967 			FILE* printerfp = fopen("resources/out/printer.xml", "w");
968 			XMLTest("Open printer.xml", true, printerfp != 0);
969 			XMLPrinter printer(printerfp);
970 			printer.OpenElement("foo");
971 			printer.PushAttribute("attrib-text", "text");
972 			printer.PushAttribute("attrib-int", int(1));
973 			printer.PushAttribute("attrib-unsigned", unsigned(2));
974 			printer.PushAttribute("attrib-int64", int64_t(3));
975 			printer.PushAttribute("attrib-uint64", uint64_t(37));
976 			printer.PushAttribute("attrib-bool", true);
977 			printer.PushAttribute("attrib-double", 4.0);
978 			printer.CloseElement();
979 			fclose(printerfp);
980 		}
981 		{
982 			XMLDocument doc;
983 			doc.LoadFile("resources/out/printer.xml");
984 			XMLTest("XMLPrinter Stream mode: load", XML_SUCCESS, doc.ErrorID(), true);
985 
986 			const XMLDocument& cdoc = doc;
987 
988 			const XMLAttribute* attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-text");
989 			XMLTest("attrib-text", "text", attrib->Value(), true);
990 			attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int");
991 			XMLTest("attrib-int", int(1), attrib->IntValue(), true);
992 			attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-unsigned");
993 			XMLTest("attrib-unsigned", unsigned(2), attrib->UnsignedValue(), true);
994 			attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int64");
995 			XMLTest("attrib-int64", int64_t(3), attrib->Int64Value(), true);
996 			attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-uint64");
997 			XMLTest("attrib-uint64", uint64_t(37), attrib->Unsigned64Value(), true);
998 			attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-bool");
999 			XMLTest("attrib-bool", true, attrib->BoolValue(), true);
1000 			attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-double");
1001 			XMLTest("attrib-double", 4.0, attrib->DoubleValue(), true);
1002 		}
1003 		// Add API_testcatse :PushDeclaration();PushText();PushComment()
1004 		{
1005 			FILE* fp1 = fopen("resources/out/printer_1.xml", "w");
1006 			XMLPrinter printer(fp1);
1007 
1008 			printer.PushDeclaration("version = '1.0' enconding = 'utf-8'");
1009 
1010 			printer.OpenElement("foo");
1011 			printer.PushAttribute("attrib-text", "text");
1012 
1013 			printer.OpenElement("text");
1014 			printer.PushText("Tinyxml2");
1015 			printer.CloseElement();
1016 
1017 			printer.OpenElement("int");
1018 			printer.PushText(int(11));
1019 			printer.CloseElement();
1020 
1021 			printer.OpenElement("unsigned");
1022 			printer.PushText(unsigned(12));
1023 			printer.CloseElement();
1024 
1025 			printer.OpenElement("int64_t");
1026 			printer.PushText(int64_t(13));
1027 			printer.CloseElement();
1028 
1029 			printer.OpenElement("uint64_t");
1030 			printer.PushText(uint64_t(14));
1031 			printer.CloseElement();
1032 
1033 			printer.OpenElement("bool");
1034 			printer.PushText(true);
1035 			printer.CloseElement();
1036 
1037 			printer.OpenElement("float");
1038 			printer.PushText("1.56");
1039 			printer.CloseElement();
1040 
1041 			printer.OpenElement("double");
1042 			printer.PushText("12.12");
1043 			printer.CloseElement();
1044 
1045 			printer.OpenElement("comment");
1046 			printer.PushComment("this is Tinyxml2");
1047 			printer.CloseElement();
1048 
1049 			printer.CloseElement();
1050 			fclose(fp1);
1051 		}
1052 		{
1053 			XMLDocument doc;
1054 			doc.LoadFile("resources/out/printer_1.xml");
1055 			XMLTest("XMLPrinter Stream mode: load", XML_SUCCESS, doc.ErrorID(), true);
1056 
1057 			const XMLDocument& cdoc = doc;
1058 
1059 			const  XMLElement* root = cdoc.FirstChildElement("foo");
1060 
1061 			const char* text_value;
1062 			text_value = root->FirstChildElement("text")->GetText();
1063 			XMLTest("PushText( const char* text, bool cdata=false ) test", "Tinyxml2", text_value);
1064 
1065 			int  int_value;
1066 			int_value = root->FirstChildElement("int")->IntText();
1067 			XMLTest("PushText( int value ) test", 11, int_value);
1068 
1069 			unsigned  unsigned_value;
1070 			unsigned_value = root->FirstChildElement("unsigned")->UnsignedText();
1071 			XMLTest("PushText( unsigned value ) test", (unsigned)12, unsigned_value);
1072 
1073 			int64_t  int64_t_value;
1074 			int64_t_value = root->FirstChildElement("int64_t")->Int64Text();
1075 			XMLTest("PushText( int64_t value ) test", (int64_t) 13, int64_t_value);
1076 
1077 			uint64_t uint64_t_value;
1078 			uint64_t_value = root->FirstChildElement("uint64_t")->Unsigned64Text();
1079 			XMLTest("PushText( uint64_t value ) test", (uint64_t) 14, uint64_t_value);
1080 
1081 			float  float_value;
1082 			float_value = root->FirstChildElement("float")->FloatText();
1083 			XMLTest("PushText( float value ) test", 1.56f, float_value);
1084 
1085 			double double_value;
1086 			double_value = root->FirstChildElement("double")->DoubleText();
1087 			XMLTest("PushText( double value ) test", 12.12, double_value);
1088 
1089 			bool bool_value;
1090 			bool_value = root->FirstChildElement("bool")->BoolText();
1091 			XMLTest("PushText( bool value ) test", true, bool_value);
1092 
1093 			const XMLComment* comment = root->FirstChildElement("comment")->FirstChild()->ToComment();
1094 			const char* comment_value = comment->Value();
1095 			XMLTest("PushComment() test", "this is Tinyxml2", comment_value);
1096 
1097 			const XMLDeclaration* declaration = cdoc.FirstChild()->ToDeclaration();
1098 			const char* declaration_value = declaration->Value();
1099 			XMLTest("PushDeclaration() test", "version = '1.0' enconding = 'utf-8'", declaration_value);
1100 		}
1101 	}
1102 
1103 
1104 	// ---------- CDATA ---------------
1105 	{
1106 		const char* str =	"<xmlElement>"
1107 								"<![CDATA["
1108 									"I am > the rules!\n"
1109 									"...since I make symbolic puns"
1110 								"]]>"
1111 							"</xmlElement>";
1112 		XMLDocument doc;
1113 		doc.Parse( str );
1114 		XMLTest( "CDATA symbolic puns round 1", false, doc.Error() );
1115 		doc.Print();
1116 
1117 		XMLTest( "CDATA parse.", "I am > the rules!\n...since I make symbolic puns",
1118 								 doc.FirstChildElement()->FirstChild()->Value(),
1119 								 false );
1120 	}
1121 
1122 	// ----------- CDATA -------------
1123 	{
1124 		const char* str =	"<xmlElement>"
1125 								"<![CDATA["
1126 									"<b>I am > the rules!</b>\n"
1127 									"...since I make symbolic puns"
1128 								"]]>"
1129 							"</xmlElement>";
1130 		XMLDocument doc;
1131 		doc.Parse( str );
1132 		XMLTest( "CDATA symbolic puns round 2", false, doc.Error() );
1133 		doc.Print();
1134 
1135 		XMLTest( "CDATA parse. [ tixml1:1480107 ]",
1136 								 "<b>I am > the rules!</b>\n...since I make symbolic puns",
1137 								 doc.FirstChildElement()->FirstChild()->Value(),
1138 								 false );
1139 	}
1140 
1141 	// InsertAfterChild causes crash.
1142 	{
1143 		// InsertBeforeChild and InsertAfterChild causes crash.
1144 		XMLDocument doc;
1145 		XMLElement* parent = doc.NewElement( "Parent" );
1146 		doc.InsertFirstChild( parent );
1147 
1148 		XMLElement* childText0 = doc.NewElement( "childText0" );
1149 		XMLElement* childText1 = doc.NewElement( "childText1" );
1150 
1151 		XMLNode* childNode0 = parent->InsertEndChild( childText0 );
1152 		XMLTest( "InsertEndChild() return", true, childNode0 == childText0 );
1153 		XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 );
1154 		XMLTest( "InsertAfterChild() return", true, childNode1 == childText1 );
1155 
1156 		XMLTest( "Test InsertAfterChild on empty node. ", true, ( childNode1 == parent->LastChild() ) );
1157 	}
1158 
1159 	{
1160 		// Entities not being written correctly.
1161 		// From Lynn Allen
1162 
1163 		const char* passages =
1164 			"<?xml version=\"1.0\" standalone=\"no\" ?>"
1165 			"<passages count=\"006\" formatversion=\"20020620\">"
1166 				"<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
1167 				" It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
1168 			"</passages>";
1169 
1170 		XMLDocument doc;
1171 		doc.Parse( passages );
1172 		XMLTest( "Entity transformation parse round 1", false, doc.Error() );
1173 		XMLElement* psg = doc.RootElement()->FirstChildElement();
1174 		const char* context = psg->Attribute( "context" );
1175 		const char* expected = "Line 5 has \"quotation marks\" and 'apostrophe marks'. It also has <, >, and &, as well as a fake copyright \xC2\xA9.";
1176 
1177 		XMLTest( "Entity transformation: read. ", expected, context, true );
1178 
1179 		const char* textFilePath = "resources/out/textfile.txt";
1180 		FILE* textfile = fopen( textFilePath, "w" );
1181 		XMLTest( "Entity transformation: open text file for writing", true, textfile != 0, true );
1182 		if ( textfile )
1183 		{
1184 			XMLPrinter streamer( textfile );
1185 			bool acceptResult = psg->Accept( &streamer );
1186 			fclose( textfile );
1187 			XMLTest( "Entity transformation: Accept", true, acceptResult );
1188 		}
1189 
1190 		textfile = fopen( textFilePath, "r" );
1191 		XMLTest( "Entity transformation: open text file for reading", true, textfile != 0, true );
1192 		if ( textfile )
1193 		{
1194 			char buf[ 1024 ];
1195 			fgets( buf, 1024, textfile );
1196 			XMLTest( "Entity transformation: write. ",
1197 					 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
1198 					 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.\"/>\n",
1199 					 buf, false );
1200 			fclose( textfile );
1201 		}
1202 	}
1203 
1204 	{
1205 		// Suppress entities.
1206 		const char* passages =
1207 			"<?xml version=\"1.0\" standalone=\"no\" ?>"
1208 			"<passages count=\"006\" formatversion=\"20020620\">"
1209 				"<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
1210 			"</passages>";
1211 
1212 		XMLDocument doc( false );
1213 		doc.Parse( passages );
1214 		XMLTest( "Entity transformation parse round 2", false, doc.Error() );
1215 
1216 		XMLTest( "No entity parsing.",
1217 				 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.",
1218 				 doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ) );
1219 		XMLTest( "No entity parsing.", "Crazy &ttk;",
1220 				 doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value() );
1221 		doc.Print();
1222 	}
1223 
1224 	{
1225 		const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
1226 
1227 		XMLDocument doc;
1228 		doc.Parse( test );
1229 		XMLTest( "dot in names", false, doc.Error() );
1230 		XMLTest( "dot in names", "a.elem", doc.FirstChildElement()->Name() );
1231 		XMLTest( "dot in names", "2.0", doc.FirstChildElement()->Attribute( "xmi.version" ) );
1232 	}
1233 
1234 	{
1235 		const char* test = "<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>";
1236 
1237 		XMLDocument doc;
1238 		doc.Parse( test );
1239 		XMLTest( "fin thickness", false, doc.Error() );
1240 
1241 		XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
1242 		XMLTest( "Entity with one digit.",
1243 				 "1.1 Start easy ignore fin thickness\n", text->Value(),
1244 				 false );
1245 	}
1246 
1247 	{
1248 		// DOCTYPE not preserved (950171)
1249 		//
1250 		const char* doctype =
1251 			"<?xml version=\"1.0\" ?>"
1252 			"<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
1253 			"<!ELEMENT title (#PCDATA)>"
1254 			"<!ELEMENT books (title,authors)>"
1255 			"<element />";
1256 
1257 		XMLDocument doc;
1258 		doc.Parse( doctype );
1259 		XMLTest( "PLAY SYSTEM parse", false, doc.Error() );
1260 		doc.SaveFile( "resources/out/test7.xml" );
1261 		XMLTest( "PLAY SYSTEM save", false, doc.Error() );
1262 		doc.DeleteChild( doc.RootElement() );
1263 		doc.LoadFile( "resources/out/test7.xml" );
1264 		XMLTest( "PLAY SYSTEM load", false, doc.Error() );
1265 		doc.Print();
1266 
1267 		const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown();
1268 		XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() );
1269 
1270 	}
1271 
1272 	{
1273 		// Comments do not stream out correctly.
1274 		const char* doctype =
1275 			"<!-- Somewhat<evil> -->";
1276 		XMLDocument doc;
1277 		doc.Parse( doctype );
1278 		XMLTest( "Comment somewhat evil", false, doc.Error() );
1279 
1280 		XMLComment* comment = doc.FirstChild()->ToComment();
1281 
1282 		XMLTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
1283 	}
1284 	{
1285 		// Double attributes
1286 		const char* doctype = "<element attr='red' attr='blue' />";
1287 
1288 		XMLDocument doc;
1289 		doc.Parse( doctype );
1290 
1291 		XMLTest( "Parsing repeated attributes.", XML_ERROR_PARSING_ATTRIBUTE, doc.ErrorID() );	// is an  error to tinyxml (didn't use to be, but caused issues)
1292 		doc.PrintError();
1293 	}
1294 
1295 	{
1296 		// Embedded null in stream.
1297 		const char* doctype = "<element att\0r='red' attr='blue' />";
1298 
1299 		XMLDocument doc;
1300 		doc.Parse( doctype );
1301 		XMLTest( "Embedded null throws error.", true, doc.Error() );
1302 	}
1303 
1304 	{
1305 		// Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
1306 		const char* str = "";
1307 		XMLDocument doc;
1308 		doc.Parse( str );
1309 		XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
1310 
1311 		// But be sure there is an error string!
1312 		const char* errorStr = doc.ErrorStr();
1313 		XMLTest("Error string should be set",
1314 			"Error=XML_ERROR_EMPTY_DOCUMENT ErrorID=13 (0xd) Line number=0",
1315 			errorStr);
1316 	}
1317 
1318 	{
1319 		// Documents with all whitespaces should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
1320 		const char* str = "    ";
1321 		XMLDocument doc;
1322 		doc.Parse( str );
1323 		XMLTest( "All whitespaces document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
1324 	}
1325 
1326 	{
1327 		// Low entities
1328 		XMLDocument doc;
1329 		doc.Parse( "<test>&#x0e;</test>" );
1330 		XMLTest( "Hex values", false, doc.Error() );
1331 		const char result[] = { 0x0e, 0 };
1332 		XMLTest( "Low entities.", result, doc.FirstChildElement()->GetText() );
1333 		doc.Print();
1334 	}
1335 
1336 	{
1337 		// Attribute values with trailing quotes not handled correctly
1338 		XMLDocument doc;
1339 		doc.Parse( "<foo attribute=bar\" />" );
1340 		XMLTest( "Throw error with bad end quotes.", true, doc.Error() );
1341 	}
1342 
1343 	{
1344 		// [ 1663758 ] Failure to report error on bad XML
1345 		XMLDocument xml;
1346 		xml.Parse("<x>");
1347 		XMLTest("Missing end tag at end of input", true, xml.Error());
1348 		xml.Parse("<x> ");
1349 		XMLTest("Missing end tag with trailing whitespace", true, xml.Error());
1350 		xml.Parse("<x></y>");
1351 		XMLTest("Mismatched tags", XML_ERROR_MISMATCHED_ELEMENT, xml.ErrorID() );
1352 	}
1353 
1354 
1355 	{
1356 		// [ 1475201 ] TinyXML parses entities in comments
1357 		XMLDocument xml;
1358 		xml.Parse("<!-- declarations for <head> & <body> -->"
1359 				  "<!-- far &amp; away -->" );
1360 		XMLTest( "Declarations for head and body", false, xml.Error() );
1361 
1362 		XMLNode* e0 = xml.FirstChild();
1363 		XMLNode* e1 = e0->NextSibling();
1364 		XMLComment* c0 = e0->ToComment();
1365 		XMLComment* c1 = e1->ToComment();
1366 
1367 		XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
1368 		XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
1369 	}
1370 
1371 	{
1372 		XMLDocument xml;
1373 		xml.Parse( "<Parent>"
1374 						"<child1 att=''/>"
1375 						"<!-- With this comment, child2 will not be parsed! -->"
1376 						"<child2 att=''/>"
1377 					"</Parent>" );
1378 		XMLTest( "Comments iteration", false, xml.Error() );
1379 		xml.Print();
1380 
1381 		int count = 0;
1382 
1383 		for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
1384 			 ele;
1385 			 ele = ele->NextSibling() )
1386 		{
1387 			++count;
1388 		}
1389 
1390 		XMLTest( "Comments iterate correctly.", 3, count );
1391 	}
1392 
1393 	{
1394 		// trying to repro [1874301]. If it doesn't go into an infinite loop, all is well.
1395 		unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
1396 		buf[60] = 239;
1397 		buf[61] = 0;
1398 
1399 		XMLDocument doc;
1400 		doc.Parse( (const char*)buf);
1401 		XMLTest( "Broken CDATA", true, doc.Error() );
1402 	}
1403 
1404 
1405 	{
1406 		// bug 1827248 Error while parsing a little bit malformed file
1407 		// Actually not malformed - should work.
1408 		XMLDocument xml;
1409 		xml.Parse( "<attributelist> </attributelist >" );
1410 		XMLTest( "Handle end tag whitespace", false, xml.Error() );
1411 	}
1412 
1413 	{
1414 		// This one must not result in an infinite loop
1415 		XMLDocument xml;
1416 		xml.Parse( "<infinite>loop" );
1417 		XMLTest( "No closing element", true, xml.Error() );
1418 		XMLTest( "Infinite loop test.", true, true );
1419 	}
1420 #endif
1421 	{
1422 		const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
1423 		XMLDocument doc;
1424 		doc.Parse( pub );
1425 		XMLTest( "Trailing DOCTYPE", false, doc.Error() );
1426 
1427 		XMLDocument clone;
1428 		for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
1429 			XMLNode* copy = node->ShallowClone( &clone );
1430 			clone.InsertEndChild( copy );
1431 		}
1432 
1433 		clone.Print();
1434 
1435 		int count=0;
1436 		const XMLNode* a=clone.FirstChild();
1437 		const XMLNode* b=doc.FirstChild();
1438 		for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
1439 			++count;
1440 			XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
1441 		}
1442 		XMLTest( "Clone and Equal", 4, count );
1443 	}
1444 
1445 	{
1446 		// Deep Cloning of root element.
1447 		XMLDocument doc2;
1448 		XMLPrinter printer1;
1449 		{
1450 			// Make sure doc1 is deleted before we test doc2
1451 			const char* xml =
1452 				"<root>"
1453 				"    <child1 foo='bar'/>"
1454 				"    <!-- comment thing -->"
1455 				"    <child2 val='1'>Text</child2>"
1456 				"</root>";
1457 			XMLDocument doc;
1458 			doc.Parse(xml);
1459 			XMLTest( "Parse before deep cloning root element", false, doc.Error() );
1460 
1461 			doc.Print(&printer1);
1462 			XMLNode* root = doc.RootElement()->DeepClone(&doc2);
1463 			doc2.InsertFirstChild(root);
1464 		}
1465 		XMLPrinter printer2;
1466 		doc2.Print(&printer2);
1467 
1468 		XMLTest("Deep clone of element.", printer1.CStr(), printer2.CStr(), true);
1469 	}
1470 
1471 	{
1472 		// Deep Cloning of sub element.
1473 		XMLDocument doc2;
1474 		XMLPrinter printer1;
1475 		{
1476 			// Make sure doc1 is deleted before we test doc2
1477 			const char* xml =
1478 				"<?xml version ='1.0'?>"
1479 				"<root>"
1480 				"    <child1 foo='bar'/>"
1481 				"    <!-- comment thing -->"
1482 				"    <child2 val='1'>Text</child2>"
1483 				"</root>";
1484 			XMLDocument doc;
1485 			doc.Parse(xml);
1486 			XMLTest( "Parse before deep cloning sub element", false, doc.Error() );
1487 
1488 			const XMLElement* subElement = doc.FirstChildElement("root")->FirstChildElement("child2");
1489 			bool acceptResult = subElement->Accept(&printer1);
1490 			XMLTest( "Accept before deep cloning", true, acceptResult );
1491 
1492 			XMLNode* clonedSubElement = subElement->DeepClone(&doc2);
1493 			doc2.InsertFirstChild(clonedSubElement);
1494 		}
1495 		XMLPrinter printer2;
1496 		doc2.Print(&printer2);
1497 
1498 		XMLTest("Deep clone of sub-element.", printer1.CStr(), printer2.CStr(), true);
1499 	}
1500 
1501 	{
1502 		// Deep cloning of document.
1503 		XMLDocument doc2;
1504 		XMLPrinter printer1;
1505 		{
1506 			// Make sure doc1 is deleted before we test doc2
1507 			const char* xml =
1508 				"<?xml version ='1.0'?>"
1509 				"<!-- Top level comment. -->"
1510 				"<root>"
1511 				"    <child1 foo='bar'/>"
1512 				"    <!-- comment thing -->"
1513 				"    <child2 val='1'>Text</child2>"
1514 				"</root>";
1515 			XMLDocument doc;
1516 			doc.Parse(xml);
1517 			XMLTest( "Parse before deep cloning document", false, doc.Error() );
1518 			doc.Print(&printer1);
1519 
1520 			doc.DeepCopy(&doc2);
1521 		}
1522 		XMLPrinter printer2;
1523 		doc2.Print(&printer2);
1524 
1525 		XMLTest("DeepCopy of document.", printer1.CStr(), printer2.CStr(), true);
1526 	}
1527 
1528 
1529  	{
1530 		// This shouldn't crash.
1531 		XMLDocument doc;
1532 		if(XML_SUCCESS != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
1533 		{
1534 			doc.PrintError();
1535 		}
1536 		XMLTest( "Error in snprinf handling.", true, doc.Error() );
1537 	}
1538 
1539 	{
1540 		// Attribute ordering.
1541 		static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
1542 		XMLDocument doc;
1543 		doc.Parse( xml );
1544 		XMLTest( "Parse for attribute ordering", false, doc.Error() );
1545 		XMLElement* ele = doc.FirstChildElement();
1546 
1547 		const XMLAttribute* a = ele->FirstAttribute();
1548 		XMLTest( "Attribute order", "1", a->Value() );
1549 		a = a->Next();
1550 		XMLTest( "Attribute order", "2", a->Value() );
1551 		a = a->Next();
1552 		XMLTest( "Attribute order", "3", a->Value() );
1553 		XMLTest( "Attribute order", "attrib3", a->Name() );
1554 
1555 		ele->DeleteAttribute( "attrib2" );
1556 		a = ele->FirstAttribute();
1557 		XMLTest( "Attribute order", "1", a->Value() );
1558 		a = a->Next();
1559 		XMLTest( "Attribute order", "3", a->Value() );
1560 
1561 		ele->DeleteAttribute( "attrib1" );
1562 		ele->DeleteAttribute( "attrib3" );
1563 		XMLTest( "Attribute order (empty)", true, ele->FirstAttribute() == 0 );
1564 	}
1565 
1566 	{
1567 		// Make sure an attribute with a space in it succeeds.
1568 		static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
1569 		static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
1570 		static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
1571 		XMLDocument doc0;
1572 		doc0.Parse( xml0 );
1573 		XMLTest( "Parse attribute with space 1", false, doc0.Error() );
1574 		XMLDocument doc1;
1575 		doc1.Parse( xml1 );
1576 		XMLTest( "Parse attribute with space 2", false, doc1.Error() );
1577 		XMLDocument doc2;
1578 		doc2.Parse( xml2 );
1579 		XMLTest( "Parse attribute with space 3", false, doc2.Error() );
1580 
1581 		XMLElement* ele = 0;
1582 		ele = doc0.FirstChildElement();
1583 		XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
1584 		ele = doc1.FirstChildElement();
1585 		XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
1586 		ele = doc2.FirstChildElement();
1587 		XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
1588 	}
1589 
1590 	{
1591 		// Make sure we don't go into an infinite loop.
1592 		static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
1593 		XMLDocument doc;
1594 		doc.Parse( xml );
1595 		XMLTest( "Parse two elements with attribute", false, doc.Error() );
1596 		XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
1597 		XMLElement* ele1 = ele0->NextSiblingElement();
1598 		bool equal = ele0->ShallowEqual( ele1 );
1599 
1600 		XMLTest( "Infinite loop in shallow equal.", true, equal );
1601 	}
1602 
1603 	// -------- Handles ------------
1604 	{
1605 		static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1606 		XMLDocument doc;
1607 		doc.Parse( xml );
1608 		XMLTest( "Handle, parse element with attribute and nested element", false, doc.Error() );
1609 
1610 		{
1611 			XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
1612 			XMLTest( "Handle, non-const, element is found", true, ele != 0 );
1613 			XMLTest( "Handle, non-const, element name matches", "sub", ele->Value() );
1614 		}
1615 
1616 		{
1617 			XMLHandle docH( doc );
1618 			XMLElement* ele = docH.FirstChildElement( "noSuchElement" ).FirstChildElement( "element" ).ToElement();
1619 			XMLTest( "Handle, non-const, element not found", true, ele == 0 );
1620 		}
1621 
1622 		{
1623 			const XMLElement* ele = XMLConstHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
1624 			XMLTest( "Handle, const, element is found", true, ele != 0 );
1625 			XMLTest( "Handle, const, element name matches", "sub", ele->Value() );
1626 		}
1627 
1628 		{
1629 			XMLConstHandle docH( doc );
1630 			const XMLElement* ele = docH.FirstChildElement( "noSuchElement" ).FirstChildElement( "element" ).ToElement();
1631 			XMLTest( "Handle, const, element not found", true, ele == 0 );
1632 		}
1633 	}
1634 	{
1635 		// Default Declaration & BOM
1636 		XMLDocument doc;
1637 		doc.InsertEndChild( doc.NewDeclaration() );
1638 		doc.SetBOM( true );
1639 
1640 		XMLPrinter printer;
1641 		doc.Print( &printer );
1642 
1643 		static const char* result  = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
1644 		XMLTest( "BOM and default declaration", result, printer.CStr(), false );
1645 		XMLTest( "CStrSize", 42, printer.CStrSize(), false );
1646 	}
1647 	{
1648 		const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
1649 		XMLDocument doc;
1650 		doc.Parse( xml );
1651 		XMLTest( "Ill formed XML", true, doc.Error() );
1652 	}
1653 
1654     {
1655         //API:IntText(),UnsignedText(),Int64Text(),DoubleText(),BoolText() and FloatText() test
1656         const char* xml = "<point> <IntText>-24</IntText> <UnsignedText>42</UnsignedText> \
1657 						   <Int64Text>38</Int64Text> <BoolText>true</BoolText> <DoubleText>2.35</DoubleText> </point>";
1658         XMLDocument doc;
1659         doc.Parse(xml);
1660 
1661         const XMLElement* pointElement = doc.RootElement();
1662         int test1 = pointElement->FirstChildElement("IntText")->IntText();
1663         XMLTest("IntText() test", -24, test1);
1664 
1665         unsigned test2 = pointElement->FirstChildElement("UnsignedText")->UnsignedText();
1666         XMLTest("UnsignedText() test", static_cast<unsigned>(42), test2);
1667 
1668         int64_t test3 = pointElement->FirstChildElement("Int64Text")->Int64Text();
1669         XMLTest("Int64Text() test", static_cast<int64_t>(38), test3);
1670 
1671         double test4 = pointElement->FirstChildElement("DoubleText")->DoubleText();
1672         XMLTest("DoubleText() test", 2.35, test4);
1673 
1674         float test5 = pointElement->FirstChildElement("DoubleText")->FloatText();
1675         XMLTest("FloatText()) test", 2.35f, test5);
1676 
1677         bool test6 = pointElement->FirstChildElement("BoolText")->BoolText();
1678         XMLTest("FloatText()) test", true, test6);
1679     }
1680 
1681     {
1682         // hex value test
1683         const char* xml = "<point> <IntText>  0x2020</IntText> <UnsignedText>0X2020</UnsignedText> \
1684 						   <Int64Text> 0x1234</Int64Text></point>";
1685         XMLDocument doc;
1686         doc.Parse(xml);
1687 
1688         const XMLElement* pointElement = doc.RootElement();
1689         int test1 = pointElement->FirstChildElement("IntText")->IntText();
1690         XMLTest("IntText() hex value test", 0x2020, test1);
1691 
1692         unsigned test2 = pointElement->FirstChildElement("UnsignedText")->UnsignedText();
1693         XMLTest("UnsignedText() hex value test", static_cast<unsigned>(0x2020), test2);
1694 
1695         int64_t test3 = pointElement->FirstChildElement("Int64Text")->Int64Text();
1696         XMLTest("Int64Text() hex value test", static_cast<int64_t>(0x1234), test3);
1697     }
1698 
1699 	{
1700 		//API:ShallowEqual() test
1701 		const char* xml = "<playlist id = 'playlist'>"
1702 						    "<property name = 'track_name'>voice</property>"
1703 						  "</playlist>";
1704 		XMLDocument doc;
1705 		doc.Parse( xml );
1706 		const XMLNode* PlaylistNode = doc.RootElement();
1707 		const XMLNode* PropertyNode = PlaylistNode->FirstChildElement();
1708 		bool result;
1709 		result = PlaylistNode->ShallowEqual(PropertyNode);
1710 		XMLTest("ShallowEqual() test",false,result);
1711 		result = PlaylistNode->ShallowEqual(PlaylistNode);
1712 		XMLTest("ShallowEqual() test",true,result);
1713 	}
1714 
1715 	{
1716 		//API: previousSiblingElement() and NextSiblingElement() test
1717 		const char* xml = "<playlist id = 'playlist'>"
1718 						    "<property name = 'track_name'>voice</property>"
1719 						    "<entry out = '946' producer = '2_playlist1' in = '0'/>"
1720 							"<blank length = '1'/>"
1721 						  "</playlist>";
1722 		XMLDocument doc;
1723 		doc.Parse( xml );
1724 		XMLElement* ElementPlaylist = doc.FirstChildElement("playlist");
1725 		XMLTest("previousSiblingElement() test",true,ElementPlaylist != 0);
1726 		const XMLElement* pre = ElementPlaylist->PreviousSiblingElement();
1727 		XMLTest("previousSiblingElement() test",true,pre == 0);
1728 		const XMLElement* ElementBlank = ElementPlaylist->FirstChildElement("entry")->NextSiblingElement("blank");
1729 		XMLTest("NextSiblingElement() test",true,ElementBlank != 0);
1730 		const XMLElement* next = ElementBlank->NextSiblingElement();
1731 		XMLTest("NextSiblingElement() test",true,next == 0);
1732 		const XMLElement* ElementEntry = ElementBlank->PreviousSiblingElement("entry");
1733 		XMLTest("PreviousSiblingElement test",true,ElementEntry != 0);
1734 	}
1735 
1736 	// QueryXYZText
1737 	{
1738 		const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
1739 		XMLDocument doc;
1740 		doc.Parse( xml );
1741 		XMLTest( "Parse points", false, doc.Error() );
1742 
1743 		const XMLElement* pointElement = doc.RootElement();
1744 
1745 		{
1746 			int intValue = 0;
1747 			XMLError queryResult = pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
1748 			XMLTest( "QueryIntText result", XML_SUCCESS, queryResult, false );
1749 			XMLTest( "QueryIntText", 1, intValue, false );
1750 		}
1751 
1752 		{
1753 			unsigned unsignedValue = 0;
1754 			XMLError queryResult = pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
1755 			XMLTest( "QueryUnsignedText result", XML_SUCCESS, queryResult, false );
1756 			XMLTest( "QueryUnsignedText", (unsigned)1, unsignedValue, false );
1757 		}
1758 
1759 		{
1760 			float floatValue = 0;
1761 			XMLError queryResult = pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
1762 			XMLTest( "QueryFloatText result", XML_SUCCESS, queryResult, false );
1763 			XMLTest( "QueryFloatText", 1.2f, floatValue, false );
1764 		}
1765 
1766 		{
1767 			double doubleValue = 0;
1768 			XMLError queryResult = pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
1769 			XMLTest( "QueryDoubleText result", XML_SUCCESS, queryResult, false );
1770 			XMLTest( "QueryDoubleText", 1.2, doubleValue, false );
1771 		}
1772 
1773 		{
1774 			bool boolValue = false;
1775 			XMLError queryResult = pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
1776 			XMLTest( "QueryBoolText result", XML_SUCCESS, queryResult, false );
1777 			XMLTest( "QueryBoolText", true, boolValue, false );
1778 		}
1779 	}
1780 
1781 	{
1782 		const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
1783 		XMLDocument doc;
1784 		doc.Parse( xml );
1785 		XMLTest( "Non-alpha element lead letter parses.", false, doc.Error() );
1786 	}
1787 
1788     {
1789         const char* xml = "<element _attr1=\"foo\" :attr2=\"bar\"></element>";
1790         XMLDocument doc;
1791         doc.Parse( xml );
1792         XMLTest("Non-alpha attribute lead character parses.", false, doc.Error());
1793     }
1794 
1795     {
1796         const char* xml = "<3lement></3lement>";
1797         XMLDocument doc;
1798         doc.Parse( xml );
1799         XMLTest("Element names with lead digit fail to parse.", true, doc.Error());
1800     }
1801 
1802 	{
1803 		const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
1804 		XMLDocument doc;
1805 		doc.Parse( xml, 10 );
1806 		XMLTest( "Set length of incoming data", false, doc.Error() );
1807 	}
1808 
1809     {
1810         XMLDocument doc;
1811         XMLTest( "Document is initially empty", true, doc.NoChildren() );
1812         doc.Clear();
1813         XMLTest( "Empty is empty after Clear()", true, doc.NoChildren() );
1814         doc.LoadFile( "resources/dream.xml" );
1815         XMLTest( "Load dream.xml", false, doc.Error() );
1816         XMLTest( "Document has something to Clear()", false, doc.NoChildren() );
1817         doc.Clear();
1818         XMLTest( "Document Clear()'s", true, doc.NoChildren() );
1819     }
1820 
1821     {
1822         XMLDocument doc;
1823         XMLTest( "No error initially", false, doc.Error() );
1824         XMLError error = doc.Parse( "This is not XML" );
1825         XMLTest( "Error after invalid XML", true, doc.Error() );
1826         XMLTest( "Error after invalid XML", error, doc.ErrorID() );
1827         doc.Clear();
1828         XMLTest( "No error after Clear()", false, doc.Error() );
1829     }
1830 
1831 	// ----------- Whitespace ------------
1832 	{
1833 		const char* xml = "<element>"
1834 							"<a> This \nis &apos;  text  &apos; </a>"
1835 							"<b>  This is &apos; text &apos;  \n</b>"
1836 							"<c>This  is  &apos;  \n\n text &apos;</c>"
1837 						  "</element>";
1838 		XMLDocument doc( true, COLLAPSE_WHITESPACE );
1839 		doc.Parse( xml );
1840 		XMLTest( "Parse with whitespace collapsing and &apos", false, doc.Error() );
1841 
1842 		const XMLElement* element = doc.FirstChildElement();
1843 		for( const XMLElement* parent = element->FirstChildElement();
1844 			 parent;
1845 			 parent = parent->NextSiblingElement() )
1846 		{
1847 			XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
1848 		}
1849 	}
1850 
1851 #if 0
1852 	{
1853 		// Passes if assert doesn't fire.
1854 		XMLDocument xmlDoc;
1855 
1856 	    xmlDoc.NewDeclaration();
1857 	    xmlDoc.NewComment("Configuration file");
1858 
1859 	    XMLElement *root = xmlDoc.NewElement("settings");
1860 	    root->SetAttribute("version", 2);
1861 	}
1862 #endif
1863 
1864 	{
1865 		const char* xml = "<element>    </element>";
1866 		XMLDocument doc( true, COLLAPSE_WHITESPACE );
1867 		doc.Parse( xml );
1868 		XMLTest( "Parse with all whitespaces", false, doc.Error() );
1869 		XMLTest( "Whitespace  all space", true, 0 == doc.FirstChildElement()->FirstChild() );
1870 	}
1871 
1872 	// ----------- Preserve Whitespace ------------
1873 	{
1874 		const char* xml = "<element>This  is  &apos;  \n\n text &apos;</element>";
1875 		XMLDocument doc(true, PRESERVE_WHITESPACE);
1876 		doc.Parse(xml);
1877 		XMLTest("Parse with whitespace preserved", false, doc.Error());
1878 		XMLTest("Whitespace preserved", "This  is  '  \n\n text '", doc.FirstChildElement()->GetText());
1879 	}
1880 
1881 	{
1882 		const char* xml = "<element> This \nis &apos;  text  &apos;  </element>";
1883 		XMLDocument doc(true, PRESERVE_WHITESPACE);
1884 		doc.Parse(xml);
1885 		XMLTest("Parse with whitespace preserved", false, doc.Error());
1886 		XMLTest("Whitespace preserved", " This \nis '  text  '  ", doc.FirstChildElement()->GetText());
1887 	}
1888 
1889 	{
1890 		const char* xml = "<element>  \n This is &apos; text &apos;  \n</element>";
1891 		XMLDocument doc(true, PRESERVE_WHITESPACE);
1892 		doc.Parse(xml);
1893 		XMLTest("Parse with whitespace preserved", false, doc.Error());
1894 		XMLTest("Whitespace preserved", "  \n This is ' text '  \n", doc.FirstChildElement()->GetText());
1895 	}
1896 
1897 	// Following cases are for text that is all whitespace which are not preserved intentionally
1898 	{
1899 		const char* xml = "<element> </element>";
1900 		XMLDocument doc(true, PRESERVE_WHITESPACE);
1901 		doc.Parse(xml);
1902 		XMLTest("Parse with whitespace preserved", false, doc.Error());
1903 		XMLTest("Whitespace preserved", true, 0 == doc.FirstChildElement()->GetText());
1904 	}
1905 
1906 	{
1907 		const char* xml = "<element>   </element>";
1908 		XMLDocument doc(true, PRESERVE_WHITESPACE);
1909 		doc.Parse(xml);
1910 		XMLTest("Parse with whitespace preserved", false, doc.Error());
1911 		XMLTest("Whitespace preserved", true, 0 == doc.FirstChildElement()->GetText());
1912 	}
1913 
1914 	{
1915 		const char* xml = "<element>\n\n</element>";
1916 		XMLDocument doc(true, PRESERVE_WHITESPACE);
1917 		doc.Parse(xml);
1918 		XMLTest("Parse with whitespace preserved", false, doc.Error());
1919 		XMLTest("Whitespace preserved", true, 0 == doc.FirstChildElement()->GetText());
1920 	}
1921 
1922 	{
1923 		const char* xml = "<element>  \n</element>";
1924 		XMLDocument doc(true, PRESERVE_WHITESPACE);
1925 		doc.Parse(xml);
1926 		XMLTest("Parse with whitespace preserved", false, doc.Error());
1927 		XMLTest("Whitespace preserved", true, 0 == doc.FirstChildElement()->GetText());
1928 	}
1929 
1930 	{
1931 		const char* xml = "<element> \n \n </element>";
1932 		XMLDocument doc(true, PRESERVE_WHITESPACE);
1933 		doc.Parse(xml);
1934 		XMLTest("Parse with whitespace preserved", false, doc.Error());
1935 		XMLTest("Whitespace preserved", true, 0 == doc.FirstChildElement()->GetText());
1936 	}
1937 
1938 	// ----------- Pedantic Whitespace ------------
1939 	{
1940 		const char* xml = "<element>This  is  &apos;  \n\n text &apos;</element>";
1941 		XMLDocument doc(true, PEDANTIC_WHITESPACE);
1942 		doc.Parse(xml);
1943 		XMLTest("Parse with pedantic whitespace", false, doc.Error());
1944 		XMLTest("Pedantic whitespace", "This  is  '  \n\n text '", doc.FirstChildElement()->GetText());
1945 	}
1946 
1947 	{
1948 		const char* xml = "<element> This \nis &apos;  text  &apos;  </element>";
1949 		XMLDocument doc(true, PEDANTIC_WHITESPACE);
1950 		doc.Parse(xml);
1951 		XMLTest("Parse with pedantic whitespace", false, doc.Error());
1952 		XMLTest("Pedantic whitespace", " This \nis '  text  '  ", doc.FirstChildElement()->GetText());
1953 	}
1954 
1955 	{
1956 		const char* xml = "<element>  \n This is &apos; text &apos;  \n</element>";
1957 		XMLDocument doc(true, PEDANTIC_WHITESPACE);
1958 		doc.Parse(xml);
1959 		XMLTest("Parse with pedantic whitespace", false, doc.Error());
1960 		XMLTest("Pedantic whitespace", "  \n This is ' text '  \n", doc.FirstChildElement()->GetText());
1961 	}
1962 
1963 	// Following cases are for text that is all whitespace which is preserved with pedantic mode
1964 	{
1965 		const char* xml = "<element> </element>";
1966 		XMLDocument doc(true, PEDANTIC_WHITESPACE);
1967 		doc.Parse(xml);
1968 		XMLTest("Parse with pedantic whitespace", false, doc.Error());
1969 		XMLTest("Pedantic whitespace", " ", doc.FirstChildElement()->GetText());
1970 	}
1971 
1972 	{
1973 		const char* xml = "<element>   </element>";
1974 		XMLDocument doc(true, PEDANTIC_WHITESPACE);
1975 		doc.Parse(xml);
1976 		XMLTest("Parse with pedantic whitespace", false, doc.Error());
1977 		XMLTest("Pedantic whitespace", "   ", doc.FirstChildElement()->GetText());
1978 	}
1979 
1980 	{
1981 		const char* xml = "<element>\n\n</element>\n";
1982 		XMLDocument doc(true, PEDANTIC_WHITESPACE);
1983 		doc.Parse(xml);
1984 		XMLTest("Parse with pedantic whitespace", false, doc.Error());
1985 		XMLTest("Pedantic whitespace", "\n\n", doc.FirstChildElement()->GetText());
1986 	}
1987 
1988 	{
1989 		const char* xml = "<element>  \n</element> \n ";
1990 		XMLDocument doc(true, PEDANTIC_WHITESPACE);
1991 		doc.Parse(xml);
1992 		XMLTest("Parse with pedantic whitespace", false, doc.Error());
1993 		XMLTest("Pedantic whitespace", "  \n", doc.FirstChildElement()->GetText());
1994 	}
1995 
1996 	{
1997 		const char* xml = "<element> \n  \n </element>  ";
1998 		XMLDocument doc(true, PEDANTIC_WHITESPACE);
1999 		doc.Parse(xml);
2000 		XMLTest("Parse with pedantic whitespace", false, doc.Error());
2001 		XMLTest("Pedantic whitespace", " \n  \n ", doc.FirstChildElement()->GetText());
2002 	}
2003 
2004 	// Following cases are for checking nested elements are still parsed with pedantic whitespace
2005 	{
2006 		const char* xml = "<element>\n\t<a> This is nested text </a>\n</element>  ";
2007 		XMLDocument doc(true, PEDANTIC_WHITESPACE);
2008 		doc.Parse(xml);
2009 		XMLTest("Parse nested elements with pedantic whitespace", false, doc.Error());
2010 		XMLTest("Pedantic whitespace", " This is nested text ", doc.RootElement()->FirstChildElement()->GetText());
2011 	}
2012 
2013 	{
2014 		const char* xml = "<element>  <b> </b>  </element>\n";
2015 		XMLDocument doc(true, PEDANTIC_WHITESPACE);
2016 		doc.Parse(xml);
2017 		XMLTest("Parse nested elements with pedantic whitespace", false, doc.Error());
2018 		XMLTest("Pedantic whitespace", " ", doc.RootElement()->FirstChildElement()->GetText());
2019 	}
2020 
2021 	{
2022 		const char* xml = "<element>  <c attribute=\"test\"/>  </element>\n ";
2023 		XMLDocument doc(true, PEDANTIC_WHITESPACE);
2024 		doc.Parse(xml);
2025 		XMLTest("Parse nested elements with pedantic whitespace", false, doc.Error());
2026 		XMLTest("Pedantic whitespace", true, 0 == doc.RootElement()->FirstChildElement()->GetText());
2027 	}
2028 
2029 	// Check sample xml can be parsed with pedantic mode
2030 	{
2031 		XMLDocument doc(true, PEDANTIC_WHITESPACE);
2032 		doc.LoadFile("resources/dream.xml");
2033 		XMLTest("Load dream.xml with pedantic whitespace mode", false, doc.Error());
2034 
2035 		XMLTest("Dream", "xml version=\"1.0\"",
2036 			doc.FirstChild()->ToDeclaration()->Value());
2037 		XMLTest("Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() != 0);
2038 		XMLTest("Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
2039 			doc.FirstChild()->NextSibling()->ToUnknown()->Value());
2040 		XMLTest("Dream", "And Robin shall restore amends.",
2041 			doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText());
2042 	}
2043 
2044 	{
2045 		// An assert should not fire.
2046 		const char* xml = "<element/>";
2047 		XMLDocument doc;
2048 		doc.Parse( xml );
2049 		XMLTest( "Parse with self-closed element", false, doc.Error() );
2050 		XMLElement* ele = doc.NewElement( "unused" );		// This will get cleaned up with the 'doc' going out of scope.
2051 		XMLTest( "Tracking unused elements", true, ele != 0, false );
2052 	}
2053 
2054 
2055 	{
2056 		const char* xml = "<parent><child>abc</child></parent>";
2057 		XMLDocument doc;
2058 		doc.Parse( xml );
2059 		XMLTest( "Parse for printing of sub-element", false, doc.Error() );
2060 		XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child");
2061 
2062 		XMLPrinter printer;
2063 		bool acceptResult = ele->Accept( &printer );
2064 		XMLTest( "Accept of sub-element", true, acceptResult );
2065 		XMLTest( "Printing of sub-element", "<child>abc</child>\n", printer.CStr(), false );
2066 	}
2067 
2068 
2069 	{
2070 		XMLDocument doc;
2071 		XMLError error = doc.LoadFile( "resources/empty.xml" );
2072 		XMLTest( "Loading an empty file", XML_ERROR_EMPTY_DOCUMENT, error );
2073 		XMLTest( "Loading an empty file and ErrorName as string", "XML_ERROR_EMPTY_DOCUMENT", doc.ErrorName() );
2074 		doc.PrintError();
2075 	}
2076 
2077 	{
2078         // BOM preservation
2079         static const char* xml_bom_preservation  = "\xef\xbb\xbf<element/>\n";
2080         {
2081 			XMLDocument doc;
2082 			XMLTest( "BOM preservation (parse)", XML_SUCCESS, doc.Parse( xml_bom_preservation ), false );
2083             XMLPrinter printer;
2084             doc.Print( &printer );
2085 
2086             XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
2087 			doc.SaveFile( "resources/out/bomtest.xml" );
2088 			XMLTest( "Save bomtest.xml", false, doc.Error() );
2089         }
2090 		{
2091 			XMLDocument doc;
2092 			doc.LoadFile( "resources/out/bomtest.xml" );
2093 			XMLTest( "Load bomtest.xml", false, doc.Error() );
2094 			XMLTest( "BOM preservation (load)", true, doc.HasBOM(), false );
2095 
2096             XMLPrinter printer;
2097             doc.Print( &printer );
2098             XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
2099 		}
2100 	}
2101 
2102 	{
2103 		// Insertion with Removal
2104 		const char* xml = "<?xml version=\"1.0\" ?>"
2105 			"<root>"
2106 			"<one>"
2107 			"<subtree>"
2108 			"<elem>element 1</elem>text<!-- comment -->"
2109 			"</subtree>"
2110 			"</one>"
2111 			"<two/>"
2112 			"</root>";
2113 		const char* xmlInsideTwo = "<?xml version=\"1.0\" ?>"
2114 			"<root>"
2115 			"<one/>"
2116 			"<two>"
2117 			"<subtree>"
2118 			"<elem>element 1</elem>text<!-- comment -->"
2119 			"</subtree>"
2120 			"</two>"
2121 			"</root>";
2122 		const char* xmlAfterOne = "<?xml version=\"1.0\" ?>"
2123 			"<root>"
2124 			"<one/>"
2125 			"<subtree>"
2126 			"<elem>element 1</elem>text<!-- comment -->"
2127 			"</subtree>"
2128 			"<two/>"
2129 			"</root>";
2130 		const char* xmlAfterTwo = "<?xml version=\"1.0\" ?>"
2131 			"<root>"
2132 			"<one/>"
2133 			"<two/>"
2134 			"<subtree>"
2135 			"<elem>element 1</elem>text<!-- comment -->"
2136 			"</subtree>"
2137 			"</root>";
2138 
2139 		XMLDocument doc;
2140 		doc.Parse(xml);
2141 		XMLTest( "Insertion with removal parse round 1", false, doc.Error() );
2142 		XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
2143 		XMLElement* two = doc.RootElement()->FirstChildElement("two");
2144 		two->InsertFirstChild(subtree);
2145 		XMLPrinter printer1(0, true);
2146 		bool acceptResult = doc.Accept(&printer1);
2147 		XMLTest("Move node from within <one> to <two> - Accept()", true, acceptResult);
2148 		XMLTest("Move node from within <one> to <two>", xmlInsideTwo, printer1.CStr());
2149 
2150 		doc.Parse(xml);
2151 		XMLTest( "Insertion with removal parse round 2", false, doc.Error() );
2152 		subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
2153 		two = doc.RootElement()->FirstChildElement("two");
2154 		doc.RootElement()->InsertAfterChild(two, subtree);
2155 		XMLPrinter printer2(0, true);
2156 		acceptResult = doc.Accept(&printer2);
2157 		XMLTest("Move node from within <one> after <two> - Accept()", true, acceptResult);
2158 		XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer2.CStr(), false);
2159 
2160 		doc.Parse(xml);
2161 		XMLTest( "Insertion with removal parse round 3", false, doc.Error() );
2162 		XMLNode* one = doc.RootElement()->FirstChildElement("one");
2163 		subtree = one->FirstChildElement("subtree");
2164 		doc.RootElement()->InsertAfterChild(one, subtree);
2165 		XMLPrinter printer3(0, true);
2166 		acceptResult = doc.Accept(&printer3);
2167 		XMLTest("Move node from within <one> after <one> - Accept()", true, acceptResult);
2168 		XMLTest("Move node from within <one> after <one>", xmlAfterOne, printer3.CStr(), false);
2169 
2170 		doc.Parse(xml);
2171 		XMLTest( "Insertion with removal parse round 4", false, doc.Error() );
2172 		subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
2173 		two = doc.RootElement()->FirstChildElement("two");
2174 		XMLTest("<two> is the last child at root level", true, two == doc.RootElement()->LastChildElement());
2175 		doc.RootElement()->InsertEndChild(subtree);
2176 		XMLPrinter printer4(0, true);
2177 		acceptResult = doc.Accept(&printer4);
2178 		XMLTest("Move node from within <one> after <two> - Accept()", true, acceptResult);
2179 		XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer4.CStr(), false);
2180 	}
2181 
2182 	{
2183 		const char* xml = "<svg width = \"128\" height = \"128\">"
2184 			"	<text> </text>"
2185 			"</svg>";
2186 		XMLDocument doc;
2187 		doc.Parse(xml);
2188 		XMLTest( "Parse svg with text", false, doc.Error() );
2189 		doc.Print();
2190 	}
2191 
2192 	{
2193 		// Test that it doesn't crash.
2194 		const char* xml = "<?xml version=\"1.0\"?><root><sample><field0><1</field0><field1>2</field1></sample></root>";
2195 		XMLDocument doc;
2196 		doc.Parse(xml);
2197 		XMLTest( "Parse root-sample-field0", true, doc.Error() );
2198 		doc.PrintError();
2199 	}
2200 
2201 #if 1
2202 		// the question being explored is what kind of print to use:
2203 		// https://github.com/leethomason/tinyxml2/issues/63
2204 	{
2205 		//const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9' attrC='1.0e-10' attrD='1001000000.000000' attrE='0.1234567890123456789'/>";
2206 		const char* xml = "<element/>";
2207 		XMLDocument doc;
2208 		doc.Parse( xml );
2209 		XMLTest( "Parse self-closed empty element", false, doc.Error() );
2210 		doc.FirstChildElement()->SetAttribute( "attrA-f64", 123456789.123456789 );
2211 		doc.FirstChildElement()->SetAttribute( "attrB-f64", 1.001e9 );
2212 		doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e9 );
2213 		doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e20 );
2214 		doc.FirstChildElement()->SetAttribute( "attrD-f64", 1.0e-10 );
2215 		doc.FirstChildElement()->SetAttribute( "attrD-f64", 0.123456789 );
2216 
2217 		doc.FirstChildElement()->SetAttribute( "attrA-f32", 123456789.123456789f );
2218 		doc.FirstChildElement()->SetAttribute( "attrB-f32", 1.001e9f );
2219 		doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e9f );
2220 		doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e20f );
2221 		doc.FirstChildElement()->SetAttribute( "attrD-f32", 1.0e-10f );
2222 		doc.FirstChildElement()->SetAttribute( "attrD-f32", 0.123456789f );
2223 
2224 		doc.Print();
2225 
2226 		/* The result of this test is platform, compiler, and library version dependent. :("
2227 		XMLPrinter printer;
2228 		doc.Print( &printer );
2229 		XMLTest( "Float and double formatting.",
2230 			"<element attrA-f64=\"123456789.12345679\" attrB-f64=\"1001000000\" attrC-f64=\"1e+20\" attrD-f64=\"0.123456789\" attrA-f32=\"1.2345679e+08\" attrB-f32=\"1.001e+09\" attrC-f32=\"1e+20\" attrD-f32=\"0.12345679\"/>\n",
2231 			printer.CStr(),
2232 			true );
2233 		*/
2234 	}
2235 #endif
2236 
2237     {
2238         // Issue #184
2239         // If it doesn't assert, it passes. Caused by objects
2240         // getting created during parsing which are then
2241         // inaccessible in the memory pools.
2242         const char* xmlText = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>";
2243         {
2244             XMLDocument doc;
2245             doc.Parse(xmlText);
2246             XMLTest( "Parse hex no closing tag round 1", true, doc.Error() );
2247         }
2248         {
2249             XMLDocument doc;
2250             doc.Parse(xmlText);
2251             XMLTest( "Parse hex no closing tag round 2", true, doc.Error() );
2252             doc.Clear();
2253         }
2254     }
2255 
2256     {
2257         // If this doesn't assert in TINYXML2_DEBUG, all is well.
2258         tinyxml2::XMLDocument doc;
2259         tinyxml2::XMLElement *pRoot = doc.NewElement("Root");
2260         doc.DeleteNode(pRoot);
2261     }
2262 
2263     {
2264         XMLDocument doc;
2265         XMLElement* root = doc.NewElement( "Root" );
2266         XMLTest( "Node document before insertion", true, &doc == root->GetDocument() );
2267         doc.InsertEndChild( root );
2268         XMLTest( "Node document after insertion", true, &doc == root->GetDocument() );
2269     }
2270 
2271     {
2272         // If this doesn't assert in TINYXML2_DEBUG, all is well.
2273         XMLDocument doc;
2274         XMLElement* unlinkedRoot = doc.NewElement( "Root" );
2275         XMLElement* linkedRoot = doc.NewElement( "Root" );
2276         doc.InsertFirstChild( linkedRoot );
2277         unlinkedRoot->GetDocument()->DeleteNode( linkedRoot );
2278         unlinkedRoot->GetDocument()->DeleteNode( unlinkedRoot );
2279     }
2280 
2281 	{
2282 		// Should not assert in TINYXML2_DEBUG
2283 		XMLPrinter printer;
2284 	}
2285 
2286 	{
2287 		// Issue 291. Should not crash
2288 		const char* xml = "&#0</a>";
2289 		XMLDocument doc;
2290 		doc.Parse( xml );
2291 		XMLTest( "Parse hex with closing tag", false, doc.Error() );
2292 
2293 		XMLPrinter printer;
2294 		doc.Print( &printer );
2295 	}
2296 	{
2297 		// Issue 299. Can print elements that are not linked in.
2298 		// Will crash if issue not fixed.
2299 		XMLDocument doc;
2300 		XMLElement* newElement = doc.NewElement( "printme" );
2301 		XMLPrinter printer;
2302 		bool acceptResult = newElement->Accept( &printer );
2303 		XMLTest( "printme - Accept()", true, acceptResult );
2304 		// Delete the node to avoid possible memory leak report in debug output
2305 		doc.DeleteNode( newElement );
2306 	}
2307 	{
2308 		// Issue 302. Clear errors from LoadFile/SaveFile
2309 		XMLDocument doc;
2310 		XMLTest( "Issue 302. Should be no error initially", "XML_SUCCESS", doc.ErrorName() );
2311 		doc.SaveFile( "./no/such/path/pretty.xml" );
2312 		XMLTest( "Issue 302. Fail to save", "XML_ERROR_FILE_COULD_NOT_BE_OPENED", doc.ErrorName() );
2313 		doc.SaveFile( "./resources/out/compact.xml", true );
2314 		XMLTest( "Issue 302. Subsequent success in saving", "XML_SUCCESS", doc.ErrorName() );
2315 	}
2316 
2317 	{
2318 		// If a document fails to load then subsequent
2319 		// successful loads should clear the error
2320 		XMLDocument doc;
2321 		XMLTest( "Should be no error initially", false, doc.Error() );
2322 		doc.LoadFile( "resources/no-such-file.xml" );
2323 		XMLTest( "No such file - should fail", true, doc.Error() );
2324 
2325 		doc.LoadFile("resources/dream.xml");
2326 		XMLTest("Error should be cleared", false, doc.Error());
2327 
2328 		doc.LoadFile( "resources/xmltest-5330.xml" );
2329         XMLTest( "parse errors occur - should fail", true, doc.Error() );
2330 
2331 		doc.LoadFile( "resources/dream.xml" );
2332 		XMLTest( "Error should be cleared", false, doc.Error() );
2333 	}
2334 
2335 	{
2336 		// Check that declarations are allowed only at beginning of document
2337 	    const char* xml0 = "<?xml version=\"1.0\" ?>"
2338 	                       "   <!-- xml version=\"1.1\" -->"
2339 	                       "<first />";
2340 	    const char* xml1 = "<?xml version=\"1.0\" ?>"
2341 	                       "<?xml-stylesheet type=\"text/xsl\" href=\"Anything.xsl\"?>"
2342 	                       "<first />";
2343 	    const char* xml2 = "<first />"
2344 	                       "<?xml version=\"1.0\" ?>";
2345 	    const char* xml3 = "<first></first>"
2346 	                       "<?xml version=\"1.0\" ?>";
2347 
2348 	    const char* xml4 = "<first><?xml version=\"1.0\" ?></first>";
2349 
2350 	    XMLDocument doc;
2351 	    doc.Parse(xml0);
2352 	    XMLTest("Test that the code changes do not affect normal parsing", false, doc.Error() );
2353 	    doc.Parse(xml1);
2354 	    XMLTest("Test that the second declaration is allowed", false, doc.Error() );
2355 	    doc.Parse(xml2);
2356 	    XMLTest("Test that declaration after self-closed child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );
2357 	    doc.Parse(xml3);
2358 	    XMLTest("Test that declaration after a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );
2359 	    doc.Parse(xml4);
2360 	    XMLTest("Test that declaration inside a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );
2361 	}
2362 
2363     {
2364 	    // No matter - before or after successfully parsing a text -
2365 	    // calling XMLDocument::Value() used to cause an assert in debug.
2366 	    // Null must be returned.
2367 	    const char* validXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
2368 	                           "<first />"
2369 	                           "<second />";
2370 	    XMLDocument* doc = new XMLDocument();
2371 	    XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
2372 	    doc->Parse( validXml );
2373 	    XMLTest( "Parse to test XMLDocument::Value()", false, doc->Error());
2374 	    XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
2375 	    delete doc;
2376     }
2377 
2378 	{
2379 		XMLDocument doc;
2380 		for( int i = 0; i < XML_ERROR_COUNT; i++ ) {
2381 			const XMLError error = static_cast<XMLError>(i);
2382 			const char* name = XMLDocument::ErrorIDToName(error);
2383 			XMLTest( "ErrorName() not null after ClearError()", true, name != 0 );
2384 			if( name == 0 ) {
2385 				// passing null pointer into strlen() is undefined behavior, so
2386 				// compiler is allowed to optimise away the null test above if it's
2387 				// as reachable as the strlen() call
2388 				continue;
2389 			}
2390 			XMLTest( "ErrorName() not empty after ClearError()", true, strlen(name) > 0 );
2391 		}
2392 	}
2393 
2394 	{
2395 		const char* html("<!DOCTYPE html><html><body><p>test</p><p><br/></p></body></html>");
2396 		XMLDocument doc(false);
2397 		doc.Parse(html);
2398 
2399 		XMLPrinter printer(0, true);
2400 		doc.Print(&printer);
2401 
2402 		XMLTest(html, html, printer.CStr());
2403 	}
2404 
2405 	{
2406 		// Evil memory leaks.
2407 		// If an XMLElement (etc) is allocated via NewElement() (etc.)
2408 		// and NOT added to the XMLDocument, what happens?
2409 		//
2410 		// Previously (buggy):
2411 		//		The memory would be free'd when the XMLDocument is
2412 		//      destructed. But the XMLElement destructor wasn't called, so
2413 		//      memory allocated for the XMLElement text would not be free'd.
2414 		//      In practice this meant strings allocated for the XMLElement
2415 		//      text would be leaked. An edge case, but annoying.
2416 		// Now:
2417 		//      The XMLElement destructor is called. But the unlinked nodes
2418 		//      have to be tracked using a list. This has a minor performance
2419 		//      impact that can become significant if you have a lot of
2420 		//      unlinked nodes. (But why would you do that?)
2421 		// The only way to see this bug was in a Visual C++ runtime debug heap
2422 		// leak tracker. This is compiled in by default on Windows Debug and
2423 		// enabled with _CRTDBG_LEAK_CHECK_DF parameter passed to _CrtSetDbgFlag().
2424 		{
2425 			XMLDocument doc;
2426 			doc.NewElement("LEAK 1");
2427 		}
2428 		{
2429 			XMLDocument doc;
2430 			XMLElement* ele = doc.NewElement("LEAK 2");
2431 			doc.DeleteNode(ele);
2432 		}
2433 	}
2434 
2435 	{
2436 		// Bad bad crash. Parsing error results in stack overflow, if uncaught.
2437 		const char* TESTS[] = {
2438 			"./resources/xmltest-5330.xml",
2439 			"./resources/xmltest-4636783552757760.xml",
2440 			"./resources/xmltest-5720541257269248.xml",
2441 			0
2442 		};
2443 		for (int i=0; TESTS[i]; ++i) {
2444 			XMLDocument doc;
2445 			doc.LoadFile(TESTS[i]);
2446 			XMLTest("Stack overflow prevented.", XML_ELEMENT_DEPTH_EXCEEDED, doc.ErrorID());
2447 		}
2448 	}
2449     {
2450         const char* TESTS[] = {
2451             "./resources/xmltest-5662204197076992.xml",     // Security-level performance issue.
2452             0
2453         };
2454         for (int i = 0; TESTS[i]; ++i) {
2455             XMLDocument doc;
2456             doc.LoadFile(TESTS[i]);
2457             // Need only not crash / lock up.
2458             XMLTest("Fuzz attack prevented.", true, true);
2459         }
2460     }
2461 	{
2462 		// Crashing reported via email.
2463 		const char* xml =
2464 			"<playlist id='playlist1'>"
2465 			"<property name='track_name'>voice</property>"
2466 			"<property name='audio_track'>1</property>"
2467 			"<entry out = '604' producer = '4_playlist1' in = '0' />"
2468 			"<blank length = '1' />"
2469 			"<entry out = '1625' producer = '3_playlist' in = '0' />"
2470 			"<blank length = '2' />"
2471 			"<entry out = '946' producer = '2_playlist1' in = '0' />"
2472 			"<blank length = '1' />"
2473 			"<entry out = '128' producer = '1_playlist1' in = '0' />"
2474 			"</playlist>";
2475 
2476 		// It's not a good idea to delete elements as you walk the
2477 		// list. I'm not sure this technically should work; but it's
2478 		// an interesting test case.
2479 		XMLDocument doc;
2480 		XMLError err = doc.Parse(xml);
2481 		XMLTest("Crash bug parsing", XML_SUCCESS, err );
2482 
2483 		XMLElement* playlist = doc.FirstChildElement("playlist");
2484 		XMLTest("Crash bug parsing", true, playlist != 0);
2485 
2486 		{
2487 			const char* elementName = "entry";
2488 			XMLElement* entry = playlist->FirstChildElement(elementName);
2489 			XMLTest("Crash bug parsing", true, entry != 0);
2490 			while (entry) {
2491 				XMLElement* todelete = entry;
2492 				entry = entry->NextSiblingElement(elementName);
2493 				playlist->DeleteChild(todelete);
2494 			}
2495 			entry = playlist->FirstChildElement(elementName);
2496 			XMLTest("Crash bug parsing", true, entry == 0);
2497 		}
2498 		{
2499 			const char* elementName = "blank";
2500 			XMLElement* blank = playlist->FirstChildElement(elementName);
2501 			XMLTest("Crash bug parsing", true, blank != 0);
2502 			while (blank) {
2503 				XMLElement* todelete = blank;
2504 				blank = blank->NextSiblingElement(elementName);
2505 				playlist->DeleteChild(todelete);
2506 			}
2507 			XMLTest("Crash bug parsing", true, blank == 0);
2508 		}
2509 
2510 		tinyxml2::XMLPrinter printer;
2511 		const bool acceptResult = playlist->Accept(&printer);
2512 		XMLTest("Crash bug parsing - Accept()", true, acceptResult);
2513 		printf("%s\n", printer.CStr());
2514 
2515 		// No test; it only need to not crash.
2516 		// Still, wrap it up with a sanity check
2517 		int nProperty = 0;
2518 		for (const XMLElement* p = playlist->FirstChildElement("property"); p; p = p->NextSiblingElement("property")) {
2519 			nProperty++;
2520 		}
2521 		XMLTest("Crash bug parsing", 2, nProperty);
2522 	}
2523 
2524     // ----------- Line Number Tracking --------------
2525     {
2526         struct TestUtil: XMLVisitor
2527         {
2528             TestUtil() : str() {}
2529 
2530             void TestParseError(const char *testString, const char *docStr, XMLError expected_error, int expectedLine)
2531             {
2532                 XMLDocument doc;
2533                 const XMLError parseError = doc.Parse(docStr);
2534 
2535                 XMLTest(testString, parseError, doc.ErrorID());
2536                 XMLTest(testString, true, doc.Error());
2537                 XMLTest(testString, expected_error, parseError);
2538                 XMLTest(testString, expectedLine, doc.ErrorLineNum());
2539             };
2540 
2541             void TestStringLines(const char *testString, const char *docStr, const char *expectedLines)
2542             {
2543                 XMLDocument doc;
2544                 doc.Parse(docStr);
2545                 XMLTest(testString, false, doc.Error());
2546                 TestDocLines(testString, doc, expectedLines);
2547             }
2548 
2549             void TestFileLines(const char *testString, const char *file_name, const char *expectedLines)
2550             {
2551                 XMLDocument doc;
2552                 doc.LoadFile(file_name);
2553                 XMLTest(testString, false, doc.Error());
2554                 TestDocLines(testString, doc, expectedLines);
2555             }
2556 
2557         private:
2558             DynArray<char, 10> str;
2559 
2560             void Push(char type, int lineNum)
2561             {
2562                 str.Push(type);
2563                 str.Push(char('0' + (lineNum / 10)));
2564                 str.Push(char('0' + (lineNum % 10)));
2565             }
2566 
2567             bool VisitEnter(const XMLDocument& doc)
2568             {
2569                 Push('D', doc.GetLineNum());
2570                 return true;
2571             }
2572             bool VisitEnter(const XMLElement& element, const XMLAttribute* firstAttribute)
2573             {
2574                 Push('E', element.GetLineNum());
2575                 for (const XMLAttribute *attr = firstAttribute; attr != 0; attr = attr->Next())
2576                     Push('A', attr->GetLineNum());
2577                 return true;
2578             }
2579             bool Visit(const XMLDeclaration& declaration)
2580             {
2581                 Push('L', declaration.GetLineNum());
2582                 return true;
2583             }
2584             bool Visit(const XMLText& text)
2585             {
2586                 Push('T', text.GetLineNum());
2587                 return true;
2588             }
2589             bool Visit(const XMLComment& comment)
2590             {
2591                 Push('C', comment.GetLineNum());
2592                 return true;
2593             }
2594             bool Visit(const XMLUnknown& unknown)
2595             {
2596                 Push('U', unknown.GetLineNum());
2597                 return true;
2598             }
2599 
2600             void TestDocLines(const char *testString, XMLDocument &doc, const char *expectedLines)
2601             {
2602                 str.Clear();
2603                 const bool acceptResult = doc.Accept(this);
2604                 XMLTest(testString, true, acceptResult);
2605                 str.Push(0);
2606                 XMLTest(testString, expectedLines, str.Mem());
2607             }
2608         } tester;
2609 
2610 		tester.TestParseError("ErrorLine-Parsing", "\n<root>\n foo \n<unclosed/>", XML_ERROR_PARSING, 2);
2611         tester.TestParseError("ErrorLine-Declaration", "<root>\n<?xml version=\"1.0\"?>", XML_ERROR_PARSING_DECLARATION, 2);
2612         tester.TestParseError("ErrorLine-Mismatch", "\n<root>\n</mismatch>", XML_ERROR_MISMATCHED_ELEMENT, 2);
2613         tester.TestParseError("ErrorLine-CData", "\n<root><![CDATA[ \n foo bar \n", XML_ERROR_PARSING_CDATA, 2);
2614         tester.TestParseError("ErrorLine-Text", "\n<root>\n foo bar \n", XML_ERROR_PARSING_TEXT, 3);
2615         tester.TestParseError("ErrorLine-Comment", "\n<root>\n<!-- >\n", XML_ERROR_PARSING_COMMENT, 3);
2616         tester.TestParseError("ErrorLine-Declaration", "\n<root>\n<? >\n", XML_ERROR_PARSING_DECLARATION, 3);
2617         tester.TestParseError("ErrorLine-Unknown", "\n<root>\n<! \n", XML_ERROR_PARSING_UNKNOWN, 3);
2618         tester.TestParseError("ErrorLine-Element", "\n<root>\n<unclosed \n", XML_ERROR_PARSING_ELEMENT, 3);
2619         tester.TestParseError("ErrorLine-Attribute", "\n<root>\n<unclosed \n att\n", XML_ERROR_PARSING_ATTRIBUTE, 4);
2620         tester.TestParseError("ErrorLine-ElementClose", "\n<root>\n<unclosed \n/unexpected", XML_ERROR_PARSING_ELEMENT, 3);
2621 
2622 		tester.TestStringLines(
2623             "LineNumbers-String",
2624 
2625             "<?xml version=\"1.0\"?>\n"					// 1 Doc, DecL
2626                 "<root a='b' \n"						// 2 Element Attribute
2627                 "c='d'> d <blah/>  \n"					// 3 Attribute Text Element
2628                 "newline in text \n"					// 4 Text
2629                 "and second <zxcv/><![CDATA[\n"			// 5 Element Text
2630                 " cdata test ]]><!-- comment -->\n"		// 6 Comment
2631                 "<! unknown></root>",					// 7 Unknown
2632 
2633             "D01L01E02A02A03T03E03T04E05T05C06U07");
2634 
2635 		tester.TestStringLines(
2636             "LineNumbers-CRLF",
2637 
2638             "\r\n"										// 1 Doc (arguably should be line 2)
2639             "<?xml version=\"1.0\"?>\n"					// 2 DecL
2640             "<root>\r\n"								// 3 Element
2641             "\n"										// 4
2642             "text contining new line \n"				// 5 Text
2643             " and also containing crlf \r\n"			// 6
2644             "<sub><![CDATA[\n"							// 7 Element Text
2645             "cdata containing new line \n"				// 8
2646             " and also containing cflr\r\n"				// 9
2647             "]]></sub><sub2/></root>",					// 10 Element
2648 
2649             "D01L02E03T05E07T07E10");
2650 
2651 		tester.TestFileLines(
2652             "LineNumbers-File",
2653             "resources/utf8test.xml",
2654             "D01L01E02E03A03A03T03E04A04A04T04E05A05A05T05E06A06A06T06E07A07A07T07E08A08A08T08E09T09E10T10");
2655     }
2656 
2657     {
2658     	const char* xml = "<Hello>Text</Error>";
2659     	XMLDocument doc;
2660     	doc.Parse(xml);
2661     	XMLTest("Test mismatched elements.", true, doc.Error());
2662     	XMLTest("Test mismatched elements.", XML_ERROR_MISMATCHED_ELEMENT, doc.ErrorID());
2663     	// For now just make sure calls work & doesn't crash.
2664     	// May solidify the error output in the future.
2665     	printf("%s\n", doc.ErrorStr());
2666     	doc.PrintError();
2667     }
2668 
2669     // ----------- Performance tracking --------------
2670 	{
2671 #if defined( _MSC_VER )
2672 		__int64 start, end, freq;
2673 		QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
2674 #endif
2675 
2676 		FILE* perfFP = fopen("resources/dream.xml", "r");
2677 		XMLTest("Open dream.xml", true, perfFP != 0);
2678 		fseek(perfFP, 0, SEEK_END);
2679 		long size = ftell(perfFP);
2680 		fseek(perfFP, 0, SEEK_SET);
2681 
2682 		char* mem = new char[size + 1];
2683 		memset(mem, 0xfe, size);
2684 		size_t bytesRead = fread(mem, 1, size, perfFP);
2685 		XMLTest("Read dream.xml", true, uint32_t(size) >= uint32_t(bytesRead));
2686 		fclose(perfFP);
2687 		mem[size] = 0;
2688 
2689 #if defined( _MSC_VER )
2690 		QueryPerformanceCounter((LARGE_INTEGER*)&start);
2691 #else
2692 		clock_t cstart = clock();
2693 #endif
2694 		bool parseDreamXmlFailed = false;
2695 		static const int COUNT = 10;
2696 		for (int i = 0; i < COUNT; ++i) {
2697 			XMLDocument doc;
2698 			doc.Parse(mem);
2699 			parseDreamXmlFailed = parseDreamXmlFailed || doc.Error();
2700 		}
2701 #if defined( _MSC_VER )
2702 		QueryPerformanceCounter((LARGE_INTEGER*)&end);
2703 #else
2704 		clock_t cend = clock();
2705 #endif
2706 		XMLTest( "Parse dream.xml", false, parseDreamXmlFailed );
2707 
2708 		delete[] mem;
2709 
2710 		static const char* note =
2711 #ifdef TINYXML2_DEBUG
2712 			"DEBUG";
2713 #else
2714 			"Release";
2715 #endif
2716 
2717 #if defined( _MSC_VER )
2718 		const double duration = 1000.0 * (double)(end - start) / ((double)freq * (double)COUNT);
2719 #else
2720 		const double duration = (double)(cend - cstart) / (double)COUNT;
2721 #endif
2722 		printf("\nParsing dream.xml (%s): %.3f milli-seconds\n", note, duration);
2723 	}
2724 
2725 #if defined( _MSC_VER ) &&  defined( TINYXML2_DEBUG )
2726 	{
2727 		_CrtMemCheckpoint( &endMemState );
2728 
2729 		_CrtMemState diffMemState;
2730 		_CrtMemDifference( &diffMemState, &startMemState, &endMemState );
2731 		_CrtMemDumpStatistics( &diffMemState );
2732 
2733 		{
2734 			int leaksBeforeExit = _CrtDumpMemoryLeaks();
2735 			XMLTest( "No leaks before exit?", FALSE, leaksBeforeExit );
2736 		}
2737 	}
2738 #endif
2739 
2740 	printf ("\nPass %d, Fail %d\n", gPass, gFail);
2741 
2742 	return gFail;
2743 }
2744