blob: 9fedbe39ceaa2797e91536c5b430e2823dcc4f1e [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;
Sarat Addepallid608c562015-05-20 10:19:00 +053037 else
38 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}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200115/** @page Example-1 Load an XML File
116 * @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 */
124
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}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200134/** @page Example-2 Parse an XML from char buffer
135 * @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}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200167/** @page Example-3 Get information out of XML
168 @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.
175
176 (The XML is an excerpt from "dream.xml").
177
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
195 For this example, we want to print out the
196 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
215 text nodes can contain elements.
216
217 @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()
228 is a cast from a Node to a XMLText.
229*/
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}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200258/** @page Example-4 Read attributes and text information.
259 @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
272 TinyXML-2 has accessors for both approaches.
273
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{
Lee Thomason (grinliz)0a4df402012-02-27 20:50:52 -0800295 #if defined( _MSC_VER ) && defined( 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
kbinny62bf29a152017-06-23 18:15:25 +0000341#if defined WIN32
Lee Thomasone4dc7212017-07-06 17:05:01 -0700342 if ( !CreateDirectory( L"resources\\out", NULL ) && GetLastError() != ERROR_ALREADY_EXISTS ) {
kbinny62bf29a152017-06-23 18:15:25 +0000343#else
kbinny629720fba2017-06-27 01:40:33 +0000344 if ( mkdir( "resources/out", S_IRWXU | S_IRGRP | S_IXGRP ) == -1 && errno != EEXIST ) {
kbinny62bf29a152017-06-23 18:15:25 +0000345#endif
346 printf( "Unable to create directory 'resources/out': %s\n", strerror( errno ) );
347 exit( 1 );
348 }
349
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700350 XMLTest( "Example-1", 0, example_1() );
351 XMLTest( "Example-2", 0, example_2() );
352 XMLTest( "Example-3", 0, example_3() );
Lee Thomason21be8822012-07-15 17:27:22 -0700353 XMLTest( "Example-4", true, example_4() );
Lee Thomason87e475a2012-03-20 11:55:29 -0700354
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700355 /* ------ Example 2: Lookup information. ---- */
Lee Thomason87e475a2012-03-20 11:55:29 -0700356
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800357 {
Lee Thomason43f59302012-02-06 18:18:11 -0800358 static const char* test[] = { "<element />",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400359 "<element></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800360 "<element><subelement/></element>",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400361 "<element><subelement></subelement></element>",
362 "<element><subelement><subsub/></subelement></element>",
363 "<!--comment beside elements--><element><subelement></subelement></element>",
364 "<!--comment beside elements, this time with spaces--> \n <element> <subelement> \n </subelement> </element>",
365 "<element attrib1='foo' attrib2=\"bar\" ></element>",
366 "<element attrib1='foo' attrib2=\"bar\" ><subelement attrib3='yeehaa' /></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800367 "<element>Text inside element.</element>",
368 "<element><b></b></element>",
369 "<element>Text inside and <b>bolded</b> in the element.</element>",
370 "<outer><element>Text inside and <b>bolded</b> in the element.</element></outer>",
Lee Thomason8ee79892012-01-25 17:44:30 -0800371 "<element>This &amp; That.</element>",
Lee Thomason18d68bd2012-01-26 18:17:26 -0800372 "<element attrib='This&lt;That' />",
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800373 0
374 };
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800375 for( int i=0; test[i]; ++i ) {
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800376 XMLDocument doc;
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800377 doc.Parse( test[i] );
Dmitry-Me68578f42017-07-03 18:21:23 +0300378 XMLTest( "Element test", false, doc.Error() );
Lee Thomason5cae8972012-01-24 18:03:07 -0800379 doc.Print();
Lee Thomasonec975ce2012-01-23 11:42:06 -0800380 printf( "----------------------------------------------\n" );
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800381 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800382 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800383#if 1
Lee Thomasond6277762012-02-22 16:00:12 -0800384 {
385 static const char* test = "<!--hello world\n"
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400386 " line 2\r"
387 " line 3\r\n"
388 " line 4\n\r"
389 " line 5\r-->";
Lee Thomasond6277762012-02-22 16:00:12 -0800390
391 XMLDocument doc;
392 doc.Parse( test );
Dmitry-Me68578f42017-07-03 18:21:23 +0300393 XMLTest( "Hello world declaration", false, doc.Error() );
Lee Thomasond6277762012-02-22 16:00:12 -0800394 doc.Print();
395 }
396
Lee Thomason2c85a712012-01-31 08:24:24 -0800397 {
398 static const char* test = "<element>Text before.</element>";
399 XMLDocument doc;
400 doc.Parse( test );
Dmitry-Me68578f42017-07-03 18:21:23 +0300401 XMLTest( "Element text before", false, doc.Error() );
Lee Thomason2c85a712012-01-31 08:24:24 -0800402 XMLElement* root = doc.FirstChildElement();
403 XMLElement* newElement = doc.NewElement( "Subelement" );
404 root->InsertEndChild( newElement );
405 doc.Print();
406 }
Lee Thomasond1983222012-02-06 08:41:24 -0800407 {
408 XMLDocument* doc = new XMLDocument();
409 static const char* test = "<element><sub/></element>";
410 doc->Parse( test );
Dmitry-Me68578f42017-07-03 18:21:23 +0300411 XMLTest( "Element with sub element", false, doc->Error() );
Lee Thomasond1983222012-02-06 08:41:24 -0800412 delete doc;
413 }
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800414 {
Lee Thomason1ff38e02012-02-14 18:18:16 -0800415 // Test: Programmatic DOM
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800416 // Build:
417 // <element>
418 // <!--comment-->
419 // <sub attrib="1" />
420 // <sub attrib="2" />
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800421 // <sub attrib="3" >& Text!</sub>
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800422 // <element>
423
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800424 XMLDocument* doc = new XMLDocument();
Lee Thomason1ff38e02012-02-14 18:18:16 -0800425 XMLNode* element = doc->InsertEndChild( doc->NewElement( "element" ) );
426
427 XMLElement* sub[3] = { doc->NewElement( "sub" ), doc->NewElement( "sub" ), doc->NewElement( "sub" ) };
428 for( int i=0; i<3; ++i ) {
429 sub[i]->SetAttribute( "attrib", i );
430 }
431 element->InsertEndChild( sub[2] );
432 XMLNode* comment = element->InsertFirstChild( doc->NewComment( "comment" ) );
Lee Thomasonaf9bce12016-07-17 22:35:52 -0700433 comment->SetUserData((void*)2);
Lee Thomason1ff38e02012-02-14 18:18:16 -0800434 element->InsertAfterChild( comment, sub[0] );
435 element->InsertAfterChild( sub[0], sub[1] );
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800436 sub[2]->InsertFirstChild( doc->NewText( "& Text!" ));
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800437 doc->Print();
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800438 XMLTest( "Programmatic DOM", "comment", doc->FirstChildElement( "element" )->FirstChild()->Value() );
439 XMLTest( "Programmatic DOM", "0", doc->FirstChildElement( "element" )->FirstChildElement()->Attribute( "attrib" ) );
440 XMLTest( "Programmatic DOM", 2, doc->FirstChildElement()->LastChildElement( "sub" )->IntAttribute( "attrib" ) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700441 XMLTest( "Programmatic DOM", "& Text!",
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800442 doc->FirstChildElement()->LastChildElement( "sub" )->FirstChild()->ToText()->Value() );
Lee Thomasonc9445462016-07-17 22:53:48 -0700443 XMLTest("User data", (void*)2 == comment->GetUserData(), true, false);
U-Stream\Leeae25a442012-02-17 17:48:16 -0800444
445 // And now deletion:
446 element->DeleteChild( sub[2] );
447 doc->DeleteNode( comment );
448
449 element->FirstChildElement()->SetAttribute( "attrib", true );
450 element->LastChildElement()->DeleteAttribute( "attrib" );
451
452 XMLTest( "Programmatic DOM", true, doc->FirstChildElement()->FirstChildElement()->BoolAttribute( "attrib" ) );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700453 int value1 = 10;
454 int value2 = doc->FirstChildElement()->LastChildElement()->IntAttribute( "attrib", 10 );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300455 XMLError result = doc->FirstChildElement()->LastChildElement()->QueryIntAttribute( "attrib", &value1 );
456 XMLTest( "Programmatic DOM", XML_NO_ATTRIBUTE, result );
457 XMLTest( "Programmatic DOM", 10, value1 );
458 XMLTest( "Programmatic DOM", 10, value2 );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800459
460 doc->Print();
461
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700462 {
463 XMLPrinter streamer;
464 doc->Print( &streamer );
465 printf( "%s", streamer.CStr() );
466 }
467 {
468 XMLPrinter streamer( 0, true );
469 doc->Print( &streamer );
Doruk Turak1f212f32016-08-28 20:54:17 +0200470 XMLTest( "Compact mode", "<element><sub attrib=\"true\"/><sub/></element>", streamer.CStr(), false );
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700471 }
Lee Thomason (grinliz)6b8b0122012-09-08 21:21:00 -0700472 doc->SaveFile( "./resources/out/pretty.xml" );
473 doc->SaveFile( "./resources/out/compact.xml", true );
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800474 delete doc;
475 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800476 {
477 // Test: Dream
478 // XML1 : 1,187,569 bytes in 31,209 allocations
479 // XML2 : 469,073 bytes in 323 allocations
480 //int newStart = gNew;
481 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300482 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800483
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400484 doc.SaveFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800485 doc.PrintError();
486
487 XMLTest( "Dream", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400488 doc.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800489 XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() ? true : false );
490 XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
491 doc.FirstChild()->NextSibling()->ToUnknown()->Value() );
492 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400493 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800494 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400495 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800496
497 XMLDocument doc2;
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400498 doc2.LoadFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800499 XMLTest( "Dream-out", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400500 doc2.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800501 XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() ? true : false );
502 XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
503 doc2.FirstChild()->NextSibling()->ToUnknown()->Value() );
504 XMLTest( "Dream-out", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400505 doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800506
507 //gNewTotal = gNew - newStart;
508 }
Lee Thomason6f381b72012-03-02 12:59:39 -0800509
510
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800511 {
512 const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n"
513 "<passages count=\"006\" formatversion=\"20020620\">\n"
514 " <wrong error>\n"
515 "</passages>";
516
517 XMLDocument doc;
518 doc.Parse( error );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300519 XMLTest( "Bad XML", XML_ERROR_PARSING_ATTRIBUTE, doc.ErrorID() );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800520 }
521
522 {
523 const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
524
525 XMLDocument doc;
526 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300527 XMLTest( "Top level attributes", false, doc.Error() );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800528
529 XMLElement* ele = doc.FirstChildElement();
530
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300531 int iVal;
532 XMLError result;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800533 double dVal;
534
535 result = ele->QueryDoubleAttribute( "attr0", &dVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300536 XMLTest( "Query attribute: int as double", XML_SUCCESS, result);
537 XMLTest( "Query attribute: int as double", 1, (int)dVal );
538 XMLTest( "Query attribute: int as double", 1, (int)ele->DoubleAttribute("attr0"));
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700539
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800540 result = ele->QueryDoubleAttribute( "attr1", &dVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300541 XMLTest( "Query attribute: double as double", XML_SUCCESS, result);
542 XMLTest( "Query attribute: double as double", 2.0, dVal );
543 XMLTest( "Query attribute: double as double", 2.0, ele->DoubleAttribute("attr1") );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700544
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800545 result = ele->QueryIntAttribute( "attr1", &iVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300546 XMLTest( "Query attribute: double as int", XML_SUCCESS, result);
547 XMLTest( "Query attribute: double as int", 2, iVal );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700548
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800549 result = ele->QueryIntAttribute( "attr2", &iVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300550 XMLTest( "Query attribute: not a number", XML_WRONG_ATTRIBUTE_TYPE, result );
551 XMLTest( "Query attribute: not a number", 4.0, ele->DoubleAttribute("attr2", 4.0) );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700552
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800553 result = ele->QueryIntAttribute( "bar", &iVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300554 XMLTest( "Query attribute: does not exist", XML_NO_ATTRIBUTE, result );
555 XMLTest( "Query attribute: does not exist", true, ele->BoolAttribute("bar", true) );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800556 }
557
558 {
559 const char* str = "<doc/>";
560
561 XMLDocument doc;
562 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300563 XMLTest( "Empty top element", false, doc.Error() );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800564
565 XMLElement* ele = doc.FirstChildElement();
566
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800567 int iVal, iVal2;
568 double dVal, dVal2;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800569
570 ele->SetAttribute( "str", "strValue" );
571 ele->SetAttribute( "int", 1 );
572 ele->SetAttribute( "double", -1.0 );
573
574 const char* cStr = ele->Attribute( "str" );
575 ele->QueryIntAttribute( "int", &iVal );
576 ele->QueryDoubleAttribute( "double", &dVal );
577
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800578 ele->QueryAttribute( "int", &iVal2 );
579 ele->QueryAttribute( "double", &dVal2 );
580
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300581 XMLTest( "Attribute match test", "strValue", ele->Attribute( "str", "strValue" ) );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800582 XMLTest( "Attribute round trip. c-string.", "strValue", cStr );
583 XMLTest( "Attribute round trip. int.", 1, iVal );
584 XMLTest( "Attribute round trip. double.", -1, (int)dVal );
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800585 XMLTest( "Alternate query", true, iVal == iVal2 );
586 XMLTest( "Alternate query", true, dVal == dVal2 );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700587 XMLTest( "Alternate query", true, iVal == ele->IntAttribute("int") );
588 XMLTest( "Alternate query", true, dVal == ele->DoubleAttribute("double") );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800589 }
590
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800591 {
592 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300593 doc.LoadFile( "resources/utf8test.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800594
595 // Get the attribute "value" from the "Russian" element and check it.
596 XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700597 const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800598 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
599
600 XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) );
601
602 const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U,
603 0xd1U, 0x81U, 0xd1U, 0x81U,
604 0xd0U, 0xbaU, 0xd0U, 0xb8U,
605 0xd0U, 0xb9U, 0 };
606 const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
607
608 XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText();
609 XMLTest( "UTF-8: Browsing russian element name.",
610 russianText,
611 text->Value() );
612
613 // Now try for a round trip.
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400614 doc.SaveFile( "resources/out/utf8testout.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800615
616 // Check the round trip.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800617 int okay = 0;
618
Thomas Roßa6dd8c62012-07-26 20:42:18 +0200619 FILE* saved = fopen( "resources/out/utf8testout.xml", "r" );
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300620 FILE* verify = fopen( "resources/utf8testverify.xml", "r" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800621
622 if ( saved && verify )
623 {
624 okay = 1;
PKEuSc28ba3a2012-07-16 03:08:47 -0700625 char verifyBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800626 while ( fgets( verifyBuf, 256, verify ) )
627 {
PKEuSc28ba3a2012-07-16 03:08:47 -0700628 char savedBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800629 fgets( savedBuf, 256, saved );
630 NullLineEndings( verifyBuf );
631 NullLineEndings( savedBuf );
632
633 if ( strcmp( verifyBuf, savedBuf ) )
634 {
635 printf( "verify:%s<\n", verifyBuf );
636 printf( "saved :%s<\n", savedBuf );
637 okay = 0;
638 break;
639 }
640 }
641 }
642 if ( saved )
643 fclose( saved );
644 if ( verify )
645 fclose( verify );
646 XMLTest( "UTF-8: Verified multi-language round trip.", 1, okay );
647 }
648
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800649 // --------GetText()-----------
650 {
651 const char* str = "<foo>This is text</foo>";
652 XMLDocument doc;
653 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300654 XMLTest( "Double whitespace", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800655 const XMLElement* element = doc.RootElement();
656
657 XMLTest( "GetText() normal use.", "This is text", element->GetText() );
658
659 str = "<foo><b>This is text</b></foo>";
660 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300661 XMLTest( "Bold text simulation", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800662 element = doc.RootElement();
663
664 XMLTest( "GetText() contained element.", element->GetText() == 0, true );
665 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800666
Lee Thomasond6277762012-02-22 16:00:12 -0800667
Uli Kusterer321072e2014-01-21 01:57:38 +0100668 // --------SetText()-----------
669 {
670 const char* str = "<foo></foo>";
671 XMLDocument doc;
672 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300673 XMLTest( "Empty closed element", false, doc.Error() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100674 XMLElement* element = doc.RootElement();
675
Lee Thomason9c0678a2014-01-24 10:18:27 -0800676 element->SetText("darkness.");
677 XMLTest( "SetText() normal use (open/close).", "darkness.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100678
Lee Thomason9c0678a2014-01-24 10:18:27 -0800679 element->SetText("blue flame.");
680 XMLTest( "SetText() replace.", "blue flame.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100681
682 str = "<foo/>";
683 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300684 XMLTest( "Empty self-closed element", false, doc.Error() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100685 element = doc.RootElement();
686
Lee Thomason9c0678a2014-01-24 10:18:27 -0800687 element->SetText("The driver");
688 XMLTest( "SetText() normal use. (self-closing)", "The driver", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100689
Lee Thomason9c0678a2014-01-24 10:18:27 -0800690 element->SetText("<b>horses</b>");
691 XMLTest( "SetText() replace with tag-like text.", "<b>horses</b>", element->GetText() );
692 //doc.Print();
Uli Kusterer321072e2014-01-21 01:57:38 +0100693
694 str = "<foo><bar>Text in nested element</bar></foo>";
695 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300696 XMLTest( "Text in nested element", false, doc.Error() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100697 element = doc.RootElement();
698
Lee Thomason9c0678a2014-01-24 10:18:27 -0800699 element->SetText("wolves");
700 XMLTest( "SetText() prefix to nested non-text children.", "wolves", element->GetText() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800701
702 str = "<foo/>";
703 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300704 XMLTest( "Empty self-closed element round 2", false, doc.Error() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800705 element = doc.RootElement();
706
707 element->SetText( "str" );
708 XMLTest( "SetText types", "str", element->GetText() );
709
710 element->SetText( 1 );
711 XMLTest( "SetText types", "1", element->GetText() );
712
713 element->SetText( 1U );
714 XMLTest( "SetText types", "1", element->GetText() );
715
716 element->SetText( true );
Doruk Turak1f212f32016-08-28 20:54:17 +0200717 XMLTest( "SetText types", "true", element->GetText() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800718
719 element->SetText( 1.5f );
720 XMLTest( "SetText types", "1.5", element->GetText() );
721
722 element->SetText( 1.5 );
723 XMLTest( "SetText types", "1.5", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100724 }
725
Lee Thomason51c12712016-06-04 20:18:49 -0700726 // ---------- Attributes ---------
727 {
728 static const int64_t BIG = -123456789012345678;
729 XMLDocument doc;
730 XMLElement* element = doc.NewElement("element");
731 doc.InsertFirstChild(element);
732
733 {
734 element->SetAttribute("attrib", int(-100));
735 int v = 0;
736 element->QueryIntAttribute("attrib", &v);
737 XMLTest("Attribute: int", -100, v, true);
738 element->QueryAttribute("attrib", &v);
739 XMLTest("Attribute: int", -100, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700740 XMLTest("Attribute: int", -100, element->IntAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700741 }
742 {
743 element->SetAttribute("attrib", unsigned(100));
744 unsigned v = 0;
745 element->QueryUnsignedAttribute("attrib", &v);
746 XMLTest("Attribute: unsigned", unsigned(100), v, true);
747 element->QueryAttribute("attrib", &v);
748 XMLTest("Attribute: unsigned", unsigned(100), v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700749 XMLTest("Attribute: unsigned", unsigned(100), element->UnsignedAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700750 }
751 {
752 element->SetAttribute("attrib", BIG);
753 int64_t v = 0;
754 element->QueryInt64Attribute("attrib", &v);
755 XMLTest("Attribute: int64_t", BIG, v, true);
756 element->QueryAttribute("attrib", &v);
757 XMLTest("Attribute: int64_t", BIG, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700758 XMLTest("Attribute: int64_t", BIG, element->Int64Attribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700759 }
760 {
761 element->SetAttribute("attrib", true);
762 bool v = false;
763 element->QueryBoolAttribute("attrib", &v);
764 XMLTest("Attribute: bool", true, v, true);
765 element->QueryAttribute("attrib", &v);
766 XMLTest("Attribute: bool", true, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700767 XMLTest("Attribute: bool", true, element->BoolAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700768 }
769 {
Lee Thomasonce667c92016-12-26 16:45:30 -0800770 element->SetAttribute("attrib", true);
771 const char* result = element->Attribute("attrib");
772 XMLTest("Bool true is 'true'", "true", result);
773
Lee Thomasonc5c99c22016-12-29 11:19:17 -0800774 XMLUtil::SetBoolSerialization("1", "0");
Lee Thomasonce667c92016-12-26 16:45:30 -0800775 element->SetAttribute("attrib", true);
776 result = element->Attribute("attrib");
777 XMLTest("Bool true is '1'", "1", result);
778
Lee Thomasonc5c99c22016-12-29 11:19:17 -0800779 XMLUtil::SetBoolSerialization(0, 0);
Lee Thomasonce667c92016-12-26 16:45:30 -0800780 }
781 {
Lee Thomason51c12712016-06-04 20:18:49 -0700782 element->SetAttribute("attrib", 100.0);
783 double v = 0;
784 element->QueryDoubleAttribute("attrib", &v);
785 XMLTest("Attribute: double", 100.0, v, true);
786 element->QueryAttribute("attrib", &v);
787 XMLTest("Attribute: double", 100.0, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700788 XMLTest("Attribute: double", 100.0, element->DoubleAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700789 }
790 {
791 element->SetAttribute("attrib", 100.0f);
792 float v = 0;
793 element->QueryFloatAttribute("attrib", &v);
794 XMLTest("Attribute: float", 100.0f, v, true);
795 element->QueryAttribute("attrib", &v);
796 XMLTest("Attribute: float", 100.0f, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700797 XMLTest("Attribute: float", 100.0f, element->FloatAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700798 }
799 {
800 element->SetText(BIG);
801 int64_t v = 0;
802 element->QueryInt64Text(&v);
803 XMLTest("Element: int64_t", BIG, v, true);
804 }
805 }
806
807 // ---------- XMLPrinter stream mode ------
808 {
809 {
810 FILE* printerfp = fopen("resources/printer.xml", "w");
811 XMLPrinter printer(printerfp);
812 printer.OpenElement("foo");
813 printer.PushAttribute("attrib-text", "text");
814 printer.PushAttribute("attrib-int", int(1));
815 printer.PushAttribute("attrib-unsigned", unsigned(2));
816 printer.PushAttribute("attrib-int64", int64_t(3));
817 printer.PushAttribute("attrib-bool", true);
818 printer.PushAttribute("attrib-double", 4.0);
819 printer.CloseElement();
820 fclose(printerfp);
821 }
822 {
823 XMLDocument doc;
824 doc.LoadFile("resources/printer.xml");
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300825 XMLTest("XMLPrinter Stream mode: load", XML_SUCCESS, doc.ErrorID(), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700826
827 const XMLDocument& cdoc = doc;
828
829 const XMLAttribute* attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-text");
830 XMLTest("attrib-text", "text", attrib->Value(), true);
831 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int");
832 XMLTest("attrib-int", int(1), attrib->IntValue(), true);
833 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-unsigned");
834 XMLTest("attrib-unsigned", unsigned(2), attrib->UnsignedValue(), true);
835 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int64");
836 XMLTest("attrib-int64", int64_t(3), attrib->Int64Value(), true);
837 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-bool");
838 XMLTest("attrib-bool", true, attrib->BoolValue(), true);
839 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-double");
840 XMLTest("attrib-double", 4.0, attrib->DoubleValue(), true);
841 }
842
843 }
844
Uli Kusterer321072e2014-01-21 01:57:38 +0100845
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800846 // ---------- CDATA ---------------
847 {
848 const char* str = "<xmlElement>"
849 "<![CDATA["
850 "I am > the rules!\n"
851 "...since I make symbolic puns"
852 "]]>"
853 "</xmlElement>";
854 XMLDocument doc;
855 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300856 XMLTest( "CDATA symbolic puns round 1", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800857 doc.Print();
Lee Thomasond6277762012-02-22 16:00:12 -0800858
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300859 XMLTest( "CDATA parse.", "I am > the rules!\n...since I make symbolic puns",
860 doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomasond6277762012-02-22 16:00:12 -0800861 false );
862 }
863
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800864 // ----------- CDATA -------------
865 {
866 const char* str = "<xmlElement>"
867 "<![CDATA["
868 "<b>I am > the rules!</b>\n"
869 "...since I make symbolic puns"
870 "]]>"
871 "</xmlElement>";
872 XMLDocument doc;
873 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300874 XMLTest( "CDATA symbolic puns round 2", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800875 doc.Print();
876
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300877 XMLTest( "CDATA parse. [ tixml1:1480107 ]",
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800878 "<b>I am > the rules!</b>\n...since I make symbolic puns",
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300879 doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800880 false );
881 }
882
883 // InsertAfterChild causes crash.
884 {
885 // InsertBeforeChild and InsertAfterChild causes crash.
886 XMLDocument doc;
887 XMLElement* parent = doc.NewElement( "Parent" );
888 doc.InsertFirstChild( parent );
889
890 XMLElement* childText0 = doc.NewElement( "childText0" );
891 XMLElement* childText1 = doc.NewElement( "childText1" );
892
893 XMLNode* childNode0 = parent->InsertEndChild( childText0 );
894 XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 );
895
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300896 XMLTest( "Test InsertAfterChild on empty node. ", true, ( childNode1 == parent->LastChild() ) );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800897 }
Lee Thomasond6277762012-02-22 16:00:12 -0800898
899 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800900 // Entities not being written correctly.
901 // From Lynn Allen
Lee Thomasond6277762012-02-22 16:00:12 -0800902
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800903 const char* passages =
904 "<?xml version=\"1.0\" standalone=\"no\" ?>"
905 "<passages count=\"006\" formatversion=\"20020620\">"
906 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
907 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
908 "</passages>";
Lee Thomasond6277762012-02-22 16:00:12 -0800909
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800910 XMLDocument doc;
911 doc.Parse( passages );
Dmitry-Me68578f42017-07-03 18:21:23 +0300912 XMLTest( "Entity transformation parse round 1", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800913 XMLElement* psg = doc.RootElement()->FirstChildElement();
914 const char* context = psg->Attribute( "context" );
915 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 -0800916
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800917 XMLTest( "Entity transformation: read. ", expected, context, true );
Lee Thomasond6277762012-02-22 16:00:12 -0800918
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400919 FILE* textfile = fopen( "resources/out/textfile.txt", "w" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800920 if ( textfile )
921 {
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800922 XMLPrinter streamer( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800923 psg->Accept( &streamer );
924 fclose( textfile );
925 }
Thomas Roß0922b732012-09-23 16:31:22 +0200926
927 textfile = fopen( "resources/out/textfile.txt", "r" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800928 TIXMLASSERT( textfile );
929 if ( textfile )
930 {
931 char buf[ 1024 ];
932 fgets( buf, 1024, textfile );
933 XMLTest( "Entity transformation: write. ",
934 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
935 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.\"/>\n",
936 buf, false );
PKEuSc28ba3a2012-07-16 03:08:47 -0700937 fclose( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800938 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800939 }
940
941 {
Lee Thomason6f381b72012-03-02 12:59:39 -0800942 // Suppress entities.
943 const char* passages =
944 "<?xml version=\"1.0\" standalone=\"no\" ?>"
945 "<passages count=\"006\" formatversion=\"20020620\">"
946 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
947 "</passages>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700948
Lee Thomason6f381b72012-03-02 12:59:39 -0800949 XMLDocument doc( false );
950 doc.Parse( passages );
Dmitry-Me68578f42017-07-03 18:21:23 +0300951 XMLTest( "Entity transformation parse round 2", false, doc.Error() );
Lee Thomason6f381b72012-03-02 12:59:39 -0800952
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300953 XMLTest( "No entity parsing.",
954 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.",
955 doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ) );
956 XMLTest( "No entity parsing.", "Crazy &ttk;",
957 doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value() );
Lee Thomason6f381b72012-03-02 12:59:39 -0800958 doc.Print();
959 }
960
961 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400962 const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800963
964 XMLDocument doc;
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400965 doc.Parse( test );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300966 XMLTest( "dot in names", false, doc.Error() );
967 XMLTest( "dot in names", "a.elem", doc.FirstChildElement()->Name() );
968 XMLTest( "dot in names", "2.0", doc.FirstChildElement()->Attribute( "xmi.version" ) );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800969 }
970
971 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400972 const char* test = "<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800973
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400974 XMLDocument doc;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800975 doc.Parse( test );
Dmitry-Me68578f42017-07-03 18:21:23 +0300976 XMLTest( "fin thickness", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800977
978 XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
979 XMLTest( "Entity with one digit.",
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300980 "1.1 Start easy ignore fin thickness\n", text->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800981 false );
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400982 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800983
984 {
985 // DOCTYPE not preserved (950171)
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700986 //
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800987 const char* doctype =
988 "<?xml version=\"1.0\" ?>"
989 "<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
990 "<!ELEMENT title (#PCDATA)>"
991 "<!ELEMENT books (title,authors)>"
992 "<element />";
993
994 XMLDocument doc;
995 doc.Parse( doctype );
Dmitry-Me68578f42017-07-03 18:21:23 +0300996 XMLTest( "PLAY SYSTEM parse", false, doc.Error() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400997 doc.SaveFile( "resources/out/test7.xml" );
Dmitry-Me68578f42017-07-03 18:21:23 +0300998 XMLTest( "PLAY SYSTEM save", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800999 doc.DeleteChild( doc.RootElement() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +04001000 doc.LoadFile( "resources/out/test7.xml" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001001 XMLTest( "PLAY SYSTEM load", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001002 doc.Print();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001003
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001004 const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown();
1005 XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() );
1006
1007 }
1008
1009 {
1010 // Comments do not stream out correctly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001011 const char* doctype =
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001012 "<!-- Somewhat<evil> -->";
1013 XMLDocument doc;
1014 doc.Parse( doctype );
Dmitry-Me68578f42017-07-03 18:21:23 +03001015 XMLTest( "Comment somewhat evil", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001016
1017 XMLComment* comment = doc.FirstChild()->ToComment();
1018
1019 XMLTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
1020 }
1021 {
1022 // Double attributes
1023 const char* doctype = "<element attr='red' attr='blue' />";
1024
1025 XMLDocument doc;
1026 doc.Parse( doctype );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001027
Lee Thomason2fa81722012-11-09 12:37:46 -08001028 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 -08001029 doc.PrintError();
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001030 }
1031
1032 {
1033 // Embedded null in stream.
1034 const char* doctype = "<element att\0r='red' attr='blue' />";
1035
1036 XMLDocument doc;
1037 doc.Parse( doctype );
1038 XMLTest( "Embedded null throws error.", true, doc.Error() );
1039 }
1040
1041 {
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -07001042 // Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
Dmitry-Me588bb8d2014-12-25 18:59:18 +03001043 const char* str = "";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001044 XMLDocument doc;
1045 doc.Parse( str );
Lee Thomason2fa81722012-11-09 12:37:46 -08001046 XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001047 }
1048
1049 {
Dmitry-Me588bb8d2014-12-25 18:59:18 +03001050 // Documents with all whitespaces should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
1051 const char* str = " ";
1052 XMLDocument doc;
1053 doc.Parse( str );
1054 XMLTest( "All whitespaces document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
1055 }
1056
1057 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001058 // Low entities
1059 XMLDocument doc;
1060 doc.Parse( "<test>&#x0e;</test>" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001061 XMLTest( "Hex values", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001062 const char result[] = { 0x0e, 0 };
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001063 XMLTest( "Low entities.", result, doc.FirstChildElement()->GetText() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001064 doc.Print();
1065 }
1066
1067 {
1068 // Attribute values with trailing quotes not handled correctly
1069 XMLDocument doc;
1070 doc.Parse( "<foo attribute=bar\" />" );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001071 XMLTest( "Throw error with bad end quotes.", true, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001072 }
1073
1074 {
1075 // [ 1663758 ] Failure to report error on bad XML
1076 XMLDocument xml;
1077 xml.Parse("<x>");
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001078 XMLTest("Missing end tag at end of input", true, xml.Error());
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001079 xml.Parse("<x> ");
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001080 XMLTest("Missing end tag with trailing whitespace", true, xml.Error());
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001081 xml.Parse("<x></y>");
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001082 XMLTest("Mismatched tags", XML_ERROR_MISMATCHED_ELEMENT, xml.ErrorID() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001083 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001084
1085
1086 {
1087 // [ 1475201 ] TinyXML parses entities in comments
1088 XMLDocument xml;
1089 xml.Parse("<!-- declarations for <head> & <body> -->"
1090 "<!-- far &amp; away -->" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001091 XMLTest( "Declarations for head and body", false, xml.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001092
1093 XMLNode* e0 = xml.FirstChild();
1094 XMLNode* e1 = e0->NextSibling();
1095 XMLComment* c0 = e0->ToComment();
1096 XMLComment* c1 = e1->ToComment();
1097
1098 XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
1099 XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
1100 }
1101
1102 {
1103 XMLDocument xml;
1104 xml.Parse( "<Parent>"
1105 "<child1 att=''/>"
1106 "<!-- With this comment, child2 will not be parsed! -->"
1107 "<child2 att=''/>"
1108 "</Parent>" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001109 XMLTest( "Comments iteration", false, xml.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001110 xml.Print();
1111
1112 int count = 0;
1113
1114 for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
1115 ele;
1116 ele = ele->NextSibling() )
1117 {
1118 ++count;
1119 }
1120
1121 XMLTest( "Comments iterate correctly.", 3, count );
1122 }
1123
1124 {
1125 // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
1126 unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
1127 buf[60] = 239;
1128 buf[61] = 0;
1129
1130 XMLDocument doc;
1131 doc.Parse( (const char*)buf);
Dmitry-Me68578f42017-07-03 18:21:23 +03001132 XMLTest( "Broken CDATA", true, doc.Error() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001133 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001134
1135
1136 {
1137 // bug 1827248 Error while parsing a little bit malformed file
1138 // Actually not malformed - should work.
1139 XMLDocument xml;
1140 xml.Parse( "<attributelist> </attributelist >" );
1141 XMLTest( "Handle end tag whitespace", false, xml.Error() );
1142 }
1143
1144 {
1145 // This one must not result in an infinite loop
1146 XMLDocument xml;
1147 xml.Parse( "<infinite>loop" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001148 XMLTest( "No closing element", true, xml.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001149 XMLTest( "Infinite loop test.", true, true );
1150 }
1151#endif
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001152 {
1153 const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
1154 XMLDocument doc;
1155 doc.Parse( pub );
Dmitry-Me68578f42017-07-03 18:21:23 +03001156 XMLTest( "Trailing DOCTYPE", false, doc.Error() );
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001157
1158 XMLDocument clone;
1159 for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
1160 XMLNode* copy = node->ShallowClone( &clone );
1161 clone.InsertEndChild( copy );
1162 }
1163
1164 clone.Print();
1165
1166 int count=0;
1167 const XMLNode* a=clone.FirstChild();
1168 const XMLNode* b=doc.FirstChild();
1169 for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
1170 ++count;
1171 XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
1172 }
1173 XMLTest( "Clone and Equal", 4, count );
1174 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001175
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001176 {
Lee Thomason7085f002017-06-01 18:09:43 -07001177 // Deep Cloning of root element.
1178 XMLDocument doc2;
1179 XMLPrinter printer1;
1180 {
1181 // Make sure doc1 is deleted before we test doc2
1182 const char* xml =
1183 "<root>"
1184 " <child1 foo='bar'/>"
1185 " <!-- comment thing -->"
1186 " <child2 val='1'>Text</child2>"
1187 "</root>";
1188 XMLDocument doc;
1189 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001190 XMLTest( "Parse before deep cloning root element", false, doc.Error() );
Lee Thomason7085f002017-06-01 18:09:43 -07001191
1192 doc.Print(&printer1);
1193 XMLNode* root = doc.RootElement()->DeepClone(&doc2);
1194 doc2.InsertFirstChild(root);
1195 }
1196 XMLPrinter printer2;
1197 doc2.Print(&printer2);
1198
1199 XMLTest("Deep clone of element.", printer1.CStr(), printer2.CStr(), true);
1200 }
1201
1202 {
1203 // Deep Cloning of sub element.
1204 XMLDocument doc2;
1205 XMLPrinter printer1;
1206 {
1207 // Make sure doc1 is deleted before we test doc2
1208 const char* xml =
1209 "<?xml version ='1.0'?>"
1210 "<root>"
1211 " <child1 foo='bar'/>"
1212 " <!-- comment thing -->"
1213 " <child2 val='1'>Text</child2>"
1214 "</root>";
1215 XMLDocument doc;
1216 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001217 XMLTest( "Parse before deep cloning sub element", false, doc.Error() );
Lee Thomason7085f002017-06-01 18:09:43 -07001218
1219 const XMLElement* subElement = doc.FirstChildElement("root")->FirstChildElement("child2");
1220 subElement->Accept(&printer1);
1221
1222 XMLNode* clonedSubElement = subElement->DeepClone(&doc2);
1223 doc2.InsertFirstChild(clonedSubElement);
1224 }
1225 XMLPrinter printer2;
1226 doc2.Print(&printer2);
1227
1228 XMLTest("Deep clone of sub-element.", printer1.CStr(), printer2.CStr(), true);
1229 }
1230
1231 {
1232 // Deep cloning of document.
1233 XMLDocument doc2;
1234 XMLPrinter printer1;
1235 {
1236 // Make sure doc1 is deleted before we test doc2
1237 const char* xml =
1238 "<?xml version ='1.0'?>"
1239 "<!-- Top level comment. -->"
1240 "<root>"
1241 " <child1 foo='bar'/>"
1242 " <!-- comment thing -->"
1243 " <child2 val='1'>Text</child2>"
1244 "</root>";
1245 XMLDocument doc;
1246 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001247 XMLTest( "Parse before deep cloning document", false, doc.Error() );
Lee Thomason7085f002017-06-01 18:09:43 -07001248 doc.Print(&printer1);
1249
1250 doc.DeepCopy(&doc2);
1251 }
1252 XMLPrinter printer2;
1253 doc2.Print(&printer2);
1254
1255 XMLTest("DeepCopy of document.", printer1.CStr(), printer2.CStr(), true);
1256 }
1257
1258
1259 {
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001260 // This shouldn't crash.
1261 XMLDocument doc;
Lee Thomason85536252016-06-04 19:10:53 -07001262 if(XML_SUCCESS != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001263 {
1264 doc.PrintError();
1265 }
1266 XMLTest( "Error in snprinf handling.", true, doc.Error() );
1267 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001268
Lee Thomason5e3803c2012-04-16 08:57:05 -07001269 {
1270 // Attribute ordering.
1271 static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
1272 XMLDocument doc;
1273 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001274 XMLTest( "Parse for attribute ordering", false, doc.Error() );
Lee Thomason5e3803c2012-04-16 08:57:05 -07001275 XMLElement* ele = doc.FirstChildElement();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001276
Lee Thomason5e3803c2012-04-16 08:57:05 -07001277 const XMLAttribute* a = ele->FirstAttribute();
1278 XMLTest( "Attribute order", "1", a->Value() );
1279 a = a->Next();
1280 XMLTest( "Attribute order", "2", a->Value() );
1281 a = a->Next();
1282 XMLTest( "Attribute order", "3", a->Value() );
1283 XMLTest( "Attribute order", "attrib3", a->Name() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001284
Lee Thomason5e3803c2012-04-16 08:57:05 -07001285 ele->DeleteAttribute( "attrib2" );
1286 a = ele->FirstAttribute();
1287 XMLTest( "Attribute order", "1", a->Value() );
1288 a = a->Next();
1289 XMLTest( "Attribute order", "3", a->Value() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001290
Lee Thomason5e3803c2012-04-16 08:57:05 -07001291 ele->DeleteAttribute( "attrib1" );
1292 ele->DeleteAttribute( "attrib3" );
1293 XMLTest( "Attribute order (empty)", false, ele->FirstAttribute() ? true : false );
1294 }
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001295
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001296 {
1297 // Make sure an attribute with a space in it succeeds.
Lee Thomason78a773d2012-07-02 10:10:19 -07001298 static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
1299 static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
1300 static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
1301 XMLDocument doc0;
1302 doc0.Parse( xml0 );
Dmitry-Me68578f42017-07-03 18:21:23 +03001303 XMLTest( "Parse attribute with space 1", false, doc0.Error() );
Lee Thomason78a773d2012-07-02 10:10:19 -07001304 XMLDocument doc1;
1305 doc1.Parse( xml1 );
Dmitry-Me68578f42017-07-03 18:21:23 +03001306 XMLTest( "Parse attribute with space 2", false, doc1.Error() );
Lee Thomason78a773d2012-07-02 10:10:19 -07001307 XMLDocument doc2;
1308 doc2.Parse( xml2 );
Dmitry-Me68578f42017-07-03 18:21:23 +03001309 XMLTest( "Parse attribute with space 3", false, doc2.Error() );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001310
Lee Thomason78a773d2012-07-02 10:10:19 -07001311 XMLElement* ele = 0;
1312 ele = doc0.FirstChildElement();
1313 XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
1314 ele = doc1.FirstChildElement();
1315 XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
1316 ele = doc2.FirstChildElement();
1317 XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001318 }
1319
1320 {
1321 // Make sure we don't go into an infinite loop.
1322 static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
1323 XMLDocument doc;
1324 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001325 XMLTest( "Parse two elements with attribute", false, doc.Error() );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001326 XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
1327 XMLElement* ele1 = ele0->NextSiblingElement();
1328 bool equal = ele0->ShallowEqual( ele1 );
1329
1330 XMLTest( "Infinite loop in shallow equal.", true, equal );
1331 }
1332
Lee Thomason5708f812012-03-28 17:46:41 -07001333 // -------- Handles ------------
1334 {
1335 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1336 XMLDocument doc;
1337 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001338 XMLTest( "Parse element with attribute and nested element round 1", false, doc.Error() );
Lee Thomason5708f812012-03-28 17:46:41 -07001339
1340 XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001341 XMLTest( "Handle, success, mutable", "sub", ele->Value() );
Lee Thomason5708f812012-03-28 17:46:41 -07001342
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001343 XMLHandle docH( doc );
1344 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001345 XMLTest( "Handle, dne, mutable", false, ele != 0 );
Lee Thomason5708f812012-03-28 17:46:41 -07001346 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001347
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001348 {
1349 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1350 XMLDocument doc;
1351 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001352 XMLTest( "Parse element with attribute and nested element round 2", false, doc.Error() );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001353 XMLConstHandle docH( doc );
1354
1355 const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement();
1356 XMLTest( "Handle, success, const", ele->Value(), "sub" );
1357
1358 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001359 XMLTest( "Handle, dne, const", false, ele != 0 );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001360 }
Lee Thomasonf68c4382012-04-28 14:37:11 -07001361 {
1362 // Default Declaration & BOM
1363 XMLDocument doc;
1364 doc.InsertEndChild( doc.NewDeclaration() );
1365 doc.SetBOM( true );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001366
Lee Thomasonf68c4382012-04-28 14:37:11 -07001367 XMLPrinter printer;
1368 doc.Print( &printer );
1369
1370 static const char* result = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001371 XMLTest( "BOM and default declaration", result, printer.CStr(), false );
1372 XMLTest( "CStrSize", 42, printer.CStrSize(), false );
Lee Thomasonf68c4382012-04-28 14:37:11 -07001373 }
Lee Thomason21be8822012-07-15 17:27:22 -07001374 {
1375 const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
1376 XMLDocument doc;
1377 doc.Parse( xml );
1378 XMLTest( "Ill formed XML", true, doc.Error() );
1379 }
1380
1381 // QueryXYZText
1382 {
1383 const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
1384 XMLDocument doc;
1385 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001386 XMLTest( "Parse points", false, doc.Error() );
Lee Thomason21be8822012-07-15 17:27:22 -07001387
1388 const XMLElement* pointElement = doc.RootElement();
1389
1390 int intValue = 0;
1391 unsigned unsignedValue = 0;
1392 float floatValue = 0;
1393 double doubleValue = 0;
1394 bool boolValue = false;
1395
1396 pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
1397 pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
1398 pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
1399 pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
1400 pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
1401
1402
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001403 XMLTest( "QueryIntText", 1, intValue, false );
1404 XMLTest( "QueryUnsignedText", (unsigned)1, unsignedValue, false );
1405 XMLTest( "QueryFloatText", 1.2f, floatValue, false );
1406 XMLTest( "QueryDoubleText", 1.2, doubleValue, false );
1407 XMLTest( "QueryBoolText", true, boolValue, false );
Lee Thomason21be8822012-07-15 17:27:22 -07001408 }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001409
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001410 {
1411 const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
1412 XMLDocument doc;
1413 doc.Parse( xml );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001414 XMLTest( "Non-alpha element lead letter parses.", false, doc.Error() );
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001415 }
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001416
1417 {
1418 const char* xml = "<element _attr1=\"foo\" :attr2=\"bar\"></element>";
1419 XMLDocument doc;
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001420 doc.Parse( xml );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001421 XMLTest("Non-alpha attribute lead character parses.", false, doc.Error());
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001422 }
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001423
1424 {
1425 const char* xml = "<3lement></3lement>";
1426 XMLDocument doc;
1427 doc.Parse( xml );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001428 XMLTest("Element names with lead digit fail to parse.", true, doc.Error());
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001429 }
Lee Thomason (grinliz)62d1c5a2012-09-08 21:44:12 -07001430
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001431 {
1432 const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
1433 XMLDocument doc;
1434 doc.Parse( xml, 10 );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001435 XMLTest( "Set length of incoming data", false, doc.Error() );
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001436 }
1437
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001438 {
1439 XMLDocument doc;
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001440 XMLTest( "Document is initially empty", true, doc.NoChildren() );
Dmitry-Me48b5df02015-04-06 18:20:25 +03001441 doc.Clear();
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001442 XMLTest( "Empty is empty after Clear()", true, doc.NoChildren() );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001443 doc.LoadFile( "resources/dream.xml" );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001444 XMLTest( "Document has something to Clear()", false, doc.NoChildren() );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001445 doc.Clear();
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001446 XMLTest( "Document Clear()'s", true, doc.NoChildren() );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001447 }
1448
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001449 // ----------- Whitespace ------------
1450 {
1451 const char* xml = "<element>"
1452 "<a> This \nis &apos; text &apos; </a>"
1453 "<b> This is &apos; text &apos; \n</b>"
1454 "<c>This is &apos; \n\n text &apos;</c>"
1455 "</element>";
1456 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1457 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001458 XMLTest( "Parse with whitespace collapsing and &apos", false, doc.Error() );
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001459
1460 const XMLElement* element = doc.FirstChildElement();
1461 for( const XMLElement* parent = element->FirstChildElement();
1462 parent;
1463 parent = parent->NextSiblingElement() )
1464 {
1465 XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
1466 }
1467 }
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001468
Lee Thomasonae9ab072012-10-24 10:17:53 -07001469#if 0
1470 {
1471 // Passes if assert doesn't fire.
1472 XMLDocument xmlDoc;
1473
1474 xmlDoc.NewDeclaration();
1475 xmlDoc.NewComment("Configuration file");
1476
1477 XMLElement *root = xmlDoc.NewElement("settings");
1478 root->SetAttribute("version", 2);
1479 }
1480#endif
1481
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001482 {
1483 const char* xml = "<element> </element>";
1484 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1485 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001486 XMLTest( "Parse with all whitespaces", false, doc.Error() );
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001487 XMLTest( "Whitespace all space", true, 0 == doc.FirstChildElement()->FirstChild() );
1488 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001489
Lee Thomason5b0a6772012-11-19 13:54:42 -08001490 {
1491 // An assert should not fire.
1492 const char* xml = "<element/>";
1493 XMLDocument doc;
1494 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001495 XMLTest( "Parse with self-closed element", false, doc.Error() );
Lee Thomason5b0a6772012-11-19 13:54:42 -08001496 XMLElement* ele = doc.NewElement( "unused" ); // This will get cleaned up with the 'doc' going out of scope.
1497 XMLTest( "Tracking unused elements", true, ele != 0, false );
1498 }
1499
Lee Thomasona6412ac2012-12-13 15:39:11 -08001500
1501 {
1502 const char* xml = "<parent><child>abc</child></parent>";
1503 XMLDocument doc;
1504 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001505 XMLTest( "Parse for printing of sub-element", false, doc.Error() );
Lee Thomasona6412ac2012-12-13 15:39:11 -08001506 XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child");
1507
1508 XMLPrinter printer;
1509 ele->Accept( &printer );
1510 XMLTest( "Printing of sub-element", "<child>abc</child>\n", printer.CStr(), false );
1511 }
1512
1513
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001514 {
1515 XMLDocument doc;
1516 XMLError error = doc.LoadFile( "resources/empty.xml" );
1517 XMLTest( "Loading an empty file", XML_ERROR_EMPTY_DOCUMENT, error );
Lee Thomason331596e2014-09-11 14:56:43 -07001518 XMLTest( "Loading an empty file and ErrorName as string", "XML_ERROR_EMPTY_DOCUMENT", doc.ErrorName() );
Lee Thomasonc7556672014-09-14 12:39:42 -07001519 doc.PrintError();
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001520 }
1521
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001522 {
1523 // BOM preservation
1524 static const char* xml_bom_preservation = "\xef\xbb\xbf<element/>\n";
1525 {
1526 XMLDocument doc;
Lee Thomason85536252016-06-04 19:10:53 -07001527 XMLTest( "BOM preservation (parse)", XML_SUCCESS, doc.Parse( xml_bom_preservation ), false );
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001528 XMLPrinter printer;
1529 doc.Print( &printer );
1530
1531 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1532 doc.SaveFile( "resources/bomtest.xml" );
1533 }
1534 {
1535 XMLDocument doc;
1536 doc.LoadFile( "resources/bomtest.xml" );
1537 XMLTest( "BOM preservation (load)", true, doc.HasBOM(), false );
1538
1539 XMLPrinter printer;
1540 doc.Print( &printer );
1541 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1542 }
1543 }
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001544
Michael Daumlinged523282013-10-23 07:47:29 +02001545 {
1546 // Insertion with Removal
1547 const char* xml = "<?xml version=\"1.0\" ?>"
1548 "<root>"
1549 "<one>"
1550 "<subtree>"
1551 "<elem>element 1</elem>text<!-- comment -->"
1552 "</subtree>"
1553 "</one>"
1554 "<two/>"
1555 "</root>";
1556 const char* xmlInsideTwo = "<?xml version=\"1.0\" ?>"
1557 "<root>"
1558 "<one/>"
1559 "<two>"
1560 "<subtree>"
1561 "<elem>element 1</elem>text<!-- comment -->"
1562 "</subtree>"
1563 "</two>"
1564 "</root>";
1565 const char* xmlAfterOne = "<?xml version=\"1.0\" ?>"
1566 "<root>"
1567 "<one/>"
1568 "<subtree>"
1569 "<elem>element 1</elem>text<!-- comment -->"
1570 "</subtree>"
1571 "<two/>"
1572 "</root>";
1573 const char* xmlAfterTwo = "<?xml version=\"1.0\" ?>"
1574 "<root>"
1575 "<one/>"
1576 "<two/>"
1577 "<subtree>"
1578 "<elem>element 1</elem>text<!-- comment -->"
1579 "</subtree>"
1580 "</root>";
1581
1582 XMLDocument doc;
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001583 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001584 XMLTest( "Insertion with removal parse round 1", false, doc.Error() );
Michael Daumlinged523282013-10-23 07:47:29 +02001585 XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1586 XMLElement* two = doc.RootElement()->FirstChildElement("two");
1587 two->InsertFirstChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001588 XMLPrinter printer1(0, true);
1589 doc.Accept(&printer1);
1590 XMLTest("Move node from within <one> to <two>", xmlInsideTwo, printer1.CStr());
Michael Daumlinged523282013-10-23 07:47:29 +02001591
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001592 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001593 XMLTest( "Insertion with removal parse round 2", false, doc.Error() );
Michael Daumlinged523282013-10-23 07:47:29 +02001594 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1595 two = doc.RootElement()->FirstChildElement("two");
1596 doc.RootElement()->InsertAfterChild(two, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001597 XMLPrinter printer2(0, true);
1598 doc.Accept(&printer2);
1599 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer2.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001600
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001601 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001602 XMLTest( "Insertion with removal parse round 3", false, doc.Error() );
Michael Daumlinged523282013-10-23 07:47:29 +02001603 XMLNode* one = doc.RootElement()->FirstChildElement("one");
1604 subtree = one->FirstChildElement("subtree");
1605 doc.RootElement()->InsertAfterChild(one, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001606 XMLPrinter printer3(0, true);
1607 doc.Accept(&printer3);
1608 XMLTest("Move node from within <one> after <one>", xmlAfterOne, printer3.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001609
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001610 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001611 XMLTest( "Insertion with removal parse round 4", false, doc.Error() );
Michael Daumlinged523282013-10-23 07:47:29 +02001612 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1613 two = doc.RootElement()->FirstChildElement("two");
1614 doc.RootElement()->InsertEndChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001615 XMLPrinter printer4(0, true);
1616 doc.Accept(&printer4);
1617 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer4.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001618 }
1619
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001620 {
1621 const char* xml = "<svg width = \"128\" height = \"128\">"
1622 " <text> </text>"
1623 "</svg>";
1624 XMLDocument doc;
1625 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001626 XMLTest( "Parse svg with text", false, doc.Error() );
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001627 doc.Print();
1628 }
1629
Lee Thomason92e521b2014-11-15 17:45:51 -08001630 {
1631 // Test that it doesn't crash.
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001632 const char* xml = "<?xml version=\"1.0\"?><root><sample><field0><1</field0><field1>2</field1></sample></root>";
1633 XMLDocument doc;
1634 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001635 XMLTest( "Parse root-sample-field0", true, doc.Error() );
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001636 doc.PrintError();
Lee Thomason92e521b2014-11-15 17:45:51 -08001637 }
1638
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001639#if 1
1640 // the question being explored is what kind of print to use:
1641 // https://github.com/leethomason/tinyxml2/issues/63
1642 {
1643 //const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9' attrC='1.0e-10' attrD='1001000000.000000' attrE='0.1234567890123456789'/>";
1644 const char* xml = "<element/>";
1645 XMLDocument doc;
1646 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001647 XMLTest( "Parse self-closed empty element", false, doc.Error() );
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001648 doc.FirstChildElement()->SetAttribute( "attrA-f64", 123456789.123456789 );
1649 doc.FirstChildElement()->SetAttribute( "attrB-f64", 1.001e9 );
1650 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e9 );
1651 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e20 );
1652 doc.FirstChildElement()->SetAttribute( "attrD-f64", 1.0e-10 );
1653 doc.FirstChildElement()->SetAttribute( "attrD-f64", 0.123456789 );
1654
1655 doc.FirstChildElement()->SetAttribute( "attrA-f32", 123456789.123456789f );
1656 doc.FirstChildElement()->SetAttribute( "attrB-f32", 1.001e9f );
1657 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e9f );
1658 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e20f );
1659 doc.FirstChildElement()->SetAttribute( "attrD-f32", 1.0e-10f );
1660 doc.FirstChildElement()->SetAttribute( "attrD-f32", 0.123456789f );
1661
1662 doc.Print();
1663
1664 /* The result of this test is platform, compiler, and library version dependent. :("
1665 XMLPrinter printer;
1666 doc.Print( &printer );
1667 XMLTest( "Float and double formatting.",
1668 "<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",
1669 printer.CStr(),
1670 true );
1671 */
1672 }
1673#endif
Lee Thomasonf07b9522014-10-30 13:25:12 -07001674
1675 {
1676 // Issue #184
1677 // If it doesn't assert, it passes. Caused by objects
1678 // getting created during parsing which are then
1679 // inaccessible in the memory pools.
Dmitry-Me5d1aec12017-06-28 14:51:17 +03001680 const char* xmlText = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>";
Lee Thomasonf07b9522014-10-30 13:25:12 -07001681 {
1682 XMLDocument doc;
Dmitry-Me5d1aec12017-06-28 14:51:17 +03001683 doc.Parse(xmlText);
Dmitry-Me68578f42017-07-03 18:21:23 +03001684 XMLTest( "Parse hex no closing tag round 1", true, doc.Error() );
Lee Thomasonf07b9522014-10-30 13:25:12 -07001685 }
1686 {
1687 XMLDocument doc;
Dmitry-Me5d1aec12017-06-28 14:51:17 +03001688 doc.Parse(xmlText);
Dmitry-Me68578f42017-07-03 18:21:23 +03001689 XMLTest( "Parse hex no closing tag round 2", true, doc.Error() );
Lee Thomasonf07b9522014-10-30 13:25:12 -07001690 doc.Clear();
1691 }
1692 }
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001693
1694 {
1695 // If this doesn't assert in DEBUG, all is well.
1696 tinyxml2::XMLDocument doc;
1697 tinyxml2::XMLElement *pRoot = doc.NewElement("Root");
1698 doc.DeleteNode(pRoot);
1699 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001700
Dmitry-Me8b67d742014-12-22 11:35:12 +03001701 {
1702 // Should not assert in DEBUG
1703 XMLPrinter printer;
1704 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001705
Dmitry-Me6f51c802015-03-14 13:25:03 +03001706 {
1707 // Issue 291. Should not crash
1708 const char* xml = "&#0</a>";
1709 XMLDocument doc;
1710 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001711 XMLTest( "Parse hex with closing tag", false, doc.Error() );
Dmitry-Me6f51c802015-03-14 13:25:03 +03001712
1713 XMLPrinter printer;
1714 doc.Print( &printer );
1715 }
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001716 {
1717 // Issue 299. Can print elements that are not linked in.
1718 // Will crash if issue not fixed.
1719 XMLDocument doc;
1720 XMLElement* newElement = doc.NewElement( "printme" );
1721 XMLPrinter printer;
1722 newElement->Accept( &printer );
Dmitry-Me5daa54c2015-04-08 17:45:07 +03001723 // Delete the node to avoid possible memory leak report in debug output
1724 doc.DeleteNode( newElement );
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001725 }
Lee Thomasonf6577832015-03-26 11:18:21 -07001726 {
Ant Mitchell189198f2015-03-24 16:20:36 +00001727 // Issue 302. Clear errors from LoadFile/SaveFile
1728 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001729 XMLTest( "Issue 302. Should be no error initially", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001730 doc.SaveFile( "./no/such/path/pretty.xml" );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001731 XMLTest( "Issue 302. Fail to save", "XML_ERROR_FILE_COULD_NOT_BE_OPENED", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001732 doc.SaveFile( "./resources/out/compact.xml", true );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001733 XMLTest( "Issue 302. Subsequent success in saving", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001734 }
Dmitry-Me6f51c802015-03-14 13:25:03 +03001735
Dmitry-Med9852a52015-03-25 10:17:49 +03001736 {
1737 // If a document fails to load then subsequent
1738 // successful loads should clear the error
1739 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001740 XMLTest( "Should be no error initially", false, doc.Error() );
Dmitry-Med9852a52015-03-25 10:17:49 +03001741 doc.LoadFile( "resources/no-such-file.xml" );
1742 XMLTest( "No such file - should fail", true, doc.Error() );
1743
1744 doc.LoadFile( "resources/dream.xml" );
1745 XMLTest( "Error should be cleared", false, doc.Error() );
1746 }
Sarat Addepalli8e85afa2015-05-19 09:07:03 +05301747
Sarat Addepalli2bb6bb52015-05-18 09:16:34 +05301748 {
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001749 // Check that declarations are allowed only at beginning of document
Lee Thomason85492022015-05-22 11:07:45 -07001750 const char* xml0 = "<?xml version=\"1.0\" ?>"
1751 " <!-- xml version=\"1.1\" -->"
1752 "<first />";
1753 const char* xml1 = "<?xml version=\"1.0\" ?>"
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001754 "<?xml-stylesheet type=\"text/xsl\" href=\"Anything.xsl\"?>"
Lee Thomason85492022015-05-22 11:07:45 -07001755 "<first />";
1756 const char* xml2 = "<first />"
1757 "<?xml version=\"1.0\" ?>";
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001758 const char* xml3 = "<first></first>"
1759 "<?xml version=\"1.0\" ?>";
1760
1761 const char* xml4 = "<first><?xml version=\"1.0\" ?></first>";
1762
Lee Thomason85492022015-05-22 11:07:45 -07001763 XMLDocument doc;
1764 doc.Parse(xml0);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001765 XMLTest("Test that the code changes do not affect normal parsing", false, doc.Error() );
Lee Thomason85492022015-05-22 11:07:45 -07001766 doc.Parse(xml1);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001767 XMLTest("Test that the second declaration is allowed", false, doc.Error() );
Lee Thomason85492022015-05-22 11:07:45 -07001768 doc.Parse(xml2);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001769 XMLTest("Test that declaration after a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001770 doc.Parse(xml3);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001771 XMLTest("Test that declaration after a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001772 doc.Parse(xml4);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001773 XMLTest("Test that declaration inside a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );
Sarat Addepalli2bb6bb52015-05-18 09:16:34 +05301774 }
Dmitry-Med9852a52015-03-25 10:17:49 +03001775
Lee Thomason85492022015-05-22 11:07:45 -07001776 {
1777 // No matter - before or after successfully parsing a text -
1778 // calling XMLDocument::Value() causes an assert in debug.
1779 const char* validXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
1780 "<first />"
1781 "<second />";
1782 XMLDocument* doc = new XMLDocument();
1783 XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
1784 doc->Parse( validXml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001785 XMLTest( "Parse to test XMLDocument::Value()", false, doc->Error());
Lee Thomason85492022015-05-22 11:07:45 -07001786 XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
1787 delete doc;
1788 }
1789
Dmitry-Mea1beddf2015-05-26 16:19:21 +03001790 {
1791 XMLDocument doc;
1792 for( int i = 0; i < XML_ERROR_COUNT; i++ ) {
kezenatorec694152016-11-26 17:21:43 +10001793 doc.SetError( (XMLError)i, 0, 0, 0 );
Dmitry-Mea1beddf2015-05-26 16:19:21 +03001794 doc.ErrorName();
1795 }
1796 }
1797
Lee Thomason816d3fa2017-06-05 14:35:55 -07001798 {
Lee Thomasonb754ddf2017-06-14 15:02:38 -07001799 // Evil memory leaks.
1800 // If an XMLElement (etc) is allocated via NewElement() (etc.)
1801 // and NOT added to the XMLDocument, what happens?
1802 //
1803 // Previously (buggy):
1804 // The memory would be free'd when the XMLDocument is
1805 // destructed. But the destructor wasn't called, so that
1806 // memory allocated by the XMLElement would not be free'd.
1807 // In practice this meant strings allocated by the XMLElement
1808 // would leak. An edge case, but annoying.
1809 // Now:
1810 // The destructor is called. But the list of unlinked nodes
1811 // has to be tracked. This has a minor performance impact
1812 // that can become significant if you have a lot. (But why
1813 // would you do that?)
1814 // The only way to see this bug is in a leak tracker. This
1815 // is compiled in by default on Windows Debug.
Lee Thomason816d3fa2017-06-05 14:35:55 -07001816 {
1817 XMLDocument doc;
1818 doc.NewElement("LEAK 1");
1819 }
1820 {
1821 XMLDocument doc;
1822 XMLElement* ele = doc.NewElement("LEAK 2");
1823 doc.DeleteNode(ele);
1824 }
1825 }
1826
Lee Thomason224ef772017-06-16 09:45:26 -07001827 {
1828 // Crashing reported via email.
1829 const char* xml =
1830 "<playlist id='playlist1'>"
Lee Thomason82bb0742017-06-16 09:48:20 -07001831 "<property name='track_name'>voice</property>"
1832 "<property name='audio_track'>1</property>"
1833 "<entry out = '604' producer = '4_playlist1' in = '0' />"
1834 "<blank length = '1' />"
1835 "<entry out = '1625' producer = '3_playlist' in = '0' />"
1836 "<blank length = '2' />"
1837 "<entry out = '946' producer = '2_playlist1' in = '0' />"
1838 "<blank length = '1' />"
1839 "<entry out = '128' producer = '1_playlist1' in = '0' />"
Lee Thomason224ef772017-06-16 09:45:26 -07001840 "</playlist>";
Lee Thomason82bb0742017-06-16 09:48:20 -07001841
Lee Thomason224ef772017-06-16 09:45:26 -07001842 // It's not a good idea to delete elements as you walk the
1843 // list. I'm not sure this technically should work; but it's
1844 // an interesting test case.
1845 XMLDocument doc;
1846 XMLError err = doc.Parse(xml);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001847 XMLTest("Crash bug parsing", XML_SUCCESS, err );
Dmitry-Meaea64c42017-06-20 18:20:15 +03001848
1849 XMLElement* playlist = doc.FirstChildElement("playlist");
Lee Thomason224ef772017-06-16 09:45:26 -07001850 XMLTest("Crash bug parsing", true, playlist != 0);
1851
1852 tinyxml2::XMLElement* entry = playlist->FirstChildElement("entry");
1853 XMLTest("Crash bug parsing", true, entry != 0);
1854 while (entry) {
1855 tinyxml2::XMLElement* todelete = entry;
1856 entry = entry->NextSiblingElement("entry");
1857 playlist->DeleteChild(todelete);
1858 };
1859 tinyxml2::XMLElement* blank = playlist->FirstChildElement("blank");
1860 while (blank) {
1861 tinyxml2::XMLElement* todelete = blank;
1862 blank = blank->NextSiblingElement("blank");
1863 playlist->DeleteChild(todelete);
1864 };
1865
1866 tinyxml2::XMLPrinter printer;
1867 playlist->Accept(&printer);
1868 printf("%s\n", printer.CStr());
1869
Lee Thomason82bb0742017-06-16 09:48:20 -07001870 // No test; it only need to not crash.
1871 // Still, wrap it up with a sanity check
1872 int nProperty = 0;
1873 for (const XMLElement* p = playlist->FirstChildElement("property"); p; p = p->NextSiblingElement("property")) {
1874 nProperty++;
1875 }
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001876 XMLTest("Crash bug parsing", 2, nProperty);
Lee Thomason224ef772017-06-16 09:45:26 -07001877 }
1878
kezenatorec694152016-11-26 17:21:43 +10001879 // ----------- Line Number Tracking --------------
1880 {
Lee Thomasone90e9012016-12-24 07:34:39 -08001881 struct TestUtil: XMLVisitor
kezenatorec694152016-11-26 17:21:43 +10001882 {
1883 void TestParseError(const char *testString, const char *docStr, XMLError expected_error, int expectedLine)
1884 {
1885 XMLDocument doc;
1886 XMLError err = doc.Parse(docStr);
1887
1888 XMLTest(testString, true, doc.Error());
1889 XMLTest(testString, expected_error, err);
1890 XMLTest(testString, expectedLine, doc.GetErrorLineNum());
1891 };
1892
1893 void TestStringLines(const char *testString, const char *docStr, const char *expectedLines)
1894 {
1895 XMLDocument doc;
1896 doc.Parse(docStr);
1897 XMLTest(testString, false, doc.Error());
1898 TestDocLines(testString, doc, expectedLines);
1899 }
1900
1901 void TestFileLines(const char *testString, const char *file_name, const char *expectedLines)
1902 {
1903 XMLDocument doc;
1904 doc.LoadFile(file_name);
1905 XMLTest(testString, false, doc.Error());
1906 TestDocLines(testString, doc, expectedLines);
1907 }
1908
1909 private:
1910 DynArray<char, 10> str;
1911
1912 void Push(char type, int lineNum)
1913 {
1914 str.Push(type);
1915 str.Push(char('0' + (lineNum / 10)));
1916 str.Push(char('0' + (lineNum % 10)));
1917 }
1918
1919 bool VisitEnter(const XMLDocument& doc)
1920 {
kezenator19d8ea82016-11-29 19:50:27 +10001921 Push('D', doc.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001922 return true;
1923 }
1924 bool VisitEnter(const XMLElement& element, const XMLAttribute* firstAttribute)
1925 {
kezenator19d8ea82016-11-29 19:50:27 +10001926 Push('E', element.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001927 for (const XMLAttribute *attr = firstAttribute; attr != 0; attr = attr->Next())
kezenator19d8ea82016-11-29 19:50:27 +10001928 Push('A', attr->GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001929 return true;
1930 }
1931 bool Visit(const XMLDeclaration& declaration)
1932 {
kezenator19d8ea82016-11-29 19:50:27 +10001933 Push('L', declaration.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001934 return true;
1935 }
1936 bool Visit(const XMLText& text)
1937 {
kezenator19d8ea82016-11-29 19:50:27 +10001938 Push('T', text.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001939 return true;
1940 }
1941 bool Visit(const XMLComment& comment)
1942 {
kezenator19d8ea82016-11-29 19:50:27 +10001943 Push('C', comment.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001944 return true;
1945 }
1946 bool Visit(const XMLUnknown& unknown)
1947 {
kezenator19d8ea82016-11-29 19:50:27 +10001948 Push('U', unknown.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001949 return true;
1950 }
1951
1952 void TestDocLines(const char *testString, XMLDocument &doc, const char *expectedLines)
1953 {
1954 str.Clear();
1955 doc.Accept(this);
1956 str.Push(0);
1957 XMLTest(testString, expectedLines, str.Mem());
1958 }
Lee Thomasone90e9012016-12-24 07:34:39 -08001959 } tester;
kezenatorec694152016-11-26 17:21:43 +10001960
Lee Thomasone90e9012016-12-24 07:34:39 -08001961 tester.TestParseError("ErrorLine-Parsing", "\n<root>\n foo \n<unclosed/>", XML_ERROR_PARSING, 2);
1962 tester.TestParseError("ErrorLine-Declaration", "<root>\n<?xml version=\"1.0\"?>", XML_ERROR_PARSING_DECLARATION, 2);
1963 tester.TestParseError("ErrorLine-Mismatch", "\n<root>\n</mismatch>", XML_ERROR_MISMATCHED_ELEMENT, 2);
1964 tester.TestParseError("ErrorLine-CData", "\n<root><![CDATA[ \n foo bar \n", XML_ERROR_PARSING_CDATA, 2);
1965 tester.TestParseError("ErrorLine-Text", "\n<root>\n foo bar \n", XML_ERROR_PARSING_TEXT, 3);
1966 tester.TestParseError("ErrorLine-Comment", "\n<root>\n<!-- >\n", XML_ERROR_PARSING_COMMENT, 3);
1967 tester.TestParseError("ErrorLine-Declaration", "\n<root>\n<? >\n", XML_ERROR_PARSING_DECLARATION, 3);
1968 tester.TestParseError("ErrorLine-Unknown", "\n<root>\n<! \n", XML_ERROR_PARSING_UNKNOWN, 3);
1969 tester.TestParseError("ErrorLine-Element", "\n<root>\n<unclosed \n", XML_ERROR_PARSING_ELEMENT, 3);
1970 tester.TestParseError("ErrorLine-Attribute", "\n<root>\n<unclosed \n att\n", XML_ERROR_PARSING_ATTRIBUTE, 4);
1971 tester.TestParseError("ErrorLine-ElementClose", "\n<root>\n<unclosed \n/unexpected", XML_ERROR_PARSING_ELEMENT, 3);
kezenatorec694152016-11-26 17:21:43 +10001972
Lee Thomasone90e9012016-12-24 07:34:39 -08001973 tester.TestStringLines(
kezenatorec694152016-11-26 17:21:43 +10001974 "LineNumbers-String",
Lee Thomasone90e9012016-12-24 07:34:39 -08001975
1976 "<?xml version=\"1.0\"?>\n" // 1 Doc, DecL
1977 "<root a='b' \n" // 2 Element Attribute
1978 "c='d'> d <blah/> \n" // 3 Attribute Text Element
1979 "newline in text \n" // 4 Text
1980 "and second <zxcv/><![CDATA[\n" // 5 Element Text
1981 " cdata test ]]><!-- comment -->\n" // 6 Comment
1982 "<! unknown></root>", // 7 Unknown
1983
kezenatorec694152016-11-26 17:21:43 +10001984 "D01L01E02A02A03T03E03T04E05T05C06U07");
1985
Lee Thomasone90e9012016-12-24 07:34:39 -08001986 tester.TestStringLines(
kezenatorec694152016-11-26 17:21:43 +10001987 "LineNumbers-CRLF",
Lee Thomasone90e9012016-12-24 07:34:39 -08001988
1989 "\r\n" // 1 Doc (arguably should be line 2)
1990 "<?xml version=\"1.0\"?>\n" // 2 DecL
1991 "<root>\r\n" // 3 Element
1992 "\n" // 4
1993 "text contining new line \n" // 5 Text
1994 " and also containing crlf \r\n" // 6
1995 "<sub><![CDATA[\n" // 7 Element Text
1996 "cdata containing new line \n" // 8
1997 " and also containing cflr\r\n" // 9
1998 "]]></sub><sub2/></root>", // 10 Element
1999
kezenatorec694152016-11-26 17:21:43 +10002000 "D01L02E03T05E07T07E10");
2001
Lee Thomasone90e9012016-12-24 07:34:39 -08002002 tester.TestFileLines(
kezenatorec694152016-11-26 17:21:43 +10002003 "LineNumbers-File",
2004 "resources/utf8test.xml",
2005 "D01L01E02E03A03A03T03E04A04A04T04E05A05A05T05E06A06A06T06E07A07A07T07E08A08A08T08E09T09E10T10");
2006 }
2007
Lee Thomason85492022015-05-22 11:07:45 -07002008 // ----------- Performance tracking --------------
Lee Thomason6f381b72012-03-02 12:59:39 -08002009 {
2010#if defined( _MSC_VER )
2011 __int64 start, end, freq;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002012 QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
Lee Thomason6f381b72012-03-02 12:59:39 -08002013#endif
2014
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002015 FILE* perfFP = fopen("resources/dream.xml", "r");
Dmitry-Med1b82822017-07-04 18:02:54 +03002016 XMLTest("Open dream.xml", true, perfFP != 0);
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002017 fseek(perfFP, 0, SEEK_END);
Armagetron3c21d6f2016-10-13 13:31:23 +02002018 long size = ftell(perfFP);
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002019 fseek(perfFP, 0, SEEK_SET);
Lee Thomason6f381b72012-03-02 12:59:39 -08002020
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002021 char* mem = new char[size + 1];
Dmitry-Med1b82822017-07-04 18:02:54 +03002022 memset(mem, 0xfe, size);
Lee Thomasone4dc7212017-07-06 17:05:01 -07002023 size_t bytesRead = fread(mem, 1, size, perfFP);
2024 XMLTest("Read dream.xml", true, uint32_t(size) >= uint32_t(bytesRead));
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002025 fclose(perfFP);
Lee Thomason6f381b72012-03-02 12:59:39 -08002026 mem[size] = 0;
2027
2028#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002029 QueryPerformanceCounter((LARGE_INTEGER*)&start);
Lee Thomason6f381b72012-03-02 12:59:39 -08002030#else
2031 clock_t cstart = clock();
2032#endif
Dmitry-Me68578f42017-07-03 18:21:23 +03002033 bool parseDreamXmlFailed = false;
Lee Thomason6f381b72012-03-02 12:59:39 -08002034 static const int COUNT = 10;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002035 for (int i = 0; i < COUNT; ++i) {
Lee Thomason6f381b72012-03-02 12:59:39 -08002036 XMLDocument doc;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002037 doc.Parse(mem);
Dmitry-Me68578f42017-07-03 18:21:23 +03002038 parseDreamXmlFailed = parseDreamXmlFailed || doc.Error();
Lee Thomason6f381b72012-03-02 12:59:39 -08002039 }
Dmitry-Me68578f42017-07-03 18:21:23 +03002040 XMLTest( "Parse dream.xml", false, parseDreamXmlFailed );
Lee Thomason6f381b72012-03-02 12:59:39 -08002041#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002042 QueryPerformanceCounter((LARGE_INTEGER*)&end);
Lee Thomason6f381b72012-03-02 12:59:39 -08002043#else
2044 clock_t cend = clock();
2045#endif
2046
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002047 delete[] mem;
Lee Thomason6f381b72012-03-02 12:59:39 -08002048
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07002049 static const char* note =
Lee Thomason6f381b72012-03-02 12:59:39 -08002050#ifdef DEBUG
2051 "DEBUG";
2052#else
2053 "Release";
2054#endif
2055
2056#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002057 printf("\nParsing %s of dream.xml: %.3f milli-seconds\n", note, 1000.0 * (double)(end - start) / ((double)freq * (double)COUNT));
Lee Thomason6f381b72012-03-02 12:59:39 -08002058#else
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002059 printf("\nParsing %s of dream.xml: %.3f milli-seconds\n", note, (double)(cend - cstart) / (double)COUNT);
Lee Thomason6f381b72012-03-02 12:59:39 -08002060#endif
2061 }
2062
Lee Thomason (grinliz)7ca55582012-03-07 21:54:57 -08002063 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07002064 _CrtMemCheckpoint( &endMemState );
Lee Thomason1ff38e02012-02-14 18:18:16 -08002065
2066 _CrtMemState diffMemState;
2067 _CrtMemDifference( &diffMemState, &startMemState, &endMemState );
2068 _CrtMemDumpStatistics( &diffMemState );
Dmitry-Meed785702017-06-15 13:39:53 +03002069
2070 {
2071 int leaksBeforeExit = _CrtDumpMemoryLeaks();
2072 XMLTest( "No leaks before exit?", FALSE, leaksBeforeExit );
2073 }
Lee Thomason1ff38e02012-02-14 18:18:16 -08002074 #endif
2075
2076 printf ("\nPass %d, Fail %d\n", gPass, gFail);
Lee Thomason (grinliz)db304252013-07-31 12:24:52 -07002077
2078 return gFail;
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -08002079}