blob: e1951723cb9488f5691f881bc694faa52c37598c [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
Lee Thomason3a6e51a2017-07-06 17:08:37 -0700341#if 0
kbinny62bf29a152017-06-23 18:15:25 +0000342#if defined WIN32
Lee Thomasone4dc7212017-07-06 17:05:01 -0700343 if ( !CreateDirectory( L"resources\\out", NULL ) && GetLastError() != ERROR_ALREADY_EXISTS ) {
kbinny62bf29a152017-06-23 18:15:25 +0000344#else
kbinny629720fba2017-06-27 01:40:33 +0000345 if ( mkdir( "resources/out", S_IRWXU | S_IRGRP | S_IXGRP ) == -1 && errno != EEXIST ) {
kbinny62bf29a152017-06-23 18:15:25 +0000346#endif
347 printf( "Unable to create directory 'resources/out': %s\n", strerror( errno ) );
348 exit( 1 );
349 }
Lee Thomason3a6e51a2017-07-06 17:08:37 -0700350#endif
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700351 XMLTest( "Example-1", 0, example_1() );
352 XMLTest( "Example-2", 0, example_2() );
353 XMLTest( "Example-3", 0, example_3() );
Lee Thomason21be8822012-07-15 17:27:22 -0700354 XMLTest( "Example-4", true, example_4() );
Lee Thomason87e475a2012-03-20 11:55:29 -0700355
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700356 /* ------ Example 2: Lookup information. ---- */
Lee Thomason87e475a2012-03-20 11:55:29 -0700357
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800358 {
Lee Thomason43f59302012-02-06 18:18:11 -0800359 static const char* test[] = { "<element />",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400360 "<element></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800361 "<element><subelement/></element>",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400362 "<element><subelement></subelement></element>",
363 "<element><subelement><subsub/></subelement></element>",
364 "<!--comment beside elements--><element><subelement></subelement></element>",
365 "<!--comment beside elements, this time with spaces--> \n <element> <subelement> \n </subelement> </element>",
366 "<element attrib1='foo' attrib2=\"bar\" ></element>",
367 "<element attrib1='foo' attrib2=\"bar\" ><subelement attrib3='yeehaa' /></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800368 "<element>Text inside element.</element>",
369 "<element><b></b></element>",
370 "<element>Text inside and <b>bolded</b> in the element.</element>",
371 "<outer><element>Text inside and <b>bolded</b> in the element.</element></outer>",
Lee Thomason8ee79892012-01-25 17:44:30 -0800372 "<element>This &amp; That.</element>",
Lee Thomason18d68bd2012-01-26 18:17:26 -0800373 "<element attrib='This&lt;That' />",
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800374 0
375 };
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800376 for( int i=0; test[i]; ++i ) {
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800377 XMLDocument doc;
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800378 doc.Parse( test[i] );
Dmitry-Me68578f42017-07-03 18:21:23 +0300379 XMLTest( "Element test", false, doc.Error() );
Lee Thomason5cae8972012-01-24 18:03:07 -0800380 doc.Print();
Lee Thomasonec975ce2012-01-23 11:42:06 -0800381 printf( "----------------------------------------------\n" );
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800382 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800383 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800384#if 1
Lee Thomasond6277762012-02-22 16:00:12 -0800385 {
386 static const char* test = "<!--hello world\n"
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400387 " line 2\r"
388 " line 3\r\n"
389 " line 4\n\r"
390 " line 5\r-->";
Lee Thomasond6277762012-02-22 16:00:12 -0800391
392 XMLDocument doc;
393 doc.Parse( test );
Dmitry-Me68578f42017-07-03 18:21:23 +0300394 XMLTest( "Hello world declaration", false, doc.Error() );
Lee Thomasond6277762012-02-22 16:00:12 -0800395 doc.Print();
396 }
397
Lee Thomason2c85a712012-01-31 08:24:24 -0800398 {
399 static const char* test = "<element>Text before.</element>";
400 XMLDocument doc;
401 doc.Parse( test );
Dmitry-Me68578f42017-07-03 18:21:23 +0300402 XMLTest( "Element text before", false, doc.Error() );
Lee Thomason2c85a712012-01-31 08:24:24 -0800403 XMLElement* root = doc.FirstChildElement();
404 XMLElement* newElement = doc.NewElement( "Subelement" );
405 root->InsertEndChild( newElement );
406 doc.Print();
407 }
Lee Thomasond1983222012-02-06 08:41:24 -0800408 {
409 XMLDocument* doc = new XMLDocument();
410 static const char* test = "<element><sub/></element>";
411 doc->Parse( test );
Dmitry-Me68578f42017-07-03 18:21:23 +0300412 XMLTest( "Element with sub element", false, doc->Error() );
Lee Thomasond1983222012-02-06 08:41:24 -0800413 delete doc;
414 }
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800415 {
Lee Thomason1ff38e02012-02-14 18:18:16 -0800416 // Test: Programmatic DOM
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800417 // Build:
418 // <element>
419 // <!--comment-->
420 // <sub attrib="1" />
421 // <sub attrib="2" />
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800422 // <sub attrib="3" >& Text!</sub>
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800423 // <element>
424
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800425 XMLDocument* doc = new XMLDocument();
Lee Thomason1ff38e02012-02-14 18:18:16 -0800426 XMLNode* element = doc->InsertEndChild( doc->NewElement( "element" ) );
427
428 XMLElement* sub[3] = { doc->NewElement( "sub" ), doc->NewElement( "sub" ), doc->NewElement( "sub" ) };
429 for( int i=0; i<3; ++i ) {
430 sub[i]->SetAttribute( "attrib", i );
431 }
432 element->InsertEndChild( sub[2] );
433 XMLNode* comment = element->InsertFirstChild( doc->NewComment( "comment" ) );
Lee Thomasonaf9bce12016-07-17 22:35:52 -0700434 comment->SetUserData((void*)2);
Lee Thomason1ff38e02012-02-14 18:18:16 -0800435 element->InsertAfterChild( comment, sub[0] );
436 element->InsertAfterChild( sub[0], sub[1] );
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800437 sub[2]->InsertFirstChild( doc->NewText( "& Text!" ));
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800438 doc->Print();
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800439 XMLTest( "Programmatic DOM", "comment", doc->FirstChildElement( "element" )->FirstChild()->Value() );
440 XMLTest( "Programmatic DOM", "0", doc->FirstChildElement( "element" )->FirstChildElement()->Attribute( "attrib" ) );
441 XMLTest( "Programmatic DOM", 2, doc->FirstChildElement()->LastChildElement( "sub" )->IntAttribute( "attrib" ) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700442 XMLTest( "Programmatic DOM", "& Text!",
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800443 doc->FirstChildElement()->LastChildElement( "sub" )->FirstChild()->ToText()->Value() );
Lee Thomasonc9445462016-07-17 22:53:48 -0700444 XMLTest("User data", (void*)2 == comment->GetUserData(), true, false);
U-Stream\Leeae25a442012-02-17 17:48:16 -0800445
446 // And now deletion:
447 element->DeleteChild( sub[2] );
448 doc->DeleteNode( comment );
449
450 element->FirstChildElement()->SetAttribute( "attrib", true );
451 element->LastChildElement()->DeleteAttribute( "attrib" );
452
453 XMLTest( "Programmatic DOM", true, doc->FirstChildElement()->FirstChildElement()->BoolAttribute( "attrib" ) );
Dmitry-Me3d20c5d2017-07-10 18:28:19 +0300454 const int defaultIntValue = 10;
455 const int replacementIntValue = 20;
456 int value1 = defaultIntValue;
457 int value2 = doc->FirstChildElement()->LastChildElement()->IntAttribute( "attrib", replacementIntValue );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300458 XMLError result = doc->FirstChildElement()->LastChildElement()->QueryIntAttribute( "attrib", &value1 );
459 XMLTest( "Programmatic DOM", XML_NO_ATTRIBUTE, result );
Dmitry-Me3d20c5d2017-07-10 18:28:19 +0300460 XMLTest( "Programmatic DOM", defaultIntValue, value1 );
461 XMLTest( "Programmatic DOM", replacementIntValue, value2 );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800462
463 doc->Print();
464
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700465 {
466 XMLPrinter streamer;
467 doc->Print( &streamer );
468 printf( "%s", streamer.CStr() );
469 }
470 {
471 XMLPrinter streamer( 0, true );
472 doc->Print( &streamer );
Doruk Turak1f212f32016-08-28 20:54:17 +0200473 XMLTest( "Compact mode", "<element><sub attrib=\"true\"/><sub/></element>", streamer.CStr(), false );
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700474 }
Lee Thomason (grinliz)6b8b0122012-09-08 21:21:00 -0700475 doc->SaveFile( "./resources/out/pretty.xml" );
476 doc->SaveFile( "./resources/out/compact.xml", true );
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800477 delete doc;
478 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800479 {
480 // Test: Dream
481 // XML1 : 1,187,569 bytes in 31,209 allocations
482 // XML2 : 469,073 bytes in 323 allocations
483 //int newStart = gNew;
484 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300485 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800486
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400487 doc.SaveFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800488 doc.PrintError();
489
490 XMLTest( "Dream", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400491 doc.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800492 XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() ? true : false );
493 XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
494 doc.FirstChild()->NextSibling()->ToUnknown()->Value() );
495 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400496 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800497 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400498 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800499
500 XMLDocument doc2;
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400501 doc2.LoadFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800502 XMLTest( "Dream-out", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400503 doc2.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800504 XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() ? true : false );
505 XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
506 doc2.FirstChild()->NextSibling()->ToUnknown()->Value() );
507 XMLTest( "Dream-out", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400508 doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800509
510 //gNewTotal = gNew - newStart;
511 }
Lee Thomason6f381b72012-03-02 12:59:39 -0800512
513
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800514 {
515 const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n"
516 "<passages count=\"006\" formatversion=\"20020620\">\n"
517 " <wrong error>\n"
518 "</passages>";
519
520 XMLDocument doc;
521 doc.Parse( error );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300522 XMLTest( "Bad XML", XML_ERROR_PARSING_ATTRIBUTE, doc.ErrorID() );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800523 }
524
525 {
526 const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
527
528 XMLDocument doc;
529 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300530 XMLTest( "Top level attributes", false, doc.Error() );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800531
532 XMLElement* ele = doc.FirstChildElement();
533
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300534 int iVal;
535 XMLError result;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800536 double dVal;
537
538 result = ele->QueryDoubleAttribute( "attr0", &dVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300539 XMLTest( "Query attribute: int as double", XML_SUCCESS, result);
540 XMLTest( "Query attribute: int as double", 1, (int)dVal );
541 XMLTest( "Query attribute: int as double", 1, (int)ele->DoubleAttribute("attr0"));
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700542
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800543 result = ele->QueryDoubleAttribute( "attr1", &dVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300544 XMLTest( "Query attribute: double as double", XML_SUCCESS, result);
545 XMLTest( "Query attribute: double as double", 2.0, dVal );
546 XMLTest( "Query attribute: double as double", 2.0, ele->DoubleAttribute("attr1") );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700547
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800548 result = ele->QueryIntAttribute( "attr1", &iVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300549 XMLTest( "Query attribute: double as int", XML_SUCCESS, result);
550 XMLTest( "Query attribute: double as int", 2, iVal );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700551
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800552 result = ele->QueryIntAttribute( "attr2", &iVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300553 XMLTest( "Query attribute: not a number", XML_WRONG_ATTRIBUTE_TYPE, result );
554 XMLTest( "Query attribute: not a number", 4.0, ele->DoubleAttribute("attr2", 4.0) );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700555
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800556 result = ele->QueryIntAttribute( "bar", &iVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300557 XMLTest( "Query attribute: does not exist", XML_NO_ATTRIBUTE, result );
558 XMLTest( "Query attribute: does not exist", true, ele->BoolAttribute("bar", true) );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800559 }
560
561 {
562 const char* str = "<doc/>";
563
564 XMLDocument doc;
565 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300566 XMLTest( "Empty top element", false, doc.Error() );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800567
568 XMLElement* ele = doc.FirstChildElement();
569
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800570 int iVal, iVal2;
571 double dVal, dVal2;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800572
573 ele->SetAttribute( "str", "strValue" );
574 ele->SetAttribute( "int", 1 );
575 ele->SetAttribute( "double", -1.0 );
576
577 const char* cStr = ele->Attribute( "str" );
578 ele->QueryIntAttribute( "int", &iVal );
579 ele->QueryDoubleAttribute( "double", &dVal );
580
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800581 ele->QueryAttribute( "int", &iVal2 );
582 ele->QueryAttribute( "double", &dVal2 );
583
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300584 XMLTest( "Attribute match test", "strValue", ele->Attribute( "str", "strValue" ) );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800585 XMLTest( "Attribute round trip. c-string.", "strValue", cStr );
586 XMLTest( "Attribute round trip. int.", 1, iVal );
587 XMLTest( "Attribute round trip. double.", -1, (int)dVal );
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800588 XMLTest( "Alternate query", true, iVal == iVal2 );
589 XMLTest( "Alternate query", true, dVal == dVal2 );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700590 XMLTest( "Alternate query", true, iVal == ele->IntAttribute("int") );
591 XMLTest( "Alternate query", true, dVal == ele->DoubleAttribute("double") );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800592 }
593
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800594 {
595 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300596 doc.LoadFile( "resources/utf8test.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800597
598 // Get the attribute "value" from the "Russian" element and check it.
599 XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700600 const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800601 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
602
603 XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) );
604
605 const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U,
606 0xd1U, 0x81U, 0xd1U, 0x81U,
607 0xd0U, 0xbaU, 0xd0U, 0xb8U,
608 0xd0U, 0xb9U, 0 };
609 const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
610
611 XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText();
612 XMLTest( "UTF-8: Browsing russian element name.",
613 russianText,
614 text->Value() );
615
616 // Now try for a round trip.
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400617 doc.SaveFile( "resources/out/utf8testout.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800618
619 // Check the round trip.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800620 int okay = 0;
621
Thomas Roßa6dd8c62012-07-26 20:42:18 +0200622 FILE* saved = fopen( "resources/out/utf8testout.xml", "r" );
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300623 FILE* verify = fopen( "resources/utf8testverify.xml", "r" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800624
625 if ( saved && verify )
626 {
627 okay = 1;
PKEuSc28ba3a2012-07-16 03:08:47 -0700628 char verifyBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800629 while ( fgets( verifyBuf, 256, verify ) )
630 {
PKEuSc28ba3a2012-07-16 03:08:47 -0700631 char savedBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800632 fgets( savedBuf, 256, saved );
633 NullLineEndings( verifyBuf );
634 NullLineEndings( savedBuf );
635
636 if ( strcmp( verifyBuf, savedBuf ) )
637 {
638 printf( "verify:%s<\n", verifyBuf );
639 printf( "saved :%s<\n", savedBuf );
640 okay = 0;
641 break;
642 }
643 }
644 }
645 if ( saved )
646 fclose( saved );
647 if ( verify )
648 fclose( verify );
649 XMLTest( "UTF-8: Verified multi-language round trip.", 1, okay );
650 }
651
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800652 // --------GetText()-----------
653 {
654 const char* str = "<foo>This is text</foo>";
655 XMLDocument doc;
656 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300657 XMLTest( "Double whitespace", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800658 const XMLElement* element = doc.RootElement();
659
660 XMLTest( "GetText() normal use.", "This is text", element->GetText() );
661
662 str = "<foo><b>This is text</b></foo>";
663 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300664 XMLTest( "Bold text simulation", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800665 element = doc.RootElement();
666
667 XMLTest( "GetText() contained element.", element->GetText() == 0, true );
668 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800669
Lee Thomasond6277762012-02-22 16:00:12 -0800670
Uli Kusterer321072e2014-01-21 01:57:38 +0100671 // --------SetText()-----------
672 {
673 const char* str = "<foo></foo>";
674 XMLDocument doc;
675 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300676 XMLTest( "Empty closed element", false, doc.Error() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100677 XMLElement* element = doc.RootElement();
678
Lee Thomason9c0678a2014-01-24 10:18:27 -0800679 element->SetText("darkness.");
680 XMLTest( "SetText() normal use (open/close).", "darkness.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100681
Lee Thomason9c0678a2014-01-24 10:18:27 -0800682 element->SetText("blue flame.");
683 XMLTest( "SetText() replace.", "blue flame.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100684
685 str = "<foo/>";
686 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300687 XMLTest( "Empty self-closed element", false, doc.Error() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100688 element = doc.RootElement();
689
Lee Thomason9c0678a2014-01-24 10:18:27 -0800690 element->SetText("The driver");
691 XMLTest( "SetText() normal use. (self-closing)", "The driver", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100692
Lee Thomason9c0678a2014-01-24 10:18:27 -0800693 element->SetText("<b>horses</b>");
694 XMLTest( "SetText() replace with tag-like text.", "<b>horses</b>", element->GetText() );
695 //doc.Print();
Uli Kusterer321072e2014-01-21 01:57:38 +0100696
697 str = "<foo><bar>Text in nested element</bar></foo>";
698 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300699 XMLTest( "Text in nested element", false, doc.Error() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100700 element = doc.RootElement();
701
Lee Thomason9c0678a2014-01-24 10:18:27 -0800702 element->SetText("wolves");
703 XMLTest( "SetText() prefix to nested non-text children.", "wolves", element->GetText() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800704
705 str = "<foo/>";
706 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300707 XMLTest( "Empty self-closed element round 2", false, doc.Error() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800708 element = doc.RootElement();
709
710 element->SetText( "str" );
711 XMLTest( "SetText types", "str", element->GetText() );
712
713 element->SetText( 1 );
714 XMLTest( "SetText types", "1", element->GetText() );
715
716 element->SetText( 1U );
717 XMLTest( "SetText types", "1", element->GetText() );
718
719 element->SetText( true );
Doruk Turak1f212f32016-08-28 20:54:17 +0200720 XMLTest( "SetText types", "true", element->GetText() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800721
722 element->SetText( 1.5f );
723 XMLTest( "SetText types", "1.5", element->GetText() );
724
725 element->SetText( 1.5 );
726 XMLTest( "SetText types", "1.5", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100727 }
728
Lee Thomason51c12712016-06-04 20:18:49 -0700729 // ---------- Attributes ---------
730 {
731 static const int64_t BIG = -123456789012345678;
732 XMLDocument doc;
733 XMLElement* element = doc.NewElement("element");
734 doc.InsertFirstChild(element);
735
736 {
737 element->SetAttribute("attrib", int(-100));
738 int v = 0;
739 element->QueryIntAttribute("attrib", &v);
740 XMLTest("Attribute: int", -100, v, true);
741 element->QueryAttribute("attrib", &v);
742 XMLTest("Attribute: int", -100, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700743 XMLTest("Attribute: int", -100, element->IntAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700744 }
745 {
746 element->SetAttribute("attrib", unsigned(100));
747 unsigned v = 0;
748 element->QueryUnsignedAttribute("attrib", &v);
749 XMLTest("Attribute: unsigned", unsigned(100), v, true);
750 element->QueryAttribute("attrib", &v);
751 XMLTest("Attribute: unsigned", unsigned(100), v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700752 XMLTest("Attribute: unsigned", unsigned(100), element->UnsignedAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700753 }
754 {
755 element->SetAttribute("attrib", BIG);
756 int64_t v = 0;
757 element->QueryInt64Attribute("attrib", &v);
758 XMLTest("Attribute: int64_t", BIG, v, true);
759 element->QueryAttribute("attrib", &v);
760 XMLTest("Attribute: int64_t", BIG, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700761 XMLTest("Attribute: int64_t", BIG, element->Int64Attribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700762 }
763 {
764 element->SetAttribute("attrib", true);
765 bool v = false;
766 element->QueryBoolAttribute("attrib", &v);
767 XMLTest("Attribute: bool", true, v, true);
768 element->QueryAttribute("attrib", &v);
769 XMLTest("Attribute: bool", true, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700770 XMLTest("Attribute: bool", true, element->BoolAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700771 }
772 {
Lee Thomasonce667c92016-12-26 16:45:30 -0800773 element->SetAttribute("attrib", true);
774 const char* result = element->Attribute("attrib");
775 XMLTest("Bool true is 'true'", "true", result);
776
Lee Thomasonc5c99c22016-12-29 11:19:17 -0800777 XMLUtil::SetBoolSerialization("1", "0");
Lee Thomasonce667c92016-12-26 16:45:30 -0800778 element->SetAttribute("attrib", true);
779 result = element->Attribute("attrib");
780 XMLTest("Bool true is '1'", "1", result);
781
Lee Thomasonc5c99c22016-12-29 11:19:17 -0800782 XMLUtil::SetBoolSerialization(0, 0);
Lee Thomasonce667c92016-12-26 16:45:30 -0800783 }
784 {
Lee Thomason51c12712016-06-04 20:18:49 -0700785 element->SetAttribute("attrib", 100.0);
786 double v = 0;
787 element->QueryDoubleAttribute("attrib", &v);
788 XMLTest("Attribute: double", 100.0, v, true);
789 element->QueryAttribute("attrib", &v);
790 XMLTest("Attribute: double", 100.0, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700791 XMLTest("Attribute: double", 100.0, element->DoubleAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700792 }
793 {
794 element->SetAttribute("attrib", 100.0f);
795 float v = 0;
796 element->QueryFloatAttribute("attrib", &v);
797 XMLTest("Attribute: float", 100.0f, v, true);
798 element->QueryAttribute("attrib", &v);
799 XMLTest("Attribute: float", 100.0f, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700800 XMLTest("Attribute: float", 100.0f, element->FloatAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700801 }
802 {
803 element->SetText(BIG);
804 int64_t v = 0;
805 element->QueryInt64Text(&v);
806 XMLTest("Element: int64_t", BIG, v, true);
807 }
808 }
809
810 // ---------- XMLPrinter stream mode ------
811 {
812 {
813 FILE* printerfp = fopen("resources/printer.xml", "w");
814 XMLPrinter printer(printerfp);
815 printer.OpenElement("foo");
816 printer.PushAttribute("attrib-text", "text");
817 printer.PushAttribute("attrib-int", int(1));
818 printer.PushAttribute("attrib-unsigned", unsigned(2));
819 printer.PushAttribute("attrib-int64", int64_t(3));
820 printer.PushAttribute("attrib-bool", true);
821 printer.PushAttribute("attrib-double", 4.0);
822 printer.CloseElement();
823 fclose(printerfp);
824 }
825 {
826 XMLDocument doc;
827 doc.LoadFile("resources/printer.xml");
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300828 XMLTest("XMLPrinter Stream mode: load", XML_SUCCESS, doc.ErrorID(), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700829
830 const XMLDocument& cdoc = doc;
831
832 const XMLAttribute* attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-text");
833 XMLTest("attrib-text", "text", attrib->Value(), true);
834 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int");
835 XMLTest("attrib-int", int(1), attrib->IntValue(), true);
836 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-unsigned");
837 XMLTest("attrib-unsigned", unsigned(2), attrib->UnsignedValue(), true);
838 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int64");
839 XMLTest("attrib-int64", int64_t(3), attrib->Int64Value(), true);
840 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-bool");
841 XMLTest("attrib-bool", true, attrib->BoolValue(), true);
842 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-double");
843 XMLTest("attrib-double", 4.0, attrib->DoubleValue(), true);
844 }
845
846 }
847
Uli Kusterer321072e2014-01-21 01:57:38 +0100848
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800849 // ---------- CDATA ---------------
850 {
851 const char* str = "<xmlElement>"
852 "<![CDATA["
853 "I am > the rules!\n"
854 "...since I make symbolic puns"
855 "]]>"
856 "</xmlElement>";
857 XMLDocument doc;
858 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300859 XMLTest( "CDATA symbolic puns round 1", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800860 doc.Print();
Lee Thomasond6277762012-02-22 16:00:12 -0800861
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300862 XMLTest( "CDATA parse.", "I am > the rules!\n...since I make symbolic puns",
863 doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomasond6277762012-02-22 16:00:12 -0800864 false );
865 }
866
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800867 // ----------- CDATA -------------
868 {
869 const char* str = "<xmlElement>"
870 "<![CDATA["
871 "<b>I am > the rules!</b>\n"
872 "...since I make symbolic puns"
873 "]]>"
874 "</xmlElement>";
875 XMLDocument doc;
876 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300877 XMLTest( "CDATA symbolic puns round 2", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800878 doc.Print();
879
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300880 XMLTest( "CDATA parse. [ tixml1:1480107 ]",
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800881 "<b>I am > the rules!</b>\n...since I make symbolic puns",
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300882 doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800883 false );
884 }
885
886 // InsertAfterChild causes crash.
887 {
888 // InsertBeforeChild and InsertAfterChild causes crash.
889 XMLDocument doc;
890 XMLElement* parent = doc.NewElement( "Parent" );
891 doc.InsertFirstChild( parent );
892
893 XMLElement* childText0 = doc.NewElement( "childText0" );
894 XMLElement* childText1 = doc.NewElement( "childText1" );
895
896 XMLNode* childNode0 = parent->InsertEndChild( childText0 );
897 XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 );
898
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300899 XMLTest( "Test InsertAfterChild on empty node. ", true, ( childNode1 == parent->LastChild() ) );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800900 }
Lee Thomasond6277762012-02-22 16:00:12 -0800901
902 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800903 // Entities not being written correctly.
904 // From Lynn Allen
Lee Thomasond6277762012-02-22 16:00:12 -0800905
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800906 const char* passages =
907 "<?xml version=\"1.0\" standalone=\"no\" ?>"
908 "<passages count=\"006\" formatversion=\"20020620\">"
909 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
910 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
911 "</passages>";
Lee Thomasond6277762012-02-22 16:00:12 -0800912
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800913 XMLDocument doc;
914 doc.Parse( passages );
Dmitry-Me68578f42017-07-03 18:21:23 +0300915 XMLTest( "Entity transformation parse round 1", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800916 XMLElement* psg = doc.RootElement()->FirstChildElement();
917 const char* context = psg->Attribute( "context" );
918 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 -0800919
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800920 XMLTest( "Entity transformation: read. ", expected, context, true );
Lee Thomasond6277762012-02-22 16:00:12 -0800921
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400922 FILE* textfile = fopen( "resources/out/textfile.txt", "w" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800923 if ( textfile )
924 {
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800925 XMLPrinter streamer( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800926 psg->Accept( &streamer );
927 fclose( textfile );
928 }
Thomas Roß0922b732012-09-23 16:31:22 +0200929
930 textfile = fopen( "resources/out/textfile.txt", "r" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800931 TIXMLASSERT( textfile );
932 if ( textfile )
933 {
934 char buf[ 1024 ];
935 fgets( buf, 1024, textfile );
936 XMLTest( "Entity transformation: write. ",
937 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
938 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.\"/>\n",
939 buf, false );
PKEuSc28ba3a2012-07-16 03:08:47 -0700940 fclose( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800941 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800942 }
943
944 {
Lee Thomason6f381b72012-03-02 12:59:39 -0800945 // Suppress entities.
946 const char* passages =
947 "<?xml version=\"1.0\" standalone=\"no\" ?>"
948 "<passages count=\"006\" formatversion=\"20020620\">"
949 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
950 "</passages>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700951
Lee Thomason6f381b72012-03-02 12:59:39 -0800952 XMLDocument doc( false );
953 doc.Parse( passages );
Dmitry-Me68578f42017-07-03 18:21:23 +0300954 XMLTest( "Entity transformation parse round 2", false, doc.Error() );
Lee Thomason6f381b72012-03-02 12:59:39 -0800955
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300956 XMLTest( "No entity parsing.",
957 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.",
958 doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ) );
959 XMLTest( "No entity parsing.", "Crazy &ttk;",
960 doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value() );
Lee Thomason6f381b72012-03-02 12:59:39 -0800961 doc.Print();
962 }
963
964 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400965 const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800966
967 XMLDocument doc;
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400968 doc.Parse( test );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300969 XMLTest( "dot in names", false, doc.Error() );
970 XMLTest( "dot in names", "a.elem", doc.FirstChildElement()->Name() );
971 XMLTest( "dot in names", "2.0", doc.FirstChildElement()->Attribute( "xmi.version" ) );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800972 }
973
974 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400975 const char* test = "<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800976
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400977 XMLDocument doc;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800978 doc.Parse( test );
Dmitry-Me68578f42017-07-03 18:21:23 +0300979 XMLTest( "fin thickness", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800980
981 XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
982 XMLTest( "Entity with one digit.",
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300983 "1.1 Start easy ignore fin thickness\n", text->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800984 false );
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400985 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800986
987 {
988 // DOCTYPE not preserved (950171)
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700989 //
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800990 const char* doctype =
991 "<?xml version=\"1.0\" ?>"
992 "<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
993 "<!ELEMENT title (#PCDATA)>"
994 "<!ELEMENT books (title,authors)>"
995 "<element />";
996
997 XMLDocument doc;
998 doc.Parse( doctype );
Dmitry-Me68578f42017-07-03 18:21:23 +0300999 XMLTest( "PLAY SYSTEM parse", false, doc.Error() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +04001000 doc.SaveFile( "resources/out/test7.xml" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001001 XMLTest( "PLAY SYSTEM save", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001002 doc.DeleteChild( doc.RootElement() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +04001003 doc.LoadFile( "resources/out/test7.xml" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001004 XMLTest( "PLAY SYSTEM load", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001005 doc.Print();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001006
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001007 const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown();
1008 XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() );
1009
1010 }
1011
1012 {
1013 // Comments do not stream out correctly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001014 const char* doctype =
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001015 "<!-- Somewhat<evil> -->";
1016 XMLDocument doc;
1017 doc.Parse( doctype );
Dmitry-Me68578f42017-07-03 18:21:23 +03001018 XMLTest( "Comment somewhat evil", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001019
1020 XMLComment* comment = doc.FirstChild()->ToComment();
1021
1022 XMLTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
1023 }
1024 {
1025 // Double attributes
1026 const char* doctype = "<element attr='red' attr='blue' />";
1027
1028 XMLDocument doc;
1029 doc.Parse( doctype );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001030
Lee Thomason2fa81722012-11-09 12:37:46 -08001031 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 -08001032 doc.PrintError();
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001033 }
1034
1035 {
1036 // Embedded null in stream.
1037 const char* doctype = "<element att\0r='red' attr='blue' />";
1038
1039 XMLDocument doc;
1040 doc.Parse( doctype );
1041 XMLTest( "Embedded null throws error.", true, doc.Error() );
1042 }
1043
1044 {
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -07001045 // Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
Dmitry-Me588bb8d2014-12-25 18:59:18 +03001046 const char* str = "";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001047 XMLDocument doc;
1048 doc.Parse( str );
Lee Thomason2fa81722012-11-09 12:37:46 -08001049 XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001050 }
1051
1052 {
Dmitry-Me588bb8d2014-12-25 18:59:18 +03001053 // Documents with all whitespaces should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
1054 const char* str = " ";
1055 XMLDocument doc;
1056 doc.Parse( str );
1057 XMLTest( "All whitespaces document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
1058 }
1059
1060 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001061 // Low entities
1062 XMLDocument doc;
1063 doc.Parse( "<test>&#x0e;</test>" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001064 XMLTest( "Hex values", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001065 const char result[] = { 0x0e, 0 };
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001066 XMLTest( "Low entities.", result, doc.FirstChildElement()->GetText() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001067 doc.Print();
1068 }
1069
1070 {
1071 // Attribute values with trailing quotes not handled correctly
1072 XMLDocument doc;
1073 doc.Parse( "<foo attribute=bar\" />" );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001074 XMLTest( "Throw error with bad end quotes.", true, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001075 }
1076
1077 {
1078 // [ 1663758 ] Failure to report error on bad XML
1079 XMLDocument xml;
1080 xml.Parse("<x>");
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001081 XMLTest("Missing end tag at end of input", true, xml.Error());
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001082 xml.Parse("<x> ");
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001083 XMLTest("Missing end tag with trailing whitespace", true, xml.Error());
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001084 xml.Parse("<x></y>");
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001085 XMLTest("Mismatched tags", XML_ERROR_MISMATCHED_ELEMENT, xml.ErrorID() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001086 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001087
1088
1089 {
1090 // [ 1475201 ] TinyXML parses entities in comments
1091 XMLDocument xml;
1092 xml.Parse("<!-- declarations for <head> & <body> -->"
1093 "<!-- far &amp; away -->" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001094 XMLTest( "Declarations for head and body", false, xml.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001095
1096 XMLNode* e0 = xml.FirstChild();
1097 XMLNode* e1 = e0->NextSibling();
1098 XMLComment* c0 = e0->ToComment();
1099 XMLComment* c1 = e1->ToComment();
1100
1101 XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
1102 XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
1103 }
1104
1105 {
1106 XMLDocument xml;
1107 xml.Parse( "<Parent>"
1108 "<child1 att=''/>"
1109 "<!-- With this comment, child2 will not be parsed! -->"
1110 "<child2 att=''/>"
1111 "</Parent>" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001112 XMLTest( "Comments iteration", false, xml.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001113 xml.Print();
1114
1115 int count = 0;
1116
1117 for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
1118 ele;
1119 ele = ele->NextSibling() )
1120 {
1121 ++count;
1122 }
1123
1124 XMLTest( "Comments iterate correctly.", 3, count );
1125 }
1126
1127 {
1128 // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
1129 unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
1130 buf[60] = 239;
1131 buf[61] = 0;
1132
1133 XMLDocument doc;
1134 doc.Parse( (const char*)buf);
Dmitry-Me68578f42017-07-03 18:21:23 +03001135 XMLTest( "Broken CDATA", true, doc.Error() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001136 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001137
1138
1139 {
1140 // bug 1827248 Error while parsing a little bit malformed file
1141 // Actually not malformed - should work.
1142 XMLDocument xml;
1143 xml.Parse( "<attributelist> </attributelist >" );
1144 XMLTest( "Handle end tag whitespace", false, xml.Error() );
1145 }
1146
1147 {
1148 // This one must not result in an infinite loop
1149 XMLDocument xml;
1150 xml.Parse( "<infinite>loop" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001151 XMLTest( "No closing element", true, xml.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001152 XMLTest( "Infinite loop test.", true, true );
1153 }
1154#endif
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001155 {
1156 const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
1157 XMLDocument doc;
1158 doc.Parse( pub );
Dmitry-Me68578f42017-07-03 18:21:23 +03001159 XMLTest( "Trailing DOCTYPE", false, doc.Error() );
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001160
1161 XMLDocument clone;
1162 for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
1163 XMLNode* copy = node->ShallowClone( &clone );
1164 clone.InsertEndChild( copy );
1165 }
1166
1167 clone.Print();
1168
1169 int count=0;
1170 const XMLNode* a=clone.FirstChild();
1171 const XMLNode* b=doc.FirstChild();
1172 for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
1173 ++count;
1174 XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
1175 }
1176 XMLTest( "Clone and Equal", 4, count );
1177 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001178
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001179 {
Lee Thomason7085f002017-06-01 18:09:43 -07001180 // Deep Cloning of root element.
1181 XMLDocument doc2;
1182 XMLPrinter printer1;
1183 {
1184 // Make sure doc1 is deleted before we test doc2
1185 const char* xml =
1186 "<root>"
1187 " <child1 foo='bar'/>"
1188 " <!-- comment thing -->"
1189 " <child2 val='1'>Text</child2>"
1190 "</root>";
1191 XMLDocument doc;
1192 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001193 XMLTest( "Parse before deep cloning root element", false, doc.Error() );
Lee Thomason7085f002017-06-01 18:09:43 -07001194
1195 doc.Print(&printer1);
1196 XMLNode* root = doc.RootElement()->DeepClone(&doc2);
1197 doc2.InsertFirstChild(root);
1198 }
1199 XMLPrinter printer2;
1200 doc2.Print(&printer2);
1201
1202 XMLTest("Deep clone of element.", printer1.CStr(), printer2.CStr(), true);
1203 }
1204
1205 {
1206 // Deep Cloning of sub element.
1207 XMLDocument doc2;
1208 XMLPrinter printer1;
1209 {
1210 // Make sure doc1 is deleted before we test doc2
1211 const char* xml =
1212 "<?xml version ='1.0'?>"
1213 "<root>"
1214 " <child1 foo='bar'/>"
1215 " <!-- comment thing -->"
1216 " <child2 val='1'>Text</child2>"
1217 "</root>";
1218 XMLDocument doc;
1219 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001220 XMLTest( "Parse before deep cloning sub element", false, doc.Error() );
Lee Thomason7085f002017-06-01 18:09:43 -07001221
1222 const XMLElement* subElement = doc.FirstChildElement("root")->FirstChildElement("child2");
1223 subElement->Accept(&printer1);
1224
1225 XMLNode* clonedSubElement = subElement->DeepClone(&doc2);
1226 doc2.InsertFirstChild(clonedSubElement);
1227 }
1228 XMLPrinter printer2;
1229 doc2.Print(&printer2);
1230
1231 XMLTest("Deep clone of sub-element.", printer1.CStr(), printer2.CStr(), true);
1232 }
1233
1234 {
1235 // Deep cloning of document.
1236 XMLDocument doc2;
1237 XMLPrinter printer1;
1238 {
1239 // Make sure doc1 is deleted before we test doc2
1240 const char* xml =
1241 "<?xml version ='1.0'?>"
1242 "<!-- Top level comment. -->"
1243 "<root>"
1244 " <child1 foo='bar'/>"
1245 " <!-- comment thing -->"
1246 " <child2 val='1'>Text</child2>"
1247 "</root>";
1248 XMLDocument doc;
1249 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001250 XMLTest( "Parse before deep cloning document", false, doc.Error() );
Lee Thomason7085f002017-06-01 18:09:43 -07001251 doc.Print(&printer1);
1252
1253 doc.DeepCopy(&doc2);
1254 }
1255 XMLPrinter printer2;
1256 doc2.Print(&printer2);
1257
1258 XMLTest("DeepCopy of document.", printer1.CStr(), printer2.CStr(), true);
1259 }
1260
1261
1262 {
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001263 // This shouldn't crash.
1264 XMLDocument doc;
Lee Thomason85536252016-06-04 19:10:53 -07001265 if(XML_SUCCESS != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001266 {
1267 doc.PrintError();
1268 }
1269 XMLTest( "Error in snprinf handling.", true, doc.Error() );
1270 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001271
Lee Thomason5e3803c2012-04-16 08:57:05 -07001272 {
1273 // Attribute ordering.
1274 static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
1275 XMLDocument doc;
1276 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001277 XMLTest( "Parse for attribute ordering", false, doc.Error() );
Lee Thomason5e3803c2012-04-16 08:57:05 -07001278 XMLElement* ele = doc.FirstChildElement();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001279
Lee Thomason5e3803c2012-04-16 08:57:05 -07001280 const XMLAttribute* a = ele->FirstAttribute();
1281 XMLTest( "Attribute order", "1", a->Value() );
1282 a = a->Next();
1283 XMLTest( "Attribute order", "2", a->Value() );
1284 a = a->Next();
1285 XMLTest( "Attribute order", "3", a->Value() );
1286 XMLTest( "Attribute order", "attrib3", a->Name() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001287
Lee Thomason5e3803c2012-04-16 08:57:05 -07001288 ele->DeleteAttribute( "attrib2" );
1289 a = ele->FirstAttribute();
1290 XMLTest( "Attribute order", "1", a->Value() );
1291 a = a->Next();
1292 XMLTest( "Attribute order", "3", a->Value() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001293
Lee Thomason5e3803c2012-04-16 08:57:05 -07001294 ele->DeleteAttribute( "attrib1" );
1295 ele->DeleteAttribute( "attrib3" );
1296 XMLTest( "Attribute order (empty)", false, ele->FirstAttribute() ? true : false );
1297 }
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001298
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001299 {
1300 // Make sure an attribute with a space in it succeeds.
Lee Thomason78a773d2012-07-02 10:10:19 -07001301 static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
1302 static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
1303 static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
1304 XMLDocument doc0;
1305 doc0.Parse( xml0 );
Dmitry-Me68578f42017-07-03 18:21:23 +03001306 XMLTest( "Parse attribute with space 1", false, doc0.Error() );
Lee Thomason78a773d2012-07-02 10:10:19 -07001307 XMLDocument doc1;
1308 doc1.Parse( xml1 );
Dmitry-Me68578f42017-07-03 18:21:23 +03001309 XMLTest( "Parse attribute with space 2", false, doc1.Error() );
Lee Thomason78a773d2012-07-02 10:10:19 -07001310 XMLDocument doc2;
1311 doc2.Parse( xml2 );
Dmitry-Me68578f42017-07-03 18:21:23 +03001312 XMLTest( "Parse attribute with space 3", false, doc2.Error() );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001313
Lee Thomason78a773d2012-07-02 10:10:19 -07001314 XMLElement* ele = 0;
1315 ele = doc0.FirstChildElement();
1316 XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
1317 ele = doc1.FirstChildElement();
1318 XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
1319 ele = doc2.FirstChildElement();
1320 XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001321 }
1322
1323 {
1324 // Make sure we don't go into an infinite loop.
1325 static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
1326 XMLDocument doc;
1327 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001328 XMLTest( "Parse two elements with attribute", false, doc.Error() );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001329 XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
1330 XMLElement* ele1 = ele0->NextSiblingElement();
1331 bool equal = ele0->ShallowEqual( ele1 );
1332
1333 XMLTest( "Infinite loop in shallow equal.", true, equal );
1334 }
1335
Lee Thomason5708f812012-03-28 17:46:41 -07001336 // -------- Handles ------------
1337 {
1338 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1339 XMLDocument doc;
1340 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001341 XMLTest( "Parse element with attribute and nested element round 1", false, doc.Error() );
Lee Thomason5708f812012-03-28 17:46:41 -07001342
1343 XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001344 XMLTest( "Handle, success, mutable", "sub", ele->Value() );
Lee Thomason5708f812012-03-28 17:46:41 -07001345
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001346 XMLHandle docH( doc );
1347 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001348 XMLTest( "Handle, dne, mutable", false, ele != 0 );
Lee Thomason5708f812012-03-28 17:46:41 -07001349 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001350
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001351 {
1352 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1353 XMLDocument doc;
1354 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001355 XMLTest( "Parse element with attribute and nested element round 2", false, doc.Error() );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001356 XMLConstHandle docH( doc );
1357
1358 const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement();
1359 XMLTest( "Handle, success, const", ele->Value(), "sub" );
1360
1361 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001362 XMLTest( "Handle, dne, const", false, ele != 0 );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001363 }
Lee Thomasonf68c4382012-04-28 14:37:11 -07001364 {
1365 // Default Declaration & BOM
1366 XMLDocument doc;
1367 doc.InsertEndChild( doc.NewDeclaration() );
1368 doc.SetBOM( true );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001369
Lee Thomasonf68c4382012-04-28 14:37:11 -07001370 XMLPrinter printer;
1371 doc.Print( &printer );
1372
1373 static const char* result = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001374 XMLTest( "BOM and default declaration", result, printer.CStr(), false );
1375 XMLTest( "CStrSize", 42, printer.CStrSize(), false );
Lee Thomasonf68c4382012-04-28 14:37:11 -07001376 }
Lee Thomason21be8822012-07-15 17:27:22 -07001377 {
1378 const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
1379 XMLDocument doc;
1380 doc.Parse( xml );
1381 XMLTest( "Ill formed XML", true, doc.Error() );
1382 }
1383
1384 // QueryXYZText
1385 {
1386 const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
1387 XMLDocument doc;
1388 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001389 XMLTest( "Parse points", false, doc.Error() );
Lee Thomason21be8822012-07-15 17:27:22 -07001390
1391 const XMLElement* pointElement = doc.RootElement();
1392
1393 int intValue = 0;
1394 unsigned unsignedValue = 0;
1395 float floatValue = 0;
1396 double doubleValue = 0;
1397 bool boolValue = false;
1398
1399 pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
1400 pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
1401 pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
1402 pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
1403 pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
1404
1405
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001406 XMLTest( "QueryIntText", 1, intValue, false );
1407 XMLTest( "QueryUnsignedText", (unsigned)1, unsignedValue, false );
1408 XMLTest( "QueryFloatText", 1.2f, floatValue, false );
1409 XMLTest( "QueryDoubleText", 1.2, doubleValue, false );
1410 XMLTest( "QueryBoolText", true, boolValue, false );
Lee Thomason21be8822012-07-15 17:27:22 -07001411 }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001412
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001413 {
1414 const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
1415 XMLDocument doc;
1416 doc.Parse( xml );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001417 XMLTest( "Non-alpha element lead letter parses.", false, doc.Error() );
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001418 }
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001419
1420 {
1421 const char* xml = "<element _attr1=\"foo\" :attr2=\"bar\"></element>";
1422 XMLDocument doc;
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001423 doc.Parse( xml );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001424 XMLTest("Non-alpha attribute lead character parses.", false, doc.Error());
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001425 }
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001426
1427 {
1428 const char* xml = "<3lement></3lement>";
1429 XMLDocument doc;
1430 doc.Parse( xml );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001431 XMLTest("Element names with lead digit fail to parse.", true, doc.Error());
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001432 }
Lee Thomason (grinliz)62d1c5a2012-09-08 21:44:12 -07001433
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001434 {
1435 const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
1436 XMLDocument doc;
1437 doc.Parse( xml, 10 );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001438 XMLTest( "Set length of incoming data", false, doc.Error() );
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001439 }
1440
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001441 {
1442 XMLDocument doc;
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001443 XMLTest( "Document is initially empty", true, doc.NoChildren() );
Dmitry-Me48b5df02015-04-06 18:20:25 +03001444 doc.Clear();
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001445 XMLTest( "Empty is empty after Clear()", true, doc.NoChildren() );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001446 doc.LoadFile( "resources/dream.xml" );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001447 XMLTest( "Document has something to Clear()", false, doc.NoChildren() );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001448 doc.Clear();
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001449 XMLTest( "Document Clear()'s", true, doc.NoChildren() );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001450 }
1451
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001452 // ----------- Whitespace ------------
1453 {
1454 const char* xml = "<element>"
1455 "<a> This \nis &apos; text &apos; </a>"
1456 "<b> This is &apos; text &apos; \n</b>"
1457 "<c>This is &apos; \n\n text &apos;</c>"
1458 "</element>";
1459 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1460 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001461 XMLTest( "Parse with whitespace collapsing and &apos", false, doc.Error() );
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001462
1463 const XMLElement* element = doc.FirstChildElement();
1464 for( const XMLElement* parent = element->FirstChildElement();
1465 parent;
1466 parent = parent->NextSiblingElement() )
1467 {
1468 XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
1469 }
1470 }
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001471
Lee Thomasonae9ab072012-10-24 10:17:53 -07001472#if 0
1473 {
1474 // Passes if assert doesn't fire.
1475 XMLDocument xmlDoc;
1476
1477 xmlDoc.NewDeclaration();
1478 xmlDoc.NewComment("Configuration file");
1479
1480 XMLElement *root = xmlDoc.NewElement("settings");
1481 root->SetAttribute("version", 2);
1482 }
1483#endif
1484
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001485 {
1486 const char* xml = "<element> </element>";
1487 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1488 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001489 XMLTest( "Parse with all whitespaces", false, doc.Error() );
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001490 XMLTest( "Whitespace all space", true, 0 == doc.FirstChildElement()->FirstChild() );
1491 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001492
Lee Thomason5b0a6772012-11-19 13:54:42 -08001493 {
1494 // An assert should not fire.
1495 const char* xml = "<element/>";
1496 XMLDocument doc;
1497 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001498 XMLTest( "Parse with self-closed element", false, doc.Error() );
Lee Thomason5b0a6772012-11-19 13:54:42 -08001499 XMLElement* ele = doc.NewElement( "unused" ); // This will get cleaned up with the 'doc' going out of scope.
1500 XMLTest( "Tracking unused elements", true, ele != 0, false );
1501 }
1502
Lee Thomasona6412ac2012-12-13 15:39:11 -08001503
1504 {
1505 const char* xml = "<parent><child>abc</child></parent>";
1506 XMLDocument doc;
1507 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001508 XMLTest( "Parse for printing of sub-element", false, doc.Error() );
Lee Thomasona6412ac2012-12-13 15:39:11 -08001509 XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child");
1510
1511 XMLPrinter printer;
1512 ele->Accept( &printer );
1513 XMLTest( "Printing of sub-element", "<child>abc</child>\n", printer.CStr(), false );
1514 }
1515
1516
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001517 {
1518 XMLDocument doc;
1519 XMLError error = doc.LoadFile( "resources/empty.xml" );
1520 XMLTest( "Loading an empty file", XML_ERROR_EMPTY_DOCUMENT, error );
Lee Thomason331596e2014-09-11 14:56:43 -07001521 XMLTest( "Loading an empty file and ErrorName as string", "XML_ERROR_EMPTY_DOCUMENT", doc.ErrorName() );
Lee Thomasonc7556672014-09-14 12:39:42 -07001522 doc.PrintError();
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001523 }
1524
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001525 {
1526 // BOM preservation
1527 static const char* xml_bom_preservation = "\xef\xbb\xbf<element/>\n";
1528 {
1529 XMLDocument doc;
Lee Thomason85536252016-06-04 19:10:53 -07001530 XMLTest( "BOM preservation (parse)", XML_SUCCESS, doc.Parse( xml_bom_preservation ), false );
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001531 XMLPrinter printer;
1532 doc.Print( &printer );
1533
1534 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1535 doc.SaveFile( "resources/bomtest.xml" );
1536 }
1537 {
1538 XMLDocument doc;
1539 doc.LoadFile( "resources/bomtest.xml" );
1540 XMLTest( "BOM preservation (load)", true, doc.HasBOM(), false );
1541
1542 XMLPrinter printer;
1543 doc.Print( &printer );
1544 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1545 }
1546 }
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001547
Michael Daumlinged523282013-10-23 07:47:29 +02001548 {
1549 // Insertion with Removal
1550 const char* xml = "<?xml version=\"1.0\" ?>"
1551 "<root>"
1552 "<one>"
1553 "<subtree>"
1554 "<elem>element 1</elem>text<!-- comment -->"
1555 "</subtree>"
1556 "</one>"
1557 "<two/>"
1558 "</root>";
1559 const char* xmlInsideTwo = "<?xml version=\"1.0\" ?>"
1560 "<root>"
1561 "<one/>"
1562 "<two>"
1563 "<subtree>"
1564 "<elem>element 1</elem>text<!-- comment -->"
1565 "</subtree>"
1566 "</two>"
1567 "</root>";
1568 const char* xmlAfterOne = "<?xml version=\"1.0\" ?>"
1569 "<root>"
1570 "<one/>"
1571 "<subtree>"
1572 "<elem>element 1</elem>text<!-- comment -->"
1573 "</subtree>"
1574 "<two/>"
1575 "</root>";
1576 const char* xmlAfterTwo = "<?xml version=\"1.0\" ?>"
1577 "<root>"
1578 "<one/>"
1579 "<two/>"
1580 "<subtree>"
1581 "<elem>element 1</elem>text<!-- comment -->"
1582 "</subtree>"
1583 "</root>";
1584
1585 XMLDocument doc;
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001586 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001587 XMLTest( "Insertion with removal parse round 1", false, doc.Error() );
Michael Daumlinged523282013-10-23 07:47:29 +02001588 XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1589 XMLElement* two = doc.RootElement()->FirstChildElement("two");
1590 two->InsertFirstChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001591 XMLPrinter printer1(0, true);
1592 doc.Accept(&printer1);
1593 XMLTest("Move node from within <one> to <two>", xmlInsideTwo, printer1.CStr());
Michael Daumlinged523282013-10-23 07:47:29 +02001594
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001595 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001596 XMLTest( "Insertion with removal parse round 2", false, doc.Error() );
Michael Daumlinged523282013-10-23 07:47:29 +02001597 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1598 two = doc.RootElement()->FirstChildElement("two");
1599 doc.RootElement()->InsertAfterChild(two, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001600 XMLPrinter printer2(0, true);
1601 doc.Accept(&printer2);
1602 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer2.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001603
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001604 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001605 XMLTest( "Insertion with removal parse round 3", false, doc.Error() );
Michael Daumlinged523282013-10-23 07:47:29 +02001606 XMLNode* one = doc.RootElement()->FirstChildElement("one");
1607 subtree = one->FirstChildElement("subtree");
1608 doc.RootElement()->InsertAfterChild(one, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001609 XMLPrinter printer3(0, true);
1610 doc.Accept(&printer3);
1611 XMLTest("Move node from within <one> after <one>", xmlAfterOne, printer3.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001612
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001613 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001614 XMLTest( "Insertion with removal parse round 4", false, doc.Error() );
Michael Daumlinged523282013-10-23 07:47:29 +02001615 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1616 two = doc.RootElement()->FirstChildElement("two");
1617 doc.RootElement()->InsertEndChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001618 XMLPrinter printer4(0, true);
1619 doc.Accept(&printer4);
1620 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer4.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001621 }
1622
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001623 {
1624 const char* xml = "<svg width = \"128\" height = \"128\">"
1625 " <text> </text>"
1626 "</svg>";
1627 XMLDocument doc;
1628 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001629 XMLTest( "Parse svg with text", false, doc.Error() );
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001630 doc.Print();
1631 }
1632
Lee Thomason92e521b2014-11-15 17:45:51 -08001633 {
1634 // Test that it doesn't crash.
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001635 const char* xml = "<?xml version=\"1.0\"?><root><sample><field0><1</field0><field1>2</field1></sample></root>";
1636 XMLDocument doc;
1637 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001638 XMLTest( "Parse root-sample-field0", true, doc.Error() );
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001639 doc.PrintError();
Lee Thomason92e521b2014-11-15 17:45:51 -08001640 }
1641
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001642#if 1
1643 // the question being explored is what kind of print to use:
1644 // https://github.com/leethomason/tinyxml2/issues/63
1645 {
1646 //const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9' attrC='1.0e-10' attrD='1001000000.000000' attrE='0.1234567890123456789'/>";
1647 const char* xml = "<element/>";
1648 XMLDocument doc;
1649 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001650 XMLTest( "Parse self-closed empty element", false, doc.Error() );
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001651 doc.FirstChildElement()->SetAttribute( "attrA-f64", 123456789.123456789 );
1652 doc.FirstChildElement()->SetAttribute( "attrB-f64", 1.001e9 );
1653 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e9 );
1654 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e20 );
1655 doc.FirstChildElement()->SetAttribute( "attrD-f64", 1.0e-10 );
1656 doc.FirstChildElement()->SetAttribute( "attrD-f64", 0.123456789 );
1657
1658 doc.FirstChildElement()->SetAttribute( "attrA-f32", 123456789.123456789f );
1659 doc.FirstChildElement()->SetAttribute( "attrB-f32", 1.001e9f );
1660 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e9f );
1661 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e20f );
1662 doc.FirstChildElement()->SetAttribute( "attrD-f32", 1.0e-10f );
1663 doc.FirstChildElement()->SetAttribute( "attrD-f32", 0.123456789f );
1664
1665 doc.Print();
1666
1667 /* The result of this test is platform, compiler, and library version dependent. :("
1668 XMLPrinter printer;
1669 doc.Print( &printer );
1670 XMLTest( "Float and double formatting.",
1671 "<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",
1672 printer.CStr(),
1673 true );
1674 */
1675 }
1676#endif
Lee Thomasonf07b9522014-10-30 13:25:12 -07001677
1678 {
1679 // Issue #184
1680 // If it doesn't assert, it passes. Caused by objects
1681 // getting created during parsing which are then
1682 // inaccessible in the memory pools.
Dmitry-Me5d1aec12017-06-28 14:51:17 +03001683 const char* xmlText = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>";
Lee Thomasonf07b9522014-10-30 13:25:12 -07001684 {
1685 XMLDocument doc;
Dmitry-Me5d1aec12017-06-28 14:51:17 +03001686 doc.Parse(xmlText);
Dmitry-Me68578f42017-07-03 18:21:23 +03001687 XMLTest( "Parse hex no closing tag round 1", true, doc.Error() );
Lee Thomasonf07b9522014-10-30 13:25:12 -07001688 }
1689 {
1690 XMLDocument doc;
Dmitry-Me5d1aec12017-06-28 14:51:17 +03001691 doc.Parse(xmlText);
Dmitry-Me68578f42017-07-03 18:21:23 +03001692 XMLTest( "Parse hex no closing tag round 2", true, doc.Error() );
Lee Thomasonf07b9522014-10-30 13:25:12 -07001693 doc.Clear();
1694 }
1695 }
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001696
1697 {
1698 // If this doesn't assert in DEBUG, all is well.
1699 tinyxml2::XMLDocument doc;
1700 tinyxml2::XMLElement *pRoot = doc.NewElement("Root");
1701 doc.DeleteNode(pRoot);
1702 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001703
Dmitry-Me8b67d742014-12-22 11:35:12 +03001704 {
1705 // Should not assert in DEBUG
1706 XMLPrinter printer;
1707 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001708
Dmitry-Me6f51c802015-03-14 13:25:03 +03001709 {
1710 // Issue 291. Should not crash
1711 const char* xml = "&#0</a>";
1712 XMLDocument doc;
1713 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001714 XMLTest( "Parse hex with closing tag", false, doc.Error() );
Dmitry-Me6f51c802015-03-14 13:25:03 +03001715
1716 XMLPrinter printer;
1717 doc.Print( &printer );
1718 }
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001719 {
1720 // Issue 299. Can print elements that are not linked in.
1721 // Will crash if issue not fixed.
1722 XMLDocument doc;
1723 XMLElement* newElement = doc.NewElement( "printme" );
1724 XMLPrinter printer;
1725 newElement->Accept( &printer );
Dmitry-Me5daa54c2015-04-08 17:45:07 +03001726 // Delete the node to avoid possible memory leak report in debug output
1727 doc.DeleteNode( newElement );
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001728 }
Lee Thomasonf6577832015-03-26 11:18:21 -07001729 {
Ant Mitchell189198f2015-03-24 16:20:36 +00001730 // Issue 302. Clear errors from LoadFile/SaveFile
1731 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001732 XMLTest( "Issue 302. Should be no error initially", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001733 doc.SaveFile( "./no/such/path/pretty.xml" );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001734 XMLTest( "Issue 302. Fail to save", "XML_ERROR_FILE_COULD_NOT_BE_OPENED", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001735 doc.SaveFile( "./resources/out/compact.xml", true );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001736 XMLTest( "Issue 302. Subsequent success in saving", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001737 }
Dmitry-Me6f51c802015-03-14 13:25:03 +03001738
Dmitry-Med9852a52015-03-25 10:17:49 +03001739 {
1740 // If a document fails to load then subsequent
1741 // successful loads should clear the error
1742 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001743 XMLTest( "Should be no error initially", false, doc.Error() );
Dmitry-Med9852a52015-03-25 10:17:49 +03001744 doc.LoadFile( "resources/no-such-file.xml" );
1745 XMLTest( "No such file - should fail", true, doc.Error() );
1746
1747 doc.LoadFile( "resources/dream.xml" );
1748 XMLTest( "Error should be cleared", false, doc.Error() );
1749 }
Sarat Addepalli8e85afa2015-05-19 09:07:03 +05301750
Sarat Addepalli2bb6bb52015-05-18 09:16:34 +05301751 {
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001752 // Check that declarations are allowed only at beginning of document
Lee Thomason85492022015-05-22 11:07:45 -07001753 const char* xml0 = "<?xml version=\"1.0\" ?>"
1754 " <!-- xml version=\"1.1\" -->"
1755 "<first />";
1756 const char* xml1 = "<?xml version=\"1.0\" ?>"
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001757 "<?xml-stylesheet type=\"text/xsl\" href=\"Anything.xsl\"?>"
Lee Thomason85492022015-05-22 11:07:45 -07001758 "<first />";
1759 const char* xml2 = "<first />"
1760 "<?xml version=\"1.0\" ?>";
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001761 const char* xml3 = "<first></first>"
1762 "<?xml version=\"1.0\" ?>";
1763
1764 const char* xml4 = "<first><?xml version=\"1.0\" ?></first>";
1765
Lee Thomason85492022015-05-22 11:07:45 -07001766 XMLDocument doc;
1767 doc.Parse(xml0);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001768 XMLTest("Test that the code changes do not affect normal parsing", false, doc.Error() );
Lee Thomason85492022015-05-22 11:07:45 -07001769 doc.Parse(xml1);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001770 XMLTest("Test that the second declaration is allowed", false, doc.Error() );
Lee Thomason85492022015-05-22 11:07:45 -07001771 doc.Parse(xml2);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001772 XMLTest("Test that declaration after a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001773 doc.Parse(xml3);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001774 XMLTest("Test that declaration after a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001775 doc.Parse(xml4);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001776 XMLTest("Test that declaration inside a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );
Sarat Addepalli2bb6bb52015-05-18 09:16:34 +05301777 }
Dmitry-Med9852a52015-03-25 10:17:49 +03001778
Lee Thomason85492022015-05-22 11:07:45 -07001779 {
1780 // No matter - before or after successfully parsing a text -
1781 // calling XMLDocument::Value() causes an assert in debug.
1782 const char* validXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
1783 "<first />"
1784 "<second />";
1785 XMLDocument* doc = new XMLDocument();
1786 XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
1787 doc->Parse( validXml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001788 XMLTest( "Parse to test XMLDocument::Value()", false, doc->Error());
Lee Thomason85492022015-05-22 11:07:45 -07001789 XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
1790 delete doc;
1791 }
1792
Dmitry-Mea1beddf2015-05-26 16:19:21 +03001793 {
1794 XMLDocument doc;
1795 for( int i = 0; i < XML_ERROR_COUNT; i++ ) {
kezenatorec694152016-11-26 17:21:43 +10001796 doc.SetError( (XMLError)i, 0, 0, 0 );
Dmitry-Mea1beddf2015-05-26 16:19:21 +03001797 doc.ErrorName();
1798 }
1799 }
1800
Lee Thomason816d3fa2017-06-05 14:35:55 -07001801 {
Lee Thomasonb754ddf2017-06-14 15:02:38 -07001802 // Evil memory leaks.
1803 // If an XMLElement (etc) is allocated via NewElement() (etc.)
1804 // and NOT added to the XMLDocument, what happens?
1805 //
1806 // Previously (buggy):
1807 // The memory would be free'd when the XMLDocument is
1808 // destructed. But the destructor wasn't called, so that
1809 // memory allocated by the XMLElement would not be free'd.
1810 // In practice this meant strings allocated by the XMLElement
1811 // would leak. An edge case, but annoying.
1812 // Now:
1813 // The destructor is called. But the list of unlinked nodes
1814 // has to be tracked. This has a minor performance impact
1815 // that can become significant if you have a lot. (But why
1816 // would you do that?)
1817 // The only way to see this bug is in a leak tracker. This
1818 // is compiled in by default on Windows Debug.
Lee Thomason816d3fa2017-06-05 14:35:55 -07001819 {
1820 XMLDocument doc;
1821 doc.NewElement("LEAK 1");
1822 }
1823 {
1824 XMLDocument doc;
1825 XMLElement* ele = doc.NewElement("LEAK 2");
1826 doc.DeleteNode(ele);
1827 }
1828 }
1829
Lee Thomason224ef772017-06-16 09:45:26 -07001830 {
1831 // Crashing reported via email.
1832 const char* xml =
1833 "<playlist id='playlist1'>"
Lee Thomason82bb0742017-06-16 09:48:20 -07001834 "<property name='track_name'>voice</property>"
1835 "<property name='audio_track'>1</property>"
1836 "<entry out = '604' producer = '4_playlist1' in = '0' />"
1837 "<blank length = '1' />"
1838 "<entry out = '1625' producer = '3_playlist' in = '0' />"
1839 "<blank length = '2' />"
1840 "<entry out = '946' producer = '2_playlist1' in = '0' />"
1841 "<blank length = '1' />"
1842 "<entry out = '128' producer = '1_playlist1' in = '0' />"
Lee Thomason224ef772017-06-16 09:45:26 -07001843 "</playlist>";
Lee Thomason82bb0742017-06-16 09:48:20 -07001844
Lee Thomason224ef772017-06-16 09:45:26 -07001845 // It's not a good idea to delete elements as you walk the
1846 // list. I'm not sure this technically should work; but it's
1847 // an interesting test case.
1848 XMLDocument doc;
1849 XMLError err = doc.Parse(xml);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001850 XMLTest("Crash bug parsing", XML_SUCCESS, err );
Dmitry-Meaea64c42017-06-20 18:20:15 +03001851
1852 XMLElement* playlist = doc.FirstChildElement("playlist");
Lee Thomason224ef772017-06-16 09:45:26 -07001853 XMLTest("Crash bug parsing", true, playlist != 0);
1854
1855 tinyxml2::XMLElement* entry = playlist->FirstChildElement("entry");
1856 XMLTest("Crash bug parsing", true, entry != 0);
1857 while (entry) {
1858 tinyxml2::XMLElement* todelete = entry;
1859 entry = entry->NextSiblingElement("entry");
1860 playlist->DeleteChild(todelete);
1861 };
1862 tinyxml2::XMLElement* blank = playlist->FirstChildElement("blank");
1863 while (blank) {
1864 tinyxml2::XMLElement* todelete = blank;
1865 blank = blank->NextSiblingElement("blank");
1866 playlist->DeleteChild(todelete);
1867 };
1868
1869 tinyxml2::XMLPrinter printer;
1870 playlist->Accept(&printer);
1871 printf("%s\n", printer.CStr());
1872
Lee Thomason82bb0742017-06-16 09:48:20 -07001873 // No test; it only need to not crash.
1874 // Still, wrap it up with a sanity check
1875 int nProperty = 0;
1876 for (const XMLElement* p = playlist->FirstChildElement("property"); p; p = p->NextSiblingElement("property")) {
1877 nProperty++;
1878 }
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001879 XMLTest("Crash bug parsing", 2, nProperty);
Lee Thomason224ef772017-06-16 09:45:26 -07001880 }
1881
kezenatorec694152016-11-26 17:21:43 +10001882 // ----------- Line Number Tracking --------------
1883 {
Lee Thomasone90e9012016-12-24 07:34:39 -08001884 struct TestUtil: XMLVisitor
kezenatorec694152016-11-26 17:21:43 +10001885 {
1886 void TestParseError(const char *testString, const char *docStr, XMLError expected_error, int expectedLine)
1887 {
1888 XMLDocument doc;
1889 XMLError err = doc.Parse(docStr);
1890
1891 XMLTest(testString, true, doc.Error());
1892 XMLTest(testString, expected_error, err);
1893 XMLTest(testString, expectedLine, doc.GetErrorLineNum());
1894 };
1895
1896 void TestStringLines(const char *testString, const char *docStr, const char *expectedLines)
1897 {
1898 XMLDocument doc;
1899 doc.Parse(docStr);
1900 XMLTest(testString, false, doc.Error());
1901 TestDocLines(testString, doc, expectedLines);
1902 }
1903
1904 void TestFileLines(const char *testString, const char *file_name, const char *expectedLines)
1905 {
1906 XMLDocument doc;
1907 doc.LoadFile(file_name);
1908 XMLTest(testString, false, doc.Error());
1909 TestDocLines(testString, doc, expectedLines);
1910 }
1911
1912 private:
1913 DynArray<char, 10> str;
1914
1915 void Push(char type, int lineNum)
1916 {
1917 str.Push(type);
1918 str.Push(char('0' + (lineNum / 10)));
1919 str.Push(char('0' + (lineNum % 10)));
1920 }
1921
1922 bool VisitEnter(const XMLDocument& doc)
1923 {
kezenator19d8ea82016-11-29 19:50:27 +10001924 Push('D', doc.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001925 return true;
1926 }
1927 bool VisitEnter(const XMLElement& element, const XMLAttribute* firstAttribute)
1928 {
kezenator19d8ea82016-11-29 19:50:27 +10001929 Push('E', element.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001930 for (const XMLAttribute *attr = firstAttribute; attr != 0; attr = attr->Next())
kezenator19d8ea82016-11-29 19:50:27 +10001931 Push('A', attr->GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001932 return true;
1933 }
1934 bool Visit(const XMLDeclaration& declaration)
1935 {
kezenator19d8ea82016-11-29 19:50:27 +10001936 Push('L', declaration.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001937 return true;
1938 }
1939 bool Visit(const XMLText& text)
1940 {
kezenator19d8ea82016-11-29 19:50:27 +10001941 Push('T', text.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001942 return true;
1943 }
1944 bool Visit(const XMLComment& comment)
1945 {
kezenator19d8ea82016-11-29 19:50:27 +10001946 Push('C', comment.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001947 return true;
1948 }
1949 bool Visit(const XMLUnknown& unknown)
1950 {
kezenator19d8ea82016-11-29 19:50:27 +10001951 Push('U', unknown.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001952 return true;
1953 }
1954
1955 void TestDocLines(const char *testString, XMLDocument &doc, const char *expectedLines)
1956 {
1957 str.Clear();
1958 doc.Accept(this);
1959 str.Push(0);
1960 XMLTest(testString, expectedLines, str.Mem());
1961 }
Lee Thomasone90e9012016-12-24 07:34:39 -08001962 } tester;
kezenatorec694152016-11-26 17:21:43 +10001963
Lee Thomasone90e9012016-12-24 07:34:39 -08001964 tester.TestParseError("ErrorLine-Parsing", "\n<root>\n foo \n<unclosed/>", XML_ERROR_PARSING, 2);
1965 tester.TestParseError("ErrorLine-Declaration", "<root>\n<?xml version=\"1.0\"?>", XML_ERROR_PARSING_DECLARATION, 2);
1966 tester.TestParseError("ErrorLine-Mismatch", "\n<root>\n</mismatch>", XML_ERROR_MISMATCHED_ELEMENT, 2);
1967 tester.TestParseError("ErrorLine-CData", "\n<root><![CDATA[ \n foo bar \n", XML_ERROR_PARSING_CDATA, 2);
1968 tester.TestParseError("ErrorLine-Text", "\n<root>\n foo bar \n", XML_ERROR_PARSING_TEXT, 3);
1969 tester.TestParseError("ErrorLine-Comment", "\n<root>\n<!-- >\n", XML_ERROR_PARSING_COMMENT, 3);
1970 tester.TestParseError("ErrorLine-Declaration", "\n<root>\n<? >\n", XML_ERROR_PARSING_DECLARATION, 3);
1971 tester.TestParseError("ErrorLine-Unknown", "\n<root>\n<! \n", XML_ERROR_PARSING_UNKNOWN, 3);
1972 tester.TestParseError("ErrorLine-Element", "\n<root>\n<unclosed \n", XML_ERROR_PARSING_ELEMENT, 3);
1973 tester.TestParseError("ErrorLine-Attribute", "\n<root>\n<unclosed \n att\n", XML_ERROR_PARSING_ATTRIBUTE, 4);
1974 tester.TestParseError("ErrorLine-ElementClose", "\n<root>\n<unclosed \n/unexpected", XML_ERROR_PARSING_ELEMENT, 3);
kezenatorec694152016-11-26 17:21:43 +10001975
Lee Thomasone90e9012016-12-24 07:34:39 -08001976 tester.TestStringLines(
kezenatorec694152016-11-26 17:21:43 +10001977 "LineNumbers-String",
Lee Thomasone90e9012016-12-24 07:34:39 -08001978
1979 "<?xml version=\"1.0\"?>\n" // 1 Doc, DecL
1980 "<root a='b' \n" // 2 Element Attribute
1981 "c='d'> d <blah/> \n" // 3 Attribute Text Element
1982 "newline in text \n" // 4 Text
1983 "and second <zxcv/><![CDATA[\n" // 5 Element Text
1984 " cdata test ]]><!-- comment -->\n" // 6 Comment
1985 "<! unknown></root>", // 7 Unknown
1986
kezenatorec694152016-11-26 17:21:43 +10001987 "D01L01E02A02A03T03E03T04E05T05C06U07");
1988
Lee Thomasone90e9012016-12-24 07:34:39 -08001989 tester.TestStringLines(
kezenatorec694152016-11-26 17:21:43 +10001990 "LineNumbers-CRLF",
Lee Thomasone90e9012016-12-24 07:34:39 -08001991
1992 "\r\n" // 1 Doc (arguably should be line 2)
1993 "<?xml version=\"1.0\"?>\n" // 2 DecL
1994 "<root>\r\n" // 3 Element
1995 "\n" // 4
1996 "text contining new line \n" // 5 Text
1997 " and also containing crlf \r\n" // 6
1998 "<sub><![CDATA[\n" // 7 Element Text
1999 "cdata containing new line \n" // 8
2000 " and also containing cflr\r\n" // 9
2001 "]]></sub><sub2/></root>", // 10 Element
2002
kezenatorec694152016-11-26 17:21:43 +10002003 "D01L02E03T05E07T07E10");
2004
Lee Thomasone90e9012016-12-24 07:34:39 -08002005 tester.TestFileLines(
kezenatorec694152016-11-26 17:21:43 +10002006 "LineNumbers-File",
2007 "resources/utf8test.xml",
2008 "D01L01E02E03A03A03T03E04A04A04T04E05A05A05T05E06A06A06T06E07A07A07T07E08A08A08T08E09T09E10T10");
2009 }
2010
Lee Thomason85492022015-05-22 11:07:45 -07002011 // ----------- Performance tracking --------------
Lee Thomason6f381b72012-03-02 12:59:39 -08002012 {
2013#if defined( _MSC_VER )
2014 __int64 start, end, freq;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002015 QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
Lee Thomason6f381b72012-03-02 12:59:39 -08002016#endif
2017
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002018 FILE* perfFP = fopen("resources/dream.xml", "r");
Dmitry-Med1b82822017-07-04 18:02:54 +03002019 XMLTest("Open dream.xml", true, perfFP != 0);
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002020 fseek(perfFP, 0, SEEK_END);
Armagetron3c21d6f2016-10-13 13:31:23 +02002021 long size = ftell(perfFP);
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002022 fseek(perfFP, 0, SEEK_SET);
Lee Thomason6f381b72012-03-02 12:59:39 -08002023
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002024 char* mem = new char[size + 1];
Dmitry-Med1b82822017-07-04 18:02:54 +03002025 memset(mem, 0xfe, size);
Lee Thomasone4dc7212017-07-06 17:05:01 -07002026 size_t bytesRead = fread(mem, 1, size, perfFP);
2027 XMLTest("Read dream.xml", true, uint32_t(size) >= uint32_t(bytesRead));
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002028 fclose(perfFP);
Lee Thomason6f381b72012-03-02 12:59:39 -08002029 mem[size] = 0;
2030
2031#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002032 QueryPerformanceCounter((LARGE_INTEGER*)&start);
Lee Thomason6f381b72012-03-02 12:59:39 -08002033#else
2034 clock_t cstart = clock();
2035#endif
Dmitry-Me68578f42017-07-03 18:21:23 +03002036 bool parseDreamXmlFailed = false;
Lee Thomason6f381b72012-03-02 12:59:39 -08002037 static const int COUNT = 10;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002038 for (int i = 0; i < COUNT; ++i) {
Lee Thomason6f381b72012-03-02 12:59:39 -08002039 XMLDocument doc;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002040 doc.Parse(mem);
Dmitry-Me68578f42017-07-03 18:21:23 +03002041 parseDreamXmlFailed = parseDreamXmlFailed || doc.Error();
Lee Thomason6f381b72012-03-02 12:59:39 -08002042 }
Dmitry-Me68578f42017-07-03 18:21:23 +03002043 XMLTest( "Parse dream.xml", false, parseDreamXmlFailed );
Lee Thomason6f381b72012-03-02 12:59:39 -08002044#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002045 QueryPerformanceCounter((LARGE_INTEGER*)&end);
Lee Thomason6f381b72012-03-02 12:59:39 -08002046#else
2047 clock_t cend = clock();
2048#endif
2049
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002050 delete[] mem;
Lee Thomason6f381b72012-03-02 12:59:39 -08002051
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07002052 static const char* note =
Lee Thomason6f381b72012-03-02 12:59:39 -08002053#ifdef DEBUG
2054 "DEBUG";
2055#else
2056 "Release";
2057#endif
2058
2059#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002060 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 -08002061#else
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002062 printf("\nParsing %s of dream.xml: %.3f milli-seconds\n", note, (double)(cend - cstart) / (double)COUNT);
Lee Thomason6f381b72012-03-02 12:59:39 -08002063#endif
2064 }
2065
Lee Thomason (grinliz)7ca55582012-03-07 21:54:57 -08002066 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07002067 _CrtMemCheckpoint( &endMemState );
Lee Thomason1ff38e02012-02-14 18:18:16 -08002068
2069 _CrtMemState diffMemState;
2070 _CrtMemDifference( &diffMemState, &startMemState, &endMemState );
2071 _CrtMemDumpStatistics( &diffMemState );
Dmitry-Meed785702017-06-15 13:39:53 +03002072
2073 {
2074 int leaksBeforeExit = _CrtDumpMemoryLeaks();
2075 XMLTest( "No leaks before exit?", FALSE, leaksBeforeExit );
2076 }
Lee Thomason1ff38e02012-02-14 18:18:16 -08002077 #endif
2078
2079 printf ("\nPass %d, Fail %d\n", gPass, gFail);
Lee Thomason (grinliz)db304252013-07-31 12:24:52 -07002080
2081 return gFail;
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -08002082}