blob: 9adb058ce6b27ebce41dae38341094792e269bf8 [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" );
Dmitry-Me46b70ce2017-07-10 17:54:24 +0300474 XMLTest( "Save pretty.xml", false, doc->Error() );
Lee Thomason (grinliz)6b8b0122012-09-08 21:21:00 -0700475 doc->SaveFile( "./resources/out/compact.xml", true );
Dmitry-Me46b70ce2017-07-10 17:54:24 +0300476 XMLTest( "Save compact.xml", false, doc->Error() );
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800477 delete doc;
478 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800479 {
480 // Test: Dream
481 // XML1 : 1,187,569 bytes in 31,209 allocations
482 // XML2 : 469,073 bytes in 323 allocations
483 //int newStart = gNew;
484 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300485 doc.LoadFile( "resources/dream.xml" );
Dmitry-Me46b70ce2017-07-10 17:54:24 +0300486 XMLTest( "Load dream.xml", false, doc.Error() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800487
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400488 doc.SaveFile( "resources/out/dreamout.xml" );
Dmitry-Me46b70ce2017-07-10 17:54:24 +0300489 XMLTest( "Save dreamout.xml", false, doc.Error() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800490 doc.PrintError();
491
492 XMLTest( "Dream", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400493 doc.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800494 XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() ? true : false );
495 XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
496 doc.FirstChild()->NextSibling()->ToUnknown()->Value() );
497 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400498 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800499 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400500 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800501
502 XMLDocument doc2;
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400503 doc2.LoadFile( "resources/out/dreamout.xml" );
Dmitry-Me46b70ce2017-07-10 17:54:24 +0300504 XMLTest( "Load dreamout.xml", false, doc2.Error() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800505 XMLTest( "Dream-out", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400506 doc2.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800507 XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() ? true : false );
508 XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
509 doc2.FirstChild()->NextSibling()->ToUnknown()->Value() );
510 XMLTest( "Dream-out", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400511 doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800512
513 //gNewTotal = gNew - newStart;
514 }
Lee Thomason6f381b72012-03-02 12:59:39 -0800515
516
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800517 {
518 const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n"
519 "<passages count=\"006\" formatversion=\"20020620\">\n"
520 " <wrong error>\n"
521 "</passages>";
522
523 XMLDocument doc;
524 doc.Parse( error );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300525 XMLTest( "Bad XML", XML_ERROR_PARSING_ATTRIBUTE, doc.ErrorID() );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800526 }
527
528 {
529 const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
530
531 XMLDocument doc;
532 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300533 XMLTest( "Top level attributes", false, doc.Error() );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800534
535 XMLElement* ele = doc.FirstChildElement();
536
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300537 int iVal;
538 XMLError result;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800539 double dVal;
540
541 result = ele->QueryDoubleAttribute( "attr0", &dVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300542 XMLTest( "Query attribute: int as double", XML_SUCCESS, result);
543 XMLTest( "Query attribute: int as double", 1, (int)dVal );
544 XMLTest( "Query attribute: int as double", 1, (int)ele->DoubleAttribute("attr0"));
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700545
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800546 result = ele->QueryDoubleAttribute( "attr1", &dVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300547 XMLTest( "Query attribute: double as double", XML_SUCCESS, result);
548 XMLTest( "Query attribute: double as double", 2.0, dVal );
549 XMLTest( "Query attribute: double as double", 2.0, ele->DoubleAttribute("attr1") );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700550
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800551 result = ele->QueryIntAttribute( "attr1", &iVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300552 XMLTest( "Query attribute: double as int", XML_SUCCESS, result);
553 XMLTest( "Query attribute: double as int", 2, iVal );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700554
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800555 result = ele->QueryIntAttribute( "attr2", &iVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300556 XMLTest( "Query attribute: not a number", XML_WRONG_ATTRIBUTE_TYPE, result );
557 XMLTest( "Query attribute: not a number", 4.0, ele->DoubleAttribute("attr2", 4.0) );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700558
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800559 result = ele->QueryIntAttribute( "bar", &iVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300560 XMLTest( "Query attribute: does not exist", XML_NO_ATTRIBUTE, result );
561 XMLTest( "Query attribute: does not exist", true, ele->BoolAttribute("bar", true) );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800562 }
563
564 {
565 const char* str = "<doc/>";
566
567 XMLDocument doc;
568 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300569 XMLTest( "Empty top element", false, doc.Error() );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800570
571 XMLElement* ele = doc.FirstChildElement();
572
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800573 int iVal, iVal2;
574 double dVal, dVal2;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800575
576 ele->SetAttribute( "str", "strValue" );
577 ele->SetAttribute( "int", 1 );
578 ele->SetAttribute( "double", -1.0 );
579
580 const char* cStr = ele->Attribute( "str" );
581 ele->QueryIntAttribute( "int", &iVal );
582 ele->QueryDoubleAttribute( "double", &dVal );
583
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800584 ele->QueryAttribute( "int", &iVal2 );
585 ele->QueryAttribute( "double", &dVal2 );
586
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300587 XMLTest( "Attribute match test", "strValue", ele->Attribute( "str", "strValue" ) );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800588 XMLTest( "Attribute round trip. c-string.", "strValue", cStr );
589 XMLTest( "Attribute round trip. int.", 1, iVal );
590 XMLTest( "Attribute round trip. double.", -1, (int)dVal );
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800591 XMLTest( "Alternate query", true, iVal == iVal2 );
592 XMLTest( "Alternate query", true, dVal == dVal2 );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700593 XMLTest( "Alternate query", true, iVal == ele->IntAttribute("int") );
594 XMLTest( "Alternate query", true, dVal == ele->DoubleAttribute("double") );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800595 }
596
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800597 {
598 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300599 doc.LoadFile( "resources/utf8test.xml" );
Dmitry-Me46b70ce2017-07-10 17:54:24 +0300600 XMLTest( "Load utf8test.xml", false, doc.Error() );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800601
602 // Get the attribute "value" from the "Russian" element and check it.
603 XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700604 const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800605 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
606
607 XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) );
608
609 const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U,
610 0xd1U, 0x81U, 0xd1U, 0x81U,
611 0xd0U, 0xbaU, 0xd0U, 0xb8U,
612 0xd0U, 0xb9U, 0 };
613 const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
614
615 XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText();
616 XMLTest( "UTF-8: Browsing russian element name.",
617 russianText,
618 text->Value() );
619
620 // Now try for a round trip.
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400621 doc.SaveFile( "resources/out/utf8testout.xml" );
Dmitry-Me46b70ce2017-07-10 17:54:24 +0300622 XMLTest( "UTF-8: Save testout.xml", false, doc.Error() );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800623
624 // Check the round trip.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800625 int okay = 0;
626
Thomas Roßa6dd8c62012-07-26 20:42:18 +0200627 FILE* saved = fopen( "resources/out/utf8testout.xml", "r" );
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300628 FILE* verify = fopen( "resources/utf8testverify.xml", "r" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800629
630 if ( saved && verify )
631 {
632 okay = 1;
PKEuSc28ba3a2012-07-16 03:08:47 -0700633 char verifyBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800634 while ( fgets( verifyBuf, 256, verify ) )
635 {
PKEuSc28ba3a2012-07-16 03:08:47 -0700636 char savedBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800637 fgets( savedBuf, 256, saved );
638 NullLineEndings( verifyBuf );
639 NullLineEndings( savedBuf );
640
641 if ( strcmp( verifyBuf, savedBuf ) )
642 {
643 printf( "verify:%s<\n", verifyBuf );
644 printf( "saved :%s<\n", savedBuf );
645 okay = 0;
646 break;
647 }
648 }
649 }
650 if ( saved )
651 fclose( saved );
652 if ( verify )
653 fclose( verify );
654 XMLTest( "UTF-8: Verified multi-language round trip.", 1, okay );
655 }
656
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800657 // --------GetText()-----------
658 {
659 const char* str = "<foo>This is text</foo>";
660 XMLDocument doc;
661 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300662 XMLTest( "Double whitespace", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800663 const XMLElement* element = doc.RootElement();
664
665 XMLTest( "GetText() normal use.", "This is text", element->GetText() );
666
667 str = "<foo><b>This is text</b></foo>";
668 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300669 XMLTest( "Bold text simulation", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800670 element = doc.RootElement();
671
672 XMLTest( "GetText() contained element.", element->GetText() == 0, true );
673 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800674
Lee Thomasond6277762012-02-22 16:00:12 -0800675
Uli Kusterer321072e2014-01-21 01:57:38 +0100676 // --------SetText()-----------
677 {
678 const char* str = "<foo></foo>";
679 XMLDocument doc;
680 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300681 XMLTest( "Empty closed element", false, doc.Error() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100682 XMLElement* element = doc.RootElement();
683
Lee Thomason9c0678a2014-01-24 10:18:27 -0800684 element->SetText("darkness.");
685 XMLTest( "SetText() normal use (open/close).", "darkness.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100686
Lee Thomason9c0678a2014-01-24 10:18:27 -0800687 element->SetText("blue flame.");
688 XMLTest( "SetText() replace.", "blue flame.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100689
690 str = "<foo/>";
691 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300692 XMLTest( "Empty self-closed element", false, doc.Error() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100693 element = doc.RootElement();
694
Lee Thomason9c0678a2014-01-24 10:18:27 -0800695 element->SetText("The driver");
696 XMLTest( "SetText() normal use. (self-closing)", "The driver", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100697
Lee Thomason9c0678a2014-01-24 10:18:27 -0800698 element->SetText("<b>horses</b>");
699 XMLTest( "SetText() replace with tag-like text.", "<b>horses</b>", element->GetText() );
700 //doc.Print();
Uli Kusterer321072e2014-01-21 01:57:38 +0100701
702 str = "<foo><bar>Text in nested element</bar></foo>";
703 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300704 XMLTest( "Text in nested element", false, doc.Error() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100705 element = doc.RootElement();
706
Lee Thomason9c0678a2014-01-24 10:18:27 -0800707 element->SetText("wolves");
708 XMLTest( "SetText() prefix to nested non-text children.", "wolves", element->GetText() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800709
710 str = "<foo/>";
711 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300712 XMLTest( "Empty self-closed element round 2", false, doc.Error() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800713 element = doc.RootElement();
714
715 element->SetText( "str" );
716 XMLTest( "SetText types", "str", element->GetText() );
717
718 element->SetText( 1 );
719 XMLTest( "SetText types", "1", element->GetText() );
720
721 element->SetText( 1U );
722 XMLTest( "SetText types", "1", element->GetText() );
723
724 element->SetText( true );
Doruk Turak1f212f32016-08-28 20:54:17 +0200725 XMLTest( "SetText types", "true", element->GetText() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800726
727 element->SetText( 1.5f );
728 XMLTest( "SetText types", "1.5", element->GetText() );
729
730 element->SetText( 1.5 );
731 XMLTest( "SetText types", "1.5", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100732 }
733
Lee Thomason51c12712016-06-04 20:18:49 -0700734 // ---------- Attributes ---------
735 {
736 static const int64_t BIG = -123456789012345678;
737 XMLDocument doc;
738 XMLElement* element = doc.NewElement("element");
739 doc.InsertFirstChild(element);
740
741 {
742 element->SetAttribute("attrib", int(-100));
743 int v = 0;
744 element->QueryIntAttribute("attrib", &v);
745 XMLTest("Attribute: int", -100, v, true);
746 element->QueryAttribute("attrib", &v);
747 XMLTest("Attribute: int", -100, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700748 XMLTest("Attribute: int", -100, element->IntAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700749 }
750 {
751 element->SetAttribute("attrib", unsigned(100));
752 unsigned v = 0;
753 element->QueryUnsignedAttribute("attrib", &v);
754 XMLTest("Attribute: unsigned", unsigned(100), v, true);
755 element->QueryAttribute("attrib", &v);
756 XMLTest("Attribute: unsigned", unsigned(100), v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700757 XMLTest("Attribute: unsigned", unsigned(100), element->UnsignedAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700758 }
759 {
760 element->SetAttribute("attrib", BIG);
761 int64_t v = 0;
762 element->QueryInt64Attribute("attrib", &v);
763 XMLTest("Attribute: int64_t", BIG, v, true);
764 element->QueryAttribute("attrib", &v);
765 XMLTest("Attribute: int64_t", BIG, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700766 XMLTest("Attribute: int64_t", BIG, element->Int64Attribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700767 }
768 {
769 element->SetAttribute("attrib", true);
770 bool v = false;
771 element->QueryBoolAttribute("attrib", &v);
772 XMLTest("Attribute: bool", true, v, true);
773 element->QueryAttribute("attrib", &v);
774 XMLTest("Attribute: bool", true, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700775 XMLTest("Attribute: bool", true, element->BoolAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700776 }
777 {
Lee Thomasonce667c92016-12-26 16:45:30 -0800778 element->SetAttribute("attrib", true);
779 const char* result = element->Attribute("attrib");
780 XMLTest("Bool true is 'true'", "true", result);
781
Lee Thomasonc5c99c22016-12-29 11:19:17 -0800782 XMLUtil::SetBoolSerialization("1", "0");
Lee Thomasonce667c92016-12-26 16:45:30 -0800783 element->SetAttribute("attrib", true);
784 result = element->Attribute("attrib");
785 XMLTest("Bool true is '1'", "1", result);
786
Lee Thomasonc5c99c22016-12-29 11:19:17 -0800787 XMLUtil::SetBoolSerialization(0, 0);
Lee Thomasonce667c92016-12-26 16:45:30 -0800788 }
789 {
Lee Thomason51c12712016-06-04 20:18:49 -0700790 element->SetAttribute("attrib", 100.0);
791 double v = 0;
792 element->QueryDoubleAttribute("attrib", &v);
793 XMLTest("Attribute: double", 100.0, v, true);
794 element->QueryAttribute("attrib", &v);
795 XMLTest("Attribute: double", 100.0, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700796 XMLTest("Attribute: double", 100.0, element->DoubleAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700797 }
798 {
799 element->SetAttribute("attrib", 100.0f);
800 float v = 0;
801 element->QueryFloatAttribute("attrib", &v);
802 XMLTest("Attribute: float", 100.0f, v, true);
803 element->QueryAttribute("attrib", &v);
804 XMLTest("Attribute: float", 100.0f, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700805 XMLTest("Attribute: float", 100.0f, element->FloatAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700806 }
807 {
808 element->SetText(BIG);
809 int64_t v = 0;
810 element->QueryInt64Text(&v);
811 XMLTest("Element: int64_t", BIG, v, true);
812 }
813 }
814
815 // ---------- XMLPrinter stream mode ------
816 {
817 {
818 FILE* printerfp = fopen("resources/printer.xml", "w");
819 XMLPrinter printer(printerfp);
820 printer.OpenElement("foo");
821 printer.PushAttribute("attrib-text", "text");
822 printer.PushAttribute("attrib-int", int(1));
823 printer.PushAttribute("attrib-unsigned", unsigned(2));
824 printer.PushAttribute("attrib-int64", int64_t(3));
825 printer.PushAttribute("attrib-bool", true);
826 printer.PushAttribute("attrib-double", 4.0);
827 printer.CloseElement();
828 fclose(printerfp);
829 }
830 {
831 XMLDocument doc;
832 doc.LoadFile("resources/printer.xml");
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300833 XMLTest("XMLPrinter Stream mode: load", XML_SUCCESS, doc.ErrorID(), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700834
835 const XMLDocument& cdoc = doc;
836
837 const XMLAttribute* attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-text");
838 XMLTest("attrib-text", "text", attrib->Value(), true);
839 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int");
840 XMLTest("attrib-int", int(1), attrib->IntValue(), true);
841 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-unsigned");
842 XMLTest("attrib-unsigned", unsigned(2), attrib->UnsignedValue(), true);
843 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int64");
844 XMLTest("attrib-int64", int64_t(3), attrib->Int64Value(), true);
845 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-bool");
846 XMLTest("attrib-bool", true, attrib->BoolValue(), true);
847 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-double");
848 XMLTest("attrib-double", 4.0, attrib->DoubleValue(), true);
849 }
850
851 }
852
Uli Kusterer321072e2014-01-21 01:57:38 +0100853
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800854 // ---------- CDATA ---------------
855 {
856 const char* str = "<xmlElement>"
857 "<![CDATA["
858 "I am > the rules!\n"
859 "...since I make symbolic puns"
860 "]]>"
861 "</xmlElement>";
862 XMLDocument doc;
863 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300864 XMLTest( "CDATA symbolic puns round 1", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800865 doc.Print();
Lee Thomasond6277762012-02-22 16:00:12 -0800866
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300867 XMLTest( "CDATA parse.", "I am > the rules!\n...since I make symbolic puns",
868 doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomasond6277762012-02-22 16:00:12 -0800869 false );
870 }
871
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800872 // ----------- CDATA -------------
873 {
874 const char* str = "<xmlElement>"
875 "<![CDATA["
876 "<b>I am > the rules!</b>\n"
877 "...since I make symbolic puns"
878 "]]>"
879 "</xmlElement>";
880 XMLDocument doc;
881 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300882 XMLTest( "CDATA symbolic puns round 2", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800883 doc.Print();
884
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300885 XMLTest( "CDATA parse. [ tixml1:1480107 ]",
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800886 "<b>I am > the rules!</b>\n...since I make symbolic puns",
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300887 doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800888 false );
889 }
890
891 // InsertAfterChild causes crash.
892 {
893 // InsertBeforeChild and InsertAfterChild causes crash.
894 XMLDocument doc;
895 XMLElement* parent = doc.NewElement( "Parent" );
896 doc.InsertFirstChild( parent );
897
898 XMLElement* childText0 = doc.NewElement( "childText0" );
899 XMLElement* childText1 = doc.NewElement( "childText1" );
900
901 XMLNode* childNode0 = parent->InsertEndChild( childText0 );
902 XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 );
903
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300904 XMLTest( "Test InsertAfterChild on empty node. ", true, ( childNode1 == parent->LastChild() ) );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800905 }
Lee Thomasond6277762012-02-22 16:00:12 -0800906
907 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800908 // Entities not being written correctly.
909 // From Lynn Allen
Lee Thomasond6277762012-02-22 16:00:12 -0800910
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800911 const char* passages =
912 "<?xml version=\"1.0\" standalone=\"no\" ?>"
913 "<passages count=\"006\" formatversion=\"20020620\">"
914 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
915 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
916 "</passages>";
Lee Thomasond6277762012-02-22 16:00:12 -0800917
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800918 XMLDocument doc;
919 doc.Parse( passages );
Dmitry-Me68578f42017-07-03 18:21:23 +0300920 XMLTest( "Entity transformation parse round 1", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800921 XMLElement* psg = doc.RootElement()->FirstChildElement();
922 const char* context = psg->Attribute( "context" );
923 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 -0800924
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800925 XMLTest( "Entity transformation: read. ", expected, context, true );
Lee Thomasond6277762012-02-22 16:00:12 -0800926
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400927 FILE* textfile = fopen( "resources/out/textfile.txt", "w" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800928 if ( textfile )
929 {
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800930 XMLPrinter streamer( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800931 psg->Accept( &streamer );
932 fclose( textfile );
933 }
Thomas Roß0922b732012-09-23 16:31:22 +0200934
935 textfile = fopen( "resources/out/textfile.txt", "r" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800936 TIXMLASSERT( textfile );
937 if ( textfile )
938 {
939 char buf[ 1024 ];
940 fgets( buf, 1024, textfile );
941 XMLTest( "Entity transformation: write. ",
942 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
943 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.\"/>\n",
944 buf, false );
PKEuSc28ba3a2012-07-16 03:08:47 -0700945 fclose( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800946 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800947 }
948
949 {
Lee Thomason6f381b72012-03-02 12:59:39 -0800950 // Suppress entities.
951 const char* passages =
952 "<?xml version=\"1.0\" standalone=\"no\" ?>"
953 "<passages count=\"006\" formatversion=\"20020620\">"
954 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
955 "</passages>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700956
Lee Thomason6f381b72012-03-02 12:59:39 -0800957 XMLDocument doc( false );
958 doc.Parse( passages );
Dmitry-Me68578f42017-07-03 18:21:23 +0300959 XMLTest( "Entity transformation parse round 2", false, doc.Error() );
Lee Thomason6f381b72012-03-02 12:59:39 -0800960
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300961 XMLTest( "No entity parsing.",
962 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.",
963 doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ) );
964 XMLTest( "No entity parsing.", "Crazy &ttk;",
965 doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value() );
Lee Thomason6f381b72012-03-02 12:59:39 -0800966 doc.Print();
967 }
968
969 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400970 const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800971
972 XMLDocument doc;
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400973 doc.Parse( test );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300974 XMLTest( "dot in names", false, doc.Error() );
975 XMLTest( "dot in names", "a.elem", doc.FirstChildElement()->Name() );
976 XMLTest( "dot in names", "2.0", doc.FirstChildElement()->Attribute( "xmi.version" ) );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800977 }
978
979 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400980 const char* test = "<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800981
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400982 XMLDocument doc;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800983 doc.Parse( test );
Dmitry-Me68578f42017-07-03 18:21:23 +0300984 XMLTest( "fin thickness", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800985
986 XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
987 XMLTest( "Entity with one digit.",
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300988 "1.1 Start easy ignore fin thickness\n", text->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800989 false );
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400990 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800991
992 {
993 // DOCTYPE not preserved (950171)
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700994 //
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800995 const char* doctype =
996 "<?xml version=\"1.0\" ?>"
997 "<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
998 "<!ELEMENT title (#PCDATA)>"
999 "<!ELEMENT books (title,authors)>"
1000 "<element />";
1001
1002 XMLDocument doc;
1003 doc.Parse( doctype );
Dmitry-Me68578f42017-07-03 18:21:23 +03001004 XMLTest( "PLAY SYSTEM parse", false, doc.Error() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +04001005 doc.SaveFile( "resources/out/test7.xml" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001006 XMLTest( "PLAY SYSTEM save", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001007 doc.DeleteChild( doc.RootElement() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +04001008 doc.LoadFile( "resources/out/test7.xml" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001009 XMLTest( "PLAY SYSTEM load", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001010 doc.Print();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001011
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001012 const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown();
1013 XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() );
1014
1015 }
1016
1017 {
1018 // Comments do not stream out correctly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001019 const char* doctype =
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001020 "<!-- Somewhat<evil> -->";
1021 XMLDocument doc;
1022 doc.Parse( doctype );
Dmitry-Me68578f42017-07-03 18:21:23 +03001023 XMLTest( "Comment somewhat evil", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001024
1025 XMLComment* comment = doc.FirstChild()->ToComment();
1026
1027 XMLTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
1028 }
1029 {
1030 // Double attributes
1031 const char* doctype = "<element attr='red' attr='blue' />";
1032
1033 XMLDocument doc;
1034 doc.Parse( doctype );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001035
Lee Thomason2fa81722012-11-09 12:37:46 -08001036 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 -08001037 doc.PrintError();
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001038 }
1039
1040 {
1041 // Embedded null in stream.
1042 const char* doctype = "<element att\0r='red' attr='blue' />";
1043
1044 XMLDocument doc;
1045 doc.Parse( doctype );
1046 XMLTest( "Embedded null throws error.", true, doc.Error() );
1047 }
1048
1049 {
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -07001050 // Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
Dmitry-Me588bb8d2014-12-25 18:59:18 +03001051 const char* str = "";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001052 XMLDocument doc;
1053 doc.Parse( str );
Lee Thomason2fa81722012-11-09 12:37:46 -08001054 XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001055 }
1056
1057 {
Dmitry-Me588bb8d2014-12-25 18:59:18 +03001058 // Documents with all whitespaces should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
1059 const char* str = " ";
1060 XMLDocument doc;
1061 doc.Parse( str );
1062 XMLTest( "All whitespaces document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
1063 }
1064
1065 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001066 // Low entities
1067 XMLDocument doc;
1068 doc.Parse( "<test>&#x0e;</test>" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001069 XMLTest( "Hex values", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001070 const char result[] = { 0x0e, 0 };
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001071 XMLTest( "Low entities.", result, doc.FirstChildElement()->GetText() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001072 doc.Print();
1073 }
1074
1075 {
1076 // Attribute values with trailing quotes not handled correctly
1077 XMLDocument doc;
1078 doc.Parse( "<foo attribute=bar\" />" );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001079 XMLTest( "Throw error with bad end quotes.", true, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001080 }
1081
1082 {
1083 // [ 1663758 ] Failure to report error on bad XML
1084 XMLDocument xml;
1085 xml.Parse("<x>");
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001086 XMLTest("Missing end tag at end of input", true, xml.Error());
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001087 xml.Parse("<x> ");
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001088 XMLTest("Missing end tag with trailing whitespace", true, xml.Error());
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001089 xml.Parse("<x></y>");
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001090 XMLTest("Mismatched tags", XML_ERROR_MISMATCHED_ELEMENT, xml.ErrorID() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001091 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001092
1093
1094 {
1095 // [ 1475201 ] TinyXML parses entities in comments
1096 XMLDocument xml;
1097 xml.Parse("<!-- declarations for <head> & <body> -->"
1098 "<!-- far &amp; away -->" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001099 XMLTest( "Declarations for head and body", false, xml.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001100
1101 XMLNode* e0 = xml.FirstChild();
1102 XMLNode* e1 = e0->NextSibling();
1103 XMLComment* c0 = e0->ToComment();
1104 XMLComment* c1 = e1->ToComment();
1105
1106 XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
1107 XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
1108 }
1109
1110 {
1111 XMLDocument xml;
1112 xml.Parse( "<Parent>"
1113 "<child1 att=''/>"
1114 "<!-- With this comment, child2 will not be parsed! -->"
1115 "<child2 att=''/>"
1116 "</Parent>" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001117 XMLTest( "Comments iteration", false, xml.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001118 xml.Print();
1119
1120 int count = 0;
1121
1122 for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
1123 ele;
1124 ele = ele->NextSibling() )
1125 {
1126 ++count;
1127 }
1128
1129 XMLTest( "Comments iterate correctly.", 3, count );
1130 }
1131
1132 {
1133 // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
1134 unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
1135 buf[60] = 239;
1136 buf[61] = 0;
1137
1138 XMLDocument doc;
1139 doc.Parse( (const char*)buf);
Dmitry-Me68578f42017-07-03 18:21:23 +03001140 XMLTest( "Broken CDATA", true, doc.Error() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001141 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001142
1143
1144 {
1145 // bug 1827248 Error while parsing a little bit malformed file
1146 // Actually not malformed - should work.
1147 XMLDocument xml;
1148 xml.Parse( "<attributelist> </attributelist >" );
1149 XMLTest( "Handle end tag whitespace", false, xml.Error() );
1150 }
1151
1152 {
1153 // This one must not result in an infinite loop
1154 XMLDocument xml;
1155 xml.Parse( "<infinite>loop" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001156 XMLTest( "No closing element", true, xml.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001157 XMLTest( "Infinite loop test.", true, true );
1158 }
1159#endif
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001160 {
1161 const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
1162 XMLDocument doc;
1163 doc.Parse( pub );
Dmitry-Me68578f42017-07-03 18:21:23 +03001164 XMLTest( "Trailing DOCTYPE", false, doc.Error() );
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001165
1166 XMLDocument clone;
1167 for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
1168 XMLNode* copy = node->ShallowClone( &clone );
1169 clone.InsertEndChild( copy );
1170 }
1171
1172 clone.Print();
1173
1174 int count=0;
1175 const XMLNode* a=clone.FirstChild();
1176 const XMLNode* b=doc.FirstChild();
1177 for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
1178 ++count;
1179 XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
1180 }
1181 XMLTest( "Clone and Equal", 4, count );
1182 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001183
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001184 {
Lee Thomason7085f002017-06-01 18:09:43 -07001185 // Deep Cloning of root element.
1186 XMLDocument doc2;
1187 XMLPrinter printer1;
1188 {
1189 // Make sure doc1 is deleted before we test doc2
1190 const char* xml =
1191 "<root>"
1192 " <child1 foo='bar'/>"
1193 " <!-- comment thing -->"
1194 " <child2 val='1'>Text</child2>"
1195 "</root>";
1196 XMLDocument doc;
1197 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001198 XMLTest( "Parse before deep cloning root element", false, doc.Error() );
Lee Thomason7085f002017-06-01 18:09:43 -07001199
1200 doc.Print(&printer1);
1201 XMLNode* root = doc.RootElement()->DeepClone(&doc2);
1202 doc2.InsertFirstChild(root);
1203 }
1204 XMLPrinter printer2;
1205 doc2.Print(&printer2);
1206
1207 XMLTest("Deep clone of element.", printer1.CStr(), printer2.CStr(), true);
1208 }
1209
1210 {
1211 // Deep Cloning of sub element.
1212 XMLDocument doc2;
1213 XMLPrinter printer1;
1214 {
1215 // Make sure doc1 is deleted before we test doc2
1216 const char* xml =
1217 "<?xml version ='1.0'?>"
1218 "<root>"
1219 " <child1 foo='bar'/>"
1220 " <!-- comment thing -->"
1221 " <child2 val='1'>Text</child2>"
1222 "</root>";
1223 XMLDocument doc;
1224 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001225 XMLTest( "Parse before deep cloning sub element", false, doc.Error() );
Lee Thomason7085f002017-06-01 18:09:43 -07001226
1227 const XMLElement* subElement = doc.FirstChildElement("root")->FirstChildElement("child2");
1228 subElement->Accept(&printer1);
1229
1230 XMLNode* clonedSubElement = subElement->DeepClone(&doc2);
1231 doc2.InsertFirstChild(clonedSubElement);
1232 }
1233 XMLPrinter printer2;
1234 doc2.Print(&printer2);
1235
1236 XMLTest("Deep clone of sub-element.", printer1.CStr(), printer2.CStr(), true);
1237 }
1238
1239 {
1240 // Deep cloning of document.
1241 XMLDocument doc2;
1242 XMLPrinter printer1;
1243 {
1244 // Make sure doc1 is deleted before we test doc2
1245 const char* xml =
1246 "<?xml version ='1.0'?>"
1247 "<!-- Top level comment. -->"
1248 "<root>"
1249 " <child1 foo='bar'/>"
1250 " <!-- comment thing -->"
1251 " <child2 val='1'>Text</child2>"
1252 "</root>";
1253 XMLDocument doc;
1254 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001255 XMLTest( "Parse before deep cloning document", false, doc.Error() );
Lee Thomason7085f002017-06-01 18:09:43 -07001256 doc.Print(&printer1);
1257
1258 doc.DeepCopy(&doc2);
1259 }
1260 XMLPrinter printer2;
1261 doc2.Print(&printer2);
1262
1263 XMLTest("DeepCopy of document.", printer1.CStr(), printer2.CStr(), true);
1264 }
1265
1266
1267 {
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001268 // This shouldn't crash.
1269 XMLDocument doc;
Lee Thomason85536252016-06-04 19:10:53 -07001270 if(XML_SUCCESS != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001271 {
1272 doc.PrintError();
1273 }
1274 XMLTest( "Error in snprinf handling.", true, doc.Error() );
1275 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001276
Lee Thomason5e3803c2012-04-16 08:57:05 -07001277 {
1278 // Attribute ordering.
1279 static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
1280 XMLDocument doc;
1281 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001282 XMLTest( "Parse for attribute ordering", false, doc.Error() );
Lee Thomason5e3803c2012-04-16 08:57:05 -07001283 XMLElement* ele = doc.FirstChildElement();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001284
Lee Thomason5e3803c2012-04-16 08:57:05 -07001285 const XMLAttribute* a = ele->FirstAttribute();
1286 XMLTest( "Attribute order", "1", a->Value() );
1287 a = a->Next();
1288 XMLTest( "Attribute order", "2", a->Value() );
1289 a = a->Next();
1290 XMLTest( "Attribute order", "3", a->Value() );
1291 XMLTest( "Attribute order", "attrib3", a->Name() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001292
Lee Thomason5e3803c2012-04-16 08:57:05 -07001293 ele->DeleteAttribute( "attrib2" );
1294 a = ele->FirstAttribute();
1295 XMLTest( "Attribute order", "1", a->Value() );
1296 a = a->Next();
1297 XMLTest( "Attribute order", "3", a->Value() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001298
Lee Thomason5e3803c2012-04-16 08:57:05 -07001299 ele->DeleteAttribute( "attrib1" );
1300 ele->DeleteAttribute( "attrib3" );
1301 XMLTest( "Attribute order (empty)", false, ele->FirstAttribute() ? true : false );
1302 }
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001303
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001304 {
1305 // Make sure an attribute with a space in it succeeds.
Lee Thomason78a773d2012-07-02 10:10:19 -07001306 static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
1307 static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
1308 static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
1309 XMLDocument doc0;
1310 doc0.Parse( xml0 );
Dmitry-Me68578f42017-07-03 18:21:23 +03001311 XMLTest( "Parse attribute with space 1", false, doc0.Error() );
Lee Thomason78a773d2012-07-02 10:10:19 -07001312 XMLDocument doc1;
1313 doc1.Parse( xml1 );
Dmitry-Me68578f42017-07-03 18:21:23 +03001314 XMLTest( "Parse attribute with space 2", false, doc1.Error() );
Lee Thomason78a773d2012-07-02 10:10:19 -07001315 XMLDocument doc2;
1316 doc2.Parse( xml2 );
Dmitry-Me68578f42017-07-03 18:21:23 +03001317 XMLTest( "Parse attribute with space 3", false, doc2.Error() );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001318
Lee Thomason78a773d2012-07-02 10:10:19 -07001319 XMLElement* ele = 0;
1320 ele = doc0.FirstChildElement();
1321 XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
1322 ele = doc1.FirstChildElement();
1323 XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
1324 ele = doc2.FirstChildElement();
1325 XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001326 }
1327
1328 {
1329 // Make sure we don't go into an infinite loop.
1330 static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
1331 XMLDocument doc;
1332 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001333 XMLTest( "Parse two elements with attribute", false, doc.Error() );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001334 XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
1335 XMLElement* ele1 = ele0->NextSiblingElement();
1336 bool equal = ele0->ShallowEqual( ele1 );
1337
1338 XMLTest( "Infinite loop in shallow equal.", true, equal );
1339 }
1340
Lee Thomason5708f812012-03-28 17:46:41 -07001341 // -------- Handles ------------
1342 {
1343 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1344 XMLDocument doc;
1345 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001346 XMLTest( "Parse element with attribute and nested element round 1", false, doc.Error() );
Lee Thomason5708f812012-03-28 17:46:41 -07001347
1348 XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001349 XMLTest( "Handle, success, mutable", "sub", ele->Value() );
Lee Thomason5708f812012-03-28 17:46:41 -07001350
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001351 XMLHandle docH( doc );
1352 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001353 XMLTest( "Handle, dne, mutable", false, ele != 0 );
Lee Thomason5708f812012-03-28 17:46:41 -07001354 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001355
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001356 {
1357 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1358 XMLDocument doc;
1359 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001360 XMLTest( "Parse element with attribute and nested element round 2", false, doc.Error() );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001361 XMLConstHandle docH( doc );
1362
1363 const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement();
1364 XMLTest( "Handle, success, const", ele->Value(), "sub" );
1365
1366 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001367 XMLTest( "Handle, dne, const", false, ele != 0 );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001368 }
Lee Thomasonf68c4382012-04-28 14:37:11 -07001369 {
1370 // Default Declaration & BOM
1371 XMLDocument doc;
1372 doc.InsertEndChild( doc.NewDeclaration() );
1373 doc.SetBOM( true );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001374
Lee Thomasonf68c4382012-04-28 14:37:11 -07001375 XMLPrinter printer;
1376 doc.Print( &printer );
1377
1378 static const char* result = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001379 XMLTest( "BOM and default declaration", result, printer.CStr(), false );
1380 XMLTest( "CStrSize", 42, printer.CStrSize(), false );
Lee Thomasonf68c4382012-04-28 14:37:11 -07001381 }
Lee Thomason21be8822012-07-15 17:27:22 -07001382 {
1383 const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
1384 XMLDocument doc;
1385 doc.Parse( xml );
1386 XMLTest( "Ill formed XML", true, doc.Error() );
1387 }
1388
1389 // QueryXYZText
1390 {
1391 const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
1392 XMLDocument doc;
1393 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001394 XMLTest( "Parse points", false, doc.Error() );
Lee Thomason21be8822012-07-15 17:27:22 -07001395
1396 const XMLElement* pointElement = doc.RootElement();
1397
1398 int intValue = 0;
1399 unsigned unsignedValue = 0;
1400 float floatValue = 0;
1401 double doubleValue = 0;
1402 bool boolValue = false;
1403
1404 pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
1405 pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
1406 pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
1407 pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
1408 pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
1409
1410
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001411 XMLTest( "QueryIntText", 1, intValue, false );
1412 XMLTest( "QueryUnsignedText", (unsigned)1, unsignedValue, false );
1413 XMLTest( "QueryFloatText", 1.2f, floatValue, false );
1414 XMLTest( "QueryDoubleText", 1.2, doubleValue, false );
1415 XMLTest( "QueryBoolText", true, boolValue, false );
Lee Thomason21be8822012-07-15 17:27:22 -07001416 }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001417
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001418 {
1419 const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
1420 XMLDocument doc;
1421 doc.Parse( xml );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001422 XMLTest( "Non-alpha element lead letter parses.", false, doc.Error() );
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001423 }
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001424
1425 {
1426 const char* xml = "<element _attr1=\"foo\" :attr2=\"bar\"></element>";
1427 XMLDocument doc;
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001428 doc.Parse( xml );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001429 XMLTest("Non-alpha attribute lead character parses.", false, doc.Error());
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001430 }
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001431
1432 {
1433 const char* xml = "<3lement></3lement>";
1434 XMLDocument doc;
1435 doc.Parse( xml );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001436 XMLTest("Element names with lead digit fail to parse.", true, doc.Error());
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001437 }
Lee Thomason (grinliz)62d1c5a2012-09-08 21:44:12 -07001438
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001439 {
1440 const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
1441 XMLDocument doc;
1442 doc.Parse( xml, 10 );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001443 XMLTest( "Set length of incoming data", false, doc.Error() );
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001444 }
1445
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001446 {
1447 XMLDocument doc;
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001448 XMLTest( "Document is initially empty", true, doc.NoChildren() );
Dmitry-Me48b5df02015-04-06 18:20:25 +03001449 doc.Clear();
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001450 XMLTest( "Empty is empty after Clear()", true, doc.NoChildren() );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001451 doc.LoadFile( "resources/dream.xml" );
Dmitry-Me46b70ce2017-07-10 17:54:24 +03001452 XMLTest( "Load dream.xml", false, doc.Error() );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001453 XMLTest( "Document has something to Clear()", false, doc.NoChildren() );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001454 doc.Clear();
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001455 XMLTest( "Document Clear()'s", true, doc.NoChildren() );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001456 }
1457
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001458 // ----------- Whitespace ------------
1459 {
1460 const char* xml = "<element>"
1461 "<a> This \nis &apos; text &apos; </a>"
1462 "<b> This is &apos; text &apos; \n</b>"
1463 "<c>This is &apos; \n\n text &apos;</c>"
1464 "</element>";
1465 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1466 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001467 XMLTest( "Parse with whitespace collapsing and &apos", false, doc.Error() );
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001468
1469 const XMLElement* element = doc.FirstChildElement();
1470 for( const XMLElement* parent = element->FirstChildElement();
1471 parent;
1472 parent = parent->NextSiblingElement() )
1473 {
1474 XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
1475 }
1476 }
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001477
Lee Thomasonae9ab072012-10-24 10:17:53 -07001478#if 0
1479 {
1480 // Passes if assert doesn't fire.
1481 XMLDocument xmlDoc;
1482
1483 xmlDoc.NewDeclaration();
1484 xmlDoc.NewComment("Configuration file");
1485
1486 XMLElement *root = xmlDoc.NewElement("settings");
1487 root->SetAttribute("version", 2);
1488 }
1489#endif
1490
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001491 {
1492 const char* xml = "<element> </element>";
1493 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1494 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001495 XMLTest( "Parse with all whitespaces", false, doc.Error() );
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001496 XMLTest( "Whitespace all space", true, 0 == doc.FirstChildElement()->FirstChild() );
1497 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001498
Lee Thomason5b0a6772012-11-19 13:54:42 -08001499 {
1500 // An assert should not fire.
1501 const char* xml = "<element/>";
1502 XMLDocument doc;
1503 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001504 XMLTest( "Parse with self-closed element", false, doc.Error() );
Lee Thomason5b0a6772012-11-19 13:54:42 -08001505 XMLElement* ele = doc.NewElement( "unused" ); // This will get cleaned up with the 'doc' going out of scope.
1506 XMLTest( "Tracking unused elements", true, ele != 0, false );
1507 }
1508
Lee Thomasona6412ac2012-12-13 15:39:11 -08001509
1510 {
1511 const char* xml = "<parent><child>abc</child></parent>";
1512 XMLDocument doc;
1513 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001514 XMLTest( "Parse for printing of sub-element", false, doc.Error() );
Lee Thomasona6412ac2012-12-13 15:39:11 -08001515 XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child");
1516
1517 XMLPrinter printer;
1518 ele->Accept( &printer );
1519 XMLTest( "Printing of sub-element", "<child>abc</child>\n", printer.CStr(), false );
1520 }
1521
1522
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001523 {
1524 XMLDocument doc;
1525 XMLError error = doc.LoadFile( "resources/empty.xml" );
1526 XMLTest( "Loading an empty file", XML_ERROR_EMPTY_DOCUMENT, error );
Lee Thomason331596e2014-09-11 14:56:43 -07001527 XMLTest( "Loading an empty file and ErrorName as string", "XML_ERROR_EMPTY_DOCUMENT", doc.ErrorName() );
Lee Thomasonc7556672014-09-14 12:39:42 -07001528 doc.PrintError();
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001529 }
1530
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001531 {
1532 // BOM preservation
1533 static const char* xml_bom_preservation = "\xef\xbb\xbf<element/>\n";
1534 {
1535 XMLDocument doc;
Lee Thomason85536252016-06-04 19:10:53 -07001536 XMLTest( "BOM preservation (parse)", XML_SUCCESS, doc.Parse( xml_bom_preservation ), false );
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001537 XMLPrinter printer;
1538 doc.Print( &printer );
1539
1540 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1541 doc.SaveFile( "resources/bomtest.xml" );
Dmitry-Me46b70ce2017-07-10 17:54:24 +03001542 XMLTest( "Save bomtest.xml", false, doc.Error() );
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001543 }
1544 {
1545 XMLDocument doc;
1546 doc.LoadFile( "resources/bomtest.xml" );
Dmitry-Me46b70ce2017-07-10 17:54:24 +03001547 XMLTest( "Load bomtest.xml", false, doc.Error() );
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001548 XMLTest( "BOM preservation (load)", true, doc.HasBOM(), false );
1549
1550 XMLPrinter printer;
1551 doc.Print( &printer );
1552 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1553 }
1554 }
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001555
Michael Daumlinged523282013-10-23 07:47:29 +02001556 {
1557 // Insertion with Removal
1558 const char* xml = "<?xml version=\"1.0\" ?>"
1559 "<root>"
1560 "<one>"
1561 "<subtree>"
1562 "<elem>element 1</elem>text<!-- comment -->"
1563 "</subtree>"
1564 "</one>"
1565 "<two/>"
1566 "</root>";
1567 const char* xmlInsideTwo = "<?xml version=\"1.0\" ?>"
1568 "<root>"
1569 "<one/>"
1570 "<two>"
1571 "<subtree>"
1572 "<elem>element 1</elem>text<!-- comment -->"
1573 "</subtree>"
1574 "</two>"
1575 "</root>";
1576 const char* xmlAfterOne = "<?xml version=\"1.0\" ?>"
1577 "<root>"
1578 "<one/>"
1579 "<subtree>"
1580 "<elem>element 1</elem>text<!-- comment -->"
1581 "</subtree>"
1582 "<two/>"
1583 "</root>";
1584 const char* xmlAfterTwo = "<?xml version=\"1.0\" ?>"
1585 "<root>"
1586 "<one/>"
1587 "<two/>"
1588 "<subtree>"
1589 "<elem>element 1</elem>text<!-- comment -->"
1590 "</subtree>"
1591 "</root>";
1592
1593 XMLDocument doc;
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001594 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001595 XMLTest( "Insertion with removal parse round 1", false, doc.Error() );
Michael Daumlinged523282013-10-23 07:47:29 +02001596 XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1597 XMLElement* two = doc.RootElement()->FirstChildElement("two");
1598 two->InsertFirstChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001599 XMLPrinter printer1(0, true);
1600 doc.Accept(&printer1);
1601 XMLTest("Move node from within <one> to <two>", xmlInsideTwo, printer1.CStr());
Michael Daumlinged523282013-10-23 07:47:29 +02001602
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001603 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001604 XMLTest( "Insertion with removal parse round 2", false, doc.Error() );
Michael Daumlinged523282013-10-23 07:47:29 +02001605 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1606 two = doc.RootElement()->FirstChildElement("two");
1607 doc.RootElement()->InsertAfterChild(two, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001608 XMLPrinter printer2(0, true);
1609 doc.Accept(&printer2);
1610 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer2.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001611
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001612 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001613 XMLTest( "Insertion with removal parse round 3", false, doc.Error() );
Michael Daumlinged523282013-10-23 07:47:29 +02001614 XMLNode* one = doc.RootElement()->FirstChildElement("one");
1615 subtree = one->FirstChildElement("subtree");
1616 doc.RootElement()->InsertAfterChild(one, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001617 XMLPrinter printer3(0, true);
1618 doc.Accept(&printer3);
1619 XMLTest("Move node from within <one> after <one>", xmlAfterOne, printer3.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001620
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001621 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001622 XMLTest( "Insertion with removal parse round 4", false, doc.Error() );
Michael Daumlinged523282013-10-23 07:47:29 +02001623 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1624 two = doc.RootElement()->FirstChildElement("two");
1625 doc.RootElement()->InsertEndChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001626 XMLPrinter printer4(0, true);
1627 doc.Accept(&printer4);
1628 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer4.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001629 }
1630
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001631 {
1632 const char* xml = "<svg width = \"128\" height = \"128\">"
1633 " <text> </text>"
1634 "</svg>";
1635 XMLDocument doc;
1636 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001637 XMLTest( "Parse svg with text", false, doc.Error() );
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001638 doc.Print();
1639 }
1640
Lee Thomason92e521b2014-11-15 17:45:51 -08001641 {
1642 // Test that it doesn't crash.
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001643 const char* xml = "<?xml version=\"1.0\"?><root><sample><field0><1</field0><field1>2</field1></sample></root>";
1644 XMLDocument doc;
1645 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001646 XMLTest( "Parse root-sample-field0", true, doc.Error() );
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001647 doc.PrintError();
Lee Thomason92e521b2014-11-15 17:45:51 -08001648 }
1649
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001650#if 1
1651 // the question being explored is what kind of print to use:
1652 // https://github.com/leethomason/tinyxml2/issues/63
1653 {
1654 //const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9' attrC='1.0e-10' attrD='1001000000.000000' attrE='0.1234567890123456789'/>";
1655 const char* xml = "<element/>";
1656 XMLDocument doc;
1657 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001658 XMLTest( "Parse self-closed empty element", false, doc.Error() );
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001659 doc.FirstChildElement()->SetAttribute( "attrA-f64", 123456789.123456789 );
1660 doc.FirstChildElement()->SetAttribute( "attrB-f64", 1.001e9 );
1661 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e9 );
1662 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e20 );
1663 doc.FirstChildElement()->SetAttribute( "attrD-f64", 1.0e-10 );
1664 doc.FirstChildElement()->SetAttribute( "attrD-f64", 0.123456789 );
1665
1666 doc.FirstChildElement()->SetAttribute( "attrA-f32", 123456789.123456789f );
1667 doc.FirstChildElement()->SetAttribute( "attrB-f32", 1.001e9f );
1668 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e9f );
1669 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e20f );
1670 doc.FirstChildElement()->SetAttribute( "attrD-f32", 1.0e-10f );
1671 doc.FirstChildElement()->SetAttribute( "attrD-f32", 0.123456789f );
1672
1673 doc.Print();
1674
1675 /* The result of this test is platform, compiler, and library version dependent. :("
1676 XMLPrinter printer;
1677 doc.Print( &printer );
1678 XMLTest( "Float and double formatting.",
1679 "<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",
1680 printer.CStr(),
1681 true );
1682 */
1683 }
1684#endif
Lee Thomasonf07b9522014-10-30 13:25:12 -07001685
1686 {
1687 // Issue #184
1688 // If it doesn't assert, it passes. Caused by objects
1689 // getting created during parsing which are then
1690 // inaccessible in the memory pools.
Dmitry-Me5d1aec12017-06-28 14:51:17 +03001691 const char* xmlText = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>";
Lee Thomasonf07b9522014-10-30 13:25:12 -07001692 {
1693 XMLDocument doc;
Dmitry-Me5d1aec12017-06-28 14:51:17 +03001694 doc.Parse(xmlText);
Dmitry-Me68578f42017-07-03 18:21:23 +03001695 XMLTest( "Parse hex no closing tag round 1", true, doc.Error() );
Lee Thomasonf07b9522014-10-30 13:25:12 -07001696 }
1697 {
1698 XMLDocument doc;
Dmitry-Me5d1aec12017-06-28 14:51:17 +03001699 doc.Parse(xmlText);
Dmitry-Me68578f42017-07-03 18:21:23 +03001700 XMLTest( "Parse hex no closing tag round 2", true, doc.Error() );
Lee Thomasonf07b9522014-10-30 13:25:12 -07001701 doc.Clear();
1702 }
1703 }
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001704
1705 {
1706 // If this doesn't assert in DEBUG, all is well.
1707 tinyxml2::XMLDocument doc;
1708 tinyxml2::XMLElement *pRoot = doc.NewElement("Root");
1709 doc.DeleteNode(pRoot);
1710 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001711
Dmitry-Me8b67d742014-12-22 11:35:12 +03001712 {
1713 // Should not assert in DEBUG
1714 XMLPrinter printer;
1715 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001716
Dmitry-Me6f51c802015-03-14 13:25:03 +03001717 {
1718 // Issue 291. Should not crash
1719 const char* xml = "&#0</a>";
1720 XMLDocument doc;
1721 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001722 XMLTest( "Parse hex with closing tag", false, doc.Error() );
Dmitry-Me6f51c802015-03-14 13:25:03 +03001723
1724 XMLPrinter printer;
1725 doc.Print( &printer );
1726 }
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001727 {
1728 // Issue 299. Can print elements that are not linked in.
1729 // Will crash if issue not fixed.
1730 XMLDocument doc;
1731 XMLElement* newElement = doc.NewElement( "printme" );
1732 XMLPrinter printer;
1733 newElement->Accept( &printer );
Dmitry-Me5daa54c2015-04-08 17:45:07 +03001734 // Delete the node to avoid possible memory leak report in debug output
1735 doc.DeleteNode( newElement );
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001736 }
Lee Thomasonf6577832015-03-26 11:18:21 -07001737 {
Ant Mitchell189198f2015-03-24 16:20:36 +00001738 // Issue 302. Clear errors from LoadFile/SaveFile
1739 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001740 XMLTest( "Issue 302. Should be no error initially", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001741 doc.SaveFile( "./no/such/path/pretty.xml" );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001742 XMLTest( "Issue 302. Fail to save", "XML_ERROR_FILE_COULD_NOT_BE_OPENED", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001743 doc.SaveFile( "./resources/out/compact.xml", true );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001744 XMLTest( "Issue 302. Subsequent success in saving", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001745 }
Dmitry-Me6f51c802015-03-14 13:25:03 +03001746
Dmitry-Med9852a52015-03-25 10:17:49 +03001747 {
1748 // If a document fails to load then subsequent
1749 // successful loads should clear the error
1750 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001751 XMLTest( "Should be no error initially", false, doc.Error() );
Dmitry-Med9852a52015-03-25 10:17:49 +03001752 doc.LoadFile( "resources/no-such-file.xml" );
1753 XMLTest( "No such file - should fail", true, doc.Error() );
1754
1755 doc.LoadFile( "resources/dream.xml" );
1756 XMLTest( "Error should be cleared", false, doc.Error() );
1757 }
Sarat Addepalli8e85afa2015-05-19 09:07:03 +05301758
Sarat Addepalli2bb6bb52015-05-18 09:16:34 +05301759 {
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001760 // Check that declarations are allowed only at beginning of document
Lee Thomason85492022015-05-22 11:07:45 -07001761 const char* xml0 = "<?xml version=\"1.0\" ?>"
1762 " <!-- xml version=\"1.1\" -->"
1763 "<first />";
1764 const char* xml1 = "<?xml version=\"1.0\" ?>"
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001765 "<?xml-stylesheet type=\"text/xsl\" href=\"Anything.xsl\"?>"
Lee Thomason85492022015-05-22 11:07:45 -07001766 "<first />";
1767 const char* xml2 = "<first />"
1768 "<?xml version=\"1.0\" ?>";
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001769 const char* xml3 = "<first></first>"
1770 "<?xml version=\"1.0\" ?>";
1771
1772 const char* xml4 = "<first><?xml version=\"1.0\" ?></first>";
1773
Lee Thomason85492022015-05-22 11:07:45 -07001774 XMLDocument doc;
1775 doc.Parse(xml0);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001776 XMLTest("Test that the code changes do not affect normal parsing", false, doc.Error() );
Lee Thomason85492022015-05-22 11:07:45 -07001777 doc.Parse(xml1);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001778 XMLTest("Test that the second declaration is allowed", false, doc.Error() );
Lee Thomason85492022015-05-22 11:07:45 -07001779 doc.Parse(xml2);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001780 XMLTest("Test that declaration after a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001781 doc.Parse(xml3);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001782 XMLTest("Test that declaration after a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001783 doc.Parse(xml4);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001784 XMLTest("Test that declaration inside a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );
Sarat Addepalli2bb6bb52015-05-18 09:16:34 +05301785 }
Dmitry-Med9852a52015-03-25 10:17:49 +03001786
Lee Thomason85492022015-05-22 11:07:45 -07001787 {
1788 // No matter - before or after successfully parsing a text -
1789 // calling XMLDocument::Value() causes an assert in debug.
1790 const char* validXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
1791 "<first />"
1792 "<second />";
1793 XMLDocument* doc = new XMLDocument();
1794 XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
1795 doc->Parse( validXml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001796 XMLTest( "Parse to test XMLDocument::Value()", false, doc->Error());
Lee Thomason85492022015-05-22 11:07:45 -07001797 XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
1798 delete doc;
1799 }
1800
Dmitry-Mea1beddf2015-05-26 16:19:21 +03001801 {
1802 XMLDocument doc;
1803 for( int i = 0; i < XML_ERROR_COUNT; i++ ) {
kezenatorec694152016-11-26 17:21:43 +10001804 doc.SetError( (XMLError)i, 0, 0, 0 );
Dmitry-Mea1beddf2015-05-26 16:19:21 +03001805 doc.ErrorName();
1806 }
1807 }
1808
Lee Thomason816d3fa2017-06-05 14:35:55 -07001809 {
Lee Thomasonb754ddf2017-06-14 15:02:38 -07001810 // Evil memory leaks.
1811 // If an XMLElement (etc) is allocated via NewElement() (etc.)
1812 // and NOT added to the XMLDocument, what happens?
1813 //
1814 // Previously (buggy):
1815 // The memory would be free'd when the XMLDocument is
1816 // destructed. But the destructor wasn't called, so that
1817 // memory allocated by the XMLElement would not be free'd.
1818 // In practice this meant strings allocated by the XMLElement
1819 // would leak. An edge case, but annoying.
1820 // Now:
1821 // The destructor is called. But the list of unlinked nodes
1822 // has to be tracked. This has a minor performance impact
1823 // that can become significant if you have a lot. (But why
1824 // would you do that?)
1825 // The only way to see this bug is in a leak tracker. This
1826 // is compiled in by default on Windows Debug.
Lee Thomason816d3fa2017-06-05 14:35:55 -07001827 {
1828 XMLDocument doc;
1829 doc.NewElement("LEAK 1");
1830 }
1831 {
1832 XMLDocument doc;
1833 XMLElement* ele = doc.NewElement("LEAK 2");
1834 doc.DeleteNode(ele);
1835 }
1836 }
1837
Lee Thomason224ef772017-06-16 09:45:26 -07001838 {
1839 // Crashing reported via email.
1840 const char* xml =
1841 "<playlist id='playlist1'>"
Lee Thomason82bb0742017-06-16 09:48:20 -07001842 "<property name='track_name'>voice</property>"
1843 "<property name='audio_track'>1</property>"
1844 "<entry out = '604' producer = '4_playlist1' in = '0' />"
1845 "<blank length = '1' />"
1846 "<entry out = '1625' producer = '3_playlist' in = '0' />"
1847 "<blank length = '2' />"
1848 "<entry out = '946' producer = '2_playlist1' in = '0' />"
1849 "<blank length = '1' />"
1850 "<entry out = '128' producer = '1_playlist1' in = '0' />"
Lee Thomason224ef772017-06-16 09:45:26 -07001851 "</playlist>";
Lee Thomason82bb0742017-06-16 09:48:20 -07001852
Lee Thomason224ef772017-06-16 09:45:26 -07001853 // It's not a good idea to delete elements as you walk the
1854 // list. I'm not sure this technically should work; but it's
1855 // an interesting test case.
1856 XMLDocument doc;
1857 XMLError err = doc.Parse(xml);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001858 XMLTest("Crash bug parsing", XML_SUCCESS, err );
Dmitry-Meaea64c42017-06-20 18:20:15 +03001859
1860 XMLElement* playlist = doc.FirstChildElement("playlist");
Lee Thomason224ef772017-06-16 09:45:26 -07001861 XMLTest("Crash bug parsing", true, playlist != 0);
1862
1863 tinyxml2::XMLElement* entry = playlist->FirstChildElement("entry");
1864 XMLTest("Crash bug parsing", true, entry != 0);
1865 while (entry) {
1866 tinyxml2::XMLElement* todelete = entry;
1867 entry = entry->NextSiblingElement("entry");
1868 playlist->DeleteChild(todelete);
1869 };
1870 tinyxml2::XMLElement* blank = playlist->FirstChildElement("blank");
1871 while (blank) {
1872 tinyxml2::XMLElement* todelete = blank;
1873 blank = blank->NextSiblingElement("blank");
1874 playlist->DeleteChild(todelete);
1875 };
1876
1877 tinyxml2::XMLPrinter printer;
1878 playlist->Accept(&printer);
1879 printf("%s\n", printer.CStr());
1880
Lee Thomason82bb0742017-06-16 09:48:20 -07001881 // No test; it only need to not crash.
1882 // Still, wrap it up with a sanity check
1883 int nProperty = 0;
1884 for (const XMLElement* p = playlist->FirstChildElement("property"); p; p = p->NextSiblingElement("property")) {
1885 nProperty++;
1886 }
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001887 XMLTest("Crash bug parsing", 2, nProperty);
Lee Thomason224ef772017-06-16 09:45:26 -07001888 }
1889
kezenatorec694152016-11-26 17:21:43 +10001890 // ----------- Line Number Tracking --------------
1891 {
Lee Thomasone90e9012016-12-24 07:34:39 -08001892 struct TestUtil: XMLVisitor
kezenatorec694152016-11-26 17:21:43 +10001893 {
1894 void TestParseError(const char *testString, const char *docStr, XMLError expected_error, int expectedLine)
1895 {
1896 XMLDocument doc;
1897 XMLError err = doc.Parse(docStr);
1898
1899 XMLTest(testString, true, doc.Error());
1900 XMLTest(testString, expected_error, err);
1901 XMLTest(testString, expectedLine, doc.GetErrorLineNum());
1902 };
1903
1904 void TestStringLines(const char *testString, const char *docStr, const char *expectedLines)
1905 {
1906 XMLDocument doc;
1907 doc.Parse(docStr);
1908 XMLTest(testString, false, doc.Error());
1909 TestDocLines(testString, doc, expectedLines);
1910 }
1911
1912 void TestFileLines(const char *testString, const char *file_name, const char *expectedLines)
1913 {
1914 XMLDocument doc;
1915 doc.LoadFile(file_name);
1916 XMLTest(testString, false, doc.Error());
1917 TestDocLines(testString, doc, expectedLines);
1918 }
1919
1920 private:
1921 DynArray<char, 10> str;
1922
1923 void Push(char type, int lineNum)
1924 {
1925 str.Push(type);
1926 str.Push(char('0' + (lineNum / 10)));
1927 str.Push(char('0' + (lineNum % 10)));
1928 }
1929
1930 bool VisitEnter(const XMLDocument& doc)
1931 {
kezenator19d8ea82016-11-29 19:50:27 +10001932 Push('D', doc.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001933 return true;
1934 }
1935 bool VisitEnter(const XMLElement& element, const XMLAttribute* firstAttribute)
1936 {
kezenator19d8ea82016-11-29 19:50:27 +10001937 Push('E', element.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001938 for (const XMLAttribute *attr = firstAttribute; attr != 0; attr = attr->Next())
kezenator19d8ea82016-11-29 19:50:27 +10001939 Push('A', attr->GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001940 return true;
1941 }
1942 bool Visit(const XMLDeclaration& declaration)
1943 {
kezenator19d8ea82016-11-29 19:50:27 +10001944 Push('L', declaration.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001945 return true;
1946 }
1947 bool Visit(const XMLText& text)
1948 {
kezenator19d8ea82016-11-29 19:50:27 +10001949 Push('T', text.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001950 return true;
1951 }
1952 bool Visit(const XMLComment& comment)
1953 {
kezenator19d8ea82016-11-29 19:50:27 +10001954 Push('C', comment.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001955 return true;
1956 }
1957 bool Visit(const XMLUnknown& unknown)
1958 {
kezenator19d8ea82016-11-29 19:50:27 +10001959 Push('U', unknown.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001960 return true;
1961 }
1962
1963 void TestDocLines(const char *testString, XMLDocument &doc, const char *expectedLines)
1964 {
1965 str.Clear();
1966 doc.Accept(this);
1967 str.Push(0);
1968 XMLTest(testString, expectedLines, str.Mem());
1969 }
Lee Thomasone90e9012016-12-24 07:34:39 -08001970 } tester;
kezenatorec694152016-11-26 17:21:43 +10001971
Lee Thomasone90e9012016-12-24 07:34:39 -08001972 tester.TestParseError("ErrorLine-Parsing", "\n<root>\n foo \n<unclosed/>", XML_ERROR_PARSING, 2);
1973 tester.TestParseError("ErrorLine-Declaration", "<root>\n<?xml version=\"1.0\"?>", XML_ERROR_PARSING_DECLARATION, 2);
1974 tester.TestParseError("ErrorLine-Mismatch", "\n<root>\n</mismatch>", XML_ERROR_MISMATCHED_ELEMENT, 2);
1975 tester.TestParseError("ErrorLine-CData", "\n<root><![CDATA[ \n foo bar \n", XML_ERROR_PARSING_CDATA, 2);
1976 tester.TestParseError("ErrorLine-Text", "\n<root>\n foo bar \n", XML_ERROR_PARSING_TEXT, 3);
1977 tester.TestParseError("ErrorLine-Comment", "\n<root>\n<!-- >\n", XML_ERROR_PARSING_COMMENT, 3);
1978 tester.TestParseError("ErrorLine-Declaration", "\n<root>\n<? >\n", XML_ERROR_PARSING_DECLARATION, 3);
1979 tester.TestParseError("ErrorLine-Unknown", "\n<root>\n<! \n", XML_ERROR_PARSING_UNKNOWN, 3);
1980 tester.TestParseError("ErrorLine-Element", "\n<root>\n<unclosed \n", XML_ERROR_PARSING_ELEMENT, 3);
1981 tester.TestParseError("ErrorLine-Attribute", "\n<root>\n<unclosed \n att\n", XML_ERROR_PARSING_ATTRIBUTE, 4);
1982 tester.TestParseError("ErrorLine-ElementClose", "\n<root>\n<unclosed \n/unexpected", XML_ERROR_PARSING_ELEMENT, 3);
kezenatorec694152016-11-26 17:21:43 +10001983
Lee Thomasone90e9012016-12-24 07:34:39 -08001984 tester.TestStringLines(
kezenatorec694152016-11-26 17:21:43 +10001985 "LineNumbers-String",
Lee Thomasone90e9012016-12-24 07:34:39 -08001986
1987 "<?xml version=\"1.0\"?>\n" // 1 Doc, DecL
1988 "<root a='b' \n" // 2 Element Attribute
1989 "c='d'> d <blah/> \n" // 3 Attribute Text Element
1990 "newline in text \n" // 4 Text
1991 "and second <zxcv/><![CDATA[\n" // 5 Element Text
1992 " cdata test ]]><!-- comment -->\n" // 6 Comment
1993 "<! unknown></root>", // 7 Unknown
1994
kezenatorec694152016-11-26 17:21:43 +10001995 "D01L01E02A02A03T03E03T04E05T05C06U07");
1996
Lee Thomasone90e9012016-12-24 07:34:39 -08001997 tester.TestStringLines(
kezenatorec694152016-11-26 17:21:43 +10001998 "LineNumbers-CRLF",
Lee Thomasone90e9012016-12-24 07:34:39 -08001999
2000 "\r\n" // 1 Doc (arguably should be line 2)
2001 "<?xml version=\"1.0\"?>\n" // 2 DecL
2002 "<root>\r\n" // 3 Element
2003 "\n" // 4
2004 "text contining new line \n" // 5 Text
2005 " and also containing crlf \r\n" // 6
2006 "<sub><![CDATA[\n" // 7 Element Text
2007 "cdata containing new line \n" // 8
2008 " and also containing cflr\r\n" // 9
2009 "]]></sub><sub2/></root>", // 10 Element
2010
kezenatorec694152016-11-26 17:21:43 +10002011 "D01L02E03T05E07T07E10");
2012
Lee Thomasone90e9012016-12-24 07:34:39 -08002013 tester.TestFileLines(
kezenatorec694152016-11-26 17:21:43 +10002014 "LineNumbers-File",
2015 "resources/utf8test.xml",
2016 "D01L01E02E03A03A03T03E04A04A04T04E05A05A05T05E06A06A06T06E07A07A07T07E08A08A08T08E09T09E10T10");
2017 }
2018
Lee Thomason85492022015-05-22 11:07:45 -07002019 // ----------- Performance tracking --------------
Lee Thomason6f381b72012-03-02 12:59:39 -08002020 {
2021#if defined( _MSC_VER )
2022 __int64 start, end, freq;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002023 QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
Lee Thomason6f381b72012-03-02 12:59:39 -08002024#endif
2025
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002026 FILE* perfFP = fopen("resources/dream.xml", "r");
Dmitry-Med1b82822017-07-04 18:02:54 +03002027 XMLTest("Open dream.xml", true, perfFP != 0);
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002028 fseek(perfFP, 0, SEEK_END);
Armagetron3c21d6f2016-10-13 13:31:23 +02002029 long size = ftell(perfFP);
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002030 fseek(perfFP, 0, SEEK_SET);
Lee Thomason6f381b72012-03-02 12:59:39 -08002031
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002032 char* mem = new char[size + 1];
Dmitry-Med1b82822017-07-04 18:02:54 +03002033 memset(mem, 0xfe, size);
Lee Thomasone4dc7212017-07-06 17:05:01 -07002034 size_t bytesRead = fread(mem, 1, size, perfFP);
2035 XMLTest("Read dream.xml", true, uint32_t(size) >= uint32_t(bytesRead));
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002036 fclose(perfFP);
Lee Thomason6f381b72012-03-02 12:59:39 -08002037 mem[size] = 0;
2038
2039#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002040 QueryPerformanceCounter((LARGE_INTEGER*)&start);
Lee Thomason6f381b72012-03-02 12:59:39 -08002041#else
2042 clock_t cstart = clock();
2043#endif
Dmitry-Me68578f42017-07-03 18:21:23 +03002044 bool parseDreamXmlFailed = false;
Lee Thomason6f381b72012-03-02 12:59:39 -08002045 static const int COUNT = 10;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002046 for (int i = 0; i < COUNT; ++i) {
Lee Thomason6f381b72012-03-02 12:59:39 -08002047 XMLDocument doc;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002048 doc.Parse(mem);
Dmitry-Me68578f42017-07-03 18:21:23 +03002049 parseDreamXmlFailed = parseDreamXmlFailed || doc.Error();
Lee Thomason6f381b72012-03-02 12:59:39 -08002050 }
Dmitry-Me68578f42017-07-03 18:21:23 +03002051 XMLTest( "Parse dream.xml", false, parseDreamXmlFailed );
Lee Thomason6f381b72012-03-02 12:59:39 -08002052#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002053 QueryPerformanceCounter((LARGE_INTEGER*)&end);
Lee Thomason6f381b72012-03-02 12:59:39 -08002054#else
2055 clock_t cend = clock();
2056#endif
2057
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002058 delete[] mem;
Lee Thomason6f381b72012-03-02 12:59:39 -08002059
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07002060 static const char* note =
Lee Thomason6f381b72012-03-02 12:59:39 -08002061#ifdef DEBUG
2062 "DEBUG";
2063#else
2064 "Release";
2065#endif
2066
2067#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002068 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 -08002069#else
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002070 printf("\nParsing %s of dream.xml: %.3f milli-seconds\n", note, (double)(cend - cstart) / (double)COUNT);
Lee Thomason6f381b72012-03-02 12:59:39 -08002071#endif
2072 }
2073
Lee Thomason (grinliz)7ca55582012-03-07 21:54:57 -08002074 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07002075 _CrtMemCheckpoint( &endMemState );
Lee Thomason1ff38e02012-02-14 18:18:16 -08002076
2077 _CrtMemState diffMemState;
2078 _CrtMemDifference( &diffMemState, &startMemState, &endMemState );
2079 _CrtMemDumpStatistics( &diffMemState );
Dmitry-Meed785702017-06-15 13:39:53 +03002080
2081 {
2082 int leaksBeforeExit = _CrtDumpMemoryLeaks();
2083 XMLTest( "No leaks before exit?", FALSE, leaksBeforeExit );
2084 }
Lee Thomason1ff38e02012-02-14 18:18:16 -08002085 #endif
2086
2087 printf ("\nPass %d, Fail %d\n", gPass, gFail);
Lee Thomason (grinliz)db304252013-07-31 12:24:52 -07002088
2089 return gFail;
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -08002090}