1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/xml/xmltest.cpp
3 // Purpose: XML classes unit test
4 // Author: Vaclav Slavik
7 // Copyright: (c) 2008 Vaclav Slavik
8 ///////////////////////////////////////////////////////////////////////////////
10 // ----------------------------------------------------------------------------
12 // ----------------------------------------------------------------------------
24 #include "wx/xml/xml.h"
25 #include "wx/scopedptr.h"
26 #include "wx/sstream.h"
30 // ----------------------------------------------------------------------------
31 // helpers for testing XML tree
32 // ----------------------------------------------------------------------------
37 void CheckXml(const wxXmlNode
*n
, ...)
42 wxXmlNode
*child
= n
->GetChildren();
46 const char *childName
= va_arg(args
, char*);
47 if ( childName
== NULL
)
50 CPPUNIT_ASSERT( child
);
51 CPPUNIT_ASSERT_EQUAL( childName
, child
->GetName() );
52 CPPUNIT_ASSERT( child
->GetChildren() == NULL
);
53 CPPUNIT_ASSERT( child
->GetParent() == n
);
55 child
= child
->GetNext();
60 CPPUNIT_ASSERT( child
== NULL
); // no more children
65 // ----------------------------------------------------------------------------
67 // ----------------------------------------------------------------------------
69 class XmlTestCase
: public CppUnit::TestCase
75 CPPUNIT_TEST_SUITE( XmlTestCase
);
76 CPPUNIT_TEST( InsertChild
);
77 CPPUNIT_TEST( InsertChildAfter
);
78 CPPUNIT_TEST( LoadSave
);
79 CPPUNIT_TEST( CDATA
);
81 CPPUNIT_TEST( Escaping
);
82 CPPUNIT_TEST( DetachRoot
);
83 CPPUNIT_TEST( AppendToProlog
);
84 CPPUNIT_TEST( SetRoot
);
85 CPPUNIT_TEST( CopyNode
);
86 CPPUNIT_TEST_SUITE_END();
89 void InsertChildAfter();
95 void AppendToProlog();
99 DECLARE_NO_COPY_CLASS(XmlTestCase
)
102 // register in the unnamed registry so that these tests are run by default
103 CPPUNIT_TEST_SUITE_REGISTRATION( XmlTestCase
);
105 // also include in its own registry so that these tests can be run alone
106 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( XmlTestCase
, "XmlTestCase" );
108 void XmlTestCase::InsertChild()
110 wxScopedPtr
<wxXmlNode
> root(new wxXmlNode(wxXML_ELEMENT_NODE
, "root"));
111 root
->AddChild(new wxXmlNode(wxXML_ELEMENT_NODE
, "1"));
112 wxXmlNode
*two
= new wxXmlNode(wxXML_ELEMENT_NODE
, "2");
114 root
->AddChild(new wxXmlNode(wxXML_ELEMENT_NODE
, "3"));
115 CheckXml(root
.get(), "1", "2", "3", NULL
);
117 // check inserting in front:
118 root
->InsertChild(new wxXmlNode(wxXML_ELEMENT_NODE
, "A"), NULL
);
119 CheckXml(root
.get(), "A", "1", "2", "3", NULL
);
120 root
->InsertChild(new wxXmlNode(wxXML_ELEMENT_NODE
, "B"), root
->GetChildren());
121 CheckXml(root
.get(), "B", "A", "1", "2", "3", NULL
);
123 // and in the middle:
124 root
->InsertChild(new wxXmlNode(wxXML_ELEMENT_NODE
, "C"), two
);
125 CheckXml(root
.get(), "B", "A", "1", "C", "2", "3", NULL
);
128 void XmlTestCase::InsertChildAfter()
130 wxScopedPtr
<wxXmlNode
> root(new wxXmlNode(wxXML_ELEMENT_NODE
, "root"));
132 root
->InsertChildAfter(new wxXmlNode(wxXML_ELEMENT_NODE
, "1"), NULL
);
133 CheckXml(root
.get(), "1", NULL
);
135 wxXmlNode
*two
= new wxXmlNode(wxXML_ELEMENT_NODE
, "2");
137 wxXmlNode
*three
= new wxXmlNode(wxXML_ELEMENT_NODE
, "3");
138 root
->AddChild(three
);
139 CheckXml(root
.get(), "1", "2", "3", NULL
);
141 // check inserting in the middle:
142 root
->InsertChildAfter(new wxXmlNode(wxXML_ELEMENT_NODE
, "A"), root
->GetChildren());
143 CheckXml(root
.get(), "1", "A", "2", "3", NULL
);
144 root
->InsertChildAfter(new wxXmlNode(wxXML_ELEMENT_NODE
, "B"), two
);
145 CheckXml(root
.get(), "1", "A", "2", "B", "3", NULL
);
148 root
->InsertChildAfter(new wxXmlNode(wxXML_ELEMENT_NODE
, "C"), three
);
149 CheckXml(root
.get(), "1", "A", "2", "B", "3", "C", NULL
);
152 void XmlTestCase::LoadSave()
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
158 // Also note that there should be no blank lines here as they disappear
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"
163 " <!-- Test comment -->\n"
164 " <object class=\"wxDialog\" name=\"my_dialog\">\n"
166 " <grandchild id=\"1\"/>\n"
173 wxStringInputStream
sis(xmlText
);
176 CPPUNIT_ASSERT( doc
.Load(sis
) );
178 wxStringOutputStream sos
;
179 CPPUNIT_ASSERT( doc
.Save(sos
) );
181 CPPUNIT_ASSERT_EQUAL( xmlText
, sos
.GetString() );
185 const char *utf8xmlText
=
186 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\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"
193 wxStringInputStream
sis8(wxString::FromUTF8(utf8xmlText
));
194 CPPUNIT_ASSERT( doc
.Load(sis8
) );
196 // this contents can't be represented in Latin-1 as it contains Cyrillic
198 doc
.SetFileEncoding("ISO-8859-1");
199 CPPUNIT_ASSERT( !doc
.Save(sos
) );
201 // but it should work in UTF-8
202 wxStringOutputStream sos8
;
203 doc
.SetFileEncoding("UTF-8");
204 CPPUNIT_ASSERT( doc
.Save(sos8
) );
205 CPPUNIT_ASSERT_EQUAL( wxString(utf8xmlText
),
206 wxString(sos8
.GetString().ToUTF8()) );
207 #endif // wxUSE_UNICODE
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"
217 " <grandchild id=\"1\"/>\n"
222 "<!-- Trailing comment -->\n"
225 wxStringInputStream
sisp(xmlTextProlog
);
226 CPPUNIT_ASSERT( doc
.Load(sisp
, "UTF-8") );
228 wxStringOutputStream sosp
;
229 CPPUNIT_ASSERT( doc
.Save(sosp
) );
231 CPPUNIT_ASSERT_EQUAL( xmlTextProlog
, sosp
.GetString() );
234 void XmlTestCase::CDATA()
236 const char *xmlText
=
237 "<?xml version=\"1.0\" encoding=\"windows-1252\"?>\n"
239 " <![CDATA[Giovanni Mittone]]>\n"
243 wxStringInputStream
sis(xmlText
);
245 CPPUNIT_ASSERT( doc
.Load(sis
) );
247 wxXmlNode
*n
= doc
.GetRoot();
250 n
= n
->GetChildren();
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
256 CPPUNIT_ASSERT_EQUAL( "Giovanni Mittone", n
->GetContent() );
259 void XmlTestCase::PI()
261 const char *xmlText
=
262 "<?xml version=\"1.0\" encoding=\"windows-1252\"?>\n"
264 " <?robot index=\"no\" follow=\"no\"?>\n"
268 wxStringInputStream
sis(xmlText
);
270 CPPUNIT_ASSERT( doc
.Load(sis
) );
272 wxXmlNode
*n
= doc
.GetRoot();
275 n
= n
->GetChildren();
278 CPPUNIT_ASSERT_EQUAL( "index=\"no\" follow=\"no\"", n
->GetContent() );
281 void XmlTestCase::Escaping()
283 // Verify that attribute values are escaped correctly, see
284 // http://trac.wxwidgets.org/ticket/12275
286 const char *xmlText
=
287 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
288 "<root text=\"hello
this is a new line\">\n"
293 wxStringInputStream
sis(xmlText
);
296 CPPUNIT_ASSERT( doc
.Load(sis
) );
298 wxStringOutputStream sos
;
299 CPPUNIT_ASSERT( doc
.Save(sos
) );
301 CPPUNIT_ASSERT_EQUAL( xmlText
, sos
.GetString() );
304 void XmlTestCase::DetachRoot()
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"
314 " <grandchild id=\"1\"/>\n"
319 "<!-- Trailing comment -->\n"
321 const char *xmlTextHtm
=
322 "<?xml version=\"1.0\" encoding=\"windows-1252\"?>\n"
325 " <title>Testing wxXml</title>\n"
328 " <p>Some body text</p>\n"
334 wxStringInputStream
sish(xmlTextHtm
);
335 CPPUNIT_ASSERT( doc
.Load(sish
) );
337 wxXmlNode
*root
= doc
.DetachRoot();
339 wxStringInputStream
sisp(xmlTextProlog
);
340 CPPUNIT_ASSERT( doc
.Load(sisp
) );
344 wxStringOutputStream sos
;
345 CPPUNIT_ASSERT( doc
.Save(sos
) );
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"
353 " <title>Testing wxXml</title>\n"
356 " <p>Some body text</p>\n"
359 "<!-- Trailing comment -->\n"
361 CPPUNIT_ASSERT_EQUAL( xmlTextResult1
, sos
.GetString() );
363 wxStringInputStream
sisp2(xmlTextProlog
);
364 CPPUNIT_ASSERT( doc
.Load(sisp2
) );
366 root
= doc
.DetachRoot();
368 wxStringInputStream
sish2(xmlTextHtm
);
369 CPPUNIT_ASSERT( doc
.Load(sish2
) );
373 wxStringOutputStream sos2
;
374 CPPUNIT_ASSERT( doc
.Save(sos2
) );
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"
382 " <grandchild id=\"1\"/>\n"
388 CPPUNIT_ASSERT_EQUAL( xmlTextResult2
, sos2
.GetString() );
391 void XmlTestCase::AppendToProlog()
393 const char *xmlText
=
394 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
396 " <p>Some text</p>\n"
399 wxXmlDocument rootdoc
;
400 wxStringInputStream
sis(xmlText
);
401 CPPUNIT_ASSERT( rootdoc
.Load(sis
) );
402 wxXmlNode
*root
= rootdoc
.DetachRoot();
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 ");
412 doc
.AppendToProlog( comment1
);
413 doc
.AppendToProlog( pi
);
415 doc
.AppendToProlog( comment2
);
417 wxStringOutputStream sos
;
418 CPPUNIT_ASSERT( doc
.Save(sos
) );
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"
426 " <p>Some text</p>\n"
429 CPPUNIT_ASSERT_EQUAL( xmlTextResult
, sos
.GetString() );
432 void XmlTestCase::SetRoot()
435 CPPUNIT_ASSERT( !doc
.IsOk() );
436 wxXmlNode
*root
= new wxXmlNode(wxXML_ELEMENT_NODE
, "root");
438 // Test for the problem of http://trac.wxwidgets.org/ticket/13135
440 wxXmlNode
*docNode
= doc
.GetDocumentNode();
441 CPPUNIT_ASSERT( docNode
&& root
== docNode
->GetChildren() );
442 CPPUNIT_ASSERT( doc
.IsOk() );
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() );
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
);
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
);
470 CPPUNIT_ASSERT( !doc
.IsOk() );
472 CPPUNIT_ASSERT( doc
.IsOk() );
475 void XmlTestCase::CopyNode()
477 const char *xmlText
=
478 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
480 " <first><sub1/><sub2/><sub3/></first>\n"
485 wxStringInputStream
sis(xmlText
);
486 CPPUNIT_ASSERT( doc
.Load(sis
) );
488 wxXmlNode
* const root
= doc
.GetRoot();
489 CPPUNIT_ASSERT( root
);
491 wxXmlNode
* const first
= root
->GetChildren();
492 CPPUNIT_ASSERT( first
);
494 wxXmlNode
* const second
= first
->GetNext();
495 CPPUNIT_ASSERT( second
);
499 wxStringOutputStream sos
;
500 CPPUNIT_ASSERT( doc
.Save(sos
) );
502 const char *xmlTextResult
=
503 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
509 CPPUNIT_ASSERT_EQUAL( xmlTextResult
, sos
.GetString() );