• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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* cStr = ele->Attribute( "str" );
636 		{
637 			XMLError queryResult = ele->QueryIntAttribute( "int", &iVal );
638 			XMLTest( "Query int attribute", XML_SUCCESS, queryResult);
639 		}
640 		{
641 			XMLError queryResult = ele->QueryDoubleAttribute( "double", &dVal );
642 			XMLTest( "Query double attribute", XML_SUCCESS, queryResult);
643 		}
644 
645 		{
646 			int queryResult = ele->QueryAttribute( "int", &iVal2 );
647 			XMLTest( "Query int attribute generic", (int)XML_SUCCESS, queryResult);
648 		}
649 		{
650 			int queryResult = ele->QueryAttribute( "double", &dVal2 );
651 			XMLTest( "Query double attribute generic", (int)XML_SUCCESS, queryResult);
652 		}
653 
654 		XMLTest( "Attribute match test", "strValue", ele->Attribute( "str", "strValue" ) );
655 		XMLTest( "Attribute round trip. c-string.", "strValue", cStr );
656 		XMLTest( "Attribute round trip. int.", 1, iVal );
657 		XMLTest( "Attribute round trip. double.", -1, (int)dVal );
658 		XMLTest( "Alternate query", true, iVal == iVal2 );
659 		XMLTest( "Alternate query", true, dVal == dVal2 );
660 		XMLTest( "Alternate query", true, iVal == ele->IntAttribute("int") );
661 		XMLTest( "Alternate query", true, dVal == ele->DoubleAttribute("double") );
662 	}
663 
664 	{
665 		XMLDocument doc;
666 		doc.LoadFile( "resources/utf8test.xml" );
667 		XMLTest( "Load utf8test.xml", false, doc.Error() );
668 
669 		// Get the attribute "value" from the "Russian" element and check it.
670 		XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" );
671 		const unsigned char correctValue[] = {	0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
672 												0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
673 
674 		XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) );
675 
676 		const unsigned char russianElementName[] = {	0xd0U, 0xa0U, 0xd1U, 0x83U,
677 														0xd1U, 0x81U, 0xd1U, 0x81U,
678 														0xd0U, 0xbaU, 0xd0U, 0xb8U,
679 														0xd0U, 0xb9U, 0 };
680 		const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
681 
682 		XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText();
683 		XMLTest( "UTF-8: Browsing russian element name.",
684 				 russianText,
685 				 text->Value() );
686 
687 		// Now try for a round trip.
688 		doc.SaveFile( "resources/out/utf8testout.xml" );
689 		XMLTest( "UTF-8: Save testout.xml", false, doc.Error() );
690 
691 		// Check the round trip.
692 		bool roundTripOkay = false;
693 
694 		FILE* saved  = fopen( "resources/out/utf8testout.xml", "r" );
695 		XMLTest( "UTF-8: Open utf8testout.xml", true, saved != 0 );
696 
697 		FILE* verify = fopen( "resources/utf8testverify.xml", "r" );
698 		XMLTest( "UTF-8: Open utf8testverify.xml", true, verify != 0 );
699 
700 		if ( saved && verify )
701 		{
702 			roundTripOkay = true;
703 			char verifyBuf[256];
704 			while ( fgets( verifyBuf, 256, verify ) )
705 			{
706 				char savedBuf[256];
707 				fgets( savedBuf, 256, saved );
708 				NullLineEndings( verifyBuf );
709 				NullLineEndings( savedBuf );
710 
711 				if ( strcmp( verifyBuf, savedBuf ) )
712 				{
713 					printf( "verify:%s<\n", verifyBuf );
714 					printf( "saved :%s<\n", savedBuf );
715 					roundTripOkay = false;
716 					break;
717 				}
718 			}
719 		}
720 		if ( saved )
721 			fclose( saved );
722 		if ( verify )
723 			fclose( verify );
724 		XMLTest( "UTF-8: Verified multi-language round trip.", true, roundTripOkay );
725 	}
726 
727 	// --------GetText()-----------
728 	{
729 		const char* str = "<foo>This is  text</foo>";
730 		XMLDocument doc;
731 		doc.Parse( str );
732 		XMLTest( "Double whitespace", false, doc.Error() );
733 		const XMLElement* element = doc.RootElement();
734 
735 		XMLTest( "GetText() normal use.", "This is  text", element->GetText() );
736 
737 		str = "<foo><b>This is text</b></foo>";
738 		doc.Parse( str );
739 		XMLTest( "Bold text simulation", false, doc.Error() );
740 		element = doc.RootElement();
741 
742 		XMLTest( "GetText() contained element.", element->GetText() == 0, true );
743 	}
744 
745 
746 	// --------SetText()-----------
747 	{
748 		const char* str = "<foo></foo>";
749 		XMLDocument doc;
750 		doc.Parse( str );
751 		XMLTest( "Empty closed element", false, doc.Error() );
752 		XMLElement* element = doc.RootElement();
753 
754 		element->SetText("darkness.");
755 		XMLTest( "SetText() normal use (open/close).", "darkness.", element->GetText() );
756 
757 		element->SetText("blue flame.");
758 		XMLTest( "SetText() replace.", "blue flame.", element->GetText() );
759 
760 		str = "<foo/>";
761 		doc.Parse( str );
762 		XMLTest( "Empty self-closed element", false, doc.Error() );
763 		element = doc.RootElement();
764 
765 		element->SetText("The driver");
766 		XMLTest( "SetText() normal use. (self-closing)", "The driver", element->GetText() );
767 
768 		element->SetText("<b>horses</b>");
769 		XMLTest( "SetText() replace with tag-like text.", "<b>horses</b>", element->GetText() );
770 		//doc.Print();
771 
772 		str = "<foo><bar>Text in nested element</bar></foo>";
773 		doc.Parse( str );
774 		XMLTest( "Text in nested element", false, doc.Error() );
775 		element = doc.RootElement();
776 
777 		element->SetText("wolves");
778 		XMLTest( "SetText() prefix to nested non-text children.", "wolves", element->GetText() );
779 
780 		str = "<foo/>";
781 		doc.Parse( str );
782 		XMLTest( "Empty self-closed element round 2", false, doc.Error() );
783 		element = doc.RootElement();
784 
785 		element->SetText( "str" );
786 		XMLTest( "SetText types", "str", element->GetText() );
787 
788 		element->SetText( 1 );
789 		XMLTest( "SetText types", "1", element->GetText() );
790 
791 		element->SetText( 1U );
792 		XMLTest( "SetText types", "1", element->GetText() );
793 
794 		element->SetText( true );
795 		XMLTest( "SetText types", "true", element->GetText() );
796 
797 		element->SetText( 1.5f );
798 		XMLTest( "SetText types", "1.5", element->GetText() );
799 
800 		element->SetText( 1.5 );
801 		XMLTest( "SetText types", "1.5", element->GetText() );
802 	}
803 
804 	// ---------- Attributes ---------
805 	{
806 		static const int64_t BIG = -123456789012345678;
807         static const uint64_t BIG_POS = 123456789012345678;
808 		XMLDocument doc;
809 		XMLElement* element = doc.NewElement("element");
810 		doc.InsertFirstChild(element);
811 
812 		{
813 			element->SetAttribute("attrib", int(-100));
814 			{
815 				int v = 0;
816 				XMLError queryResult = element->QueryIntAttribute("attrib", &v);
817 				XMLTest("Attribute: int", XML_SUCCESS, queryResult, true);
818 				XMLTest("Attribute: int", -100, v, true);
819 			}
820 			{
821 				int v = 0;
822 				int queryResult = element->QueryAttribute("attrib", &v);
823 				XMLTest("Attribute: int", (int)XML_SUCCESS, queryResult, true);
824 				XMLTest("Attribute: int", -100, v, true);
825 			}
826 			XMLTest("Attribute: int", -100, element->IntAttribute("attrib"), true);
827 		}
828 		{
829 			element->SetAttribute("attrib", unsigned(100));
830 			{
831 				unsigned v = 0;
832 				XMLError queryResult = element->QueryUnsignedAttribute("attrib", &v);
833 				XMLTest("Attribute: unsigned", XML_SUCCESS, queryResult, true);
834 				XMLTest("Attribute: unsigned", unsigned(100), v, true);
835 			}
836 			{
837 				unsigned v = 0;
838 				int queryResult = element->QueryAttribute("attrib", &v);
839 				XMLTest("Attribute: unsigned", (int)XML_SUCCESS, queryResult, true);
840 				XMLTest("Attribute: unsigned", unsigned(100), v, true);
841 			}
842 			{
843 				const char* v = "failed";
844 				XMLError queryResult = element->QueryStringAttribute("not-attrib", &v);
845 				XMLTest("Attribute: string default", false, queryResult == XML_SUCCESS);
846 				queryResult = element->QueryStringAttribute("attrib", &v);
847 				XMLTest("Attribute: string", XML_SUCCESS, queryResult, true);
848 				XMLTest("Attribute: string", "100", v);
849 			}
850 			XMLTest("Attribute: unsigned", unsigned(100), element->UnsignedAttribute("attrib"), true);
851 		}
852 		{
853 			element->SetAttribute("attrib", BIG);
854 			{
855 				int64_t v = 0;
856 				XMLError queryResult = element->QueryInt64Attribute("attrib", &v);
857 				XMLTest("Attribute: int64_t", XML_SUCCESS, queryResult, true);
858 				XMLTest("Attribute: int64_t", BIG, v, true);
859 			}
860 			{
861 				int64_t v = 0;
862 				int queryResult = element->QueryAttribute("attrib", &v);
863 				XMLTest("Attribute: int64_t", (int)XML_SUCCESS, queryResult, true);
864 				XMLTest("Attribute: int64_t", BIG, v, true);
865 			}
866 			XMLTest("Attribute: int64_t", BIG, element->Int64Attribute("attrib"), true);
867 		}
868         {
869             element->SetAttribute("attrib", BIG_POS);
870             {
871                 uint64_t v = 0;
872                 XMLError queryResult = element->QueryUnsigned64Attribute("attrib", &v);
873                 XMLTest("Attribute: uint64_t", XML_SUCCESS, queryResult, true);
874                 XMLTest("Attribute: uint64_t", BIG_POS, v, true);
875             }
876             {
877                 uint64_t v = 0;
878                 int queryResult = element->QueryAttribute("attrib", &v);
879                 XMLTest("Attribute: uint64_t", (int)XML_SUCCESS, queryResult, true);
880                 XMLTest("Attribute: uint64_t", BIG_POS, v, true);
881             }
882             XMLTest("Attribute: uint64_t", BIG_POS, element->Unsigned64Attribute("attrib"), true);
883         }
884         {
885 			element->SetAttribute("attrib", true);
886 			{
887 				bool v = false;
888 				XMLError queryResult = element->QueryBoolAttribute("attrib", &v);
889 				XMLTest("Attribute: bool", XML_SUCCESS, queryResult, true);
890 				XMLTest("Attribute: bool", true, v, true);
891 			}
892 			{
893 				bool v = false;
894 				int queryResult = element->QueryAttribute("attrib", &v);
895 				XMLTest("Attribute: bool", (int)XML_SUCCESS, queryResult, true);
896 				XMLTest("Attribute: bool", true, v, true);
897 			}
898 			XMLTest("Attribute: bool", true, element->BoolAttribute("attrib"), true);
899 		}
900 		{
901 			element->SetAttribute("attrib", true);
902 			const char* result = element->Attribute("attrib");
903 			XMLTest("Bool true is 'true'", "true", result);
904 
905 			XMLUtil::SetBoolSerialization("1", "0");
906 			element->SetAttribute("attrib", true);
907 			result = element->Attribute("attrib");
908 			XMLTest("Bool true is '1'", "1", result);
909 
910 			XMLUtil::SetBoolSerialization(0, 0);
911 		}
912 		{
913 			element->SetAttribute("attrib", 100.0);
914 			{
915 				double v = 0;
916 				XMLError queryResult = element->QueryDoubleAttribute("attrib", &v);
917 				XMLTest("Attribute: double", XML_SUCCESS, queryResult, true);
918 				XMLTest("Attribute: double", 100.0, v, true);
919 			}
920 			{
921 				double v = 0;
922 				int queryResult = element->QueryAttribute("attrib", &v);
923 				XMLTest("Attribute: bool", (int)XML_SUCCESS, queryResult, true);
924 				XMLTest("Attribute: double", 100.0, v, true);
925 			}
926 			XMLTest("Attribute: double", 100.0, element->DoubleAttribute("attrib"), true);
927 		}
928 		{
929 			element->SetAttribute("attrib", 100.0f);
930 			{
931 				float v = 0;
932 				XMLError queryResult = element->QueryFloatAttribute("attrib", &v);
933 				XMLTest("Attribute: float", XML_SUCCESS, queryResult, true);
934 				XMLTest("Attribute: float", 100.0f, v, true);
935 			}
936 			{
937 				float v = 0;
938 				int queryResult = element->QueryAttribute("attrib", &v);
939 				XMLTest("Attribute: float", (int)XML_SUCCESS, queryResult, true);
940 				XMLTest("Attribute: float", 100.0f, v, true);
941 			}
942 			XMLTest("Attribute: float", 100.0f, element->FloatAttribute("attrib"), true);
943 		}
944 		{
945 			element->SetText(BIG);
946 			int64_t v = 0;
947 			XMLError queryResult = element->QueryInt64Text(&v);
948 			XMLTest("Element: int64_t", XML_SUCCESS, queryResult, true);
949 			XMLTest("Element: int64_t", BIG, v, true);
950 		}
951         {
952             element->SetText(BIG_POS);
953             uint64_t v = 0;
954             XMLError queryResult = element->QueryUnsigned64Text(&v);
955             XMLTest("Element: uint64_t", XML_SUCCESS, queryResult, true);
956             XMLTest("Element: uint64_t", BIG_POS, v, true);
957         }
958     }
959 
960 	// ---------- XMLPrinter stream mode ------
961 	{
962 		{
963 			FILE* printerfp = fopen("resources/out/printer.xml", "w");
964 			XMLTest("Open printer.xml", true, printerfp != 0);
965 			XMLPrinter printer(printerfp);
966 			printer.OpenElement("foo");
967 			printer.PushAttribute("attrib-text", "text");
968 			printer.PushAttribute("attrib-int", int(1));
969 			printer.PushAttribute("attrib-unsigned", unsigned(2));
970 			printer.PushAttribute("attrib-int64", int64_t(3));
971 			printer.PushAttribute("attrib-uint64", uint64_t(37));
972 			printer.PushAttribute("attrib-bool", true);
973 			printer.PushAttribute("attrib-double", 4.0);
974 			printer.CloseElement();
975 			fclose(printerfp);
976 		}
977 		{
978 			XMLDocument doc;
979 			doc.LoadFile("resources/out/printer.xml");
980 			XMLTest("XMLPrinter Stream mode: load", XML_SUCCESS, doc.ErrorID(), true);
981 
982 			const XMLDocument& cdoc = doc;
983 
984 			const XMLAttribute* attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-text");
985 			XMLTest("attrib-text", "text", attrib->Value(), true);
986 			attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int");
987 			XMLTest("attrib-int", int(1), attrib->IntValue(), true);
988 			attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-unsigned");
989 			XMLTest("attrib-unsigned", unsigned(2), attrib->UnsignedValue(), true);
990 			attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int64");
991 			XMLTest("attrib-int64", int64_t(3), attrib->Int64Value(), true);
992 			attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-uint64");
993 			XMLTest("attrib-uint64", uint64_t(37), attrib->Unsigned64Value(), true);
994 			attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-bool");
995 			XMLTest("attrib-bool", true, attrib->BoolValue(), true);
996 			attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-double");
997 			XMLTest("attrib-double", 4.0, attrib->DoubleValue(), true);
998 		}
999 		// Add API_testcatse :PushDeclaration();PushText();PushComment()
1000 		{
1001 			FILE* fp1 = fopen("resources/out/printer_1.xml", "w");
1002 			XMLPrinter printer(fp1);
1003 
1004 			printer.PushDeclaration("version = '1.0' enconding = 'utf-8'");
1005 
1006 			printer.OpenElement("foo");
1007 			printer.PushAttribute("attrib-text", "text");
1008 
1009 			printer.OpenElement("text");
1010 			printer.PushText("Tinyxml2");
1011 			printer.CloseElement();
1012 
1013 			printer.OpenElement("int");
1014 			printer.PushText(int(11));
1015 			printer.CloseElement();
1016 
1017 			printer.OpenElement("unsigned");
1018 			printer.PushText(unsigned(12));
1019 			printer.CloseElement();
1020 
1021 			printer.OpenElement("int64_t");
1022 			printer.PushText(int64_t(13));
1023 			printer.CloseElement();
1024 
1025 			printer.OpenElement("uint64_t");
1026 			printer.PushText(uint64_t(14));
1027 			printer.CloseElement();
1028 
1029 			printer.OpenElement("bool");
1030 			printer.PushText(true);
1031 			printer.CloseElement();
1032 
1033 			printer.OpenElement("float");
1034 			printer.PushText("1.56");
1035 			printer.CloseElement();
1036 
1037 			printer.OpenElement("double");
1038 			printer.PushText("12.12");
1039 			printer.CloseElement();
1040 
1041 			printer.OpenElement("comment");
1042 			printer.PushComment("this is Tinyxml2");
1043 			printer.CloseElement();
1044 
1045 			printer.CloseElement();
1046 			fclose(fp1);
1047 		}
1048 		{
1049 			XMLDocument doc;
1050 			doc.LoadFile("resources/out/printer_1.xml");
1051 			XMLTest("XMLPrinter Stream mode: load", XML_SUCCESS, doc.ErrorID(), true);
1052 
1053 			const XMLDocument& cdoc = doc;
1054 
1055 			const  XMLElement* root = cdoc.FirstChildElement("foo");
1056 
1057 			const char* text_value;
1058 			text_value = root->FirstChildElement("text")->GetText();
1059 			XMLTest("PushText( const char* text, bool cdata=false ) test", "Tinyxml2", text_value);
1060 
1061 			int  int_value;
1062 			int_value = root->FirstChildElement("int")->IntText();
1063 			XMLTest("PushText( int value ) test", 11, int_value);
1064 
1065 			unsigned  unsigned_value;
1066 			unsigned_value = root->FirstChildElement("unsigned")->UnsignedText();
1067 			XMLTest("PushText( unsigned value ) test", (unsigned)12, unsigned_value);
1068 
1069 			int64_t  int64_t_value;
1070 			int64_t_value = root->FirstChildElement("int64_t")->Int64Text();
1071 			XMLTest("PushText( int64_t value ) test", (int64_t) 13, int64_t_value);
1072 
1073 			uint64_t uint64_t_value;
1074 			uint64_t_value = root->FirstChildElement("uint64_t")->Unsigned64Text();
1075 			XMLTest("PushText( uint64_t value ) test", (uint64_t) 14, uint64_t_value);
1076 
1077 			float  float_value;
1078 			float_value = root->FirstChildElement("float")->FloatText();
1079 			XMLTest("PushText( float value ) test", 1.56f, float_value);
1080 
1081 			double double_value;
1082 			double_value = root->FirstChildElement("double")->DoubleText();
1083 			XMLTest("PushText( double value ) test", 12.12, double_value);
1084 
1085 			bool bool_value;
1086 			bool_value = root->FirstChildElement("bool")->BoolText();
1087 			XMLTest("PushText( bool value ) test", true, bool_value);
1088 
1089 			const XMLComment* comment = root->FirstChildElement("comment")->FirstChild()->ToComment();
1090 			const char* comment_value = comment->Value();
1091 			XMLTest("PushComment() test", "this is Tinyxml2", comment_value);
1092 
1093 			const XMLDeclaration* declaration = cdoc.FirstChild()->ToDeclaration();
1094 			const char* declaration_value = declaration->Value();
1095 			XMLTest("PushDeclaration() test", "version = '1.0' enconding = 'utf-8'", declaration_value);
1096 		}
1097 	}
1098 
1099 
1100 	// ---------- CDATA ---------------
1101 	{
1102 		const char* str =	"<xmlElement>"
1103 								"<![CDATA["
1104 									"I am > the rules!\n"
1105 									"...since I make symbolic puns"
1106 								"]]>"
1107 							"</xmlElement>";
1108 		XMLDocument doc;
1109 		doc.Parse( str );
1110 		XMLTest( "CDATA symbolic puns round 1", false, doc.Error() );
1111 		doc.Print();
1112 
1113 		XMLTest( "CDATA parse.", "I am > the rules!\n...since I make symbolic puns",
1114 								 doc.FirstChildElement()->FirstChild()->Value(),
1115 								 false );
1116 	}
1117 
1118 	// ----------- CDATA -------------
1119 	{
1120 		const char* str =	"<xmlElement>"
1121 								"<![CDATA["
1122 									"<b>I am > the rules!</b>\n"
1123 									"...since I make symbolic puns"
1124 								"]]>"
1125 							"</xmlElement>";
1126 		XMLDocument doc;
1127 		doc.Parse( str );
1128 		XMLTest( "CDATA symbolic puns round 2", false, doc.Error() );
1129 		doc.Print();
1130 
1131 		XMLTest( "CDATA parse. [ tixml1:1480107 ]",
1132 								 "<b>I am > the rules!</b>\n...since I make symbolic puns",
1133 								 doc.FirstChildElement()->FirstChild()->Value(),
1134 								 false );
1135 	}
1136 
1137 	// InsertAfterChild causes crash.
1138 	{
1139 		// InsertBeforeChild and InsertAfterChild causes crash.
1140 		XMLDocument doc;
1141 		XMLElement* parent = doc.NewElement( "Parent" );
1142 		doc.InsertFirstChild( parent );
1143 
1144 		XMLElement* childText0 = doc.NewElement( "childText0" );
1145 		XMLElement* childText1 = doc.NewElement( "childText1" );
1146 
1147 		XMLNode* childNode0 = parent->InsertEndChild( childText0 );
1148 		XMLTest( "InsertEndChild() return", true, childNode0 == childText0 );
1149 		XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 );
1150 		XMLTest( "InsertAfterChild() return", true, childNode1 == childText1 );
1151 
1152 		XMLTest( "Test InsertAfterChild on empty node. ", true, ( childNode1 == parent->LastChild() ) );
1153 	}
1154 
1155 	{
1156 		// Entities not being written correctly.
1157 		// From Lynn Allen
1158 
1159 		const char* passages =
1160 			"<?xml version=\"1.0\" standalone=\"no\" ?>"
1161 			"<passages count=\"006\" formatversion=\"20020620\">"
1162 				"<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
1163 				" It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
1164 			"</passages>";
1165 
1166 		XMLDocument doc;
1167 		doc.Parse( passages );
1168 		XMLTest( "Entity transformation parse round 1", false, doc.Error() );
1169 		XMLElement* psg = doc.RootElement()->FirstChildElement();
1170 		const char* context = psg->Attribute( "context" );
1171 		const char* expected = "Line 5 has \"quotation marks\" and 'apostrophe marks'. It also has <, >, and &, as well as a fake copyright \xC2\xA9.";
1172 
1173 		XMLTest( "Entity transformation: read. ", expected, context, true );
1174 
1175 		const char* textFilePath = "resources/out/textfile.txt";
1176 		FILE* textfile = fopen( textFilePath, "w" );
1177 		XMLTest( "Entity transformation: open text file for writing", true, textfile != 0, true );
1178 		if ( textfile )
1179 		{
1180 			XMLPrinter streamer( textfile );
1181 			bool acceptResult = psg->Accept( &streamer );
1182 			fclose( textfile );
1183 			XMLTest( "Entity transformation: Accept", true, acceptResult );
1184 		}
1185 
1186 		textfile = fopen( textFilePath, "r" );
1187 		XMLTest( "Entity transformation: open text file for reading", true, textfile != 0, true );
1188 		if ( textfile )
1189 		{
1190 			char buf[ 1024 ];
1191 			fgets( buf, 1024, textfile );
1192 			XMLTest( "Entity transformation: write. ",
1193 					 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
1194 					 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.\"/>\n",
1195 					 buf, false );
1196 			fclose( textfile );
1197 		}
1198 	}
1199 
1200 	{
1201 		// Suppress entities.
1202 		const char* passages =
1203 			"<?xml version=\"1.0\" standalone=\"no\" ?>"
1204 			"<passages count=\"006\" formatversion=\"20020620\">"
1205 				"<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
1206 			"</passages>";
1207 
1208 		XMLDocument doc( false );
1209 		doc.Parse( passages );
1210 		XMLTest( "Entity transformation parse round 2", false, doc.Error() );
1211 
1212 		XMLTest( "No entity parsing.",
1213 				 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.",
1214 				 doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ) );
1215 		XMLTest( "No entity parsing.", "Crazy &ttk;",
1216 				 doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value() );
1217 		doc.Print();
1218 	}
1219 
1220 	{
1221 		const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
1222 
1223 		XMLDocument doc;
1224 		doc.Parse( test );
1225 		XMLTest( "dot in names", false, doc.Error() );
1226 		XMLTest( "dot in names", "a.elem", doc.FirstChildElement()->Name() );
1227 		XMLTest( "dot in names", "2.0", doc.FirstChildElement()->Attribute( "xmi.version" ) );
1228 	}
1229 
1230 	{
1231 		const char* test = "<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>";
1232 
1233 		XMLDocument doc;
1234 		doc.Parse( test );
1235 		XMLTest( "fin thickness", false, doc.Error() );
1236 
1237 		XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
1238 		XMLTest( "Entity with one digit.",
1239 				 "1.1 Start easy ignore fin thickness\n", text->Value(),
1240 				 false );
1241 	}
1242 
1243 	{
1244 		// DOCTYPE not preserved (950171)
1245 		//
1246 		const char* doctype =
1247 			"<?xml version=\"1.0\" ?>"
1248 			"<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
1249 			"<!ELEMENT title (#PCDATA)>"
1250 			"<!ELEMENT books (title,authors)>"
1251 			"<element />";
1252 
1253 		XMLDocument doc;
1254 		doc.Parse( doctype );
1255 		XMLTest( "PLAY SYSTEM parse", false, doc.Error() );
1256 		doc.SaveFile( "resources/out/test7.xml" );
1257 		XMLTest( "PLAY SYSTEM save", false, doc.Error() );
1258 		doc.DeleteChild( doc.RootElement() );
1259 		doc.LoadFile( "resources/out/test7.xml" );
1260 		XMLTest( "PLAY SYSTEM load", false, doc.Error() );
1261 		doc.Print();
1262 
1263 		const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown();
1264 		XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() );
1265 
1266 	}
1267 
1268 	{
1269 		// Comments do not stream out correctly.
1270 		const char* doctype =
1271 			"<!-- Somewhat<evil> -->";
1272 		XMLDocument doc;
1273 		doc.Parse( doctype );
1274 		XMLTest( "Comment somewhat evil", false, doc.Error() );
1275 
1276 		XMLComment* comment = doc.FirstChild()->ToComment();
1277 
1278 		XMLTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
1279 	}
1280 	{
1281 		// Double attributes
1282 		const char* doctype = "<element attr='red' attr='blue' />";
1283 
1284 		XMLDocument doc;
1285 		doc.Parse( doctype );
1286 
1287 		XMLTest( "Parsing repeated attributes.", XML_ERROR_PARSING_ATTRIBUTE, doc.ErrorID() );	// is an  error to tinyxml (didn't use to be, but caused issues)
1288 		doc.PrintError();
1289 	}
1290 
1291 	{
1292 		// Embedded null in stream.
1293 		const char* doctype = "<element att\0r='red' attr='blue' />";
1294 
1295 		XMLDocument doc;
1296 		doc.Parse( doctype );
1297 		XMLTest( "Embedded null throws error.", true, doc.Error() );
1298 	}
1299 
1300 	{
1301 		// Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
1302 		const char* str = "";
1303 		XMLDocument doc;
1304 		doc.Parse( str );
1305 		XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
1306 
1307 		// But be sure there is an error string!
1308 		const char* errorStr = doc.ErrorStr();
1309 		XMLTest("Error string should be set",
1310 			"Error=XML_ERROR_EMPTY_DOCUMENT ErrorID=13 (0xd) Line number=0",
1311 			errorStr);
1312 	}
1313 
1314 	{
1315 		// Documents with all whitespaces should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
1316 		const char* str = "    ";
1317 		XMLDocument doc;
1318 		doc.Parse( str );
1319 		XMLTest( "All whitespaces document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
1320 	}
1321 
1322 	{
1323 		// Low entities
1324 		XMLDocument doc;
1325 		doc.Parse( "<test>&#x0e;</test>" );
1326 		XMLTest( "Hex values", false, doc.Error() );
1327 		const char result[] = { 0x0e, 0 };
1328 		XMLTest( "Low entities.", result, doc.FirstChildElement()->GetText() );
1329 		doc.Print();
1330 	}
1331 
1332 	{
1333 		// Attribute values with trailing quotes not handled correctly
1334 		XMLDocument doc;
1335 		doc.Parse( "<foo attribute=bar\" />" );
1336 		XMLTest( "Throw error with bad end quotes.", true, doc.Error() );
1337 	}
1338 
1339 	{
1340 		// [ 1663758 ] Failure to report error on bad XML
1341 		XMLDocument xml;
1342 		xml.Parse("<x>");
1343 		XMLTest("Missing end tag at end of input", true, xml.Error());
1344 		xml.Parse("<x> ");
1345 		XMLTest("Missing end tag with trailing whitespace", true, xml.Error());
1346 		xml.Parse("<x></y>");
1347 		XMLTest("Mismatched tags", XML_ERROR_MISMATCHED_ELEMENT, xml.ErrorID() );
1348 	}
1349 
1350 
1351 	{
1352 		// [ 1475201 ] TinyXML parses entities in comments
1353 		XMLDocument xml;
1354 		xml.Parse("<!-- declarations for <head> & <body> -->"
1355 				  "<!-- far &amp; away -->" );
1356 		XMLTest( "Declarations for head and body", false, xml.Error() );
1357 
1358 		XMLNode* e0 = xml.FirstChild();
1359 		XMLNode* e1 = e0->NextSibling();
1360 		XMLComment* c0 = e0->ToComment();
1361 		XMLComment* c1 = e1->ToComment();
1362 
1363 		XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
1364 		XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
1365 	}
1366 
1367 	{
1368 		XMLDocument xml;
1369 		xml.Parse( "<Parent>"
1370 						"<child1 att=''/>"
1371 						"<!-- With this comment, child2 will not be parsed! -->"
1372 						"<child2 att=''/>"
1373 					"</Parent>" );
1374 		XMLTest( "Comments iteration", false, xml.Error() );
1375 		xml.Print();
1376 
1377 		int count = 0;
1378 
1379 		for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
1380 			 ele;
1381 			 ele = ele->NextSibling() )
1382 		{
1383 			++count;
1384 		}
1385 
1386 		XMLTest( "Comments iterate correctly.", 3, count );
1387 	}
1388 
1389 	{
1390 		// trying to repro [1874301]. If it doesn't go into an infinite loop, all is well.
1391 		unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
1392 		buf[60] = 239;
1393 		buf[61] = 0;
1394 
1395 		XMLDocument doc;
1396 		doc.Parse( (const char*)buf);
1397 		XMLTest( "Broken CDATA", true, doc.Error() );
1398 	}
1399 
1400 
1401 	{
1402 		// bug 1827248 Error while parsing a little bit malformed file
1403 		// Actually not malformed - should work.
1404 		XMLDocument xml;
1405 		xml.Parse( "<attributelist> </attributelist >" );
1406 		XMLTest( "Handle end tag whitespace", false, xml.Error() );
1407 	}
1408 
1409 	{
1410 		// This one must not result in an infinite loop
1411 		XMLDocument xml;
1412 		xml.Parse( "<infinite>loop" );
1413 		XMLTest( "No closing element", true, xml.Error() );
1414 		XMLTest( "Infinite loop test.", true, true );
1415 	}
1416 #endif
1417 	{
1418 		const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
1419 		XMLDocument doc;
1420 		doc.Parse( pub );
1421 		XMLTest( "Trailing DOCTYPE", false, doc.Error() );
1422 
1423 		XMLDocument clone;
1424 		for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
1425 			XMLNode* copy = node->ShallowClone( &clone );
1426 			clone.InsertEndChild( copy );
1427 		}
1428 
1429 		clone.Print();
1430 
1431 		int count=0;
1432 		const XMLNode* a=clone.FirstChild();
1433 		const XMLNode* b=doc.FirstChild();
1434 		for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
1435 			++count;
1436 			XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
1437 		}
1438 		XMLTest( "Clone and Equal", 4, count );
1439 	}
1440 
1441 	{
1442 		// Deep Cloning of root element.
1443 		XMLDocument doc2;
1444 		XMLPrinter printer1;
1445 		{
1446 			// Make sure doc1 is deleted before we test doc2
1447 			const char* xml =
1448 				"<root>"
1449 				"    <child1 foo='bar'/>"
1450 				"    <!-- comment thing -->"
1451 				"    <child2 val='1'>Text</child2>"
1452 				"</root>";
1453 			XMLDocument doc;
1454 			doc.Parse(xml);
1455 			XMLTest( "Parse before deep cloning root element", false, doc.Error() );
1456 
1457 			doc.Print(&printer1);
1458 			XMLNode* root = doc.RootElement()->DeepClone(&doc2);
1459 			doc2.InsertFirstChild(root);
1460 		}
1461 		XMLPrinter printer2;
1462 		doc2.Print(&printer2);
1463 
1464 		XMLTest("Deep clone of element.", printer1.CStr(), printer2.CStr(), true);
1465 	}
1466 
1467 	{
1468 		// Deep Cloning of sub element.
1469 		XMLDocument doc2;
1470 		XMLPrinter printer1;
1471 		{
1472 			// Make sure doc1 is deleted before we test doc2
1473 			const char* xml =
1474 				"<?xml version ='1.0'?>"
1475 				"<root>"
1476 				"    <child1 foo='bar'/>"
1477 				"    <!-- comment thing -->"
1478 				"    <child2 val='1'>Text</child2>"
1479 				"</root>";
1480 			XMLDocument doc;
1481 			doc.Parse(xml);
1482 			XMLTest( "Parse before deep cloning sub element", false, doc.Error() );
1483 
1484 			const XMLElement* subElement = doc.FirstChildElement("root")->FirstChildElement("child2");
1485 			bool acceptResult = subElement->Accept(&printer1);
1486 			XMLTest( "Accept before deep cloning", true, acceptResult );
1487 
1488 			XMLNode* clonedSubElement = subElement->DeepClone(&doc2);
1489 			doc2.InsertFirstChild(clonedSubElement);
1490 		}
1491 		XMLPrinter printer2;
1492 		doc2.Print(&printer2);
1493 
1494 		XMLTest("Deep clone of sub-element.", printer1.CStr(), printer2.CStr(), true);
1495 	}
1496 
1497 	{
1498 		// Deep cloning of document.
1499 		XMLDocument doc2;
1500 		XMLPrinter printer1;
1501 		{
1502 			// Make sure doc1 is deleted before we test doc2
1503 			const char* xml =
1504 				"<?xml version ='1.0'?>"
1505 				"<!-- Top level comment. -->"
1506 				"<root>"
1507 				"    <child1 foo='bar'/>"
1508 				"    <!-- comment thing -->"
1509 				"    <child2 val='1'>Text</child2>"
1510 				"</root>";
1511 			XMLDocument doc;
1512 			doc.Parse(xml);
1513 			XMLTest( "Parse before deep cloning document", false, doc.Error() );
1514 			doc.Print(&printer1);
1515 
1516 			doc.DeepCopy(&doc2);
1517 		}
1518 		XMLPrinter printer2;
1519 		doc2.Print(&printer2);
1520 
1521 		XMLTest("DeepCopy of document.", printer1.CStr(), printer2.CStr(), true);
1522 	}
1523 
1524 
1525  	{
1526 		// This shouldn't crash.
1527 		XMLDocument doc;
1528 		if(XML_SUCCESS != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
1529 		{
1530 			doc.PrintError();
1531 		}
1532 		XMLTest( "Error in snprinf handling.", true, doc.Error() );
1533 	}
1534 
1535 	{
1536 		// Attribute ordering.
1537 		static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
1538 		XMLDocument doc;
1539 		doc.Parse( xml );
1540 		XMLTest( "Parse for attribute ordering", false, doc.Error() );
1541 		XMLElement* ele = doc.FirstChildElement();
1542 
1543 		const XMLAttribute* a = ele->FirstAttribute();
1544 		XMLTest( "Attribute order", "1", a->Value() );
1545 		a = a->Next();
1546 		XMLTest( "Attribute order", "2", a->Value() );
1547 		a = a->Next();
1548 		XMLTest( "Attribute order", "3", a->Value() );
1549 		XMLTest( "Attribute order", "attrib3", a->Name() );
1550 
1551 		ele->DeleteAttribute( "attrib2" );
1552 		a = ele->FirstAttribute();
1553 		XMLTest( "Attribute order", "1", a->Value() );
1554 		a = a->Next();
1555 		XMLTest( "Attribute order", "3", a->Value() );
1556 
1557 		ele->DeleteAttribute( "attrib1" );
1558 		ele->DeleteAttribute( "attrib3" );
1559 		XMLTest( "Attribute order (empty)", true, ele->FirstAttribute() == 0 );
1560 	}
1561 
1562 	{
1563 		// Make sure an attribute with a space in it succeeds.
1564 		static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
1565 		static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
1566 		static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
1567 		XMLDocument doc0;
1568 		doc0.Parse( xml0 );
1569 		XMLTest( "Parse attribute with space 1", false, doc0.Error() );
1570 		XMLDocument doc1;
1571 		doc1.Parse( xml1 );
1572 		XMLTest( "Parse attribute with space 2", false, doc1.Error() );
1573 		XMLDocument doc2;
1574 		doc2.Parse( xml2 );
1575 		XMLTest( "Parse attribute with space 3", false, doc2.Error() );
1576 
1577 		XMLElement* ele = 0;
1578 		ele = doc0.FirstChildElement();
1579 		XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
1580 		ele = doc1.FirstChildElement();
1581 		XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
1582 		ele = doc2.FirstChildElement();
1583 		XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
1584 	}
1585 
1586 	{
1587 		// Make sure we don't go into an infinite loop.
1588 		static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
1589 		XMLDocument doc;
1590 		doc.Parse( xml );
1591 		XMLTest( "Parse two elements with attribute", false, doc.Error() );
1592 		XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
1593 		XMLElement* ele1 = ele0->NextSiblingElement();
1594 		bool equal = ele0->ShallowEqual( ele1 );
1595 
1596 		XMLTest( "Infinite loop in shallow equal.", true, equal );
1597 	}
1598 
1599 	// -------- Handles ------------
1600 	{
1601 		static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1602 		XMLDocument doc;
1603 		doc.Parse( xml );
1604 		XMLTest( "Handle, parse element with attribute and nested element", false, doc.Error() );
1605 
1606 		{
1607 			XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
1608 			XMLTest( "Handle, non-const, element is found", true, ele != 0 );
1609 			XMLTest( "Handle, non-const, element name matches", "sub", ele->Value() );
1610 		}
1611 
1612 		{
1613 			XMLHandle docH( doc );
1614 			XMLElement* ele = docH.FirstChildElement( "noSuchElement" ).FirstChildElement( "element" ).ToElement();
1615 			XMLTest( "Handle, non-const, element not found", true, ele == 0 );
1616 		}
1617 
1618 		{
1619 			const XMLElement* ele = XMLConstHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
1620 			XMLTest( "Handle, const, element is found", true, ele != 0 );
1621 			XMLTest( "Handle, const, element name matches", "sub", ele->Value() );
1622 		}
1623 
1624 		{
1625 			XMLConstHandle docH( doc );
1626 			const XMLElement* ele = docH.FirstChildElement( "noSuchElement" ).FirstChildElement( "element" ).ToElement();
1627 			XMLTest( "Handle, const, element not found", true, ele == 0 );
1628 		}
1629 	}
1630 	{
1631 		// Default Declaration & BOM
1632 		XMLDocument doc;
1633 		doc.InsertEndChild( doc.NewDeclaration() );
1634 		doc.SetBOM( true );
1635 
1636 		XMLPrinter printer;
1637 		doc.Print( &printer );
1638 
1639 		static const char* result  = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
1640 		XMLTest( "BOM and default declaration", result, printer.CStr(), false );
1641 		XMLTest( "CStrSize", 42, printer.CStrSize(), false );
1642 	}
1643 	{
1644 		const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
1645 		XMLDocument doc;
1646 		doc.Parse( xml );
1647 		XMLTest( "Ill formed XML", true, doc.Error() );
1648 	}
1649 
1650     {
1651         //API:IntText(),UnsignedText(),Int64Text(),DoubleText(),BoolText() and FloatText() test
1652         const char* xml = "<point> <IntText>-24</IntText> <UnsignedText>42</UnsignedText> \
1653 						   <Int64Text>38</Int64Text> <BoolText>true</BoolText> <DoubleText>2.35</DoubleText> </point>";
1654         XMLDocument doc;
1655         doc.Parse(xml);
1656 
1657         const XMLElement* pointElement = doc.RootElement();
1658         int test1 = pointElement->FirstChildElement("IntText")->IntText();
1659         XMLTest("IntText() test", -24, test1);
1660 
1661         unsigned test2 = pointElement->FirstChildElement("UnsignedText")->UnsignedText();
1662         XMLTest("UnsignedText() test", static_cast<unsigned>(42), test2);
1663 
1664         int64_t test3 = pointElement->FirstChildElement("Int64Text")->Int64Text();
1665         XMLTest("Int64Text() test", static_cast<int64_t>(38), test3);
1666 
1667         double test4 = pointElement->FirstChildElement("DoubleText")->DoubleText();
1668         XMLTest("DoubleText() test", 2.35, test4);
1669 
1670         float test5 = pointElement->FirstChildElement("DoubleText")->FloatText();
1671         XMLTest("FloatText()) test", 2.35f, test5);
1672 
1673         bool test6 = pointElement->FirstChildElement("BoolText")->BoolText();
1674         XMLTest("FloatText()) test", true, test6);
1675     }
1676 
1677 	{
1678 		//API:ShallowEqual() test
1679 		const char* xml = "<playlist id = 'playlist'>"
1680 						    "<property name = 'track_name'>voice</property>"
1681 						  "</playlist>";
1682 		XMLDocument doc;
1683 		doc.Parse( xml );
1684 		const XMLNode* PlaylistNode = doc.RootElement();
1685 		const XMLNode* PropertyNode = PlaylistNode->FirstChildElement();
1686 		bool result;
1687 		result = PlaylistNode->ShallowEqual(PropertyNode);
1688 		XMLTest("ShallowEqual() test",false,result);
1689 		result = PlaylistNode->ShallowEqual(PlaylistNode);
1690 		XMLTest("ShallowEqual() test",true,result);
1691 	}
1692 
1693 	{
1694 		//API: previousSiblingElement() and NextSiblingElement() test
1695 		const char* xml = "<playlist id = 'playlist'>"
1696 						    "<property name = 'track_name'>voice</property>"
1697 						    "<entry out = '946' producer = '2_playlist1' in = '0'/>"
1698 							"<blank length = '1'/>"
1699 						  "</playlist>";
1700 		XMLDocument doc;
1701 		doc.Parse( xml );
1702 		XMLElement* ElementPlaylist = doc.FirstChildElement("playlist");
1703 		XMLTest("previousSiblingElement() test",true,ElementPlaylist != 0);
1704 		const XMLElement* pre = ElementPlaylist->PreviousSiblingElement();
1705 		XMLTest("previousSiblingElement() test",true,pre == 0);
1706 		const XMLElement* ElementBlank = ElementPlaylist->FirstChildElement("entry")->NextSiblingElement("blank");
1707 		XMLTest("NextSiblingElement() test",true,ElementBlank != 0);
1708 		const XMLElement* next = ElementBlank->NextSiblingElement();
1709 		XMLTest("NextSiblingElement() test",true,next == 0);
1710 		const XMLElement* ElementEntry = ElementBlank->PreviousSiblingElement("entry");
1711 		XMLTest("PreviousSiblingElement test",true,ElementEntry != 0);
1712 	}
1713 
1714 	// QueryXYZText
1715 	{
1716 		const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
1717 		XMLDocument doc;
1718 		doc.Parse( xml );
1719 		XMLTest( "Parse points", false, doc.Error() );
1720 
1721 		const XMLElement* pointElement = doc.RootElement();
1722 
1723 		{
1724 			int intValue = 0;
1725 			XMLError queryResult = pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
1726 			XMLTest( "QueryIntText result", XML_SUCCESS, queryResult, false );
1727 			XMLTest( "QueryIntText", 1, intValue, false );
1728 		}
1729 
1730 		{
1731 			unsigned unsignedValue = 0;
1732 			XMLError queryResult = pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
1733 			XMLTest( "QueryUnsignedText result", XML_SUCCESS, queryResult, false );
1734 			XMLTest( "QueryUnsignedText", (unsigned)1, unsignedValue, false );
1735 		}
1736 
1737 		{
1738 			float floatValue = 0;
1739 			XMLError queryResult = pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
1740 			XMLTest( "QueryFloatText result", XML_SUCCESS, queryResult, false );
1741 			XMLTest( "QueryFloatText", 1.2f, floatValue, false );
1742 		}
1743 
1744 		{
1745 			double doubleValue = 0;
1746 			XMLError queryResult = pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
1747 			XMLTest( "QueryDoubleText result", XML_SUCCESS, queryResult, false );
1748 			XMLTest( "QueryDoubleText", 1.2, doubleValue, false );
1749 		}
1750 
1751 		{
1752 			bool boolValue = false;
1753 			XMLError queryResult = pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
1754 			XMLTest( "QueryBoolText result", XML_SUCCESS, queryResult, false );
1755 			XMLTest( "QueryBoolText", true, boolValue, false );
1756 		}
1757 	}
1758 
1759 	{
1760 		const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
1761 		XMLDocument doc;
1762 		doc.Parse( xml );
1763 		XMLTest( "Non-alpha element lead letter parses.", false, doc.Error() );
1764 	}
1765 
1766     {
1767         const char* xml = "<element _attr1=\"foo\" :attr2=\"bar\"></element>";
1768         XMLDocument doc;
1769         doc.Parse( xml );
1770         XMLTest("Non-alpha attribute lead character parses.", false, doc.Error());
1771     }
1772 
1773     {
1774         const char* xml = "<3lement></3lement>";
1775         XMLDocument doc;
1776         doc.Parse( xml );
1777         XMLTest("Element names with lead digit fail to parse.", true, doc.Error());
1778     }
1779 
1780 	{
1781 		const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
1782 		XMLDocument doc;
1783 		doc.Parse( xml, 10 );
1784 		XMLTest( "Set length of incoming data", false, doc.Error() );
1785 	}
1786 
1787     {
1788         XMLDocument doc;
1789         XMLTest( "Document is initially empty", true, doc.NoChildren() );
1790         doc.Clear();
1791         XMLTest( "Empty is empty after Clear()", true, doc.NoChildren() );
1792         doc.LoadFile( "resources/dream.xml" );
1793         XMLTest( "Load dream.xml", false, doc.Error() );
1794         XMLTest( "Document has something to Clear()", false, doc.NoChildren() );
1795         doc.Clear();
1796         XMLTest( "Document Clear()'s", true, doc.NoChildren() );
1797     }
1798 
1799     {
1800         XMLDocument doc;
1801         XMLTest( "No error initially", false, doc.Error() );
1802         XMLError error = doc.Parse( "This is not XML" );
1803         XMLTest( "Error after invalid XML", true, doc.Error() );
1804         XMLTest( "Error after invalid XML", error, doc.ErrorID() );
1805         doc.Clear();
1806         XMLTest( "No error after Clear()", false, doc.Error() );
1807     }
1808 
1809 	// ----------- Whitespace ------------
1810 	{
1811 		const char* xml = "<element>"
1812 							"<a> This \nis &apos;  text  &apos; </a>"
1813 							"<b>  This is &apos; text &apos;  \n</b>"
1814 							"<c>This  is  &apos;  \n\n text &apos;</c>"
1815 						  "</element>";
1816 		XMLDocument doc( true, COLLAPSE_WHITESPACE );
1817 		doc.Parse( xml );
1818 		XMLTest( "Parse with whitespace collapsing and &apos", false, doc.Error() );
1819 
1820 		const XMLElement* element = doc.FirstChildElement();
1821 		for( const XMLElement* parent = element->FirstChildElement();
1822 			 parent;
1823 			 parent = parent->NextSiblingElement() )
1824 		{
1825 			XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
1826 		}
1827 	}
1828 
1829 #if 0
1830 	{
1831 		// Passes if assert doesn't fire.
1832 		XMLDocument xmlDoc;
1833 
1834 	    xmlDoc.NewDeclaration();
1835 	    xmlDoc.NewComment("Configuration file");
1836 
1837 	    XMLElement *root = xmlDoc.NewElement("settings");
1838 	    root->SetAttribute("version", 2);
1839 	}
1840 #endif
1841 
1842 	{
1843 		const char* xml = "<element>    </element>";
1844 		XMLDocument doc( true, COLLAPSE_WHITESPACE );
1845 		doc.Parse( xml );
1846 		XMLTest( "Parse with all whitespaces", false, doc.Error() );
1847 		XMLTest( "Whitespace  all space", true, 0 == doc.FirstChildElement()->FirstChild() );
1848 	}
1849 
1850 	{
1851 		// An assert should not fire.
1852 		const char* xml = "<element/>";
1853 		XMLDocument doc;
1854 		doc.Parse( xml );
1855 		XMLTest( "Parse with self-closed element", false, doc.Error() );
1856 		XMLElement* ele = doc.NewElement( "unused" );		// This will get cleaned up with the 'doc' going out of scope.
1857 		XMLTest( "Tracking unused elements", true, ele != 0, false );
1858 	}
1859 
1860 
1861 	{
1862 		const char* xml = "<parent><child>abc</child></parent>";
1863 		XMLDocument doc;
1864 		doc.Parse( xml );
1865 		XMLTest( "Parse for printing of sub-element", false, doc.Error() );
1866 		XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child");
1867 
1868 		XMLPrinter printer;
1869 		bool acceptResult = ele->Accept( &printer );
1870 		XMLTest( "Accept of sub-element", true, acceptResult );
1871 		XMLTest( "Printing of sub-element", "<child>abc</child>\n", printer.CStr(), false );
1872 	}
1873 
1874 
1875 	{
1876 		XMLDocument doc;
1877 		XMLError error = doc.LoadFile( "resources/empty.xml" );
1878 		XMLTest( "Loading an empty file", XML_ERROR_EMPTY_DOCUMENT, error );
1879 		XMLTest( "Loading an empty file and ErrorName as string", "XML_ERROR_EMPTY_DOCUMENT", doc.ErrorName() );
1880 		doc.PrintError();
1881 	}
1882 
1883 	{
1884         // BOM preservation
1885         static const char* xml_bom_preservation  = "\xef\xbb\xbf<element/>\n";
1886         {
1887 			XMLDocument doc;
1888 			XMLTest( "BOM preservation (parse)", XML_SUCCESS, doc.Parse( xml_bom_preservation ), false );
1889             XMLPrinter printer;
1890             doc.Print( &printer );
1891 
1892             XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1893 			doc.SaveFile( "resources/out/bomtest.xml" );
1894 			XMLTest( "Save bomtest.xml", false, doc.Error() );
1895         }
1896 		{
1897 			XMLDocument doc;
1898 			doc.LoadFile( "resources/out/bomtest.xml" );
1899 			XMLTest( "Load bomtest.xml", false, doc.Error() );
1900 			XMLTest( "BOM preservation (load)", true, doc.HasBOM(), false );
1901 
1902             XMLPrinter printer;
1903             doc.Print( &printer );
1904             XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1905 		}
1906 	}
1907 
1908 	{
1909 		// Insertion with Removal
1910 		const char* xml = "<?xml version=\"1.0\" ?>"
1911 			"<root>"
1912 			"<one>"
1913 			"<subtree>"
1914 			"<elem>element 1</elem>text<!-- comment -->"
1915 			"</subtree>"
1916 			"</one>"
1917 			"<two/>"
1918 			"</root>";
1919 		const char* xmlInsideTwo = "<?xml version=\"1.0\" ?>"
1920 			"<root>"
1921 			"<one/>"
1922 			"<two>"
1923 			"<subtree>"
1924 			"<elem>element 1</elem>text<!-- comment -->"
1925 			"</subtree>"
1926 			"</two>"
1927 			"</root>";
1928 		const char* xmlAfterOne = "<?xml version=\"1.0\" ?>"
1929 			"<root>"
1930 			"<one/>"
1931 			"<subtree>"
1932 			"<elem>element 1</elem>text<!-- comment -->"
1933 			"</subtree>"
1934 			"<two/>"
1935 			"</root>";
1936 		const char* xmlAfterTwo = "<?xml version=\"1.0\" ?>"
1937 			"<root>"
1938 			"<one/>"
1939 			"<two/>"
1940 			"<subtree>"
1941 			"<elem>element 1</elem>text<!-- comment -->"
1942 			"</subtree>"
1943 			"</root>";
1944 
1945 		XMLDocument doc;
1946 		doc.Parse(xml);
1947 		XMLTest( "Insertion with removal parse round 1", false, doc.Error() );
1948 		XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1949 		XMLElement* two = doc.RootElement()->FirstChildElement("two");
1950 		two->InsertFirstChild(subtree);
1951 		XMLPrinter printer1(0, true);
1952 		bool acceptResult = doc.Accept(&printer1);
1953 		XMLTest("Move node from within <one> to <two> - Accept()", true, acceptResult);
1954 		XMLTest("Move node from within <one> to <two>", xmlInsideTwo, printer1.CStr());
1955 
1956 		doc.Parse(xml);
1957 		XMLTest( "Insertion with removal parse round 2", false, doc.Error() );
1958 		subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1959 		two = doc.RootElement()->FirstChildElement("two");
1960 		doc.RootElement()->InsertAfterChild(two, subtree);
1961 		XMLPrinter printer2(0, true);
1962 		acceptResult = doc.Accept(&printer2);
1963 		XMLTest("Move node from within <one> after <two> - Accept()", true, acceptResult);
1964 		XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer2.CStr(), false);
1965 
1966 		doc.Parse(xml);
1967 		XMLTest( "Insertion with removal parse round 3", false, doc.Error() );
1968 		XMLNode* one = doc.RootElement()->FirstChildElement("one");
1969 		subtree = one->FirstChildElement("subtree");
1970 		doc.RootElement()->InsertAfterChild(one, subtree);
1971 		XMLPrinter printer3(0, true);
1972 		acceptResult = doc.Accept(&printer3);
1973 		XMLTest("Move node from within <one> after <one> - Accept()", true, acceptResult);
1974 		XMLTest("Move node from within <one> after <one>", xmlAfterOne, printer3.CStr(), false);
1975 
1976 		doc.Parse(xml);
1977 		XMLTest( "Insertion with removal parse round 4", false, doc.Error() );
1978 		subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1979 		two = doc.RootElement()->FirstChildElement("two");
1980 		XMLTest("<two> is the last child at root level", true, two == doc.RootElement()->LastChildElement());
1981 		doc.RootElement()->InsertEndChild(subtree);
1982 		XMLPrinter printer4(0, true);
1983 		acceptResult = doc.Accept(&printer4);
1984 		XMLTest("Move node from within <one> after <two> - Accept()", true, acceptResult);
1985 		XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer4.CStr(), false);
1986 	}
1987 
1988 	{
1989 		const char* xml = "<svg width = \"128\" height = \"128\">"
1990 			"	<text> </text>"
1991 			"</svg>";
1992 		XMLDocument doc;
1993 		doc.Parse(xml);
1994 		XMLTest( "Parse svg with text", false, doc.Error() );
1995 		doc.Print();
1996 	}
1997 
1998 	{
1999 		// Test that it doesn't crash.
2000 		const char* xml = "<?xml version=\"1.0\"?><root><sample><field0><1</field0><field1>2</field1></sample></root>";
2001 		XMLDocument doc;
2002 		doc.Parse(xml);
2003 		XMLTest( "Parse root-sample-field0", true, doc.Error() );
2004 		doc.PrintError();
2005 	}
2006 
2007 #if 1
2008 		// the question being explored is what kind of print to use:
2009 		// https://github.com/leethomason/tinyxml2/issues/63
2010 	{
2011 		//const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9' attrC='1.0e-10' attrD='1001000000.000000' attrE='0.1234567890123456789'/>";
2012 		const char* xml = "<element/>";
2013 		XMLDocument doc;
2014 		doc.Parse( xml );
2015 		XMLTest( "Parse self-closed empty element", false, doc.Error() );
2016 		doc.FirstChildElement()->SetAttribute( "attrA-f64", 123456789.123456789 );
2017 		doc.FirstChildElement()->SetAttribute( "attrB-f64", 1.001e9 );
2018 		doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e9 );
2019 		doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e20 );
2020 		doc.FirstChildElement()->SetAttribute( "attrD-f64", 1.0e-10 );
2021 		doc.FirstChildElement()->SetAttribute( "attrD-f64", 0.123456789 );
2022 
2023 		doc.FirstChildElement()->SetAttribute( "attrA-f32", 123456789.123456789f );
2024 		doc.FirstChildElement()->SetAttribute( "attrB-f32", 1.001e9f );
2025 		doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e9f );
2026 		doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e20f );
2027 		doc.FirstChildElement()->SetAttribute( "attrD-f32", 1.0e-10f );
2028 		doc.FirstChildElement()->SetAttribute( "attrD-f32", 0.123456789f );
2029 
2030 		doc.Print();
2031 
2032 		/* The result of this test is platform, compiler, and library version dependent. :("
2033 		XMLPrinter printer;
2034 		doc.Print( &printer );
2035 		XMLTest( "Float and double formatting.",
2036 			"<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",
2037 			printer.CStr(),
2038 			true );
2039 		*/
2040 	}
2041 #endif
2042 
2043     {
2044         // Issue #184
2045         // If it doesn't assert, it passes. Caused by objects
2046         // getting created during parsing which are then
2047         // inaccessible in the memory pools.
2048         const char* xmlText = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>";
2049         {
2050             XMLDocument doc;
2051             doc.Parse(xmlText);
2052             XMLTest( "Parse hex no closing tag round 1", true, doc.Error() );
2053         }
2054         {
2055             XMLDocument doc;
2056             doc.Parse(xmlText);
2057             XMLTest( "Parse hex no closing tag round 2", true, doc.Error() );
2058             doc.Clear();
2059         }
2060     }
2061 
2062     {
2063         // If this doesn't assert in TINYXML2_DEBUG, all is well.
2064         tinyxml2::XMLDocument doc;
2065         tinyxml2::XMLElement *pRoot = doc.NewElement("Root");
2066         doc.DeleteNode(pRoot);
2067     }
2068 
2069     {
2070         XMLDocument doc;
2071         XMLElement* root = doc.NewElement( "Root" );
2072         XMLTest( "Node document before insertion", true, &doc == root->GetDocument() );
2073         doc.InsertEndChild( root );
2074         XMLTest( "Node document after insertion", true, &doc == root->GetDocument() );
2075     }
2076 
2077     {
2078         // If this doesn't assert in TINYXML2_DEBUG, all is well.
2079         XMLDocument doc;
2080         XMLElement* unlinkedRoot = doc.NewElement( "Root" );
2081         XMLElement* linkedRoot = doc.NewElement( "Root" );
2082         doc.InsertFirstChild( linkedRoot );
2083         unlinkedRoot->GetDocument()->DeleteNode( linkedRoot );
2084         unlinkedRoot->GetDocument()->DeleteNode( unlinkedRoot );
2085     }
2086 
2087 	{
2088 		// Should not assert in TINYXML2_DEBUG
2089 		XMLPrinter printer;
2090 	}
2091 
2092 	{
2093 		// Issue 291. Should not crash
2094 		const char* xml = "&#0</a>";
2095 		XMLDocument doc;
2096 		doc.Parse( xml );
2097 		XMLTest( "Parse hex with closing tag", false, doc.Error() );
2098 
2099 		XMLPrinter printer;
2100 		doc.Print( &printer );
2101 	}
2102 	{
2103 		// Issue 299. Can print elements that are not linked in.
2104 		// Will crash if issue not fixed.
2105 		XMLDocument doc;
2106 		XMLElement* newElement = doc.NewElement( "printme" );
2107 		XMLPrinter printer;
2108 		bool acceptResult = newElement->Accept( &printer );
2109 		XMLTest( "printme - Accept()", true, acceptResult );
2110 		// Delete the node to avoid possible memory leak report in debug output
2111 		doc.DeleteNode( newElement );
2112 	}
2113 	{
2114 		// Issue 302. Clear errors from LoadFile/SaveFile
2115 		XMLDocument doc;
2116 		XMLTest( "Issue 302. Should be no error initially", "XML_SUCCESS", doc.ErrorName() );
2117 		doc.SaveFile( "./no/such/path/pretty.xml" );
2118 		XMLTest( "Issue 302. Fail to save", "XML_ERROR_FILE_COULD_NOT_BE_OPENED", doc.ErrorName() );
2119 		doc.SaveFile( "./resources/out/compact.xml", true );
2120 		XMLTest( "Issue 302. Subsequent success in saving", "XML_SUCCESS", doc.ErrorName() );
2121 	}
2122 
2123 	{
2124 		// If a document fails to load then subsequent
2125 		// successful loads should clear the error
2126 		XMLDocument doc;
2127 		XMLTest( "Should be no error initially", false, doc.Error() );
2128 		doc.LoadFile( "resources/no-such-file.xml" );
2129 		XMLTest( "No such file - should fail", true, doc.Error() );
2130 
2131 		doc.LoadFile( "resources/dream.xml" );
2132 		XMLTest( "Error should be cleared", false, doc.Error() );
2133 	}
2134 
2135 	{
2136 		// Check that declarations are allowed only at beginning of document
2137 	    const char* xml0 = "<?xml version=\"1.0\" ?>"
2138 	                       "   <!-- xml version=\"1.1\" -->"
2139 	                       "<first />";
2140 	    const char* xml1 = "<?xml version=\"1.0\" ?>"
2141 	                       "<?xml-stylesheet type=\"text/xsl\" href=\"Anything.xsl\"?>"
2142 	                       "<first />";
2143 	    const char* xml2 = "<first />"
2144 	                       "<?xml version=\"1.0\" ?>";
2145 	    const char* xml3 = "<first></first>"
2146 	                       "<?xml version=\"1.0\" ?>";
2147 
2148 	    const char* xml4 = "<first><?xml version=\"1.0\" ?></first>";
2149 
2150 	    XMLDocument doc;
2151 	    doc.Parse(xml0);
2152 	    XMLTest("Test that the code changes do not affect normal parsing", false, doc.Error() );
2153 	    doc.Parse(xml1);
2154 	    XMLTest("Test that the second declaration is allowed", false, doc.Error() );
2155 	    doc.Parse(xml2);
2156 	    XMLTest("Test that declaration after self-closed child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );
2157 	    doc.Parse(xml3);
2158 	    XMLTest("Test that declaration after a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );
2159 	    doc.Parse(xml4);
2160 	    XMLTest("Test that declaration inside a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );
2161 	}
2162 
2163     {
2164 	    // No matter - before or after successfully parsing a text -
2165 	    // calling XMLDocument::Value() used to cause an assert in debug.
2166 	    // Null must be returned.
2167 	    const char* validXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
2168 	                           "<first />"
2169 	                           "<second />";
2170 	    XMLDocument* doc = new XMLDocument();
2171 	    XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
2172 	    doc->Parse( validXml );
2173 	    XMLTest( "Parse to test XMLDocument::Value()", false, doc->Error());
2174 	    XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
2175 	    delete doc;
2176     }
2177 
2178 	{
2179 		XMLDocument doc;
2180 		for( int i = 0; i < XML_ERROR_COUNT; i++ ) {
2181 			const XMLError error = static_cast<XMLError>(i);
2182 			const char* name = XMLDocument::ErrorIDToName(error);
2183 			XMLTest( "ErrorName() not null after ClearError()", true, name != 0 );
2184 			if( name == 0 ) {
2185 				// passing null pointer into strlen() is undefined behavior, so
2186 				// compiler is allowed to optimise away the null test above if it's
2187 				// as reachable as the strlen() call
2188 				continue;
2189 			}
2190 			XMLTest( "ErrorName() not empty after ClearError()", true, strlen(name) > 0 );
2191 		}
2192 	}
2193 
2194 	{
2195 		const char* html("<!DOCTYPE html><html><body><p>test</p><p><br/></p></body></html>");
2196 		XMLDocument doc(false);
2197 		doc.Parse(html);
2198 
2199 		XMLPrinter printer(0, true);
2200 		doc.Print(&printer);
2201 
2202 		XMLTest(html, html, printer.CStr());
2203 	}
2204 
2205 	{
2206 		// Evil memory leaks.
2207 		// If an XMLElement (etc) is allocated via NewElement() (etc.)
2208 		// and NOT added to the XMLDocument, what happens?
2209 		//
2210 		// Previously (buggy):
2211 		//		The memory would be free'd when the XMLDocument is
2212 		//      destructed. But the XMLElement destructor wasn't called, so
2213 		//      memory allocated for the XMLElement text would not be free'd.
2214 		//      In practice this meant strings allocated for the XMLElement
2215 		//      text would be leaked. An edge case, but annoying.
2216 		// Now:
2217 		//      The XMLElement destructor is called. But the unlinked nodes
2218 		//      have to be tracked using a list. This has a minor performance
2219 		//      impact that can become significant if you have a lot of
2220 		//      unlinked nodes. (But why would you do that?)
2221 		// The only way to see this bug was in a Visual C++ runtime debug heap
2222 		// leak tracker. This is compiled in by default on Windows Debug and
2223 		// enabled with _CRTDBG_LEAK_CHECK_DF parameter passed to _CrtSetDbgFlag().
2224 		{
2225 			XMLDocument doc;
2226 			doc.NewElement("LEAK 1");
2227 		}
2228 		{
2229 			XMLDocument doc;
2230 			XMLElement* ele = doc.NewElement("LEAK 2");
2231 			doc.DeleteNode(ele);
2232 		}
2233 	}
2234 
2235 	{
2236 		// Bad bad crash. Parsing error results in stack overflow, if uncaught.
2237 		const char* TESTS[] = {
2238 			"./resources/xmltest-5330.xml",
2239 			"./resources/xmltest-4636783552757760.xml",
2240 			"./resources/xmltest-5720541257269248.xml",
2241 			0
2242 		};
2243 		for (int i=0; TESTS[i]; ++i) {
2244 			XMLDocument doc;
2245 			doc.LoadFile(TESTS[i]);
2246 			XMLTest("Stack overflow prevented.", XML_ELEMENT_DEPTH_EXCEEDED, doc.ErrorID());
2247 		}
2248 	}
2249     {
2250         const char* TESTS[] = {
2251             "./resources/xmltest-5662204197076992.xml",     // Security-level performance issue.
2252             0
2253         };
2254         for (int i = 0; TESTS[i]; ++i) {
2255             XMLDocument doc;
2256             doc.LoadFile(TESTS[i]);
2257             // Need only not crash / lock up.
2258             XMLTest("Fuzz attack prevented.", true, true);
2259         }
2260     }
2261 	{
2262 		// Crashing reported via email.
2263 		const char* xml =
2264 			"<playlist id='playlist1'>"
2265 			"<property name='track_name'>voice</property>"
2266 			"<property name='audio_track'>1</property>"
2267 			"<entry out = '604' producer = '4_playlist1' in = '0' />"
2268 			"<blank length = '1' />"
2269 			"<entry out = '1625' producer = '3_playlist' in = '0' />"
2270 			"<blank length = '2' />"
2271 			"<entry out = '946' producer = '2_playlist1' in = '0' />"
2272 			"<blank length = '1' />"
2273 			"<entry out = '128' producer = '1_playlist1' in = '0' />"
2274 			"</playlist>";
2275 
2276 		// It's not a good idea to delete elements as you walk the
2277 		// list. I'm not sure this technically should work; but it's
2278 		// an interesting test case.
2279 		XMLDocument doc;
2280 		XMLError err = doc.Parse(xml);
2281 		XMLTest("Crash bug parsing", XML_SUCCESS, err );
2282 
2283 		XMLElement* playlist = doc.FirstChildElement("playlist");
2284 		XMLTest("Crash bug parsing", true, playlist != 0);
2285 
2286 		{
2287 			const char* elementName = "entry";
2288 			XMLElement* entry = playlist->FirstChildElement(elementName);
2289 			XMLTest("Crash bug parsing", true, entry != 0);
2290 			while (entry) {
2291 				XMLElement* todelete = entry;
2292 				entry = entry->NextSiblingElement(elementName);
2293 				playlist->DeleteChild(todelete);
2294 			}
2295 			entry = playlist->FirstChildElement(elementName);
2296 			XMLTest("Crash bug parsing", true, entry == 0);
2297 		}
2298 		{
2299 			const char* elementName = "blank";
2300 			XMLElement* blank = playlist->FirstChildElement(elementName);
2301 			XMLTest("Crash bug parsing", true, blank != 0);
2302 			while (blank) {
2303 				XMLElement* todelete = blank;
2304 				blank = blank->NextSiblingElement(elementName);
2305 				playlist->DeleteChild(todelete);
2306 			}
2307 			XMLTest("Crash bug parsing", true, blank == 0);
2308 		}
2309 
2310 		tinyxml2::XMLPrinter printer;
2311 		const bool acceptResult = playlist->Accept(&printer);
2312 		XMLTest("Crash bug parsing - Accept()", true, acceptResult);
2313 		printf("%s\n", printer.CStr());
2314 
2315 		// No test; it only need to not crash.
2316 		// Still, wrap it up with a sanity check
2317 		int nProperty = 0;
2318 		for (const XMLElement* p = playlist->FirstChildElement("property"); p; p = p->NextSiblingElement("property")) {
2319 			nProperty++;
2320 		}
2321 		XMLTest("Crash bug parsing", 2, nProperty);
2322 	}
2323 
2324     // ----------- Line Number Tracking --------------
2325     {
2326         struct TestUtil: XMLVisitor
2327         {
2328             TestUtil() : str() {}
2329 
2330             void TestParseError(const char *testString, const char *docStr, XMLError expected_error, int expectedLine)
2331             {
2332                 XMLDocument doc;
2333                 const XMLError parseError = doc.Parse(docStr);
2334 
2335                 XMLTest(testString, parseError, doc.ErrorID());
2336                 XMLTest(testString, true, doc.Error());
2337                 XMLTest(testString, expected_error, parseError);
2338                 XMLTest(testString, expectedLine, doc.ErrorLineNum());
2339             };
2340 
2341             void TestStringLines(const char *testString, const char *docStr, const char *expectedLines)
2342             {
2343                 XMLDocument doc;
2344                 doc.Parse(docStr);
2345                 XMLTest(testString, false, doc.Error());
2346                 TestDocLines(testString, doc, expectedLines);
2347             }
2348 
2349             void TestFileLines(const char *testString, const char *file_name, const char *expectedLines)
2350             {
2351                 XMLDocument doc;
2352                 doc.LoadFile(file_name);
2353                 XMLTest(testString, false, doc.Error());
2354                 TestDocLines(testString, doc, expectedLines);
2355             }
2356 
2357         private:
2358             DynArray<char, 10> str;
2359 
2360             void Push(char type, int lineNum)
2361             {
2362                 str.Push(type);
2363                 str.Push(char('0' + (lineNum / 10)));
2364                 str.Push(char('0' + (lineNum % 10)));
2365             }
2366 
2367             bool VisitEnter(const XMLDocument& doc)
2368             {
2369                 Push('D', doc.GetLineNum());
2370                 return true;
2371             }
2372             bool VisitEnter(const XMLElement& element, const XMLAttribute* firstAttribute)
2373             {
2374                 Push('E', element.GetLineNum());
2375                 for (const XMLAttribute *attr = firstAttribute; attr != 0; attr = attr->Next())
2376                     Push('A', attr->GetLineNum());
2377                 return true;
2378             }
2379             bool Visit(const XMLDeclaration& declaration)
2380             {
2381                 Push('L', declaration.GetLineNum());
2382                 return true;
2383             }
2384             bool Visit(const XMLText& text)
2385             {
2386                 Push('T', text.GetLineNum());
2387                 return true;
2388             }
2389             bool Visit(const XMLComment& comment)
2390             {
2391                 Push('C', comment.GetLineNum());
2392                 return true;
2393             }
2394             bool Visit(const XMLUnknown& unknown)
2395             {
2396                 Push('U', unknown.GetLineNum());
2397                 return true;
2398             }
2399 
2400             void TestDocLines(const char *testString, XMLDocument &doc, const char *expectedLines)
2401             {
2402                 str.Clear();
2403                 const bool acceptResult = doc.Accept(this);
2404                 XMLTest(testString, true, acceptResult);
2405                 str.Push(0);
2406                 XMLTest(testString, expectedLines, str.Mem());
2407             }
2408         } tester;
2409 
2410 		tester.TestParseError("ErrorLine-Parsing", "\n<root>\n foo \n<unclosed/>", XML_ERROR_PARSING, 2);
2411         tester.TestParseError("ErrorLine-Declaration", "<root>\n<?xml version=\"1.0\"?>", XML_ERROR_PARSING_DECLARATION, 2);
2412         tester.TestParseError("ErrorLine-Mismatch", "\n<root>\n</mismatch>", XML_ERROR_MISMATCHED_ELEMENT, 2);
2413         tester.TestParseError("ErrorLine-CData", "\n<root><![CDATA[ \n foo bar \n", XML_ERROR_PARSING_CDATA, 2);
2414         tester.TestParseError("ErrorLine-Text", "\n<root>\n foo bar \n", XML_ERROR_PARSING_TEXT, 3);
2415         tester.TestParseError("ErrorLine-Comment", "\n<root>\n<!-- >\n", XML_ERROR_PARSING_COMMENT, 3);
2416         tester.TestParseError("ErrorLine-Declaration", "\n<root>\n<? >\n", XML_ERROR_PARSING_DECLARATION, 3);
2417         tester.TestParseError("ErrorLine-Unknown", "\n<root>\n<! \n", XML_ERROR_PARSING_UNKNOWN, 3);
2418         tester.TestParseError("ErrorLine-Element", "\n<root>\n<unclosed \n", XML_ERROR_PARSING_ELEMENT, 3);
2419         tester.TestParseError("ErrorLine-Attribute", "\n<root>\n<unclosed \n att\n", XML_ERROR_PARSING_ATTRIBUTE, 4);
2420         tester.TestParseError("ErrorLine-ElementClose", "\n<root>\n<unclosed \n/unexpected", XML_ERROR_PARSING_ELEMENT, 3);
2421 
2422 		tester.TestStringLines(
2423             "LineNumbers-String",
2424 
2425             "<?xml version=\"1.0\"?>\n"					// 1 Doc, DecL
2426                 "<root a='b' \n"						// 2 Element Attribute
2427                 "c='d'> d <blah/>  \n"					// 3 Attribute Text Element
2428                 "newline in text \n"					// 4 Text
2429                 "and second <zxcv/><![CDATA[\n"			// 5 Element Text
2430                 " cdata test ]]><!-- comment -->\n"		// 6 Comment
2431                 "<! unknown></root>",					// 7 Unknown
2432 
2433             "D01L01E02A02A03T03E03T04E05T05C06U07");
2434 
2435 		tester.TestStringLines(
2436             "LineNumbers-CRLF",
2437 
2438             "\r\n"										// 1 Doc (arguably should be line 2)
2439             "<?xml version=\"1.0\"?>\n"					// 2 DecL
2440             "<root>\r\n"								// 3 Element
2441             "\n"										// 4
2442             "text contining new line \n"				// 5 Text
2443             " and also containing crlf \r\n"			// 6
2444             "<sub><![CDATA[\n"							// 7 Element Text
2445             "cdata containing new line \n"				// 8
2446             " and also containing cflr\r\n"				// 9
2447             "]]></sub><sub2/></root>",					// 10 Element
2448 
2449             "D01L02E03T05E07T07E10");
2450 
2451 		tester.TestFileLines(
2452             "LineNumbers-File",
2453             "resources/utf8test.xml",
2454             "D01L01E02E03A03A03T03E04A04A04T04E05A05A05T05E06A06A06T06E07A07A07T07E08A08A08T08E09T09E10T10");
2455     }
2456 
2457     {
2458     	const char* xml = "<Hello>Text</Error>";
2459     	XMLDocument doc;
2460     	doc.Parse(xml);
2461     	XMLTest("Test mismatched elements.", true, doc.Error());
2462     	XMLTest("Test mismatched elements.", XML_ERROR_MISMATCHED_ELEMENT, doc.ErrorID());
2463     	// For now just make sure calls work & doesn't crash.
2464     	// May solidify the error output in the future.
2465     	printf("%s\n", doc.ErrorStr());
2466     	doc.PrintError();
2467     }
2468 
2469     // ----------- Performance tracking --------------
2470 	{
2471 #if defined( _MSC_VER )
2472 		__int64 start, end, freq;
2473 		QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
2474 #endif
2475 
2476 		FILE* perfFP = fopen("resources/dream.xml", "r");
2477 		XMLTest("Open dream.xml", true, perfFP != 0);
2478 		fseek(perfFP, 0, SEEK_END);
2479 		long size = ftell(perfFP);
2480 		fseek(perfFP, 0, SEEK_SET);
2481 
2482 		char* mem = new char[size + 1];
2483 		memset(mem, 0xfe, size);
2484 		size_t bytesRead = fread(mem, 1, size, perfFP);
2485 		XMLTest("Read dream.xml", true, uint32_t(size) >= uint32_t(bytesRead));
2486 		fclose(perfFP);
2487 		mem[size] = 0;
2488 
2489 #if defined( _MSC_VER )
2490 		QueryPerformanceCounter((LARGE_INTEGER*)&start);
2491 #else
2492 		clock_t cstart = clock();
2493 #endif
2494 		bool parseDreamXmlFailed = false;
2495 		static const int COUNT = 10;
2496 		for (int i = 0; i < COUNT; ++i) {
2497 			XMLDocument doc;
2498 			doc.Parse(mem);
2499 			parseDreamXmlFailed = parseDreamXmlFailed || doc.Error();
2500 		}
2501 #if defined( _MSC_VER )
2502 		QueryPerformanceCounter((LARGE_INTEGER*)&end);
2503 #else
2504 		clock_t cend = clock();
2505 #endif
2506 		XMLTest( "Parse dream.xml", false, parseDreamXmlFailed );
2507 
2508 		delete[] mem;
2509 
2510 		static const char* note =
2511 #ifdef TINYXML2_DEBUG
2512 			"DEBUG";
2513 #else
2514 			"Release";
2515 #endif
2516 
2517 #if defined( _MSC_VER )
2518 		const double duration = 1000.0 * (double)(end - start) / ((double)freq * (double)COUNT);
2519 #else
2520 		const double duration = (double)(cend - cstart) / (double)COUNT;
2521 #endif
2522 		printf("\nParsing dream.xml (%s): %.3f milli-seconds\n", note, duration);
2523 	}
2524 
2525 #if defined( _MSC_VER ) &&  defined( TINYXML2_DEBUG )
2526 	{
2527 		_CrtMemCheckpoint( &endMemState );
2528 
2529 		_CrtMemState diffMemState;
2530 		_CrtMemDifference( &diffMemState, &startMemState, &endMemState );
2531 		_CrtMemDumpStatistics( &diffMemState );
2532 
2533 		{
2534 			int leaksBeforeExit = _CrtDumpMemoryLeaks();
2535 			XMLTest( "No leaks before exit?", FALSE, leaksBeforeExit );
2536 		}
2537 	}
2538 #endif
2539 
2540 	printf ("\nPass %d, Fail %d\n", gPass, gFail);
2541 
2542 	return gFail;
2543 }
2544