1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/xml/xmltest.cpp
3 // Purpose: XML classes unit test
4 // Author: Vaclav Slavik
6 // Copyright: (c) 2008 Vaclav Slavik
7 ///////////////////////////////////////////////////////////////////////////////
9 // ----------------------------------------------------------------------------
11 // ----------------------------------------------------------------------------
23 #include "wx/xml/xml.h"
24 #include "wx/scopedptr.h"
25 #include "wx/sstream.h"
29 // ----------------------------------------------------------------------------
30 // helpers for testing XML tree
31 // ----------------------------------------------------------------------------
36 void CheckXml(const wxXmlNode
*n
, ...)
41 wxXmlNode
*child
= n
->GetChildren();
45 const char *childName
= va_arg(args
, char*);
46 if ( childName
== NULL
)
49 CPPUNIT_ASSERT( child
);
50 CPPUNIT_ASSERT_EQUAL( childName
, child
->GetName() );
51 CPPUNIT_ASSERT( child
->GetChildren() == NULL
);
52 CPPUNIT_ASSERT( child
->GetParent() == n
);
54 child
= child
->GetNext();
59 CPPUNIT_ASSERT( child
== NULL
); // no more children
64 // ----------------------------------------------------------------------------
66 // ----------------------------------------------------------------------------
68 class XmlTestCase
: public CppUnit::TestCase
74 CPPUNIT_TEST_SUITE( XmlTestCase
);
75 CPPUNIT_TEST( InsertChild
);
76 CPPUNIT_TEST( InsertChildAfter
);
77 CPPUNIT_TEST( LoadSave
);
78 CPPUNIT_TEST( CDATA
);
80 CPPUNIT_TEST( Escaping
);
81 CPPUNIT_TEST( DetachRoot
);
82 CPPUNIT_TEST( AppendToProlog
);
83 CPPUNIT_TEST( SetRoot
);
84 CPPUNIT_TEST( CopyNode
);
85 CPPUNIT_TEST_SUITE_END();
88 void InsertChildAfter();
94 void AppendToProlog();
98 DECLARE_NO_COPY_CLASS(XmlTestCase
)
101 // register in the unnamed registry so that these tests are run by default
102 CPPUNIT_TEST_SUITE_REGISTRATION( XmlTestCase
);
104 // also include in its own registry so that these tests can be run alone
105 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( XmlTestCase
, "XmlTestCase" );
107 void XmlTestCase::InsertChild()
109 wxScopedPtr
<wxXmlNode
> root(new wxXmlNode(wxXML_ELEMENT_NODE
, "root"));
110 root
->AddChild(new wxXmlNode(wxXML_ELEMENT_NODE
, "1"));
111 wxXmlNode
*two
= new wxXmlNode(wxXML_ELEMENT_NODE
, "2");
113 root
->AddChild(new wxXmlNode(wxXML_ELEMENT_NODE
, "3"));
114 CheckXml(root
.get(), "1", "2", "3", NULL
);
116 // check inserting in front:
117 root
->InsertChild(new wxXmlNode(wxXML_ELEMENT_NODE
, "A"), NULL
);
118 CheckXml(root
.get(), "A", "1", "2", "3", NULL
);
119 root
->InsertChild(new wxXmlNode(wxXML_ELEMENT_NODE
, "B"), root
->GetChildren());
120 CheckXml(root
.get(), "B", "A", "1", "2", "3", NULL
);
122 // and in the middle:
123 root
->InsertChild(new wxXmlNode(wxXML_ELEMENT_NODE
, "C"), two
);
124 CheckXml(root
.get(), "B", "A", "1", "C", "2", "3", NULL
);
127 void XmlTestCase::InsertChildAfter()
129 wxScopedPtr
<wxXmlNode
> root(new wxXmlNode(wxXML_ELEMENT_NODE
, "root"));
131 root
->InsertChildAfter(new wxXmlNode(wxXML_ELEMENT_NODE
, "1"), NULL
);
132 CheckXml(root
.get(), "1", NULL
);
134 wxXmlNode
*two
= new wxXmlNode(wxXML_ELEMENT_NODE
, "2");
136 wxXmlNode
*three
= new wxXmlNode(wxXML_ELEMENT_NODE
, "3");
137 root
->AddChild(three
);
138 CheckXml(root
.get(), "1", "2", "3", NULL
);
140 // check inserting in the middle:
141 root
->InsertChildAfter(new wxXmlNode(wxXML_ELEMENT_NODE
, "A"), root
->GetChildren());
142 CheckXml(root
.get(), "1", "A", "2", "3", NULL
);
143 root
->InsertChildAfter(new wxXmlNode(wxXML_ELEMENT_NODE
, "B"), two
);
144 CheckXml(root
.get(), "1", "A", "2", "B", "3", NULL
);
147 root
->InsertChildAfter(new wxXmlNode(wxXML_ELEMENT_NODE
, "C"), three
);
148 CheckXml(root
.get(), "1", "A", "2", "B", "3", "C", NULL
);
151 void XmlTestCase::LoadSave()
153 // NB: this is not real XRC but rather some XRC-like XML fragment which
154 // exercises different XML constructs to check that they're saved back
157 // Also note that there should be no blank lines here as they disappear
159 const char *xmlText
=
160 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"
161 "<resource xmlns=\"http://www.wxwidgets.org/wxxrc\" version=\"2.3.0.1\">\n"
162 " <!-- Test comment -->\n"
163 " <object class=\"wxDialog\" name=\"my_dialog\">\n"
165 " <grandchild id=\"1\"/>\n"
172 wxStringInputStream
sis(xmlText
);
175 CPPUNIT_ASSERT( doc
.Load(sis
) );
177 wxStringOutputStream sos
;
178 CPPUNIT_ASSERT( doc
.Save(sos
) );
180 CPPUNIT_ASSERT_EQUAL( xmlText
, sos
.GetString() );
184 const char *utf8xmlText
=
185 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
187 " <lang name=\"fr\">\xc3\xa9t\xc3\xa9</lang>\n"
188 " <lang name=\"ru\">\xd0\xbb\xd0\xb5\xd1\x82\xd0\xbe</lang>\n"
192 wxStringInputStream
sis8(wxString::FromUTF8(utf8xmlText
));
193 CPPUNIT_ASSERT( doc
.Load(sis8
) );
195 // this contents can't be represented in Latin-1 as it contains Cyrillic
197 doc
.SetFileEncoding("ISO-8859-1");
198 CPPUNIT_ASSERT( !doc
.Save(sos
) );
200 // but it should work in UTF-8
201 wxStringOutputStream sos8
;
202 doc
.SetFileEncoding("UTF-8");
203 CPPUNIT_ASSERT( doc
.Save(sos8
) );
204 CPPUNIT_ASSERT_EQUAL( wxString(utf8xmlText
),
205 wxString(sos8
.GetString().ToUTF8()) );
206 #endif // wxUSE_UNICODE
208 const char *xmlTextProlog
=
209 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
210 "<!-- Prolog comment -->\n"
211 "<?xml-stylesheet href=\"style.css\" type=\"text/css\"?>\n"
212 "<resource xmlns=\"http://www.wxwidgets.org/wxxrc\" version=\"2.3.0.1\">\n"
213 " <!-- Test comment -->\n"
214 " <object class=\"wxDialog\" name=\"my_dialog\">\n"
216 " <grandchild id=\"1\"/>\n"
221 "<!-- Trailing comment -->\n"
224 wxStringInputStream
sisp(xmlTextProlog
);
225 CPPUNIT_ASSERT( doc
.Load(sisp
, "UTF-8") );
227 wxStringOutputStream sosp
;
228 CPPUNIT_ASSERT( doc
.Save(sosp
) );
230 CPPUNIT_ASSERT_EQUAL( xmlTextProlog
, sosp
.GetString() );
233 void XmlTestCase::CDATA()
235 const char *xmlText
=
236 "<?xml version=\"1.0\" encoding=\"windows-1252\"?>\n"
238 " <![CDATA[Giovanni Mittone]]>\n"
242 wxStringInputStream
sis(xmlText
);
244 CPPUNIT_ASSERT( doc
.Load(sis
) );
246 wxXmlNode
*n
= doc
.GetRoot();
249 n
= n
->GetChildren();
252 // check that both leading (" ") and trailing white space is not part of
253 // the node contents when CDATA is used and wxXMLDOC_KEEP_WHITESPACE_NODES
255 CPPUNIT_ASSERT_EQUAL( "Giovanni Mittone", n
->GetContent() );
258 void XmlTestCase::PI()
260 const char *xmlText
=
261 "<?xml version=\"1.0\" encoding=\"windows-1252\"?>\n"
263 " <?robot index=\"no\" follow=\"no\"?>\n"
267 wxStringInputStream
sis(xmlText
);
269 CPPUNIT_ASSERT( doc
.Load(sis
) );
271 wxXmlNode
*n
= doc
.GetRoot();
274 n
= n
->GetChildren();
277 CPPUNIT_ASSERT_EQUAL( "index=\"no\" follow=\"no\"", n
->GetContent() );
280 void XmlTestCase::Escaping()
282 // Verify that attribute values are escaped correctly, see
283 // http://trac.wxwidgets.org/ticket/12275
285 const char *xmlText
=
286 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
287 "<root text=\"hello
this is a new line\">\n"
292 wxStringInputStream
sis(xmlText
);
295 CPPUNIT_ASSERT( doc
.Load(sis
) );
297 wxStringOutputStream sos
;
298 CPPUNIT_ASSERT( doc
.Save(sos
) );
300 CPPUNIT_ASSERT_EQUAL( xmlText
, sos
.GetString() );
303 void XmlTestCase::DetachRoot()
305 const char *xmlTextProlog
=
306 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
307 "<!-- Prolog comment -->\n"
308 "<?xml-stylesheet href=\"style.css\" type=\"text/css\"?>\n"
309 "<resource xmlns=\"http://www.wxwidgets.org/wxxrc\" version=\"2.3.0.1\">\n"
310 " <!-- Test comment -->\n"
311 " <object class=\"wxDialog\" name=\"my_dialog\">\n"
313 " <grandchild id=\"1\"/>\n"
318 "<!-- Trailing comment -->\n"
320 const char *xmlTextHtm
=
321 "<?xml version=\"1.0\" encoding=\"windows-1252\"?>\n"
324 " <title>Testing wxXml</title>\n"
327 " <p>Some body text</p>\n"
333 wxStringInputStream
sish(xmlTextHtm
);
334 CPPUNIT_ASSERT( doc
.Load(sish
) );
336 wxXmlNode
*root
= doc
.DetachRoot();
338 wxStringInputStream
sisp(xmlTextProlog
);
339 CPPUNIT_ASSERT( doc
.Load(sisp
) );
343 wxStringOutputStream sos
;
344 CPPUNIT_ASSERT( doc
.Save(sos
) );
346 const char *xmlTextResult1
=
347 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
348 "<!-- Prolog comment -->\n"
349 "<?xml-stylesheet href=\"style.css\" type=\"text/css\"?>\n"
352 " <title>Testing wxXml</title>\n"
355 " <p>Some body text</p>\n"
358 "<!-- Trailing comment -->\n"
360 CPPUNIT_ASSERT_EQUAL( xmlTextResult1
, sos
.GetString() );
362 wxStringInputStream
sisp2(xmlTextProlog
);
363 CPPUNIT_ASSERT( doc
.Load(sisp2
) );
365 root
= doc
.DetachRoot();
367 wxStringInputStream
sish2(xmlTextHtm
);
368 CPPUNIT_ASSERT( doc
.Load(sish2
) );
372 wxStringOutputStream sos2
;
373 CPPUNIT_ASSERT( doc
.Save(sos2
) );
375 const char *xmlTextResult2
=
376 "<?xml version=\"1.0\" encoding=\"windows-1252\"?>\n"
377 "<resource xmlns=\"http://www.wxwidgets.org/wxxrc\" version=\"2.3.0.1\">\n"
378 " <!-- Test comment -->\n"
379 " <object class=\"wxDialog\" name=\"my_dialog\">\n"
381 " <grandchild id=\"1\"/>\n"
387 CPPUNIT_ASSERT_EQUAL( xmlTextResult2
, sos2
.GetString() );
390 void XmlTestCase::AppendToProlog()
392 const char *xmlText
=
393 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
395 " <p>Some text</p>\n"
398 wxXmlDocument rootdoc
;
399 wxStringInputStream
sis(xmlText
);
400 CPPUNIT_ASSERT( rootdoc
.Load(sis
) );
401 wxXmlNode
*root
= rootdoc
.DetachRoot();
403 wxXmlNode
*comment1
= new wxXmlNode(wxXML_COMMENT_NODE
, "comment",
404 " 1st prolog entry ");
405 wxXmlNode
*pi
= new wxXmlNode(wxXML_PI_NODE
, "xml-stylesheet",
406 "href=\"style.css\" type=\"text/css\"");
407 wxXmlNode
*comment2
= new wxXmlNode(wxXML_COMMENT_NODE
, "comment",
408 " 3rd prolog entry ");
411 doc
.AppendToProlog( comment1
);
412 doc
.AppendToProlog( pi
);
414 doc
.AppendToProlog( comment2
);
416 wxStringOutputStream sos
;
417 CPPUNIT_ASSERT( doc
.Save(sos
) );
419 const char *xmlTextResult
=
420 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
421 "<!-- 1st prolog entry -->\n"
422 "<?xml-stylesheet href=\"style.css\" type=\"text/css\"?>\n"
423 "<!-- 3rd prolog entry -->\n"
425 " <p>Some text</p>\n"
428 CPPUNIT_ASSERT_EQUAL( xmlTextResult
, sos
.GetString() );
431 void XmlTestCase::SetRoot()
434 CPPUNIT_ASSERT( !doc
.IsOk() );
435 wxXmlNode
*root
= new wxXmlNode(wxXML_ELEMENT_NODE
, "root");
437 // Test for the problem of http://trac.wxwidgets.org/ticket/13135
439 wxXmlNode
*docNode
= doc
.GetDocumentNode();
440 CPPUNIT_ASSERT( docNode
&& root
== docNode
->GetChildren() );
441 CPPUNIT_ASSERT( doc
.IsOk() );
444 CPPUNIT_ASSERT( docNode
== root
->GetParent() );
445 doc
.SetRoot(NULL
); // Removes from doc but dosn't free mem, doc node left.
446 CPPUNIT_ASSERT( !doc
.IsOk() );
448 wxXmlNode
*comment
= new wxXmlNode(wxXML_COMMENT_NODE
, "comment", "Prolog Comment");
449 wxXmlNode
*pi
= new wxXmlNode(wxXML_PI_NODE
, "target", "PI instructions");
450 doc
.AppendToProlog(comment
);
452 doc
.AppendToProlog(pi
);
453 CPPUNIT_ASSERT( doc
.IsOk() );
454 wxXmlNode
*node
= docNode
->GetChildren();
455 CPPUNIT_ASSERT( node
);
456 CPPUNIT_ASSERT( node
->GetType() == wxXML_COMMENT_NODE
);
457 CPPUNIT_ASSERT( node
->GetParent() == docNode
);
458 node
= node
->GetNext();
459 CPPUNIT_ASSERT( node
);
460 CPPUNIT_ASSERT( node
->GetType() == wxXML_PI_NODE
);
461 CPPUNIT_ASSERT( node
->GetParent() == docNode
);
462 node
= node
->GetNext();
463 CPPUNIT_ASSERT( node
);
464 CPPUNIT_ASSERT( node
->GetType() == wxXML_ELEMENT_NODE
);
465 CPPUNIT_ASSERT( node
->GetParent() == docNode
);
466 node
= node
->GetNext();
467 CPPUNIT_ASSERT( !node
);
469 CPPUNIT_ASSERT( !doc
.IsOk() );
471 CPPUNIT_ASSERT( doc
.IsOk() );
474 void XmlTestCase::CopyNode()
476 const char *xmlText
=
477 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
479 " <first><sub1/><sub2/><sub3/></first>\n"
484 wxStringInputStream
sis(xmlText
);
485 CPPUNIT_ASSERT( doc
.Load(sis
) );
487 wxXmlNode
* const root
= doc
.GetRoot();
488 CPPUNIT_ASSERT( root
);
490 wxXmlNode
* const first
= root
->GetChildren();
491 CPPUNIT_ASSERT( first
);
493 wxXmlNode
* const second
= first
->GetNext();
494 CPPUNIT_ASSERT( second
);
498 wxStringOutputStream sos
;
499 CPPUNIT_ASSERT( doc
.Save(sos
) );
501 const char *xmlTextResult
=
502 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
508 CPPUNIT_ASSERT_EQUAL( xmlTextResult
, sos
.GetString() );