blob: da977d5d429464612dfd5e0e5f8889931d2f271a [file] [log] [blame]
Lee Thomason5b0a6772012-11-19 13:54:42 -08001#if defined( _MSC_VER )
Serhat Eser Erdemca5d6842014-04-17 14:06:15 +02002 #if !defined( _CRT_SECURE_NO_WARNINGS )
3 #define _CRT_SECURE_NO_WARNINGS // This test file is not intended to be secure.
4 #endif
Lee Thomason5b0a6772012-11-19 13:54:42 -08005#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08006
Lee Thomason5b0a6772012-11-19 13:54:42 -08007#include "tinyxml2.h"
kbinny62bf29a152017-06-23 18:15:25 +00008#include <cerrno>
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -07009#include <cstdlib>
10#include <cstring>
11#include <ctime>
U-Lama\Leee13c3e62011-12-28 14:36:55 -080012
kbinny62bf29a152017-06-23 18:15:25 +000013#if defined( _MSC_VER ) || defined (WIN32)
Lee Thomason1ff38e02012-02-14 18:18:16 -080014 #include <crtdbg.h>
Lee Thomason6f381b72012-03-02 12:59:39 -080015 #define WIN32_LEAN_AND_MEAN
16 #include <windows.h>
Lee Thomason1ff38e02012-02-14 18:18:16 -080017 _CrtMemState startMemState;
Lee Thomason53858b42017-06-01 19:09:16 -070018 _CrtMemState endMemState;
kbinny62bf29a152017-06-23 18:15:25 +000019#else
20 #include <sys/stat.h>
21 #include <sys/types.h>
Lee Thomason1ff38e02012-02-14 18:18:16 -080022#endif
Lee Thomasone9ecdab2012-02-13 18:11:20 -080023
U-Lama\Leee13c3e62011-12-28 14:36:55 -080024using namespace tinyxml2;
Anton Indrawan8a0006c2014-11-20 18:27:07 +010025using namespace std;
Lee Thomasonec5a7b42012-02-13 18:16:52 -080026int gPass = 0;
27int gFail = 0;
28
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -080029
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070030bool XMLTest (const char* testString, const char* expected, const char* found, bool echo=true, bool extraNL=false )
Lee Thomason1ff38e02012-02-14 18:18:16 -080031{
Sarat Addepalli13b2d732015-05-19 12:44:57 +053032 bool pass;
33 if ( !expected && !found )
34 pass = true;
35 else if ( !expected || !found )
36 pass = false;
Lee Thomasonc4836462018-06-29 15:57:55 -070037 else
Sarat Addepallid608c562015-05-20 10:19:00 +053038 pass = !strcmp( expected, found );
Lee Thomason1ff38e02012-02-14 18:18:16 -080039 if ( pass )
40 printf ("[pass]");
41 else
42 printf ("[fail]");
43
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070044 if ( !echo ) {
Lee Thomason1ff38e02012-02-14 18:18:16 -080045 printf (" %s\n", testString);
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070046 }
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 }
Lee Thomason1ff38e02012-02-14 18:18:16 -080057
58 if ( pass )
59 ++gPass;
60 else
61 ++gFail;
62 return pass;
63}
64
kezenator5a700712016-11-26 13:54:42 +100065bool XMLTest(const char* testString, XMLError expected, XMLError found, bool echo = true, bool extraNL = false)
66{
Lee Thomasone90e9012016-12-24 07:34:39 -080067 return XMLTest(testString, XMLDocument::ErrorIDToName(expected), XMLDocument::ErrorIDToName(found), echo, extraNL);
kezenator5a700712016-11-26 13:54:42 +100068}
69
70bool 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}
Lee Thomason1ff38e02012-02-14 18:18:16 -080074
Lee Thomason21be8822012-07-15 17:27:22 -070075template< class T > bool XMLTest( const char* testString, T expected, T found, bool echo=true )
Lee Thomason1ff38e02012-02-14 18:18:16 -080076{
77 bool pass = ( expected == found );
78 if ( pass )
79 printf ("[pass]");
80 else
81 printf ("[fail]");
82
U-Stream\Lee09a11c52012-02-17 08:31:16 -080083 if ( !echo )
Lee Thomason1ff38e02012-02-14 18:18:16 -080084 printf (" %s\n", testString);
85 else
Lee Thomasonc8312792012-07-16 12:44:41 -070086 printf (" %s [%d][%d]\n", testString, static_cast<int>(expected), static_cast<int>(found) );
Lee Thomason1ff38e02012-02-14 18:18:16 -080087
88 if ( pass )
89 ++gPass;
90 else
91 ++gFail;
92 return pass;
93}
Lee Thomasonec5a7b42012-02-13 18:16:52 -080094
U-Lama\Leee13c3e62011-12-28 14:36:55 -080095
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -080096void NullLineEndings( char* p )
97{
98 while( p && *p ) {
99 if ( *p == '\n' || *p == '\r' ) {
100 *p = 0;
101 return;
102 }
103 ++p;
104 }
105}
106
107
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700108int example_1()
109{
110 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300111 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700112
113 return doc.ErrorID();
114}
Lee Thomasoncf100692017-12-10 20:03:39 -0800115/** @page Example_1 Load an XML File
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200116 * @dontinclude ./xmltest.cpp
117 * Basic XML file loading.
118 * The basic syntax to load an XML file from
119 * disk and check for an error. (ErrorID()
120 * will return 0 for no error.)
121 * @skip example_1()
122 * @until }
123 */
Lee Thomasonc4836462018-06-29 15:57:55 -0700124
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700125
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700126int example_2()
127{
128 static const char* xml = "<element/>";
129 XMLDocument doc;
130 doc.Parse( xml );
131
132 return doc.ErrorID();
133}
Lee Thomasoncf100692017-12-10 20:03:39 -0800134/** @page Example_2 Parse an XML from char buffer
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200135 * @dontinclude ./xmltest.cpp
136 * Basic XML string parsing.
137 * The basic syntax to parse an XML for
138 * a char* and check for an error. (ErrorID()
139 * will return 0 for no error.)
140 * @skip example_2()
141 * @until }
142 */
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700143
144
145int example_3()
146{
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700147 static const char* xml =
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700148 "<?xml version=\"1.0\"?>"
149 "<!DOCTYPE PLAY SYSTEM \"play.dtd\">"
150 "<PLAY>"
151 "<TITLE>A Midsummer Night's Dream</TITLE>"
152 "</PLAY>";
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700153
154 XMLDocument doc;
155 doc.Parse( xml );
156
157 XMLElement* titleElement = doc.FirstChildElement( "PLAY" )->FirstChildElement( "TITLE" );
158 const char* title = titleElement->GetText();
159 printf( "Name of play (1): %s\n", title );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700160
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700161 XMLText* textNode = titleElement->FirstChild()->ToText();
162 title = textNode->Value();
163 printf( "Name of play (2): %s\n", title );
164
165 return doc.ErrorID();
166}
Lee Thomasoncf100692017-12-10 20:03:39 -0800167/** @page Example_3 Get information out of XML
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200168 @dontinclude ./xmltest.cpp
169 In this example, we navigate a simple XML
170 file, and read some interesting text. Note
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700171 that this example doesn't use error
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200172 checking; working code should check for null
173 pointers when walking an XML tree, or use
174 XMLHandle.
Lee Thomasonc4836462018-06-29 15:57:55 -0700175
176 (The XML is an excerpt from "dream.xml").
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200177
178 @skip example_3()
179 @until </PLAY>";
180
181 The structure of the XML file is:
182
183 <ul>
184 <li>(declaration)</li>
185 <li>(dtd stuff)</li>
186 <li>Element "PLAY"</li>
187 <ul>
188 <li>Element "TITLE"</li>
189 <ul>
190 <li>Text "A Midsummer Night's Dream"</li>
191 </ul>
192 </ul>
193 </ul>
194
Lee Thomasonc4836462018-06-29 15:57:55 -0700195 For this example, we want to print out the
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200196 title of the play. The text of the title (what
197 we want) is child of the "TITLE" element which
198 is a child of the "PLAY" element.
199
200 We want to skip the declaration and dtd, so the
201 method FirstChildElement() is a good choice. The
202 FirstChildElement() of the Document is the "PLAY"
203 Element, the FirstChildElement() of the "PLAY" Element
204 is the "TITLE" Element.
205
206 @until ( "TITLE" );
207
208 We can then use the convenience function GetText()
209 to get the title of the play.
210
211 @until title );
212
213 Text is just another Node in the XML DOM. And in
214 fact you should be a little cautious with it, as
Lee Thomasonc4836462018-06-29 15:57:55 -0700215 text nodes can contain elements.
216
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200217 @verbatim
218 Consider: A Midsummer Night's <b>Dream</b>
219 @endverbatim
220
221 It is more correct to actually query the Text Node
222 if in doubt:
223
224 @until title );
225
226 Noting that here we use FirstChild() since we are
227 looking for XMLText, not an element, and ToText()
Lee Thomasonc4836462018-06-29 15:57:55 -0700228 is a cast from a Node to a XMLText.
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200229*/
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700230
231
Lee Thomason21be8822012-07-15 17:27:22 -0700232bool example_4()
233{
234 static const char* xml =
235 "<information>"
236 " <attributeApproach v='2' />"
237 " <textApproach>"
238 " <v>2</v>"
239 " </textApproach>"
240 "</information>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700241
Lee Thomason21be8822012-07-15 17:27:22 -0700242 XMLDocument doc;
243 doc.Parse( xml );
244
245 int v0 = 0;
246 int v1 = 0;
247
248 XMLElement* attributeApproachElement = doc.FirstChildElement()->FirstChildElement( "attributeApproach" );
249 attributeApproachElement->QueryIntAttribute( "v", &v0 );
250
251 XMLElement* textApproachElement = doc.FirstChildElement()->FirstChildElement( "textApproach" );
252 textApproachElement->FirstChildElement( "v" )->QueryIntText( &v1 );
253
254 printf( "Both values are the same: %d and %d\n", v0, v1 );
255
256 return !doc.Error() && ( v0 == v1 );
257}
Lee Thomasoncf100692017-12-10 20:03:39 -0800258/** @page Example_4 Read attributes and text information.
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200259 @dontinclude ./xmltest.cpp
260
261 There are fundamentally 2 ways of writing a key-value
262 pair into an XML file. (Something that's always annoyed
263 me about XML.) Either by using attributes, or by writing
264 the key name into an element and the value into
265 the text node wrapped by the element. Both approaches
266 are illustrated in this example, which shows two ways
267 to encode the value "2" into the key "v":
268
269 @skip example_4()
270 @until "</information>";
271
Lee Thomasonc4836462018-06-29 15:57:55 -0700272 TinyXML-2 has accessors for both approaches.
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200273
274 When using an attribute, you navigate to the XMLElement
275 with that attribute and use the QueryIntAttribute()
276 group of methods. (Also QueryFloatAttribute(), etc.)
277
278 @skip XMLElement* attributeApproachElement
279 @until &v0 );
280
281 When using the text approach, you need to navigate
282 down one more step to the XMLElement that contains
283 the text. Note the extra FirstChildElement( "v" )
284 in the code below. The value of the text can then
285 be safely queried with the QueryIntText() group
286 of methods. (Also QueryFloatText(), etc.)
287
288 @skip XMLElement* textApproachElement
289 @until &v1 );
290*/
Lee Thomason21be8822012-07-15 17:27:22 -0700291
292
Lee Thomason178e4cc2013-01-25 16:19:05 -0800293int main( int argc, const char ** argv )
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800294{
Peter Matula50689912018-01-09 12:52:26 +0100295 #if defined( _MSC_VER ) && defined( TINYXML2_DEBUG )
Lee Thomason1ff38e02012-02-14 18:18:16 -0800296 _CrtMemCheckpoint( &startMemState );
Dmitry-Me99916592014-10-23 11:37:03 +0400297 // Enable MS Visual C++ debug heap memory leaks dump on exit
298 _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
Dmitry-Meed785702017-06-15 13:39:53 +0300299 {
300 int leaksOnStart = _CrtDumpMemoryLeaks();
301 XMLTest( "No leaks on start?", FALSE, leaksOnStart );
302 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700303 #endif
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800304
Dmitry-Me4bcbf142014-12-25 19:05:18 +0300305 {
306 TIXMLASSERT( true );
307 }
308
Lee Thomason178e4cc2013-01-25 16:19:05 -0800309 if ( argc > 1 ) {
310 XMLDocument* doc = new XMLDocument();
311 clock_t startTime = clock();
312 doc->LoadFile( argv[1] );
Anton Indrawan8a0006c2014-11-20 18:27:07 +0100313 clock_t loadTime = clock();
Lee Thomason178e4cc2013-01-25 16:19:05 -0800314 int errorID = doc->ErrorID();
315 delete doc; doc = 0;
Anton Indrawan8a0006c2014-11-20 18:27:07 +0100316 clock_t deleteTime = clock();
Lee Thomason178e4cc2013-01-25 16:19:05 -0800317
318 printf( "Test file '%s' loaded. ErrorID=%d\n", argv[1], errorID );
319 if ( !errorID ) {
Lee Thomason (grinliz)d6bd7362013-05-11 20:23:13 -0700320 printf( "Load time=%u\n", (unsigned)(loadTime - startTime) );
321 printf( "Delete time=%u\n", (unsigned)(deleteTime - loadTime) );
322 printf( "Total time=%u\n", (unsigned)(deleteTime - startTime) );
Lee Thomason178e4cc2013-01-25 16:19:05 -0800323 }
324 exit(0);
325 }
326
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300327 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason7f7b1622012-03-24 12:49:03 -0700328 if ( !fp ) {
329 printf( "Error opening test file 'dream.xml'.\n"
330 "Is your working directory the same as where \n"
331 "the xmltest.cpp and dream.xml file are?\n\n"
332 #if defined( _MSC_VER )
333 "In windows Visual Studio you may need to set\n"
334 "Properties->Debugging->Working Directory to '..'\n"
335 #endif
336 );
337 exit( 1 );
338 }
339 fclose( fp );
340
Lee Thomasoncf100692017-12-10 20:03:39 -0800341 XMLTest( "Example_1", 0, example_1() );
342 XMLTest( "Example_2", 0, example_2() );
343 XMLTest( "Example_3", 0, example_3() );
344 XMLTest( "Example_4", true, example_4() );
Lee Thomason87e475a2012-03-20 11:55:29 -0700345
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700346 /* ------ Example 2: Lookup information. ---- */
Lee Thomason87e475a2012-03-20 11:55:29 -0700347
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800348 {
Lee Thomason43f59302012-02-06 18:18:11 -0800349 static const char* test[] = { "<element />",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400350 "<element></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800351 "<element><subelement/></element>",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400352 "<element><subelement></subelement></element>",
353 "<element><subelement><subsub/></subelement></element>",
354 "<!--comment beside elements--><element><subelement></subelement></element>",
355 "<!--comment beside elements, this time with spaces--> \n <element> <subelement> \n </subelement> </element>",
356 "<element attrib1='foo' attrib2=\"bar\" ></element>",
357 "<element attrib1='foo' attrib2=\"bar\" ><subelement attrib3='yeehaa' /></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800358 "<element>Text inside element.</element>",
359 "<element><b></b></element>",
360 "<element>Text inside and <b>bolded</b> in the element.</element>",
361 "<outer><element>Text inside and <b>bolded</b> in the element.</element></outer>",
Lee Thomason8ee79892012-01-25 17:44:30 -0800362 "<element>This &amp; That.</element>",
Lee Thomason18d68bd2012-01-26 18:17:26 -0800363 "<element attrib='This&lt;That' />",
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800364 0
365 };
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800366 for( int i=0; test[i]; ++i ) {
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800367 XMLDocument doc;
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800368 doc.Parse( test[i] );
Dmitry-Me68578f42017-07-03 18:21:23 +0300369 XMLTest( "Element test", false, doc.Error() );
Lee Thomason5cae8972012-01-24 18:03:07 -0800370 doc.Print();
Lee Thomasonec975ce2012-01-23 11:42:06 -0800371 printf( "----------------------------------------------\n" );
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800372 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800373 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800374#if 1
Lee Thomasond6277762012-02-22 16:00:12 -0800375 {
376 static const char* test = "<!--hello world\n"
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400377 " line 2\r"
378 " line 3\r\n"
379 " line 4\n\r"
380 " line 5\r-->";
Lee Thomasond6277762012-02-22 16:00:12 -0800381
382 XMLDocument doc;
383 doc.Parse( test );
Dmitry-Me68578f42017-07-03 18:21:23 +0300384 XMLTest( "Hello world declaration", false, doc.Error() );
Lee Thomasond6277762012-02-22 16:00:12 -0800385 doc.Print();
386 }
387
Lee Thomason2c85a712012-01-31 08:24:24 -0800388 {
Dmitry-Mee8f4a8b2017-09-15 19:34:36 +0300389 // This test is pre-test for the next one
390 // (where Element1 is inserted "after itself".
391 // This code didn't use to crash.
392 XMLDocument doc;
393 XMLElement* element1 = doc.NewElement("Element1");
394 XMLElement* element2 = doc.NewElement("Element2");
395 doc.InsertEndChild(element1);
396 doc.InsertEndChild(element2);
397 doc.InsertAfterChild(element2, element2);
398 doc.InsertAfterChild(element2, element2);
399 }
400
401 {
402 XMLDocument doc;
403 XMLElement* element1 = doc.NewElement("Element1");
404 XMLElement* element2 = doc.NewElement("Element2");
405 doc.InsertEndChild(element1);
406 doc.InsertEndChild(element2);
407
408 // This insertion "after itself"
409 // used to cause invalid memory access and crash
410 doc.InsertAfterChild(element1, element1);
411 doc.InsertAfterChild(element1, element1);
412 doc.InsertAfterChild(element2, element2);
413 doc.InsertAfterChild(element2, element2);
414 }
415
416 {
Lee Thomason2c85a712012-01-31 08:24:24 -0800417 static const char* test = "<element>Text before.</element>";
418 XMLDocument doc;
419 doc.Parse( test );
Dmitry-Me68578f42017-07-03 18:21:23 +0300420 XMLTest( "Element text before", false, doc.Error() );
Lee Thomason2c85a712012-01-31 08:24:24 -0800421 XMLElement* root = doc.FirstChildElement();
422 XMLElement* newElement = doc.NewElement( "Subelement" );
423 root->InsertEndChild( newElement );
424 doc.Print();
425 }
Lee Thomasond1983222012-02-06 08:41:24 -0800426 {
427 XMLDocument* doc = new XMLDocument();
428 static const char* test = "<element><sub/></element>";
429 doc->Parse( test );
Dmitry-Me68578f42017-07-03 18:21:23 +0300430 XMLTest( "Element with sub element", false, doc->Error() );
Lee Thomasond1983222012-02-06 08:41:24 -0800431 delete doc;
432 }
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800433 {
Dmitry-Me8e063702017-08-01 17:40:40 +0300434 // Test: Programmatic DOM nodes insertion return values
435 XMLDocument doc;
436
437 XMLNode* first = doc.NewElement( "firstElement" );
438 XMLTest( "New element", true, first != 0 );
439 XMLNode* firstAfterInsertion = doc.InsertFirstChild( first );
440 XMLTest( "New element inserted first", true, firstAfterInsertion == first );
441
442 XMLNode* last = doc.NewElement( "lastElement" );
443 XMLTest( "New element", true, last != 0 );
444 XMLNode* lastAfterInsertion = doc.InsertEndChild( last );
445 XMLTest( "New element inserted last", true, lastAfterInsertion == last );
446
447 XMLNode* middle = doc.NewElement( "middleElement" );
448 XMLTest( "New element", true, middle != 0 );
449 XMLNode* middleAfterInsertion = doc.InsertAfterChild( first, middle );
450 XMLTest( "New element inserted middle", true, middleAfterInsertion == middle );
451 }
452 {
Lee Thomason1ff38e02012-02-14 18:18:16 -0800453 // Test: Programmatic DOM
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800454 // Build:
455 // <element>
456 // <!--comment-->
457 // <sub attrib="1" />
458 // <sub attrib="2" />
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800459 // <sub attrib="3" >& Text!</sub>
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800460 // <element>
461
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800462 XMLDocument* doc = new XMLDocument();
Lee Thomason1ff38e02012-02-14 18:18:16 -0800463 XMLNode* element = doc->InsertEndChild( doc->NewElement( "element" ) );
464
465 XMLElement* sub[3] = { doc->NewElement( "sub" ), doc->NewElement( "sub" ), doc->NewElement( "sub" ) };
466 for( int i=0; i<3; ++i ) {
467 sub[i]->SetAttribute( "attrib", i );
468 }
469 element->InsertEndChild( sub[2] );
Dmitry-Me7d8dfb92017-08-01 17:48:54 +0300470
471 const int dummyInitialValue = 1000;
472 int dummyValue = dummyInitialValue;
473
Lee Thomason1ff38e02012-02-14 18:18:16 -0800474 XMLNode* comment = element->InsertFirstChild( doc->NewComment( "comment" ) );
Dmitry-Me7d8dfb92017-08-01 17:48:54 +0300475 comment->SetUserData(&dummyValue);
Lee Thomason1ff38e02012-02-14 18:18:16 -0800476 element->InsertAfterChild( comment, sub[0] );
477 element->InsertAfterChild( sub[0], sub[1] );
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800478 sub[2]->InsertFirstChild( doc->NewText( "& Text!" ));
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800479 doc->Print();
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800480 XMLTest( "Programmatic DOM", "comment", doc->FirstChildElement( "element" )->FirstChild()->Value() );
481 XMLTest( "Programmatic DOM", "0", doc->FirstChildElement( "element" )->FirstChildElement()->Attribute( "attrib" ) );
482 XMLTest( "Programmatic DOM", 2, doc->FirstChildElement()->LastChildElement( "sub" )->IntAttribute( "attrib" ) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700483 XMLTest( "Programmatic DOM", "& Text!",
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800484 doc->FirstChildElement()->LastChildElement( "sub" )->FirstChild()->ToText()->Value() );
Dmitry-Mecaed4ec2017-08-11 17:39:47 +0300485 XMLTest("User data - pointer", true, &dummyValue == comment->GetUserData(), false);
486 XMLTest("User data - value behind pointer", dummyInitialValue, dummyValue, false);
U-Stream\Leeae25a442012-02-17 17:48:16 -0800487
488 // And now deletion:
489 element->DeleteChild( sub[2] );
490 doc->DeleteNode( comment );
491
492 element->FirstChildElement()->SetAttribute( "attrib", true );
493 element->LastChildElement()->DeleteAttribute( "attrib" );
494
495 XMLTest( "Programmatic DOM", true, doc->FirstChildElement()->FirstChildElement()->BoolAttribute( "attrib" ) );
Dmitry-Me3d20c5d2017-07-10 18:28:19 +0300496 const int defaultIntValue = 10;
497 const int replacementIntValue = 20;
498 int value1 = defaultIntValue;
499 int value2 = doc->FirstChildElement()->LastChildElement()->IntAttribute( "attrib", replacementIntValue );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300500 XMLError result = doc->FirstChildElement()->LastChildElement()->QueryIntAttribute( "attrib", &value1 );
501 XMLTest( "Programmatic DOM", XML_NO_ATTRIBUTE, result );
Dmitry-Me3d20c5d2017-07-10 18:28:19 +0300502 XMLTest( "Programmatic DOM", defaultIntValue, value1 );
503 XMLTest( "Programmatic DOM", replacementIntValue, value2 );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800504
505 doc->Print();
506
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700507 {
508 XMLPrinter streamer;
509 doc->Print( &streamer );
510 printf( "%s", streamer.CStr() );
511 }
512 {
513 XMLPrinter streamer( 0, true );
514 doc->Print( &streamer );
Doruk Turak1f212f32016-08-28 20:54:17 +0200515 XMLTest( "Compact mode", "<element><sub attrib=\"true\"/><sub/></element>", streamer.CStr(), false );
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700516 }
Lee Thomason (grinliz)6b8b0122012-09-08 21:21:00 -0700517 doc->SaveFile( "./resources/out/pretty.xml" );
Dmitry-Me46b70ce2017-07-10 17:54:24 +0300518 XMLTest( "Save pretty.xml", false, doc->Error() );
Lee Thomason (grinliz)6b8b0122012-09-08 21:21:00 -0700519 doc->SaveFile( "./resources/out/compact.xml", true );
Dmitry-Me46b70ce2017-07-10 17:54:24 +0300520 XMLTest( "Save compact.xml", false, doc->Error() );
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800521 delete doc;
522 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800523 {
524 // Test: Dream
525 // XML1 : 1,187,569 bytes in 31,209 allocations
526 // XML2 : 469,073 bytes in 323 allocations
527 //int newStart = gNew;
528 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300529 doc.LoadFile( "resources/dream.xml" );
Dmitry-Me46b70ce2017-07-10 17:54:24 +0300530 XMLTest( "Load dream.xml", false, doc.Error() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800531
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400532 doc.SaveFile( "resources/out/dreamout.xml" );
Dmitry-Me46b70ce2017-07-10 17:54:24 +0300533 XMLTest( "Save dreamout.xml", false, doc.Error() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800534 doc.PrintError();
535
536 XMLTest( "Dream", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400537 doc.FirstChild()->ToDeclaration()->Value() );
Dmitry-Mef5af9512018-03-23 21:01:25 +0300538 XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() != 0 );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800539 XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
540 doc.FirstChild()->NextSibling()->ToUnknown()->Value() );
541 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400542 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800543 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400544 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800545
546 XMLDocument doc2;
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400547 doc2.LoadFile( "resources/out/dreamout.xml" );
Dmitry-Me46b70ce2017-07-10 17:54:24 +0300548 XMLTest( "Load dreamout.xml", false, doc2.Error() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800549 XMLTest( "Dream-out", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400550 doc2.FirstChild()->ToDeclaration()->Value() );
Dmitry-Mef5af9512018-03-23 21:01:25 +0300551 XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() != 0 );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800552 XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
553 doc2.FirstChild()->NextSibling()->ToUnknown()->Value() );
554 XMLTest( "Dream-out", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400555 doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800556
557 //gNewTotal = gNew - newStart;
558 }
Lee Thomason6f381b72012-03-02 12:59:39 -0800559
560
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800561 {
562 const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n"
563 "<passages count=\"006\" formatversion=\"20020620\">\n"
564 " <wrong error>\n"
565 "</passages>";
566
567 XMLDocument doc;
568 doc.Parse( error );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300569 XMLTest( "Bad XML", XML_ERROR_PARSING_ATTRIBUTE, doc.ErrorID() );
Lee Thomasona36f7ac2017-12-28 13:48:54 -0800570 const char* errorStr = doc.ErrorStr();
571 XMLTest("Formatted error string",
Lee Thomasonc4836462018-06-29 15:57:55 -0700572 "Error=XML_ERROR_PARSING_ATTRIBUTE ErrorID=7 (0x7) Line number=3: XMLElement name=wrong",
Lee Thomasona36f7ac2017-12-28 13:48:54 -0800573 errorStr);
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800574 }
575
576 {
577 const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
578
579 XMLDocument doc;
580 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300581 XMLTest( "Top level attributes", false, doc.Error() );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800582
583 XMLElement* ele = doc.FirstChildElement();
584
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300585 int iVal;
586 XMLError result;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800587 double dVal;
588
589 result = ele->QueryDoubleAttribute( "attr0", &dVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300590 XMLTest( "Query attribute: int as double", XML_SUCCESS, result);
591 XMLTest( "Query attribute: int as double", 1, (int)dVal );
592 XMLTest( "Query attribute: int as double", 1, (int)ele->DoubleAttribute("attr0"));
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700593
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800594 result = ele->QueryDoubleAttribute( "attr1", &dVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300595 XMLTest( "Query attribute: double as double", XML_SUCCESS, result);
596 XMLTest( "Query attribute: double as double", 2.0, dVal );
597 XMLTest( "Query attribute: double as double", 2.0, ele->DoubleAttribute("attr1") );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700598
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800599 result = ele->QueryIntAttribute( "attr1", &iVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300600 XMLTest( "Query attribute: double as int", XML_SUCCESS, result);
601 XMLTest( "Query attribute: double as int", 2, iVal );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700602
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800603 result = ele->QueryIntAttribute( "attr2", &iVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300604 XMLTest( "Query attribute: not a number", XML_WRONG_ATTRIBUTE_TYPE, result );
605 XMLTest( "Query attribute: not a number", 4.0, ele->DoubleAttribute("attr2", 4.0) );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700606
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800607 result = ele->QueryIntAttribute( "bar", &iVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300608 XMLTest( "Query attribute: does not exist", XML_NO_ATTRIBUTE, result );
609 XMLTest( "Query attribute: does not exist", true, ele->BoolAttribute("bar", true) );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800610 }
611
612 {
613 const char* str = "<doc/>";
614
615 XMLDocument doc;
616 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300617 XMLTest( "Empty top element", false, doc.Error() );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800618
619 XMLElement* ele = doc.FirstChildElement();
620
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800621 int iVal, iVal2;
622 double dVal, dVal2;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800623
624 ele->SetAttribute( "str", "strValue" );
625 ele->SetAttribute( "int", 1 );
626 ele->SetAttribute( "double", -1.0 );
627
628 const char* cStr = ele->Attribute( "str" );
Dmitry-Me2087a272017-07-10 18:13:07 +0300629 {
630 XMLError queryResult = ele->QueryIntAttribute( "int", &iVal );
631 XMLTest( "Query int attribute", XML_SUCCESS, queryResult);
632 }
633 {
634 XMLError queryResult = ele->QueryDoubleAttribute( "double", &dVal );
635 XMLTest( "Query double attribute", XML_SUCCESS, queryResult);
636 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800637
Dmitry-Me2087a272017-07-10 18:13:07 +0300638 {
639 int queryResult = ele->QueryAttribute( "int", &iVal2 );
640 XMLTest( "Query int attribute generic", (int)XML_SUCCESS, queryResult);
641 }
642 {
643 int queryResult = ele->QueryAttribute( "double", &dVal2 );
644 XMLTest( "Query double attribute generic", (int)XML_SUCCESS, queryResult);
645 }
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800646
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300647 XMLTest( "Attribute match test", "strValue", ele->Attribute( "str", "strValue" ) );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800648 XMLTest( "Attribute round trip. c-string.", "strValue", cStr );
649 XMLTest( "Attribute round trip. int.", 1, iVal );
650 XMLTest( "Attribute round trip. double.", -1, (int)dVal );
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800651 XMLTest( "Alternate query", true, iVal == iVal2 );
652 XMLTest( "Alternate query", true, dVal == dVal2 );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700653 XMLTest( "Alternate query", true, iVal == ele->IntAttribute("int") );
Lee Thomasonc4836462018-06-29 15:57:55 -0700654 XMLTest( "Alternate query", true, dVal == ele->DoubleAttribute("double") );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800655 }
656
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800657 {
658 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300659 doc.LoadFile( "resources/utf8test.xml" );
Dmitry-Me46b70ce2017-07-10 17:54:24 +0300660 XMLTest( "Load utf8test.xml", false, doc.Error() );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800661
662 // Get the attribute "value" from the "Russian" element and check it.
663 XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700664 const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800665 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
666
667 XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) );
668
669 const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U,
670 0xd1U, 0x81U, 0xd1U, 0x81U,
671 0xd0U, 0xbaU, 0xd0U, 0xb8U,
672 0xd0U, 0xb9U, 0 };
673 const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
674
675 XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText();
676 XMLTest( "UTF-8: Browsing russian element name.",
677 russianText,
678 text->Value() );
679
680 // Now try for a round trip.
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400681 doc.SaveFile( "resources/out/utf8testout.xml" );
Dmitry-Me46b70ce2017-07-10 17:54:24 +0300682 XMLTest( "UTF-8: Save testout.xml", false, doc.Error() );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800683
684 // Check the round trip.
Dmitry-Me520009e2017-08-10 17:50:03 +0300685 bool roundTripOkay = false;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800686
Thomas Roßa6dd8c62012-07-26 20:42:18 +0200687 FILE* saved = fopen( "resources/out/utf8testout.xml", "r" );
Dmitry-Me520009e2017-08-10 17:50:03 +0300688 XMLTest( "UTF-8: Open utf8testout.xml", true, saved != 0 );
689
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300690 FILE* verify = fopen( "resources/utf8testverify.xml", "r" );
Dmitry-Me520009e2017-08-10 17:50:03 +0300691 XMLTest( "UTF-8: Open utf8testverify.xml", true, verify != 0 );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800692
693 if ( saved && verify )
694 {
Dmitry-Me520009e2017-08-10 17:50:03 +0300695 roundTripOkay = true;
PKEuSc28ba3a2012-07-16 03:08:47 -0700696 char verifyBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800697 while ( fgets( verifyBuf, 256, verify ) )
698 {
PKEuSc28ba3a2012-07-16 03:08:47 -0700699 char savedBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800700 fgets( savedBuf, 256, saved );
701 NullLineEndings( verifyBuf );
702 NullLineEndings( savedBuf );
703
704 if ( strcmp( verifyBuf, savedBuf ) )
705 {
706 printf( "verify:%s<\n", verifyBuf );
707 printf( "saved :%s<\n", savedBuf );
Dmitry-Me520009e2017-08-10 17:50:03 +0300708 roundTripOkay = false;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800709 break;
710 }
711 }
712 }
713 if ( saved )
714 fclose( saved );
715 if ( verify )
716 fclose( verify );
Dmitry-Me520009e2017-08-10 17:50:03 +0300717 XMLTest( "UTF-8: Verified multi-language round trip.", true, roundTripOkay );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800718 }
719
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800720 // --------GetText()-----------
721 {
722 const char* str = "<foo>This is text</foo>";
723 XMLDocument doc;
724 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300725 XMLTest( "Double whitespace", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800726 const XMLElement* element = doc.RootElement();
727
728 XMLTest( "GetText() normal use.", "This is text", element->GetText() );
729
730 str = "<foo><b>This is text</b></foo>";
731 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300732 XMLTest( "Bold text simulation", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800733 element = doc.RootElement();
734
735 XMLTest( "GetText() contained element.", element->GetText() == 0, true );
736 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800737
Lee Thomasond6277762012-02-22 16:00:12 -0800738
Uli Kusterer321072e2014-01-21 01:57:38 +0100739 // --------SetText()-----------
740 {
741 const char* str = "<foo></foo>";
742 XMLDocument doc;
743 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300744 XMLTest( "Empty closed element", false, doc.Error() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100745 XMLElement* element = doc.RootElement();
746
Lee Thomason9c0678a2014-01-24 10:18:27 -0800747 element->SetText("darkness.");
748 XMLTest( "SetText() normal use (open/close).", "darkness.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100749
Lee Thomason9c0678a2014-01-24 10:18:27 -0800750 element->SetText("blue flame.");
751 XMLTest( "SetText() replace.", "blue flame.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100752
753 str = "<foo/>";
754 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300755 XMLTest( "Empty self-closed element", false, doc.Error() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100756 element = doc.RootElement();
757
Lee Thomason9c0678a2014-01-24 10:18:27 -0800758 element->SetText("The driver");
759 XMLTest( "SetText() normal use. (self-closing)", "The driver", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100760
Lee Thomason9c0678a2014-01-24 10:18:27 -0800761 element->SetText("<b>horses</b>");
762 XMLTest( "SetText() replace with tag-like text.", "<b>horses</b>", element->GetText() );
763 //doc.Print();
Uli Kusterer321072e2014-01-21 01:57:38 +0100764
765 str = "<foo><bar>Text in nested element</bar></foo>";
766 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300767 XMLTest( "Text in nested element", false, doc.Error() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100768 element = doc.RootElement();
Lee Thomasonc4836462018-06-29 15:57:55 -0700769
Lee Thomason9c0678a2014-01-24 10:18:27 -0800770 element->SetText("wolves");
771 XMLTest( "SetText() prefix to nested non-text children.", "wolves", element->GetText() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800772
773 str = "<foo/>";
774 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300775 XMLTest( "Empty self-closed element round 2", false, doc.Error() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800776 element = doc.RootElement();
Lee Thomasonc4836462018-06-29 15:57:55 -0700777
Lee Thomason5bb2d802014-01-24 10:42:57 -0800778 element->SetText( "str" );
779 XMLTest( "SetText types", "str", element->GetText() );
780
781 element->SetText( 1 );
782 XMLTest( "SetText types", "1", element->GetText() );
783
784 element->SetText( 1U );
785 XMLTest( "SetText types", "1", element->GetText() );
786
787 element->SetText( true );
Doruk Turak1f212f32016-08-28 20:54:17 +0200788 XMLTest( "SetText types", "true", element->GetText() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800789
790 element->SetText( 1.5f );
791 XMLTest( "SetText types", "1.5", element->GetText() );
792
793 element->SetText( 1.5 );
794 XMLTest( "SetText types", "1.5", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100795 }
796
Lee Thomason51c12712016-06-04 20:18:49 -0700797 // ---------- Attributes ---------
798 {
799 static const int64_t BIG = -123456789012345678;
800 XMLDocument doc;
801 XMLElement* element = doc.NewElement("element");
802 doc.InsertFirstChild(element);
803
804 {
805 element->SetAttribute("attrib", int(-100));
Dmitry-Me2087a272017-07-10 18:13:07 +0300806 {
807 int v = 0;
808 XMLError queryResult = element->QueryIntAttribute("attrib", &v);
809 XMLTest("Attribute: int", XML_SUCCESS, queryResult, true);
810 XMLTest("Attribute: int", -100, v, true);
811 }
812 {
813 int v = 0;
814 int queryResult = element->QueryAttribute("attrib", &v);
815 XMLTest("Attribute: int", (int)XML_SUCCESS, queryResult, true);
816 XMLTest("Attribute: int", -100, v, true);
817 }
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700818 XMLTest("Attribute: int", -100, element->IntAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700819 }
820 {
821 element->SetAttribute("attrib", unsigned(100));
Dmitry-Me2087a272017-07-10 18:13:07 +0300822 {
823 unsigned v = 0;
824 XMLError queryResult = element->QueryUnsignedAttribute("attrib", &v);
825 XMLTest("Attribute: unsigned", XML_SUCCESS, queryResult, true);
826 XMLTest("Attribute: unsigned", unsigned(100), v, true);
827 }
828 {
829 unsigned v = 0;
830 int queryResult = element->QueryAttribute("attrib", &v);
831 XMLTest("Attribute: unsigned", (int)XML_SUCCESS, queryResult, true);
832 XMLTest("Attribute: unsigned", unsigned(100), v, true);
833 }
Lee Thomason5b00e062017-12-28 14:07:47 -0800834 {
835 const char* v = "failed";
Dmitry-Me63d8de62018-01-09 00:20:45 +0300836 XMLError queryResult = element->QueryStringAttribute("not-attrib", &v);
Lee Thomason5b00e062017-12-28 14:07:47 -0800837 XMLTest("Attribute: string default", false, queryResult == XML_SUCCESS);
838 queryResult = element->QueryStringAttribute("attrib", &v);
Dmitry-Me63d8de62018-01-09 00:20:45 +0300839 XMLTest("Attribute: string", XML_SUCCESS, queryResult, true);
Lee Thomason5b00e062017-12-28 14:07:47 -0800840 XMLTest("Attribute: string", "100", v);
841 }
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700842 XMLTest("Attribute: unsigned", unsigned(100), element->UnsignedAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700843 }
844 {
845 element->SetAttribute("attrib", BIG);
Dmitry-Me2087a272017-07-10 18:13:07 +0300846 {
847 int64_t v = 0;
848 XMLError queryResult = element->QueryInt64Attribute("attrib", &v);
849 XMLTest("Attribute: int64_t", XML_SUCCESS, queryResult, true);
850 XMLTest("Attribute: int64_t", BIG, v, true);
851 }
852 {
853 int64_t v = 0;
854 int queryResult = element->QueryAttribute("attrib", &v);
855 XMLTest("Attribute: int64_t", (int)XML_SUCCESS, queryResult, true);
856 XMLTest("Attribute: int64_t", BIG, v, true);
857 }
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700858 XMLTest("Attribute: int64_t", BIG, element->Int64Attribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700859 }
860 {
861 element->SetAttribute("attrib", true);
Dmitry-Me2087a272017-07-10 18:13:07 +0300862 {
863 bool v = false;
864 XMLError queryResult = element->QueryBoolAttribute("attrib", &v);
865 XMLTest("Attribute: bool", XML_SUCCESS, queryResult, true);
866 XMLTest("Attribute: bool", true, v, true);
867 }
868 {
869 bool v = false;
870 int queryResult = element->QueryAttribute("attrib", &v);
871 XMLTest("Attribute: bool", (int)XML_SUCCESS, queryResult, true);
872 XMLTest("Attribute: bool", true, v, true);
873 }
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700874 XMLTest("Attribute: bool", true, element->BoolAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700875 }
876 {
Lee Thomasonce667c92016-12-26 16:45:30 -0800877 element->SetAttribute("attrib", true);
878 const char* result = element->Attribute("attrib");
879 XMLTest("Bool true is 'true'", "true", result);
880
Lee Thomasonc5c99c22016-12-29 11:19:17 -0800881 XMLUtil::SetBoolSerialization("1", "0");
Lee Thomasonce667c92016-12-26 16:45:30 -0800882 element->SetAttribute("attrib", true);
883 result = element->Attribute("attrib");
884 XMLTest("Bool true is '1'", "1", result);
885
Lee Thomasonc5c99c22016-12-29 11:19:17 -0800886 XMLUtil::SetBoolSerialization(0, 0);
Lee Thomasonce667c92016-12-26 16:45:30 -0800887 }
888 {
Lee Thomason51c12712016-06-04 20:18:49 -0700889 element->SetAttribute("attrib", 100.0);
Dmitry-Me2087a272017-07-10 18:13:07 +0300890 {
891 double v = 0;
892 XMLError queryResult = element->QueryDoubleAttribute("attrib", &v);
893 XMLTest("Attribute: double", XML_SUCCESS, queryResult, true);
894 XMLTest("Attribute: double", 100.0, v, true);
895 }
896 {
897 double v = 0;
898 int queryResult = element->QueryAttribute("attrib", &v);
899 XMLTest("Attribute: bool", (int)XML_SUCCESS, queryResult, true);
900 XMLTest("Attribute: double", 100.0, v, true);
901 }
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700902 XMLTest("Attribute: double", 100.0, element->DoubleAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700903 }
904 {
905 element->SetAttribute("attrib", 100.0f);
Dmitry-Me2087a272017-07-10 18:13:07 +0300906 {
907 float v = 0;
908 XMLError queryResult = element->QueryFloatAttribute("attrib", &v);
909 XMLTest("Attribute: float", XML_SUCCESS, queryResult, true);
910 XMLTest("Attribute: float", 100.0f, v, true);
911 }
912 {
913 float v = 0;
914 int queryResult = element->QueryAttribute("attrib", &v);
915 XMLTest("Attribute: float", (int)XML_SUCCESS, queryResult, true);
916 XMLTest("Attribute: float", 100.0f, v, true);
917 }
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700918 XMLTest("Attribute: float", 100.0f, element->FloatAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700919 }
920 {
921 element->SetText(BIG);
922 int64_t v = 0;
Dmitry-Me2087a272017-07-10 18:13:07 +0300923 XMLError queryResult = element->QueryInt64Text(&v);
924 XMLTest("Element: int64_t", XML_SUCCESS, queryResult, true);
Lee Thomason51c12712016-06-04 20:18:49 -0700925 XMLTest("Element: int64_t", BIG, v, true);
926 }
927 }
928
929 // ---------- XMLPrinter stream mode ------
930 {
931 {
Dmitry-Mec0fad292017-08-09 19:05:42 +0300932 FILE* printerfp = fopen("resources/out/printer.xml", "w");
933 XMLTest("Open printer.xml", true, printerfp != 0);
Lee Thomason51c12712016-06-04 20:18:49 -0700934 XMLPrinter printer(printerfp);
935 printer.OpenElement("foo");
936 printer.PushAttribute("attrib-text", "text");
937 printer.PushAttribute("attrib-int", int(1));
938 printer.PushAttribute("attrib-unsigned", unsigned(2));
939 printer.PushAttribute("attrib-int64", int64_t(3));
940 printer.PushAttribute("attrib-bool", true);
941 printer.PushAttribute("attrib-double", 4.0);
942 printer.CloseElement();
943 fclose(printerfp);
944 }
945 {
946 XMLDocument doc;
Dmitry-Mec0fad292017-08-09 19:05:42 +0300947 doc.LoadFile("resources/out/printer.xml");
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300948 XMLTest("XMLPrinter Stream mode: load", XML_SUCCESS, doc.ErrorID(), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700949
950 const XMLDocument& cdoc = doc;
951
952 const XMLAttribute* attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-text");
953 XMLTest("attrib-text", "text", attrib->Value(), true);
954 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int");
955 XMLTest("attrib-int", int(1), attrib->IntValue(), true);
956 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-unsigned");
957 XMLTest("attrib-unsigned", unsigned(2), attrib->UnsignedValue(), true);
958 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int64");
959 XMLTest("attrib-int64", int64_t(3), attrib->Int64Value(), true);
960 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-bool");
961 XMLTest("attrib-bool", true, attrib->BoolValue(), true);
962 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-double");
963 XMLTest("attrib-double", 4.0, attrib->DoubleValue(), true);
964 }
965
966 }
967
Uli Kusterer321072e2014-01-21 01:57:38 +0100968
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800969 // ---------- CDATA ---------------
970 {
971 const char* str = "<xmlElement>"
972 "<![CDATA["
973 "I am > the rules!\n"
974 "...since I make symbolic puns"
975 "]]>"
976 "</xmlElement>";
977 XMLDocument doc;
978 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300979 XMLTest( "CDATA symbolic puns round 1", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800980 doc.Print();
Lee Thomasond6277762012-02-22 16:00:12 -0800981
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300982 XMLTest( "CDATA parse.", "I am > the rules!\n...since I make symbolic puns",
983 doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomasond6277762012-02-22 16:00:12 -0800984 false );
985 }
986
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800987 // ----------- CDATA -------------
988 {
989 const char* str = "<xmlElement>"
990 "<![CDATA["
991 "<b>I am > the rules!</b>\n"
992 "...since I make symbolic puns"
993 "]]>"
994 "</xmlElement>";
995 XMLDocument doc;
996 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300997 XMLTest( "CDATA symbolic puns round 2", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800998 doc.Print();
999
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001000 XMLTest( "CDATA parse. [ tixml1:1480107 ]",
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001001 "<b>I am > the rules!</b>\n...since I make symbolic puns",
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001002 doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001003 false );
1004 }
1005
1006 // InsertAfterChild causes crash.
1007 {
1008 // InsertBeforeChild and InsertAfterChild causes crash.
1009 XMLDocument doc;
1010 XMLElement* parent = doc.NewElement( "Parent" );
1011 doc.InsertFirstChild( parent );
1012
1013 XMLElement* childText0 = doc.NewElement( "childText0" );
1014 XMLElement* childText1 = doc.NewElement( "childText1" );
1015
1016 XMLNode* childNode0 = parent->InsertEndChild( childText0 );
Dmitry-Me8e063702017-08-01 17:40:40 +03001017 XMLTest( "InsertEndChild() return", true, childNode0 == childText0 );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001018 XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 );
Dmitry-Me8e063702017-08-01 17:40:40 +03001019 XMLTest( "InsertAfterChild() return", true, childNode1 == childText1 );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001020
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001021 XMLTest( "Test InsertAfterChild on empty node. ", true, ( childNode1 == parent->LastChild() ) );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001022 }
Lee Thomasond6277762012-02-22 16:00:12 -08001023
1024 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001025 // Entities not being written correctly.
1026 // From Lynn Allen
Lee Thomasond6277762012-02-22 16:00:12 -08001027
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001028 const char* passages =
1029 "<?xml version=\"1.0\" standalone=\"no\" ?>"
1030 "<passages count=\"006\" formatversion=\"20020620\">"
1031 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
1032 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
1033 "</passages>";
Lee Thomasond6277762012-02-22 16:00:12 -08001034
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001035 XMLDocument doc;
1036 doc.Parse( passages );
Dmitry-Me68578f42017-07-03 18:21:23 +03001037 XMLTest( "Entity transformation parse round 1", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001038 XMLElement* psg = doc.RootElement()->FirstChildElement();
1039 const char* context = psg->Attribute( "context" );
1040 const char* expected = "Line 5 has \"quotation marks\" and 'apostrophe marks'. It also has <, >, and &, as well as a fake copyright \xC2\xA9.";
Lee Thomasond6277762012-02-22 16:00:12 -08001041
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001042 XMLTest( "Entity transformation: read. ", expected, context, true );
Lee Thomasond6277762012-02-22 16:00:12 -08001043
Dmitry-Me520009e2017-08-10 17:50:03 +03001044 const char* textFilePath = "resources/out/textfile.txt";
1045 FILE* textfile = fopen( textFilePath, "w" );
1046 XMLTest( "Entity transformation: open text file for writing", true, textfile != 0, true );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001047 if ( textfile )
1048 {
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001049 XMLPrinter streamer( textfile );
Dmitry-Mef0f2e992017-09-25 17:38:42 +03001050 bool acceptResult = psg->Accept( &streamer );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001051 fclose( textfile );
Dmitry-Mef0f2e992017-09-25 17:38:42 +03001052 XMLTest( "Entity transformation: Accept", true, acceptResult );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001053 }
Thomas Roß0922b732012-09-23 16:31:22 +02001054
Dmitry-Me520009e2017-08-10 17:50:03 +03001055 textfile = fopen( textFilePath, "r" );
1056 XMLTest( "Entity transformation: open text file for reading", true, textfile != 0, true );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001057 if ( textfile )
1058 {
1059 char buf[ 1024 ];
1060 fgets( buf, 1024, textfile );
1061 XMLTest( "Entity transformation: write. ",
1062 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
1063 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.\"/>\n",
1064 buf, false );
PKEuSc28ba3a2012-07-16 03:08:47 -07001065 fclose( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001066 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001067 }
1068
1069 {
Lee Thomason6f381b72012-03-02 12:59:39 -08001070 // Suppress entities.
1071 const char* passages =
1072 "<?xml version=\"1.0\" standalone=\"no\" ?>"
1073 "<passages count=\"006\" formatversion=\"20020620\">"
1074 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
1075 "</passages>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001076
Lee Thomason6f381b72012-03-02 12:59:39 -08001077 XMLDocument doc( false );
1078 doc.Parse( passages );
Dmitry-Me68578f42017-07-03 18:21:23 +03001079 XMLTest( "Entity transformation parse round 2", false, doc.Error() );
Lee Thomason6f381b72012-03-02 12:59:39 -08001080
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001081 XMLTest( "No entity parsing.",
1082 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.",
1083 doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ) );
1084 XMLTest( "No entity parsing.", "Crazy &ttk;",
1085 doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value() );
Lee Thomason6f381b72012-03-02 12:59:39 -08001086 doc.Print();
1087 }
1088
1089 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +04001090 const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001091
1092 XMLDocument doc;
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +04001093 doc.Parse( test );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001094 XMLTest( "dot in names", false, doc.Error() );
1095 XMLTest( "dot in names", "a.elem", doc.FirstChildElement()->Name() );
1096 XMLTest( "dot in names", "2.0", doc.FirstChildElement()->Attribute( "xmi.version" ) );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001097 }
1098
1099 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +04001100 const char* test = "<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001101
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +04001102 XMLDocument doc;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001103 doc.Parse( test );
Dmitry-Me68578f42017-07-03 18:21:23 +03001104 XMLTest( "fin thickness", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001105
1106 XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
1107 XMLTest( "Entity with one digit.",
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001108 "1.1 Start easy ignore fin thickness\n", text->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001109 false );
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +04001110 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001111
1112 {
1113 // DOCTYPE not preserved (950171)
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001114 //
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001115 const char* doctype =
1116 "<?xml version=\"1.0\" ?>"
1117 "<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
1118 "<!ELEMENT title (#PCDATA)>"
1119 "<!ELEMENT books (title,authors)>"
1120 "<element />";
1121
1122 XMLDocument doc;
1123 doc.Parse( doctype );
Dmitry-Me68578f42017-07-03 18:21:23 +03001124 XMLTest( "PLAY SYSTEM parse", false, doc.Error() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +04001125 doc.SaveFile( "resources/out/test7.xml" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001126 XMLTest( "PLAY SYSTEM save", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001127 doc.DeleteChild( doc.RootElement() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +04001128 doc.LoadFile( "resources/out/test7.xml" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001129 XMLTest( "PLAY SYSTEM load", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001130 doc.Print();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001131
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001132 const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown();
1133 XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() );
1134
1135 }
1136
1137 {
1138 // Comments do not stream out correctly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001139 const char* doctype =
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001140 "<!-- Somewhat<evil> -->";
1141 XMLDocument doc;
1142 doc.Parse( doctype );
Dmitry-Me68578f42017-07-03 18:21:23 +03001143 XMLTest( "Comment somewhat evil", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001144
1145 XMLComment* comment = doc.FirstChild()->ToComment();
1146
1147 XMLTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
1148 }
1149 {
1150 // Double attributes
1151 const char* doctype = "<element attr='red' attr='blue' />";
1152
1153 XMLDocument doc;
1154 doc.Parse( doctype );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001155
Lee Thomason2fa81722012-11-09 12:37:46 -08001156 XMLTest( "Parsing repeated attributes.", XML_ERROR_PARSING_ATTRIBUTE, doc.ErrorID() ); // is an error to tinyxml (didn't use to be, but caused issues)
Lee Thomason (grinliz)0a4df402012-02-27 20:50:52 -08001157 doc.PrintError();
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001158 }
1159
1160 {
1161 // Embedded null in stream.
1162 const char* doctype = "<element att\0r='red' attr='blue' />";
1163
1164 XMLDocument doc;
1165 doc.Parse( doctype );
1166 XMLTest( "Embedded null throws error.", true, doc.Error() );
1167 }
1168
1169 {
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -07001170 // Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
Dmitry-Me588bb8d2014-12-25 18:59:18 +03001171 const char* str = "";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001172 XMLDocument doc;
1173 doc.Parse( str );
Lee Thomason2fa81722012-11-09 12:37:46 -08001174 XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
Lee Thomasona36f7ac2017-12-28 13:48:54 -08001175
1176 // But be sure there is an error string!
1177 const char* errorStr = doc.ErrorStr();
1178 XMLTest("Error string should be set",
Lee Thomasonc4836462018-06-29 15:57:55 -07001179 "Error=XML_ERROR_EMPTY_DOCUMENT ErrorID=13 (0xd) Line number=0",
Lee Thomasona36f7ac2017-12-28 13:48:54 -08001180 errorStr);
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001181 }
1182
1183 {
Dmitry-Me588bb8d2014-12-25 18:59:18 +03001184 // Documents with all whitespaces should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
1185 const char* str = " ";
1186 XMLDocument doc;
1187 doc.Parse( str );
1188 XMLTest( "All whitespaces document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
1189 }
1190
1191 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001192 // Low entities
1193 XMLDocument doc;
1194 doc.Parse( "<test>&#x0e;</test>" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001195 XMLTest( "Hex values", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001196 const char result[] = { 0x0e, 0 };
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001197 XMLTest( "Low entities.", result, doc.FirstChildElement()->GetText() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001198 doc.Print();
1199 }
1200
1201 {
1202 // Attribute values with trailing quotes not handled correctly
1203 XMLDocument doc;
1204 doc.Parse( "<foo attribute=bar\" />" );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001205 XMLTest( "Throw error with bad end quotes.", true, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001206 }
1207
1208 {
1209 // [ 1663758 ] Failure to report error on bad XML
1210 XMLDocument xml;
1211 xml.Parse("<x>");
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001212 XMLTest("Missing end tag at end of input", true, xml.Error());
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001213 xml.Parse("<x> ");
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001214 XMLTest("Missing end tag with trailing whitespace", true, xml.Error());
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001215 xml.Parse("<x></y>");
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001216 XMLTest("Mismatched tags", XML_ERROR_MISMATCHED_ELEMENT, xml.ErrorID() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001217 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001218
1219
1220 {
1221 // [ 1475201 ] TinyXML parses entities in comments
1222 XMLDocument xml;
1223 xml.Parse("<!-- declarations for <head> & <body> -->"
1224 "<!-- far &amp; away -->" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001225 XMLTest( "Declarations for head and body", false, xml.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001226
1227 XMLNode* e0 = xml.FirstChild();
1228 XMLNode* e1 = e0->NextSibling();
1229 XMLComment* c0 = e0->ToComment();
1230 XMLComment* c1 = e1->ToComment();
1231
1232 XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
1233 XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
1234 }
1235
1236 {
1237 XMLDocument xml;
1238 xml.Parse( "<Parent>"
1239 "<child1 att=''/>"
1240 "<!-- With this comment, child2 will not be parsed! -->"
1241 "<child2 att=''/>"
1242 "</Parent>" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001243 XMLTest( "Comments iteration", false, xml.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001244 xml.Print();
1245
1246 int count = 0;
1247
1248 for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
1249 ele;
1250 ele = ele->NextSibling() )
1251 {
1252 ++count;
1253 }
1254
1255 XMLTest( "Comments iterate correctly.", 3, count );
1256 }
1257
1258 {
1259 // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
1260 unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
1261 buf[60] = 239;
1262 buf[61] = 0;
1263
1264 XMLDocument doc;
1265 doc.Parse( (const char*)buf);
Dmitry-Me68578f42017-07-03 18:21:23 +03001266 XMLTest( "Broken CDATA", true, doc.Error() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001267 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001268
1269
1270 {
1271 // bug 1827248 Error while parsing a little bit malformed file
1272 // Actually not malformed - should work.
1273 XMLDocument xml;
1274 xml.Parse( "<attributelist> </attributelist >" );
1275 XMLTest( "Handle end tag whitespace", false, xml.Error() );
1276 }
1277
1278 {
1279 // This one must not result in an infinite loop
1280 XMLDocument xml;
1281 xml.Parse( "<infinite>loop" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001282 XMLTest( "No closing element", true, xml.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001283 XMLTest( "Infinite loop test.", true, true );
1284 }
1285#endif
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001286 {
1287 const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
1288 XMLDocument doc;
1289 doc.Parse( pub );
Dmitry-Me68578f42017-07-03 18:21:23 +03001290 XMLTest( "Trailing DOCTYPE", false, doc.Error() );
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001291
1292 XMLDocument clone;
1293 for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
1294 XMLNode* copy = node->ShallowClone( &clone );
1295 clone.InsertEndChild( copy );
1296 }
1297
1298 clone.Print();
1299
1300 int count=0;
1301 const XMLNode* a=clone.FirstChild();
1302 const XMLNode* b=doc.FirstChild();
1303 for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
1304 ++count;
1305 XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
1306 }
1307 XMLTest( "Clone and Equal", 4, count );
1308 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001309
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001310 {
Lee Thomason7085f002017-06-01 18:09:43 -07001311 // Deep Cloning of root element.
1312 XMLDocument doc2;
1313 XMLPrinter printer1;
1314 {
1315 // Make sure doc1 is deleted before we test doc2
1316 const char* xml =
1317 "<root>"
1318 " <child1 foo='bar'/>"
1319 " <!-- comment thing -->"
1320 " <child2 val='1'>Text</child2>"
1321 "</root>";
1322 XMLDocument doc;
1323 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001324 XMLTest( "Parse before deep cloning root element", false, doc.Error() );
Lee Thomason7085f002017-06-01 18:09:43 -07001325
1326 doc.Print(&printer1);
1327 XMLNode* root = doc.RootElement()->DeepClone(&doc2);
1328 doc2.InsertFirstChild(root);
1329 }
1330 XMLPrinter printer2;
1331 doc2.Print(&printer2);
1332
1333 XMLTest("Deep clone of element.", printer1.CStr(), printer2.CStr(), true);
1334 }
1335
1336 {
1337 // Deep Cloning of sub element.
1338 XMLDocument doc2;
1339 XMLPrinter printer1;
1340 {
1341 // Make sure doc1 is deleted before we test doc2
1342 const char* xml =
1343 "<?xml version ='1.0'?>"
1344 "<root>"
1345 " <child1 foo='bar'/>"
1346 " <!-- comment thing -->"
1347 " <child2 val='1'>Text</child2>"
1348 "</root>";
1349 XMLDocument doc;
1350 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001351 XMLTest( "Parse before deep cloning sub element", false, doc.Error() );
Lee Thomason7085f002017-06-01 18:09:43 -07001352
1353 const XMLElement* subElement = doc.FirstChildElement("root")->FirstChildElement("child2");
Dmitry-Mef0f2e992017-09-25 17:38:42 +03001354 bool acceptResult = subElement->Accept(&printer1);
1355 XMLTest( "Accept before deep cloning", true, acceptResult );
Lee Thomason7085f002017-06-01 18:09:43 -07001356
1357 XMLNode* clonedSubElement = subElement->DeepClone(&doc2);
1358 doc2.InsertFirstChild(clonedSubElement);
1359 }
1360 XMLPrinter printer2;
1361 doc2.Print(&printer2);
1362
1363 XMLTest("Deep clone of sub-element.", printer1.CStr(), printer2.CStr(), true);
1364 }
1365
1366 {
1367 // Deep cloning of document.
1368 XMLDocument doc2;
1369 XMLPrinter printer1;
1370 {
1371 // Make sure doc1 is deleted before we test doc2
1372 const char* xml =
1373 "<?xml version ='1.0'?>"
1374 "<!-- Top level comment. -->"
1375 "<root>"
1376 " <child1 foo='bar'/>"
1377 " <!-- comment thing -->"
1378 " <child2 val='1'>Text</child2>"
1379 "</root>";
1380 XMLDocument doc;
1381 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001382 XMLTest( "Parse before deep cloning document", false, doc.Error() );
Lee Thomason7085f002017-06-01 18:09:43 -07001383 doc.Print(&printer1);
1384
1385 doc.DeepCopy(&doc2);
1386 }
1387 XMLPrinter printer2;
1388 doc2.Print(&printer2);
1389
1390 XMLTest("DeepCopy of document.", printer1.CStr(), printer2.CStr(), true);
1391 }
1392
1393
1394 {
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001395 // This shouldn't crash.
1396 XMLDocument doc;
Lee Thomason85536252016-06-04 19:10:53 -07001397 if(XML_SUCCESS != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001398 {
1399 doc.PrintError();
1400 }
1401 XMLTest( "Error in snprinf handling.", true, doc.Error() );
1402 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001403
Lee Thomason5e3803c2012-04-16 08:57:05 -07001404 {
1405 // Attribute ordering.
1406 static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
1407 XMLDocument doc;
1408 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001409 XMLTest( "Parse for attribute ordering", false, doc.Error() );
Lee Thomason5e3803c2012-04-16 08:57:05 -07001410 XMLElement* ele = doc.FirstChildElement();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001411
Lee Thomason5e3803c2012-04-16 08:57:05 -07001412 const XMLAttribute* a = ele->FirstAttribute();
1413 XMLTest( "Attribute order", "1", a->Value() );
1414 a = a->Next();
1415 XMLTest( "Attribute order", "2", a->Value() );
1416 a = a->Next();
1417 XMLTest( "Attribute order", "3", a->Value() );
1418 XMLTest( "Attribute order", "attrib3", a->Name() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001419
Lee Thomason5e3803c2012-04-16 08:57:05 -07001420 ele->DeleteAttribute( "attrib2" );
1421 a = ele->FirstAttribute();
1422 XMLTest( "Attribute order", "1", a->Value() );
1423 a = a->Next();
1424 XMLTest( "Attribute order", "3", a->Value() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001425
Lee Thomason5e3803c2012-04-16 08:57:05 -07001426 ele->DeleteAttribute( "attrib1" );
1427 ele->DeleteAttribute( "attrib3" );
Dmitry-Mebc6920b2017-08-03 18:46:31 +03001428 XMLTest( "Attribute order (empty)", true, ele->FirstAttribute() == 0 );
Lee Thomason5e3803c2012-04-16 08:57:05 -07001429 }
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001430
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001431 {
1432 // Make sure an attribute with a space in it succeeds.
Lee Thomason78a773d2012-07-02 10:10:19 -07001433 static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
1434 static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
1435 static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
1436 XMLDocument doc0;
1437 doc0.Parse( xml0 );
Dmitry-Me68578f42017-07-03 18:21:23 +03001438 XMLTest( "Parse attribute with space 1", false, doc0.Error() );
Lee Thomason78a773d2012-07-02 10:10:19 -07001439 XMLDocument doc1;
1440 doc1.Parse( xml1 );
Dmitry-Me68578f42017-07-03 18:21:23 +03001441 XMLTest( "Parse attribute with space 2", false, doc1.Error() );
Lee Thomason78a773d2012-07-02 10:10:19 -07001442 XMLDocument doc2;
1443 doc2.Parse( xml2 );
Dmitry-Me68578f42017-07-03 18:21:23 +03001444 XMLTest( "Parse attribute with space 3", false, doc2.Error() );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001445
Lee Thomason78a773d2012-07-02 10:10:19 -07001446 XMLElement* ele = 0;
1447 ele = doc0.FirstChildElement();
1448 XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
1449 ele = doc1.FirstChildElement();
1450 XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
1451 ele = doc2.FirstChildElement();
1452 XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001453 }
1454
1455 {
1456 // Make sure we don't go into an infinite loop.
1457 static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
1458 XMLDocument doc;
1459 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001460 XMLTest( "Parse two elements with attribute", false, doc.Error() );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001461 XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
1462 XMLElement* ele1 = ele0->NextSiblingElement();
1463 bool equal = ele0->ShallowEqual( ele1 );
1464
1465 XMLTest( "Infinite loop in shallow equal.", true, equal );
1466 }
1467
Lee Thomason5708f812012-03-28 17:46:41 -07001468 // -------- Handles ------------
1469 {
1470 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1471 XMLDocument doc;
1472 doc.Parse( xml );
Dmitry-Me938560f2018-03-15 01:30:39 +03001473 XMLTest( "Handle, parse element with attribute and nested element", false, doc.Error() );
Lee Thomason5708f812012-03-28 17:46:41 -07001474
Dmitry-Me938560f2018-03-15 01:30:39 +03001475 {
1476 XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
1477 XMLTest( "Handle, non-const, element is found", true, ele != 0 );
1478 XMLTest( "Handle, non-const, element name matches", "sub", ele->Value() );
1479 }
Lee Thomason5708f812012-03-28 17:46:41 -07001480
Dmitry-Me938560f2018-03-15 01:30:39 +03001481 {
1482 XMLHandle docH( doc );
1483 XMLElement* ele = docH.FirstChildElement( "noSuchElement" ).FirstChildElement( "element" ).ToElement();
1484 XMLTest( "Handle, non-const, element not found", true, ele == 0 );
1485 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001486
Dmitry-Me938560f2018-03-15 01:30:39 +03001487 {
1488 const XMLElement* ele = XMLConstHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
1489 XMLTest( "Handle, const, element is found", true, ele != 0 );
1490 XMLTest( "Handle, const, element name matches", "sub", ele->Value() );
1491 }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001492
Dmitry-Me938560f2018-03-15 01:30:39 +03001493 {
1494 XMLConstHandle docH( doc );
1495 const XMLElement* ele = docH.FirstChildElement( "noSuchElement" ).FirstChildElement( "element" ).ToElement();
1496 XMLTest( "Handle, const, element not found", true, ele == 0 );
1497 }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001498 }
Lee Thomasonf68c4382012-04-28 14:37:11 -07001499 {
1500 // Default Declaration & BOM
1501 XMLDocument doc;
1502 doc.InsertEndChild( doc.NewDeclaration() );
1503 doc.SetBOM( true );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001504
Lee Thomasonf68c4382012-04-28 14:37:11 -07001505 XMLPrinter printer;
1506 doc.Print( &printer );
1507
1508 static const char* result = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001509 XMLTest( "BOM and default declaration", result, printer.CStr(), false );
1510 XMLTest( "CStrSize", 42, printer.CStrSize(), false );
Lee Thomasonf68c4382012-04-28 14:37:11 -07001511 }
Lee Thomason21be8822012-07-15 17:27:22 -07001512 {
1513 const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
1514 XMLDocument doc;
1515 doc.Parse( xml );
1516 XMLTest( "Ill formed XML", true, doc.Error() );
1517 }
1518
1519 // QueryXYZText
1520 {
1521 const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
1522 XMLDocument doc;
1523 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001524 XMLTest( "Parse points", false, doc.Error() );
Lee Thomason21be8822012-07-15 17:27:22 -07001525
1526 const XMLElement* pointElement = doc.RootElement();
1527
Dmitry-Me43c019d2017-08-02 18:05:23 +03001528 {
1529 int intValue = 0;
1530 XMLError queryResult = pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
1531 XMLTest( "QueryIntText result", XML_SUCCESS, queryResult, false );
1532 XMLTest( "QueryIntText", 1, intValue, false );
1533 }
Lee Thomason21be8822012-07-15 17:27:22 -07001534
Dmitry-Me43c019d2017-08-02 18:05:23 +03001535 {
1536 unsigned unsignedValue = 0;
1537 XMLError queryResult = pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
1538 XMLTest( "QueryUnsignedText result", XML_SUCCESS, queryResult, false );
1539 XMLTest( "QueryUnsignedText", (unsigned)1, unsignedValue, false );
1540 }
Lee Thomason21be8822012-07-15 17:27:22 -07001541
Dmitry-Me43c019d2017-08-02 18:05:23 +03001542 {
1543 float floatValue = 0;
1544 XMLError queryResult = pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
1545 XMLTest( "QueryFloatText result", XML_SUCCESS, queryResult, false );
1546 XMLTest( "QueryFloatText", 1.2f, floatValue, false );
1547 }
Lee Thomason21be8822012-07-15 17:27:22 -07001548
Dmitry-Me43c019d2017-08-02 18:05:23 +03001549 {
1550 double doubleValue = 0;
1551 XMLError queryResult = pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
1552 XMLTest( "QueryDoubleText result", XML_SUCCESS, queryResult, false );
1553 XMLTest( "QueryDoubleText", 1.2, doubleValue, false );
1554 }
1555
1556 {
1557 bool boolValue = false;
1558 XMLError queryResult = pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
1559 XMLTest( "QueryBoolText result", XML_SUCCESS, queryResult, false );
1560 XMLTest( "QueryBoolText", true, boolValue, false );
1561 }
Lee Thomason21be8822012-07-15 17:27:22 -07001562 }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001563
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001564 {
1565 const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
1566 XMLDocument doc;
1567 doc.Parse( xml );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001568 XMLTest( "Non-alpha element lead letter parses.", false, doc.Error() );
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001569 }
Lee Thomasonc4836462018-06-29 15:57:55 -07001570
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001571 {
1572 const char* xml = "<element _attr1=\"foo\" :attr2=\"bar\"></element>";
1573 XMLDocument doc;
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001574 doc.Parse( xml );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001575 XMLTest("Non-alpha attribute lead character parses.", false, doc.Error());
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001576 }
Lee Thomasonc4836462018-06-29 15:57:55 -07001577
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001578 {
1579 const char* xml = "<3lement></3lement>";
1580 XMLDocument doc;
1581 doc.Parse( xml );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001582 XMLTest("Element names with lead digit fail to parse.", true, doc.Error());
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001583 }
Lee Thomason (grinliz)62d1c5a2012-09-08 21:44:12 -07001584
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001585 {
1586 const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
1587 XMLDocument doc;
1588 doc.Parse( xml, 10 );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001589 XMLTest( "Set length of incoming data", false, doc.Error() );
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001590 }
1591
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001592 {
1593 XMLDocument doc;
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001594 XMLTest( "Document is initially empty", true, doc.NoChildren() );
Dmitry-Me48b5df02015-04-06 18:20:25 +03001595 doc.Clear();
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001596 XMLTest( "Empty is empty after Clear()", true, doc.NoChildren() );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001597 doc.LoadFile( "resources/dream.xml" );
Dmitry-Me46b70ce2017-07-10 17:54:24 +03001598 XMLTest( "Load dream.xml", false, doc.Error() );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001599 XMLTest( "Document has something to Clear()", false, doc.NoChildren() );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001600 doc.Clear();
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001601 XMLTest( "Document Clear()'s", true, doc.NoChildren() );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001602 }
Dmitry-Me985ea1f2017-08-28 18:36:29 +03001603
1604 {
1605 XMLDocument doc;
1606 XMLTest( "No error initially", false, doc.Error() );
1607 XMLError error = doc.Parse( "This is not XML" );
1608 XMLTest( "Error after invalid XML", true, doc.Error() );
1609 XMLTest( "Error after invalid XML", error, doc.ErrorID() );
1610 doc.Clear();
1611 XMLTest( "No error after Clear()", false, doc.Error() );
1612 }
Lee Thomasonc4836462018-06-29 15:57:55 -07001613
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001614 // ----------- Whitespace ------------
1615 {
1616 const char* xml = "<element>"
1617 "<a> This \nis &apos; text &apos; </a>"
1618 "<b> This is &apos; text &apos; \n</b>"
1619 "<c>This is &apos; \n\n text &apos;</c>"
1620 "</element>";
1621 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1622 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001623 XMLTest( "Parse with whitespace collapsing and &apos", false, doc.Error() );
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001624
1625 const XMLElement* element = doc.FirstChildElement();
1626 for( const XMLElement* parent = element->FirstChildElement();
1627 parent;
1628 parent = parent->NextSiblingElement() )
1629 {
1630 XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
1631 }
1632 }
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001633
Lee Thomasonae9ab072012-10-24 10:17:53 -07001634#if 0
1635 {
1636 // Passes if assert doesn't fire.
1637 XMLDocument xmlDoc;
1638
1639 xmlDoc.NewDeclaration();
1640 xmlDoc.NewComment("Configuration file");
1641
1642 XMLElement *root = xmlDoc.NewElement("settings");
1643 root->SetAttribute("version", 2);
1644 }
1645#endif
1646
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001647 {
1648 const char* xml = "<element> </element>";
1649 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1650 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001651 XMLTest( "Parse with all whitespaces", false, doc.Error() );
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001652 XMLTest( "Whitespace all space", true, 0 == doc.FirstChildElement()->FirstChild() );
1653 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001654
Lee Thomason5b0a6772012-11-19 13:54:42 -08001655 {
1656 // An assert should not fire.
1657 const char* xml = "<element/>";
1658 XMLDocument doc;
1659 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001660 XMLTest( "Parse with self-closed element", false, doc.Error() );
Lee Thomason5b0a6772012-11-19 13:54:42 -08001661 XMLElement* ele = doc.NewElement( "unused" ); // This will get cleaned up with the 'doc' going out of scope.
1662 XMLTest( "Tracking unused elements", true, ele != 0, false );
1663 }
1664
Lee Thomasona6412ac2012-12-13 15:39:11 -08001665
1666 {
1667 const char* xml = "<parent><child>abc</child></parent>";
1668 XMLDocument doc;
1669 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001670 XMLTest( "Parse for printing of sub-element", false, doc.Error() );
Lee Thomasona6412ac2012-12-13 15:39:11 -08001671 XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child");
1672
1673 XMLPrinter printer;
Dmitry-Mef0f2e992017-09-25 17:38:42 +03001674 bool acceptResult = ele->Accept( &printer );
1675 XMLTest( "Accept of sub-element", true, acceptResult );
Lee Thomasona6412ac2012-12-13 15:39:11 -08001676 XMLTest( "Printing of sub-element", "<child>abc</child>\n", printer.CStr(), false );
1677 }
1678
1679
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001680 {
1681 XMLDocument doc;
1682 XMLError error = doc.LoadFile( "resources/empty.xml" );
1683 XMLTest( "Loading an empty file", XML_ERROR_EMPTY_DOCUMENT, error );
Lee Thomason331596e2014-09-11 14:56:43 -07001684 XMLTest( "Loading an empty file and ErrorName as string", "XML_ERROR_EMPTY_DOCUMENT", doc.ErrorName() );
Lee Thomasonc7556672014-09-14 12:39:42 -07001685 doc.PrintError();
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001686 }
1687
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001688 {
1689 // BOM preservation
1690 static const char* xml_bom_preservation = "\xef\xbb\xbf<element/>\n";
1691 {
1692 XMLDocument doc;
Lee Thomason85536252016-06-04 19:10:53 -07001693 XMLTest( "BOM preservation (parse)", XML_SUCCESS, doc.Parse( xml_bom_preservation ), false );
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001694 XMLPrinter printer;
1695 doc.Print( &printer );
1696
1697 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1698 doc.SaveFile( "resources/bomtest.xml" );
Dmitry-Me46b70ce2017-07-10 17:54:24 +03001699 XMLTest( "Save bomtest.xml", false, doc.Error() );
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001700 }
1701 {
1702 XMLDocument doc;
1703 doc.LoadFile( "resources/bomtest.xml" );
Dmitry-Me46b70ce2017-07-10 17:54:24 +03001704 XMLTest( "Load bomtest.xml", false, doc.Error() );
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001705 XMLTest( "BOM preservation (load)", true, doc.HasBOM(), false );
1706
1707 XMLPrinter printer;
1708 doc.Print( &printer );
1709 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1710 }
1711 }
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001712
Michael Daumlinged523282013-10-23 07:47:29 +02001713 {
1714 // Insertion with Removal
1715 const char* xml = "<?xml version=\"1.0\" ?>"
1716 "<root>"
1717 "<one>"
1718 "<subtree>"
1719 "<elem>element 1</elem>text<!-- comment -->"
1720 "</subtree>"
1721 "</one>"
1722 "<two/>"
1723 "</root>";
1724 const char* xmlInsideTwo = "<?xml version=\"1.0\" ?>"
1725 "<root>"
1726 "<one/>"
1727 "<two>"
1728 "<subtree>"
1729 "<elem>element 1</elem>text<!-- comment -->"
1730 "</subtree>"
1731 "</two>"
1732 "</root>";
1733 const char* xmlAfterOne = "<?xml version=\"1.0\" ?>"
1734 "<root>"
1735 "<one/>"
1736 "<subtree>"
1737 "<elem>element 1</elem>text<!-- comment -->"
1738 "</subtree>"
1739 "<two/>"
1740 "</root>";
1741 const char* xmlAfterTwo = "<?xml version=\"1.0\" ?>"
1742 "<root>"
1743 "<one/>"
1744 "<two/>"
1745 "<subtree>"
1746 "<elem>element 1</elem>text<!-- comment -->"
1747 "</subtree>"
1748 "</root>";
1749
1750 XMLDocument doc;
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001751 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001752 XMLTest( "Insertion with removal parse round 1", false, doc.Error() );
Michael Daumlinged523282013-10-23 07:47:29 +02001753 XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1754 XMLElement* two = doc.RootElement()->FirstChildElement("two");
1755 two->InsertFirstChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001756 XMLPrinter printer1(0, true);
Dmitry-Mef0f2e992017-09-25 17:38:42 +03001757 bool acceptResult = doc.Accept(&printer1);
1758 XMLTest("Move node from within <one> to <two> - Accept()", true, acceptResult);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001759 XMLTest("Move node from within <one> to <two>", xmlInsideTwo, printer1.CStr());
Michael Daumlinged523282013-10-23 07:47:29 +02001760
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001761 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001762 XMLTest( "Insertion with removal parse round 2", false, doc.Error() );
Michael Daumlinged523282013-10-23 07:47:29 +02001763 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1764 two = doc.RootElement()->FirstChildElement("two");
1765 doc.RootElement()->InsertAfterChild(two, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001766 XMLPrinter printer2(0, true);
Dmitry-Mef0f2e992017-09-25 17:38:42 +03001767 acceptResult = doc.Accept(&printer2);
1768 XMLTest("Move node from within <one> after <two> - Accept()", true, acceptResult);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001769 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer2.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001770
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001771 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001772 XMLTest( "Insertion with removal parse round 3", false, doc.Error() );
Michael Daumlinged523282013-10-23 07:47:29 +02001773 XMLNode* one = doc.RootElement()->FirstChildElement("one");
1774 subtree = one->FirstChildElement("subtree");
1775 doc.RootElement()->InsertAfterChild(one, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001776 XMLPrinter printer3(0, true);
Dmitry-Mef0f2e992017-09-25 17:38:42 +03001777 acceptResult = doc.Accept(&printer3);
1778 XMLTest("Move node from within <one> after <one> - Accept()", true, acceptResult);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001779 XMLTest("Move node from within <one> after <one>", xmlAfterOne, printer3.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001780
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001781 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001782 XMLTest( "Insertion with removal parse round 4", false, doc.Error() );
Michael Daumlinged523282013-10-23 07:47:29 +02001783 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1784 two = doc.RootElement()->FirstChildElement("two");
1785 doc.RootElement()->InsertEndChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001786 XMLPrinter printer4(0, true);
Dmitry-Mef0f2e992017-09-25 17:38:42 +03001787 acceptResult = doc.Accept(&printer4);
1788 XMLTest("Move node from within <one> after <two> - Accept()", true, acceptResult);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001789 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer4.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001790 }
1791
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001792 {
1793 const char* xml = "<svg width = \"128\" height = \"128\">"
1794 " <text> </text>"
1795 "</svg>";
1796 XMLDocument doc;
1797 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001798 XMLTest( "Parse svg with text", false, doc.Error() );
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001799 doc.Print();
1800 }
1801
Lee Thomason92e521b2014-11-15 17:45:51 -08001802 {
1803 // Test that it doesn't crash.
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001804 const char* xml = "<?xml version=\"1.0\"?><root><sample><field0><1</field0><field1>2</field1></sample></root>";
1805 XMLDocument doc;
1806 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001807 XMLTest( "Parse root-sample-field0", true, doc.Error() );
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001808 doc.PrintError();
Lee Thomason92e521b2014-11-15 17:45:51 -08001809 }
1810
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001811#if 1
Lee Thomasonc4836462018-06-29 15:57:55 -07001812 // the question being explored is what kind of print to use:
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001813 // https://github.com/leethomason/tinyxml2/issues/63
1814 {
1815 //const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9' attrC='1.0e-10' attrD='1001000000.000000' attrE='0.1234567890123456789'/>";
1816 const char* xml = "<element/>";
1817 XMLDocument doc;
1818 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001819 XMLTest( "Parse self-closed empty element", false, doc.Error() );
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001820 doc.FirstChildElement()->SetAttribute( "attrA-f64", 123456789.123456789 );
1821 doc.FirstChildElement()->SetAttribute( "attrB-f64", 1.001e9 );
1822 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e9 );
1823 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e20 );
1824 doc.FirstChildElement()->SetAttribute( "attrD-f64", 1.0e-10 );
1825 doc.FirstChildElement()->SetAttribute( "attrD-f64", 0.123456789 );
1826
1827 doc.FirstChildElement()->SetAttribute( "attrA-f32", 123456789.123456789f );
1828 doc.FirstChildElement()->SetAttribute( "attrB-f32", 1.001e9f );
1829 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e9f );
1830 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e20f );
1831 doc.FirstChildElement()->SetAttribute( "attrD-f32", 1.0e-10f );
1832 doc.FirstChildElement()->SetAttribute( "attrD-f32", 0.123456789f );
1833
1834 doc.Print();
1835
1836 /* The result of this test is platform, compiler, and library version dependent. :("
1837 XMLPrinter printer;
1838 doc.Print( &printer );
Lee Thomasonc4836462018-06-29 15:57:55 -07001839 XMLTest( "Float and double formatting.",
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001840 "<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",
Lee Thomasonc4836462018-06-29 15:57:55 -07001841 printer.CStr(),
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001842 true );
1843 */
1844 }
1845#endif
Lee Thomasonc4836462018-06-29 15:57:55 -07001846
Lee Thomasonf07b9522014-10-30 13:25:12 -07001847 {
1848 // Issue #184
1849 // If it doesn't assert, it passes. Caused by objects
1850 // getting created during parsing which are then
1851 // inaccessible in the memory pools.
Dmitry-Me5d1aec12017-06-28 14:51:17 +03001852 const char* xmlText = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>";
Lee Thomasonf07b9522014-10-30 13:25:12 -07001853 {
1854 XMLDocument doc;
Dmitry-Me5d1aec12017-06-28 14:51:17 +03001855 doc.Parse(xmlText);
Dmitry-Me68578f42017-07-03 18:21:23 +03001856 XMLTest( "Parse hex no closing tag round 1", true, doc.Error() );
Lee Thomasonf07b9522014-10-30 13:25:12 -07001857 }
1858 {
1859 XMLDocument doc;
Dmitry-Me5d1aec12017-06-28 14:51:17 +03001860 doc.Parse(xmlText);
Dmitry-Me68578f42017-07-03 18:21:23 +03001861 XMLTest( "Parse hex no closing tag round 2", true, doc.Error() );
Lee Thomasonf07b9522014-10-30 13:25:12 -07001862 doc.Clear();
1863 }
1864 }
Lee Thomasonc4836462018-06-29 15:57:55 -07001865
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001866 {
Peter Matula50689912018-01-09 12:52:26 +01001867 // If this doesn't assert in TINYXML2_DEBUG, all is well.
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001868 tinyxml2::XMLDocument doc;
1869 tinyxml2::XMLElement *pRoot = doc.NewElement("Root");
1870 doc.DeleteNode(pRoot);
1871 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001872
Dmitry-Mee5790db2017-07-28 17:54:38 +03001873 {
1874 XMLDocument doc;
1875 XMLElement* root = doc.NewElement( "Root" );
1876 XMLTest( "Node document before insertion", true, &doc == root->GetDocument() );
1877 doc.InsertEndChild( root );
1878 XMLTest( "Node document after insertion", true, &doc == root->GetDocument() );
1879 }
1880
1881 {
Peter Matula50689912018-01-09 12:52:26 +01001882 // If this doesn't assert in TINYXML2_DEBUG, all is well.
Dmitry-Mee5790db2017-07-28 17:54:38 +03001883 XMLDocument doc;
1884 XMLElement* unlinkedRoot = doc.NewElement( "Root" );
1885 XMLElement* linkedRoot = doc.NewElement( "Root" );
1886 doc.InsertFirstChild( linkedRoot );
1887 unlinkedRoot->GetDocument()->DeleteNode( linkedRoot );
1888 unlinkedRoot->GetDocument()->DeleteNode( unlinkedRoot );
1889 }
1890
Dmitry-Me8b67d742014-12-22 11:35:12 +03001891 {
Peter Matula50689912018-01-09 12:52:26 +01001892 // Should not assert in TINYXML2_DEBUG
Dmitry-Me8b67d742014-12-22 11:35:12 +03001893 XMLPrinter printer;
1894 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001895
Dmitry-Me6f51c802015-03-14 13:25:03 +03001896 {
1897 // Issue 291. Should not crash
1898 const char* xml = "&#0</a>";
1899 XMLDocument doc;
1900 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001901 XMLTest( "Parse hex with closing tag", false, doc.Error() );
Dmitry-Me6f51c802015-03-14 13:25:03 +03001902
1903 XMLPrinter printer;
1904 doc.Print( &printer );
1905 }
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001906 {
Lee Thomasonc4836462018-06-29 15:57:55 -07001907 // Issue 299. Can print elements that are not linked in.
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001908 // Will crash if issue not fixed.
1909 XMLDocument doc;
1910 XMLElement* newElement = doc.NewElement( "printme" );
1911 XMLPrinter printer;
Dmitry-Mef0f2e992017-09-25 17:38:42 +03001912 bool acceptResult = newElement->Accept( &printer );
1913 XMLTest( "printme - Accept()", true, acceptResult );
Dmitry-Me5daa54c2015-04-08 17:45:07 +03001914 // Delete the node to avoid possible memory leak report in debug output
1915 doc.DeleteNode( newElement );
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001916 }
Lee Thomasonf6577832015-03-26 11:18:21 -07001917 {
Ant Mitchell189198f2015-03-24 16:20:36 +00001918 // Issue 302. Clear errors from LoadFile/SaveFile
1919 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001920 XMLTest( "Issue 302. Should be no error initially", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001921 doc.SaveFile( "./no/such/path/pretty.xml" );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001922 XMLTest( "Issue 302. Fail to save", "XML_ERROR_FILE_COULD_NOT_BE_OPENED", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001923 doc.SaveFile( "./resources/out/compact.xml", true );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001924 XMLTest( "Issue 302. Subsequent success in saving", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001925 }
Dmitry-Me6f51c802015-03-14 13:25:03 +03001926
Dmitry-Med9852a52015-03-25 10:17:49 +03001927 {
1928 // If a document fails to load then subsequent
1929 // successful loads should clear the error
1930 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001931 XMLTest( "Should be no error initially", false, doc.Error() );
Dmitry-Med9852a52015-03-25 10:17:49 +03001932 doc.LoadFile( "resources/no-such-file.xml" );
1933 XMLTest( "No such file - should fail", true, doc.Error() );
1934
1935 doc.LoadFile( "resources/dream.xml" );
1936 XMLTest( "Error should be cleared", false, doc.Error() );
1937 }
Sarat Addepalli8e85afa2015-05-19 09:07:03 +05301938
Sarat Addepalli2bb6bb52015-05-18 09:16:34 +05301939 {
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001940 // Check that declarations are allowed only at beginning of document
Lee Thomason85492022015-05-22 11:07:45 -07001941 const char* xml0 = "<?xml version=\"1.0\" ?>"
1942 " <!-- xml version=\"1.1\" -->"
1943 "<first />";
1944 const char* xml1 = "<?xml version=\"1.0\" ?>"
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001945 "<?xml-stylesheet type=\"text/xsl\" href=\"Anything.xsl\"?>"
Lee Thomason85492022015-05-22 11:07:45 -07001946 "<first />";
1947 const char* xml2 = "<first />"
1948 "<?xml version=\"1.0\" ?>";
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001949 const char* xml3 = "<first></first>"
1950 "<?xml version=\"1.0\" ?>";
1951
1952 const char* xml4 = "<first><?xml version=\"1.0\" ?></first>";
1953
Lee Thomason85492022015-05-22 11:07:45 -07001954 XMLDocument doc;
1955 doc.Parse(xml0);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001956 XMLTest("Test that the code changes do not affect normal parsing", false, doc.Error() );
Lee Thomason85492022015-05-22 11:07:45 -07001957 doc.Parse(xml1);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001958 XMLTest("Test that the second declaration is allowed", false, doc.Error() );
Lee Thomason85492022015-05-22 11:07:45 -07001959 doc.Parse(xml2);
Dmitry-Me6a18a312018-03-23 21:09:13 +03001960 XMLTest("Test that declaration after self-closed child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001961 doc.Parse(xml3);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001962 XMLTest("Test that declaration after a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001963 doc.Parse(xml4);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001964 XMLTest("Test that declaration inside a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );
Sarat Addepalli2bb6bb52015-05-18 09:16:34 +05301965 }
Dmitry-Med9852a52015-03-25 10:17:49 +03001966
Lee Thomason85492022015-05-22 11:07:45 -07001967 {
1968 // No matter - before or after successfully parsing a text -
Dmitry-Me26043362017-08-30 17:40:15 +03001969 // calling XMLDocument::Value() used to cause an assert in debug.
orbitcowboy22b21ec2018-07-17 11:52:57 +02001970 // Null must be returned.
Lee Thomason85492022015-05-22 11:07:45 -07001971 const char* validXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
1972 "<first />"
1973 "<second />";
1974 XMLDocument* doc = new XMLDocument();
1975 XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
1976 doc->Parse( validXml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001977 XMLTest( "Parse to test XMLDocument::Value()", false, doc->Error());
Lee Thomason85492022015-05-22 11:07:45 -07001978 XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
1979 delete doc;
1980 }
1981
Dmitry-Mea1beddf2015-05-26 16:19:21 +03001982 {
1983 XMLDocument doc;
1984 for( int i = 0; i < XML_ERROR_COUNT; i++ ) {
Dmitry-Med3f6c632017-08-30 17:43:14 +03001985 const XMLError error = static_cast<XMLError>(i);
Lee Thomasonf49b9652017-10-11 10:57:49 -07001986 const char* name = XMLDocument::ErrorIDToName(error);
Dmitry-Me95f687b2018-03-23 20:56:46 +03001987 XMLTest( "ErrorName() not null after ClearError()", true, name != 0 );
1988 if( name == 0 ) {
1989 // passing null pointer into strlen() is undefined behavior, so
1990 // compiler is allowed to optimise away the null test above if it's
1991 // as reachable as the strlen() call
1992 continue;
1993 }
1994 XMLTest( "ErrorName() not empty after ClearError()", true, strlen(name) > 0 );
Dmitry-Mea1beddf2015-05-26 16:19:21 +03001995 }
1996 }
1997
Lee Thomason816d3fa2017-06-05 14:35:55 -07001998 {
Derek Quambe69ae62018-04-18 13:40:46 -05001999 const char* html("<!DOCTYPE html><html><body><p>test</p><p><br/></p></body></html>");
2000 XMLDocument doc(false);
2001 doc.Parse(html);
2002
2003 XMLPrinter printer(0, true);
2004 doc.Print(&printer);
2005
2006 XMLTest(html, html, printer.CStr());
2007 }
2008
2009 {
Lee Thomasonc4836462018-06-29 15:57:55 -07002010 // Evil memory leaks.
Lee Thomasonb754ddf2017-06-14 15:02:38 -07002011 // If an XMLElement (etc) is allocated via NewElement() (etc.)
2012 // and NOT added to the XMLDocument, what happens?
2013 //
2014 // Previously (buggy):
2015 // The memory would be free'd when the XMLDocument is
Dmitry-Mea9e75d12017-09-08 19:05:23 +03002016 // destructed. But the XMLElement destructor wasn't called, so
2017 // memory allocated for the XMLElement text would not be free'd.
2018 // In practice this meant strings allocated for the XMLElement
2019 // text would be leaked. An edge case, but annoying.
Lee Thomasonb754ddf2017-06-14 15:02:38 -07002020 // Now:
Dmitry-Mea9e75d12017-09-08 19:05:23 +03002021 // The XMLElement destructor is called. But the unlinked nodes
2022 // have to be tracked using a list. This has a minor performance
2023 // impact that can become significant if you have a lot of
2024 // unlinked nodes. (But why would you do that?)
2025 // The only way to see this bug was in a Visual C++ runtime debug heap
2026 // leak tracker. This is compiled in by default on Windows Debug and
2027 // enabled with _CRTDBG_LEAK_CHECK_DF parameter passed to _CrtSetDbgFlag().
Lee Thomason816d3fa2017-06-05 14:35:55 -07002028 {
2029 XMLDocument doc;
2030 doc.NewElement("LEAK 1");
2031 }
2032 {
2033 XMLDocument doc;
2034 XMLElement* ele = doc.NewElement("LEAK 2");
2035 doc.DeleteNode(ele);
2036 }
2037 }
2038
Lee Thomason224ef772017-06-16 09:45:26 -07002039 {
Lee Thomasonf928c352018-04-05 09:24:20 -07002040 // Bad bad crash. Parsing error results in stack overflow, if uncaught.
2041 const char* TESTS[] = {
2042 "./resources/xmltest-5330.xml",
2043 "./resources/xmltest-4636783552757760.xml",
2044 "./resources/xmltest-5720541257269248.xml",
2045 0
2046 };
2047 for (int i=0; TESTS[i]; ++i) {
2048 XMLDocument doc;
2049 doc.LoadFile(TESTS[i]);
Lee Thomasone2d02e12018-04-05 15:57:48 -07002050 XMLTest("Stack overflow prevented.", XML_ELEMENT_DEPTH_EXCEEDED, doc.ErrorID());
Lee Thomasonf928c352018-04-05 09:24:20 -07002051 }
Lee Thomasond946dda2018-04-05 09:11:08 -07002052 }
Lee Thomasond946dda2018-04-05 09:11:08 -07002053 {
Lee Thomason224ef772017-06-16 09:45:26 -07002054 // Crashing reported via email.
2055 const char* xml =
2056 "<playlist id='playlist1'>"
Lee Thomason82bb0742017-06-16 09:48:20 -07002057 "<property name='track_name'>voice</property>"
2058 "<property name='audio_track'>1</property>"
2059 "<entry out = '604' producer = '4_playlist1' in = '0' />"
2060 "<blank length = '1' />"
2061 "<entry out = '1625' producer = '3_playlist' in = '0' />"
2062 "<blank length = '2' />"
2063 "<entry out = '946' producer = '2_playlist1' in = '0' />"
2064 "<blank length = '1' />"
2065 "<entry out = '128' producer = '1_playlist1' in = '0' />"
Lee Thomason224ef772017-06-16 09:45:26 -07002066 "</playlist>";
Lee Thomason82bb0742017-06-16 09:48:20 -07002067
Lee Thomason224ef772017-06-16 09:45:26 -07002068 // It's not a good idea to delete elements as you walk the
2069 // list. I'm not sure this technically should work; but it's
2070 // an interesting test case.
2071 XMLDocument doc;
2072 XMLError err = doc.Parse(xml);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03002073 XMLTest("Crash bug parsing", XML_SUCCESS, err );
Dmitry-Meaea64c42017-06-20 18:20:15 +03002074
2075 XMLElement* playlist = doc.FirstChildElement("playlist");
Lee Thomason224ef772017-06-16 09:45:26 -07002076 XMLTest("Crash bug parsing", true, playlist != 0);
2077
Dmitry-Meb41e24a2017-09-27 18:51:01 +03002078 {
2079 const char* elementName = "entry";
2080 XMLElement* entry = playlist->FirstChildElement(elementName);
2081 XMLTest("Crash bug parsing", true, entry != 0);
2082 while (entry) {
2083 XMLElement* todelete = entry;
2084 entry = entry->NextSiblingElement(elementName);
2085 playlist->DeleteChild(todelete);
2086 }
2087 entry = playlist->FirstChildElement(elementName);
2088 XMLTest("Crash bug parsing", true, entry == 0);
2089 }
2090 {
2091 const char* elementName = "blank";
2092 XMLElement* blank = playlist->FirstChildElement(elementName);
2093 XMLTest("Crash bug parsing", true, blank != 0);
2094 while (blank) {
2095 XMLElement* todelete = blank;
2096 blank = blank->NextSiblingElement(elementName);
2097 playlist->DeleteChild(todelete);
2098 }
2099 XMLTest("Crash bug parsing", true, blank == 0);
2100 }
Lee Thomason224ef772017-06-16 09:45:26 -07002101
2102 tinyxml2::XMLPrinter printer;
Dmitry-Mef0f2e992017-09-25 17:38:42 +03002103 const bool acceptResult = playlist->Accept(&printer);
2104 XMLTest("Crash bug parsing - Accept()", true, acceptResult);
Lee Thomason224ef772017-06-16 09:45:26 -07002105 printf("%s\n", printer.CStr());
2106
Lee Thomasonc4836462018-06-29 15:57:55 -07002107 // No test; it only need to not crash.
Lee Thomason82bb0742017-06-16 09:48:20 -07002108 // Still, wrap it up with a sanity check
2109 int nProperty = 0;
2110 for (const XMLElement* p = playlist->FirstChildElement("property"); p; p = p->NextSiblingElement("property")) {
2111 nProperty++;
2112 }
Dmitry-Me9832a5f2017-06-23 18:29:16 +03002113 XMLTest("Crash bug parsing", 2, nProperty);
Lee Thomason224ef772017-06-16 09:45:26 -07002114 }
2115
kezenatorec694152016-11-26 17:21:43 +10002116 // ----------- Line Number Tracking --------------
2117 {
Lee Thomasone90e9012016-12-24 07:34:39 -08002118 struct TestUtil: XMLVisitor
kezenatorec694152016-11-26 17:21:43 +10002119 {
Thierry Lelegard7f0f7542017-09-01 10:14:16 +02002120 TestUtil() : str() {}
2121
kezenatorec694152016-11-26 17:21:43 +10002122 void TestParseError(const char *testString, const char *docStr, XMLError expected_error, int expectedLine)
2123 {
2124 XMLDocument doc;
Dmitry-Me8d40f7a2017-08-09 19:10:08 +03002125 const XMLError parseError = doc.Parse(docStr);
kezenatorec694152016-11-26 17:21:43 +10002126
Dmitry-Me8d40f7a2017-08-09 19:10:08 +03002127 XMLTest(testString, parseError, doc.ErrorID());
kezenatorec694152016-11-26 17:21:43 +10002128 XMLTest(testString, true, doc.Error());
Dmitry-Me8d40f7a2017-08-09 19:10:08 +03002129 XMLTest(testString, expected_error, parseError);
Lee Thomasonf49b9652017-10-11 10:57:49 -07002130 XMLTest(testString, expectedLine, doc.ErrorLineNum());
kezenatorec694152016-11-26 17:21:43 +10002131 };
2132
2133 void TestStringLines(const char *testString, const char *docStr, const char *expectedLines)
2134 {
2135 XMLDocument doc;
2136 doc.Parse(docStr);
2137 XMLTest(testString, false, doc.Error());
2138 TestDocLines(testString, doc, expectedLines);
2139 }
2140
2141 void TestFileLines(const char *testString, const char *file_name, const char *expectedLines)
2142 {
2143 XMLDocument doc;
2144 doc.LoadFile(file_name);
2145 XMLTest(testString, false, doc.Error());
2146 TestDocLines(testString, doc, expectedLines);
2147 }
2148
2149 private:
2150 DynArray<char, 10> str;
2151
2152 void Push(char type, int lineNum)
2153 {
2154 str.Push(type);
2155 str.Push(char('0' + (lineNum / 10)));
2156 str.Push(char('0' + (lineNum % 10)));
2157 }
2158
2159 bool VisitEnter(const XMLDocument& doc)
2160 {
kezenator19d8ea82016-11-29 19:50:27 +10002161 Push('D', doc.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10002162 return true;
2163 }
2164 bool VisitEnter(const XMLElement& element, const XMLAttribute* firstAttribute)
2165 {
kezenator19d8ea82016-11-29 19:50:27 +10002166 Push('E', element.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10002167 for (const XMLAttribute *attr = firstAttribute; attr != 0; attr = attr->Next())
kezenator19d8ea82016-11-29 19:50:27 +10002168 Push('A', attr->GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10002169 return true;
2170 }
2171 bool Visit(const XMLDeclaration& declaration)
2172 {
kezenator19d8ea82016-11-29 19:50:27 +10002173 Push('L', declaration.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10002174 return true;
2175 }
2176 bool Visit(const XMLText& text)
2177 {
kezenator19d8ea82016-11-29 19:50:27 +10002178 Push('T', text.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10002179 return true;
2180 }
2181 bool Visit(const XMLComment& comment)
2182 {
kezenator19d8ea82016-11-29 19:50:27 +10002183 Push('C', comment.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10002184 return true;
2185 }
2186 bool Visit(const XMLUnknown& unknown)
2187 {
kezenator19d8ea82016-11-29 19:50:27 +10002188 Push('U', unknown.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10002189 return true;
2190 }
2191
2192 void TestDocLines(const char *testString, XMLDocument &doc, const char *expectedLines)
2193 {
2194 str.Clear();
Dmitry-Mef0f2e992017-09-25 17:38:42 +03002195 const bool acceptResult = doc.Accept(this);
2196 XMLTest(testString, true, acceptResult);
kezenatorec694152016-11-26 17:21:43 +10002197 str.Push(0);
2198 XMLTest(testString, expectedLines, str.Mem());
2199 }
Lee Thomasone90e9012016-12-24 07:34:39 -08002200 } tester;
kezenatorec694152016-11-26 17:21:43 +10002201
Lee Thomasone90e9012016-12-24 07:34:39 -08002202 tester.TestParseError("ErrorLine-Parsing", "\n<root>\n foo \n<unclosed/>", XML_ERROR_PARSING, 2);
2203 tester.TestParseError("ErrorLine-Declaration", "<root>\n<?xml version=\"1.0\"?>", XML_ERROR_PARSING_DECLARATION, 2);
2204 tester.TestParseError("ErrorLine-Mismatch", "\n<root>\n</mismatch>", XML_ERROR_MISMATCHED_ELEMENT, 2);
2205 tester.TestParseError("ErrorLine-CData", "\n<root><![CDATA[ \n foo bar \n", XML_ERROR_PARSING_CDATA, 2);
2206 tester.TestParseError("ErrorLine-Text", "\n<root>\n foo bar \n", XML_ERROR_PARSING_TEXT, 3);
2207 tester.TestParseError("ErrorLine-Comment", "\n<root>\n<!-- >\n", XML_ERROR_PARSING_COMMENT, 3);
2208 tester.TestParseError("ErrorLine-Declaration", "\n<root>\n<? >\n", XML_ERROR_PARSING_DECLARATION, 3);
2209 tester.TestParseError("ErrorLine-Unknown", "\n<root>\n<! \n", XML_ERROR_PARSING_UNKNOWN, 3);
2210 tester.TestParseError("ErrorLine-Element", "\n<root>\n<unclosed \n", XML_ERROR_PARSING_ELEMENT, 3);
2211 tester.TestParseError("ErrorLine-Attribute", "\n<root>\n<unclosed \n att\n", XML_ERROR_PARSING_ATTRIBUTE, 4);
2212 tester.TestParseError("ErrorLine-ElementClose", "\n<root>\n<unclosed \n/unexpected", XML_ERROR_PARSING_ELEMENT, 3);
kezenatorec694152016-11-26 17:21:43 +10002213
Lee Thomasone90e9012016-12-24 07:34:39 -08002214 tester.TestStringLines(
kezenatorec694152016-11-26 17:21:43 +10002215 "LineNumbers-String",
Lee Thomasone90e9012016-12-24 07:34:39 -08002216
2217 "<?xml version=\"1.0\"?>\n" // 1 Doc, DecL
2218 "<root a='b' \n" // 2 Element Attribute
2219 "c='d'> d <blah/> \n" // 3 Attribute Text Element
2220 "newline in text \n" // 4 Text
2221 "and second <zxcv/><![CDATA[\n" // 5 Element Text
2222 " cdata test ]]><!-- comment -->\n" // 6 Comment
2223 "<! unknown></root>", // 7 Unknown
2224
kezenatorec694152016-11-26 17:21:43 +10002225 "D01L01E02A02A03T03E03T04E05T05C06U07");
2226
Lee Thomasone90e9012016-12-24 07:34:39 -08002227 tester.TestStringLines(
kezenatorec694152016-11-26 17:21:43 +10002228 "LineNumbers-CRLF",
Lee Thomasone90e9012016-12-24 07:34:39 -08002229
2230 "\r\n" // 1 Doc (arguably should be line 2)
2231 "<?xml version=\"1.0\"?>\n" // 2 DecL
2232 "<root>\r\n" // 3 Element
2233 "\n" // 4
2234 "text contining new line \n" // 5 Text
2235 " and also containing crlf \r\n" // 6
2236 "<sub><![CDATA[\n" // 7 Element Text
2237 "cdata containing new line \n" // 8
2238 " and also containing cflr\r\n" // 9
2239 "]]></sub><sub2/></root>", // 10 Element
2240
kezenatorec694152016-11-26 17:21:43 +10002241 "D01L02E03T05E07T07E10");
2242
Lee Thomasone90e9012016-12-24 07:34:39 -08002243 tester.TestFileLines(
kezenatorec694152016-11-26 17:21:43 +10002244 "LineNumbers-File",
2245 "resources/utf8test.xml",
2246 "D01L01E02E03A03A03T03E04A04A04T04E05A05A05T05E06A06A06T06E07A07A07T07E08A08A08T08E09T09E10T10");
2247 }
2248
Lee Thomasonf49b9652017-10-11 10:57:49 -07002249 {
2250 const char* xml = "<Hello>Text</Error>";
2251 XMLDocument doc;
2252 doc.Parse(xml);
2253 XMLTest("Test mismatched elements.", true, doc.Error());
2254 XMLTest("Test mismatched elements.", XML_ERROR_MISMATCHED_ELEMENT, doc.ErrorID());
2255 // For now just make sure calls work & doesn't crash.
2256 // May solidify the error output in the future.
2257 printf("%s\n", doc.ErrorStr());
2258 doc.PrintError();
2259 }
2260
Lee Thomason85492022015-05-22 11:07:45 -07002261 // ----------- Performance tracking --------------
Lee Thomason6f381b72012-03-02 12:59:39 -08002262 {
2263#if defined( _MSC_VER )
2264 __int64 start, end, freq;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002265 QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
Lee Thomason6f381b72012-03-02 12:59:39 -08002266#endif
2267
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002268 FILE* perfFP = fopen("resources/dream.xml", "r");
Dmitry-Med1b82822017-07-04 18:02:54 +03002269 XMLTest("Open dream.xml", true, perfFP != 0);
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002270 fseek(perfFP, 0, SEEK_END);
Armagetron3c21d6f2016-10-13 13:31:23 +02002271 long size = ftell(perfFP);
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002272 fseek(perfFP, 0, SEEK_SET);
Lee Thomason6f381b72012-03-02 12:59:39 -08002273
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002274 char* mem = new char[size + 1];
Dmitry-Med1b82822017-07-04 18:02:54 +03002275 memset(mem, 0xfe, size);
Lee Thomasone4dc7212017-07-06 17:05:01 -07002276 size_t bytesRead = fread(mem, 1, size, perfFP);
2277 XMLTest("Read dream.xml", true, uint32_t(size) >= uint32_t(bytesRead));
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002278 fclose(perfFP);
Lee Thomason6f381b72012-03-02 12:59:39 -08002279 mem[size] = 0;
2280
2281#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002282 QueryPerformanceCounter((LARGE_INTEGER*)&start);
Lee Thomason6f381b72012-03-02 12:59:39 -08002283#else
2284 clock_t cstart = clock();
2285#endif
Dmitry-Me68578f42017-07-03 18:21:23 +03002286 bool parseDreamXmlFailed = false;
Lee Thomason6f381b72012-03-02 12:59:39 -08002287 static const int COUNT = 10;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002288 for (int i = 0; i < COUNT; ++i) {
Lee Thomason6f381b72012-03-02 12:59:39 -08002289 XMLDocument doc;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002290 doc.Parse(mem);
Dmitry-Me68578f42017-07-03 18:21:23 +03002291 parseDreamXmlFailed = parseDreamXmlFailed || doc.Error();
Lee Thomason6f381b72012-03-02 12:59:39 -08002292 }
2293#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002294 QueryPerformanceCounter((LARGE_INTEGER*)&end);
Lee Thomason6f381b72012-03-02 12:59:39 -08002295#else
2296 clock_t cend = clock();
2297#endif
Dmitry-Me1ab85872017-08-10 17:28:10 +03002298 XMLTest( "Parse dream.xml", false, parseDreamXmlFailed );
Lee Thomason6f381b72012-03-02 12:59:39 -08002299
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002300 delete[] mem;
Lee Thomason6f381b72012-03-02 12:59:39 -08002301
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07002302 static const char* note =
Peter Matula50689912018-01-09 12:52:26 +01002303#ifdef TINYXML2_DEBUG
Lee Thomason6f381b72012-03-02 12:59:39 -08002304 "DEBUG";
2305#else
2306 "Release";
2307#endif
2308
2309#if defined( _MSC_VER )
Dmitry-Me6f4c4e72017-07-27 12:06:56 +03002310 const double duration = 1000.0 * (double)(end - start) / ((double)freq * (double)COUNT);
Lee Thomason6f381b72012-03-02 12:59:39 -08002311#else
Dmitry-Me6f4c4e72017-07-27 12:06:56 +03002312 const double duration = (double)(cend - cstart) / (double)COUNT;
Lee Thomason6f381b72012-03-02 12:59:39 -08002313#endif
Dmitry-Me6f4c4e72017-07-27 12:06:56 +03002314 printf("\nParsing dream.xml (%s): %.3f milli-seconds\n", note, duration);
Lee Thomason6f381b72012-03-02 12:59:39 -08002315 }
2316
Peter Matula50689912018-01-09 12:52:26 +01002317#if defined( _MSC_VER ) && defined( TINYXML2_DEBUG )
Dmitry-Mede381df2017-07-26 18:05:25 +03002318 {
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07002319 _CrtMemCheckpoint( &endMemState );
Lee Thomason1ff38e02012-02-14 18:18:16 -08002320
2321 _CrtMemState diffMemState;
2322 _CrtMemDifference( &diffMemState, &startMemState, &endMemState );
2323 _CrtMemDumpStatistics( &diffMemState );
Dmitry-Meed785702017-06-15 13:39:53 +03002324
2325 {
2326 int leaksBeforeExit = _CrtDumpMemoryLeaks();
2327 XMLTest( "No leaks before exit?", FALSE, leaksBeforeExit );
2328 }
Dmitry-Mede381df2017-07-26 18:05:25 +03002329 }
2330#endif
Lee Thomason1ff38e02012-02-14 18:18:16 -08002331
2332 printf ("\nPass %d, Fail %d\n", gPass, gFail);
Lee Thomason (grinliz)db304252013-07-31 12:24:52 -07002333
2334 return gFail;
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -08002335}