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