11 static XML_Parser parser
;
17 parser
= XML_ParserCreate(NULL
);
19 fail("Parser not created.");
26 XML_ParserFree(parser
);
29 /* Generate a failure using the parser state to create an error message;
30 this should be used when the parser reports an error we weren't
34 _xml_failure(XML_Parser parser
, const char *file
, int line
)
38 "\n %s (line %d, offset %d)\n reported from %s, line %d",
39 XML_ErrorString(XML_GetErrorCode(parser
)),
40 XML_GetCurrentLineNumber(parser
),
41 XML_GetCurrentColumnNumber(parser
),
43 _fail_unless(0, file
, line
, buffer
);
46 #define xml_failure(parser) _xml_failure((parser), __FILE__, __LINE__)
49 _expect_failure(char *text
, enum XML_Error errorCode
, char *errorMessage
,
50 char *file
, int lineno
)
52 if (XML_Parse(parser
, text
, strlen(text
), XML_TRUE
) == XML_STATUS_OK
)
53 /* Hackish use of _fail_unless() macro, but let's us report
54 the right filename and line number. */
55 _fail_unless(0, file
, lineno
, errorMessage
);
56 if (XML_GetErrorCode(parser
) != errorCode
)
57 _xml_failure(parser
, file
, lineno
);
60 #define expect_failure(text, errorCode, errorMessage) \
61 _expect_failure((text), (errorCode), (errorMessage), \
64 /* Dummy handlers for when we need to set a handler to tickle a bug,
65 but it doesn't need to do anything.
69 dummy_start_doctype_handler(void *userData
,
70 const XML_Char
*doctypeName
,
71 const XML_Char
*sysid
,
72 const XML_Char
*pubid
,
73 int has_internal_subset
)
77 dummy_end_doctype_handler(void *userData
)
81 dummy_entity_decl_handler(void *userData
,
82 const XML_Char
*entityName
,
83 int is_parameter_entity
,
84 const XML_Char
*value
,
87 const XML_Char
*systemId
,
88 const XML_Char
*publicId
,
89 const XML_Char
*notationName
)
93 dummy_notation_decl_handler(void *userData
,
94 const XML_Char
*notationName
,
96 const XML_Char
*systemId
,
97 const XML_Char
*publicId
)
101 dummy_element_decl_handler(void *userData
,
102 const XML_Char
*name
,
107 dummy_attlist_decl_handler(void *userData
,
108 const XML_Char
*elname
,
109 const XML_Char
*attname
,
110 const XML_Char
*att_type
,
111 const XML_Char
*dflt
,
116 dummy_comment_handler(void *userData
, const XML_Char
*data
)
120 dummy_pi_handler(void *userData
, const XML_Char
*target
, const XML_Char
*data
)
124 dummy_start_element(void *userData
,
125 const XML_Char
*name
, const XML_Char
**atts
)
130 * Character & encoding tests.
133 START_TEST(test_nul_byte
)
135 char text
[] = "<doc>\0</doc>";
137 /* test that a NUL byte (in US-ASCII data) is an error */
138 if (XML_Parse(parser
, text
, sizeof(text
) - 1, XML_TRUE
) == XML_STATUS_OK
)
139 fail("Parser did not report error on NUL-byte.");
140 if (XML_GetErrorCode(parser
) != XML_ERROR_INVALID_TOKEN
)
146 START_TEST(test_u0000_char
)
148 /* test that a NUL byte (in US-ASCII data) is an error */
149 expect_failure("<doc>�</doc>",
150 XML_ERROR_BAD_CHAR_REF
,
151 "Parser did not report error on NUL-byte.");
155 START_TEST(test_bom_utf8
)
157 /* This test is really just making sure we don't core on a UTF-8 BOM. */
158 char *text
= "\357\273\277<e/>";
160 if (XML_Parse(parser
, text
, strlen(text
), XML_TRUE
) == XML_STATUS_ERROR
)
165 START_TEST(test_bom_utf16_be
)
167 char text
[] = "\376\377\0<\0e\0/\0>";
169 if (XML_Parse(parser
, text
, sizeof(text
)-1, XML_TRUE
) == XML_STATUS_ERROR
)
174 START_TEST(test_bom_utf16_le
)
176 char text
[] = "\377\376<\0e\0/\0>\0";
178 if (XML_Parse(parser
, text
, sizeof(text
)-1, XML_TRUE
) == XML_STATUS_ERROR
)
184 accumulate_characters(void *userData
, const XML_Char
*s
, int len
)
186 CharData_AppendXMLChars((CharData
*)userData
, s
, len
);
190 accumulate_attribute(void *userData
, const XML_Char
*name
,
191 const XML_Char
**atts
)
193 CharData
*storage
= (CharData
*)userData
;
194 if (storage
->count
< 0 && atts
!= NULL
&& atts
[0] != NULL
) {
195 /* "accumulate" the value of the first attribute we see */
196 CharData_AppendXMLChars(storage
, atts
[1], -1);
202 _run_character_check(XML_Char
*text
, XML_Char
*expected
,
203 const char *file
, int line
)
207 CharData_Init(&storage
);
208 XML_SetUserData(parser
, &storage
);
209 XML_SetCharacterDataHandler(parser
, accumulate_characters
);
210 if (XML_Parse(parser
, text
, strlen(text
), XML_TRUE
) == XML_STATUS_ERROR
)
211 _xml_failure(parser
, file
, line
);
212 CharData_CheckXMLChars(&storage
, expected
);
215 #define run_character_check(text, expected) \
216 _run_character_check(text, expected, __FILE__, __LINE__)
219 _run_attribute_check(XML_Char
*text
, XML_Char
*expected
,
220 const char *file
, int line
)
224 CharData_Init(&storage
);
225 XML_SetUserData(parser
, &storage
);
226 XML_SetStartElementHandler(parser
, accumulate_attribute
);
227 if (XML_Parse(parser
, text
, strlen(text
), XML_TRUE
) == XML_STATUS_ERROR
)
228 _xml_failure(parser
, file
, line
);
229 CharData_CheckXMLChars(&storage
, expected
);
232 #define run_attribute_check(text, expected) \
233 _run_attribute_check(text, expected, __FILE__, __LINE__)
235 /* Regression test for SF bug #491986. */
236 START_TEST(test_danish_latin1
)
239 "<?xml version='1.0' encoding='iso-8859-1'?>\n"
240 "<e>Jørgen æøåÆØÅ</e>";
241 run_character_check(text
,
242 "J\xC3\xB8rgen \xC3\xA6\xC3\xB8\xC3\xA5\xC3\x86\xC3\x98\xC3\x85");
247 /* Regression test for SF bug #514281. */
248 START_TEST(test_french_charref_hexidecimal
)
251 "<?xml version='1.0' encoding='iso-8859-1'?>\n"
252 "<doc>éèàçêÈ</doc>";
253 run_character_check(text
,
254 "\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
258 START_TEST(test_french_charref_decimal
)
261 "<?xml version='1.0' encoding='iso-8859-1'?>\n"
262 "<doc>éèàçêÈ</doc>";
263 run_character_check(text
,
264 "\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
268 START_TEST(test_french_latin1
)
271 "<?xml version='1.0' encoding='iso-8859-1'?>\n"
272 "<doc>\xE9\xE8\xE0\xE7\xEa\xC8</doc>";
273 run_character_check(text
,
274 "\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
278 START_TEST(test_french_utf8
)
281 "<?xml version='1.0' encoding='utf-8'?>\n"
282 "<doc>\xC3\xA9</doc>";
283 run_character_check(text
, "\xC3\xA9");
287 /* Regression test for SF bug #600479.
288 XXX There should be a test that exercises all legal XML Unicode
289 characters as PCDATA and attribute value content, and XML Name
290 characters as part of element and attribute names.
292 START_TEST(test_utf8_false_rejection
)
294 char *text
= "<doc>\xEF\xBA\xBF</doc>";
295 run_character_check(text
, "\xEF\xBA\xBF");
299 /* Regression test for SF bug #477667.
300 This test assures that any 8-bit character followed by a 7-bit
301 character will not be mistakenly interpreted as a valid UTF-8
304 START_TEST(test_illegal_utf8
)
309 for (i
= 128; i
<= 255; ++i
) {
310 sprintf(text
, "<e>%ccd</e>", i
);
311 if (XML_Parse(parser
, text
, strlen(text
), XML_TRUE
) == XML_STATUS_OK
) {
313 "expected token error for '%c' (ordinal %d) in UTF-8 text",
317 else if (XML_GetErrorCode(parser
) != XML_ERROR_INVALID_TOKEN
)
319 /* Reset the parser since we use the same parser repeatedly. */
320 XML_ParserReset(parser
, NULL
);
325 START_TEST(test_utf16
)
327 /* <?xml version="1.0" encoding="UTF-16"?>
328 <doc a='123'>some text</doc>
331 "\000<\000?\000x\000m\000\154\000 \000v\000e\000r\000s\000i\000o"
332 "\000n\000=\000'\0001\000.\000\060\000'\000 \000e\000n\000c\000o"
333 "\000d\000i\000n\000g\000=\000'\000U\000T\000F\000-\0001\000\066"
334 "\000'\000?\000>\000\n"
335 "\000<\000d\000o\000c\000 \000a\000=\000'\0001\0002\0003\000'"
336 "\000>\000s\000o\000m\000e\000 \000t\000e\000x\000t\000<\000/"
337 "\000d\000o\000c\000>";
338 if (XML_Parse(parser
, text
, sizeof(text
)-1, XML_TRUE
) == XML_STATUS_ERROR
)
343 START_TEST(test_utf16_le_epilog_newline
)
345 int first_chunk_bytes
= 17;
348 "<\000e\000/\000>\000" /* document element */
349 "\r\000\n\000\r\000\n\000"; /* epilog */
351 if (first_chunk_bytes
>= sizeof(text
) - 1)
352 fail("bad value of first_chunk_bytes");
353 if ( XML_Parse(parser
, text
, first_chunk_bytes
, XML_FALSE
)
358 rc
= XML_Parse(parser
, text
+ first_chunk_bytes
,
359 sizeof(text
) - first_chunk_bytes
- 1, XML_TRUE
);
360 if (rc
== XML_STATUS_ERROR
)
366 /* Regression test for SF bug #481609. */
367 START_TEST(test_latin1_umlauts
)
370 "<?xml version='1.0' encoding='iso-8859-1'?>\n"
371 "<e a='ä ö ü ä ö ü ä ö ü'\n"
372 " >ä ö ü ä ö ü ä ö ü</e>";
374 "\xC3\xA4 \xC3\xB6 \xC3\xBC "
375 "\xC3\xA4 \xC3\xB6 \xC3\xBC "
376 "\xC3\xA4 \xC3\xB6 \xC3\xBC";
377 run_character_check(text
, utf8
);
378 XML_ParserReset(parser
, NULL
);
379 run_attribute_check(text
, utf8
);
383 /* Regression test #1 for SF bug #653180. */
384 START_TEST(test_line_number_after_parse
)
392 if (XML_Parse(parser
, text
, strlen(text
), XML_FALSE
) == XML_STATUS_ERROR
)
394 lineno
= XML_GetCurrentLineNumber(parser
);
397 sprintf(buffer
, "expected 4 lines, saw %d", lineno
);
403 /* Regression test #2 for SF bug #653180. */
404 START_TEST(test_column_number_after_parse
)
406 char *text
= "<tag></tag>";
409 if (XML_Parse(parser
, text
, strlen(text
), XML_FALSE
) == XML_STATUS_ERROR
)
411 colno
= XML_GetCurrentColumnNumber(parser
);
414 sprintf(buffer
, "expected 11 columns, saw %d", colno
);
421 start_element_event_handler2(void *userData
, const XML_Char
*name
,
422 const XML_Char
**attr
)
424 CharData
*storage
= (CharData
*) userData
;
427 sprintf(buffer
, "<%s> at col:%d line:%d\n", name
,
428 XML_GetCurrentColumnNumber(parser
),
429 XML_GetCurrentLineNumber(parser
));
430 CharData_AppendString(storage
, buffer
);
434 end_element_event_handler2(void *userData
, const XML_Char
*name
)
436 CharData
*storage
= (CharData
*) userData
;
439 sprintf(buffer
, "</%s> at col:%d line:%d\n", name
,
440 XML_GetCurrentColumnNumber(parser
),
441 XML_GetCurrentLineNumber(parser
));
442 CharData_AppendString(storage
, buffer
);
445 /* Regression test #3 for SF bug #653180. */
446 START_TEST(test_line_and_column_numbers_inside_handlers
)
449 "<a>\n" /* Unix end-of-line */
450 " <b>\r\n" /* Windows end-of-line */
451 " <c/>\r" /* Mac OS end-of-line */
458 "<a> at col:0 line:1\n"
459 "<b> at col:2 line:2\n"
460 "<c> at col:4 line:3\n"
461 "</c> at col:8 line:3\n"
462 "</b> at col:2 line:4\n"
463 "<d> at col:2 line:5\n"
464 "<f> at col:4 line:6\n"
465 "</f> at col:8 line:6\n"
466 "</d> at col:2 line:7\n"
467 "</a> at col:0 line:8\n";
470 CharData_Init(&storage
);
471 XML_SetUserData(parser
, &storage
);
472 XML_SetStartElementHandler(parser
, start_element_event_handler2
);
473 XML_SetEndElementHandler(parser
, end_element_event_handler2
);
474 if (XML_Parse(parser
, text
, strlen(text
), XML_TRUE
) == XML_STATUS_ERROR
)
477 CharData_CheckString(&storage
, expected
);
481 /* Regression test #4 for SF bug #653180. */
482 START_TEST(test_line_number_after_error
)
487 " </a>"; /* missing </b> */
489 if (XML_Parse(parser
, text
, strlen(text
), XML_FALSE
) != XML_STATUS_ERROR
)
490 fail("Expected a parse error");
492 lineno
= XML_GetCurrentLineNumber(parser
);
495 sprintf(buffer
, "expected 3 lines, saw %d", lineno
);
501 /* Regression test #5 for SF bug #653180. */
502 START_TEST(test_column_number_after_error
)
507 " </a>"; /* missing </b> */
509 if (XML_Parse(parser
, text
, strlen(text
), XML_FALSE
) != XML_STATUS_ERROR
)
510 fail("Expected a parse error");
512 colno
= XML_GetCurrentColumnNumber(parser
);
515 sprintf(buffer
, "expected 4 columns, saw %d", colno
);
521 /* Regression test for SF bug #478332. */
522 START_TEST(test_really_long_lines
)
524 /* This parses an input line longer than INIT_DATA_BUF_SIZE
525 characters long (defined to be 1024 in xmlparse.c). We take a
526 really cheesy approach to building the input buffer, because
527 this avoids writing bugs in buffer-filling code.
532 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
533 /* until we have at least 1024 characters on the line: */
534 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
535 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
536 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
537 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
538 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
539 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
540 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
541 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
542 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
543 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
544 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
545 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
546 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
547 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
548 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
549 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
551 if (XML_Parse(parser
, text
, strlen(text
), XML_TRUE
) == XML_STATUS_ERROR
)
558 * Element event tests.
562 end_element_event_handler(void *userData
, const XML_Char
*name
)
564 CharData
*storage
= (CharData
*) userData
;
565 CharData_AppendString(storage
, "/");
566 CharData_AppendXMLChars(storage
, name
, -1);
569 START_TEST(test_end_element_events
)
571 char *text
= "<a><b><c/></b><d><f/></d></a>";
572 char *expected
= "/c/b/f/d/a";
575 CharData_Init(&storage
);
576 XML_SetUserData(parser
, &storage
);
577 XML_SetEndElementHandler(parser
, end_element_event_handler
);
578 if (XML_Parse(parser
, text
, strlen(text
), XML_TRUE
) == XML_STATUS_ERROR
)
580 CharData_CheckString(&storage
, expected
);
589 /* Helpers used by the following test; this checks any "attr" and "refs"
590 attributes to make sure whitespace has been normalized.
592 Return true if whitespace has been normalized in a string, using
593 the rules for attribute value normalization. The 'is_cdata' flag
594 is needed since CDATA attributes don't need to have multiple
595 whitespace characters collapsed to a single space, while other
596 attribute data types do. (Section 3.3.3 of the recommendation.)
599 is_whitespace_normalized(const XML_Char
*s
, int is_cdata
)
606 else if (*s
== '\t' || *s
== '\n' || *s
== '\r')
611 if (blanks
&& !is_cdata
)
612 /* illegal leading blanks */
615 else if (blanks
> 1 && !is_cdata
)
621 if (blanks
&& !is_cdata
)
626 /* Check the attribute whitespace checker: */
628 testhelper_is_whitespace_normalized(void)
630 assert(is_whitespace_normalized("abc", 0));
631 assert(is_whitespace_normalized("abc", 1));
632 assert(is_whitespace_normalized("abc def ghi", 0));
633 assert(is_whitespace_normalized("abc def ghi", 1));
634 assert(!is_whitespace_normalized(" abc def ghi", 0));
635 assert(is_whitespace_normalized(" abc def ghi", 1));
636 assert(!is_whitespace_normalized("abc def ghi", 0));
637 assert(is_whitespace_normalized("abc def ghi", 1));
638 assert(!is_whitespace_normalized("abc def ghi ", 0));
639 assert(is_whitespace_normalized("abc def ghi ", 1));
640 assert(!is_whitespace_normalized(" ", 0));
641 assert(is_whitespace_normalized(" ", 1));
642 assert(!is_whitespace_normalized("\t", 0));
643 assert(!is_whitespace_normalized("\t", 1));
644 assert(!is_whitespace_normalized("\n", 0));
645 assert(!is_whitespace_normalized("\n", 1));
646 assert(!is_whitespace_normalized("\r", 0));
647 assert(!is_whitespace_normalized("\r", 1));
648 assert(!is_whitespace_normalized("abc\t def", 1));
652 check_attr_contains_normalized_whitespace(void *userData
,
653 const XML_Char
*name
,
654 const XML_Char
**atts
)
657 for (i
= 0; atts
[i
] != NULL
; i
+= 2) {
658 const XML_Char
*attrname
= atts
[i
];
659 const XML_Char
*value
= atts
[i
+ 1];
660 if (strcmp("attr", attrname
) == 0
661 || strcmp("ents", attrname
) == 0
662 || strcmp("refs", attrname
) == 0) {
663 if (!is_whitespace_normalized(value
, 0)) {
665 sprintf(buffer
, "attribute value not normalized: %s='%s'",
673 START_TEST(test_attr_whitespace_normalization
)
678 " attr NMTOKENS #REQUIRED\n"
679 " ents ENTITIES #REQUIRED\n"
680 " refs IDREFS #REQUIRED>\n"
682 "<doc attr=' a b c\t\td\te\t' refs=' id-1 \t id-2\t\t' \n"
683 " ents=' ent-1 \t\r\n"
689 XML_SetStartElementHandler(parser
,
690 check_attr_contains_normalized_whitespace
);
691 if (XML_Parse(parser
, text
, strlen(text
), XML_TRUE
) == XML_STATUS_ERROR
)
698 * XML declaration tests.
701 START_TEST(test_xmldecl_misplaced
)
704 "<?xml version='1.0'?>\n"
706 XML_ERROR_MISPLACED_XML_PI
,
707 "failed to report misplaced XML declaration");
711 /* Regression test for SF bug #584832. */
713 UnknownEncodingHandler(void *data
,const XML_Char
*encoding
,XML_Encoding
*info
)
715 if (strcmp(encoding
,"unsupported-encoding") == 0) {
717 for (i
= 0; i
< 256; ++i
)
720 info
->convert
= NULL
;
721 info
->release
= NULL
;
722 return XML_STATUS_OK
;
724 return XML_STATUS_ERROR
;
727 START_TEST(test_unknown_encoding_internal_entity
)
730 "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
731 "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
734 XML_SetUnknownEncodingHandler(parser
, UnknownEncodingHandler
, NULL
);
735 if (XML_Parse(parser
, text
, strlen(text
), XML_TRUE
) == XML_STATUS_ERROR
)
740 /* Regression test for SF bug #620106. */
742 external_entity_loader_set_encoding(XML_Parser parser
,
743 const XML_Char
*context
,
744 const XML_Char
*base
,
745 const XML_Char
*systemId
,
746 const XML_Char
*publicId
)
748 /* This text says it's an unsupported encoding, but it's really
749 UTF-8, which we tell Expat using XML_SetEncoding().
752 "<?xml encoding='iso-8859-3'?>"
754 XML_Parser extparser
;
756 extparser
= XML_ExternalEntityParserCreate(parser
, context
, NULL
);
757 if (extparser
== NULL
)
758 fail("Could not create external entity parser.");
759 if (!XML_SetEncoding(extparser
, "utf-8"))
760 fail("XML_SetEncoding() ignored for external entity");
761 if ( XML_Parse(extparser
, text
, strlen(text
), XML_TRUE
)
762 == XML_STATUS_ERROR
) {
769 START_TEST(test_ext_entity_set_encoding
)
773 " <!ENTITY en SYSTEM 'http://xml.libexpat.org/dummy.ent'>\n"
777 XML_SetExternalEntityRefHandler(parser
,
778 external_entity_loader_set_encoding
);
779 run_character_check(text
, "\xC3\xA9");
783 /* Test that no error is reported for unknown entities if we don't
784 read an external subset. This was fixed in Expat 1.95.5.
786 START_TEST(test_wfc_undeclared_entity_unread_external_subset
) {
788 "<!DOCTYPE doc SYSTEM 'foo'>\n"
789 "<doc>&entity;</doc>";
791 if (XML_Parse(parser
, text
, strlen(text
), XML_TRUE
) == XML_STATUS_ERROR
)
796 /* Test that an error is reported for unknown entities if we don't
797 have an external subset.
799 START_TEST(test_wfc_undeclared_entity_no_external_subset
) {
800 expect_failure("<doc>&entity;</doc>",
801 XML_ERROR_UNDEFINED_ENTITY
,
802 "Parser did not report undefined entity w/out a DTD.");
806 /* Test that an error is reported for unknown entities if we don't
807 read an external subset, but have been declared standalone.
809 START_TEST(test_wfc_undeclared_entity_standalone
) {
811 "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
812 "<!DOCTYPE doc SYSTEM 'foo'>\n"
813 "<doc>&entity;</doc>";
816 XML_ERROR_UNDEFINED_ENTITY
,
817 "Parser did not report undefined entity (standalone).");
822 external_entity_loader(XML_Parser parser
,
823 const XML_Char
*context
,
824 const XML_Char
*base
,
825 const XML_Char
*systemId
,
826 const XML_Char
*publicId
)
828 char *text
= (char *)XML_GetUserData(parser
);
829 XML_Parser extparser
;
831 extparser
= XML_ExternalEntityParserCreate(parser
, context
, NULL
);
832 if (extparser
== NULL
)
833 fail("Could not create external entity parser.");
834 if ( XML_Parse(extparser
, text
, strlen(text
), XML_TRUE
)
835 == XML_STATUS_ERROR
) {
837 return XML_STATUS_ERROR
;
839 return XML_STATUS_OK
;
842 /* Test that an error is reported for unknown entities if we have read
843 an external subset, and standalone is true.
845 START_TEST(test_wfc_undeclared_entity_with_external_subset_standalone
) {
847 "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
848 "<!DOCTYPE doc SYSTEM 'foo'>\n"
849 "<doc>&entity;</doc>";
851 "<!ELEMENT doc (#PCDATA)*>";
853 XML_SetParamEntityParsing(parser
, XML_PARAM_ENTITY_PARSING_ALWAYS
);
854 XML_SetUserData(parser
, foo_text
);
855 XML_SetExternalEntityRefHandler(parser
, external_entity_loader
);
857 XML_ERROR_UNDEFINED_ENTITY
,
858 "Parser did not report undefined entity (external DTD).");
862 /* Test that no error is reported for unknown entities if we have read
863 an external subset, and standalone is false.
865 START_TEST(test_wfc_undeclared_entity_with_external_subset
) {
867 "<?xml version='1.0' encoding='us-ascii'?>\n"
868 "<!DOCTYPE doc SYSTEM 'foo'>\n"
869 "<doc>&entity;</doc>";
871 "<!ELEMENT doc (#PCDATA)*>";
873 XML_SetParamEntityParsing(parser
, XML_PARAM_ENTITY_PARSING_ALWAYS
);
874 XML_SetUserData(parser
, foo_text
);
875 XML_SetExternalEntityRefHandler(parser
, external_entity_loader
);
876 if (XML_Parse(parser
, text
, strlen(text
), XML_TRUE
) == XML_STATUS_ERROR
)
881 START_TEST(test_wfc_no_recursive_entity_refs
)
885 " <!ENTITY entity '&entity;'>\n"
887 "<doc>&entity;</doc>";
890 XML_ERROR_RECURSIVE_ENTITY_REF
,
891 "Parser did not report recursive entity reference.");
895 /* Regression test for SF bug #483514. */
896 START_TEST(test_dtd_default_handling
)
900 "<!ENTITY e SYSTEM 'http://xml.libexpat.org/e'>\n"
901 "<!NOTATION n SYSTEM 'http://xml.libexpat.org/n'>\n"
902 "<!ELEMENT doc EMPTY>\n"
903 "<!ATTLIST doc a CDATA #IMPLIED>\n"
905 "<!--comment in dtd-->\n"
908 XML_SetDefaultHandler(parser
, accumulate_characters
);
909 XML_SetDoctypeDeclHandler(parser
,
910 dummy_start_doctype_handler
,
911 dummy_end_doctype_handler
);
912 XML_SetEntityDeclHandler(parser
, dummy_entity_decl_handler
);
913 XML_SetNotationDeclHandler(parser
, dummy_notation_decl_handler
);
914 XML_SetElementDeclHandler(parser
, dummy_element_decl_handler
);
915 XML_SetAttlistDeclHandler(parser
, dummy_attlist_decl_handler
);
916 XML_SetProcessingInstructionHandler(parser
, dummy_pi_handler
);
917 XML_SetCommentHandler(parser
, dummy_comment_handler
);
918 run_character_check(text
, "\n\n\n\n\n\n\n<doc/>");
922 /* See related SF bug #673791.
923 When namespace processing is enabled, setting the namespace URI for
924 a prefix is not allowed; this test ensures that it *is* allowed
925 when namespace processing is not enabled.
926 (See Namespaces in XML, section 2.)
928 START_TEST(test_empty_ns_without_namespaces
)
931 "<doc xmlns:prefix='http://www.example.com/'>\n"
932 " <e xmlns:prefix=''/>\n"
935 if (XML_Parse(parser
, text
, strlen(text
), XML_TRUE
) == XML_STATUS_ERROR
)
946 namespace_setup(void)
948 parser
= XML_ParserCreateNS(NULL
, ' ');
950 fail("Parser not created.");
954 namespace_teardown(void)
959 /* Check that an element name and attribute name match the expected values.
960 The expected values are passed as an array reference of string pointers
961 provided as the userData argument; the first is the expected
962 element name, and the second is the expected attribute name.
965 triplet_start_checker(void *userData
, const XML_Char
*name
,
966 const XML_Char
**atts
)
968 char **elemstr
= (char **)userData
;
970 if (strcmp(elemstr
[0], name
) != 0) {
971 sprintf(buffer
, "unexpected start string: '%s'", name
);
974 if (strcmp(elemstr
[1], atts
[0]) != 0) {
975 sprintf(buffer
, "unexpected attribute string: '%s'", atts
[0]);
980 /* Check that the element name passed to the end-element handler matches
981 the expected value. The expected value is passed as the first element
982 in an array of strings passed as the userData argument.
985 triplet_end_checker(void *userData
, const XML_Char
*name
)
987 char **elemstr
= (char **)userData
;
988 if (strcmp(elemstr
[0], name
) != 0) {
990 sprintf(buffer
, "unexpected end string: '%s'", name
);
995 START_TEST(test_return_ns_triplet
)
998 "<foo:e xmlns:foo='http://expat.sf.net/' bar:a='12'\n"
999 " xmlns:bar='http://expat.sf.net/'></foo:e>";
1001 "http://expat.sf.net/ e foo",
1002 "http://expat.sf.net/ a bar"
1004 XML_SetReturnNSTriplet(parser
, XML_TRUE
);
1005 XML_SetUserData(parser
, elemstr
);
1006 XML_SetElementHandler(parser
, triplet_start_checker
, triplet_end_checker
);
1007 if (XML_Parse(parser
, text
, strlen(text
), XML_TRUE
) == XML_STATUS_ERROR
)
1008 xml_failure(parser
);
1013 overwrite_start_checker(void *userData
, const XML_Char
*name
,
1014 const XML_Char
**atts
)
1016 CharData
*storage
= (CharData
*) userData
;
1017 CharData_AppendString(storage
, "start ");
1018 CharData_AppendXMLChars(storage
, name
, -1);
1019 while (*atts
!= NULL
) {
1020 CharData_AppendString(storage
, "\nattribute ");
1021 CharData_AppendXMLChars(storage
, *atts
, -1);
1024 CharData_AppendString(storage
, "\n");
1028 overwrite_end_checker(void *userData
, const XML_Char
*name
)
1030 CharData
*storage
= (CharData
*) userData
;
1031 CharData_AppendString(storage
, "end ");
1032 CharData_AppendXMLChars(storage
, name
, -1);
1033 CharData_AppendString(storage
, "\n");
1037 run_ns_tagname_overwrite_test(char *text
, char *result
)
1040 CharData_Init(&storage
);
1041 XML_SetUserData(parser
, &storage
);
1042 XML_SetElementHandler(parser
,
1043 overwrite_start_checker
, overwrite_end_checker
);
1044 if (XML_Parse(parser
, text
, strlen(text
), XML_TRUE
) == XML_STATUS_ERROR
)
1045 xml_failure(parser
);
1046 CharData_CheckString(&storage
, result
);
1049 /* Regression test for SF bug #566334. */
1050 START_TEST(test_ns_tagname_overwrite
)
1053 "<n:e xmlns:n='http://xml.libexpat.org/'>\n"
1054 " <n:f n:attr='foo'/>\n"
1055 " <n:g n:attr2='bar'/>\n"
1058 "start http://xml.libexpat.org/ e\n"
1059 "start http://xml.libexpat.org/ f\n"
1060 "attribute http://xml.libexpat.org/ attr\n"
1061 "end http://xml.libexpat.org/ f\n"
1062 "start http://xml.libexpat.org/ g\n"
1063 "attribute http://xml.libexpat.org/ attr2\n"
1064 "end http://xml.libexpat.org/ g\n"
1065 "end http://xml.libexpat.org/ e\n";
1066 run_ns_tagname_overwrite_test(text
, result
);
1070 /* Regression test for SF bug #566334. */
1071 START_TEST(test_ns_tagname_overwrite_triplet
)
1074 "<n:e xmlns:n='http://xml.libexpat.org/'>\n"
1075 " <n:f n:attr='foo'/>\n"
1076 " <n:g n:attr2='bar'/>\n"
1079 "start http://xml.libexpat.org/ e n\n"
1080 "start http://xml.libexpat.org/ f n\n"
1081 "attribute http://xml.libexpat.org/ attr n\n"
1082 "end http://xml.libexpat.org/ f n\n"
1083 "start http://xml.libexpat.org/ g n\n"
1084 "attribute http://xml.libexpat.org/ attr2 n\n"
1085 "end http://xml.libexpat.org/ g n\n"
1086 "end http://xml.libexpat.org/ e n\n";
1087 XML_SetReturnNSTriplet(parser
, XML_TRUE
);
1088 run_ns_tagname_overwrite_test(text
, result
);
1093 /* Regression test for SF bug #620343. */
1095 start_element_fail(void *userData
,
1096 const XML_Char
*name
, const XML_Char
**atts
)
1098 /* We should never get here. */
1099 fail("should never reach start_element_fail()");
1103 start_ns_clearing_start_element(void *userData
,
1104 const XML_Char
*prefix
,
1105 const XML_Char
*uri
)
1107 XML_SetStartElementHandler((XML_Parser
) userData
, NULL
);
1110 START_TEST(test_start_ns_clears_start_element
)
1112 /* This needs to use separate start/end tags; using the empty tag
1113 syntax doesn't cause the problematic path through Expat to be
1116 char *text
= "<e xmlns='http://xml.libexpat.org/'></e>";
1118 XML_SetStartElementHandler(parser
, start_element_fail
);
1119 XML_SetStartNamespaceDeclHandler(parser
, start_ns_clearing_start_element
);
1120 XML_UseParserAsHandlerArg(parser
);
1121 if (XML_Parse(parser
, text
, strlen(text
), XML_TRUE
) == XML_STATUS_ERROR
)
1122 xml_failure(parser
);
1126 /* Regression test for SF bug #616863. */
1128 external_entity_handler(XML_Parser parser
,
1129 const XML_Char
*context
,
1130 const XML_Char
*base
,
1131 const XML_Char
*systemId
,
1132 const XML_Char
*publicId
)
1134 int callno
= 1 + (int)XML_GetUserData(parser
);
1139 text
= ("<!ELEMENT doc (e+)>\n"
1140 "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
1141 "<!ELEMENT e EMPTY>\n");
1143 text
= ("<?xml version='1.0' encoding='us-ascii'?>"
1146 XML_SetUserData(parser
, (void *) callno
);
1147 p2
= XML_ExternalEntityParserCreate(parser
, context
, NULL
);
1148 if (XML_Parse(p2
, text
, strlen(text
), XML_TRUE
) == XML_STATUS_ERROR
) {
1156 START_TEST(test_default_ns_from_ext_subset_and_ext_ge
)
1159 "<?xml version='1.0'?>\n"
1160 "<!DOCTYPE doc SYSTEM 'http://xml.libexpat.org/doc.dtd' [\n"
1161 " <!ENTITY en SYSTEM 'http://xml.libexpat.org/entity.ent'>\n"
1163 "<doc xmlns='http://xml.libexpat.org/ns1'>\n"
1167 XML_SetParamEntityParsing(parser
, XML_PARAM_ENTITY_PARSING_ALWAYS
);
1168 XML_SetExternalEntityRefHandler(parser
, external_entity_handler
);
1169 /* We actually need to set this handler to tickle this bug. */
1170 XML_SetStartElementHandler(parser
, dummy_start_element
);
1171 XML_SetUserData(parser
, NULL
);
1172 if (XML_Parse(parser
, text
, strlen(text
), XML_TRUE
) == XML_STATUS_ERROR
)
1173 xml_failure(parser
);
1177 /* Regression test #1 for SF bug #673791. */
1178 START_TEST(test_ns_prefix_with_empty_uri_1
)
1181 "<doc xmlns:prefix='http://xml.libexpat.org/'>\n"
1182 " <e xmlns:prefix=''/>\n"
1185 expect_failure(text
,
1187 "Did not report re-setting namespace"
1188 " URI with prefix to ''.");
1192 /* Regression test #2 for SF bug #673791. */
1193 START_TEST(test_ns_prefix_with_empty_uri_2
)
1196 "<?xml version='1.0'?>\n"
1197 "<docelem xmlns:pre=''/>";
1199 expect_failure(text
,
1201 "Did not report setting namespace URI with prefix to ''.");
1205 /* Regression test #3 for SF bug #673791. */
1206 START_TEST(test_ns_prefix_with_empty_uri_3
)
1210 " <!ELEMENT doc EMPTY>\n"
1212 " xmlns:prefix CDATA ''>\n"
1216 expect_failure(text
,
1218 "Didn't report attr default setting NS w/ prefix to ''.");
1222 /* Regression test #4 for SF bug #673791. */
1223 START_TEST(test_ns_prefix_with_empty_uri_4
)
1227 " <!ELEMENT prefix:doc EMPTY>\n"
1228 " <!ATTLIST prefix:doc\n"
1229 " xmlns:prefix CDATA 'http://xml.libexpat.org/'>\n"
1232 /* Packaged info expected by the end element handler;
1233 the weird structuring lets us re-use the triplet_end_checker()
1234 function also used for another test. */
1236 "http://xml.libexpat.org/ doc prefix"
1238 XML_SetReturnNSTriplet(parser
, XML_TRUE
);
1239 XML_SetUserData(parser
, elemstr
);
1240 XML_SetEndElementHandler(parser
, triplet_end_checker
);
1241 if (XML_Parse(parser
, text
, strlen(text
), XML_TRUE
) == XML_STATUS_ERROR
)
1242 xml_failure(parser
);
1246 START_TEST(test_ns_default_with_empty_uri
)
1249 "<doc xmlns='http://xml.libexpat.org/'>\n"
1252 if (XML_Parse(parser
, text
, strlen(text
), XML_TRUE
) == XML_STATUS_ERROR
)
1253 xml_failure(parser
);
1258 make_basic_suite(void)
1260 Suite
*s
= suite_create("basic");
1261 TCase
*tc_basic
= tcase_create("basic tests");
1262 TCase
*tc_namespace
= tcase_create("XML namespaces");
1264 suite_add_tcase(s
, tc_basic
);
1265 tcase_add_checked_fixture(tc_basic
, basic_setup
, basic_teardown
);
1266 tcase_add_test(tc_basic
, test_nul_byte
);
1267 tcase_add_test(tc_basic
, test_u0000_char
);
1268 tcase_add_test(tc_basic
, test_bom_utf8
);
1269 tcase_add_test(tc_basic
, test_bom_utf16_be
);
1270 tcase_add_test(tc_basic
, test_bom_utf16_le
);
1271 tcase_add_test(tc_basic
, test_illegal_utf8
);
1272 tcase_add_test(tc_basic
, test_utf16
);
1273 tcase_add_test(tc_basic
, test_utf16_le_epilog_newline
);
1274 tcase_add_test(tc_basic
, test_latin1_umlauts
);
1275 /* Regression test for SF bug #491986. */
1276 tcase_add_test(tc_basic
, test_danish_latin1
);
1277 /* Regression test for SF bug #514281. */
1278 tcase_add_test(tc_basic
, test_french_charref_hexidecimal
);
1279 tcase_add_test(tc_basic
, test_french_charref_decimal
);
1280 tcase_add_test(tc_basic
, test_french_latin1
);
1281 tcase_add_test(tc_basic
, test_french_utf8
);
1282 tcase_add_test(tc_basic
, test_utf8_false_rejection
);
1283 tcase_add_test(tc_basic
, test_line_number_after_parse
);
1284 tcase_add_test(tc_basic
, test_column_number_after_parse
);
1285 tcase_add_test(tc_basic
, test_line_and_column_numbers_inside_handlers
);
1286 tcase_add_test(tc_basic
, test_line_number_after_error
);
1287 tcase_add_test(tc_basic
, test_column_number_after_error
);
1288 tcase_add_test(tc_basic
, test_really_long_lines
);
1289 tcase_add_test(tc_basic
, test_end_element_events
);
1290 tcase_add_test(tc_basic
, test_attr_whitespace_normalization
);
1291 tcase_add_test(tc_basic
, test_xmldecl_misplaced
);
1292 tcase_add_test(tc_basic
, test_unknown_encoding_internal_entity
);
1293 tcase_add_test(tc_basic
,
1294 test_wfc_undeclared_entity_unread_external_subset
);
1295 tcase_add_test(tc_basic
, test_wfc_undeclared_entity_no_external_subset
);
1296 tcase_add_test(tc_basic
, test_wfc_undeclared_entity_standalone
);
1297 tcase_add_test(tc_basic
, test_wfc_undeclared_entity_with_external_subset
);
1298 tcase_add_test(tc_basic
,
1299 test_wfc_undeclared_entity_with_external_subset_standalone
);
1300 tcase_add_test(tc_basic
, test_wfc_no_recursive_entity_refs
);
1301 tcase_add_test(tc_basic
, test_ext_entity_set_encoding
);
1302 tcase_add_test(tc_basic
, test_dtd_default_handling
);
1303 tcase_add_test(tc_basic
, test_empty_ns_without_namespaces
);
1305 suite_add_tcase(s
, tc_namespace
);
1306 tcase_add_checked_fixture(tc_namespace
,
1307 namespace_setup
, namespace_teardown
);
1308 tcase_add_test(tc_namespace
, test_return_ns_triplet
);
1309 tcase_add_test(tc_namespace
, test_ns_tagname_overwrite
);
1310 tcase_add_test(tc_namespace
, test_ns_tagname_overwrite_triplet
);
1311 tcase_add_test(tc_namespace
, test_start_ns_clears_start_element
);
1312 tcase_add_test(tc_namespace
, test_default_ns_from_ext_subset_and_ext_ge
);
1313 tcase_add_test(tc_namespace
, test_ns_prefix_with_empty_uri_1
);
1314 tcase_add_test(tc_namespace
, test_ns_prefix_with_empty_uri_2
);
1315 tcase_add_test(tc_namespace
, test_ns_prefix_with_empty_uri_3
);
1316 tcase_add_test(tc_namespace
, test_ns_prefix_with_empty_uri_4
);
1317 tcase_add_test(tc_namespace
, test_ns_default_with_empty_uri
);
1324 main(int argc
, char *argv
[])
1327 int forking
= 0, forking_set
= 0;
1328 int verbosity
= CK_NORMAL
;
1329 Suite
*s
= make_basic_suite();
1330 SRunner
*sr
= srunner_create(s
);
1332 /* run the tests for internal helper functions */
1333 testhelper_is_whitespace_normalized();
1335 for (i
= 1; i
< argc
; ++i
) {
1336 char *opt
= argv
[i
];
1337 if (strcmp(opt
, "-v") == 0 || strcmp(opt
, "--verbose") == 0)
1338 verbosity
= CK_VERBOSE
;
1339 else if (strcmp(opt
, "-q") == 0 || strcmp(opt
, "--quiet") == 0)
1340 verbosity
= CK_SILENT
;
1341 else if (strcmp(opt
, "-f") == 0 || strcmp(opt
, "--fork") == 0) {
1345 else if (strcmp(opt
, "-n") == 0 || strcmp(opt
, "--no-fork") == 0) {
1350 fprintf(stderr
, "runtests: unknown option '%s'\n", opt
);
1355 srunner_set_fork_status(sr
, forking
? CK_FORK
: CK_NOFORK
);
1356 if (verbosity
!= CK_SILENT
)
1357 printf("Expat version: %s\n", XML_ExpatVersion());
1358 srunner_run_all(sr
, verbosity
);
1359 nf
= srunner_ntests_failed(sr
);
1363 return (nf
== 0) ? EXIT_SUCCESS
: EXIT_FAILURE
;