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