Fix vararg function in wxXml unit test broken by recent changes.
[wxWidgets.git] / tests / xml / xmltest.cpp
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"
25 #include "wx/scopedptr.h"
26 #include "wx/sstream.h"
27
28 #include <stdarg.h>
29
30 // ----------------------------------------------------------------------------
31 // helpers for testing XML tree
32 // ----------------------------------------------------------------------------
33
34 namespace
35 {
36
37 void CheckXml(const wxXmlNode *n, ...)
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 );
51 CPPUNIT_ASSERT_EQUAL( childName, child->GetName() );
52 CPPUNIT_ASSERT( child->GetChildren() == NULL );
53 CPPUNIT_ASSERT( child->GetParent() == n );
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
69 class XmlTestCase : public CppUnit::TestCase
70 {
71 public:
72 XmlTestCase() {}
73
74 private:
75 CPPUNIT_TEST_SUITE( XmlTestCase );
76 CPPUNIT_TEST( InsertChild );
77 CPPUNIT_TEST( InsertChildAfter );
78 CPPUNIT_TEST( LoadSave );
79 CPPUNIT_TEST( CDATA );
80 CPPUNIT_TEST( PI );
81 CPPUNIT_TEST( Escaping );
82 CPPUNIT_TEST( DetachRoot );
83 CPPUNIT_TEST( AppendToProlog );
84 CPPUNIT_TEST_SUITE_END();
85
86 void InsertChild();
87 void InsertChildAfter();
88 void LoadSave();
89 void CDATA();
90 void PI();
91 void Escaping();
92 void DetachRoot();
93 void AppendToProlog();
94
95 DECLARE_NO_COPY_CLASS(XmlTestCase)
96 };
97
98 // register in the unnamed registry so that these tests are run by default
99 CPPUNIT_TEST_SUITE_REGISTRATION( XmlTestCase );
100
101 // also include in it's own registry so that these tests can be run alone
102 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( XmlTestCase, "XmlTestCase" );
103
104 void XmlTestCase::InsertChild()
105 {
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");
109 root->AddChild(two);
110 root->AddChild(new wxXmlNode(wxXML_ELEMENT_NODE, "3"));
111 CheckXml(root.get(), "1", "2", "3", NULL);
112
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);
118
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);
122 }
123
124 void XmlTestCase::InsertChildAfter()
125 {
126 wxScopedPtr<wxXmlNode> root(new wxXmlNode(wxXML_ELEMENT_NODE, "root"));
127
128 root->InsertChildAfter(new wxXmlNode(wxXML_ELEMENT_NODE, "1"), NULL);
129 CheckXml(root.get(), "1", NULL);
130
131 wxXmlNode *two = new wxXmlNode(wxXML_ELEMENT_NODE, "2");
132 root->AddChild(two);
133 wxXmlNode *three = new wxXmlNode(wxXML_ELEMENT_NODE, "3");
134 root->AddChild(three);
135 CheckXml(root.get(), "1", "2", "3", NULL);
136
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);
142
143 // and at the end:
144 root->InsertChildAfter(new wxXmlNode(wxXML_ELEMENT_NODE, "C"), three);
145 CheckXml(root.get(), "1", "A", "2", "B", "3", "C", NULL);
146 }
147
148 void XmlTestCase::LoadSave()
149 {
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
152 // correctly
153 //
154 // Also note that there should be no blank lines here as they disappear
155 // after saving.
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"
161 " <children>\n"
162 " <grandchild id=\"1\"/>\n"
163 " </children>\n"
164 " <subobject/>\n"
165 " </object>\n"
166 "</resource>\n"
167 ;
168
169 wxStringInputStream sis(xmlText);
170
171 wxXmlDocument doc;
172 CPPUNIT_ASSERT( doc.Load(sis) );
173
174 wxStringOutputStream sos;
175 CPPUNIT_ASSERT( doc.Save(sos) );
176
177 CPPUNIT_ASSERT_EQUAL( xmlText, sos.GetString() );
178
179
180 #if wxUSE_UNICODE
181 const char *utf8xmlText =
182 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
183 "<word>\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"
186 "</word>\n"
187 ;
188
189 wxStringInputStream sis8(wxString::FromUTF8(utf8xmlText));
190 CPPUNIT_ASSERT( doc.Load(sis8) );
191
192 // this contents can't be represented in Latin-1 as it contains Cyrillic
193 // letters
194 doc.SetFileEncoding("ISO-8859-1");
195 CPPUNIT_ASSERT( !doc.Save(sos) );
196
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
204
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"
212 " <children>\n"
213 " <grandchild id=\"1\"/>\n"
214 " </children>\n"
215 " <subobject/>\n"
216 " </object>\n"
217 "</resource>\n"
218 "<!-- Trailing comment -->\n"
219 ;
220
221 wxStringInputStream sisp(xmlTextProlog);
222 CPPUNIT_ASSERT( doc.Load(sisp, "UTF-8") );
223
224 wxStringOutputStream sosp;
225 CPPUNIT_ASSERT( doc.Save(sosp) );
226
227 CPPUNIT_ASSERT_EQUAL( xmlTextProlog, sosp.GetString() );
228 }
229
230 void XmlTestCase::CDATA()
231 {
232 const char *xmlText =
233 "<?xml version=\"1.0\" encoding=\"windows-1252\"?>\n"
234 "<name>\n"
235 " <![CDATA[Giovanni Mittone]]>\n"
236 "</name>\n"
237 ;
238
239 wxStringInputStream sis(xmlText);
240 wxXmlDocument doc;
241 CPPUNIT_ASSERT( doc.Load(sis) );
242
243 wxXmlNode *n = doc.GetRoot();
244 CPPUNIT_ASSERT( n );
245
246 n = n->GetChildren();
247 CPPUNIT_ASSERT( n );
248
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
251 // is not
252 CPPUNIT_ASSERT_EQUAL( "Giovanni Mittone", n->GetContent() );
253 }
254
255 void XmlTestCase::PI()
256 {
257 const char *xmlText =
258 "<?xml version=\"1.0\" encoding=\"windows-1252\"?>\n"
259 "<root>\n"
260 " <?robot index=\"no\" follow=\"no\"?>\n"
261 "</root>\n"
262 ;
263
264 wxStringInputStream sis(xmlText);
265 wxXmlDocument doc;
266 CPPUNIT_ASSERT( doc.Load(sis) );
267
268 wxXmlNode *n = doc.GetRoot();
269 CPPUNIT_ASSERT( n );
270
271 n = n->GetChildren();
272 CPPUNIT_ASSERT( n );
273
274 CPPUNIT_ASSERT_EQUAL( "index=\"no\" follow=\"no\"", n->GetContent() );
275 }
276
277 void XmlTestCase::Escaping()
278 {
279 // Verify that attribute values are escaped correctly, see
280 // http://trac.wxwidgets.org/ticket/12275
281
282 const char *xmlText =
283 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
284 "<root text=\"hello&#xD;&#xA;this is a new line\">\n"
285 " <x/>\n"
286 "</root>\n"
287 ;
288
289 wxStringInputStream sis(xmlText);
290
291 wxXmlDocument doc;
292 CPPUNIT_ASSERT( doc.Load(sis) );
293
294 wxStringOutputStream sos;
295 CPPUNIT_ASSERT( doc.Save(sos) );
296
297 CPPUNIT_ASSERT_EQUAL( xmlText, sos.GetString() );
298 }
299
300 void XmlTestCase::DetachRoot()
301 {
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"
309 " <children>\n"
310 " <grandchild id=\"1\"/>\n"
311 " </children>\n"
312 " <subobject/>\n"
313 " </object>\n"
314 "</resource>\n"
315 "<!-- Trailing comment -->\n"
316 ;
317 const char *xmlTextHtm =
318 "<?xml version=\"1.0\" encoding=\"windows-1252\"?>\n"
319 "<html>\n"
320 " <head>\n"
321 " <title>Testing wxXml</title>\n"
322 " </head>\n"
323 " <body>\n"
324 " <p>Some body text</p>\n"
325 " </body>\n"
326 "</html>\n"
327 ;
328 wxXmlDocument doc;
329
330 wxStringInputStream sish(xmlTextHtm);
331 CPPUNIT_ASSERT( doc.Load(sish) );
332
333 wxXmlNode *root = doc.DetachRoot();
334
335 wxStringInputStream sisp(xmlTextProlog);
336 CPPUNIT_ASSERT( doc.Load(sisp) );
337
338 doc.SetRoot(root);
339
340 wxStringOutputStream sos;
341 CPPUNIT_ASSERT( doc.Save(sos) );
342
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"
347 "<html>\n"
348 " <head>\n"
349 " <title>Testing wxXml</title>\n"
350 " </head>\n"
351 " <body>\n"
352 " <p>Some body text</p>\n"
353 " </body>\n"
354 "</html>\n"
355 "<!-- Trailing comment -->\n"
356 ;
357 CPPUNIT_ASSERT_EQUAL( xmlTextResult1, sos.GetString() );
358
359 wxStringInputStream sisp2(xmlTextProlog);
360 CPPUNIT_ASSERT( doc.Load(sisp2) );
361
362 root = doc.DetachRoot();
363
364 wxStringInputStream sish2(xmlTextHtm);
365 CPPUNIT_ASSERT( doc.Load(sish2) );
366
367 doc.SetRoot(root);
368
369 wxStringOutputStream sos2;
370 CPPUNIT_ASSERT( doc.Save(sos2) );
371
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"
377 " <children>\n"
378 " <grandchild id=\"1\"/>\n"
379 " </children>\n"
380 " <subobject/>\n"
381 " </object>\n"
382 "</resource>\n"
383 ;
384 CPPUNIT_ASSERT_EQUAL( xmlTextResult2, sos2.GetString() );
385 }
386
387 void XmlTestCase::AppendToProlog()
388 {
389 const char *xmlText =
390 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
391 "<root>\n"
392 " <p>Some text</p>\n"
393 "</root>\n"
394 ;
395 wxXmlDocument rootdoc;
396 wxStringInputStream sis(xmlText);
397 CPPUNIT_ASSERT( rootdoc.Load(sis) );
398 wxXmlNode *root = rootdoc.DetachRoot();
399
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 ");
406
407 wxXmlDocument doc;
408 doc.AppendToProlog( comment1 );
409 doc.AppendToProlog( pi );
410 doc.SetRoot( root );
411 doc.AppendToProlog( comment2 );
412
413 wxStringOutputStream sos;
414 CPPUNIT_ASSERT( doc.Save(sos) );
415
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"
421 "<root>\n"
422 " <p>Some text</p>\n"
423 "</root>\n"
424 ;
425 CPPUNIT_ASSERT_EQUAL( xmlTextResult, sos.GetString() );
426 }