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_SUITE_END();
87 void InsertChildAfter();
93 void AppendToProlog();
95 DECLARE_NO_COPY_CLASS(XmlTestCase
)
98 // register in the unnamed registry so that these tests are run by default
99 CPPUNIT_TEST_SUITE_REGISTRATION( XmlTestCase
);
101 // also include in it's own registry so that these tests can be run alone
102 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( XmlTestCase
, "XmlTestCase" );
104 void XmlTestCase::InsertChild()
106 wxScopedPtr
<wxXmlNode
> root(new wxXmlNode(wxXML_ELEMENT_NODE
, "root"));
107 root
->AddChild(new wxXmlNode(wxXML_ELEMENT_NODE
, "1"));
108 wxXmlNode
*two
= new wxXmlNode(wxXML_ELEMENT_NODE
, "2");
110 root
->AddChild(new wxXmlNode(wxXML_ELEMENT_NODE
, "3"));
111 CheckXml(root
.get(), "1", "2", "3", NULL
);
113 // check inserting in front:
114 root
->InsertChild(new wxXmlNode(wxXML_ELEMENT_NODE
, "A"), NULL
);
115 CheckXml(root
.get(), "A", "1", "2", "3", NULL
);
116 root
->InsertChild(new wxXmlNode(wxXML_ELEMENT_NODE
, "B"), root
->GetChildren());
117 CheckXml(root
.get(), "B", "A", "1", "2", "3", NULL
);
119 // and in the middle:
120 root
->InsertChild(new wxXmlNode(wxXML_ELEMENT_NODE
, "C"), two
);
121 CheckXml(root
.get(), "B", "A", "1", "C", "2", "3", NULL
);
124 void XmlTestCase::InsertChildAfter()
126 wxScopedPtr
<wxXmlNode
> root(new wxXmlNode(wxXML_ELEMENT_NODE
, "root"));
128 root
->InsertChildAfter(new wxXmlNode(wxXML_ELEMENT_NODE
, "1"), NULL
);
129 CheckXml(root
.get(), "1", NULL
);
131 wxXmlNode
*two
= new wxXmlNode(wxXML_ELEMENT_NODE
, "2");
133 wxXmlNode
*three
= new wxXmlNode(wxXML_ELEMENT_NODE
, "3");
134 root
->AddChild(three
);
135 CheckXml(root
.get(), "1", "2", "3", NULL
);
137 // check inserting in the middle:
138 root
->InsertChildAfter(new wxXmlNode(wxXML_ELEMENT_NODE
, "A"), root
->GetChildren());
139 CheckXml(root
.get(), "1", "A", "2", "3", NULL
);
140 root
->InsertChildAfter(new wxXmlNode(wxXML_ELEMENT_NODE
, "B"), two
);
141 CheckXml(root
.get(), "1", "A", "2", "B", "3", NULL
);
144 root
->InsertChildAfter(new wxXmlNode(wxXML_ELEMENT_NODE
, "C"), three
);
145 CheckXml(root
.get(), "1", "A", "2", "B", "3", "C", NULL
);
148 void XmlTestCase::LoadSave()
150 // NB: this is not real XRC but rather some XRC-like XML fragment which
151 // exercises different XML constructs to check that they're saved back
154 // Also note that there should be no blank lines here as they disappear
156 const char *xmlText
=
157 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"
158 "<resource xmlns=\"http://www.wxwidgets.org/wxxrc\" version=\"2.3.0.1\">\n"
159 " <!-- Test comment -->\n"
160 " <object class=\"wxDialog\" name=\"my_dialog\">\n"
162 " <grandchild id=\"1\"/>\n"
169 wxStringInputStream
sis(xmlText
);
172 CPPUNIT_ASSERT( doc
.Load(sis
) );
174 wxStringOutputStream sos
;
175 CPPUNIT_ASSERT( doc
.Save(sos
) );
177 CPPUNIT_ASSERT_EQUAL( xmlText
, sos
.GetString() );
181 const char *utf8xmlText
=
182 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
184 " <lang name=\"fr\">\xc3\xa9t\xc3\xa9</lang>\n"
185 " <lang name=\"ru\">\xd0\xbb\xd0\xb5\xd1\x82\xd0\xbe</lang>\n"
189 wxStringInputStream
sis8(wxString::FromUTF8(utf8xmlText
));
190 CPPUNIT_ASSERT( doc
.Load(sis8
) );
192 // this contents can't be represented in Latin-1 as it contains Cyrillic
194 doc
.SetFileEncoding("ISO-8859-1");
195 CPPUNIT_ASSERT( !doc
.Save(sos
) );
197 // but it should work in UTF-8
198 wxStringOutputStream sos8
;
199 doc
.SetFileEncoding("UTF-8");
200 CPPUNIT_ASSERT( doc
.Save(sos8
) );
201 CPPUNIT_ASSERT_EQUAL( wxString(utf8xmlText
),
202 wxString(sos8
.GetString().ToUTF8()) );
203 #endif // wxUSE_UNICODE
205 const char *xmlTextProlog
=
206 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
207 "<!-- Prolog comment -->\n"
208 "<?xml-stylesheet href=\"style.css\" type=\"text/css\"?>\n"
209 "<resource xmlns=\"http://www.wxwidgets.org/wxxrc\" version=\"2.3.0.1\">\n"
210 " <!-- Test comment -->\n"
211 " <object class=\"wxDialog\" name=\"my_dialog\">\n"
213 " <grandchild id=\"1\"/>\n"
218 "<!-- Trailing comment -->\n"
221 wxStringInputStream
sisp(xmlTextProlog
);
222 CPPUNIT_ASSERT( doc
.Load(sisp
, "UTF-8") );
224 wxStringOutputStream sosp
;
225 CPPUNIT_ASSERT( doc
.Save(sosp
) );
227 CPPUNIT_ASSERT_EQUAL( xmlTextProlog
, sosp
.GetString() );
230 void XmlTestCase::CDATA()
232 const char *xmlText
=
233 "<?xml version=\"1.0\" encoding=\"windows-1252\"?>\n"
235 " <![CDATA[Giovanni Mittone]]>\n"
239 wxStringInputStream
sis(xmlText
);
241 CPPUNIT_ASSERT( doc
.Load(sis
) );
243 wxXmlNode
*n
= doc
.GetRoot();
246 n
= n
->GetChildren();
249 // check that both leading (" ") and trailing white space is not part of
250 // the node contents when CDATA is used and wxXMLDOC_KEEP_WHITESPACE_NODES
252 CPPUNIT_ASSERT_EQUAL( "Giovanni Mittone", n
->GetContent() );
255 void XmlTestCase::PI()
257 const char *xmlText
=
258 "<?xml version=\"1.0\" encoding=\"windows-1252\"?>\n"
260 " <?robot index=\"no\" follow=\"no\"?>\n"
264 wxStringInputStream
sis(xmlText
);
266 CPPUNIT_ASSERT( doc
.Load(sis
) );
268 wxXmlNode
*n
= doc
.GetRoot();
271 n
= n
->GetChildren();
274 CPPUNIT_ASSERT_EQUAL( "index=\"no\" follow=\"no\"", n
->GetContent() );
277 void XmlTestCase::Escaping()
279 // Verify that attribute values are escaped correctly, see
280 // http://trac.wxwidgets.org/ticket/12275
282 const char *xmlText
=
283 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
284 "<root text=\"hello
this is a new line\">\n"
289 wxStringInputStream
sis(xmlText
);
292 CPPUNIT_ASSERT( doc
.Load(sis
) );
294 wxStringOutputStream sos
;
295 CPPUNIT_ASSERT( doc
.Save(sos
) );
297 CPPUNIT_ASSERT_EQUAL( xmlText
, sos
.GetString() );
300 void XmlTestCase::DetachRoot()
302 const char *xmlTextProlog
=
303 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
304 "<!-- Prolog comment -->\n"
305 "<?xml-stylesheet href=\"style.css\" type=\"text/css\"?>\n"
306 "<resource xmlns=\"http://www.wxwidgets.org/wxxrc\" version=\"2.3.0.1\">\n"
307 " <!-- Test comment -->\n"
308 " <object class=\"wxDialog\" name=\"my_dialog\">\n"
310 " <grandchild id=\"1\"/>\n"
315 "<!-- Trailing comment -->\n"
317 const char *xmlTextHtm
=
318 "<?xml version=\"1.0\" encoding=\"windows-1252\"?>\n"
321 " <title>Testing wxXml</title>\n"
324 " <p>Some body text</p>\n"
330 wxStringInputStream
sish(xmlTextHtm
);
331 CPPUNIT_ASSERT( doc
.Load(sish
) );
333 wxXmlNode
*root
= doc
.DetachRoot();
335 wxStringInputStream
sisp(xmlTextProlog
);
336 CPPUNIT_ASSERT( doc
.Load(sisp
) );
340 wxStringOutputStream sos
;
341 CPPUNIT_ASSERT( doc
.Save(sos
) );
343 const char *xmlTextResult1
=
344 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
345 "<!-- Prolog comment -->\n"
346 "<?xml-stylesheet href=\"style.css\" type=\"text/css\"?>\n"
349 " <title>Testing wxXml</title>\n"
352 " <p>Some body text</p>\n"
355 "<!-- Trailing comment -->\n"
357 CPPUNIT_ASSERT_EQUAL( xmlTextResult1
, sos
.GetString() );
359 wxStringInputStream
sisp2(xmlTextProlog
);
360 CPPUNIT_ASSERT( doc
.Load(sisp2
) );
362 root
= doc
.DetachRoot();
364 wxStringInputStream
sish2(xmlTextHtm
);
365 CPPUNIT_ASSERT( doc
.Load(sish2
) );
369 wxStringOutputStream sos2
;
370 CPPUNIT_ASSERT( doc
.Save(sos2
) );
372 const char *xmlTextResult2
=
373 "<?xml version=\"1.0\" encoding=\"windows-1252\"?>\n"
374 "<resource xmlns=\"http://www.wxwidgets.org/wxxrc\" version=\"2.3.0.1\">\n"
375 " <!-- Test comment -->\n"
376 " <object class=\"wxDialog\" name=\"my_dialog\">\n"
378 " <grandchild id=\"1\"/>\n"
384 CPPUNIT_ASSERT_EQUAL( xmlTextResult2
, sos2
.GetString() );
387 void XmlTestCase::AppendToProlog()
389 const char *xmlText
=
390 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
392 " <p>Some text</p>\n"
395 wxXmlDocument rootdoc
;
396 wxStringInputStream
sis(xmlText
);
397 CPPUNIT_ASSERT( rootdoc
.Load(sis
) );
398 wxXmlNode
*root
= rootdoc
.DetachRoot();
400 wxXmlNode
*comment1
= new wxXmlNode(wxXML_COMMENT_NODE
, "comment",
401 " 1st prolog entry ");
402 wxXmlNode
*pi
= new wxXmlNode(wxXML_PI_NODE
, "xml-stylesheet",
403 "href=\"style.css\" type=\"text/css\"");
404 wxXmlNode
*comment2
= new wxXmlNode(wxXML_COMMENT_NODE
, "comment",
405 " 3rd prolog entry ");
408 doc
.AppendToProlog( comment1
);
409 doc
.AppendToProlog( pi
);
411 doc
.AppendToProlog( comment2
);
413 wxStringOutputStream sos
;
414 CPPUNIT_ASSERT( doc
.Save(sos
) );
416 const char *xmlTextResult
=
417 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
418 "<!-- 1st prolog entry -->\n"
419 "<?xml-stylesheet href=\"style.css\" type=\"text/css\"?>\n"
420 "<!-- 3rd prolog entry -->\n"
422 " <p>Some text</p>\n"
425 CPPUNIT_ASSERT_EQUAL( xmlTextResult
, sos
.GetString() );