blob: b6ad3b38bd1dab5977a40f0301da193ffa990b1d [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" ) );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700454 int value1 = 10;
455 int value2 = doc->FirstChildElement()->LastChildElement()->IntAttribute( "attrib", 10 );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300456 XMLError result = doc->FirstChildElement()->LastChildElement()->QueryIntAttribute( "attrib", &value1 );
457 XMLTest( "Programmatic DOM", XML_NO_ATTRIBUTE, result );
458 XMLTest( "Programmatic DOM", 10, value1 );
459 XMLTest( "Programmatic DOM", 10, value2 );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800460
461 doc->Print();
462
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700463 {
464 XMLPrinter streamer;
465 doc->Print( &streamer );
466 printf( "%s", streamer.CStr() );
467 }
468 {
469 XMLPrinter streamer( 0, true );
470 doc->Print( &streamer );
Doruk Turak1f212f32016-08-28 20:54:17 +0200471 XMLTest( "Compact mode", "<element><sub attrib=\"true\"/><sub/></element>", streamer.CStr(), false );
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700472 }
Lee Thomason (grinliz)6b8b0122012-09-08 21:21:00 -0700473 doc->SaveFile( "./resources/out/pretty.xml" );
474 doc->SaveFile( "./resources/out/compact.xml", true );
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800475 delete doc;
476 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800477 {
478 // Test: Dream
479 // XML1 : 1,187,569 bytes in 31,209 allocations
480 // XML2 : 469,073 bytes in 323 allocations
481 //int newStart = gNew;
482 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300483 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800484
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400485 doc.SaveFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800486 doc.PrintError();
487
488 XMLTest( "Dream", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400489 doc.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800490 XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() ? true : false );
491 XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
492 doc.FirstChild()->NextSibling()->ToUnknown()->Value() );
493 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400494 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800495 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
498 XMLDocument doc2;
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400499 doc2.LoadFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800500 XMLTest( "Dream-out", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400501 doc2.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800502 XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() ? true : false );
503 XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
504 doc2.FirstChild()->NextSibling()->ToUnknown()->Value() );
505 XMLTest( "Dream-out", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400506 doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800507
508 //gNewTotal = gNew - newStart;
509 }
Lee Thomason6f381b72012-03-02 12:59:39 -0800510
511
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800512 {
513 const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n"
514 "<passages count=\"006\" formatversion=\"20020620\">\n"
515 " <wrong error>\n"
516 "</passages>";
517
518 XMLDocument doc;
519 doc.Parse( error );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300520 XMLTest( "Bad XML", XML_ERROR_PARSING_ATTRIBUTE, doc.ErrorID() );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800521 }
522
523 {
524 const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
525
526 XMLDocument doc;
527 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300528 XMLTest( "Top level attributes", false, doc.Error() );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800529
530 XMLElement* ele = doc.FirstChildElement();
531
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300532 int iVal;
533 XMLError result;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800534 double dVal;
535
536 result = ele->QueryDoubleAttribute( "attr0", &dVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300537 XMLTest( "Query attribute: int as double", XML_SUCCESS, result);
538 XMLTest( "Query attribute: int as double", 1, (int)dVal );
539 XMLTest( "Query attribute: int as double", 1, (int)ele->DoubleAttribute("attr0"));
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700540
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800541 result = ele->QueryDoubleAttribute( "attr1", &dVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300542 XMLTest( "Query attribute: double as double", XML_SUCCESS, result);
543 XMLTest( "Query attribute: double as double", 2.0, dVal );
544 XMLTest( "Query attribute: double as double", 2.0, ele->DoubleAttribute("attr1") );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700545
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800546 result = ele->QueryIntAttribute( "attr1", &iVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300547 XMLTest( "Query attribute: double as int", XML_SUCCESS, result);
548 XMLTest( "Query attribute: double as int", 2, iVal );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700549
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800550 result = ele->QueryIntAttribute( "attr2", &iVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300551 XMLTest( "Query attribute: not a number", XML_WRONG_ATTRIBUTE_TYPE, result );
552 XMLTest( "Query attribute: not a number", 4.0, ele->DoubleAttribute("attr2", 4.0) );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700553
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800554 result = ele->QueryIntAttribute( "bar", &iVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300555 XMLTest( "Query attribute: does not exist", XML_NO_ATTRIBUTE, result );
556 XMLTest( "Query attribute: does not exist", true, ele->BoolAttribute("bar", true) );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800557 }
558
559 {
560 const char* str = "<doc/>";
561
562 XMLDocument doc;
563 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300564 XMLTest( "Empty top element", false, doc.Error() );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800565
566 XMLElement* ele = doc.FirstChildElement();
567
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800568 int iVal, iVal2;
569 double dVal, dVal2;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800570
571 ele->SetAttribute( "str", "strValue" );
572 ele->SetAttribute( "int", 1 );
573 ele->SetAttribute( "double", -1.0 );
574
575 const char* cStr = ele->Attribute( "str" );
576 ele->QueryIntAttribute( "int", &iVal );
577 ele->QueryDoubleAttribute( "double", &dVal );
578
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800579 ele->QueryAttribute( "int", &iVal2 );
580 ele->QueryAttribute( "double", &dVal2 );
581
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300582 XMLTest( "Attribute match test", "strValue", ele->Attribute( "str", "strValue" ) );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800583 XMLTest( "Attribute round trip. c-string.", "strValue", cStr );
584 XMLTest( "Attribute round trip. int.", 1, iVal );
585 XMLTest( "Attribute round trip. double.", -1, (int)dVal );
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800586 XMLTest( "Alternate query", true, iVal == iVal2 );
587 XMLTest( "Alternate query", true, dVal == dVal2 );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700588 XMLTest( "Alternate query", true, iVal == ele->IntAttribute("int") );
589 XMLTest( "Alternate query", true, dVal == ele->DoubleAttribute("double") );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800590 }
591
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800592 {
593 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300594 doc.LoadFile( "resources/utf8test.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800595
596 // Get the attribute "value" from the "Russian" element and check it.
597 XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700598 const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800599 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
600
601 XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) );
602
603 const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U,
604 0xd1U, 0x81U, 0xd1U, 0x81U,
605 0xd0U, 0xbaU, 0xd0U, 0xb8U,
606 0xd0U, 0xb9U, 0 };
607 const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
608
609 XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText();
610 XMLTest( "UTF-8: Browsing russian element name.",
611 russianText,
612 text->Value() );
613
614 // Now try for a round trip.
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400615 doc.SaveFile( "resources/out/utf8testout.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800616
617 // Check the round trip.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800618 int okay = 0;
619
Thomas Roßa6dd8c62012-07-26 20:42:18 +0200620 FILE* saved = fopen( "resources/out/utf8testout.xml", "r" );
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300621 FILE* verify = fopen( "resources/utf8testverify.xml", "r" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800622
623 if ( saved && verify )
624 {
625 okay = 1;
PKEuSc28ba3a2012-07-16 03:08:47 -0700626 char verifyBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800627 while ( fgets( verifyBuf, 256, verify ) )
628 {
PKEuSc28ba3a2012-07-16 03:08:47 -0700629 char savedBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800630 fgets( savedBuf, 256, saved );
631 NullLineEndings( verifyBuf );
632 NullLineEndings( savedBuf );
633
634 if ( strcmp( verifyBuf, savedBuf ) )
635 {
636 printf( "verify:%s<\n", verifyBuf );
637 printf( "saved :%s<\n", savedBuf );
638 okay = 0;
639 break;
640 }
641 }
642 }
643 if ( saved )
644 fclose( saved );
645 if ( verify )
646 fclose( verify );
647 XMLTest( "UTF-8: Verified multi-language round trip.", 1, okay );
648 }
649
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800650 // --------GetText()-----------
651 {
652 const char* str = "<foo>This is text</foo>";
653 XMLDocument doc;
654 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300655 XMLTest( "Double whitespace", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800656 const XMLElement* element = doc.RootElement();
657
658 XMLTest( "GetText() normal use.", "This is text", element->GetText() );
659
660 str = "<foo><b>This is text</b></foo>";
661 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300662 XMLTest( "Bold text simulation", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800663 element = doc.RootElement();
664
665 XMLTest( "GetText() contained element.", element->GetText() == 0, true );
666 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800667
Lee Thomasond6277762012-02-22 16:00:12 -0800668
Uli Kusterer321072e2014-01-21 01:57:38 +0100669 // --------SetText()-----------
670 {
671 const char* str = "<foo></foo>";
672 XMLDocument doc;
673 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300674 XMLTest( "Empty closed element", false, doc.Error() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100675 XMLElement* element = doc.RootElement();
676
Lee Thomason9c0678a2014-01-24 10:18:27 -0800677 element->SetText("darkness.");
678 XMLTest( "SetText() normal use (open/close).", "darkness.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100679
Lee Thomason9c0678a2014-01-24 10:18:27 -0800680 element->SetText("blue flame.");
681 XMLTest( "SetText() replace.", "blue flame.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100682
683 str = "<foo/>";
684 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300685 XMLTest( "Empty self-closed element", false, doc.Error() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100686 element = doc.RootElement();
687
Lee Thomason9c0678a2014-01-24 10:18:27 -0800688 element->SetText("The driver");
689 XMLTest( "SetText() normal use. (self-closing)", "The driver", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100690
Lee Thomason9c0678a2014-01-24 10:18:27 -0800691 element->SetText("<b>horses</b>");
692 XMLTest( "SetText() replace with tag-like text.", "<b>horses</b>", element->GetText() );
693 //doc.Print();
Uli Kusterer321072e2014-01-21 01:57:38 +0100694
695 str = "<foo><bar>Text in nested element</bar></foo>";
696 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300697 XMLTest( "Text in nested element", false, doc.Error() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100698 element = doc.RootElement();
699
Lee Thomason9c0678a2014-01-24 10:18:27 -0800700 element->SetText("wolves");
701 XMLTest( "SetText() prefix to nested non-text children.", "wolves", element->GetText() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800702
703 str = "<foo/>";
704 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300705 XMLTest( "Empty self-closed element round 2", false, doc.Error() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800706 element = doc.RootElement();
707
708 element->SetText( "str" );
709 XMLTest( "SetText types", "str", element->GetText() );
710
711 element->SetText( 1 );
712 XMLTest( "SetText types", "1", element->GetText() );
713
714 element->SetText( 1U );
715 XMLTest( "SetText types", "1", element->GetText() );
716
717 element->SetText( true );
Doruk Turak1f212f32016-08-28 20:54:17 +0200718 XMLTest( "SetText types", "true", element->GetText() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800719
720 element->SetText( 1.5f );
721 XMLTest( "SetText types", "1.5", element->GetText() );
722
723 element->SetText( 1.5 );
724 XMLTest( "SetText types", "1.5", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100725 }
726
Lee Thomason51c12712016-06-04 20:18:49 -0700727 // ---------- Attributes ---------
728 {
729 static const int64_t BIG = -123456789012345678;
730 XMLDocument doc;
731 XMLElement* element = doc.NewElement("element");
732 doc.InsertFirstChild(element);
733
734 {
735 element->SetAttribute("attrib", int(-100));
736 int v = 0;
737 element->QueryIntAttribute("attrib", &v);
738 XMLTest("Attribute: int", -100, v, true);
739 element->QueryAttribute("attrib", &v);
740 XMLTest("Attribute: int", -100, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700741 XMLTest("Attribute: int", -100, element->IntAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700742 }
743 {
744 element->SetAttribute("attrib", unsigned(100));
745 unsigned v = 0;
746 element->QueryUnsignedAttribute("attrib", &v);
747 XMLTest("Attribute: unsigned", unsigned(100), v, true);
748 element->QueryAttribute("attrib", &v);
749 XMLTest("Attribute: unsigned", unsigned(100), v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700750 XMLTest("Attribute: unsigned", unsigned(100), element->UnsignedAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700751 }
752 {
753 element->SetAttribute("attrib", BIG);
754 int64_t v = 0;
755 element->QueryInt64Attribute("attrib", &v);
756 XMLTest("Attribute: int64_t", BIG, v, true);
757 element->QueryAttribute("attrib", &v);
758 XMLTest("Attribute: int64_t", BIG, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700759 XMLTest("Attribute: int64_t", BIG, element->Int64Attribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700760 }
761 {
762 element->SetAttribute("attrib", true);
763 bool v = false;
764 element->QueryBoolAttribute("attrib", &v);
765 XMLTest("Attribute: bool", true, v, true);
766 element->QueryAttribute("attrib", &v);
767 XMLTest("Attribute: bool", true, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700768 XMLTest("Attribute: bool", true, element->BoolAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700769 }
770 {
Lee Thomasonce667c92016-12-26 16:45:30 -0800771 element->SetAttribute("attrib", true);
772 const char* result = element->Attribute("attrib");
773 XMLTest("Bool true is 'true'", "true", result);
774
Lee Thomasonc5c99c22016-12-29 11:19:17 -0800775 XMLUtil::SetBoolSerialization("1", "0");
Lee Thomasonce667c92016-12-26 16:45:30 -0800776 element->SetAttribute("attrib", true);
777 result = element->Attribute("attrib");
778 XMLTest("Bool true is '1'", "1", result);
779
Lee Thomasonc5c99c22016-12-29 11:19:17 -0800780 XMLUtil::SetBoolSerialization(0, 0);
Lee Thomasonce667c92016-12-26 16:45:30 -0800781 }
782 {
Lee Thomason51c12712016-06-04 20:18:49 -0700783 element->SetAttribute("attrib", 100.0);
784 double v = 0;
785 element->QueryDoubleAttribute("attrib", &v);
786 XMLTest("Attribute: double", 100.0, v, true);
787 element->QueryAttribute("attrib", &v);
788 XMLTest("Attribute: double", 100.0, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700789 XMLTest("Attribute: double", 100.0, element->DoubleAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700790 }
791 {
792 element->SetAttribute("attrib", 100.0f);
793 float v = 0;
794 element->QueryFloatAttribute("attrib", &v);
795 XMLTest("Attribute: float", 100.0f, v, true);
796 element->QueryAttribute("attrib", &v);
797 XMLTest("Attribute: float", 100.0f, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700798 XMLTest("Attribute: float", 100.0f, element->FloatAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700799 }
800 {
801 element->SetText(BIG);
802 int64_t v = 0;
803 element->QueryInt64Text(&v);
804 XMLTest("Element: int64_t", BIG, v, true);
805 }
806 }
807
808 // ---------- XMLPrinter stream mode ------
809 {
810 {
811 FILE* printerfp = fopen("resources/printer.xml", "w");
812 XMLPrinter printer(printerfp);
813 printer.OpenElement("foo");
814 printer.PushAttribute("attrib-text", "text");
815 printer.PushAttribute("attrib-int", int(1));
816 printer.PushAttribute("attrib-unsigned", unsigned(2));
817 printer.PushAttribute("attrib-int64", int64_t(3));
818 printer.PushAttribute("attrib-bool", true);
819 printer.PushAttribute("attrib-double", 4.0);
820 printer.CloseElement();
821 fclose(printerfp);
822 }
823 {
824 XMLDocument doc;
825 doc.LoadFile("resources/printer.xml");
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300826 XMLTest("XMLPrinter Stream mode: load", XML_SUCCESS, doc.ErrorID(), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700827
828 const XMLDocument& cdoc = doc;
829
830 const XMLAttribute* attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-text");
831 XMLTest("attrib-text", "text", attrib->Value(), true);
832 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int");
833 XMLTest("attrib-int", int(1), attrib->IntValue(), true);
834 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-unsigned");
835 XMLTest("attrib-unsigned", unsigned(2), attrib->UnsignedValue(), true);
836 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int64");
837 XMLTest("attrib-int64", int64_t(3), attrib->Int64Value(), true);
838 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-bool");
839 XMLTest("attrib-bool", true, attrib->BoolValue(), true);
840 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-double");
841 XMLTest("attrib-double", 4.0, attrib->DoubleValue(), true);
842 }
843
844 }
845
Uli Kusterer321072e2014-01-21 01:57:38 +0100846
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800847 // ---------- CDATA ---------------
848 {
849 const char* str = "<xmlElement>"
850 "<![CDATA["
851 "I am > the rules!\n"
852 "...since I make symbolic puns"
853 "]]>"
854 "</xmlElement>";
855 XMLDocument doc;
856 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300857 XMLTest( "CDATA symbolic puns round 1", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800858 doc.Print();
Lee Thomasond6277762012-02-22 16:00:12 -0800859
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300860 XMLTest( "CDATA parse.", "I am > the rules!\n...since I make symbolic puns",
861 doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomasond6277762012-02-22 16:00:12 -0800862 false );
863 }
864
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800865 // ----------- CDATA -------------
866 {
867 const char* str = "<xmlElement>"
868 "<![CDATA["
869 "<b>I am > the rules!</b>\n"
870 "...since I make symbolic puns"
871 "]]>"
872 "</xmlElement>";
873 XMLDocument doc;
874 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300875 XMLTest( "CDATA symbolic puns round 2", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800876 doc.Print();
877
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300878 XMLTest( "CDATA parse. [ tixml1:1480107 ]",
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800879 "<b>I am > the rules!</b>\n...since I make symbolic puns",
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300880 doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800881 false );
882 }
883
884 // InsertAfterChild causes crash.
885 {
886 // InsertBeforeChild and InsertAfterChild causes crash.
887 XMLDocument doc;
888 XMLElement* parent = doc.NewElement( "Parent" );
889 doc.InsertFirstChild( parent );
890
891 XMLElement* childText0 = doc.NewElement( "childText0" );
892 XMLElement* childText1 = doc.NewElement( "childText1" );
893
894 XMLNode* childNode0 = parent->InsertEndChild( childText0 );
895 XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 );
896
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300897 XMLTest( "Test InsertAfterChild on empty node. ", true, ( childNode1 == parent->LastChild() ) );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800898 }
Lee Thomasond6277762012-02-22 16:00:12 -0800899
900 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800901 // Entities not being written correctly.
902 // From Lynn Allen
Lee Thomasond6277762012-02-22 16:00:12 -0800903
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800904 const char* passages =
905 "<?xml version=\"1.0\" standalone=\"no\" ?>"
906 "<passages count=\"006\" formatversion=\"20020620\">"
907 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
908 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
909 "</passages>";
Lee Thomasond6277762012-02-22 16:00:12 -0800910
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800911 XMLDocument doc;
912 doc.Parse( passages );
Dmitry-Me68578f42017-07-03 18:21:23 +0300913 XMLTest( "Entity transformation parse round 1", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800914 XMLElement* psg = doc.RootElement()->FirstChildElement();
915 const char* context = psg->Attribute( "context" );
916 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 -0800917
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800918 XMLTest( "Entity transformation: read. ", expected, context, true );
Lee Thomasond6277762012-02-22 16:00:12 -0800919
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400920 FILE* textfile = fopen( "resources/out/textfile.txt", "w" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800921 if ( textfile )
922 {
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800923 XMLPrinter streamer( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800924 psg->Accept( &streamer );
925 fclose( textfile );
926 }
Thomas Roß0922b732012-09-23 16:31:22 +0200927
928 textfile = fopen( "resources/out/textfile.txt", "r" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800929 TIXMLASSERT( textfile );
930 if ( textfile )
931 {
932 char buf[ 1024 ];
933 fgets( buf, 1024, textfile );
934 XMLTest( "Entity transformation: write. ",
935 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
936 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.\"/>\n",
937 buf, false );
PKEuSc28ba3a2012-07-16 03:08:47 -0700938 fclose( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800939 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800940 }
941
942 {
Lee Thomason6f381b72012-03-02 12:59:39 -0800943 // Suppress entities.
944 const char* passages =
945 "<?xml version=\"1.0\" standalone=\"no\" ?>"
946 "<passages count=\"006\" formatversion=\"20020620\">"
947 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
948 "</passages>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700949
Lee Thomason6f381b72012-03-02 12:59:39 -0800950 XMLDocument doc( false );
951 doc.Parse( passages );
Dmitry-Me68578f42017-07-03 18:21:23 +0300952 XMLTest( "Entity transformation parse round 2", false, doc.Error() );
Lee Thomason6f381b72012-03-02 12:59:39 -0800953
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300954 XMLTest( "No entity parsing.",
955 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.",
956 doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ) );
957 XMLTest( "No entity parsing.", "Crazy &ttk;",
958 doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value() );
Lee Thomason6f381b72012-03-02 12:59:39 -0800959 doc.Print();
960 }
961
962 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400963 const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800964
965 XMLDocument doc;
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400966 doc.Parse( test );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300967 XMLTest( "dot in names", false, doc.Error() );
968 XMLTest( "dot in names", "a.elem", doc.FirstChildElement()->Name() );
969 XMLTest( "dot in names", "2.0", doc.FirstChildElement()->Attribute( "xmi.version" ) );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800970 }
971
972 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400973 const char* test = "<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800974
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400975 XMLDocument doc;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800976 doc.Parse( test );
Dmitry-Me68578f42017-07-03 18:21:23 +0300977 XMLTest( "fin thickness", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800978
979 XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
980 XMLTest( "Entity with one digit.",
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300981 "1.1 Start easy ignore fin thickness\n", text->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800982 false );
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400983 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800984
985 {
986 // DOCTYPE not preserved (950171)
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700987 //
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800988 const char* doctype =
989 "<?xml version=\"1.0\" ?>"
990 "<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
991 "<!ELEMENT title (#PCDATA)>"
992 "<!ELEMENT books (title,authors)>"
993 "<element />";
994
995 XMLDocument doc;
996 doc.Parse( doctype );
Dmitry-Me68578f42017-07-03 18:21:23 +0300997 XMLTest( "PLAY SYSTEM parse", false, doc.Error() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400998 doc.SaveFile( "resources/out/test7.xml" );
Dmitry-Me68578f42017-07-03 18:21:23 +0300999 XMLTest( "PLAY SYSTEM save", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001000 doc.DeleteChild( doc.RootElement() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +04001001 doc.LoadFile( "resources/out/test7.xml" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001002 XMLTest( "PLAY SYSTEM load", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001003 doc.Print();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001004
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001005 const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown();
1006 XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() );
1007
1008 }
1009
1010 {
1011 // Comments do not stream out correctly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001012 const char* doctype =
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001013 "<!-- Somewhat<evil> -->";
1014 XMLDocument doc;
1015 doc.Parse( doctype );
Dmitry-Me68578f42017-07-03 18:21:23 +03001016 XMLTest( "Comment somewhat evil", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001017
1018 XMLComment* comment = doc.FirstChild()->ToComment();
1019
1020 XMLTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
1021 }
1022 {
1023 // Double attributes
1024 const char* doctype = "<element attr='red' attr='blue' />";
1025
1026 XMLDocument doc;
1027 doc.Parse( doctype );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001028
Lee Thomason2fa81722012-11-09 12:37:46 -08001029 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 -08001030 doc.PrintError();
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001031 }
1032
1033 {
1034 // Embedded null in stream.
1035 const char* doctype = "<element att\0r='red' attr='blue' />";
1036
1037 XMLDocument doc;
1038 doc.Parse( doctype );
1039 XMLTest( "Embedded null throws error.", true, doc.Error() );
1040 }
1041
1042 {
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -07001043 // Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
Dmitry-Me588bb8d2014-12-25 18:59:18 +03001044 const char* str = "";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001045 XMLDocument doc;
1046 doc.Parse( str );
Lee Thomason2fa81722012-11-09 12:37:46 -08001047 XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001048 }
1049
1050 {
Dmitry-Me588bb8d2014-12-25 18:59:18 +03001051 // Documents with all whitespaces should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
1052 const char* str = " ";
1053 XMLDocument doc;
1054 doc.Parse( str );
1055 XMLTest( "All whitespaces document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
1056 }
1057
1058 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001059 // Low entities
1060 XMLDocument doc;
1061 doc.Parse( "<test>&#x0e;</test>" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001062 XMLTest( "Hex values", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001063 const char result[] = { 0x0e, 0 };
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001064 XMLTest( "Low entities.", result, doc.FirstChildElement()->GetText() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001065 doc.Print();
1066 }
1067
1068 {
1069 // Attribute values with trailing quotes not handled correctly
1070 XMLDocument doc;
1071 doc.Parse( "<foo attribute=bar\" />" );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001072 XMLTest( "Throw error with bad end quotes.", true, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001073 }
1074
1075 {
1076 // [ 1663758 ] Failure to report error on bad XML
1077 XMLDocument xml;
1078 xml.Parse("<x>");
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001079 XMLTest("Missing end tag at end of input", true, xml.Error());
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001080 xml.Parse("<x> ");
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001081 XMLTest("Missing end tag with trailing whitespace", true, xml.Error());
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001082 xml.Parse("<x></y>");
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001083 XMLTest("Mismatched tags", XML_ERROR_MISMATCHED_ELEMENT, xml.ErrorID() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001084 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001085
1086
1087 {
1088 // [ 1475201 ] TinyXML parses entities in comments
1089 XMLDocument xml;
1090 xml.Parse("<!-- declarations for <head> & <body> -->"
1091 "<!-- far &amp; away -->" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001092 XMLTest( "Declarations for head and body", false, xml.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001093
1094 XMLNode* e0 = xml.FirstChild();
1095 XMLNode* e1 = e0->NextSibling();
1096 XMLComment* c0 = e0->ToComment();
1097 XMLComment* c1 = e1->ToComment();
1098
1099 XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
1100 XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
1101 }
1102
1103 {
1104 XMLDocument xml;
1105 xml.Parse( "<Parent>"
1106 "<child1 att=''/>"
1107 "<!-- With this comment, child2 will not be parsed! -->"
1108 "<child2 att=''/>"
1109 "</Parent>" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001110 XMLTest( "Comments iteration", false, xml.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001111 xml.Print();
1112
1113 int count = 0;
1114
1115 for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
1116 ele;
1117 ele = ele->NextSibling() )
1118 {
1119 ++count;
1120 }
1121
1122 XMLTest( "Comments iterate correctly.", 3, count );
1123 }
1124
1125 {
1126 // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
1127 unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
1128 buf[60] = 239;
1129 buf[61] = 0;
1130
1131 XMLDocument doc;
1132 doc.Parse( (const char*)buf);
Dmitry-Me68578f42017-07-03 18:21:23 +03001133 XMLTest( "Broken CDATA", true, doc.Error() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001134 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001135
1136
1137 {
1138 // bug 1827248 Error while parsing a little bit malformed file
1139 // Actually not malformed - should work.
1140 XMLDocument xml;
1141 xml.Parse( "<attributelist> </attributelist >" );
1142 XMLTest( "Handle end tag whitespace", false, xml.Error() );
1143 }
1144
1145 {
1146 // This one must not result in an infinite loop
1147 XMLDocument xml;
1148 xml.Parse( "<infinite>loop" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001149 XMLTest( "No closing element", true, xml.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001150 XMLTest( "Infinite loop test.", true, true );
1151 }
1152#endif
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001153 {
1154 const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
1155 XMLDocument doc;
1156 doc.Parse( pub );
Dmitry-Me68578f42017-07-03 18:21:23 +03001157 XMLTest( "Trailing DOCTYPE", false, doc.Error() );
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001158
1159 XMLDocument clone;
1160 for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
1161 XMLNode* copy = node->ShallowClone( &clone );
1162 clone.InsertEndChild( copy );
1163 }
1164
1165 clone.Print();
1166
1167 int count=0;
1168 const XMLNode* a=clone.FirstChild();
1169 const XMLNode* b=doc.FirstChild();
1170 for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
1171 ++count;
1172 XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
1173 }
1174 XMLTest( "Clone and Equal", 4, count );
1175 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001176
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001177 {
Lee Thomason7085f002017-06-01 18:09:43 -07001178 // Deep Cloning of root element.
1179 XMLDocument doc2;
1180 XMLPrinter printer1;
1181 {
1182 // Make sure doc1 is deleted before we test doc2
1183 const char* xml =
1184 "<root>"
1185 " <child1 foo='bar'/>"
1186 " <!-- comment thing -->"
1187 " <child2 val='1'>Text</child2>"
1188 "</root>";
1189 XMLDocument doc;
1190 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001191 XMLTest( "Parse before deep cloning root element", false, doc.Error() );
Lee Thomason7085f002017-06-01 18:09:43 -07001192
1193 doc.Print(&printer1);
1194 XMLNode* root = doc.RootElement()->DeepClone(&doc2);
1195 doc2.InsertFirstChild(root);
1196 }
1197 XMLPrinter printer2;
1198 doc2.Print(&printer2);
1199
1200 XMLTest("Deep clone of element.", printer1.CStr(), printer2.CStr(), true);
1201 }
1202
1203 {
1204 // Deep Cloning of sub element.
1205 XMLDocument doc2;
1206 XMLPrinter printer1;
1207 {
1208 // Make sure doc1 is deleted before we test doc2
1209 const char* xml =
1210 "<?xml version ='1.0'?>"
1211 "<root>"
1212 " <child1 foo='bar'/>"
1213 " <!-- comment thing -->"
1214 " <child2 val='1'>Text</child2>"
1215 "</root>";
1216 XMLDocument doc;
1217 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001218 XMLTest( "Parse before deep cloning sub element", false, doc.Error() );
Lee Thomason7085f002017-06-01 18:09:43 -07001219
1220 const XMLElement* subElement = doc.FirstChildElement("root")->FirstChildElement("child2");
1221 subElement->Accept(&printer1);
1222
1223 XMLNode* clonedSubElement = subElement->DeepClone(&doc2);
1224 doc2.InsertFirstChild(clonedSubElement);
1225 }
1226 XMLPrinter printer2;
1227 doc2.Print(&printer2);
1228
1229 XMLTest("Deep clone of sub-element.", printer1.CStr(), printer2.CStr(), true);
1230 }
1231
1232 {
1233 // Deep cloning of document.
1234 XMLDocument doc2;
1235 XMLPrinter printer1;
1236 {
1237 // Make sure doc1 is deleted before we test doc2
1238 const char* xml =
1239 "<?xml version ='1.0'?>"
1240 "<!-- Top level comment. -->"
1241 "<root>"
1242 " <child1 foo='bar'/>"
1243 " <!-- comment thing -->"
1244 " <child2 val='1'>Text</child2>"
1245 "</root>";
1246 XMLDocument doc;
1247 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001248 XMLTest( "Parse before deep cloning document", false, doc.Error() );
Lee Thomason7085f002017-06-01 18:09:43 -07001249 doc.Print(&printer1);
1250
1251 doc.DeepCopy(&doc2);
1252 }
1253 XMLPrinter printer2;
1254 doc2.Print(&printer2);
1255
1256 XMLTest("DeepCopy of document.", printer1.CStr(), printer2.CStr(), true);
1257 }
1258
1259
1260 {
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001261 // This shouldn't crash.
1262 XMLDocument doc;
Lee Thomason85536252016-06-04 19:10:53 -07001263 if(XML_SUCCESS != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001264 {
1265 doc.PrintError();
1266 }
1267 XMLTest( "Error in snprinf handling.", true, doc.Error() );
1268 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001269
Lee Thomason5e3803c2012-04-16 08:57:05 -07001270 {
1271 // Attribute ordering.
1272 static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
1273 XMLDocument doc;
1274 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001275 XMLTest( "Parse for attribute ordering", false, doc.Error() );
Lee Thomason5e3803c2012-04-16 08:57:05 -07001276 XMLElement* ele = doc.FirstChildElement();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001277
Lee Thomason5e3803c2012-04-16 08:57:05 -07001278 const XMLAttribute* a = ele->FirstAttribute();
1279 XMLTest( "Attribute order", "1", a->Value() );
1280 a = a->Next();
1281 XMLTest( "Attribute order", "2", a->Value() );
1282 a = a->Next();
1283 XMLTest( "Attribute order", "3", a->Value() );
1284 XMLTest( "Attribute order", "attrib3", a->Name() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001285
Lee Thomason5e3803c2012-04-16 08:57:05 -07001286 ele->DeleteAttribute( "attrib2" );
1287 a = ele->FirstAttribute();
1288 XMLTest( "Attribute order", "1", a->Value() );
1289 a = a->Next();
1290 XMLTest( "Attribute order", "3", a->Value() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001291
Lee Thomason5e3803c2012-04-16 08:57:05 -07001292 ele->DeleteAttribute( "attrib1" );
1293 ele->DeleteAttribute( "attrib3" );
1294 XMLTest( "Attribute order (empty)", false, ele->FirstAttribute() ? true : false );
1295 }
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001296
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001297 {
1298 // Make sure an attribute with a space in it succeeds.
Lee Thomason78a773d2012-07-02 10:10:19 -07001299 static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
1300 static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
1301 static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
1302 XMLDocument doc0;
1303 doc0.Parse( xml0 );
Dmitry-Me68578f42017-07-03 18:21:23 +03001304 XMLTest( "Parse attribute with space 1", false, doc0.Error() );
Lee Thomason78a773d2012-07-02 10:10:19 -07001305 XMLDocument doc1;
1306 doc1.Parse( xml1 );
Dmitry-Me68578f42017-07-03 18:21:23 +03001307 XMLTest( "Parse attribute with space 2", false, doc1.Error() );
Lee Thomason78a773d2012-07-02 10:10:19 -07001308 XMLDocument doc2;
1309 doc2.Parse( xml2 );
Dmitry-Me68578f42017-07-03 18:21:23 +03001310 XMLTest( "Parse attribute with space 3", false, doc2.Error() );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001311
Lee Thomason78a773d2012-07-02 10:10:19 -07001312 XMLElement* ele = 0;
1313 ele = doc0.FirstChildElement();
1314 XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
1315 ele = doc1.FirstChildElement();
1316 XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
1317 ele = doc2.FirstChildElement();
1318 XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001319 }
1320
1321 {
1322 // Make sure we don't go into an infinite loop.
1323 static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
1324 XMLDocument doc;
1325 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001326 XMLTest( "Parse two elements with attribute", false, doc.Error() );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001327 XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
1328 XMLElement* ele1 = ele0->NextSiblingElement();
1329 bool equal = ele0->ShallowEqual( ele1 );
1330
1331 XMLTest( "Infinite loop in shallow equal.", true, equal );
1332 }
1333
Lee Thomason5708f812012-03-28 17:46:41 -07001334 // -------- Handles ------------
1335 {
1336 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1337 XMLDocument doc;
1338 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001339 XMLTest( "Parse element with attribute and nested element round 1", false, doc.Error() );
Lee Thomason5708f812012-03-28 17:46:41 -07001340
1341 XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001342 XMLTest( "Handle, success, mutable", "sub", ele->Value() );
Lee Thomason5708f812012-03-28 17:46:41 -07001343
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001344 XMLHandle docH( doc );
1345 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001346 XMLTest( "Handle, dne, mutable", false, ele != 0 );
Lee Thomason5708f812012-03-28 17:46:41 -07001347 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001348
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001349 {
1350 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1351 XMLDocument doc;
1352 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001353 XMLTest( "Parse element with attribute and nested element round 2", false, doc.Error() );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001354 XMLConstHandle docH( doc );
1355
1356 const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement();
1357 XMLTest( "Handle, success, const", ele->Value(), "sub" );
1358
1359 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001360 XMLTest( "Handle, dne, const", false, ele != 0 );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001361 }
Lee Thomasonf68c4382012-04-28 14:37:11 -07001362 {
1363 // Default Declaration & BOM
1364 XMLDocument doc;
1365 doc.InsertEndChild( doc.NewDeclaration() );
1366 doc.SetBOM( true );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001367
Lee Thomasonf68c4382012-04-28 14:37:11 -07001368 XMLPrinter printer;
1369 doc.Print( &printer );
1370
1371 static const char* result = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001372 XMLTest( "BOM and default declaration", result, printer.CStr(), false );
1373 XMLTest( "CStrSize", 42, printer.CStrSize(), false );
Lee Thomasonf68c4382012-04-28 14:37:11 -07001374 }
Lee Thomason21be8822012-07-15 17:27:22 -07001375 {
1376 const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
1377 XMLDocument doc;
1378 doc.Parse( xml );
1379 XMLTest( "Ill formed XML", true, doc.Error() );
1380 }
1381
1382 // QueryXYZText
1383 {
1384 const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
1385 XMLDocument doc;
1386 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001387 XMLTest( "Parse points", false, doc.Error() );
Lee Thomason21be8822012-07-15 17:27:22 -07001388
1389 const XMLElement* pointElement = doc.RootElement();
1390
1391 int intValue = 0;
1392 unsigned unsignedValue = 0;
1393 float floatValue = 0;
1394 double doubleValue = 0;
1395 bool boolValue = false;
1396
1397 pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
1398 pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
1399 pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
1400 pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
1401 pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
1402
1403
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001404 XMLTest( "QueryIntText", 1, intValue, false );
1405 XMLTest( "QueryUnsignedText", (unsigned)1, unsignedValue, false );
1406 XMLTest( "QueryFloatText", 1.2f, floatValue, false );
1407 XMLTest( "QueryDoubleText", 1.2, doubleValue, false );
1408 XMLTest( "QueryBoolText", true, boolValue, false );
Lee Thomason21be8822012-07-15 17:27:22 -07001409 }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001410
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001411 {
1412 const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
1413 XMLDocument doc;
1414 doc.Parse( xml );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001415 XMLTest( "Non-alpha element lead letter parses.", false, doc.Error() );
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001416 }
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001417
1418 {
1419 const char* xml = "<element _attr1=\"foo\" :attr2=\"bar\"></element>";
1420 XMLDocument doc;
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001421 doc.Parse( xml );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001422 XMLTest("Non-alpha attribute lead character parses.", false, doc.Error());
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001423 }
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001424
1425 {
1426 const char* xml = "<3lement></3lement>";
1427 XMLDocument doc;
1428 doc.Parse( xml );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001429 XMLTest("Element names with lead digit fail to parse.", true, doc.Error());
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001430 }
Lee Thomason (grinliz)62d1c5a2012-09-08 21:44:12 -07001431
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001432 {
1433 const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
1434 XMLDocument doc;
1435 doc.Parse( xml, 10 );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001436 XMLTest( "Set length of incoming data", false, doc.Error() );
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001437 }
1438
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001439 {
1440 XMLDocument doc;
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001441 XMLTest( "Document is initially empty", true, doc.NoChildren() );
Dmitry-Me48b5df02015-04-06 18:20:25 +03001442 doc.Clear();
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001443 XMLTest( "Empty is empty after Clear()", true, doc.NoChildren() );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001444 doc.LoadFile( "resources/dream.xml" );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001445 XMLTest( "Document has something to Clear()", false, doc.NoChildren() );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001446 doc.Clear();
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001447 XMLTest( "Document Clear()'s", true, doc.NoChildren() );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001448 }
1449
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001450 // ----------- Whitespace ------------
1451 {
1452 const char* xml = "<element>"
1453 "<a> This \nis &apos; text &apos; </a>"
1454 "<b> This is &apos; text &apos; \n</b>"
1455 "<c>This is &apos; \n\n text &apos;</c>"
1456 "</element>";
1457 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1458 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001459 XMLTest( "Parse with whitespace collapsing and &apos", false, doc.Error() );
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001460
1461 const XMLElement* element = doc.FirstChildElement();
1462 for( const XMLElement* parent = element->FirstChildElement();
1463 parent;
1464 parent = parent->NextSiblingElement() )
1465 {
1466 XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
1467 }
1468 }
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001469
Lee Thomasonae9ab072012-10-24 10:17:53 -07001470#if 0
1471 {
1472 // Passes if assert doesn't fire.
1473 XMLDocument xmlDoc;
1474
1475 xmlDoc.NewDeclaration();
1476 xmlDoc.NewComment("Configuration file");
1477
1478 XMLElement *root = xmlDoc.NewElement("settings");
1479 root->SetAttribute("version", 2);
1480 }
1481#endif
1482
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001483 {
1484 const char* xml = "<element> </element>";
1485 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1486 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001487 XMLTest( "Parse with all whitespaces", false, doc.Error() );
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001488 XMLTest( "Whitespace all space", true, 0 == doc.FirstChildElement()->FirstChild() );
1489 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001490
Lee Thomason5b0a6772012-11-19 13:54:42 -08001491 {
1492 // An assert should not fire.
1493 const char* xml = "<element/>";
1494 XMLDocument doc;
1495 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001496 XMLTest( "Parse with self-closed element", false, doc.Error() );
Lee Thomason5b0a6772012-11-19 13:54:42 -08001497 XMLElement* ele = doc.NewElement( "unused" ); // This will get cleaned up with the 'doc' going out of scope.
1498 XMLTest( "Tracking unused elements", true, ele != 0, false );
1499 }
1500
Lee Thomasona6412ac2012-12-13 15:39:11 -08001501
1502 {
1503 const char* xml = "<parent><child>abc</child></parent>";
1504 XMLDocument doc;
1505 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001506 XMLTest( "Parse for printing of sub-element", false, doc.Error() );
Lee Thomasona6412ac2012-12-13 15:39:11 -08001507 XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child");
1508
1509 XMLPrinter printer;
1510 ele->Accept( &printer );
1511 XMLTest( "Printing of sub-element", "<child>abc</child>\n", printer.CStr(), false );
1512 }
1513
1514
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001515 {
1516 XMLDocument doc;
1517 XMLError error = doc.LoadFile( "resources/empty.xml" );
1518 XMLTest( "Loading an empty file", XML_ERROR_EMPTY_DOCUMENT, error );
Lee Thomason331596e2014-09-11 14:56:43 -07001519 XMLTest( "Loading an empty file and ErrorName as string", "XML_ERROR_EMPTY_DOCUMENT", doc.ErrorName() );
Lee Thomasonc7556672014-09-14 12:39:42 -07001520 doc.PrintError();
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001521 }
1522
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001523 {
1524 // BOM preservation
1525 static const char* xml_bom_preservation = "\xef\xbb\xbf<element/>\n";
1526 {
1527 XMLDocument doc;
Lee Thomason85536252016-06-04 19:10:53 -07001528 XMLTest( "BOM preservation (parse)", XML_SUCCESS, doc.Parse( xml_bom_preservation ), false );
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001529 XMLPrinter printer;
1530 doc.Print( &printer );
1531
1532 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1533 doc.SaveFile( "resources/bomtest.xml" );
1534 }
1535 {
1536 XMLDocument doc;
1537 doc.LoadFile( "resources/bomtest.xml" );
1538 XMLTest( "BOM preservation (load)", true, doc.HasBOM(), false );
1539
1540 XMLPrinter printer;
1541 doc.Print( &printer );
1542 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1543 }
1544 }
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001545
Michael Daumlinged523282013-10-23 07:47:29 +02001546 {
1547 // Insertion with Removal
1548 const char* xml = "<?xml version=\"1.0\" ?>"
1549 "<root>"
1550 "<one>"
1551 "<subtree>"
1552 "<elem>element 1</elem>text<!-- comment -->"
1553 "</subtree>"
1554 "</one>"
1555 "<two/>"
1556 "</root>";
1557 const char* xmlInsideTwo = "<?xml version=\"1.0\" ?>"
1558 "<root>"
1559 "<one/>"
1560 "<two>"
1561 "<subtree>"
1562 "<elem>element 1</elem>text<!-- comment -->"
1563 "</subtree>"
1564 "</two>"
1565 "</root>";
1566 const char* xmlAfterOne = "<?xml version=\"1.0\" ?>"
1567 "<root>"
1568 "<one/>"
1569 "<subtree>"
1570 "<elem>element 1</elem>text<!-- comment -->"
1571 "</subtree>"
1572 "<two/>"
1573 "</root>";
1574 const char* xmlAfterTwo = "<?xml version=\"1.0\" ?>"
1575 "<root>"
1576 "<one/>"
1577 "<two/>"
1578 "<subtree>"
1579 "<elem>element 1</elem>text<!-- comment -->"
1580 "</subtree>"
1581 "</root>";
1582
1583 XMLDocument doc;
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001584 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001585 XMLTest( "Insertion with removal parse round 1", false, doc.Error() );
Michael Daumlinged523282013-10-23 07:47:29 +02001586 XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1587 XMLElement* two = doc.RootElement()->FirstChildElement("two");
1588 two->InsertFirstChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001589 XMLPrinter printer1(0, true);
1590 doc.Accept(&printer1);
1591 XMLTest("Move node from within <one> to <two>", xmlInsideTwo, printer1.CStr());
Michael Daumlinged523282013-10-23 07:47:29 +02001592
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001593 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001594 XMLTest( "Insertion with removal parse round 2", false, doc.Error() );
Michael Daumlinged523282013-10-23 07:47:29 +02001595 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1596 two = doc.RootElement()->FirstChildElement("two");
1597 doc.RootElement()->InsertAfterChild(two, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001598 XMLPrinter printer2(0, true);
1599 doc.Accept(&printer2);
1600 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer2.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001601
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001602 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001603 XMLTest( "Insertion with removal parse round 3", false, doc.Error() );
Michael Daumlinged523282013-10-23 07:47:29 +02001604 XMLNode* one = doc.RootElement()->FirstChildElement("one");
1605 subtree = one->FirstChildElement("subtree");
1606 doc.RootElement()->InsertAfterChild(one, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001607 XMLPrinter printer3(0, true);
1608 doc.Accept(&printer3);
1609 XMLTest("Move node from within <one> after <one>", xmlAfterOne, printer3.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001610
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001611 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001612 XMLTest( "Insertion with removal parse round 4", false, doc.Error() );
Michael Daumlinged523282013-10-23 07:47:29 +02001613 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1614 two = doc.RootElement()->FirstChildElement("two");
1615 doc.RootElement()->InsertEndChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001616 XMLPrinter printer4(0, true);
1617 doc.Accept(&printer4);
1618 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer4.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001619 }
1620
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001621 {
1622 const char* xml = "<svg width = \"128\" height = \"128\">"
1623 " <text> </text>"
1624 "</svg>";
1625 XMLDocument doc;
1626 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001627 XMLTest( "Parse svg with text", false, doc.Error() );
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001628 doc.Print();
1629 }
1630
Lee Thomason92e521b2014-11-15 17:45:51 -08001631 {
1632 // Test that it doesn't crash.
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001633 const char* xml = "<?xml version=\"1.0\"?><root><sample><field0><1</field0><field1>2</field1></sample></root>";
1634 XMLDocument doc;
1635 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001636 XMLTest( "Parse root-sample-field0", true, doc.Error() );
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001637 doc.PrintError();
Lee Thomason92e521b2014-11-15 17:45:51 -08001638 }
1639
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001640#if 1
1641 // the question being explored is what kind of print to use:
1642 // https://github.com/leethomason/tinyxml2/issues/63
1643 {
1644 //const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9' attrC='1.0e-10' attrD='1001000000.000000' attrE='0.1234567890123456789'/>";
1645 const char* xml = "<element/>";
1646 XMLDocument doc;
1647 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001648 XMLTest( "Parse self-closed empty element", false, doc.Error() );
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001649 doc.FirstChildElement()->SetAttribute( "attrA-f64", 123456789.123456789 );
1650 doc.FirstChildElement()->SetAttribute( "attrB-f64", 1.001e9 );
1651 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e9 );
1652 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e20 );
1653 doc.FirstChildElement()->SetAttribute( "attrD-f64", 1.0e-10 );
1654 doc.FirstChildElement()->SetAttribute( "attrD-f64", 0.123456789 );
1655
1656 doc.FirstChildElement()->SetAttribute( "attrA-f32", 123456789.123456789f );
1657 doc.FirstChildElement()->SetAttribute( "attrB-f32", 1.001e9f );
1658 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e9f );
1659 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e20f );
1660 doc.FirstChildElement()->SetAttribute( "attrD-f32", 1.0e-10f );
1661 doc.FirstChildElement()->SetAttribute( "attrD-f32", 0.123456789f );
1662
1663 doc.Print();
1664
1665 /* The result of this test is platform, compiler, and library version dependent. :("
1666 XMLPrinter printer;
1667 doc.Print( &printer );
1668 XMLTest( "Float and double formatting.",
1669 "<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",
1670 printer.CStr(),
1671 true );
1672 */
1673 }
1674#endif
Lee Thomasonf07b9522014-10-30 13:25:12 -07001675
1676 {
1677 // Issue #184
1678 // If it doesn't assert, it passes. Caused by objects
1679 // getting created during parsing which are then
1680 // inaccessible in the memory pools.
Dmitry-Me5d1aec12017-06-28 14:51:17 +03001681 const char* xmlText = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>";
Lee Thomasonf07b9522014-10-30 13:25:12 -07001682 {
1683 XMLDocument doc;
Dmitry-Me5d1aec12017-06-28 14:51:17 +03001684 doc.Parse(xmlText);
Dmitry-Me68578f42017-07-03 18:21:23 +03001685 XMLTest( "Parse hex no closing tag round 1", true, doc.Error() );
Lee Thomasonf07b9522014-10-30 13:25:12 -07001686 }
1687 {
1688 XMLDocument doc;
Dmitry-Me5d1aec12017-06-28 14:51:17 +03001689 doc.Parse(xmlText);
Dmitry-Me68578f42017-07-03 18:21:23 +03001690 XMLTest( "Parse hex no closing tag round 2", true, doc.Error() );
Lee Thomasonf07b9522014-10-30 13:25:12 -07001691 doc.Clear();
1692 }
1693 }
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001694
1695 {
1696 // If this doesn't assert in DEBUG, all is well.
1697 tinyxml2::XMLDocument doc;
1698 tinyxml2::XMLElement *pRoot = doc.NewElement("Root");
1699 doc.DeleteNode(pRoot);
1700 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001701
Dmitry-Me8b67d742014-12-22 11:35:12 +03001702 {
1703 // Should not assert in DEBUG
1704 XMLPrinter printer;
1705 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001706
Dmitry-Me6f51c802015-03-14 13:25:03 +03001707 {
1708 // Issue 291. Should not crash
1709 const char* xml = "&#0</a>";
1710 XMLDocument doc;
1711 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001712 XMLTest( "Parse hex with closing tag", false, doc.Error() );
Dmitry-Me6f51c802015-03-14 13:25:03 +03001713
1714 XMLPrinter printer;
1715 doc.Print( &printer );
1716 }
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001717 {
1718 // Issue 299. Can print elements that are not linked in.
1719 // Will crash if issue not fixed.
1720 XMLDocument doc;
1721 XMLElement* newElement = doc.NewElement( "printme" );
1722 XMLPrinter printer;
1723 newElement->Accept( &printer );
Dmitry-Me5daa54c2015-04-08 17:45:07 +03001724 // Delete the node to avoid possible memory leak report in debug output
1725 doc.DeleteNode( newElement );
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001726 }
Lee Thomasonf6577832015-03-26 11:18:21 -07001727 {
Ant Mitchell189198f2015-03-24 16:20:36 +00001728 // Issue 302. Clear errors from LoadFile/SaveFile
1729 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001730 XMLTest( "Issue 302. Should be no error initially", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001731 doc.SaveFile( "./no/such/path/pretty.xml" );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001732 XMLTest( "Issue 302. Fail to save", "XML_ERROR_FILE_COULD_NOT_BE_OPENED", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001733 doc.SaveFile( "./resources/out/compact.xml", true );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001734 XMLTest( "Issue 302. Subsequent success in saving", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001735 }
Dmitry-Me6f51c802015-03-14 13:25:03 +03001736
Dmitry-Med9852a52015-03-25 10:17:49 +03001737 {
1738 // If a document fails to load then subsequent
1739 // successful loads should clear the error
1740 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001741 XMLTest( "Should be no error initially", false, doc.Error() );
Dmitry-Med9852a52015-03-25 10:17:49 +03001742 doc.LoadFile( "resources/no-such-file.xml" );
1743 XMLTest( "No such file - should fail", true, doc.Error() );
1744
1745 doc.LoadFile( "resources/dream.xml" );
1746 XMLTest( "Error should be cleared", false, doc.Error() );
1747 }
Sarat Addepalli8e85afa2015-05-19 09:07:03 +05301748
Sarat Addepalli2bb6bb52015-05-18 09:16:34 +05301749 {
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001750 // Check that declarations are allowed only at beginning of document
Lee Thomason85492022015-05-22 11:07:45 -07001751 const char* xml0 = "<?xml version=\"1.0\" ?>"
1752 " <!-- xml version=\"1.1\" -->"
1753 "<first />";
1754 const char* xml1 = "<?xml version=\"1.0\" ?>"
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001755 "<?xml-stylesheet type=\"text/xsl\" href=\"Anything.xsl\"?>"
Lee Thomason85492022015-05-22 11:07:45 -07001756 "<first />";
1757 const char* xml2 = "<first />"
1758 "<?xml version=\"1.0\" ?>";
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001759 const char* xml3 = "<first></first>"
1760 "<?xml version=\"1.0\" ?>";
1761
1762 const char* xml4 = "<first><?xml version=\"1.0\" ?></first>";
1763
Lee Thomason85492022015-05-22 11:07:45 -07001764 XMLDocument doc;
1765 doc.Parse(xml0);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001766 XMLTest("Test that the code changes do not affect normal parsing", false, doc.Error() );
Lee Thomason85492022015-05-22 11:07:45 -07001767 doc.Parse(xml1);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001768 XMLTest("Test that the second declaration is allowed", false, doc.Error() );
Lee Thomason85492022015-05-22 11:07:45 -07001769 doc.Parse(xml2);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001770 XMLTest("Test that declaration after a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001771 doc.Parse(xml3);
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(xml4);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001774 XMLTest("Test that declaration inside a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );
Sarat Addepalli2bb6bb52015-05-18 09:16:34 +05301775 }
Dmitry-Med9852a52015-03-25 10:17:49 +03001776
Lee Thomason85492022015-05-22 11:07:45 -07001777 {
1778 // No matter - before or after successfully parsing a text -
1779 // calling XMLDocument::Value() causes an assert in debug.
1780 const char* validXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
1781 "<first />"
1782 "<second />";
1783 XMLDocument* doc = new XMLDocument();
1784 XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
1785 doc->Parse( validXml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001786 XMLTest( "Parse to test XMLDocument::Value()", false, doc->Error());
Lee Thomason85492022015-05-22 11:07:45 -07001787 XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
1788 delete doc;
1789 }
1790
Dmitry-Mea1beddf2015-05-26 16:19:21 +03001791 {
1792 XMLDocument doc;
1793 for( int i = 0; i < XML_ERROR_COUNT; i++ ) {
kezenatorec694152016-11-26 17:21:43 +10001794 doc.SetError( (XMLError)i, 0, 0, 0 );
Dmitry-Mea1beddf2015-05-26 16:19:21 +03001795 doc.ErrorName();
1796 }
1797 }
1798
Lee Thomason816d3fa2017-06-05 14:35:55 -07001799 {
Lee Thomasonb754ddf2017-06-14 15:02:38 -07001800 // Evil memory leaks.
1801 // If an XMLElement (etc) is allocated via NewElement() (etc.)
1802 // and NOT added to the XMLDocument, what happens?
1803 //
1804 // Previously (buggy):
1805 // The memory would be free'd when the XMLDocument is
1806 // destructed. But the destructor wasn't called, so that
1807 // memory allocated by the XMLElement would not be free'd.
1808 // In practice this meant strings allocated by the XMLElement
1809 // would leak. An edge case, but annoying.
1810 // Now:
1811 // The destructor is called. But the list of unlinked nodes
1812 // has to be tracked. This has a minor performance impact
1813 // that can become significant if you have a lot. (But why
1814 // would you do that?)
1815 // The only way to see this bug is in a leak tracker. This
1816 // is compiled in by default on Windows Debug.
Lee Thomason816d3fa2017-06-05 14:35:55 -07001817 {
1818 XMLDocument doc;
1819 doc.NewElement("LEAK 1");
1820 }
1821 {
1822 XMLDocument doc;
1823 XMLElement* ele = doc.NewElement("LEAK 2");
1824 doc.DeleteNode(ele);
1825 }
1826 }
1827
Lee Thomason224ef772017-06-16 09:45:26 -07001828 {
1829 // Crashing reported via email.
1830 const char* xml =
1831 "<playlist id='playlist1'>"
Lee Thomason82bb0742017-06-16 09:48:20 -07001832 "<property name='track_name'>voice</property>"
1833 "<property name='audio_track'>1</property>"
1834 "<entry out = '604' producer = '4_playlist1' in = '0' />"
1835 "<blank length = '1' />"
1836 "<entry out = '1625' producer = '3_playlist' in = '0' />"
1837 "<blank length = '2' />"
1838 "<entry out = '946' producer = '2_playlist1' in = '0' />"
1839 "<blank length = '1' />"
1840 "<entry out = '128' producer = '1_playlist1' in = '0' />"
Lee Thomason224ef772017-06-16 09:45:26 -07001841 "</playlist>";
Lee Thomason82bb0742017-06-16 09:48:20 -07001842
Lee Thomason224ef772017-06-16 09:45:26 -07001843 // It's not a good idea to delete elements as you walk the
1844 // list. I'm not sure this technically should work; but it's
1845 // an interesting test case.
1846 XMLDocument doc;
1847 XMLError err = doc.Parse(xml);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001848 XMLTest("Crash bug parsing", XML_SUCCESS, err );
Dmitry-Meaea64c42017-06-20 18:20:15 +03001849
1850 XMLElement* playlist = doc.FirstChildElement("playlist");
Lee Thomason224ef772017-06-16 09:45:26 -07001851 XMLTest("Crash bug parsing", true, playlist != 0);
1852
1853 tinyxml2::XMLElement* entry = playlist->FirstChildElement("entry");
1854 XMLTest("Crash bug parsing", true, entry != 0);
1855 while (entry) {
1856 tinyxml2::XMLElement* todelete = entry;
1857 entry = entry->NextSiblingElement("entry");
1858 playlist->DeleteChild(todelete);
1859 };
1860 tinyxml2::XMLElement* blank = playlist->FirstChildElement("blank");
1861 while (blank) {
1862 tinyxml2::XMLElement* todelete = blank;
1863 blank = blank->NextSiblingElement("blank");
1864 playlist->DeleteChild(todelete);
1865 };
1866
1867 tinyxml2::XMLPrinter printer;
1868 playlist->Accept(&printer);
1869 printf("%s\n", printer.CStr());
1870
Lee Thomason82bb0742017-06-16 09:48:20 -07001871 // No test; it only need to not crash.
1872 // Still, wrap it up with a sanity check
1873 int nProperty = 0;
1874 for (const XMLElement* p = playlist->FirstChildElement("property"); p; p = p->NextSiblingElement("property")) {
1875 nProperty++;
1876 }
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001877 XMLTest("Crash bug parsing", 2, nProperty);
Lee Thomason224ef772017-06-16 09:45:26 -07001878 }
1879
kezenatorec694152016-11-26 17:21:43 +10001880 // ----------- Line Number Tracking --------------
1881 {
Lee Thomasone90e9012016-12-24 07:34:39 -08001882 struct TestUtil: XMLVisitor
kezenatorec694152016-11-26 17:21:43 +10001883 {
1884 void TestParseError(const char *testString, const char *docStr, XMLError expected_error, int expectedLine)
1885 {
1886 XMLDocument doc;
1887 XMLError err = doc.Parse(docStr);
1888
1889 XMLTest(testString, true, doc.Error());
1890 XMLTest(testString, expected_error, err);
1891 XMLTest(testString, expectedLine, doc.GetErrorLineNum());
1892 };
1893
1894 void TestStringLines(const char *testString, const char *docStr, const char *expectedLines)
1895 {
1896 XMLDocument doc;
1897 doc.Parse(docStr);
1898 XMLTest(testString, false, doc.Error());
1899 TestDocLines(testString, doc, expectedLines);
1900 }
1901
1902 void TestFileLines(const char *testString, const char *file_name, const char *expectedLines)
1903 {
1904 XMLDocument doc;
1905 doc.LoadFile(file_name);
1906 XMLTest(testString, false, doc.Error());
1907 TestDocLines(testString, doc, expectedLines);
1908 }
1909
1910 private:
1911 DynArray<char, 10> str;
1912
1913 void Push(char type, int lineNum)
1914 {
1915 str.Push(type);
1916 str.Push(char('0' + (lineNum / 10)));
1917 str.Push(char('0' + (lineNum % 10)));
1918 }
1919
1920 bool VisitEnter(const XMLDocument& doc)
1921 {
kezenator19d8ea82016-11-29 19:50:27 +10001922 Push('D', doc.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001923 return true;
1924 }
1925 bool VisitEnter(const XMLElement& element, const XMLAttribute* firstAttribute)
1926 {
kezenator19d8ea82016-11-29 19:50:27 +10001927 Push('E', element.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001928 for (const XMLAttribute *attr = firstAttribute; attr != 0; attr = attr->Next())
kezenator19d8ea82016-11-29 19:50:27 +10001929 Push('A', attr->GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001930 return true;
1931 }
1932 bool Visit(const XMLDeclaration& declaration)
1933 {
kezenator19d8ea82016-11-29 19:50:27 +10001934 Push('L', declaration.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001935 return true;
1936 }
1937 bool Visit(const XMLText& text)
1938 {
kezenator19d8ea82016-11-29 19:50:27 +10001939 Push('T', text.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001940 return true;
1941 }
1942 bool Visit(const XMLComment& comment)
1943 {
kezenator19d8ea82016-11-29 19:50:27 +10001944 Push('C', comment.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001945 return true;
1946 }
1947 bool Visit(const XMLUnknown& unknown)
1948 {
kezenator19d8ea82016-11-29 19:50:27 +10001949 Push('U', unknown.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001950 return true;
1951 }
1952
1953 void TestDocLines(const char *testString, XMLDocument &doc, const char *expectedLines)
1954 {
1955 str.Clear();
1956 doc.Accept(this);
1957 str.Push(0);
1958 XMLTest(testString, expectedLines, str.Mem());
1959 }
Lee Thomasone90e9012016-12-24 07:34:39 -08001960 } tester;
kezenatorec694152016-11-26 17:21:43 +10001961
Lee Thomasone90e9012016-12-24 07:34:39 -08001962 tester.TestParseError("ErrorLine-Parsing", "\n<root>\n foo \n<unclosed/>", XML_ERROR_PARSING, 2);
1963 tester.TestParseError("ErrorLine-Declaration", "<root>\n<?xml version=\"1.0\"?>", XML_ERROR_PARSING_DECLARATION, 2);
1964 tester.TestParseError("ErrorLine-Mismatch", "\n<root>\n</mismatch>", XML_ERROR_MISMATCHED_ELEMENT, 2);
1965 tester.TestParseError("ErrorLine-CData", "\n<root><![CDATA[ \n foo bar \n", XML_ERROR_PARSING_CDATA, 2);
1966 tester.TestParseError("ErrorLine-Text", "\n<root>\n foo bar \n", XML_ERROR_PARSING_TEXT, 3);
1967 tester.TestParseError("ErrorLine-Comment", "\n<root>\n<!-- >\n", XML_ERROR_PARSING_COMMENT, 3);
1968 tester.TestParseError("ErrorLine-Declaration", "\n<root>\n<? >\n", XML_ERROR_PARSING_DECLARATION, 3);
1969 tester.TestParseError("ErrorLine-Unknown", "\n<root>\n<! \n", XML_ERROR_PARSING_UNKNOWN, 3);
1970 tester.TestParseError("ErrorLine-Element", "\n<root>\n<unclosed \n", XML_ERROR_PARSING_ELEMENT, 3);
1971 tester.TestParseError("ErrorLine-Attribute", "\n<root>\n<unclosed \n att\n", XML_ERROR_PARSING_ATTRIBUTE, 4);
1972 tester.TestParseError("ErrorLine-ElementClose", "\n<root>\n<unclosed \n/unexpected", XML_ERROR_PARSING_ELEMENT, 3);
kezenatorec694152016-11-26 17:21:43 +10001973
Lee Thomasone90e9012016-12-24 07:34:39 -08001974 tester.TestStringLines(
kezenatorec694152016-11-26 17:21:43 +10001975 "LineNumbers-String",
Lee Thomasone90e9012016-12-24 07:34:39 -08001976
1977 "<?xml version=\"1.0\"?>\n" // 1 Doc, DecL
1978 "<root a='b' \n" // 2 Element Attribute
1979 "c='d'> d <blah/> \n" // 3 Attribute Text Element
1980 "newline in text \n" // 4 Text
1981 "and second <zxcv/><![CDATA[\n" // 5 Element Text
1982 " cdata test ]]><!-- comment -->\n" // 6 Comment
1983 "<! unknown></root>", // 7 Unknown
1984
kezenatorec694152016-11-26 17:21:43 +10001985 "D01L01E02A02A03T03E03T04E05T05C06U07");
1986
Lee Thomasone90e9012016-12-24 07:34:39 -08001987 tester.TestStringLines(
kezenatorec694152016-11-26 17:21:43 +10001988 "LineNumbers-CRLF",
Lee Thomasone90e9012016-12-24 07:34:39 -08001989
1990 "\r\n" // 1 Doc (arguably should be line 2)
1991 "<?xml version=\"1.0\"?>\n" // 2 DecL
1992 "<root>\r\n" // 3 Element
1993 "\n" // 4
1994 "text contining new line \n" // 5 Text
1995 " and also containing crlf \r\n" // 6
1996 "<sub><![CDATA[\n" // 7 Element Text
1997 "cdata containing new line \n" // 8
1998 " and also containing cflr\r\n" // 9
1999 "]]></sub><sub2/></root>", // 10 Element
2000
kezenatorec694152016-11-26 17:21:43 +10002001 "D01L02E03T05E07T07E10");
2002
Lee Thomasone90e9012016-12-24 07:34:39 -08002003 tester.TestFileLines(
kezenatorec694152016-11-26 17:21:43 +10002004 "LineNumbers-File",
2005 "resources/utf8test.xml",
2006 "D01L01E02E03A03A03T03E04A04A04T04E05A05A05T05E06A06A06T06E07A07A07T07E08A08A08T08E09T09E10T10");
2007 }
2008
Lee Thomason85492022015-05-22 11:07:45 -07002009 // ----------- Performance tracking --------------
Lee Thomason6f381b72012-03-02 12:59:39 -08002010 {
2011#if defined( _MSC_VER )
2012 __int64 start, end, freq;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002013 QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
Lee Thomason6f381b72012-03-02 12:59:39 -08002014#endif
2015
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002016 FILE* perfFP = fopen("resources/dream.xml", "r");
Dmitry-Med1b82822017-07-04 18:02:54 +03002017 XMLTest("Open dream.xml", true, perfFP != 0);
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002018 fseek(perfFP, 0, SEEK_END);
Armagetron3c21d6f2016-10-13 13:31:23 +02002019 long size = ftell(perfFP);
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002020 fseek(perfFP, 0, SEEK_SET);
Lee Thomason6f381b72012-03-02 12:59:39 -08002021
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002022 char* mem = new char[size + 1];
Dmitry-Med1b82822017-07-04 18:02:54 +03002023 memset(mem, 0xfe, size);
Lee Thomasone4dc7212017-07-06 17:05:01 -07002024 size_t bytesRead = fread(mem, 1, size, perfFP);
2025 XMLTest("Read dream.xml", true, uint32_t(size) >= uint32_t(bytesRead));
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002026 fclose(perfFP);
Lee Thomason6f381b72012-03-02 12:59:39 -08002027 mem[size] = 0;
2028
2029#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002030 QueryPerformanceCounter((LARGE_INTEGER*)&start);
Lee Thomason6f381b72012-03-02 12:59:39 -08002031#else
2032 clock_t cstart = clock();
2033#endif
Dmitry-Me68578f42017-07-03 18:21:23 +03002034 bool parseDreamXmlFailed = false;
Lee Thomason6f381b72012-03-02 12:59:39 -08002035 static const int COUNT = 10;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002036 for (int i = 0; i < COUNT; ++i) {
Lee Thomason6f381b72012-03-02 12:59:39 -08002037 XMLDocument doc;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002038 doc.Parse(mem);
Dmitry-Me68578f42017-07-03 18:21:23 +03002039 parseDreamXmlFailed = parseDreamXmlFailed || doc.Error();
Lee Thomason6f381b72012-03-02 12:59:39 -08002040 }
Dmitry-Me68578f42017-07-03 18:21:23 +03002041 XMLTest( "Parse dream.xml", false, parseDreamXmlFailed );
Lee Thomason6f381b72012-03-02 12:59:39 -08002042#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002043 QueryPerformanceCounter((LARGE_INTEGER*)&end);
Lee Thomason6f381b72012-03-02 12:59:39 -08002044#else
2045 clock_t cend = clock();
2046#endif
2047
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002048 delete[] mem;
Lee Thomason6f381b72012-03-02 12:59:39 -08002049
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07002050 static const char* note =
Lee Thomason6f381b72012-03-02 12:59:39 -08002051#ifdef DEBUG
2052 "DEBUG";
2053#else
2054 "Release";
2055#endif
2056
2057#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002058 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 -08002059#else
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002060 printf("\nParsing %s of dream.xml: %.3f milli-seconds\n", note, (double)(cend - cstart) / (double)COUNT);
Lee Thomason6f381b72012-03-02 12:59:39 -08002061#endif
2062 }
2063
Lee Thomason (grinliz)7ca55582012-03-07 21:54:57 -08002064 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07002065 _CrtMemCheckpoint( &endMemState );
Lee Thomason1ff38e02012-02-14 18:18:16 -08002066
2067 _CrtMemState diffMemState;
2068 _CrtMemDifference( &diffMemState, &startMemState, &endMemState );
2069 _CrtMemDumpStatistics( &diffMemState );
Dmitry-Meed785702017-06-15 13:39:53 +03002070
2071 {
2072 int leaksBeforeExit = _CrtDumpMemoryLeaks();
2073 XMLTest( "No leaks before exit?", FALSE, leaksBeforeExit );
2074 }
Lee Thomason1ff38e02012-02-14 18:18:16 -08002075 #endif
2076
2077 printf ("\nPass %d, Fail %d\n", gPass, gFail);
Lee Thomason (grinliz)db304252013-07-31 12:24:52 -07002078
2079 return gFail;
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -08002080}