1 #define _CRT_SECURE_NO_WARNINGS
2 #define _SCL_SECURE_NO_WARNINGS
3 #define _SCL_SECURE_NO_DEPRECATE
4
5 #include "test.hpp"
6
7 #include <string.h>
8 #include <stdio.h>
9 #include <wchar.h>
10
11 #include <utility>
12 #include <vector>
13 #include <iterator>
14 #include <string>
15
16 #include "helpers.hpp"
17
18 using namespace pugi;
19
20 #ifdef PUGIXML_NO_STL
move_iter(I base,int n)21 template <typename I> static I move_iter(I base, int n)
22 {
23 if (n > 0) while (n--) ++base;
24 else while (n++) --base;
25 return base;
26 }
27 #else
move_iter(I base,int n)28 template <typename I> static I move_iter(I base, int n)
29 {
30 std::advance(base, n);
31 return base;
32 }
33 #endif
34
35 TEST_XML(dom_attr_bool_ops, "<node attr='1'/>")
36 {
37 generic_bool_ops_test(doc.child(STR("node")).attribute(STR("attr")));
38 }
39
40 TEST_XML(dom_attr_eq_ops, "<node attr1='1' attr2='2'/>")
41 {
42 generic_eq_ops_test(doc.child(STR("node")).attribute(STR("attr1")), doc.child(STR("node")).attribute(STR("attr2")));
43 }
44
45 TEST_XML(dom_attr_rel_ops, "<node attr1='1' attr2='2'/>")
46 {
47 generic_rel_ops_test(doc.child(STR("node")).attribute(STR("attr1")), doc.child(STR("node")).attribute(STR("attr2")));
48 }
49
50 TEST_XML(dom_attr_empty, "<node attr='1'/>")
51 {
52 generic_empty_test(doc.child(STR("node")).attribute(STR("attr")));
53 }
54
55 TEST_XML(dom_attr_next_previous_attribute, "<node attr1='1' attr2='2' />")
56 {
57 xml_attribute attr1 = doc.child(STR("node")).attribute(STR("attr1"));
58 xml_attribute attr2 = doc.child(STR("node")).attribute(STR("attr2"));
59
60 CHECK(attr1.next_attribute() == attr2);
61 CHECK(attr2.next_attribute() == xml_attribute());
62
63 CHECK(attr1.previous_attribute() == xml_attribute());
64 CHECK(attr2.previous_attribute() == attr1);
65
66 CHECK(xml_attribute().next_attribute() == xml_attribute());
67 CHECK(xml_attribute().previous_attribute() == xml_attribute());
68 }
69
70 TEST_XML(dom_attr_name_value, "<node attr='1'/>")
71 {
72 xml_attribute attr = doc.child(STR("node")).attribute(STR("attr"));
73
74 CHECK_NAME_VALUE(attr, STR("attr"), STR("1"));
75 CHECK_NAME_VALUE(xml_attribute(), STR(""), STR(""));
76 }
77
78 TEST_XML(dom_attr_as_string, "<node attr='1'/>")
79 {
80 xml_attribute attr = doc.child(STR("node")).attribute(STR("attr"));
81
82 CHECK_STRING(attr.as_string(), STR("1"));
83 CHECK_STRING(xml_attribute().as_string(), STR(""));
84 }
85
86 TEST_XML(dom_attr_as_int, "<node attr1='1' attr2='-1' attr3='-2147483648' attr4='2147483647' attr5='0'/>")
87 {
88 xml_node node = doc.child(STR("node"));
89
90 CHECK(xml_attribute().as_int() == 0);
91 CHECK(node.attribute(STR("attr1")).as_int() == 1);
92 CHECK(node.attribute(STR("attr2")).as_int() == -1);
93 CHECK(node.attribute(STR("attr3")).as_int() == -2147483647 - 1);
94 CHECK(node.attribute(STR("attr4")).as_int() == 2147483647);
95 CHECK(node.attribute(STR("attr5")).as_int() == 0);
96 }
97
98 TEST_XML(dom_attr_as_int_hex, "<node attr1='0777' attr2='0x5ab' attr3='0XFf' attr4='-0x20' attr5='-0x80000000' attr6='0x'/>")
99 {
100 xml_node node = doc.child(STR("node"));
101
102 CHECK(node.attribute(STR("attr1")).as_int() == 777); // no octal support! intentional
103 CHECK(node.attribute(STR("attr2")).as_int() == 1451);
104 CHECK(node.attribute(STR("attr3")).as_int() == 255);
105 CHECK(node.attribute(STR("attr4")).as_int() == -32);
106 CHECK(node.attribute(STR("attr5")).as_int() == -2147483647 - 1);
107 CHECK(node.attribute(STR("attr6")).as_int() == 0);
108 }
109
110 TEST_XML(dom_attr_as_uint, "<node attr1='0' attr2='1' attr3='2147483647' attr4='4294967295' attr5='0'/>")
111 {
112 xml_node node = doc.child(STR("node"));
113
114 CHECK(xml_attribute().as_uint() == 0);
115 CHECK(node.attribute(STR("attr1")).as_uint() == 0);
116 CHECK(node.attribute(STR("attr2")).as_uint() == 1);
117 CHECK(node.attribute(STR("attr3")).as_uint() == 2147483647);
118 CHECK(node.attribute(STR("attr4")).as_uint() == 4294967295u);
119 CHECK(node.attribute(STR("attr5")).as_uint() == 0);
120 }
121
122 TEST_XML(dom_attr_as_uint_hex, "<node attr1='0777' attr2='0x5ab' attr3='0XFf' attr4='0x20' attr5='0xFFFFFFFF' attr6='0x'/>")
123 {
124 xml_node node = doc.child(STR("node"));
125
126 CHECK(node.attribute(STR("attr1")).as_uint() == 777); // no octal support! intentional
127 CHECK(node.attribute(STR("attr2")).as_uint() == 1451);
128 CHECK(node.attribute(STR("attr3")).as_uint() == 255);
129 CHECK(node.attribute(STR("attr4")).as_uint() == 32);
130 CHECK(node.attribute(STR("attr5")).as_uint() == 4294967295u);
131 CHECK(node.attribute(STR("attr6")).as_uint() == 0);
132 }
133
134 TEST_XML(dom_attr_as_integer_space, "<node attr1=' \t1234' attr2='\t 0x123' attr3='- 16' attr4='- 0x10'/>")
135 {
136 xml_node node = doc.child(STR("node"));
137
138 CHECK(node.attribute(STR("attr1")).as_int() == 1234);
139 CHECK(node.attribute(STR("attr2")).as_int() == 291);
140 CHECK(node.attribute(STR("attr3")).as_int() == 0);
141 CHECK(node.attribute(STR("attr4")).as_int() == 0);
142
143 #ifdef PUGIXML_HAS_LONG_LONG
144 CHECK(node.attribute(STR("attr1")).as_llong() == 1234);
145 #endif
146 }
147
148 TEST_XML(dom_attr_as_float, "<node attr1='0' attr2='1' attr3='0.12' attr4='-5.1' attr5='3e-4' attr6='3.14159265358979323846'/>")
149 {
150 xml_node node = doc.child(STR("node"));
151
152 CHECK(xml_attribute().as_float() == 0);
153 CHECK_DOUBLE(node.attribute(STR("attr1")).as_float(), 0);
154 CHECK_DOUBLE(node.attribute(STR("attr2")).as_float(), 1);
155 CHECK_DOUBLE(node.attribute(STR("attr3")).as_float(), 0.12);
156 CHECK_DOUBLE(node.attribute(STR("attr4")).as_float(), -5.1);
157 CHECK_DOUBLE(node.attribute(STR("attr5")).as_float(), 3e-4);
158 CHECK_DOUBLE(node.attribute(STR("attr6")).as_float(), 3.14159265358979323846);
159 }
160
161 TEST_XML(dom_attr_as_double, "<node attr1='0' attr2='1' attr3='0.12' attr4='-5.1' attr5='3e-4' attr6='3.14159265358979323846'/>")
162 {
163 xml_node node = doc.child(STR("node"));
164
165 CHECK(xml_attribute().as_double() == 0);
166 CHECK_DOUBLE(node.attribute(STR("attr1")).as_double(), 0);
167 CHECK_DOUBLE(node.attribute(STR("attr2")).as_double(), 1);
168 CHECK_DOUBLE(node.attribute(STR("attr3")).as_double(), 0.12);
169 CHECK_DOUBLE(node.attribute(STR("attr4")).as_double(), -5.1);
170 CHECK_DOUBLE(node.attribute(STR("attr5")).as_double(), 3e-4);
171 CHECK_DOUBLE(node.attribute(STR("attr6")).as_double(), 3.14159265358979323846);
172 }
173
174 TEST_XML(dom_attr_as_bool, "<node attr1='0' attr2='1' attr3='true' attr4='True' attr5='Yes' attr6='yes' attr7='false'/>")
175 {
176 xml_node node = doc.child(STR("node"));
177
178 CHECK(!xml_attribute().as_bool());
179 CHECK(!node.attribute(STR("attr1")).as_bool());
180 CHECK(node.attribute(STR("attr2")).as_bool());
181 CHECK(node.attribute(STR("attr3")).as_bool());
182 CHECK(node.attribute(STR("attr4")).as_bool());
183 CHECK(node.attribute(STR("attr5")).as_bool());
184 CHECK(node.attribute(STR("attr6")).as_bool());
185 CHECK(!node.attribute(STR("attr7")).as_bool());
186 }
187
188 #ifdef PUGIXML_HAS_LONG_LONG
189 TEST_XML(dom_attr_as_llong, "<node attr1='1' attr2='-1' attr3='-9223372036854775808' attr4='9223372036854775807' attr5='0'/>")
190 {
191 xml_node node = doc.child(STR("node"));
192
193 CHECK(xml_attribute().as_llong() == 0);
194 CHECK(node.attribute(STR("attr1")).as_llong() == 1);
195 CHECK(node.attribute(STR("attr2")).as_llong() == -1);
196 CHECK(node.attribute(STR("attr3")).as_llong() == -9223372036854775807ll - 1);
197 CHECK(node.attribute(STR("attr4")).as_llong() == 9223372036854775807ll);
198 CHECK(node.attribute(STR("attr5")).as_llong() == 0);
199 }
200
201 TEST_XML(dom_attr_as_llong_hex, "<node attr1='0777' attr2='0x5ab' attr3='0XFf' attr4='-0x20' attr5='-0x8000000000000000' attr6='0x'/>")
202 {
203 xml_node node = doc.child(STR("node"));
204
205 CHECK(node.attribute(STR("attr1")).as_llong() == 777); // no octal support! intentional
206 CHECK(node.attribute(STR("attr2")).as_llong() == 1451);
207 CHECK(node.attribute(STR("attr3")).as_llong() == 255);
208 CHECK(node.attribute(STR("attr4")).as_llong() == -32);
209 CHECK(node.attribute(STR("attr5")).as_llong() == -9223372036854775807ll - 1);
210 CHECK(node.attribute(STR("attr6")).as_llong() == 0);
211 }
212
213 TEST_XML(dom_attr_as_ullong, "<node attr1='0' attr2='1' attr3='9223372036854775807' attr4='18446744073709551615' attr5='0'/>")
214 {
215 xml_node node = doc.child(STR("node"));
216
217 CHECK(xml_attribute().as_ullong() == 0);
218 CHECK(node.attribute(STR("attr1")).as_ullong() == 0);
219 CHECK(node.attribute(STR("attr2")).as_ullong() == 1);
220 CHECK(node.attribute(STR("attr3")).as_ullong() == 9223372036854775807ull);
221 CHECK(node.attribute(STR("attr4")).as_ullong() == 18446744073709551615ull);
222 CHECK(node.attribute(STR("attr5")).as_ullong() == 0);
223 }
224
225 TEST_XML(dom_attr_as_ullong_hex, "<node attr1='0777' attr2='0x5ab' attr3='0XFf' attr4='0x20' attr5='0xFFFFFFFFFFFFFFFF' attr6='0x'/>")
226 {
227 xml_node node = doc.child(STR("node"));
228
229 CHECK(node.attribute(STR("attr1")).as_ullong() == 777); // no octal support! intentional
230 CHECK(node.attribute(STR("attr2")).as_ullong() == 1451);
231 CHECK(node.attribute(STR("attr3")).as_ullong() == 255);
232 CHECK(node.attribute(STR("attr4")).as_ullong() == 32);
233 CHECK(node.attribute(STR("attr5")).as_ullong() == 18446744073709551615ull);
234 CHECK(node.attribute(STR("attr6")).as_ullong() == 0);
235 }
236 #endif
237
TEST(dom_attr_defaults)238 TEST(dom_attr_defaults)
239 {
240 xml_attribute attr;
241
242 CHECK_STRING(attr.as_string(STR("foo")), STR("foo"));
243 CHECK(attr.as_int(42) == 42);
244 CHECK(attr.as_uint(42) == 42);
245 CHECK(attr.as_double(42) == 42);
246 CHECK(attr.as_float(42) == 42);
247 CHECK(attr.as_bool(true) == true);
248
249 #ifdef PUGIXML_HAS_LONG_LONG
250 CHECK(attr.as_llong(42) == 42);
251 CHECK(attr.as_ullong(42) == 42);
252 #endif
253 }
254
255 TEST_XML(dom_attr_iterator, "<node><node1 attr1='0'/><node2 attr1='0' attr2='1'/><node3/></node>")
256 {
257 xml_node node1 = doc.child(STR("node")).child(STR("node1"));
258 xml_node node2 = doc.child(STR("node")).child(STR("node2"));
259 xml_node node3 = doc.child(STR("node")).child(STR("node3"));
260
261 CHECK(xml_node().attributes_begin() == xml_attribute_iterator());
262 CHECK(xml_node().attributes_end() == xml_attribute_iterator());
263
264 CHECK(node1.attributes_begin() == xml_attribute_iterator(node1.attribute(STR("attr1")), node1));
265 CHECK(move_iter(node1.attributes_begin(), 1) == node1.attributes_end());
266 CHECK(move_iter(node1.attributes_end(), -1) == node1.attributes_begin());
267 CHECK(*node1.attributes_begin() == node1.attribute(STR("attr1")));
268 CHECK_STRING(node1.attributes_begin()->name(), STR("attr1"));
269
270 CHECK(move_iter(node2.attributes_begin(), 2) == node2.attributes_end());
271 CHECK(move_iter(node2.attributes_end(), -2) == node2.attributes_begin());
272
273 CHECK(node3.attributes_begin() != xml_attribute_iterator());
274 CHECK(node3.attributes_begin() == node3.attributes_end());
275
276 xml_attribute_iterator it = xml_attribute_iterator(node2.attribute(STR("attr2")), node2);
277 xml_attribute_iterator itt = it;
278
279 CHECK(itt++ == it);
280 CHECK(itt == node2.attributes_end());
281
282 CHECK(itt-- == node2.attributes_end());
283 CHECK(itt == it);
284
285 CHECK(++itt == node2.attributes_end());
286 CHECK(itt == node2.attributes_end());
287
288 CHECK(--itt == it);
289 CHECK(itt == it);
290
291 CHECK(++itt != it);
292 }
293
294 TEST_XML(dom_attr_iterator_end, "<node><node1 attr1='0'/><node2 attr1='0' attr2='1'/><node3/></node>")
295 {
296 xml_node node1 = doc.child(STR("node")).child(STR("node1"));
297 xml_node node2 = doc.child(STR("node")).child(STR("node2"));
298 xml_node node3 = doc.child(STR("node")).child(STR("node3"));
299
300 CHECK(node1.attributes_end() != node2.attributes_end() && node1.attributes_end() != node3.attributes_end() && node2.attributes_end() != node3.attributes_end());
301 CHECK(node1.attributes_end() != xml_attribute_iterator() && node2.attributes_end() != xml_attribute_iterator() && node3.attributes_end() != xml_attribute_iterator());
302 }
303
304 TEST_XML(dom_attr_iterator_invalidate, "<node><node1 attr1='0'/><node2 attr1='0' attr2='1'/><node3/></node>")
305 {
306 xml_node node2 = doc.child(STR("node")).child(STR("node2"));
307
308 xml_attribute_iterator it1 = node2.attributes_begin();
309 xml_attribute_iterator it2 = move_iter(it1, 1);
310 xml_attribute_iterator it3 = move_iter(it2, 1);
311
312 CHECK(it3 == node2.attributes_end());
313
314 // removing attr2, it2 is invalid now, it3 is still past-the-end
315 node2.remove_attribute(*it2);
316
317 CHECK(node2.attributes_end() == it3);
318 CHECK(move_iter(it1, 1) == it3);
319 CHECK(move_iter(it3, -1) == it1);
320 CHECK_STRING(it1->name(), STR("attr1"));
321
322 // adding attr2 back, it3 is still past-the-end!
323 xml_attribute_iterator it2new = xml_attribute_iterator(node2.append_attribute(STR("attr2-new")), node2);
324
325 CHECK(node2.attributes_end() == it3);
326 CHECK(move_iter(it1, 1) == it2new);
327 CHECK(move_iter(it2new, 1) == it3);
328 CHECK(move_iter(it3, -1) == it2new);
329 CHECK_STRING(it2new->name(), STR("attr2-new"));
330
331 // removing both attributes, it3 is now equal to the begin
332 node2.remove_attribute(*it1);
333 node2.remove_attribute(*it2new);
334 CHECK(!node2.first_attribute());
335
336 CHECK(node2.attributes_begin() == it3);
337 CHECK(node2.attributes_end() == it3);
338 }
339
340 TEST_XML(dom_attr_iterator_const, "<node attr1='0' attr2='1'/>")
341 {
342 xml_node node = doc.child(STR("node"));
343
344 const xml_attribute_iterator i1 = node.attributes_begin();
345 const xml_attribute_iterator i2 = ++xml_attribute_iterator(i1);
346 const xml_attribute_iterator i3 = ++xml_attribute_iterator(i2);
347
348 CHECK(*i1 == node.attribute(STR("attr1")));
349 CHECK(*i2 == node.attribute(STR("attr2")));
350 CHECK(i3 == node.attributes_end());
351
352 CHECK_STRING(i1->name(), STR("attr1"));
353 CHECK_STRING(i2->name(), STR("attr2"));
354 }
355
356 TEST_XML(dom_node_bool_ops, "<node/>")
357 {
358 generic_bool_ops_test(doc.child(STR("node")));
359 }
360
361 TEST_XML(dom_node_eq_ops, "<node><node1/><node2/></node>")
362 {
363 generic_eq_ops_test(doc.child(STR("node")).child(STR("node1")), doc.child(STR("node")).child(STR("node2")));
364 }
365
366 TEST_XML(dom_node_rel_ops, "<node><node1/><node2/></node>")
367 {
368 generic_rel_ops_test(doc.child(STR("node")).child(STR("node1")), doc.child(STR("node")).child(STR("node2")));
369 }
370
371 TEST_XML(dom_node_empty, "<node/>")
372 {
373 generic_empty_test(doc.child(STR("node")));
374 }
375
376 TEST_XML(dom_node_iterator, "<node><node1><child1/></node1><node2><child1/><child2/></node2><node3/></node>")
377 {
378 xml_node node1 = doc.child(STR("node")).child(STR("node1"));
379 xml_node node2 = doc.child(STR("node")).child(STR("node2"));
380 xml_node node3 = doc.child(STR("node")).child(STR("node3"));
381
382 CHECK(xml_node().begin() == xml_node_iterator());
383 CHECK(xml_node().end() == xml_node_iterator());
384
385 CHECK(node1.begin() == xml_node_iterator(node1.child(STR("child1"))));
386 CHECK(move_iter(node1.begin(), 1) == node1.end());
387 CHECK(move_iter(node1.end(), -1) == node1.begin());
388 CHECK(*node1.begin() == node1.child(STR("child1")));
389 CHECK_STRING(node1.begin()->name(), STR("child1"));
390
391 CHECK(move_iter(node2.begin(), 2) == node2.end());
392 CHECK(move_iter(node2.end(), -2) == node2.begin());
393
394 CHECK(node3.begin() != xml_node_iterator());
395 CHECK(node3.begin() == node3.end());
396
397 xml_node_iterator it = node2.child(STR("child2"));
398 xml_node_iterator itt = it;
399
400 CHECK(itt++ == it);
401 CHECK(itt == node2.end());
402
403 CHECK(itt-- == node2.end());
404 CHECK(itt == it);
405
406 CHECK(++itt == node2.end());
407 CHECK(itt == node2.end());
408
409 CHECK(--itt == it);
410 CHECK(itt == it);
411
412 CHECK(++itt != it);
413 }
414
415 TEST_XML(dom_node_iterator_end, "<node><node1><child1/></node1><node2><child1/><child2/></node2><node3/></node>")
416 {
417 xml_node node1 = doc.child(STR("node")).child(STR("node1"));
418 xml_node node2 = doc.child(STR("node")).child(STR("node2"));
419 xml_node node3 = doc.child(STR("node")).child(STR("node3"));
420
421 CHECK(node1.end() != node2.end() && node1.end() != node3.end() && node2.end() != node3.end());
422 CHECK(node1.end() != xml_node_iterator() && node2.end() != xml_node_iterator() && node3.end() != xml_node_iterator());
423 }
424
425 TEST_XML(dom_node_iterator_invalidate, "<node><node1><child1/></node1><node2><child1/><child2/></node2><node3/></node>")
426 {
427 xml_node node2 = doc.child(STR("node")).child(STR("node2"));
428
429 xml_node_iterator it1 = node2.begin();
430 xml_node_iterator it2 = move_iter(it1, 1);
431 xml_node_iterator it3 = move_iter(it2, 1);
432
433 CHECK(it3 == node2.end());
434
435 // removing child2, it2 is invalid now, it3 is still past-the-end
436 node2.remove_child(*it2);
437
438 CHECK(node2.end() == it3);
439 CHECK(move_iter(it1, 1) == it3);
440 CHECK(move_iter(it3, -1) == it1);
441 CHECK_STRING(it1->name(), STR("child1"));
442
443 // adding attr2 back, it3 is still past-the-end!
444 xml_node_iterator it2new = node2.append_child();
445 it2new->set_name(STR("child2-new"));
446
447 CHECK(node2.end() == it3);
448 CHECK(move_iter(it1, 1) == it2new);
449 CHECK(move_iter(it2new, 1) == it3);
450 CHECK(move_iter(it3, -1) == it2new);
451 CHECK_STRING(it2new->name(), STR("child2-new"));
452
453 // removing both nodes, it3 is now equal to the begin
454 node2.remove_child(*it1);
455 node2.remove_child(*it2new);
456 CHECK(!node2.first_child());
457
458 CHECK(node2.begin() == it3);
459 CHECK(node2.end() == it3);
460 }
461
462 TEST_XML(dom_node_iterator_const, "<node><child1/><child2/></node>")
463 {
464 xml_node node = doc.child(STR("node"));
465
466 const xml_node_iterator i1 = node.begin();
467 const xml_node_iterator i2 = ++xml_node_iterator(i1);
468 const xml_node_iterator i3 = ++xml_node_iterator(i2);
469
470 CHECK(*i1 == node.child(STR("child1")));
471 CHECK(*i2 == node.child(STR("child2")));
472 CHECK(i3 == node.end());
473
474 CHECK_STRING(i1->name(), STR("child1"));
475 CHECK_STRING(i2->name(), STR("child2"));
476 }
477
478 TEST_XML(dom_node_parent, "<node><child/></node>")
479 {
480 CHECK(xml_node().parent() == xml_node());
481 CHECK(doc.child(STR("node")).child(STR("child")).parent() == doc.child(STR("node")));
482 CHECK(doc.child(STR("node")).parent() == doc);
483 }
484
485 TEST_XML(dom_node_root, "<node><child/></node>")
486 {
487 CHECK(xml_node().root() == xml_node());
488 CHECK(doc.child(STR("node")).child(STR("child")).root() == doc);
489 CHECK(doc.child(STR("node")).root() == doc);
490 }
491
492 TEST_XML_FLAGS(dom_node_type, "<?xml?><!DOCTYPE><?pi?><!--comment--><node>pcdata<![CDATA[cdata]]></node>", parse_default | parse_pi | parse_comments | parse_declaration | parse_doctype)
493 {
494 CHECK(xml_node().type() == node_null);
495 CHECK(doc.type() == node_document);
496
497 xml_node_iterator it = doc.begin();
498
499 CHECK((it++)->type() == node_declaration);
500 CHECK((it++)->type() == node_doctype);
501 CHECK((it++)->type() == node_pi);
502 CHECK((it++)->type() == node_comment);
503 CHECK((it++)->type() == node_element);
504
505 xml_node_iterator cit = doc.child(STR("node")).begin();
506
507 CHECK((cit++)->type() == node_pcdata);
508 CHECK((cit++)->type() == node_cdata);
509 }
510
511 TEST_XML_FLAGS(dom_node_name_value, "<?xml?><!DOCTYPE id><?pi?><!--comment--><node>pcdata<![CDATA[cdata]]></node>", parse_default | parse_pi | parse_comments | parse_declaration | parse_doctype)
512 {
513 CHECK_NAME_VALUE(xml_node(), STR(""), STR(""));
514 CHECK_NAME_VALUE(doc, STR(""), STR(""));
515
516 xml_node_iterator it = doc.begin();
517
518 CHECK_NAME_VALUE(*it++, STR("xml"), STR(""));
519 CHECK_NAME_VALUE(*it++, STR(""), STR("id"));
520 CHECK_NAME_VALUE(*it++, STR("pi"), STR(""));
521 CHECK_NAME_VALUE(*it++, STR(""), STR("comment"));
522 CHECK_NAME_VALUE(*it++, STR("node"), STR(""));
523
524 xml_node_iterator cit = doc.child(STR("node")).begin();
525
526 CHECK_NAME_VALUE(*cit++, STR(""), STR("pcdata"));
527 CHECK_NAME_VALUE(*cit++, STR(""), STR("cdata"));
528 }
529
530 TEST_XML(dom_node_child, "<node><child1/><child2/></node>")
531 {
532 CHECK(xml_node().child(STR("n")) == xml_node());
533
534 CHECK(doc.child(STR("n")) == xml_node());
535 CHECK_NAME_VALUE(doc.child(STR("node")), STR("node"), STR(""));
536 CHECK(doc.child(STR("node")).child(STR("child2")) == doc.child(STR("node")).last_child());
537 }
538
539 TEST_XML(dom_node_attribute, "<node attr1='0' attr2='1'/>")
540 {
541 CHECK(xml_node().attribute(STR("a")) == xml_attribute());
542
543 xml_node node = doc.child(STR("node"));
544
545 CHECK(node.attribute(STR("n")) == xml_attribute());
546 CHECK_NAME_VALUE(node.attribute(STR("attr1")), STR("attr1"), STR("0"));
547 CHECK(node.attribute(STR("attr2")) == node.last_attribute());
548 }
549
550 TEST_XML(dom_node_next_previous_sibling, "<node><child1/><child2/><child3/></node>")
551 {
552 CHECK(xml_node().next_sibling() == xml_node());
553 CHECK(xml_node().next_sibling(STR("n")) == xml_node());
554
555 CHECK(xml_node().previous_sibling() == xml_node());
556 CHECK(xml_node().previous_sibling(STR("n")) == xml_node());
557
558 xml_node child1 = doc.child(STR("node")).child(STR("child1"));
559 xml_node child2 = doc.child(STR("node")).child(STR("child2"));
560 xml_node child3 = doc.child(STR("node")).child(STR("child3"));
561
562 CHECK(child1.next_sibling() == child2);
563 CHECK(child3.next_sibling() == xml_node());
564
565 CHECK(child1.previous_sibling() == xml_node());
566 CHECK(child3.previous_sibling() == child2);
567
568 CHECK(child1.next_sibling(STR("child3")) == child3);
569 CHECK(child1.next_sibling(STR("child")) == xml_node());
570
571 CHECK(child3.previous_sibling(STR("child1")) == child1);
572 CHECK(child3.previous_sibling(STR("child")) == xml_node());
573 }
574
575 TEST_XML(dom_node_child_value, "<node><novalue/><child1>value1</child1><child2>value2<n/></child2><child3><![CDATA[value3]]></child3>value4</node>")
576 {
577 CHECK_STRING(xml_node().child_value(), STR(""));
578 CHECK_STRING(xml_node().child_value(STR("n")), STR(""));
579
580 xml_node node = doc.child(STR("node"));
581
582 CHECK_STRING(node.child_value(), STR("value4"));
583 CHECK_STRING(node.child(STR("child1")).child_value(), STR("value1"));
584 CHECK_STRING(node.child(STR("child2")).child_value(), STR("value2"));
585 CHECK_STRING(node.child(STR("child3")).child_value(), STR("value3"));
586 CHECK_STRING(node.child_value(STR("child3")), STR("value3"));
587 CHECK_STRING(node.child_value(STR("novalue")), STR(""));
588 }
589
590 TEST_XML(dom_node_first_last_attribute, "<node attr1='0' attr2='1'/>")
591 {
592 xml_node node = doc.child(STR("node"));
593
594 CHECK(node.first_attribute() == node.attribute(STR("attr1")));
595 CHECK(node.last_attribute() == node.attribute(STR("attr2")));
596
597 CHECK(xml_node().first_attribute() == xml_attribute());
598 CHECK(xml_node().last_attribute() == xml_attribute());
599
600 CHECK(doc.first_attribute() == xml_attribute());
601 CHECK(doc.last_attribute() == xml_attribute());
602 }
603
604 TEST_XML(dom_node_first_last_child, "<node><child1/><child2/></node>")
605 {
606 xml_node node = doc.child(STR("node"));
607
608 CHECK(node.first_child() == node.child(STR("child1")));
609 CHECK(node.last_child() == node.child(STR("child2")));
610
611 CHECK(xml_node().first_child() == xml_node());
612 CHECK(xml_node().last_child() == xml_node());
613
614 CHECK(doc.first_child() == node);
615 CHECK(doc.last_child() == node);
616 }
617
618 TEST_XML(dom_node_find_child_by_attribute, "<node><stub attr='value3' /><child1 attr='value1'/><child2 attr='value2'/><child2 attr='value3'/></node>")
619 {
620 CHECK(xml_node().find_child_by_attribute(STR("name"), STR("attr"), STR("value")) == xml_node());
621 CHECK(xml_node().find_child_by_attribute(STR("attr"), STR("value")) == xml_node());
622
623 xml_node node = doc.child(STR("node"));
624
625 CHECK(node.find_child_by_attribute(STR("child2"), STR("attr"), STR("value3")) == node.last_child());
626 CHECK(node.find_child_by_attribute(STR("child2"), STR("attr3"), STR("value3")) == xml_node());
627 CHECK(node.find_child_by_attribute(STR("attr"), STR("value2")) == node.child(STR("child2")));
628 CHECK(node.find_child_by_attribute(STR("attr3"), STR("value")) == xml_node());
629 }
630
TEST(dom_node_find_child_by_attribute_null)631 TEST(dom_node_find_child_by_attribute_null)
632 {
633 xml_document doc;
634 xml_node node0 = doc.append_child();
635 xml_node node1 = doc.append_child(STR("a"));
636 xml_node node2 = doc.append_child(STR("a"));
637 xml_node node3 = doc.append_child(STR("a"));
638
639 (void)node0;
640
641 // this adds an attribute with null name and/or value in the internal representation
642 node1.append_attribute(STR(""));
643 node2.append_attribute(STR("id"));
644 node3.append_attribute(STR("id")) = STR("1");
645
646 // make sure find_child_by_attribute works if name/value is null
647 CHECK(doc.find_child_by_attribute(STR("unknown"), STR("wrong")) == xml_node());
648 CHECK(doc.find_child_by_attribute(STR("id"), STR("wrong")) == xml_node());
649 CHECK(doc.find_child_by_attribute(STR("id"), STR("")) == node2);
650 CHECK(doc.find_child_by_attribute(STR("id"), STR("1")) == node3);
651
652 CHECK(doc.find_child_by_attribute(STR("a"), STR("unknown"), STR("wrong")) == xml_node());
653 CHECK(doc.find_child_by_attribute(STR("a"), STR("id"), STR("wrong")) == xml_node());
654 CHECK(doc.find_child_by_attribute(STR("a"), STR("id"), STR("")) == node2);
655 CHECK(doc.find_child_by_attribute(STR("a"), STR("id"), STR("1")) == node3);
656 }
657
658 struct find_predicate_const
659 {
660 bool result;
661
find_predicate_constfind_predicate_const662 find_predicate_const(bool result_): result(result_)
663 {
664 }
665
operator ()find_predicate_const666 template <typename T> bool operator()(const T&) const
667 {
668 return result;
669 }
670 };
671
672 struct find_predicate_prefix
673 {
674 const char_t* prefix;
675
find_predicate_prefixfind_predicate_prefix676 find_predicate_prefix(const char_t* prefix_): prefix(prefix_)
677 {
678 }
679
operator ()find_predicate_prefix680 template <typename T> bool operator()(const T& obj) const
681 {
682 #ifdef PUGIXML_WCHAR_MODE
683 // can't use wcsncmp here because of a bug in DMC
684 return std::basic_string<char_t>(obj.name()).compare(0, wcslen(prefix), prefix) == 0;
685 #else
686 return strncmp(obj.name(), prefix, strlen(prefix)) == 0;
687 #endif
688 }
689 };
690
691 TEST_XML(dom_node_find_attribute, "<node attr1='0' attr2='1'/>")
692 {
693 CHECK(xml_node().find_attribute(find_predicate_const(true)) == xml_attribute());
694
695 xml_node node = doc.child(STR("node"));
696
697 CHECK(doc.find_attribute(find_predicate_const(true)) == xml_attribute());
698 CHECK(node.find_attribute(find_predicate_const(true)) == node.first_attribute());
699 CHECK(node.find_attribute(find_predicate_const(false)) == xml_attribute());
700 CHECK(node.find_attribute(find_predicate_prefix(STR("attr2"))) == node.last_attribute());
701 CHECK(node.find_attribute(find_predicate_prefix(STR("attr"))) == node.first_attribute());
702 }
703
704 TEST_XML(dom_node_find_child, "<node><child1/><child2/></node>")
705 {
706 CHECK(xml_node().find_child(find_predicate_const(true)) == xml_node());
707
708 xml_node node = doc.child(STR("node"));
709
710 CHECK(node.child(STR("node")).child(STR("child1")).find_child(find_predicate_const(true)) == xml_node());
711 CHECK(node.find_child(find_predicate_const(true)) == node.first_child());
712 CHECK(node.find_child(find_predicate_const(false)) == xml_node());
713 CHECK(node.find_child(find_predicate_prefix(STR("child2"))) == node.last_child());
714 CHECK(node.find_child(find_predicate_prefix(STR("child"))) == node.first_child());
715 }
716
717 TEST_XML(dom_node_find_node, "<node><child1/><child2/></node>")
718 {
719 CHECK(xml_node().find_node(find_predicate_const(true)) == xml_node());
720
721 xml_node node = doc.child(STR("node"));
722
723 CHECK(node.child(STR("node")).child(STR("child1")).find_node(find_predicate_const(true)) == xml_node());
724 CHECK(node.find_node(find_predicate_const(true)) == node.first_child());
725 CHECK(node.find_node(find_predicate_const(false)) == xml_node());
726 CHECK(node.find_node(find_predicate_prefix(STR("child2"))) == node.last_child());
727 CHECK(node.find_node(find_predicate_prefix(STR("child"))) == node.first_child());
728 CHECK(doc.find_node(find_predicate_prefix(STR("child"))) == node.first_child());
729 CHECK(doc.find_node(find_predicate_prefix(STR("child2"))) == node.last_child());
730 CHECK(doc.find_node(find_predicate_prefix(STR("child3"))) == xml_node());
731 }
732
733 #ifndef PUGIXML_NO_STL
734 TEST_XML(dom_node_path, "<node><child1>text<child2/></child1></node>")
735 {
736 CHECK(xml_node().path() == STR(""));
737
738 CHECK(doc.path() == STR(""));
739 CHECK(doc.child(STR("node")).path() == STR("/node"));
740 CHECK(doc.child(STR("node")).child(STR("child1")).path() == STR("/node/child1"));
741 CHECK(doc.child(STR("node")).child(STR("child1")).child(STR("child2")).path() == STR("/node/child1/child2"));
742 CHECK(doc.child(STR("node")).child(STR("child1")).first_child().path() == STR("/node/child1/"));
743
744 CHECK(doc.child(STR("node")).child(STR("child1")).path('\\') == STR("\\node\\child1"));
745
746 doc.append_child(node_element);
747 CHECK(doc.last_child().path() == STR("/"));
748 }
749 #endif
750
751 TEST_XML(dom_node_first_element_by_path, "<node><child1>text<child2/></child1></node>")
752 {
753 CHECK(xml_node().first_element_by_path(STR("/")) == xml_node());
754 CHECK(xml_node().first_element_by_path(STR("a")) == xml_node());
755
756 CHECK(doc.first_element_by_path(STR("")) == doc);
757 CHECK(doc.first_element_by_path(STR("/")) == doc);
758
759 CHECK(doc.first_element_by_path(STR("/node/")) == doc.child(STR("node")));
760 CHECK(doc.first_element_by_path(STR("node/")) == doc.child(STR("node")));
761 CHECK(doc.first_element_by_path(STR("node")) == doc.child(STR("node")));
762 CHECK(doc.first_element_by_path(STR("/node")) == doc.child(STR("node")));
763
764 #ifndef PUGIXML_NO_STL
765 CHECK(doc.first_element_by_path(STR("/node/child1/child2")).path() == STR("/node/child1/child2"));
766 #endif
767
768 CHECK(doc.first_element_by_path(STR("/node/child2")) == xml_node());
769
770 CHECK(doc.first_element_by_path(STR("\\node\\child1"), '\\') == doc.child(STR("node")).child(STR("child1")));
771
772 CHECK(doc.child(STR("node")).first_element_by_path(STR("..")) == doc);
773 CHECK(doc.child(STR("node")).first_element_by_path(STR(".")) == doc.child(STR("node")));
774
775 CHECK(doc.child(STR("node")).first_element_by_path(STR("../node/./child1/../.")) == doc.child(STR("node")));
776
777 CHECK(doc.child(STR("node")).first_element_by_path(STR("child1")) == doc.child(STR("node")).child(STR("child1")));
778 CHECK(doc.child(STR("node")).first_element_by_path(STR("child1/")) == doc.child(STR("node")).child(STR("child1")));
779 CHECK(doc.child(STR("node")).first_element_by_path(STR("child")) == xml_node());
780 CHECK(doc.child(STR("node")).first_element_by_path(STR("child11")) == xml_node());
781
782 CHECK(doc.first_element_by_path(STR("//node")) == doc.child(STR("node")));
783 }
784
785 struct test_walker: xml_tree_walker
786 {
787 std::basic_string<char_t> log;
788 unsigned int call_count;
789 unsigned int stop_count;
790
test_walkertest_walker791 test_walker(unsigned int stop_count_ = 0): call_count(0), stop_count(stop_count_)
792 {
793 }
794
depthstrtest_walker795 std::basic_string<char_t> depthstr() const
796 {
797 char buf[32];
798 sprintf(buf, "%d", depth());
799
800 #ifdef PUGIXML_WCHAR_MODE
801 wchar_t wbuf[32];
802 std::copy(buf, buf + strlen(buf) + 1, &wbuf[0]);
803
804 return std::basic_string<char_t>(wbuf);
805 #else
806 return std::basic_string<char_t>(buf);
807 #endif
808 }
809
begintest_walker810 virtual bool begin(xml_node& node) PUGIXML_OVERRIDE
811 {
812 log += STR("|");
813 log += depthstr();
814 log += STR(" <");
815 log += node.name();
816 log += STR("=");
817 log += node.value();
818
819 return ++call_count != stop_count && xml_tree_walker::begin(node);
820 }
821
for_eachtest_walker822 virtual bool for_each(xml_node& node) PUGIXML_OVERRIDE
823 {
824 log += STR("|");
825 log += depthstr();
826 log += STR(" !");
827 log += node.name();
828 log += STR("=");
829 log += node.value();
830
831 return ++call_count != stop_count && xml_tree_walker::end(node);
832 }
833
endtest_walker834 virtual bool end(xml_node& node) PUGIXML_OVERRIDE
835 {
836 log += STR("|");
837 log += depthstr();
838 log += STR(" >");
839 log += node.name();
840 log += STR("=");
841 log += node.value();
842
843 return ++call_count != stop_count;
844 }
845 };
846
847 TEST_XML(dom_node_traverse, "<node><child>text</child></node>")
848 {
849 test_walker walker;
850
851 CHECK(doc.traverse(walker));
852
853 CHECK(walker.call_count == 5);
854 CHECK(walker.log == STR("|-1 <=|0 !node=|1 !child=|2 !=text|-1 >="));
855 }
856
857 TEST_XML(dom_node_traverse_siblings, "<node><child/><child>text</child><child/></node>")
858 {
859 test_walker walker;
860
861 CHECK(doc.traverse(walker));
862
863 CHECK(walker.call_count == 7);
864 CHECK(walker.log == STR("|-1 <=|0 !node=|1 !child=|1 !child=|2 !=text|1 !child=|-1 >="));
865 }
866
TEST(dom_node_traverse_empty)867 TEST(dom_node_traverse_empty)
868 {
869 test_walker walker;
870
871 CHECK(xml_node().traverse(walker));
872
873 CHECK(walker.call_count == 2);
874 CHECK(walker.log == STR("|-1 <=|-1 >="));
875 }
876
877 TEST_XML(dom_node_traverse_child, "<node><child>text</child></node><another>node</another>")
878 {
879 test_walker walker;
880
881 CHECK(doc.child(STR("node")).traverse(walker));
882
883 CHECK(walker.call_count == 4);
884 CHECK(walker.log == STR("|-1 <node=|0 !child=|1 !=text|-1 >node="));
885 }
886
887 TEST_XML(dom_node_traverse_stop_begin, "<node><child>text</child></node>")
888 {
889 test_walker walker(1);
890
891 CHECK(!doc.traverse(walker));
892
893 CHECK(walker.call_count == 1);
894 CHECK(walker.log == STR("|-1 <="));
895 }
896
897 TEST_XML(dom_node_traverse_stop_for_each, "<node><child>text</child></node>")
898 {
899 test_walker walker(3);
900
901 CHECK(!doc.traverse(walker));
902
903 CHECK(walker.call_count == 3);
904 CHECK(walker.log == STR("|-1 <=|0 !node=|1 !child="));
905 }
906
907 TEST_XML(dom_node_traverse_stop_end, "<node><child>text</child></node>")
908 {
909 test_walker walker(5);
910
911 CHECK(!doc.traverse(walker));
912
913 CHECK(walker.call_count == 5);
914 CHECK(walker.log == STR("|-1 <=|0 !node=|1 !child=|2 !=text|-1 >="));
915 }
916
917 TEST_XML_FLAGS(dom_offset_debug, "<?xml?><!DOCTYPE><?pi?><!--comment--><node>pcdata<![CDATA[cdata]]></node>", parse_default | parse_pi | parse_comments | parse_declaration | parse_doctype)
918 {
919 CHECK(xml_node().offset_debug() == -1);
920 CHECK(doc.offset_debug() == 0);
921
922 xml_node_iterator it = doc.begin();
923
924 CHECK((it++)->offset_debug() == 2);
925 CHECK((it++)->offset_debug() == 16);
926 CHECK((it++)->offset_debug() == 19);
927 CHECK((it++)->offset_debug() == 27);
928 CHECK((it++)->offset_debug() == 38);
929
930 xml_node_iterator cit = doc.child(STR("node")).begin();
931
932 CHECK((cit++)->offset_debug() == 43);
933 CHECK((cit++)->offset_debug() == 58);
934 }
935
TEST(dom_offset_debug_encoding)936 TEST(dom_offset_debug_encoding)
937 {
938 char buf[] = { 0, '<', 0, 'n', 0, '/', 0, '>' };
939
940 xml_document doc;
941 CHECK(doc.load_buffer(buf, sizeof(buf)));
942
943 CHECK(doc.offset_debug() == 0);
944 CHECK(doc.first_child().offset_debug() == 1);
945 }
946
947 TEST_XML(dom_offset_debug_append, "<node/>")
948 {
949 xml_node c1 = doc.first_child();
950 xml_node c2 = doc.append_child(STR("node"));
951 xml_node c3 = doc.append_child(node_pcdata);
952
953 CHECK(doc.offset_debug() == 0);
954 CHECK(c1.offset_debug() == 1);
955 CHECK(c2.offset_debug() == -1);
956 CHECK(c3.offset_debug() == -1);
957
958 c1.set_name(STR("nodenode"));
959 CHECK(c1.offset_debug() == -1);
960 }
961
962 TEST_XML(dom_offset_debug_append_buffer, "<node/>")
963 {
964 CHECK(doc.offset_debug() == 0);
965 CHECK(doc.first_child().offset_debug() == 1);
966
967 CHECK(doc.append_buffer("<node/>", 7));
968 CHECK(doc.offset_debug() == -1);
969 CHECK(doc.first_child().offset_debug() == -1);
970 CHECK(doc.last_child().offset_debug() == -1);
971 }
972
973 TEST_XML(dom_internal_object, "<node attr='value'>value</node>")
974 {
975 xml_node node = doc.child(STR("node"));
976 xml_attribute attr = node.first_attribute();
977 xml_node value = node.first_child();
978
979 CHECK(xml_node().internal_object() == 0);
980 CHECK(xml_attribute().internal_object() == 0);
981
982 CHECK(node.internal_object() != 0);
983 CHECK(value.internal_object() != 0);
984 CHECK(node.internal_object() != value.internal_object());
985
986 CHECK(attr.internal_object() != 0);
987
988 xml_node node_copy = node;
989 CHECK(node_copy.internal_object() == node.internal_object());
990
991 xml_attribute attr_copy = attr;
992 CHECK(attr_copy.internal_object() == attr.internal_object());
993 }
994
995 TEST_XML(dom_hash_value, "<node attr='value'>value</node>")
996 {
997 xml_node node = doc.child(STR("node"));
998 xml_attribute attr = node.first_attribute();
999 xml_node value = node.first_child();
1000
1001 CHECK(xml_node().hash_value() == 0);
1002 CHECK(xml_attribute().hash_value() == 0);
1003
1004 CHECK(node.hash_value() != 0);
1005 CHECK(value.hash_value() != 0);
1006 CHECK(node.hash_value() != value.hash_value());
1007
1008 CHECK(attr.hash_value() != 0);
1009
1010 xml_node node_copy = node;
1011 CHECK(node_copy.hash_value() == node.hash_value());
1012
1013 xml_attribute attr_copy = attr;
1014 CHECK(attr_copy.hash_value() == attr.hash_value());
1015 }
1016
1017 TEST_XML(dom_node_named_iterator, "<node><node1><child/></node1><node2><child/><child/></node2><node3/><node4><child/><x/></node4></node>")
1018 {
1019 xml_node node1 = doc.child(STR("node")).child(STR("node1"));
1020 xml_node node2 = doc.child(STR("node")).child(STR("node2"));
1021 xml_node node3 = doc.child(STR("node")).child(STR("node3"));
1022 xml_node node4 = doc.child(STR("node")).child(STR("node4"));
1023
1024 CHECK(xml_named_node_iterator(xml_node(), STR("child")) == xml_named_node_iterator());
1025
1026 xml_object_range<xml_named_node_iterator> r1 = node1.children(STR("child"));
1027 xml_object_range<xml_named_node_iterator> r2 = node2.children(STR("child"));
1028 xml_object_range<xml_named_node_iterator> r3 = node3.children(STR("child"));
1029 xml_object_range<xml_named_node_iterator> r4 = node4.children(STR("child"));
1030
1031 CHECK(r1.begin() != r1.end());
1032 CHECK(*r1.begin() == node1.first_child());
1033 CHECK(r1.begin() == move_iter(r1.end(), -1));
1034 CHECK(move_iter(r1.begin(), 1) == r1.end());
1035
1036 CHECK(r2.begin() != r2.end());
1037 CHECK(*r2.begin() == node2.first_child());
1038 CHECK(*move_iter(r2.begin(), 1) == node2.last_child());
1039 CHECK(r2.begin() == move_iter(r2.end(), -2));
1040 CHECK(move_iter(r2.begin(), 1) == move_iter(r2.end(), -1));
1041 CHECK(move_iter(r2.begin(), 2) == r2.end());
1042
1043 CHECK(r3.begin() == r3.end());
1044 CHECK(!(r3.begin() != r3.end()));
1045
1046 CHECK(r4.begin() != r4.end());
1047 CHECK(*r4.begin() == node4.first_child());
1048 CHECK(r4.begin() == move_iter(r4.end(), -1));
1049 CHECK(move_iter(r4.begin(), 1) == r4.end());
1050
1051 xml_named_node_iterator it = r1.begin();
1052 xml_named_node_iterator itt = it;
1053
1054 CHECK(itt == it);
1055
1056 CHECK(itt++ == it);
1057 CHECK(itt == r1.end());
1058
1059 CHECK(itt != it);
1060 CHECK(itt == ++it);
1061
1062 CHECK(itt-- == r1.end());
1063 CHECK(itt == r1.begin());
1064
1065 CHECK(itt->offset_debug() == 14);
1066 }
1067
1068 TEST_XML(dom_node_children_attributes, "<node1 attr1='value1' attr2='value2' /><node2 />")
1069 {
1070 xml_object_range<xml_node_iterator> r1 = doc.children();
1071
1072 CHECK(r1.begin() == doc.begin());
1073 CHECK(r1.end() == doc.end());
1074
1075 xml_object_range<xml_node_iterator> r2 = xml_node().children();
1076
1077 CHECK(r2.begin() == xml_node_iterator());
1078 CHECK(r2.end() == xml_node_iterator());
1079
1080 xml_node node = doc.child(STR("node1"));
1081
1082 xml_object_range<xml_attribute_iterator> r3 = node.attributes();
1083
1084 CHECK(r3.begin() == node.attributes_begin());
1085 CHECK(r3.end() == node.attributes_end());
1086
1087 xml_object_range<xml_attribute_iterator> r4 = xml_node().attributes();
1088
1089 CHECK(r4.begin() == xml_attribute_iterator());
1090 CHECK(r4.end() == xml_attribute_iterator());
1091 }
1092
1093 TEST_XML(dom_unspecified_bool_coverage, "<node attr='value'>text</node>")
1094 {
1095 xml_node node = doc.first_child();
1096
1097 CHECK(node);
1098 static_cast<void (*)(xml_node***)>(node)(0);
1099
1100 CHECK(node.first_attribute());
1101 static_cast<void (*)(xml_attribute***)>(node.first_attribute())(0);
1102
1103 CHECK(node.text());
1104 static_cast<void (*)(xml_text***)>(node.text())(0);
1105
1106 #ifndef PUGIXML_NO_XPATH
1107 xpath_query q(STR("/node"));
1108
1109 CHECK(q);
1110 static_cast<void (*)(xpath_query***)>(q)(0);
1111
1112 xpath_node qn = q.evaluate_node(doc);
1113
1114 CHECK(qn);
1115 static_cast<void (*)(xpath_node***)>(qn)(0);
1116 #endif
1117 }
1118
1119 #if __cplusplus >= 201103
1120 TEST_XML(dom_ranged_for, "<node attr1='1' attr2='2'><test>3</test><fake>5</fake><test>4</test></node>")
1121 {
1122 int index = 1;
1123
1124 for (xml_node n: doc.children())
1125 {
1126 for (xml_attribute a: n.attributes())
1127 {
1128 CHECK(a.as_int() == index);
1129 index++;
1130 }
1131
1132 for (xml_node c: n.children(STR("test")))
1133 {
1134 CHECK(c.text().as_int() == index);
1135 index++;
1136 }
1137 }
1138
1139 CHECK(index == 5);
1140 }
1141 #endif
1142
1143 TEST_XML(dom_node_attribute_hinted, "<node attr1='1' attr2='2' attr3='3' />")
1144 {
1145 xml_node node = doc.first_child();
1146 xml_attribute attr1 = node.attribute(STR("attr1"));
1147 xml_attribute attr2 = node.attribute(STR("attr2"));
1148 xml_attribute attr3 = node.attribute(STR("attr3"));
1149
1150 xml_attribute hint;
1151 CHECK(!xml_node().attribute(STR("test"), hint) && !hint);
1152
1153 CHECK(node.attribute(STR("attr2"), hint) == attr2 && hint == attr3);
1154 CHECK(node.attribute(STR("attr3"), hint) == attr3 && !hint);
1155
1156 CHECK(node.attribute(STR("attr1"), hint) == attr1 && hint == attr2);
1157 CHECK(node.attribute(STR("attr2"), hint) == attr2 && hint == attr3);
1158 CHECK(node.attribute(STR("attr1"), hint) == attr1 && hint == attr2);
1159 CHECK(node.attribute(STR("attr1"), hint) == attr1 && hint == attr2);
1160
1161 CHECK(!node.attribute(STR("attr"), hint) && hint == attr2);
1162 }
1163
1164 TEST_XML(dom_as_int_overflow, "<node attr1='-2147483649' attr2='2147483648' attr3='-4294967296' />")
1165 {
1166 xml_node node = doc.child(STR("node"));
1167
1168 CHECK(node.attribute(STR("attr1")).as_int() == -2147483647 - 1);
1169 CHECK(node.attribute(STR("attr2")).as_int() == 2147483647);
1170 CHECK(node.attribute(STR("attr3")).as_int() == -2147483647 - 1);
1171 }
1172
1173 TEST_XML(dom_as_uint_overflow, "<node attr1='-1' attr2='4294967296' attr3='5294967295' attr4='21474836479' />")
1174 {
1175 xml_node node = doc.child(STR("node"));
1176
1177 CHECK(node.attribute(STR("attr1")).as_uint() == 0);
1178 CHECK(node.attribute(STR("attr2")).as_uint() == 4294967295u);
1179 CHECK(node.attribute(STR("attr3")).as_uint() == 4294967295u);
1180 CHECK(node.attribute(STR("attr4")).as_uint() == 4294967295u);
1181 }
1182
1183 TEST_XML(dom_as_int_hex_overflow, "<node attr1='-0x80000001' attr2='0x80000000' />")
1184 {
1185 xml_node node = doc.child(STR("node"));
1186
1187 CHECK(node.attribute(STR("attr1")).as_int() == -2147483647 - 1);
1188 CHECK(node.attribute(STR("attr2")).as_int() == 2147483647);
1189 }
1190
1191 TEST_XML(dom_as_uint_hex_overflow, "<node attr1='-0x1' attr2='0x100000000' attr3='0x123456789' />")
1192 {
1193 xml_node node = doc.child(STR("node"));
1194
1195 CHECK(node.attribute(STR("attr1")).as_uint() == 0);
1196 CHECK(node.attribute(STR("attr2")).as_uint() == 4294967295u);
1197 CHECK(node.attribute(STR("attr3")).as_uint() == 4294967295u);
1198 }
1199
1200 TEST_XML(dom_as_int_many_digits, "<node attr1='0000000000000000000000000000000000000000000000001' />")
1201 {
1202 xml_node node = doc.child(STR("node"));
1203
1204 CHECK(node.attribute(STR("attr1")).as_int() == 1);
1205 CHECK(node.attribute(STR("attr1")).as_uint() == 1);
1206 }
1207
1208 TEST_XML(dom_as_int_hex_many_digits, "<node attr1='0x0000000000000000000000000000000000000000000000001' />")
1209 {
1210 xml_node node = doc.child(STR("node"));
1211
1212 CHECK(node.attribute(STR("attr1")).as_int() == 1);
1213 CHECK(node.attribute(STR("attr1")).as_uint() == 1);
1214 }
1215
1216 #ifdef PUGIXML_HAS_LONG_LONG
1217 TEST_XML(dom_as_llong_overflow, "<node attr1='-9223372036854775809' attr2='9223372036854775808' attr3='-18446744073709551616' />")
1218 {
1219 xml_node node = doc.child(STR("node"));
1220
1221 CHECK(node.attribute(STR("attr1")).as_llong() == -9223372036854775807ll - 1);
1222 CHECK(node.attribute(STR("attr2")).as_llong() == 9223372036854775807ll);
1223 CHECK(node.attribute(STR("attr3")).as_llong() == -9223372036854775807ll - 1);
1224 }
1225
1226 TEST_XML(dom_as_ullong_overflow, "<node attr1='-1' attr2='18446744073709551616' attr3='28446744073709551615' attr4='166020696663385964543' />")
1227 {
1228 xml_node node = doc.child(STR("node"));
1229
1230 CHECK(node.attribute(STR("attr1")).as_ullong() == 0);
1231 CHECK(node.attribute(STR("attr2")).as_ullong() == 18446744073709551615ull);
1232 CHECK(node.attribute(STR("attr3")).as_ullong() == 18446744073709551615ull);
1233 CHECK(node.attribute(STR("attr4")).as_ullong() == 18446744073709551615ull);
1234 }
1235
1236 TEST_XML(dom_as_llong_hex_overflow, "<node attr1='-0x8000000000000001' attr2='0x8000000000000000' />")
1237 {
1238 xml_node node = doc.child(STR("node"));
1239
1240 CHECK(node.attribute(STR("attr1")).as_llong() == -9223372036854775807ll - 1);
1241 CHECK(node.attribute(STR("attr2")).as_llong() == 9223372036854775807ll);
1242 }
1243
1244 TEST_XML(dom_as_ullong_hex_overflow, "<node attr1='-0x1' attr2='0x10000000000000000' attr3='0x12345678923456789' />")
1245 {
1246 xml_node node = doc.child(STR("node"));
1247
1248 CHECK(node.attribute(STR("attr1")).as_ullong() == 0);
1249 CHECK(node.attribute(STR("attr2")).as_ullong() == 18446744073709551615ull);
1250 CHECK(node.attribute(STR("attr3")).as_ullong() == 18446744073709551615ull);
1251 }
1252
1253 TEST_XML(dom_as_llong_many_digits, "<node attr1='0000000000000000000000000000000000000000000000001' />")
1254 {
1255 xml_node node = doc.child(STR("node"));
1256
1257 CHECK(node.attribute(STR("attr1")).as_llong() == 1);
1258 CHECK(node.attribute(STR("attr1")).as_ullong() == 1);
1259 }
1260
1261 TEST_XML(dom_as_llong_hex_many_digits, "<node attr1='0x0000000000000000000000000000000000000000000000001' />")
1262 {
1263 xml_node node = doc.child(STR("node"));
1264
1265 CHECK(node.attribute(STR("attr1")).as_llong() == 1);
1266 CHECK(node.attribute(STR("attr1")).as_ullong() == 1);
1267 }
1268 #endif
1269
1270 TEST_XML(dom_as_int_plus, "<node attr1='+1' attr2='+0xa' />")
1271 {
1272 xml_node node = doc.child(STR("node"));
1273
1274 CHECK(node.attribute(STR("attr1")).as_int() == 1);
1275 CHECK(node.attribute(STR("attr1")).as_uint() == 1);
1276 CHECK(node.attribute(STR("attr2")).as_int() == 10);
1277 CHECK(node.attribute(STR("attr2")).as_uint() == 10);
1278
1279 #ifdef PUGIXML_HAS_LONG_LONG
1280 CHECK(node.attribute(STR("attr1")).as_llong() == 1);
1281 CHECK(node.attribute(STR("attr1")).as_ullong() == 1);
1282 CHECK(node.attribute(STR("attr2")).as_llong() == 10);
1283 CHECK(node.attribute(STR("attr2")).as_ullong() == 10);
1284 #endif
1285 }
1286
TEST(dom_node_anonymous)1287 TEST(dom_node_anonymous)
1288 {
1289 xml_document doc;
1290 doc.append_child(node_element);
1291 doc.append_child(node_element);
1292 doc.append_child(node_pcdata);
1293
1294 CHECK(doc.child(STR("node")) == xml_node());
1295 CHECK(doc.first_child().next_sibling(STR("node")) == xml_node());
1296 CHECK(doc.last_child().previous_sibling(STR("node")) == xml_node());
1297 CHECK_STRING(doc.child_value(), STR(""));
1298 CHECK_STRING(doc.last_child().child_value(), STR(""));
1299 }
1300