blob: b1975d4b5632c15a108979042992e50a253a180d [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"
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -07008#include <cstdlib>
9#include <cstring>
10#include <ctime>
U-Lama\Leee13c3e62011-12-28 14:36:55 -080011
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080012#if defined( _MSC_VER )
Lee Thomason1ff38e02012-02-14 18:18:16 -080013 #include <crtdbg.h>
Lee Thomason6f381b72012-03-02 12:59:39 -080014 #define WIN32_LEAN_AND_MEAN
15 #include <windows.h>
Lee Thomason1ff38e02012-02-14 18:18:16 -080016 _CrtMemState startMemState;
Lee Thomason53858b42017-06-01 19:09:16 -070017 _CrtMemState endMemState;
Lee Thomason1ff38e02012-02-14 18:18:16 -080018#endif
Lee Thomasone9ecdab2012-02-13 18:11:20 -080019
U-Lama\Leee13c3e62011-12-28 14:36:55 -080020using namespace tinyxml2;
Anton Indrawan8a0006c2014-11-20 18:27:07 +010021using namespace std;
Lee Thomasonec5a7b42012-02-13 18:16:52 -080022int gPass = 0;
23int gFail = 0;
24
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -080025
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070026bool XMLTest (const char* testString, const char* expected, const char* found, bool echo=true, bool extraNL=false )
Lee Thomason1ff38e02012-02-14 18:18:16 -080027{
Sarat Addepalli13b2d732015-05-19 12:44:57 +053028 bool pass;
29 if ( !expected && !found )
30 pass = true;
31 else if ( !expected || !found )
32 pass = false;
Sarat Addepallid608c562015-05-20 10:19:00 +053033 else
34 pass = !strcmp( expected, found );
Lee Thomason1ff38e02012-02-14 18:18:16 -080035 if ( pass )
36 printf ("[pass]");
37 else
38 printf ("[fail]");
39
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070040 if ( !echo ) {
Lee Thomason1ff38e02012-02-14 18:18:16 -080041 printf (" %s\n", testString);
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070042 }
43 else {
44 if ( extraNL ) {
45 printf( " %s\n", testString );
46 printf( "%s\n", expected );
47 printf( "%s\n", found );
48 }
49 else {
50 printf (" %s [%s][%s]\n", testString, expected, found);
51 }
52 }
Lee Thomason1ff38e02012-02-14 18:18:16 -080053
54 if ( pass )
55 ++gPass;
56 else
57 ++gFail;
58 return pass;
59}
60
kezenator5a700712016-11-26 13:54:42 +100061bool XMLTest(const char* testString, XMLError expected, XMLError found, bool echo = true, bool extraNL = false)
62{
Lee Thomasone90e9012016-12-24 07:34:39 -080063 return XMLTest(testString, XMLDocument::ErrorIDToName(expected), XMLDocument::ErrorIDToName(found), echo, extraNL);
kezenator5a700712016-11-26 13:54:42 +100064}
65
66bool XMLTest(const char* testString, bool expected, bool found, bool echo = true, bool extraNL = false)
67{
68 return XMLTest(testString, expected ? "true" : "false", found ? "true" : "false", echo, extraNL);
69}
Lee Thomason1ff38e02012-02-14 18:18:16 -080070
Lee Thomason21be8822012-07-15 17:27:22 -070071template< class T > bool XMLTest( const char* testString, T expected, T found, bool echo=true )
Lee Thomason1ff38e02012-02-14 18:18:16 -080072{
73 bool pass = ( expected == found );
74 if ( pass )
75 printf ("[pass]");
76 else
77 printf ("[fail]");
78
U-Stream\Lee09a11c52012-02-17 08:31:16 -080079 if ( !echo )
Lee Thomason1ff38e02012-02-14 18:18:16 -080080 printf (" %s\n", testString);
81 else
Lee Thomasonc8312792012-07-16 12:44:41 -070082 printf (" %s [%d][%d]\n", testString, static_cast<int>(expected), static_cast<int>(found) );
Lee Thomason1ff38e02012-02-14 18:18:16 -080083
84 if ( pass )
85 ++gPass;
86 else
87 ++gFail;
88 return pass;
89}
Lee Thomasonec5a7b42012-02-13 18:16:52 -080090
U-Lama\Leee13c3e62011-12-28 14:36:55 -080091
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -080092void NullLineEndings( char* p )
93{
94 while( p && *p ) {
95 if ( *p == '\n' || *p == '\r' ) {
96 *p = 0;
97 return;
98 }
99 ++p;
100 }
101}
102
103
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700104int example_1()
105{
106 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300107 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700108
109 return doc.ErrorID();
110}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200111/** @page Example-1 Load an XML File
112 * @dontinclude ./xmltest.cpp
113 * Basic XML file loading.
114 * The basic syntax to load an XML file from
115 * disk and check for an error. (ErrorID()
116 * will return 0 for no error.)
117 * @skip example_1()
118 * @until }
119 */
120
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700121
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700122int example_2()
123{
124 static const char* xml = "<element/>";
125 XMLDocument doc;
126 doc.Parse( xml );
127
128 return doc.ErrorID();
129}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200130/** @page Example-2 Parse an XML from char buffer
131 * @dontinclude ./xmltest.cpp
132 * Basic XML string parsing.
133 * The basic syntax to parse an XML for
134 * a char* and check for an error. (ErrorID()
135 * will return 0 for no error.)
136 * @skip example_2()
137 * @until }
138 */
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700139
140
141int example_3()
142{
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700143 static const char* xml =
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700144 "<?xml version=\"1.0\"?>"
145 "<!DOCTYPE PLAY SYSTEM \"play.dtd\">"
146 "<PLAY>"
147 "<TITLE>A Midsummer Night's Dream</TITLE>"
148 "</PLAY>";
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700149
150 XMLDocument doc;
151 doc.Parse( xml );
152
153 XMLElement* titleElement = doc.FirstChildElement( "PLAY" )->FirstChildElement( "TITLE" );
154 const char* title = titleElement->GetText();
155 printf( "Name of play (1): %s\n", title );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700156
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700157 XMLText* textNode = titleElement->FirstChild()->ToText();
158 title = textNode->Value();
159 printf( "Name of play (2): %s\n", title );
160
161 return doc.ErrorID();
162}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200163/** @page Example-3 Get information out of XML
164 @dontinclude ./xmltest.cpp
165 In this example, we navigate a simple XML
166 file, and read some interesting text. Note
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700167 that this example doesn't use error
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200168 checking; working code should check for null
169 pointers when walking an XML tree, or use
170 XMLHandle.
171
172 (The XML is an excerpt from "dream.xml").
173
174 @skip example_3()
175 @until </PLAY>";
176
177 The structure of the XML file is:
178
179 <ul>
180 <li>(declaration)</li>
181 <li>(dtd stuff)</li>
182 <li>Element "PLAY"</li>
183 <ul>
184 <li>Element "TITLE"</li>
185 <ul>
186 <li>Text "A Midsummer Night's Dream"</li>
187 </ul>
188 </ul>
189 </ul>
190
191 For this example, we want to print out the
192 title of the play. The text of the title (what
193 we want) is child of the "TITLE" element which
194 is a child of the "PLAY" element.
195
196 We want to skip the declaration and dtd, so the
197 method FirstChildElement() is a good choice. The
198 FirstChildElement() of the Document is the "PLAY"
199 Element, the FirstChildElement() of the "PLAY" Element
200 is the "TITLE" Element.
201
202 @until ( "TITLE" );
203
204 We can then use the convenience function GetText()
205 to get the title of the play.
206
207 @until title );
208
209 Text is just another Node in the XML DOM. And in
210 fact you should be a little cautious with it, as
211 text nodes can contain elements.
212
213 @verbatim
214 Consider: A Midsummer Night's <b>Dream</b>
215 @endverbatim
216
217 It is more correct to actually query the Text Node
218 if in doubt:
219
220 @until title );
221
222 Noting that here we use FirstChild() since we are
223 looking for XMLText, not an element, and ToText()
224 is a cast from a Node to a XMLText.
225*/
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700226
227
Lee Thomason21be8822012-07-15 17:27:22 -0700228bool example_4()
229{
230 static const char* xml =
231 "<information>"
232 " <attributeApproach v='2' />"
233 " <textApproach>"
234 " <v>2</v>"
235 " </textApproach>"
236 "</information>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700237
Lee Thomason21be8822012-07-15 17:27:22 -0700238 XMLDocument doc;
239 doc.Parse( xml );
240
241 int v0 = 0;
242 int v1 = 0;
243
244 XMLElement* attributeApproachElement = doc.FirstChildElement()->FirstChildElement( "attributeApproach" );
245 attributeApproachElement->QueryIntAttribute( "v", &v0 );
246
247 XMLElement* textApproachElement = doc.FirstChildElement()->FirstChildElement( "textApproach" );
248 textApproachElement->FirstChildElement( "v" )->QueryIntText( &v1 );
249
250 printf( "Both values are the same: %d and %d\n", v0, v1 );
251
252 return !doc.Error() && ( v0 == v1 );
253}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200254/** @page Example-4 Read attributes and text information.
255 @dontinclude ./xmltest.cpp
256
257 There are fundamentally 2 ways of writing a key-value
258 pair into an XML file. (Something that's always annoyed
259 me about XML.) Either by using attributes, or by writing
260 the key name into an element and the value into
261 the text node wrapped by the element. Both approaches
262 are illustrated in this example, which shows two ways
263 to encode the value "2" into the key "v":
264
265 @skip example_4()
266 @until "</information>";
267
268 TinyXML-2 has accessors for both approaches.
269
270 When using an attribute, you navigate to the XMLElement
271 with that attribute and use the QueryIntAttribute()
272 group of methods. (Also QueryFloatAttribute(), etc.)
273
274 @skip XMLElement* attributeApproachElement
275 @until &v0 );
276
277 When using the text approach, you need to navigate
278 down one more step to the XMLElement that contains
279 the text. Note the extra FirstChildElement( "v" )
280 in the code below. The value of the text can then
281 be safely queried with the QueryIntText() group
282 of methods. (Also QueryFloatText(), etc.)
283
284 @skip XMLElement* textApproachElement
285 @until &v1 );
286*/
Lee Thomason21be8822012-07-15 17:27:22 -0700287
288
Lee Thomason178e4cc2013-01-25 16:19:05 -0800289int main( int argc, const char ** argv )
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800290{
Lee Thomason (grinliz)0a4df402012-02-27 20:50:52 -0800291 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason1ff38e02012-02-14 18:18:16 -0800292 _CrtMemCheckpoint( &startMemState );
Dmitry-Me99916592014-10-23 11:37:03 +0400293 // Enable MS Visual C++ debug heap memory leaks dump on exit
294 _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
Dmitry-Meed785702017-06-15 13:39:53 +0300295 {
296 int leaksOnStart = _CrtDumpMemoryLeaks();
297 XMLTest( "No leaks on start?", FALSE, leaksOnStart );
298 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700299 #endif
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800300
Dmitry-Me4bcbf142014-12-25 19:05:18 +0300301 {
302 TIXMLASSERT( true );
303 }
304
Lee Thomason178e4cc2013-01-25 16:19:05 -0800305 if ( argc > 1 ) {
306 XMLDocument* doc = new XMLDocument();
307 clock_t startTime = clock();
308 doc->LoadFile( argv[1] );
Anton Indrawan8a0006c2014-11-20 18:27:07 +0100309 clock_t loadTime = clock();
Lee Thomason178e4cc2013-01-25 16:19:05 -0800310 int errorID = doc->ErrorID();
311 delete doc; doc = 0;
Anton Indrawan8a0006c2014-11-20 18:27:07 +0100312 clock_t deleteTime = clock();
Lee Thomason178e4cc2013-01-25 16:19:05 -0800313
314 printf( "Test file '%s' loaded. ErrorID=%d\n", argv[1], errorID );
315 if ( !errorID ) {
Lee Thomason (grinliz)d6bd7362013-05-11 20:23:13 -0700316 printf( "Load time=%u\n", (unsigned)(loadTime - startTime) );
317 printf( "Delete time=%u\n", (unsigned)(deleteTime - loadTime) );
318 printf( "Total time=%u\n", (unsigned)(deleteTime - startTime) );
Lee Thomason178e4cc2013-01-25 16:19:05 -0800319 }
320 exit(0);
321 }
322
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300323 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason7f7b1622012-03-24 12:49:03 -0700324 if ( !fp ) {
325 printf( "Error opening test file 'dream.xml'.\n"
326 "Is your working directory the same as where \n"
327 "the xmltest.cpp and dream.xml file are?\n\n"
328 #if defined( _MSC_VER )
329 "In windows Visual Studio you may need to set\n"
330 "Properties->Debugging->Working Directory to '..'\n"
331 #endif
332 );
333 exit( 1 );
334 }
335 fclose( fp );
336
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700337 XMLTest( "Example-1", 0, example_1() );
338 XMLTest( "Example-2", 0, example_2() );
339 XMLTest( "Example-3", 0, example_3() );
Lee Thomason21be8822012-07-15 17:27:22 -0700340 XMLTest( "Example-4", true, example_4() );
Lee Thomason87e475a2012-03-20 11:55:29 -0700341
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700342 /* ------ Example 2: Lookup information. ---- */
Lee Thomason87e475a2012-03-20 11:55:29 -0700343
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800344 {
Lee Thomason43f59302012-02-06 18:18:11 -0800345 static const char* test[] = { "<element />",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400346 "<element></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800347 "<element><subelement/></element>",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400348 "<element><subelement></subelement></element>",
349 "<element><subelement><subsub/></subelement></element>",
350 "<!--comment beside elements--><element><subelement></subelement></element>",
351 "<!--comment beside elements, this time with spaces--> \n <element> <subelement> \n </subelement> </element>",
352 "<element attrib1='foo' attrib2=\"bar\" ></element>",
353 "<element attrib1='foo' attrib2=\"bar\" ><subelement attrib3='yeehaa' /></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800354 "<element>Text inside element.</element>",
355 "<element><b></b></element>",
356 "<element>Text inside and <b>bolded</b> in the element.</element>",
357 "<outer><element>Text inside and <b>bolded</b> in the element.</element></outer>",
Lee Thomason8ee79892012-01-25 17:44:30 -0800358 "<element>This &amp; That.</element>",
Lee Thomason18d68bd2012-01-26 18:17:26 -0800359 "<element attrib='This&lt;That' />",
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800360 0
361 };
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800362 for( int i=0; test[i]; ++i ) {
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800363 XMLDocument doc;
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800364 doc.Parse( test[i] );
Dmitry-Me68578f42017-07-03 18:21:23 +0300365 XMLTest( "Element test", false, doc.Error() );
Lee Thomason5cae8972012-01-24 18:03:07 -0800366 doc.Print();
Lee Thomasonec975ce2012-01-23 11:42:06 -0800367 printf( "----------------------------------------------\n" );
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800368 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800369 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800370#if 1
Lee Thomasond6277762012-02-22 16:00:12 -0800371 {
372 static const char* test = "<!--hello world\n"
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400373 " line 2\r"
374 " line 3\r\n"
375 " line 4\n\r"
376 " line 5\r-->";
Lee Thomasond6277762012-02-22 16:00:12 -0800377
378 XMLDocument doc;
379 doc.Parse( test );
Dmitry-Me68578f42017-07-03 18:21:23 +0300380 XMLTest( "Hello world declaration", false, doc.Error() );
Lee Thomasond6277762012-02-22 16:00:12 -0800381 doc.Print();
382 }
383
Lee Thomason2c85a712012-01-31 08:24:24 -0800384 {
385 static const char* test = "<element>Text before.</element>";
386 XMLDocument doc;
387 doc.Parse( test );
Dmitry-Me68578f42017-07-03 18:21:23 +0300388 XMLTest( "Element text before", false, doc.Error() );
Lee Thomason2c85a712012-01-31 08:24:24 -0800389 XMLElement* root = doc.FirstChildElement();
390 XMLElement* newElement = doc.NewElement( "Subelement" );
391 root->InsertEndChild( newElement );
392 doc.Print();
393 }
Lee Thomasond1983222012-02-06 08:41:24 -0800394 {
395 XMLDocument* doc = new XMLDocument();
396 static const char* test = "<element><sub/></element>";
397 doc->Parse( test );
Dmitry-Me68578f42017-07-03 18:21:23 +0300398 XMLTest( "Element with sub element", false, doc->Error() );
Lee Thomasond1983222012-02-06 08:41:24 -0800399 delete doc;
400 }
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800401 {
Lee Thomason1ff38e02012-02-14 18:18:16 -0800402 // Test: Programmatic DOM
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800403 // Build:
404 // <element>
405 // <!--comment-->
406 // <sub attrib="1" />
407 // <sub attrib="2" />
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800408 // <sub attrib="3" >& Text!</sub>
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800409 // <element>
410
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800411 XMLDocument* doc = new XMLDocument();
Lee Thomason1ff38e02012-02-14 18:18:16 -0800412 XMLNode* element = doc->InsertEndChild( doc->NewElement( "element" ) );
413
414 XMLElement* sub[3] = { doc->NewElement( "sub" ), doc->NewElement( "sub" ), doc->NewElement( "sub" ) };
415 for( int i=0; i<3; ++i ) {
416 sub[i]->SetAttribute( "attrib", i );
417 }
418 element->InsertEndChild( sub[2] );
419 XMLNode* comment = element->InsertFirstChild( doc->NewComment( "comment" ) );
Lee Thomasonaf9bce12016-07-17 22:35:52 -0700420 comment->SetUserData((void*)2);
Lee Thomason1ff38e02012-02-14 18:18:16 -0800421 element->InsertAfterChild( comment, sub[0] );
422 element->InsertAfterChild( sub[0], sub[1] );
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800423 sub[2]->InsertFirstChild( doc->NewText( "& Text!" ));
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800424 doc->Print();
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800425 XMLTest( "Programmatic DOM", "comment", doc->FirstChildElement( "element" )->FirstChild()->Value() );
426 XMLTest( "Programmatic DOM", "0", doc->FirstChildElement( "element" )->FirstChildElement()->Attribute( "attrib" ) );
427 XMLTest( "Programmatic DOM", 2, doc->FirstChildElement()->LastChildElement( "sub" )->IntAttribute( "attrib" ) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700428 XMLTest( "Programmatic DOM", "& Text!",
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800429 doc->FirstChildElement()->LastChildElement( "sub" )->FirstChild()->ToText()->Value() );
Lee Thomasonc9445462016-07-17 22:53:48 -0700430 XMLTest("User data", (void*)2 == comment->GetUserData(), true, false);
U-Stream\Leeae25a442012-02-17 17:48:16 -0800431
432 // And now deletion:
433 element->DeleteChild( sub[2] );
434 doc->DeleteNode( comment );
435
436 element->FirstChildElement()->SetAttribute( "attrib", true );
437 element->LastChildElement()->DeleteAttribute( "attrib" );
438
439 XMLTest( "Programmatic DOM", true, doc->FirstChildElement()->FirstChildElement()->BoolAttribute( "attrib" ) );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700440 int value1 = 10;
441 int value2 = doc->FirstChildElement()->LastChildElement()->IntAttribute( "attrib", 10 );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300442 XMLError result = doc->FirstChildElement()->LastChildElement()->QueryIntAttribute( "attrib", &value1 );
443 XMLTest( "Programmatic DOM", XML_NO_ATTRIBUTE, result );
444 XMLTest( "Programmatic DOM", 10, value1 );
445 XMLTest( "Programmatic DOM", 10, value2 );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800446
447 doc->Print();
448
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700449 {
450 XMLPrinter streamer;
451 doc->Print( &streamer );
452 printf( "%s", streamer.CStr() );
453 }
454 {
455 XMLPrinter streamer( 0, true );
456 doc->Print( &streamer );
Doruk Turak1f212f32016-08-28 20:54:17 +0200457 XMLTest( "Compact mode", "<element><sub attrib=\"true\"/><sub/></element>", streamer.CStr(), false );
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700458 }
Lee Thomason (grinliz)6b8b0122012-09-08 21:21:00 -0700459 doc->SaveFile( "./resources/out/pretty.xml" );
460 doc->SaveFile( "./resources/out/compact.xml", true );
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800461 delete doc;
462 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800463 {
464 // Test: Dream
465 // XML1 : 1,187,569 bytes in 31,209 allocations
466 // XML2 : 469,073 bytes in 323 allocations
467 //int newStart = gNew;
468 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300469 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800470
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400471 doc.SaveFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800472 doc.PrintError();
473
474 XMLTest( "Dream", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400475 doc.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800476 XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() ? true : false );
477 XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
478 doc.FirstChild()->NextSibling()->ToUnknown()->Value() );
479 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400480 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800481 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400482 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800483
484 XMLDocument doc2;
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400485 doc2.LoadFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800486 XMLTest( "Dream-out", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400487 doc2.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800488 XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() ? true : false );
489 XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
490 doc2.FirstChild()->NextSibling()->ToUnknown()->Value() );
491 XMLTest( "Dream-out", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400492 doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800493
494 //gNewTotal = gNew - newStart;
495 }
Lee Thomason6f381b72012-03-02 12:59:39 -0800496
497
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800498 {
499 const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n"
500 "<passages count=\"006\" formatversion=\"20020620\">\n"
501 " <wrong error>\n"
502 "</passages>";
503
504 XMLDocument doc;
505 doc.Parse( error );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300506 XMLTest( "Bad XML", XML_ERROR_PARSING_ATTRIBUTE, doc.ErrorID() );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800507 }
508
509 {
510 const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
511
512 XMLDocument doc;
513 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300514 XMLTest( "Top level attributes", false, doc.Error() );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800515
516 XMLElement* ele = doc.FirstChildElement();
517
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300518 int iVal;
519 XMLError result;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800520 double dVal;
521
522 result = ele->QueryDoubleAttribute( "attr0", &dVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300523 XMLTest( "Query attribute: int as double", XML_SUCCESS, result);
524 XMLTest( "Query attribute: int as double", 1, (int)dVal );
525 XMLTest( "Query attribute: int as double", 1, (int)ele->DoubleAttribute("attr0"));
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700526
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800527 result = ele->QueryDoubleAttribute( "attr1", &dVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300528 XMLTest( "Query attribute: double as double", XML_SUCCESS, result);
529 XMLTest( "Query attribute: double as double", 2.0, dVal );
530 XMLTest( "Query attribute: double as double", 2.0, ele->DoubleAttribute("attr1") );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700531
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800532 result = ele->QueryIntAttribute( "attr1", &iVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300533 XMLTest( "Query attribute: double as int", XML_SUCCESS, result);
534 XMLTest( "Query attribute: double as int", 2, iVal );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700535
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800536 result = ele->QueryIntAttribute( "attr2", &iVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300537 XMLTest( "Query attribute: not a number", XML_WRONG_ATTRIBUTE_TYPE, result );
538 XMLTest( "Query attribute: not a number", 4.0, ele->DoubleAttribute("attr2", 4.0) );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700539
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800540 result = ele->QueryIntAttribute( "bar", &iVal );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300541 XMLTest( "Query attribute: does not exist", XML_NO_ATTRIBUTE, result );
542 XMLTest( "Query attribute: does not exist", true, ele->BoolAttribute("bar", true) );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800543 }
544
545 {
546 const char* str = "<doc/>";
547
548 XMLDocument doc;
549 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300550 XMLTest( "Empty top element", false, doc.Error() );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800551
552 XMLElement* ele = doc.FirstChildElement();
553
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800554 int iVal, iVal2;
555 double dVal, dVal2;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800556
557 ele->SetAttribute( "str", "strValue" );
558 ele->SetAttribute( "int", 1 );
559 ele->SetAttribute( "double", -1.0 );
560
561 const char* cStr = ele->Attribute( "str" );
562 ele->QueryIntAttribute( "int", &iVal );
563 ele->QueryDoubleAttribute( "double", &dVal );
564
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800565 ele->QueryAttribute( "int", &iVal2 );
566 ele->QueryAttribute( "double", &dVal2 );
567
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300568 XMLTest( "Attribute match test", "strValue", ele->Attribute( "str", "strValue" ) );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800569 XMLTest( "Attribute round trip. c-string.", "strValue", cStr );
570 XMLTest( "Attribute round trip. int.", 1, iVal );
571 XMLTest( "Attribute round trip. double.", -1, (int)dVal );
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800572 XMLTest( "Alternate query", true, iVal == iVal2 );
573 XMLTest( "Alternate query", true, dVal == dVal2 );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700574 XMLTest( "Alternate query", true, iVal == ele->IntAttribute("int") );
575 XMLTest( "Alternate query", true, dVal == ele->DoubleAttribute("double") );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800576 }
577
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800578 {
579 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300580 doc.LoadFile( "resources/utf8test.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800581
582 // Get the attribute "value" from the "Russian" element and check it.
583 XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700584 const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800585 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
586
587 XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) );
588
589 const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U,
590 0xd1U, 0x81U, 0xd1U, 0x81U,
591 0xd0U, 0xbaU, 0xd0U, 0xb8U,
592 0xd0U, 0xb9U, 0 };
593 const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
594
595 XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText();
596 XMLTest( "UTF-8: Browsing russian element name.",
597 russianText,
598 text->Value() );
599
600 // Now try for a round trip.
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400601 doc.SaveFile( "resources/out/utf8testout.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800602
603 // Check the round trip.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800604 int okay = 0;
605
Thomas Roßa6dd8c62012-07-26 20:42:18 +0200606 FILE* saved = fopen( "resources/out/utf8testout.xml", "r" );
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300607 FILE* verify = fopen( "resources/utf8testverify.xml", "r" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800608
609 if ( saved && verify )
610 {
611 okay = 1;
PKEuSc28ba3a2012-07-16 03:08:47 -0700612 char verifyBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800613 while ( fgets( verifyBuf, 256, verify ) )
614 {
PKEuSc28ba3a2012-07-16 03:08:47 -0700615 char savedBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800616 fgets( savedBuf, 256, saved );
617 NullLineEndings( verifyBuf );
618 NullLineEndings( savedBuf );
619
620 if ( strcmp( verifyBuf, savedBuf ) )
621 {
622 printf( "verify:%s<\n", verifyBuf );
623 printf( "saved :%s<\n", savedBuf );
624 okay = 0;
625 break;
626 }
627 }
628 }
629 if ( saved )
630 fclose( saved );
631 if ( verify )
632 fclose( verify );
633 XMLTest( "UTF-8: Verified multi-language round trip.", 1, okay );
634 }
635
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800636 // --------GetText()-----------
637 {
638 const char* str = "<foo>This is text</foo>";
639 XMLDocument doc;
640 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300641 XMLTest( "Double whitespace", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800642 const XMLElement* element = doc.RootElement();
643
644 XMLTest( "GetText() normal use.", "This is text", element->GetText() );
645
646 str = "<foo><b>This is text</b></foo>";
647 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300648 XMLTest( "Bold text simulation", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800649 element = doc.RootElement();
650
651 XMLTest( "GetText() contained element.", element->GetText() == 0, true );
652 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800653
Lee Thomasond6277762012-02-22 16:00:12 -0800654
Uli Kusterer321072e2014-01-21 01:57:38 +0100655 // --------SetText()-----------
656 {
657 const char* str = "<foo></foo>";
658 XMLDocument doc;
659 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300660 XMLTest( "Empty closed element", false, doc.Error() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100661 XMLElement* element = doc.RootElement();
662
Lee Thomason9c0678a2014-01-24 10:18:27 -0800663 element->SetText("darkness.");
664 XMLTest( "SetText() normal use (open/close).", "darkness.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100665
Lee Thomason9c0678a2014-01-24 10:18:27 -0800666 element->SetText("blue flame.");
667 XMLTest( "SetText() replace.", "blue flame.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100668
669 str = "<foo/>";
670 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300671 XMLTest( "Empty self-closed element", false, doc.Error() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100672 element = doc.RootElement();
673
Lee Thomason9c0678a2014-01-24 10:18:27 -0800674 element->SetText("The driver");
675 XMLTest( "SetText() normal use. (self-closing)", "The driver", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100676
Lee Thomason9c0678a2014-01-24 10:18:27 -0800677 element->SetText("<b>horses</b>");
678 XMLTest( "SetText() replace with tag-like text.", "<b>horses</b>", element->GetText() );
679 //doc.Print();
Uli Kusterer321072e2014-01-21 01:57:38 +0100680
681 str = "<foo><bar>Text in nested element</bar></foo>";
682 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300683 XMLTest( "Text in nested element", false, doc.Error() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100684 element = doc.RootElement();
685
Lee Thomason9c0678a2014-01-24 10:18:27 -0800686 element->SetText("wolves");
687 XMLTest( "SetText() prefix to nested non-text children.", "wolves", element->GetText() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800688
689 str = "<foo/>";
690 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300691 XMLTest( "Empty self-closed element round 2", false, doc.Error() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800692 element = doc.RootElement();
693
694 element->SetText( "str" );
695 XMLTest( "SetText types", "str", element->GetText() );
696
697 element->SetText( 1 );
698 XMLTest( "SetText types", "1", element->GetText() );
699
700 element->SetText( 1U );
701 XMLTest( "SetText types", "1", element->GetText() );
702
703 element->SetText( true );
Doruk Turak1f212f32016-08-28 20:54:17 +0200704 XMLTest( "SetText types", "true", element->GetText() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800705
706 element->SetText( 1.5f );
707 XMLTest( "SetText types", "1.5", element->GetText() );
708
709 element->SetText( 1.5 );
710 XMLTest( "SetText types", "1.5", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100711 }
712
Lee Thomason51c12712016-06-04 20:18:49 -0700713 // ---------- Attributes ---------
714 {
715 static const int64_t BIG = -123456789012345678;
716 XMLDocument doc;
717 XMLElement* element = doc.NewElement("element");
718 doc.InsertFirstChild(element);
719
720 {
721 element->SetAttribute("attrib", int(-100));
722 int v = 0;
723 element->QueryIntAttribute("attrib", &v);
724 XMLTest("Attribute: int", -100, v, true);
725 element->QueryAttribute("attrib", &v);
726 XMLTest("Attribute: int", -100, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700727 XMLTest("Attribute: int", -100, element->IntAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700728 }
729 {
730 element->SetAttribute("attrib", unsigned(100));
731 unsigned v = 0;
732 element->QueryUnsignedAttribute("attrib", &v);
733 XMLTest("Attribute: unsigned", unsigned(100), v, true);
734 element->QueryAttribute("attrib", &v);
735 XMLTest("Attribute: unsigned", unsigned(100), v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700736 XMLTest("Attribute: unsigned", unsigned(100), element->UnsignedAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700737 }
738 {
739 element->SetAttribute("attrib", BIG);
740 int64_t v = 0;
741 element->QueryInt64Attribute("attrib", &v);
742 XMLTest("Attribute: int64_t", BIG, v, true);
743 element->QueryAttribute("attrib", &v);
744 XMLTest("Attribute: int64_t", BIG, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700745 XMLTest("Attribute: int64_t", BIG, element->Int64Attribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700746 }
747 {
748 element->SetAttribute("attrib", true);
749 bool v = false;
750 element->QueryBoolAttribute("attrib", &v);
751 XMLTest("Attribute: bool", true, v, true);
752 element->QueryAttribute("attrib", &v);
753 XMLTest("Attribute: bool", true, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700754 XMLTest("Attribute: bool", true, element->BoolAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700755 }
756 {
Lee Thomasonce667c92016-12-26 16:45:30 -0800757 element->SetAttribute("attrib", true);
758 const char* result = element->Attribute("attrib");
759 XMLTest("Bool true is 'true'", "true", result);
760
Lee Thomasonc5c99c22016-12-29 11:19:17 -0800761 XMLUtil::SetBoolSerialization("1", "0");
Lee Thomasonce667c92016-12-26 16:45:30 -0800762 element->SetAttribute("attrib", true);
763 result = element->Attribute("attrib");
764 XMLTest("Bool true is '1'", "1", result);
765
Lee Thomasonc5c99c22016-12-29 11:19:17 -0800766 XMLUtil::SetBoolSerialization(0, 0);
Lee Thomasonce667c92016-12-26 16:45:30 -0800767 }
768 {
Lee Thomason51c12712016-06-04 20:18:49 -0700769 element->SetAttribute("attrib", 100.0);
770 double v = 0;
771 element->QueryDoubleAttribute("attrib", &v);
772 XMLTest("Attribute: double", 100.0, v, true);
773 element->QueryAttribute("attrib", &v);
774 XMLTest("Attribute: double", 100.0, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700775 XMLTest("Attribute: double", 100.0, element->DoubleAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700776 }
777 {
778 element->SetAttribute("attrib", 100.0f);
779 float v = 0;
780 element->QueryFloatAttribute("attrib", &v);
781 XMLTest("Attribute: float", 100.0f, v, true);
782 element->QueryAttribute("attrib", &v);
783 XMLTest("Attribute: float", 100.0f, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700784 XMLTest("Attribute: float", 100.0f, element->FloatAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700785 }
786 {
787 element->SetText(BIG);
788 int64_t v = 0;
789 element->QueryInt64Text(&v);
790 XMLTest("Element: int64_t", BIG, v, true);
791 }
792 }
793
794 // ---------- XMLPrinter stream mode ------
795 {
796 {
797 FILE* printerfp = fopen("resources/printer.xml", "w");
798 XMLPrinter printer(printerfp);
799 printer.OpenElement("foo");
800 printer.PushAttribute("attrib-text", "text");
801 printer.PushAttribute("attrib-int", int(1));
802 printer.PushAttribute("attrib-unsigned", unsigned(2));
803 printer.PushAttribute("attrib-int64", int64_t(3));
804 printer.PushAttribute("attrib-bool", true);
805 printer.PushAttribute("attrib-double", 4.0);
806 printer.CloseElement();
807 fclose(printerfp);
808 }
809 {
810 XMLDocument doc;
811 doc.LoadFile("resources/printer.xml");
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300812 XMLTest("XMLPrinter Stream mode: load", XML_SUCCESS, doc.ErrorID(), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700813
814 const XMLDocument& cdoc = doc;
815
816 const XMLAttribute* attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-text");
817 XMLTest("attrib-text", "text", attrib->Value(), true);
818 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int");
819 XMLTest("attrib-int", int(1), attrib->IntValue(), true);
820 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-unsigned");
821 XMLTest("attrib-unsigned", unsigned(2), attrib->UnsignedValue(), true);
822 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int64");
823 XMLTest("attrib-int64", int64_t(3), attrib->Int64Value(), true);
824 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-bool");
825 XMLTest("attrib-bool", true, attrib->BoolValue(), true);
826 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-double");
827 XMLTest("attrib-double", 4.0, attrib->DoubleValue(), true);
828 }
829
830 }
831
Uli Kusterer321072e2014-01-21 01:57:38 +0100832
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800833 // ---------- CDATA ---------------
834 {
835 const char* str = "<xmlElement>"
836 "<![CDATA["
837 "I am > the rules!\n"
838 "...since I make symbolic puns"
839 "]]>"
840 "</xmlElement>";
841 XMLDocument doc;
842 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300843 XMLTest( "CDATA symbolic puns round 1", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800844 doc.Print();
Lee Thomasond6277762012-02-22 16:00:12 -0800845
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300846 XMLTest( "CDATA parse.", "I am > the rules!\n...since I make symbolic puns",
847 doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomasond6277762012-02-22 16:00:12 -0800848 false );
849 }
850
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800851 // ----------- CDATA -------------
852 {
853 const char* str = "<xmlElement>"
854 "<![CDATA["
855 "<b>I am > the rules!</b>\n"
856 "...since I make symbolic puns"
857 "]]>"
858 "</xmlElement>";
859 XMLDocument doc;
860 doc.Parse( str );
Dmitry-Me68578f42017-07-03 18:21:23 +0300861 XMLTest( "CDATA symbolic puns round 2", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800862 doc.Print();
863
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300864 XMLTest( "CDATA parse. [ tixml1:1480107 ]",
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800865 "<b>I am > the rules!</b>\n...since I make symbolic puns",
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300866 doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800867 false );
868 }
869
870 // InsertAfterChild causes crash.
871 {
872 // InsertBeforeChild and InsertAfterChild causes crash.
873 XMLDocument doc;
874 XMLElement* parent = doc.NewElement( "Parent" );
875 doc.InsertFirstChild( parent );
876
877 XMLElement* childText0 = doc.NewElement( "childText0" );
878 XMLElement* childText1 = doc.NewElement( "childText1" );
879
880 XMLNode* childNode0 = parent->InsertEndChild( childText0 );
881 XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 );
882
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300883 XMLTest( "Test InsertAfterChild on empty node. ", true, ( childNode1 == parent->LastChild() ) );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800884 }
Lee Thomasond6277762012-02-22 16:00:12 -0800885
886 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800887 // Entities not being written correctly.
888 // From Lynn Allen
Lee Thomasond6277762012-02-22 16:00:12 -0800889
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800890 const char* passages =
891 "<?xml version=\"1.0\" standalone=\"no\" ?>"
892 "<passages count=\"006\" formatversion=\"20020620\">"
893 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
894 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
895 "</passages>";
Lee Thomasond6277762012-02-22 16:00:12 -0800896
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800897 XMLDocument doc;
898 doc.Parse( passages );
Dmitry-Me68578f42017-07-03 18:21:23 +0300899 XMLTest( "Entity transformation parse round 1", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800900 XMLElement* psg = doc.RootElement()->FirstChildElement();
901 const char* context = psg->Attribute( "context" );
902 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 -0800903
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800904 XMLTest( "Entity transformation: read. ", expected, context, true );
Lee Thomasond6277762012-02-22 16:00:12 -0800905
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400906 FILE* textfile = fopen( "resources/out/textfile.txt", "w" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800907 if ( textfile )
908 {
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800909 XMLPrinter streamer( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800910 psg->Accept( &streamer );
911 fclose( textfile );
912 }
Thomas Roß0922b732012-09-23 16:31:22 +0200913
914 textfile = fopen( "resources/out/textfile.txt", "r" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800915 TIXMLASSERT( textfile );
916 if ( textfile )
917 {
918 char buf[ 1024 ];
919 fgets( buf, 1024, textfile );
920 XMLTest( "Entity transformation: write. ",
921 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
922 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.\"/>\n",
923 buf, false );
PKEuSc28ba3a2012-07-16 03:08:47 -0700924 fclose( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800925 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800926 }
927
928 {
Lee Thomason6f381b72012-03-02 12:59:39 -0800929 // Suppress entities.
930 const char* passages =
931 "<?xml version=\"1.0\" standalone=\"no\" ?>"
932 "<passages count=\"006\" formatversion=\"20020620\">"
933 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
934 "</passages>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700935
Lee Thomason6f381b72012-03-02 12:59:39 -0800936 XMLDocument doc( false );
937 doc.Parse( passages );
Dmitry-Me68578f42017-07-03 18:21:23 +0300938 XMLTest( "Entity transformation parse round 2", false, doc.Error() );
Lee Thomason6f381b72012-03-02 12:59:39 -0800939
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300940 XMLTest( "No entity parsing.",
941 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.",
942 doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ) );
943 XMLTest( "No entity parsing.", "Crazy &ttk;",
944 doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value() );
Lee Thomason6f381b72012-03-02 12:59:39 -0800945 doc.Print();
946 }
947
948 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400949 const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800950
951 XMLDocument doc;
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400952 doc.Parse( test );
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300953 XMLTest( "dot in names", false, doc.Error() );
954 XMLTest( "dot in names", "a.elem", doc.FirstChildElement()->Name() );
955 XMLTest( "dot in names", "2.0", doc.FirstChildElement()->Attribute( "xmi.version" ) );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800956 }
957
958 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400959 const char* test = "<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800960
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400961 XMLDocument doc;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800962 doc.Parse( test );
Dmitry-Me68578f42017-07-03 18:21:23 +0300963 XMLTest( "fin thickness", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800964
965 XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
966 XMLTest( "Entity with one digit.",
Dmitry-Me9832a5f2017-06-23 18:29:16 +0300967 "1.1 Start easy ignore fin thickness\n", text->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800968 false );
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400969 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800970
971 {
972 // DOCTYPE not preserved (950171)
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700973 //
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800974 const char* doctype =
975 "<?xml version=\"1.0\" ?>"
976 "<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
977 "<!ELEMENT title (#PCDATA)>"
978 "<!ELEMENT books (title,authors)>"
979 "<element />";
980
981 XMLDocument doc;
982 doc.Parse( doctype );
Dmitry-Me68578f42017-07-03 18:21:23 +0300983 XMLTest( "PLAY SYSTEM parse", false, doc.Error() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400984 doc.SaveFile( "resources/out/test7.xml" );
Dmitry-Me68578f42017-07-03 18:21:23 +0300985 XMLTest( "PLAY SYSTEM save", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800986 doc.DeleteChild( doc.RootElement() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400987 doc.LoadFile( "resources/out/test7.xml" );
Dmitry-Me68578f42017-07-03 18:21:23 +0300988 XMLTest( "PLAY SYSTEM load", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800989 doc.Print();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700990
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800991 const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown();
992 XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() );
993
994 }
995
996 {
997 // Comments do not stream out correctly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700998 const char* doctype =
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800999 "<!-- Somewhat<evil> -->";
1000 XMLDocument doc;
1001 doc.Parse( doctype );
Dmitry-Me68578f42017-07-03 18:21:23 +03001002 XMLTest( "Comment somewhat evil", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001003
1004 XMLComment* comment = doc.FirstChild()->ToComment();
1005
1006 XMLTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
1007 }
1008 {
1009 // Double attributes
1010 const char* doctype = "<element attr='red' attr='blue' />";
1011
1012 XMLDocument doc;
1013 doc.Parse( doctype );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001014
Lee Thomason2fa81722012-11-09 12:37:46 -08001015 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 -08001016 doc.PrintError();
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001017 }
1018
1019 {
1020 // Embedded null in stream.
1021 const char* doctype = "<element att\0r='red' attr='blue' />";
1022
1023 XMLDocument doc;
1024 doc.Parse( doctype );
1025 XMLTest( "Embedded null throws error.", true, doc.Error() );
1026 }
1027
1028 {
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -07001029 // Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
Dmitry-Me588bb8d2014-12-25 18:59:18 +03001030 const char* str = "";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001031 XMLDocument doc;
1032 doc.Parse( str );
Lee Thomason2fa81722012-11-09 12:37:46 -08001033 XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001034 }
1035
1036 {
Dmitry-Me588bb8d2014-12-25 18:59:18 +03001037 // Documents with all whitespaces should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
1038 const char* str = " ";
1039 XMLDocument doc;
1040 doc.Parse( str );
1041 XMLTest( "All whitespaces document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
1042 }
1043
1044 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001045 // Low entities
1046 XMLDocument doc;
1047 doc.Parse( "<test>&#x0e;</test>" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001048 XMLTest( "Hex values", false, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001049 const char result[] = { 0x0e, 0 };
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001050 XMLTest( "Low entities.", result, doc.FirstChildElement()->GetText() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001051 doc.Print();
1052 }
1053
1054 {
1055 // Attribute values with trailing quotes not handled correctly
1056 XMLDocument doc;
1057 doc.Parse( "<foo attribute=bar\" />" );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001058 XMLTest( "Throw error with bad end quotes.", true, doc.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001059 }
1060
1061 {
1062 // [ 1663758 ] Failure to report error on bad XML
1063 XMLDocument xml;
1064 xml.Parse("<x>");
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001065 XMLTest("Missing end tag at end of input", true, xml.Error());
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001066 xml.Parse("<x> ");
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001067 XMLTest("Missing end tag with trailing whitespace", true, xml.Error());
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001068 xml.Parse("<x></y>");
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001069 XMLTest("Mismatched tags", XML_ERROR_MISMATCHED_ELEMENT, xml.ErrorID() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001070 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001071
1072
1073 {
1074 // [ 1475201 ] TinyXML parses entities in comments
1075 XMLDocument xml;
1076 xml.Parse("<!-- declarations for <head> & <body> -->"
1077 "<!-- far &amp; away -->" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001078 XMLTest( "Declarations for head and body", false, xml.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001079
1080 XMLNode* e0 = xml.FirstChild();
1081 XMLNode* e1 = e0->NextSibling();
1082 XMLComment* c0 = e0->ToComment();
1083 XMLComment* c1 = e1->ToComment();
1084
1085 XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
1086 XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
1087 }
1088
1089 {
1090 XMLDocument xml;
1091 xml.Parse( "<Parent>"
1092 "<child1 att=''/>"
1093 "<!-- With this comment, child2 will not be parsed! -->"
1094 "<child2 att=''/>"
1095 "</Parent>" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001096 XMLTest( "Comments iteration", false, xml.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001097 xml.Print();
1098
1099 int count = 0;
1100
1101 for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
1102 ele;
1103 ele = ele->NextSibling() )
1104 {
1105 ++count;
1106 }
1107
1108 XMLTest( "Comments iterate correctly.", 3, count );
1109 }
1110
1111 {
1112 // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
1113 unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
1114 buf[60] = 239;
1115 buf[61] = 0;
1116
1117 XMLDocument doc;
1118 doc.Parse( (const char*)buf);
Dmitry-Me68578f42017-07-03 18:21:23 +03001119 XMLTest( "Broken CDATA", true, doc.Error() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001120 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001121
1122
1123 {
1124 // bug 1827248 Error while parsing a little bit malformed file
1125 // Actually not malformed - should work.
1126 XMLDocument xml;
1127 xml.Parse( "<attributelist> </attributelist >" );
1128 XMLTest( "Handle end tag whitespace", false, xml.Error() );
1129 }
1130
1131 {
1132 // This one must not result in an infinite loop
1133 XMLDocument xml;
1134 xml.Parse( "<infinite>loop" );
Dmitry-Me68578f42017-07-03 18:21:23 +03001135 XMLTest( "No closing element", true, xml.Error() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001136 XMLTest( "Infinite loop test.", true, true );
1137 }
1138#endif
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001139 {
1140 const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
1141 XMLDocument doc;
1142 doc.Parse( pub );
Dmitry-Me68578f42017-07-03 18:21:23 +03001143 XMLTest( "Trailing DOCTYPE", false, doc.Error() );
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001144
1145 XMLDocument clone;
1146 for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
1147 XMLNode* copy = node->ShallowClone( &clone );
1148 clone.InsertEndChild( copy );
1149 }
1150
1151 clone.Print();
1152
1153 int count=0;
1154 const XMLNode* a=clone.FirstChild();
1155 const XMLNode* b=doc.FirstChild();
1156 for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
1157 ++count;
1158 XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
1159 }
1160 XMLTest( "Clone and Equal", 4, count );
1161 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001162
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001163 {
Lee Thomason7085f002017-06-01 18:09:43 -07001164 // Deep Cloning of root element.
1165 XMLDocument doc2;
1166 XMLPrinter printer1;
1167 {
1168 // Make sure doc1 is deleted before we test doc2
1169 const char* xml =
1170 "<root>"
1171 " <child1 foo='bar'/>"
1172 " <!-- comment thing -->"
1173 " <child2 val='1'>Text</child2>"
1174 "</root>";
1175 XMLDocument doc;
1176 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001177 XMLTest( "Parse before deep cloning root element", false, doc.Error() );
Lee Thomason7085f002017-06-01 18:09:43 -07001178
1179 doc.Print(&printer1);
1180 XMLNode* root = doc.RootElement()->DeepClone(&doc2);
1181 doc2.InsertFirstChild(root);
1182 }
1183 XMLPrinter printer2;
1184 doc2.Print(&printer2);
1185
1186 XMLTest("Deep clone of element.", printer1.CStr(), printer2.CStr(), true);
1187 }
1188
1189 {
1190 // Deep Cloning of sub element.
1191 XMLDocument doc2;
1192 XMLPrinter printer1;
1193 {
1194 // Make sure doc1 is deleted before we test doc2
1195 const char* xml =
1196 "<?xml version ='1.0'?>"
1197 "<root>"
1198 " <child1 foo='bar'/>"
1199 " <!-- comment thing -->"
1200 " <child2 val='1'>Text</child2>"
1201 "</root>";
1202 XMLDocument doc;
1203 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001204 XMLTest( "Parse before deep cloning sub element", false, doc.Error() );
Lee Thomason7085f002017-06-01 18:09:43 -07001205
1206 const XMLElement* subElement = doc.FirstChildElement("root")->FirstChildElement("child2");
1207 subElement->Accept(&printer1);
1208
1209 XMLNode* clonedSubElement = subElement->DeepClone(&doc2);
1210 doc2.InsertFirstChild(clonedSubElement);
1211 }
1212 XMLPrinter printer2;
1213 doc2.Print(&printer2);
1214
1215 XMLTest("Deep clone of sub-element.", printer1.CStr(), printer2.CStr(), true);
1216 }
1217
1218 {
1219 // Deep cloning of document.
1220 XMLDocument doc2;
1221 XMLPrinter printer1;
1222 {
1223 // Make sure doc1 is deleted before we test doc2
1224 const char* xml =
1225 "<?xml version ='1.0'?>"
1226 "<!-- Top level comment. -->"
1227 "<root>"
1228 " <child1 foo='bar'/>"
1229 " <!-- comment thing -->"
1230 " <child2 val='1'>Text</child2>"
1231 "</root>";
1232 XMLDocument doc;
1233 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001234 XMLTest( "Parse before deep cloning document", false, doc.Error() );
Lee Thomason7085f002017-06-01 18:09:43 -07001235 doc.Print(&printer1);
1236
1237 doc.DeepCopy(&doc2);
1238 }
1239 XMLPrinter printer2;
1240 doc2.Print(&printer2);
1241
1242 XMLTest("DeepCopy of document.", printer1.CStr(), printer2.CStr(), true);
1243 }
1244
1245
1246 {
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001247 // This shouldn't crash.
1248 XMLDocument doc;
Lee Thomason85536252016-06-04 19:10:53 -07001249 if(XML_SUCCESS != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001250 {
1251 doc.PrintError();
1252 }
1253 XMLTest( "Error in snprinf handling.", true, doc.Error() );
1254 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001255
Lee Thomason5e3803c2012-04-16 08:57:05 -07001256 {
1257 // Attribute ordering.
1258 static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
1259 XMLDocument doc;
1260 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001261 XMLTest( "Parse for attribute ordering", false, doc.Error() );
Lee Thomason5e3803c2012-04-16 08:57:05 -07001262 XMLElement* ele = doc.FirstChildElement();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001263
Lee Thomason5e3803c2012-04-16 08:57:05 -07001264 const XMLAttribute* a = ele->FirstAttribute();
1265 XMLTest( "Attribute order", "1", a->Value() );
1266 a = a->Next();
1267 XMLTest( "Attribute order", "2", a->Value() );
1268 a = a->Next();
1269 XMLTest( "Attribute order", "3", a->Value() );
1270 XMLTest( "Attribute order", "attrib3", a->Name() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001271
Lee Thomason5e3803c2012-04-16 08:57:05 -07001272 ele->DeleteAttribute( "attrib2" );
1273 a = ele->FirstAttribute();
1274 XMLTest( "Attribute order", "1", a->Value() );
1275 a = a->Next();
1276 XMLTest( "Attribute order", "3", a->Value() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001277
Lee Thomason5e3803c2012-04-16 08:57:05 -07001278 ele->DeleteAttribute( "attrib1" );
1279 ele->DeleteAttribute( "attrib3" );
1280 XMLTest( "Attribute order (empty)", false, ele->FirstAttribute() ? true : false );
1281 }
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001282
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001283 {
1284 // Make sure an attribute with a space in it succeeds.
Lee Thomason78a773d2012-07-02 10:10:19 -07001285 static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
1286 static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
1287 static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
1288 XMLDocument doc0;
1289 doc0.Parse( xml0 );
Dmitry-Me68578f42017-07-03 18:21:23 +03001290 XMLTest( "Parse attribute with space 1", false, doc0.Error() );
Lee Thomason78a773d2012-07-02 10:10:19 -07001291 XMLDocument doc1;
1292 doc1.Parse( xml1 );
Dmitry-Me68578f42017-07-03 18:21:23 +03001293 XMLTest( "Parse attribute with space 2", false, doc1.Error() );
Lee Thomason78a773d2012-07-02 10:10:19 -07001294 XMLDocument doc2;
1295 doc2.Parse( xml2 );
Dmitry-Me68578f42017-07-03 18:21:23 +03001296 XMLTest( "Parse attribute with space 3", false, doc2.Error() );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001297
Lee Thomason78a773d2012-07-02 10:10:19 -07001298 XMLElement* ele = 0;
1299 ele = doc0.FirstChildElement();
1300 XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
1301 ele = doc1.FirstChildElement();
1302 XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
1303 ele = doc2.FirstChildElement();
1304 XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001305 }
1306
1307 {
1308 // Make sure we don't go into an infinite loop.
1309 static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
1310 XMLDocument doc;
1311 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001312 XMLTest( "Parse two elements with attribute", false, doc.Error() );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001313 XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
1314 XMLElement* ele1 = ele0->NextSiblingElement();
1315 bool equal = ele0->ShallowEqual( ele1 );
1316
1317 XMLTest( "Infinite loop in shallow equal.", true, equal );
1318 }
1319
Lee Thomason5708f812012-03-28 17:46:41 -07001320 // -------- Handles ------------
1321 {
1322 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1323 XMLDocument doc;
1324 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001325 XMLTest( "Parse element with attribute and nested element round 1", false, doc.Error() );
Lee Thomason5708f812012-03-28 17:46:41 -07001326
1327 XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001328 XMLTest( "Handle, success, mutable", "sub", ele->Value() );
Lee Thomason5708f812012-03-28 17:46:41 -07001329
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001330 XMLHandle docH( doc );
1331 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001332 XMLTest( "Handle, dne, mutable", false, ele != 0 );
Lee Thomason5708f812012-03-28 17:46:41 -07001333 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001334
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001335 {
1336 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1337 XMLDocument doc;
1338 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001339 XMLTest( "Parse element with attribute and nested element round 2", false, doc.Error() );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001340 XMLConstHandle docH( doc );
1341
1342 const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement();
1343 XMLTest( "Handle, success, const", ele->Value(), "sub" );
1344
1345 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001346 XMLTest( "Handle, dne, const", false, ele != 0 );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001347 }
Lee Thomasonf68c4382012-04-28 14:37:11 -07001348 {
1349 // Default Declaration & BOM
1350 XMLDocument doc;
1351 doc.InsertEndChild( doc.NewDeclaration() );
1352 doc.SetBOM( true );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001353
Lee Thomasonf68c4382012-04-28 14:37:11 -07001354 XMLPrinter printer;
1355 doc.Print( &printer );
1356
1357 static const char* result = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001358 XMLTest( "BOM and default declaration", result, printer.CStr(), false );
1359 XMLTest( "CStrSize", 42, printer.CStrSize(), false );
Lee Thomasonf68c4382012-04-28 14:37:11 -07001360 }
Lee Thomason21be8822012-07-15 17:27:22 -07001361 {
1362 const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
1363 XMLDocument doc;
1364 doc.Parse( xml );
1365 XMLTest( "Ill formed XML", true, doc.Error() );
1366 }
1367
1368 // QueryXYZText
1369 {
1370 const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
1371 XMLDocument doc;
1372 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001373 XMLTest( "Parse points", false, doc.Error() );
Lee Thomason21be8822012-07-15 17:27:22 -07001374
1375 const XMLElement* pointElement = doc.RootElement();
1376
1377 int intValue = 0;
1378 unsigned unsignedValue = 0;
1379 float floatValue = 0;
1380 double doubleValue = 0;
1381 bool boolValue = false;
1382
1383 pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
1384 pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
1385 pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
1386 pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
1387 pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
1388
1389
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001390 XMLTest( "QueryIntText", 1, intValue, false );
1391 XMLTest( "QueryUnsignedText", (unsigned)1, unsignedValue, false );
1392 XMLTest( "QueryFloatText", 1.2f, floatValue, false );
1393 XMLTest( "QueryDoubleText", 1.2, doubleValue, false );
1394 XMLTest( "QueryBoolText", true, boolValue, false );
Lee Thomason21be8822012-07-15 17:27:22 -07001395 }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001396
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001397 {
1398 const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
1399 XMLDocument doc;
1400 doc.Parse( xml );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001401 XMLTest( "Non-alpha element lead letter parses.", false, doc.Error() );
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001402 }
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001403
1404 {
1405 const char* xml = "<element _attr1=\"foo\" :attr2=\"bar\"></element>";
1406 XMLDocument doc;
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001407 doc.Parse( xml );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001408 XMLTest("Non-alpha attribute lead character parses.", false, doc.Error());
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001409 }
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001410
1411 {
1412 const char* xml = "<3lement></3lement>";
1413 XMLDocument doc;
1414 doc.Parse( xml );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001415 XMLTest("Element names with lead digit fail to parse.", true, doc.Error());
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001416 }
Lee Thomason (grinliz)62d1c5a2012-09-08 21:44:12 -07001417
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001418 {
1419 const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
1420 XMLDocument doc;
1421 doc.Parse( xml, 10 );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001422 XMLTest( "Set length of incoming data", false, doc.Error() );
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001423 }
1424
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001425 {
1426 XMLDocument doc;
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001427 XMLTest( "Document is initially empty", true, doc.NoChildren() );
Dmitry-Me48b5df02015-04-06 18:20:25 +03001428 doc.Clear();
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001429 XMLTest( "Empty is empty after Clear()", true, doc.NoChildren() );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001430 doc.LoadFile( "resources/dream.xml" );
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001431 XMLTest( "Document has something to Clear()", false, doc.NoChildren() );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001432 doc.Clear();
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001433 XMLTest( "Document Clear()'s", true, doc.NoChildren() );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001434 }
1435
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001436 // ----------- Whitespace ------------
1437 {
1438 const char* xml = "<element>"
1439 "<a> This \nis &apos; text &apos; </a>"
1440 "<b> This is &apos; text &apos; \n</b>"
1441 "<c>This is &apos; \n\n text &apos;</c>"
1442 "</element>";
1443 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1444 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001445 XMLTest( "Parse with whitespace collapsing and &apos", false, doc.Error() );
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001446
1447 const XMLElement* element = doc.FirstChildElement();
1448 for( const XMLElement* parent = element->FirstChildElement();
1449 parent;
1450 parent = parent->NextSiblingElement() )
1451 {
1452 XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
1453 }
1454 }
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001455
Lee Thomasonae9ab072012-10-24 10:17:53 -07001456#if 0
1457 {
1458 // Passes if assert doesn't fire.
1459 XMLDocument xmlDoc;
1460
1461 xmlDoc.NewDeclaration();
1462 xmlDoc.NewComment("Configuration file");
1463
1464 XMLElement *root = xmlDoc.NewElement("settings");
1465 root->SetAttribute("version", 2);
1466 }
1467#endif
1468
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001469 {
1470 const char* xml = "<element> </element>";
1471 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1472 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001473 XMLTest( "Parse with all whitespaces", false, doc.Error() );
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001474 XMLTest( "Whitespace all space", true, 0 == doc.FirstChildElement()->FirstChild() );
1475 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001476
Lee Thomason5b0a6772012-11-19 13:54:42 -08001477 {
1478 // An assert should not fire.
1479 const char* xml = "<element/>";
1480 XMLDocument doc;
1481 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001482 XMLTest( "Parse with self-closed element", false, doc.Error() );
Lee Thomason5b0a6772012-11-19 13:54:42 -08001483 XMLElement* ele = doc.NewElement( "unused" ); // This will get cleaned up with the 'doc' going out of scope.
1484 XMLTest( "Tracking unused elements", true, ele != 0, false );
1485 }
1486
Lee Thomasona6412ac2012-12-13 15:39:11 -08001487
1488 {
1489 const char* xml = "<parent><child>abc</child></parent>";
1490 XMLDocument doc;
1491 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001492 XMLTest( "Parse for printing of sub-element", false, doc.Error() );
Lee Thomasona6412ac2012-12-13 15:39:11 -08001493 XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child");
1494
1495 XMLPrinter printer;
1496 ele->Accept( &printer );
1497 XMLTest( "Printing of sub-element", "<child>abc</child>\n", printer.CStr(), false );
1498 }
1499
1500
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001501 {
1502 XMLDocument doc;
1503 XMLError error = doc.LoadFile( "resources/empty.xml" );
1504 XMLTest( "Loading an empty file", XML_ERROR_EMPTY_DOCUMENT, error );
Lee Thomason331596e2014-09-11 14:56:43 -07001505 XMLTest( "Loading an empty file and ErrorName as string", "XML_ERROR_EMPTY_DOCUMENT", doc.ErrorName() );
Lee Thomasonc7556672014-09-14 12:39:42 -07001506 doc.PrintError();
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001507 }
1508
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001509 {
1510 // BOM preservation
1511 static const char* xml_bom_preservation = "\xef\xbb\xbf<element/>\n";
1512 {
1513 XMLDocument doc;
Lee Thomason85536252016-06-04 19:10:53 -07001514 XMLTest( "BOM preservation (parse)", XML_SUCCESS, doc.Parse( xml_bom_preservation ), false );
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001515 XMLPrinter printer;
1516 doc.Print( &printer );
1517
1518 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1519 doc.SaveFile( "resources/bomtest.xml" );
1520 }
1521 {
1522 XMLDocument doc;
1523 doc.LoadFile( "resources/bomtest.xml" );
1524 XMLTest( "BOM preservation (load)", true, doc.HasBOM(), false );
1525
1526 XMLPrinter printer;
1527 doc.Print( &printer );
1528 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1529 }
1530 }
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001531
Michael Daumlinged523282013-10-23 07:47:29 +02001532 {
1533 // Insertion with Removal
1534 const char* xml = "<?xml version=\"1.0\" ?>"
1535 "<root>"
1536 "<one>"
1537 "<subtree>"
1538 "<elem>element 1</elem>text<!-- comment -->"
1539 "</subtree>"
1540 "</one>"
1541 "<two/>"
1542 "</root>";
1543 const char* xmlInsideTwo = "<?xml version=\"1.0\" ?>"
1544 "<root>"
1545 "<one/>"
1546 "<two>"
1547 "<subtree>"
1548 "<elem>element 1</elem>text<!-- comment -->"
1549 "</subtree>"
1550 "</two>"
1551 "</root>";
1552 const char* xmlAfterOne = "<?xml version=\"1.0\" ?>"
1553 "<root>"
1554 "<one/>"
1555 "<subtree>"
1556 "<elem>element 1</elem>text<!-- comment -->"
1557 "</subtree>"
1558 "<two/>"
1559 "</root>";
1560 const char* xmlAfterTwo = "<?xml version=\"1.0\" ?>"
1561 "<root>"
1562 "<one/>"
1563 "<two/>"
1564 "<subtree>"
1565 "<elem>element 1</elem>text<!-- comment -->"
1566 "</subtree>"
1567 "</root>";
1568
1569 XMLDocument doc;
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001570 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001571 XMLTest( "Insertion with removal parse round 1", false, doc.Error() );
Michael Daumlinged523282013-10-23 07:47:29 +02001572 XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1573 XMLElement* two = doc.RootElement()->FirstChildElement("two");
1574 two->InsertFirstChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001575 XMLPrinter printer1(0, true);
1576 doc.Accept(&printer1);
1577 XMLTest("Move node from within <one> to <two>", xmlInsideTwo, printer1.CStr());
Michael Daumlinged523282013-10-23 07:47:29 +02001578
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001579 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001580 XMLTest( "Insertion with removal parse round 2", false, doc.Error() );
Michael Daumlinged523282013-10-23 07:47:29 +02001581 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1582 two = doc.RootElement()->FirstChildElement("two");
1583 doc.RootElement()->InsertAfterChild(two, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001584 XMLPrinter printer2(0, true);
1585 doc.Accept(&printer2);
1586 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer2.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001587
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001588 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001589 XMLTest( "Insertion with removal parse round 3", false, doc.Error() );
Michael Daumlinged523282013-10-23 07:47:29 +02001590 XMLNode* one = doc.RootElement()->FirstChildElement("one");
1591 subtree = one->FirstChildElement("subtree");
1592 doc.RootElement()->InsertAfterChild(one, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001593 XMLPrinter printer3(0, true);
1594 doc.Accept(&printer3);
1595 XMLTest("Move node from within <one> after <one>", xmlAfterOne, printer3.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001596
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001597 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001598 XMLTest( "Insertion with removal parse round 4", false, doc.Error() );
Michael Daumlinged523282013-10-23 07:47:29 +02001599 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1600 two = doc.RootElement()->FirstChildElement("two");
1601 doc.RootElement()->InsertEndChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001602 XMLPrinter printer4(0, true);
1603 doc.Accept(&printer4);
1604 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer4.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001605 }
1606
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001607 {
1608 const char* xml = "<svg width = \"128\" height = \"128\">"
1609 " <text> </text>"
1610 "</svg>";
1611 XMLDocument doc;
1612 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001613 XMLTest( "Parse svg with text", false, doc.Error() );
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001614 doc.Print();
1615 }
1616
Lee Thomason92e521b2014-11-15 17:45:51 -08001617 {
1618 // Test that it doesn't crash.
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001619 const char* xml = "<?xml version=\"1.0\"?><root><sample><field0><1</field0><field1>2</field1></sample></root>";
1620 XMLDocument doc;
1621 doc.Parse(xml);
Dmitry-Me68578f42017-07-03 18:21:23 +03001622 XMLTest( "Parse root-sample-field0", true, doc.Error() );
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001623 doc.PrintError();
Lee Thomason92e521b2014-11-15 17:45:51 -08001624 }
1625
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001626#if 1
1627 // the question being explored is what kind of print to use:
1628 // https://github.com/leethomason/tinyxml2/issues/63
1629 {
1630 //const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9' attrC='1.0e-10' attrD='1001000000.000000' attrE='0.1234567890123456789'/>";
1631 const char* xml = "<element/>";
1632 XMLDocument doc;
1633 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001634 XMLTest( "Parse self-closed empty element", false, doc.Error() );
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001635 doc.FirstChildElement()->SetAttribute( "attrA-f64", 123456789.123456789 );
1636 doc.FirstChildElement()->SetAttribute( "attrB-f64", 1.001e9 );
1637 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e9 );
1638 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e20 );
1639 doc.FirstChildElement()->SetAttribute( "attrD-f64", 1.0e-10 );
1640 doc.FirstChildElement()->SetAttribute( "attrD-f64", 0.123456789 );
1641
1642 doc.FirstChildElement()->SetAttribute( "attrA-f32", 123456789.123456789f );
1643 doc.FirstChildElement()->SetAttribute( "attrB-f32", 1.001e9f );
1644 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e9f );
1645 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e20f );
1646 doc.FirstChildElement()->SetAttribute( "attrD-f32", 1.0e-10f );
1647 doc.FirstChildElement()->SetAttribute( "attrD-f32", 0.123456789f );
1648
1649 doc.Print();
1650
1651 /* The result of this test is platform, compiler, and library version dependent. :("
1652 XMLPrinter printer;
1653 doc.Print( &printer );
1654 XMLTest( "Float and double formatting.",
1655 "<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",
1656 printer.CStr(),
1657 true );
1658 */
1659 }
1660#endif
Lee Thomasonf07b9522014-10-30 13:25:12 -07001661
1662 {
1663 // Issue #184
1664 // If it doesn't assert, it passes. Caused by objects
1665 // getting created during parsing which are then
1666 // inaccessible in the memory pools.
Dmitry-Me5d1aec12017-06-28 14:51:17 +03001667 const char* xmlText = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>";
Lee Thomasonf07b9522014-10-30 13:25:12 -07001668 {
1669 XMLDocument doc;
Dmitry-Me5d1aec12017-06-28 14:51:17 +03001670 doc.Parse(xmlText);
Dmitry-Me68578f42017-07-03 18:21:23 +03001671 XMLTest( "Parse hex no closing tag round 1", true, doc.Error() );
Lee Thomasonf07b9522014-10-30 13:25:12 -07001672 }
1673 {
1674 XMLDocument doc;
Dmitry-Me5d1aec12017-06-28 14:51:17 +03001675 doc.Parse(xmlText);
Dmitry-Me68578f42017-07-03 18:21:23 +03001676 XMLTest( "Parse hex no closing tag round 2", true, doc.Error() );
Lee Thomasonf07b9522014-10-30 13:25:12 -07001677 doc.Clear();
1678 }
1679 }
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001680
1681 {
1682 // If this doesn't assert in DEBUG, all is well.
1683 tinyxml2::XMLDocument doc;
1684 tinyxml2::XMLElement *pRoot = doc.NewElement("Root");
1685 doc.DeleteNode(pRoot);
1686 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001687
Dmitry-Me8b67d742014-12-22 11:35:12 +03001688 {
1689 // Should not assert in DEBUG
1690 XMLPrinter printer;
1691 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001692
Dmitry-Me6f51c802015-03-14 13:25:03 +03001693 {
1694 // Issue 291. Should not crash
1695 const char* xml = "&#0</a>";
1696 XMLDocument doc;
1697 doc.Parse( xml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001698 XMLTest( "Parse hex with closing tag", false, doc.Error() );
Dmitry-Me6f51c802015-03-14 13:25:03 +03001699
1700 XMLPrinter printer;
1701 doc.Print( &printer );
1702 }
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001703 {
1704 // Issue 299. Can print elements that are not linked in.
1705 // Will crash if issue not fixed.
1706 XMLDocument doc;
1707 XMLElement* newElement = doc.NewElement( "printme" );
1708 XMLPrinter printer;
1709 newElement->Accept( &printer );
Dmitry-Me5daa54c2015-04-08 17:45:07 +03001710 // Delete the node to avoid possible memory leak report in debug output
1711 doc.DeleteNode( newElement );
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001712 }
Lee Thomasonf6577832015-03-26 11:18:21 -07001713 {
Ant Mitchell189198f2015-03-24 16:20:36 +00001714 // Issue 302. Clear errors from LoadFile/SaveFile
1715 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001716 XMLTest( "Issue 302. Should be no error initially", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001717 doc.SaveFile( "./no/such/path/pretty.xml" );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001718 XMLTest( "Issue 302. Fail to save", "XML_ERROR_FILE_COULD_NOT_BE_OPENED", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001719 doc.SaveFile( "./resources/out/compact.xml", true );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001720 XMLTest( "Issue 302. Subsequent success in saving", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001721 }
Dmitry-Me6f51c802015-03-14 13:25:03 +03001722
Dmitry-Med9852a52015-03-25 10:17:49 +03001723 {
1724 // If a document fails to load then subsequent
1725 // successful loads should clear the error
1726 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001727 XMLTest( "Should be no error initially", false, doc.Error() );
Dmitry-Med9852a52015-03-25 10:17:49 +03001728 doc.LoadFile( "resources/no-such-file.xml" );
1729 XMLTest( "No such file - should fail", true, doc.Error() );
1730
1731 doc.LoadFile( "resources/dream.xml" );
1732 XMLTest( "Error should be cleared", false, doc.Error() );
1733 }
Sarat Addepalli8e85afa2015-05-19 09:07:03 +05301734
Sarat Addepalli2bb6bb52015-05-18 09:16:34 +05301735 {
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001736 // Check that declarations are allowed only at beginning of document
Lee Thomason85492022015-05-22 11:07:45 -07001737 const char* xml0 = "<?xml version=\"1.0\" ?>"
1738 " <!-- xml version=\"1.1\" -->"
1739 "<first />";
1740 const char* xml1 = "<?xml version=\"1.0\" ?>"
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001741 "<?xml-stylesheet type=\"text/xsl\" href=\"Anything.xsl\"?>"
Lee Thomason85492022015-05-22 11:07:45 -07001742 "<first />";
1743 const char* xml2 = "<first />"
1744 "<?xml version=\"1.0\" ?>";
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001745 const char* xml3 = "<first></first>"
1746 "<?xml version=\"1.0\" ?>";
1747
1748 const char* xml4 = "<first><?xml version=\"1.0\" ?></first>";
1749
Lee Thomason85492022015-05-22 11:07:45 -07001750 XMLDocument doc;
1751 doc.Parse(xml0);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001752 XMLTest("Test that the code changes do not affect normal parsing", false, doc.Error() );
Lee Thomason85492022015-05-22 11:07:45 -07001753 doc.Parse(xml1);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001754 XMLTest("Test that the second declaration is allowed", false, doc.Error() );
Lee Thomason85492022015-05-22 11:07:45 -07001755 doc.Parse(xml2);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001756 XMLTest("Test that declaration after a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001757 doc.Parse(xml3);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001758 XMLTest("Test that declaration after a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001759 doc.Parse(xml4);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001760 XMLTest("Test that declaration inside a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );
Sarat Addepalli2bb6bb52015-05-18 09:16:34 +05301761 }
Dmitry-Med9852a52015-03-25 10:17:49 +03001762
Lee Thomason85492022015-05-22 11:07:45 -07001763 {
1764 // No matter - before or after successfully parsing a text -
1765 // calling XMLDocument::Value() causes an assert in debug.
1766 const char* validXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
1767 "<first />"
1768 "<second />";
1769 XMLDocument* doc = new XMLDocument();
1770 XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
1771 doc->Parse( validXml );
Dmitry-Me68578f42017-07-03 18:21:23 +03001772 XMLTest( "Parse to test XMLDocument::Value()", false, doc->Error());
Lee Thomason85492022015-05-22 11:07:45 -07001773 XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
1774 delete doc;
1775 }
1776
Dmitry-Mea1beddf2015-05-26 16:19:21 +03001777 {
1778 XMLDocument doc;
1779 for( int i = 0; i < XML_ERROR_COUNT; i++ ) {
kezenatorec694152016-11-26 17:21:43 +10001780 doc.SetError( (XMLError)i, 0, 0, 0 );
Dmitry-Mea1beddf2015-05-26 16:19:21 +03001781 doc.ErrorName();
1782 }
1783 }
1784
Lee Thomason816d3fa2017-06-05 14:35:55 -07001785 {
Lee Thomasonb754ddf2017-06-14 15:02:38 -07001786 // Evil memory leaks.
1787 // If an XMLElement (etc) is allocated via NewElement() (etc.)
1788 // and NOT added to the XMLDocument, what happens?
1789 //
1790 // Previously (buggy):
1791 // The memory would be free'd when the XMLDocument is
1792 // destructed. But the destructor wasn't called, so that
1793 // memory allocated by the XMLElement would not be free'd.
1794 // In practice this meant strings allocated by the XMLElement
1795 // would leak. An edge case, but annoying.
1796 // Now:
1797 // The destructor is called. But the list of unlinked nodes
1798 // has to be tracked. This has a minor performance impact
1799 // that can become significant if you have a lot. (But why
1800 // would you do that?)
1801 // The only way to see this bug is in a leak tracker. This
1802 // is compiled in by default on Windows Debug.
Lee Thomason816d3fa2017-06-05 14:35:55 -07001803 {
1804 XMLDocument doc;
1805 doc.NewElement("LEAK 1");
1806 }
1807 {
1808 XMLDocument doc;
1809 XMLElement* ele = doc.NewElement("LEAK 2");
1810 doc.DeleteNode(ele);
1811 }
1812 }
1813
Lee Thomason224ef772017-06-16 09:45:26 -07001814 {
1815 // Crashing reported via email.
1816 const char* xml =
1817 "<playlist id='playlist1'>"
Lee Thomason82bb0742017-06-16 09:48:20 -07001818 "<property name='track_name'>voice</property>"
1819 "<property name='audio_track'>1</property>"
1820 "<entry out = '604' producer = '4_playlist1' in = '0' />"
1821 "<blank length = '1' />"
1822 "<entry out = '1625' producer = '3_playlist' in = '0' />"
1823 "<blank length = '2' />"
1824 "<entry out = '946' producer = '2_playlist1' in = '0' />"
1825 "<blank length = '1' />"
1826 "<entry out = '128' producer = '1_playlist1' in = '0' />"
Lee Thomason224ef772017-06-16 09:45:26 -07001827 "</playlist>";
Lee Thomason82bb0742017-06-16 09:48:20 -07001828
Lee Thomason224ef772017-06-16 09:45:26 -07001829 // It's not a good idea to delete elements as you walk the
1830 // list. I'm not sure this technically should work; but it's
1831 // an interesting test case.
1832 XMLDocument doc;
1833 XMLError err = doc.Parse(xml);
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001834 XMLTest("Crash bug parsing", XML_SUCCESS, err );
Dmitry-Meaea64c42017-06-20 18:20:15 +03001835
1836 XMLElement* playlist = doc.FirstChildElement("playlist");
Lee Thomason224ef772017-06-16 09:45:26 -07001837 XMLTest("Crash bug parsing", true, playlist != 0);
1838
1839 tinyxml2::XMLElement* entry = playlist->FirstChildElement("entry");
1840 XMLTest("Crash bug parsing", true, entry != 0);
1841 while (entry) {
1842 tinyxml2::XMLElement* todelete = entry;
1843 entry = entry->NextSiblingElement("entry");
1844 playlist->DeleteChild(todelete);
1845 };
1846 tinyxml2::XMLElement* blank = playlist->FirstChildElement("blank");
1847 while (blank) {
1848 tinyxml2::XMLElement* todelete = blank;
1849 blank = blank->NextSiblingElement("blank");
1850 playlist->DeleteChild(todelete);
1851 };
1852
1853 tinyxml2::XMLPrinter printer;
1854 playlist->Accept(&printer);
1855 printf("%s\n", printer.CStr());
1856
Lee Thomason82bb0742017-06-16 09:48:20 -07001857 // No test; it only need to not crash.
1858 // Still, wrap it up with a sanity check
1859 int nProperty = 0;
1860 for (const XMLElement* p = playlist->FirstChildElement("property"); p; p = p->NextSiblingElement("property")) {
1861 nProperty++;
1862 }
Dmitry-Me9832a5f2017-06-23 18:29:16 +03001863 XMLTest("Crash bug parsing", 2, nProperty);
Lee Thomason224ef772017-06-16 09:45:26 -07001864 }
1865
kezenatorec694152016-11-26 17:21:43 +10001866 // ----------- Line Number Tracking --------------
1867 {
Lee Thomasone90e9012016-12-24 07:34:39 -08001868 struct TestUtil: XMLVisitor
kezenatorec694152016-11-26 17:21:43 +10001869 {
1870 void TestParseError(const char *testString, const char *docStr, XMLError expected_error, int expectedLine)
1871 {
1872 XMLDocument doc;
1873 XMLError err = doc.Parse(docStr);
1874
1875 XMLTest(testString, true, doc.Error());
1876 XMLTest(testString, expected_error, err);
1877 XMLTest(testString, expectedLine, doc.GetErrorLineNum());
1878 };
1879
1880 void TestStringLines(const char *testString, const char *docStr, const char *expectedLines)
1881 {
1882 XMLDocument doc;
1883 doc.Parse(docStr);
1884 XMLTest(testString, false, doc.Error());
1885 TestDocLines(testString, doc, expectedLines);
1886 }
1887
1888 void TestFileLines(const char *testString, const char *file_name, const char *expectedLines)
1889 {
1890 XMLDocument doc;
1891 doc.LoadFile(file_name);
1892 XMLTest(testString, false, doc.Error());
1893 TestDocLines(testString, doc, expectedLines);
1894 }
1895
1896 private:
1897 DynArray<char, 10> str;
1898
1899 void Push(char type, int lineNum)
1900 {
1901 str.Push(type);
1902 str.Push(char('0' + (lineNum / 10)));
1903 str.Push(char('0' + (lineNum % 10)));
1904 }
1905
1906 bool VisitEnter(const XMLDocument& doc)
1907 {
kezenator19d8ea82016-11-29 19:50:27 +10001908 Push('D', doc.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001909 return true;
1910 }
1911 bool VisitEnter(const XMLElement& element, const XMLAttribute* firstAttribute)
1912 {
kezenator19d8ea82016-11-29 19:50:27 +10001913 Push('E', element.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001914 for (const XMLAttribute *attr = firstAttribute; attr != 0; attr = attr->Next())
kezenator19d8ea82016-11-29 19:50:27 +10001915 Push('A', attr->GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001916 return true;
1917 }
1918 bool Visit(const XMLDeclaration& declaration)
1919 {
kezenator19d8ea82016-11-29 19:50:27 +10001920 Push('L', declaration.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001921 return true;
1922 }
1923 bool Visit(const XMLText& text)
1924 {
kezenator19d8ea82016-11-29 19:50:27 +10001925 Push('T', text.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001926 return true;
1927 }
1928 bool Visit(const XMLComment& comment)
1929 {
kezenator19d8ea82016-11-29 19:50:27 +10001930 Push('C', comment.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001931 return true;
1932 }
1933 bool Visit(const XMLUnknown& unknown)
1934 {
kezenator19d8ea82016-11-29 19:50:27 +10001935 Push('U', unknown.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001936 return true;
1937 }
1938
1939 void TestDocLines(const char *testString, XMLDocument &doc, const char *expectedLines)
1940 {
1941 str.Clear();
1942 doc.Accept(this);
1943 str.Push(0);
1944 XMLTest(testString, expectedLines, str.Mem());
1945 }
Lee Thomasone90e9012016-12-24 07:34:39 -08001946 } tester;
kezenatorec694152016-11-26 17:21:43 +10001947
Lee Thomasone90e9012016-12-24 07:34:39 -08001948 tester.TestParseError("ErrorLine-Parsing", "\n<root>\n foo \n<unclosed/>", XML_ERROR_PARSING, 2);
1949 tester.TestParseError("ErrorLine-Declaration", "<root>\n<?xml version=\"1.0\"?>", XML_ERROR_PARSING_DECLARATION, 2);
1950 tester.TestParseError("ErrorLine-Mismatch", "\n<root>\n</mismatch>", XML_ERROR_MISMATCHED_ELEMENT, 2);
1951 tester.TestParseError("ErrorLine-CData", "\n<root><![CDATA[ \n foo bar \n", XML_ERROR_PARSING_CDATA, 2);
1952 tester.TestParseError("ErrorLine-Text", "\n<root>\n foo bar \n", XML_ERROR_PARSING_TEXT, 3);
1953 tester.TestParseError("ErrorLine-Comment", "\n<root>\n<!-- >\n", XML_ERROR_PARSING_COMMENT, 3);
1954 tester.TestParseError("ErrorLine-Declaration", "\n<root>\n<? >\n", XML_ERROR_PARSING_DECLARATION, 3);
1955 tester.TestParseError("ErrorLine-Unknown", "\n<root>\n<! \n", XML_ERROR_PARSING_UNKNOWN, 3);
1956 tester.TestParseError("ErrorLine-Element", "\n<root>\n<unclosed \n", XML_ERROR_PARSING_ELEMENT, 3);
1957 tester.TestParseError("ErrorLine-Attribute", "\n<root>\n<unclosed \n att\n", XML_ERROR_PARSING_ATTRIBUTE, 4);
1958 tester.TestParseError("ErrorLine-ElementClose", "\n<root>\n<unclosed \n/unexpected", XML_ERROR_PARSING_ELEMENT, 3);
kezenatorec694152016-11-26 17:21:43 +10001959
Lee Thomasone90e9012016-12-24 07:34:39 -08001960 tester.TestStringLines(
kezenatorec694152016-11-26 17:21:43 +10001961 "LineNumbers-String",
Lee Thomasone90e9012016-12-24 07:34:39 -08001962
1963 "<?xml version=\"1.0\"?>\n" // 1 Doc, DecL
1964 "<root a='b' \n" // 2 Element Attribute
1965 "c='d'> d <blah/> \n" // 3 Attribute Text Element
1966 "newline in text \n" // 4 Text
1967 "and second <zxcv/><![CDATA[\n" // 5 Element Text
1968 " cdata test ]]><!-- comment -->\n" // 6 Comment
1969 "<! unknown></root>", // 7 Unknown
1970
kezenatorec694152016-11-26 17:21:43 +10001971 "D01L01E02A02A03T03E03T04E05T05C06U07");
1972
Lee Thomasone90e9012016-12-24 07:34:39 -08001973 tester.TestStringLines(
kezenatorec694152016-11-26 17:21:43 +10001974 "LineNumbers-CRLF",
Lee Thomasone90e9012016-12-24 07:34:39 -08001975
1976 "\r\n" // 1 Doc (arguably should be line 2)
1977 "<?xml version=\"1.0\"?>\n" // 2 DecL
1978 "<root>\r\n" // 3 Element
1979 "\n" // 4
1980 "text contining new line \n" // 5 Text
1981 " and also containing crlf \r\n" // 6
1982 "<sub><![CDATA[\n" // 7 Element Text
1983 "cdata containing new line \n" // 8
1984 " and also containing cflr\r\n" // 9
1985 "]]></sub><sub2/></root>", // 10 Element
1986
kezenatorec694152016-11-26 17:21:43 +10001987 "D01L02E03T05E07T07E10");
1988
Lee Thomasone90e9012016-12-24 07:34:39 -08001989 tester.TestFileLines(
kezenatorec694152016-11-26 17:21:43 +10001990 "LineNumbers-File",
1991 "resources/utf8test.xml",
1992 "D01L01E02E03A03A03T03E04A04A04T04E05A05A05T05E06A06A06T06E07A07A07T07E08A08A08T08E09T09E10T10");
1993 }
1994
Lee Thomason85492022015-05-22 11:07:45 -07001995 // ----------- Performance tracking --------------
Lee Thomason6f381b72012-03-02 12:59:39 -08001996 {
1997#if defined( _MSC_VER )
1998 __int64 start, end, freq;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001999 QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
Lee Thomason6f381b72012-03-02 12:59:39 -08002000#endif
2001
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002002 FILE* perfFP = fopen("resources/dream.xml", "r");
2003 fseek(perfFP, 0, SEEK_END);
Armagetron3c21d6f2016-10-13 13:31:23 +02002004 long size = ftell(perfFP);
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002005 fseek(perfFP, 0, SEEK_SET);
Lee Thomason6f381b72012-03-02 12:59:39 -08002006
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002007 char* mem = new char[size + 1];
2008 fread(mem, size, 1, perfFP);
2009 fclose(perfFP);
Lee Thomason6f381b72012-03-02 12:59:39 -08002010 mem[size] = 0;
2011
2012#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002013 QueryPerformanceCounter((LARGE_INTEGER*)&start);
Lee Thomason6f381b72012-03-02 12:59:39 -08002014#else
2015 clock_t cstart = clock();
2016#endif
Dmitry-Me68578f42017-07-03 18:21:23 +03002017 bool parseDreamXmlFailed = false;
Lee Thomason6f381b72012-03-02 12:59:39 -08002018 static const int COUNT = 10;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002019 for (int i = 0; i < COUNT; ++i) {
Lee Thomason6f381b72012-03-02 12:59:39 -08002020 XMLDocument doc;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002021 doc.Parse(mem);
Dmitry-Me68578f42017-07-03 18:21:23 +03002022 parseDreamXmlFailed = parseDreamXmlFailed || doc.Error();
Lee Thomason6f381b72012-03-02 12:59:39 -08002023 }
Dmitry-Me68578f42017-07-03 18:21:23 +03002024 XMLTest( "Parse dream.xml", false, parseDreamXmlFailed );
Lee Thomason6f381b72012-03-02 12:59:39 -08002025#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002026 QueryPerformanceCounter((LARGE_INTEGER*)&end);
Lee Thomason6f381b72012-03-02 12:59:39 -08002027#else
2028 clock_t cend = clock();
2029#endif
2030
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002031 delete[] mem;
Lee Thomason6f381b72012-03-02 12:59:39 -08002032
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07002033 static const char* note =
Lee Thomason6f381b72012-03-02 12:59:39 -08002034#ifdef DEBUG
2035 "DEBUG";
2036#else
2037 "Release";
2038#endif
2039
2040#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002041 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 -08002042#else
Lee Thomasondf4ffc02016-06-04 11:32:46 -07002043 printf("\nParsing %s of dream.xml: %.3f milli-seconds\n", note, (double)(cend - cstart) / (double)COUNT);
Lee Thomason6f381b72012-03-02 12:59:39 -08002044#endif
2045 }
2046
Lee Thomason (grinliz)7ca55582012-03-07 21:54:57 -08002047 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07002048 _CrtMemCheckpoint( &endMemState );
Lee Thomason1ff38e02012-02-14 18:18:16 -08002049
2050 _CrtMemState diffMemState;
2051 _CrtMemDifference( &diffMemState, &startMemState, &endMemState );
2052 _CrtMemDumpStatistics( &diffMemState );
Dmitry-Meed785702017-06-15 13:39:53 +03002053
2054 {
2055 int leaksBeforeExit = _CrtDumpMemoryLeaks();
2056 XMLTest( "No leaks before exit?", FALSE, leaksBeforeExit );
2057 }
Lee Thomason1ff38e02012-02-14 18:18:16 -08002058 #endif
2059
2060 printf ("\nPass %d, Fail %d\n", gPass, gFail);
Lee Thomason (grinliz)db304252013-07-31 12:24:52 -07002061
2062 return gFail;
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -08002063}