]> git.saurik.com Git - wxWidgets.git/blame - tests/xml/xmltest.cpp
osx needs a refocus
[wxWidgets.git] / tests / xml / xmltest.cpp
CommitLineData
5e05df3c
VS
1///////////////////////////////////////////////////////////////////////////////
2// Name: tests/xml/xmltest.cpp
3// Purpose: XML classes unit test
4// Author: Vaclav Slavik
5// Created: 2008-03-29
6// RCS-ID: $Id$
7// Copyright: (c) 2008 Vaclav Slavik
8///////////////////////////////////////////////////////////////////////////////
9
10// ----------------------------------------------------------------------------
11// headers
12// ----------------------------------------------------------------------------
13
14#include "testprec.h"
15
16#ifdef __BORLANDC__
17 #pragma hdrstop
18#endif
19
20#ifndef WX_PRECOMP
21 #include "wx/wx.h"
22#endif // WX_PRECOMP
23
24#include "wx/xml/xml.h"
e8afaabf 25#include "wx/scopedptr.h"
4c493e0b 26#include "wx/sstream.h"
5e05df3c
VS
27
28#include <stdarg.h>
29
30// ----------------------------------------------------------------------------
31// helpers for testing XML tree
32// ----------------------------------------------------------------------------
33
34namespace
35{
36
02c94354 37void CheckXml(const wxXmlNode *n, ...)
5e05df3c
VS
38{
39 va_list args;
40 va_start(args, n);
41
42 wxXmlNode *child = n->GetChildren();
43
44 for (;;)
45 {
46 const char *childName = va_arg(args, char*);
47 if ( childName == NULL )
48 break;
49
50 CPPUNIT_ASSERT( child );
1de532f5 51 CPPUNIT_ASSERT_EQUAL( childName, child->GetName() );
5e05df3c 52 CPPUNIT_ASSERT( child->GetChildren() == NULL );
02c94354 53 CPPUNIT_ASSERT( child->GetParent() == n );
5e05df3c
VS
54
55 child = child->GetNext();
56 }
57
58 va_end(args);
59
60 CPPUNIT_ASSERT( child == NULL ); // no more children
61}
62
63} // anon namespace
64
65// ----------------------------------------------------------------------------
66// test class
67// ----------------------------------------------------------------------------
68
69class XmlTestCase : public CppUnit::TestCase
70{
71public:
72 XmlTestCase() {}
73
74private:
75 CPPUNIT_TEST_SUITE( XmlTestCase );
76 CPPUNIT_TEST( InsertChild );
43a302f2 77 CPPUNIT_TEST( InsertChildAfter );
4c493e0b 78 CPPUNIT_TEST( LoadSave );
2388960a 79 CPPUNIT_TEST( CDATA );
cee8636e 80 CPPUNIT_TEST( PI );
926649a9 81 CPPUNIT_TEST( Escaping );
cee8636e
VZ
82 CPPUNIT_TEST( DetachRoot );
83 CPPUNIT_TEST( AppendToProlog );
6f24b817 84 CPPUNIT_TEST( SetRoot );
0b3e395a 85 CPPUNIT_TEST( CopyNode );
5e05df3c
VS
86 CPPUNIT_TEST_SUITE_END();
87
88 void InsertChild();
43a302f2 89 void InsertChildAfter();
4c493e0b 90 void LoadSave();
2388960a 91 void CDATA();
cee8636e 92 void PI();
926649a9 93 void Escaping();
cee8636e
VZ
94 void DetachRoot();
95 void AppendToProlog();
6f24b817 96 void SetRoot();
0b3e395a 97 void CopyNode();
5e05df3c
VS
98
99 DECLARE_NO_COPY_CLASS(XmlTestCase)
100};
101
102// register in the unnamed registry so that these tests are run by default
103CPPUNIT_TEST_SUITE_REGISTRATION( XmlTestCase );
104
e3778b4d 105// also include in its own registry so that these tests can be run alone
5e05df3c
VS
106CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( XmlTestCase, "XmlTestCase" );
107
108void XmlTestCase::InsertChild()
109{
e8afaabf 110 wxScopedPtr<wxXmlNode> root(new wxXmlNode(wxXML_ELEMENT_NODE, "root"));
5e05df3c
VS
111 root->AddChild(new wxXmlNode(wxXML_ELEMENT_NODE, "1"));
112 wxXmlNode *two = new wxXmlNode(wxXML_ELEMENT_NODE, "2");
113 root->AddChild(two);
114 root->AddChild(new wxXmlNode(wxXML_ELEMENT_NODE, "3"));
02c94354 115 CheckXml(root.get(), "1", "2", "3", NULL);
5e05df3c
VS
116
117 // check inserting in front:
118 root->InsertChild(new wxXmlNode(wxXML_ELEMENT_NODE, "A"), NULL);
02c94354 119 CheckXml(root.get(), "A", "1", "2", "3", NULL);
5e05df3c 120 root->InsertChild(new wxXmlNode(wxXML_ELEMENT_NODE, "B"), root->GetChildren());
02c94354 121 CheckXml(root.get(), "B", "A", "1", "2", "3", NULL);
5e05df3c
VS
122
123 // and in the middle:
124 root->InsertChild(new wxXmlNode(wxXML_ELEMENT_NODE, "C"), two);
02c94354 125 CheckXml(root.get(), "B", "A", "1", "C", "2", "3", NULL);
5e05df3c 126}
43a302f2
VS
127
128void XmlTestCase::InsertChildAfter()
129{
e8afaabf 130 wxScopedPtr<wxXmlNode> root(new wxXmlNode(wxXML_ELEMENT_NODE, "root"));
43a302f2
VS
131
132 root->InsertChildAfter(new wxXmlNode(wxXML_ELEMENT_NODE, "1"), NULL);
02c94354 133 CheckXml(root.get(), "1", NULL);
43a302f2
VS
134
135 wxXmlNode *two = new wxXmlNode(wxXML_ELEMENT_NODE, "2");
136 root->AddChild(two);
137 wxXmlNode *three = new wxXmlNode(wxXML_ELEMENT_NODE, "3");
138 root->AddChild(three);
02c94354 139 CheckXml(root.get(), "1", "2", "3", NULL);
43a302f2
VS
140
141 // check inserting in the middle:
142 root->InsertChildAfter(new wxXmlNode(wxXML_ELEMENT_NODE, "A"), root->GetChildren());
02c94354 143 CheckXml(root.get(), "1", "A", "2", "3", NULL);
43a302f2 144 root->InsertChildAfter(new wxXmlNode(wxXML_ELEMENT_NODE, "B"), two);
02c94354 145 CheckXml(root.get(), "1", "A", "2", "B", "3", NULL);
43a302f2
VS
146
147 // and at the end:
148 root->InsertChildAfter(new wxXmlNode(wxXML_ELEMENT_NODE, "C"), three);
02c94354 149 CheckXml(root.get(), "1", "A", "2", "B", "3", "C", NULL);
43a302f2 150}
4c493e0b
VZ
151
152void XmlTestCase::LoadSave()
153{
154 // NB: this is not real XRC but rather some XRC-like XML fragment which
155 // exercises different XML constructs to check that they're saved back
156 // correctly
157 //
158 // Also note that there should be no blank lines here as they disappear
159 // after saving.
160 const char *xmlText =
161"<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"
162"<resource xmlns=\"http://www.wxwidgets.org/wxxrc\" version=\"2.3.0.1\">\n"
cee8636e 163" <!-- Test comment -->\n"
4c493e0b
VZ
164" <object class=\"wxDialog\" name=\"my_dialog\">\n"
165" <children>\n"
166" <grandchild id=\"1\"/>\n"
167" </children>\n"
168" <subobject/>\n"
169" </object>\n"
170"</resource>\n"
171 ;
172
173 wxStringInputStream sis(xmlText);
174
175 wxXmlDocument doc;
176 CPPUNIT_ASSERT( doc.Load(sis) );
177
178 wxStringOutputStream sos;
179 CPPUNIT_ASSERT( doc.Save(sos) );
180
181 CPPUNIT_ASSERT_EQUAL( xmlText, sos.GetString() );
e767076e
VZ
182
183
87f528f1 184#if wxUSE_UNICODE
e767076e
VZ
185 const char *utf8xmlText =
186"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
187"<word>\n"
188" <lang name=\"fr\">\xc3\xa9t\xc3\xa9</lang>\n"
189" <lang name=\"ru\">\xd0\xbb\xd0\xb5\xd1\x82\xd0\xbe</lang>\n"
190"</word>\n"
191 ;
192
193 wxStringInputStream sis8(wxString::FromUTF8(utf8xmlText));
194 CPPUNIT_ASSERT( doc.Load(sis8) );
195
196 // this contents can't be represented in Latin-1 as it contains Cyrillic
197 // letters
198 doc.SetFileEncoding("ISO-8859-1");
199 CPPUNIT_ASSERT( !doc.Save(sos) );
200
201 // but it should work in UTF-8
202 wxStringOutputStream sos8;
203 doc.SetFileEncoding("UTF-8");
204 CPPUNIT_ASSERT( doc.Save(sos8) );
a0871132
VZ
205 CPPUNIT_ASSERT_EQUAL( wxString(utf8xmlText),
206 wxString(sos8.GetString().ToUTF8()) );
87f528f1 207#endif // wxUSE_UNICODE
cee8636e
VZ
208
209 const char *xmlTextProlog =
210"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
211"<!-- Prolog comment -->\n"
212"<?xml-stylesheet href=\"style.css\" type=\"text/css\"?>\n"
213"<resource xmlns=\"http://www.wxwidgets.org/wxxrc\" version=\"2.3.0.1\">\n"
214" <!-- Test comment -->\n"
215" <object class=\"wxDialog\" name=\"my_dialog\">\n"
216" <children>\n"
217" <grandchild id=\"1\"/>\n"
218" </children>\n"
219" <subobject/>\n"
220" </object>\n"
221"</resource>\n"
222"<!-- Trailing comment -->\n"
223 ;
224
225 wxStringInputStream sisp(xmlTextProlog);
226 CPPUNIT_ASSERT( doc.Load(sisp, "UTF-8") );
227
228 wxStringOutputStream sosp;
229 CPPUNIT_ASSERT( doc.Save(sosp) );
230
231 CPPUNIT_ASSERT_EQUAL( xmlTextProlog, sosp.GetString() );
4c493e0b
VZ
232}
233
2388960a
VZ
234void XmlTestCase::CDATA()
235{
236 const char *xmlText =
237 "<?xml version=\"1.0\" encoding=\"windows-1252\"?>\n"
238 "<name>\n"
239 " <![CDATA[Giovanni Mittone]]>\n"
240 "</name>\n"
241 ;
242
243 wxStringInputStream sis(xmlText);
244 wxXmlDocument doc;
245 CPPUNIT_ASSERT( doc.Load(sis) );
246
247 wxXmlNode *n = doc.GetRoot();
248 CPPUNIT_ASSERT( n );
249
250 n = n->GetChildren();
251 CPPUNIT_ASSERT( n );
252
a6cf6bcf
VZ
253 // check that both leading (" ") and trailing white space is not part of
254 // the node contents when CDATA is used and wxXMLDOC_KEEP_WHITESPACE_NODES
255 // is not
256 CPPUNIT_ASSERT_EQUAL( "Giovanni Mittone", n->GetContent() );
2388960a 257}
926649a9 258
cee8636e
VZ
259void XmlTestCase::PI()
260{
261 const char *xmlText =
262 "<?xml version=\"1.0\" encoding=\"windows-1252\"?>\n"
263 "<root>\n"
264 " <?robot index=\"no\" follow=\"no\"?>\n"
265 "</root>\n"
266 ;
267
268 wxStringInputStream sis(xmlText);
269 wxXmlDocument doc;
270 CPPUNIT_ASSERT( doc.Load(sis) );
271
272 wxXmlNode *n = doc.GetRoot();
273 CPPUNIT_ASSERT( n );
274
275 n = n->GetChildren();
276 CPPUNIT_ASSERT( n );
277
278 CPPUNIT_ASSERT_EQUAL( "index=\"no\" follow=\"no\"", n->GetContent() );
279}
280
926649a9
VS
281void XmlTestCase::Escaping()
282{
283 // Verify that attribute values are escaped correctly, see
284 // http://trac.wxwidgets.org/ticket/12275
285
286 const char *xmlText =
287"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
288"<root text=\"hello&#xD;&#xA;this is a new line\">\n"
289" <x/>\n"
290"</root>\n"
291 ;
292
293 wxStringInputStream sis(xmlText);
294
295 wxXmlDocument doc;
296 CPPUNIT_ASSERT( doc.Load(sis) );
297
298 wxStringOutputStream sos;
299 CPPUNIT_ASSERT( doc.Save(sos) );
300
301 CPPUNIT_ASSERT_EQUAL( xmlText, sos.GetString() );
302}
cee8636e
VZ
303
304void XmlTestCase::DetachRoot()
305{
306 const char *xmlTextProlog =
307"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
308"<!-- Prolog comment -->\n"
309"<?xml-stylesheet href=\"style.css\" type=\"text/css\"?>\n"
310"<resource xmlns=\"http://www.wxwidgets.org/wxxrc\" version=\"2.3.0.1\">\n"
311" <!-- Test comment -->\n"
312" <object class=\"wxDialog\" name=\"my_dialog\">\n"
313" <children>\n"
314" <grandchild id=\"1\"/>\n"
315" </children>\n"
316" <subobject/>\n"
317" </object>\n"
318"</resource>\n"
319"<!-- Trailing comment -->\n"
320 ;
321 const char *xmlTextHtm =
322"<?xml version=\"1.0\" encoding=\"windows-1252\"?>\n"
323"<html>\n"
324" <head>\n"
325" <title>Testing wxXml</title>\n"
326" </head>\n"
327" <body>\n"
328" <p>Some body text</p>\n"
329" </body>\n"
330"</html>\n"
331 ;
332 wxXmlDocument doc;
333
334 wxStringInputStream sish(xmlTextHtm);
335 CPPUNIT_ASSERT( doc.Load(sish) );
336
337 wxXmlNode *root = doc.DetachRoot();
338
339 wxStringInputStream sisp(xmlTextProlog);
340 CPPUNIT_ASSERT( doc.Load(sisp) );
341
342 doc.SetRoot(root);
343
344 wxStringOutputStream sos;
345 CPPUNIT_ASSERT( doc.Save(sos) );
346
347 const char *xmlTextResult1 =
348"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
349"<!-- Prolog comment -->\n"
350"<?xml-stylesheet href=\"style.css\" type=\"text/css\"?>\n"
351"<html>\n"
352" <head>\n"
353" <title>Testing wxXml</title>\n"
354" </head>\n"
355" <body>\n"
356" <p>Some body text</p>\n"
357" </body>\n"
358"</html>\n"
359"<!-- Trailing comment -->\n"
360 ;
361 CPPUNIT_ASSERT_EQUAL( xmlTextResult1, sos.GetString() );
362
363 wxStringInputStream sisp2(xmlTextProlog);
364 CPPUNIT_ASSERT( doc.Load(sisp2) );
365
366 root = doc.DetachRoot();
367
368 wxStringInputStream sish2(xmlTextHtm);
369 CPPUNIT_ASSERT( doc.Load(sish2) );
370
371 doc.SetRoot(root);
372
373 wxStringOutputStream sos2;
374 CPPUNIT_ASSERT( doc.Save(sos2) );
375
376 const char *xmlTextResult2 =
377"<?xml version=\"1.0\" encoding=\"windows-1252\"?>\n"
378"<resource xmlns=\"http://www.wxwidgets.org/wxxrc\" version=\"2.3.0.1\">\n"
379" <!-- Test comment -->\n"
380" <object class=\"wxDialog\" name=\"my_dialog\">\n"
381" <children>\n"
382" <grandchild id=\"1\"/>\n"
383" </children>\n"
384" <subobject/>\n"
385" </object>\n"
386"</resource>\n"
387 ;
388 CPPUNIT_ASSERT_EQUAL( xmlTextResult2, sos2.GetString() );
389}
390
391void XmlTestCase::AppendToProlog()
392{
393 const char *xmlText =
394"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
395"<root>\n"
396" <p>Some text</p>\n"
397"</root>\n"
398 ;
399 wxXmlDocument rootdoc;
400 wxStringInputStream sis(xmlText);
401 CPPUNIT_ASSERT( rootdoc.Load(sis) );
402 wxXmlNode *root = rootdoc.DetachRoot();
403
404 wxXmlNode *comment1 = new wxXmlNode(wxXML_COMMENT_NODE, "comment",
405 " 1st prolog entry ");
406 wxXmlNode *pi = new wxXmlNode(wxXML_PI_NODE, "xml-stylesheet",
407 "href=\"style.css\" type=\"text/css\"");
408 wxXmlNode *comment2 = new wxXmlNode(wxXML_COMMENT_NODE, "comment",
409 " 3rd prolog entry ");
410
411 wxXmlDocument doc;
412 doc.AppendToProlog( comment1 );
413 doc.AppendToProlog( pi );
414 doc.SetRoot( root );
415 doc.AppendToProlog( comment2 );
416
417 wxStringOutputStream sos;
418 CPPUNIT_ASSERT( doc.Save(sos) );
419
420 const char *xmlTextResult =
421"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
422"<!-- 1st prolog entry -->\n"
423"<?xml-stylesheet href=\"style.css\" type=\"text/css\"?>\n"
424"<!-- 3rd prolog entry -->\n"
425"<root>\n"
426" <p>Some text</p>\n"
427"</root>\n"
428 ;
429 CPPUNIT_ASSERT_EQUAL( xmlTextResult, sos.GetString() );
430}
6f24b817
VZ
431
432void XmlTestCase::SetRoot()
433{
434 wxXmlDocument doc;
435 CPPUNIT_ASSERT( !doc.IsOk() );
436 wxXmlNode *root = new wxXmlNode(wxXML_ELEMENT_NODE, "root");
437
438 // Test for the problem of http://trac.wxwidgets.org/ticket/13135
439 doc.SetRoot( root );
440 wxXmlNode *docNode = doc.GetDocumentNode();
441 CPPUNIT_ASSERT( docNode && root == docNode->GetChildren() );
442 CPPUNIT_ASSERT( doc.IsOk() );
443
444 // Other tests.
445 CPPUNIT_ASSERT( docNode == root->GetParent() );
446 doc.SetRoot(NULL); // Removes from doc but dosn't free mem, doc node left.
447 CPPUNIT_ASSERT( !doc.IsOk() );
448
449 wxXmlNode *comment = new wxXmlNode(wxXML_COMMENT_NODE, "comment", "Prolog Comment");
450 wxXmlNode *pi = new wxXmlNode(wxXML_PI_NODE, "target", "PI instructions");
451 doc.AppendToProlog(comment);
452 doc.SetRoot( root );
453 doc.AppendToProlog(pi);
454 CPPUNIT_ASSERT( doc.IsOk() );
455 wxXmlNode *node = docNode->GetChildren();
456 CPPUNIT_ASSERT( node );
457 CPPUNIT_ASSERT( node->GetType() == wxXML_COMMENT_NODE );
458 CPPUNIT_ASSERT( node->GetParent() == docNode );
459 node = node->GetNext();
460 CPPUNIT_ASSERT( node );
461 CPPUNIT_ASSERT( node->GetType() == wxXML_PI_NODE );
462 CPPUNIT_ASSERT( node->GetParent() == docNode );
463 node = node->GetNext();
464 CPPUNIT_ASSERT( node );
465 CPPUNIT_ASSERT( node->GetType() == wxXML_ELEMENT_NODE );
466 CPPUNIT_ASSERT( node->GetParent() == docNode );
467 node = node->GetNext();
468 CPPUNIT_ASSERT( !node );
469 doc.SetRoot(NULL);
470 CPPUNIT_ASSERT( !doc.IsOk() );
471 doc.SetRoot(root);
472 CPPUNIT_ASSERT( doc.IsOk() );
473}
0b3e395a
VZ
474
475void XmlTestCase::CopyNode()
476{
477 const char *xmlText =
478"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
479"<root>\n"
480" <first><sub1/><sub2/><sub3/></first>\n"
481" <second/>\n"
482"</root>\n"
483 ;
484 wxXmlDocument doc;
485 wxStringInputStream sis(xmlText);
486 CPPUNIT_ASSERT( doc.Load(sis) );
487
488 wxXmlNode* const root = doc.GetRoot();
489 CPPUNIT_ASSERT( root );
490
491 wxXmlNode* const first = root->GetChildren();
492 CPPUNIT_ASSERT( first );
493
494 wxXmlNode* const second = first->GetNext();
495 CPPUNIT_ASSERT( second );
496
497 *first = *second;
498
499 wxStringOutputStream sos;
500 CPPUNIT_ASSERT( doc.Save(sos) );
501
502 const char *xmlTextResult =
503"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
504"<root>\n"
505" <second/>\n"
506" <second/>\n"
507"</root>\n"
508 ;
509 CPPUNIT_ASSERT_EQUAL( xmlTextResult, sos.GetString() );
510}