1 | // |
2 | // XMLStreamParserTest.cpp |
3 | // |
4 | // Copyright (c) 2015, Applied Informatics Software Engineering GmbH. |
5 | // and Contributors. |
6 | // |
7 | // SPDX-License-Identifier: BSL-1.0 |
8 | // |
9 | |
10 | #include "XMLStreamParserTest.h" |
11 | #include "Poco/CppUnit/TestCaller.h" |
12 | #include "Poco/CppUnit/TestSuite.h" |
13 | #include "Poco/XML/XMLStreamParser.h" |
14 | #include "Poco/Exception.h" |
15 | #include <sstream> |
16 | #include <string> |
17 | #include <vector> |
18 | #include <iostream> |
19 | |
20 | |
21 | using namespace Poco::XML; |
22 | |
23 | |
24 | XMLStreamParserTest::XMLStreamParserTest(const std::string& name): |
25 | CppUnit::TestCase(name) |
26 | { |
27 | } |
28 | |
29 | |
30 | XMLStreamParserTest::~XMLStreamParserTest() |
31 | { |
32 | } |
33 | |
34 | |
35 | void XMLStreamParserTest::testParser() |
36 | { |
37 | // Test error handling. |
38 | // |
39 | try |
40 | { |
41 | std::istringstream is("<root><nested>X</nasted></root>" ); |
42 | XMLStreamParser p(is, "test" ); |
43 | |
44 | assertTrue (p.next() == XMLStreamParser::EV_START_ELEMENT); |
45 | assertTrue (p.next() == XMLStreamParser::EV_START_ELEMENT); |
46 | assertTrue (p.next() == XMLStreamParser::EV_CHARACTERS && p.value() == "X" ); |
47 | p.next(); |
48 | assertTrue (false); |
49 | } |
50 | catch (const Poco::Exception&) |
51 | { |
52 | // cerr << e.what () << endl; |
53 | } |
54 | |
55 | try |
56 | { |
57 | std::istringstream is("<root/>" ); |
58 | is.exceptions(std::ios_base::badbit | std::ios_base::failbit); |
59 | XMLStreamParser p(is, "test" ); |
60 | |
61 | is.setstate(std::ios_base::badbit); |
62 | p.next(); |
63 | assertTrue (false); |
64 | } |
65 | catch (const std::ios_base::failure&) |
66 | { |
67 | } |
68 | |
69 | // Test the nextExpect() functionality. |
70 | // |
71 | { |
72 | std::istringstream is("<root/>" ); |
73 | XMLStreamParser p(is, "test" ); |
74 | p.nextExpect(XMLStreamParser::EV_START_ELEMENT, "root" ); |
75 | p.nextExpect(XMLStreamParser::EV_END_ELEMENT); |
76 | } |
77 | |
78 | try |
79 | { |
80 | std::istringstream is("<root/>" ); |
81 | XMLStreamParser p(is, "test" ); |
82 | p.nextExpect(XMLStreamParser::EV_END_ELEMENT); |
83 | assertTrue (false); |
84 | } |
85 | catch (const Poco::Exception&) |
86 | { |
87 | // cerr << e.what () << endl; |
88 | } |
89 | |
90 | try |
91 | { |
92 | std::istringstream is("<root/>" ); |
93 | XMLStreamParser p(is, "test" ); |
94 | p.nextExpect(XMLStreamParser::EV_START_ELEMENT, "root1" ); |
95 | assertTrue (false); |
96 | } |
97 | catch (const Poco::Exception&) |
98 | { |
99 | // cerr << e.what () << endl; |
100 | } |
101 | |
102 | // Test nextExpect() with content setting. |
103 | // |
104 | { |
105 | std::istringstream is("<root> </root>" ); |
106 | XMLStreamParser p(is, "empty" ); |
107 | |
108 | p.nextExpect(XMLStreamParser::EV_START_ELEMENT, "root" , Content::Empty); |
109 | p.nextExpect(XMLStreamParser::EV_END_ELEMENT); |
110 | p.nextExpect(XMLStreamParser::EV_EOF); |
111 | } |
112 | |
113 | // Test namespace declarations. |
114 | // |
115 | { |
116 | // Followup end element event that should be precedeeded by end |
117 | // namespace declaration. |
118 | // |
119 | std::istringstream is("<root xmlns:a='a'/>" ); |
120 | XMLStreamParser p(is, "test" , XMLStreamParser::RECEIVE_DEFAULT | XMLStreamParser::RECEIVE_NAMESPACE_DECLS); |
121 | |
122 | p.nextExpect(XMLStreamParser::EV_START_ELEMENT, "root" ); |
123 | p.nextExpect(XMLStreamParser::EV_START_NAMESPACE_DECL); |
124 | p.nextExpect(XMLStreamParser::EV_END_NAMESPACE_DECL); |
125 | p.nextExpect(XMLStreamParser::EV_END_ELEMENT); |
126 | } |
127 | |
128 | // Test value extraction. |
129 | // |
130 | { |
131 | std::istringstream is("<root>123</root>" ); |
132 | XMLStreamParser p(is, "test" ); |
133 | p.nextExpect(XMLStreamParser::EV_START_ELEMENT, "root" ); |
134 | p.nextExpect(XMLStreamParser::EV_CHARACTERS); |
135 | assertTrue (p.value<int>() == 123); |
136 | p.nextExpect(XMLStreamParser::EV_END_ELEMENT); |
137 | } |
138 | |
139 | // Test attribute maps. |
140 | // |
141 | { |
142 | std::istringstream is("<root a='a' b='b' d='123' t='true'/>" ); |
143 | XMLStreamParser p(is, "test" ); |
144 | p.nextExpect(XMLStreamParser::EV_START_ELEMENT, "root" ); |
145 | |
146 | assertTrue (p.attribute("a" ) == "a" ); |
147 | assertTrue (p.attribute("b" , "B" ) == "b" ); |
148 | assertTrue (p.attribute("c" , "C" ) == "C" ); |
149 | assertTrue (p.attribute<int>("d" ) == 123); |
150 | assertTrue (p.attribute<bool>("t" ) == true); |
151 | assertTrue (p.attribute("f" , false) == false); |
152 | |
153 | p.nextExpect(XMLStreamParser::EV_END_ELEMENT); |
154 | } |
155 | |
156 | { |
157 | std::istringstream is("<root a='a'><nested a='A'><inner/></nested></root>" ); |
158 | XMLStreamParser p(is, "test" ); |
159 | p.nextExpect(XMLStreamParser::EV_START_ELEMENT, "root" ); |
160 | assertTrue (p.attribute("a" ) == "a" ); |
161 | assertTrue (p.peek() == XMLStreamParser::EV_START_ELEMENT && p.localName() == "nested" ); |
162 | assertTrue (p.attribute("a" ) == "a" ); |
163 | p.nextExpect(XMLStreamParser::EV_START_ELEMENT, "nested" ); |
164 | assertTrue (p.attribute("a" ) == "A" ); |
165 | p.nextExpect(XMLStreamParser::EV_START_ELEMENT, "inner" ); |
166 | assertTrue (p.attribute("a" , "" ) == "" ); |
167 | p.nextExpect(XMLStreamParser::EV_END_ELEMENT); |
168 | assertTrue (p.attribute("a" ) == "A" ); |
169 | assertTrue (p.peek() == XMLStreamParser::EV_END_ELEMENT); |
170 | assertTrue (p.attribute("a" ) == "A" ); // Still valid. |
171 | p.nextExpect(XMLStreamParser::EV_END_ELEMENT); |
172 | assertTrue (p.attribute("a" ) == "a" ); |
173 | p.nextExpect(XMLStreamParser::EV_END_ELEMENT); |
174 | assertTrue (p.attribute("a" , "" ) == "" ); |
175 | } |
176 | |
177 | try |
178 | { |
179 | std::istringstream is("<root a='a' b='b'/>" ); |
180 | XMLStreamParser p(is, "test" ); |
181 | p.nextExpect(XMLStreamParser::EV_START_ELEMENT, "root" ); |
182 | assertTrue (p.attribute("a" ) == "a" ); |
183 | p.nextExpect(XMLStreamParser::EV_END_ELEMENT); |
184 | assertTrue (false); |
185 | } |
186 | catch (const Poco::Exception&) |
187 | { |
188 | // cerr << e.what () << endl; |
189 | } |
190 | |
191 | try |
192 | { |
193 | std::istringstream is("<root a='abc'/>" ); |
194 | XMLStreamParser p(is, "test" ); |
195 | p.nextExpect(XMLStreamParser::EV_START_ELEMENT, "root" ); |
196 | p.attribute<int>("a" ); |
197 | assertTrue (false); |
198 | } |
199 | catch (const Poco::Exception&) |
200 | { |
201 | // cerr << e.what () << endl; |
202 | } |
203 | |
204 | // Test peeking and getting the current event. |
205 | // |
206 | { |
207 | std::istringstream is("<root x='x'>x<nested/></root>" ); |
208 | XMLStreamParser p(is, "peek" , XMLStreamParser::RECEIVE_DEFAULT | XMLStreamParser::RECEIVE_ATTRIBUTES_EVENT); |
209 | |
210 | assertTrue (p.event() == XMLStreamParser::EV_EOF); |
211 | |
212 | assertTrue (p.peek() == XMLStreamParser::EV_START_ELEMENT); |
213 | assertTrue (p.next() == XMLStreamParser::EV_START_ELEMENT); |
214 | assertTrue (p.event() == XMLStreamParser::EV_START_ELEMENT); |
215 | |
216 | assertTrue (p.peek() == XMLStreamParser::EV_START_ATTRIBUTE); |
217 | assertTrue (p.event() == XMLStreamParser::EV_START_ATTRIBUTE); |
218 | assertTrue (p.next() == XMLStreamParser::EV_START_ATTRIBUTE); |
219 | |
220 | assertTrue (p.peek() == XMLStreamParser::EV_CHARACTERS && p.value() == "x" ); |
221 | assertTrue (p.next() == XMLStreamParser::EV_CHARACTERS && p.value() == "x" ); |
222 | assertTrue (p.event() == XMLStreamParser::EV_CHARACTERS && p.value() == "x" ); |
223 | |
224 | assertTrue (p.peek() == XMLStreamParser::EV_END_ATTRIBUTE); |
225 | assertTrue (p.event() == XMLStreamParser::EV_END_ATTRIBUTE); |
226 | assertTrue (p.next() == XMLStreamParser::EV_END_ATTRIBUTE); |
227 | |
228 | assertTrue (p.peek() == XMLStreamParser::EV_CHARACTERS && p.value() == "x" ); |
229 | assertTrue (p.next() == XMLStreamParser::EV_CHARACTERS && p.value() == "x" ); |
230 | assertTrue (p.event() == XMLStreamParser::EV_CHARACTERS && p.value() == "x" ); |
231 | |
232 | assertTrue (p.peek() == XMLStreamParser::EV_START_ELEMENT); |
233 | assertTrue (p.next() == XMLStreamParser::EV_START_ELEMENT); |
234 | assertTrue (p.event() == XMLStreamParser::EV_START_ELEMENT); |
235 | |
236 | assertTrue (p.peek() == XMLStreamParser::EV_END_ELEMENT); |
237 | assertTrue (p.next() == XMLStreamParser::EV_END_ELEMENT); |
238 | assertTrue (p.event() == XMLStreamParser::EV_END_ELEMENT); |
239 | |
240 | assertTrue (p.peek() == XMLStreamParser::EV_END_ELEMENT); |
241 | assertTrue (p.next() == XMLStreamParser::EV_END_ELEMENT); |
242 | assertTrue (p.event() == XMLStreamParser::EV_END_ELEMENT); |
243 | |
244 | assertTrue (p.peek() == XMLStreamParser::EV_EOF); |
245 | assertTrue (p.next() == XMLStreamParser::EV_EOF); |
246 | assertTrue (p.event() == XMLStreamParser::EV_EOF); |
247 | } |
248 | |
249 | // Test content processing. |
250 | // |
251 | |
252 | // empty |
253 | // |
254 | { |
255 | std::istringstream is("<root x=' x '> \n\t </root>" ); |
256 | XMLStreamParser p(is, "empty" , XMLStreamParser::RECEIVE_DEFAULT | XMLStreamParser::RECEIVE_ATTRIBUTES_EVENT); |
257 | |
258 | assertTrue (p.next() == XMLStreamParser::EV_START_ELEMENT); |
259 | p.content(Content::Empty); |
260 | assertTrue (p.next() == XMLStreamParser::EV_START_ATTRIBUTE); |
261 | assertTrue (p.next() == XMLStreamParser::EV_CHARACTERS && p.value() == " x " ); |
262 | assertTrue (p.next() == XMLStreamParser::EV_END_ATTRIBUTE); |
263 | assertTrue (p.next() == XMLStreamParser::EV_END_ELEMENT); |
264 | assertTrue (p.next() == XMLStreamParser::EV_EOF); |
265 | } |
266 | |
267 | try |
268 | { |
269 | std::istringstream is("<root> \n & X \t </root>" ); |
270 | XMLStreamParser p(is, "empty" ); |
271 | |
272 | assertTrue (p.next() == XMLStreamParser::EV_START_ELEMENT); |
273 | p.content(Content::Empty); |
274 | p.next(); |
275 | assertTrue (false); |
276 | } |
277 | catch (const Poco::Exception&) |
278 | { |
279 | // cerr << e.what () << endl; |
280 | } |
281 | |
282 | // simple |
283 | // |
284 | { |
285 | std::istringstream is("<root> X </root>" ); |
286 | XMLStreamParser p(is, "simple" ); |
287 | |
288 | assertTrue (p.next() == XMLStreamParser::EV_START_ELEMENT); |
289 | p.content(Content::Simple); |
290 | assertTrue (p.next() == XMLStreamParser::EV_CHARACTERS && p.value() == " X " ); |
291 | assertTrue (p.next() == XMLStreamParser::EV_END_ELEMENT); |
292 | assertTrue (p.next() == XMLStreamParser::EV_EOF); |
293 | } |
294 | |
295 | try |
296 | { |
297 | std::istringstream is("<root> ? <nested/></root>" ); |
298 | XMLStreamParser p(is, "simple" ); |
299 | |
300 | assertTrue (p.next() == XMLStreamParser::EV_START_ELEMENT); |
301 | p.content(Content::Simple); |
302 | assertTrue (p.next() == XMLStreamParser::EV_CHARACTERS && p.value() == " ? " ); |
303 | p.next(); |
304 | assertTrue (false); |
305 | } |
306 | catch (const Poco::Exception&) |
307 | { |
308 | // cerr << e.what () << endl; |
309 | } |
310 | |
311 | { |
312 | // Test content accumulation in simple content. |
313 | // |
314 | std::istringstream is("<root xmlns:a='a'>123</root>" ); |
315 | XMLStreamParser p(is, "simple" , XMLStreamParser::RECEIVE_DEFAULT | XMLStreamParser::RECEIVE_NAMESPACE_DECLS); |
316 | |
317 | assertTrue (p.next() == XMLStreamParser::EV_START_ELEMENT); |
318 | p.nextExpect(XMLStreamParser::EV_START_NAMESPACE_DECL); |
319 | p.content(Content::Simple); |
320 | assertTrue (p.next() == XMLStreamParser::EV_CHARACTERS && p.value() == "123" ); |
321 | p.nextExpect(XMLStreamParser::EV_END_NAMESPACE_DECL); |
322 | assertTrue (p.next() == XMLStreamParser::EV_END_ELEMENT); |
323 | assertTrue (p.next() == XMLStreamParser::EV_EOF); |
324 | } |
325 | |
326 | try |
327 | { |
328 | // Test error handling in accumulation in simple content. |
329 | // |
330 | std::istringstream is("<root xmlns:a='a'>12<nested/>3</root>" ); |
331 | XMLStreamParser p(is, "simple" , XMLStreamParser::RECEIVE_DEFAULT | XMLStreamParser::RECEIVE_NAMESPACE_DECLS); |
332 | |
333 | assertTrue (p.next() == XMLStreamParser::EV_START_ELEMENT); |
334 | p.nextExpect(XMLStreamParser::EV_START_NAMESPACE_DECL); |
335 | p.content(Content::Simple); |
336 | p.next(); |
337 | assertTrue (false); |
338 | } |
339 | catch (const Poco::Exception&) |
340 | { |
341 | // cerr << e.what () << endl; |
342 | } |
343 | |
344 | // complex |
345 | // |
346 | { |
347 | std::istringstream is("<root x=' x '>\n" |
348 | " <nested>\n" |
349 | " <inner/>\n" |
350 | " <inner> X </inner>\n" |
351 | " </nested>\n" |
352 | "</root>\n" ); |
353 | XMLStreamParser p(is, "complex" , XMLStreamParser::RECEIVE_DEFAULT | XMLStreamParser::RECEIVE_ATTRIBUTES_EVENT); |
354 | |
355 | assertTrue (p.next() == XMLStreamParser::EV_START_ELEMENT); // root |
356 | p.content(Content::Complex); |
357 | |
358 | assertTrue (p.next() == XMLStreamParser::EV_START_ATTRIBUTE); |
359 | assertTrue (p.next() == XMLStreamParser::EV_CHARACTERS && p.value() == " x " ); |
360 | assertTrue (p.next() == XMLStreamParser::EV_END_ATTRIBUTE); |
361 | |
362 | assertTrue (p.next() == XMLStreamParser::EV_START_ELEMENT); // nested |
363 | p.content(Content::Complex); |
364 | |
365 | assertTrue (p.next() == XMLStreamParser::EV_START_ELEMENT); // inner |
366 | p.content(Content::Empty); |
367 | assertTrue (p.next() == XMLStreamParser::EV_END_ELEMENT); // inner |
368 | |
369 | assertTrue (p.next() == XMLStreamParser::EV_START_ELEMENT); // inner |
370 | p.content(Content::Simple); |
371 | assertTrue (p.next() == XMLStreamParser::EV_CHARACTERS && p.value() == " X " ); |
372 | assertTrue (p.next() == XMLStreamParser::EV_END_ELEMENT); // inner |
373 | |
374 | assertTrue (p.next() == XMLStreamParser::EV_END_ELEMENT); // nested |
375 | assertTrue (p.next() == XMLStreamParser::EV_END_ELEMENT); // root |
376 | assertTrue (p.next() == XMLStreamParser::EV_EOF); |
377 | } |
378 | |
379 | try |
380 | { |
381 | std::istringstream is("<root> \n<n/> X <n> X </n> </root>" ); |
382 | XMLStreamParser p(is, "complex" ); |
383 | |
384 | assertTrue (p.next() == XMLStreamParser::EV_START_ELEMENT); |
385 | p.content(Content::Complex); |
386 | assertTrue (p.next() == XMLStreamParser::EV_START_ELEMENT); |
387 | assertTrue (p.next() == XMLStreamParser::EV_END_ELEMENT); |
388 | p.next(); |
389 | assertTrue (false); |
390 | } |
391 | catch (const Poco::Exception&) |
392 | { |
393 | // cerr << e.what () << endl; |
394 | } |
395 | |
396 | // Test element with simple content helpers. |
397 | // |
398 | { |
399 | std::istringstream is("<root>" |
400 | " <nested>X</nested>" |
401 | " <nested/>" |
402 | " <nested>123</nested>" |
403 | " <nested>Y</nested>" |
404 | " <t:nested xmlns:t='test'>Z</t:nested>" |
405 | " <nested>234</nested>" |
406 | " <t:nested xmlns:t='test'>345</t:nested>" |
407 | " <nested>A</nested>" |
408 | " <t:nested xmlns:t='test'>B</t:nested>" |
409 | " <nested1>A</nested1>" |
410 | " <t:nested1 xmlns:t='test'>B</t:nested1>" |
411 | " <nested>1</nested>" |
412 | " <t:nested xmlns:t='test'>2</t:nested>" |
413 | " <nested1>1</nested1>" |
414 | " <t:nested1 xmlns:t='test'>2</t:nested1>" |
415 | "</root>" ); |
416 | XMLStreamParser p(is, "element" ); |
417 | |
418 | p.nextExpect(XMLStreamParser::EV_START_ELEMENT, "root" , Content::Complex); |
419 | |
420 | p.nextExpect(XMLStreamParser::EV_START_ELEMENT, "nested" ); |
421 | assertTrue (p.element() == "X" ); |
422 | |
423 | p.nextExpect(XMLStreamParser::EV_START_ELEMENT, "nested" ); |
424 | assertTrue (p.element() == "" ); |
425 | |
426 | p.nextExpect(XMLStreamParser::EV_START_ELEMENT, "nested" ); |
427 | assertTrue (p.element<unsigned int>() == 123); |
428 | |
429 | assertTrue (p.element("nested" ) == "Y" ); |
430 | assertTrue (p.element(QName("test" , "nested" )) == "Z" ); |
431 | |
432 | assertTrue (p.element<unsigned int>("nested" ) == 234); |
433 | assertTrue (p.element<unsigned int>(QName("test" , "nested" )) == 345); |
434 | |
435 | assertTrue (p.element("nested" , "a" ) == "A" ); |
436 | assertTrue (p.element(QName("test" , "nested" ), "b" ) == "B" ); |
437 | |
438 | assertTrue (p.element("nested" , "a" ) == "a" && p.element("nested1" ) == "A" ); |
439 | assertTrue (p.element(QName("test" , "nested" ), "b" ) == "b" && p.element(QName("test" , "nested1" )) == "B" ); |
440 | |
441 | assertTrue (p.element<unsigned int>("nested" , 10) == 1); |
442 | assertTrue (p.element<unsigned int>(QName("test" , "nested" ), 20) == 2); |
443 | |
444 | assertTrue (p.element<unsigned int>("nested" , 10) == 10 && p.element<unsigned int>("nested1" ) == 1); |
445 | assertTrue (p.element<unsigned int>(QName("test" , "nested" ), 20) == 20 && p.element<unsigned int>(QName("test" , "nested1" )) == 2); |
446 | |
447 | p.nextExpect(XMLStreamParser::EV_END_ELEMENT); |
448 | } |
449 | |
450 | // Test the iterator interface. |
451 | // |
452 | { |
453 | std::istringstream is("<root><nested>X</nested></root>" ); |
454 | XMLStreamParser p(is, "iterator" ); |
455 | |
456 | std::vector<XMLStreamParser::EventType> v; |
457 | |
458 | for (XMLStreamParser::Iterator i(p.begin()); i != p.end(); ++i) |
459 | v.push_back(*i); |
460 | |
461 | //for (XMLStreamParser::EventType e: p) |
462 | // v.push_back (e); |
463 | |
464 | assertTrue (v.size() == 5); |
465 | assertTrue (v[0] == XMLStreamParser::EV_START_ELEMENT); |
466 | assertTrue (v[1] == XMLStreamParser::EV_START_ELEMENT); |
467 | assertTrue (v[2] == XMLStreamParser::EV_CHARACTERS); |
468 | assertTrue (v[3] == XMLStreamParser::EV_END_ELEMENT); |
469 | assertTrue (v[4] == XMLStreamParser::EV_END_ELEMENT); |
470 | } |
471 | |
472 | // Test space extraction into the std::string value. |
473 | // |
474 | { |
475 | std::istringstream is("<root a=' a '> b </root>" ); |
476 | XMLStreamParser p(is, "test" ); |
477 | p.nextExpect(XMLStreamParser::EV_START_ELEMENT, "root" ); |
478 | assertTrue (p.attribute<std::string>("a" ) == " a " ); |
479 | p.nextExpect(XMLStreamParser::EV_CHARACTERS); |
480 | assertTrue (p.value<std::string>() == " b " ); |
481 | p.nextExpect(XMLStreamParser::EV_END_ELEMENT); |
482 | } |
483 | } |
484 | |
485 | |
486 | void XMLStreamParserTest::setUp() |
487 | { |
488 | } |
489 | |
490 | |
491 | void XMLStreamParserTest::tearDown() |
492 | { |
493 | } |
494 | |
495 | |
496 | CppUnit::Test* XMLStreamParserTest::suite() |
497 | { |
498 | CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("XMLStreamParserTest" ); |
499 | |
500 | CppUnit_addTest(pSuite, XMLStreamParserTest, testParser); |
501 | |
502 | return pSuite; |
503 | } |
504 | |