Annotation of embedaddon/expat/tests/runtests.c, revision 1.1.1.1
1.1 misho 1: /* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
2: See the file COPYING for copying permission.
3:
4: runtest.c : run the Expat test suite
5: */
6:
7: #ifdef HAVE_EXPAT_CONFIG_H
8: #include <expat_config.h>
9: #endif
10:
11: #include <assert.h>
12: #include <stdlib.h>
13: #include <stdio.h>
14: #include <string.h>
15:
16: #include "expat.h"
17: #include "chardata.h"
18: #include "minicheck.h"
19:
20: #if defined(__amigaos__) && defined(__USE_INLINE__)
21: #include <proto/expat.h>
22: #endif
23:
24: #ifdef XML_LARGE_SIZE
25: #define XML_FMT_INT_MOD "ll"
26: #else
27: #define XML_FMT_INT_MOD "l"
28: #endif
29:
30: static XML_Parser parser;
31:
32:
33: static void
34: basic_setup(void)
35: {
36: parser = XML_ParserCreate(NULL);
37: if (parser == NULL)
38: fail("Parser not created.");
39: }
40:
41: static void
42: basic_teardown(void)
43: {
44: if (parser != NULL)
45: XML_ParserFree(parser);
46: }
47:
48: /* Generate a failure using the parser state to create an error message;
49: this should be used when the parser reports an error we weren't
50: expecting.
51: */
52: static void
53: _xml_failure(XML_Parser parser, const char *file, int line)
54: {
55: char buffer[1024];
56: enum XML_Error err = XML_GetErrorCode(parser);
57: sprintf(buffer,
58: " %d: %s (line %" XML_FMT_INT_MOD "u, offset %"\
59: XML_FMT_INT_MOD "u)\n reported from %s, line %d\n",
60: err,
61: XML_ErrorString(err),
62: XML_GetCurrentLineNumber(parser),
63: XML_GetCurrentColumnNumber(parser),
64: file, line);
65: _fail_unless(0, file, line, buffer);
66: }
67:
68: #define xml_failure(parser) _xml_failure((parser), __FILE__, __LINE__)
69:
70: static void
71: _expect_failure(char *text, enum XML_Error errorCode, char *errorMessage,
72: char *file, int lineno)
73: {
74: if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_OK)
75: /* Hackish use of _fail_unless() macro, but let's us report
76: the right filename and line number. */
77: _fail_unless(0, file, lineno, errorMessage);
78: if (XML_GetErrorCode(parser) != errorCode)
79: _xml_failure(parser, file, lineno);
80: }
81:
82: #define expect_failure(text, errorCode, errorMessage) \
83: _expect_failure((text), (errorCode), (errorMessage), \
84: __FILE__, __LINE__)
85:
86: /* Dummy handlers for when we need to set a handler to tickle a bug,
87: but it doesn't need to do anything.
88: */
89:
90: static void XMLCALL
91: dummy_start_doctype_handler(void *userData,
92: const XML_Char *doctypeName,
93: const XML_Char *sysid,
94: const XML_Char *pubid,
95: int has_internal_subset)
96: {}
97:
98: static void XMLCALL
99: dummy_end_doctype_handler(void *userData)
100: {}
101:
102: static void XMLCALL
103: dummy_entity_decl_handler(void *userData,
104: const XML_Char *entityName,
105: int is_parameter_entity,
106: const XML_Char *value,
107: int value_length,
108: const XML_Char *base,
109: const XML_Char *systemId,
110: const XML_Char *publicId,
111: const XML_Char *notationName)
112: {}
113:
114: static void XMLCALL
115: dummy_notation_decl_handler(void *userData,
116: const XML_Char *notationName,
117: const XML_Char *base,
118: const XML_Char *systemId,
119: const XML_Char *publicId)
120: {}
121:
122: static void XMLCALL
123: dummy_element_decl_handler(void *userData,
124: const XML_Char *name,
125: XML_Content *model)
126: {}
127:
128: static void XMLCALL
129: dummy_attlist_decl_handler(void *userData,
130: const XML_Char *elname,
131: const XML_Char *attname,
132: const XML_Char *att_type,
133: const XML_Char *dflt,
134: int isrequired)
135: {}
136:
137: static void XMLCALL
138: dummy_comment_handler(void *userData, const XML_Char *data)
139: {}
140:
141: static void XMLCALL
142: dummy_pi_handler(void *userData, const XML_Char *target, const XML_Char *data)
143: {}
144:
145: static void XMLCALL
146: dummy_start_element(void *userData,
147: const XML_Char *name, const XML_Char **atts)
148: {}
149:
150:
151: /*
152: * Character & encoding tests.
153: */
154:
155: START_TEST(test_nul_byte)
156: {
157: char text[] = "<doc>\0</doc>";
158:
159: /* test that a NUL byte (in US-ASCII data) is an error */
160: if (XML_Parse(parser, text, sizeof(text) - 1, XML_TRUE) == XML_STATUS_OK)
161: fail("Parser did not report error on NUL-byte.");
162: if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)
163: xml_failure(parser);
164: }
165: END_TEST
166:
167:
168: START_TEST(test_u0000_char)
169: {
170: /* test that a NUL byte (in US-ASCII data) is an error */
171: expect_failure("<doc>�</doc>",
172: XML_ERROR_BAD_CHAR_REF,
173: "Parser did not report error on NUL-byte.");
174: }
175: END_TEST
176:
177: START_TEST(test_bom_utf8)
178: {
179: /* This test is really just making sure we don't core on a UTF-8 BOM. */
180: char *text = "\357\273\277<e/>";
181:
182: if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
183: xml_failure(parser);
184: }
185: END_TEST
186:
187: START_TEST(test_bom_utf16_be)
188: {
189: char text[] = "\376\377\0<\0e\0/\0>";
190:
191: if (XML_Parse(parser, text, sizeof(text)-1, XML_TRUE) == XML_STATUS_ERROR)
192: xml_failure(parser);
193: }
194: END_TEST
195:
196: START_TEST(test_bom_utf16_le)
197: {
198: char text[] = "\377\376<\0e\0/\0>\0";
199:
200: if (XML_Parse(parser, text, sizeof(text)-1, XML_TRUE) == XML_STATUS_ERROR)
201: xml_failure(parser);
202: }
203: END_TEST
204:
205: static void XMLCALL
206: accumulate_characters(void *userData, const XML_Char *s, int len)
207: {
208: CharData_AppendXMLChars((CharData *)userData, s, len);
209: }
210:
211: static void XMLCALL
212: accumulate_attribute(void *userData, const XML_Char *name,
213: const XML_Char **atts)
214: {
215: CharData *storage = (CharData *)userData;
216: if (storage->count < 0 && atts != NULL && atts[0] != NULL) {
217: /* "accumulate" the value of the first attribute we see */
218: CharData_AppendXMLChars(storage, atts[1], -1);
219: }
220: }
221:
222:
223: static void
224: _run_character_check(XML_Char *text, XML_Char *expected,
225: const char *file, int line)
226: {
227: CharData storage;
228:
229: CharData_Init(&storage);
230: XML_SetUserData(parser, &storage);
231: XML_SetCharacterDataHandler(parser, accumulate_characters);
232: if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
233: _xml_failure(parser, file, line);
234: CharData_CheckXMLChars(&storage, expected);
235: }
236:
237: #define run_character_check(text, expected) \
238: _run_character_check(text, expected, __FILE__, __LINE__)
239:
240: static void
241: _run_attribute_check(XML_Char *text, XML_Char *expected,
242: const char *file, int line)
243: {
244: CharData storage;
245:
246: CharData_Init(&storage);
247: XML_SetUserData(parser, &storage);
248: XML_SetStartElementHandler(parser, accumulate_attribute);
249: if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
250: _xml_failure(parser, file, line);
251: CharData_CheckXMLChars(&storage, expected);
252: }
253:
254: #define run_attribute_check(text, expected) \
255: _run_attribute_check(text, expected, __FILE__, __LINE__)
256:
257: /* Regression test for SF bug #491986. */
258: START_TEST(test_danish_latin1)
259: {
260: char *text =
261: "<?xml version='1.0' encoding='iso-8859-1'?>\n"
262: "<e>J\xF8rgen \xE6\xF8\xE5\xC6\xD8\xC5</e>";
263: run_character_check(text,
264: "J\xC3\xB8rgen \xC3\xA6\xC3\xB8\xC3\xA5\xC3\x86\xC3\x98\xC3\x85");
265: }
266: END_TEST
267:
268:
269: /* Regression test for SF bug #514281. */
270: START_TEST(test_french_charref_hexidecimal)
271: {
272: char *text =
273: "<?xml version='1.0' encoding='iso-8859-1'?>\n"
274: "<doc>éèàçêÈ</doc>";
275: run_character_check(text,
276: "\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
277: }
278: END_TEST
279:
280: START_TEST(test_french_charref_decimal)
281: {
282: char *text =
283: "<?xml version='1.0' encoding='iso-8859-1'?>\n"
284: "<doc>éèàçêÈ</doc>";
285: run_character_check(text,
286: "\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
287: }
288: END_TEST
289:
290: START_TEST(test_french_latin1)
291: {
292: char *text =
293: "<?xml version='1.0' encoding='iso-8859-1'?>\n"
294: "<doc>\xE9\xE8\xE0\xE7\xEa\xC8</doc>";
295: run_character_check(text,
296: "\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
297: }
298: END_TEST
299:
300: START_TEST(test_french_utf8)
301: {
302: char *text =
303: "<?xml version='1.0' encoding='utf-8'?>\n"
304: "<doc>\xC3\xA9</doc>";
305: run_character_check(text, "\xC3\xA9");
306: }
307: END_TEST
308:
309: /* Regression test for SF bug #600479.
310: XXX There should be a test that exercises all legal XML Unicode
311: characters as PCDATA and attribute value content, and XML Name
312: characters as part of element and attribute names.
313: */
314: START_TEST(test_utf8_false_rejection)
315: {
316: char *text = "<doc>\xEF\xBA\xBF</doc>";
317: run_character_check(text, "\xEF\xBA\xBF");
318: }
319: END_TEST
320:
321: /* Regression test for SF bug #477667.
322: This test assures that any 8-bit character followed by a 7-bit
323: character will not be mistakenly interpreted as a valid UTF-8
324: sequence.
325: */
326: START_TEST(test_illegal_utf8)
327: {
328: char text[100];
329: int i;
330:
331: for (i = 128; i <= 255; ++i) {
332: sprintf(text, "<e>%ccd</e>", i);
333: if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_OK) {
334: sprintf(text,
335: "expected token error for '%c' (ordinal %d) in UTF-8 text",
336: i, i);
337: fail(text);
338: }
339: else if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)
340: xml_failure(parser);
341: /* Reset the parser since we use the same parser repeatedly. */
342: XML_ParserReset(parser, NULL);
343: }
344: }
345: END_TEST
346:
347: START_TEST(test_utf16)
348: {
349: /* <?xml version="1.0" encoding="UTF-16"?>
350: <doc a='123'>some text</doc>
351: */
352: char text[] =
353: "\000<\000?\000x\000m\000\154\000 \000v\000e\000r\000s\000i\000o"
354: "\000n\000=\000'\0001\000.\000\060\000'\000 \000e\000n\000c\000o"
355: "\000d\000i\000n\000g\000=\000'\000U\000T\000F\000-\0001\000\066"
356: "\000'\000?\000>\000\n"
357: "\000<\000d\000o\000c\000 \000a\000=\000'\0001\0002\0003\000'"
358: "\000>\000s\000o\000m\000e\000 \000t\000e\000x\000t\000<\000/"
359: "\000d\000o\000c\000>";
360: if (XML_Parse(parser, text, sizeof(text)-1, XML_TRUE) == XML_STATUS_ERROR)
361: xml_failure(parser);
362: }
363: END_TEST
364:
365: START_TEST(test_utf16_le_epilog_newline)
366: {
367: unsigned int first_chunk_bytes = 17;
368: char text[] =
369: "\xFF\xFE" /* BOM */
370: "<\000e\000/\000>\000" /* document element */
371: "\r\000\n\000\r\000\n\000"; /* epilog */
372:
373: if (first_chunk_bytes >= sizeof(text) - 1)
374: fail("bad value of first_chunk_bytes");
375: if ( XML_Parse(parser, text, first_chunk_bytes, XML_FALSE)
376: == XML_STATUS_ERROR)
377: xml_failure(parser);
378: else {
379: enum XML_Status rc;
380: rc = XML_Parse(parser, text + first_chunk_bytes,
381: sizeof(text) - first_chunk_bytes - 1, XML_TRUE);
382: if (rc == XML_STATUS_ERROR)
383: xml_failure(parser);
384: }
385: }
386: END_TEST
387:
388: /* Regression test for SF bug #481609, #774028. */
389: START_TEST(test_latin1_umlauts)
390: {
391: char *text =
392: "<?xml version='1.0' encoding='iso-8859-1'?>\n"
393: "<e a='\xE4 \xF6 \xFC ä ö ü ä ö ü >'\n"
394: " >\xE4 \xF6 \xFC ä ö ü ä ö ü ></e>";
395: char *utf8 =
396: "\xC3\xA4 \xC3\xB6 \xC3\xBC "
397: "\xC3\xA4 \xC3\xB6 \xC3\xBC "
398: "\xC3\xA4 \xC3\xB6 \xC3\xBC >";
399: run_character_check(text, utf8);
400: XML_ParserReset(parser, NULL);
401: run_attribute_check(text, utf8);
402: }
403: END_TEST
404:
405: /* Regression test #1 for SF bug #653180. */
406: START_TEST(test_line_number_after_parse)
407: {
408: char *text =
409: "<tag>\n"
410: "\n"
411: "\n</tag>";
412: XML_Size lineno;
413:
414: if (XML_Parse(parser, text, strlen(text), XML_FALSE) == XML_STATUS_ERROR)
415: xml_failure(parser);
416: lineno = XML_GetCurrentLineNumber(parser);
417: if (lineno != 4) {
418: char buffer[100];
419: sprintf(buffer,
420: "expected 4 lines, saw %" XML_FMT_INT_MOD "u", lineno);
421: fail(buffer);
422: }
423: }
424: END_TEST
425:
426: /* Regression test #2 for SF bug #653180. */
427: START_TEST(test_column_number_after_parse)
428: {
429: char *text = "<tag></tag>";
430: XML_Size colno;
431:
432: if (XML_Parse(parser, text, strlen(text), XML_FALSE) == XML_STATUS_ERROR)
433: xml_failure(parser);
434: colno = XML_GetCurrentColumnNumber(parser);
435: if (colno != 11) {
436: char buffer[100];
437: sprintf(buffer,
438: "expected 11 columns, saw %" XML_FMT_INT_MOD "u", colno);
439: fail(buffer);
440: }
441: }
442: END_TEST
443:
444: static void XMLCALL
445: start_element_event_handler2(void *userData, const XML_Char *name,
446: const XML_Char **attr)
447: {
448: CharData *storage = (CharData *) userData;
449: char buffer[100];
450:
451: sprintf(buffer,
452: "<%s> at col:%" XML_FMT_INT_MOD "u line:%"\
453: XML_FMT_INT_MOD "u\n", name,
454: XML_GetCurrentColumnNumber(parser),
455: XML_GetCurrentLineNumber(parser));
456: CharData_AppendString(storage, buffer);
457: }
458:
459: static void XMLCALL
460: end_element_event_handler2(void *userData, const XML_Char *name)
461: {
462: CharData *storage = (CharData *) userData;
463: char buffer[100];
464:
465: sprintf(buffer,
466: "</%s> at col:%" XML_FMT_INT_MOD "u line:%"\
467: XML_FMT_INT_MOD "u\n", name,
468: XML_GetCurrentColumnNumber(parser),
469: XML_GetCurrentLineNumber(parser));
470: CharData_AppendString(storage, buffer);
471: }
472:
473: /* Regression test #3 for SF bug #653180. */
474: START_TEST(test_line_and_column_numbers_inside_handlers)
475: {
476: char *text =
477: "<a>\n" /* Unix end-of-line */
478: " <b>\r\n" /* Windows end-of-line */
479: " <c/>\r" /* Mac OS end-of-line */
480: " </b>\n"
481: " <d>\n"
482: " <f/>\n"
483: " </d>\n"
484: "</a>";
485: char *expected =
486: "<a> at col:0 line:1\n"
487: "<b> at col:2 line:2\n"
488: "<c> at col:4 line:3\n"
489: "</c> at col:8 line:3\n"
490: "</b> at col:2 line:4\n"
491: "<d> at col:2 line:5\n"
492: "<f> at col:4 line:6\n"
493: "</f> at col:8 line:6\n"
494: "</d> at col:2 line:7\n"
495: "</a> at col:0 line:8\n";
496: CharData storage;
497:
498: CharData_Init(&storage);
499: XML_SetUserData(parser, &storage);
500: XML_SetStartElementHandler(parser, start_element_event_handler2);
501: XML_SetEndElementHandler(parser, end_element_event_handler2);
502: if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
503: xml_failure(parser);
504:
505: CharData_CheckString(&storage, expected);
506: }
507: END_TEST
508:
509: /* Regression test #4 for SF bug #653180. */
510: START_TEST(test_line_number_after_error)
511: {
512: char *text =
513: "<a>\n"
514: " <b>\n"
515: " </a>"; /* missing </b> */
516: XML_Size lineno;
517: if (XML_Parse(parser, text, strlen(text), XML_FALSE) != XML_STATUS_ERROR)
518: fail("Expected a parse error");
519:
520: lineno = XML_GetCurrentLineNumber(parser);
521: if (lineno != 3) {
522: char buffer[100];
523: sprintf(buffer, "expected 3 lines, saw %" XML_FMT_INT_MOD "u", lineno);
524: fail(buffer);
525: }
526: }
527: END_TEST
528:
529: /* Regression test #5 for SF bug #653180. */
530: START_TEST(test_column_number_after_error)
531: {
532: char *text =
533: "<a>\n"
534: " <b>\n"
535: " </a>"; /* missing </b> */
536: XML_Size colno;
537: if (XML_Parse(parser, text, strlen(text), XML_FALSE) != XML_STATUS_ERROR)
538: fail("Expected a parse error");
539:
540: colno = XML_GetCurrentColumnNumber(parser);
541: if (colno != 4) {
542: char buffer[100];
543: sprintf(buffer,
544: "expected 4 columns, saw %" XML_FMT_INT_MOD "u", colno);
545: fail(buffer);
546: }
547: }
548: END_TEST
549:
550: /* Regression test for SF bug #478332. */
551: START_TEST(test_really_long_lines)
552: {
553: /* This parses an input line longer than INIT_DATA_BUF_SIZE
554: characters long (defined to be 1024 in xmlparse.c). We take a
555: really cheesy approach to building the input buffer, because
556: this avoids writing bugs in buffer-filling code.
557: */
558: char *text =
559: "<e>"
560: /* 64 chars */
561: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
562: /* until we have at least 1024 characters on the line: */
563: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
564: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
565: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
566: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
567: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
568: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
569: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
570: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
571: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
572: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
573: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
574: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
575: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
576: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
577: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
578: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
579: "</e>";
580: if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
581: xml_failure(parser);
582: }
583: END_TEST
584:
585:
586: /*
587: * Element event tests.
588: */
589:
590: static void XMLCALL
591: end_element_event_handler(void *userData, const XML_Char *name)
592: {
593: CharData *storage = (CharData *) userData;
594: CharData_AppendString(storage, "/");
595: CharData_AppendXMLChars(storage, name, -1);
596: }
597:
598: START_TEST(test_end_element_events)
599: {
600: char *text = "<a><b><c/></b><d><f/></d></a>";
601: char *expected = "/c/b/f/d/a";
602: CharData storage;
603:
604: CharData_Init(&storage);
605: XML_SetUserData(parser, &storage);
606: XML_SetEndElementHandler(parser, end_element_event_handler);
607: if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
608: xml_failure(parser);
609: CharData_CheckString(&storage, expected);
610: }
611: END_TEST
612:
613:
614: /*
615: * Attribute tests.
616: */
617:
618: /* Helpers used by the following test; this checks any "attr" and "refs"
619: attributes to make sure whitespace has been normalized.
620:
621: Return true if whitespace has been normalized in a string, using
622: the rules for attribute value normalization. The 'is_cdata' flag
623: is needed since CDATA attributes don't need to have multiple
624: whitespace characters collapsed to a single space, while other
625: attribute data types do. (Section 3.3.3 of the recommendation.)
626: */
627: static int
628: is_whitespace_normalized(const XML_Char *s, int is_cdata)
629: {
630: int blanks = 0;
631: int at_start = 1;
632: while (*s) {
633: if (*s == ' ')
634: ++blanks;
635: else if (*s == '\t' || *s == '\n' || *s == '\r')
636: return 0;
637: else {
638: if (at_start) {
639: at_start = 0;
640: if (blanks && !is_cdata)
641: /* illegal leading blanks */
642: return 0;
643: }
644: else if (blanks > 1 && !is_cdata)
645: return 0;
646: blanks = 0;
647: }
648: ++s;
649: }
650: if (blanks && !is_cdata)
651: return 0;
652: return 1;
653: }
654:
655: /* Check the attribute whitespace checker: */
656: static void
657: testhelper_is_whitespace_normalized(void)
658: {
659: assert(is_whitespace_normalized("abc", 0));
660: assert(is_whitespace_normalized("abc", 1));
661: assert(is_whitespace_normalized("abc def ghi", 0));
662: assert(is_whitespace_normalized("abc def ghi", 1));
663: assert(!is_whitespace_normalized(" abc def ghi", 0));
664: assert(is_whitespace_normalized(" abc def ghi", 1));
665: assert(!is_whitespace_normalized("abc def ghi", 0));
666: assert(is_whitespace_normalized("abc def ghi", 1));
667: assert(!is_whitespace_normalized("abc def ghi ", 0));
668: assert(is_whitespace_normalized("abc def ghi ", 1));
669: assert(!is_whitespace_normalized(" ", 0));
670: assert(is_whitespace_normalized(" ", 1));
671: assert(!is_whitespace_normalized("\t", 0));
672: assert(!is_whitespace_normalized("\t", 1));
673: assert(!is_whitespace_normalized("\n", 0));
674: assert(!is_whitespace_normalized("\n", 1));
675: assert(!is_whitespace_normalized("\r", 0));
676: assert(!is_whitespace_normalized("\r", 1));
677: assert(!is_whitespace_normalized("abc\t def", 1));
678: }
679:
680: static void XMLCALL
681: check_attr_contains_normalized_whitespace(void *userData,
682: const XML_Char *name,
683: const XML_Char **atts)
684: {
685: int i;
686: for (i = 0; atts[i] != NULL; i += 2) {
687: const XML_Char *attrname = atts[i];
688: const XML_Char *value = atts[i + 1];
689: if (strcmp("attr", attrname) == 0
690: || strcmp("ents", attrname) == 0
691: || strcmp("refs", attrname) == 0) {
692: if (!is_whitespace_normalized(value, 0)) {
693: char buffer[256];
694: sprintf(buffer, "attribute value not normalized: %s='%s'",
695: attrname, value);
696: fail(buffer);
697: }
698: }
699: }
700: }
701:
702: START_TEST(test_attr_whitespace_normalization)
703: {
704: char *text =
705: "<!DOCTYPE doc [\n"
706: " <!ATTLIST doc\n"
707: " attr NMTOKENS #REQUIRED\n"
708: " ents ENTITIES #REQUIRED\n"
709: " refs IDREFS #REQUIRED>\n"
710: "]>\n"
711: "<doc attr=' a b c\t\td\te\t' refs=' id-1 \t id-2\t\t' \n"
712: " ents=' ent-1 \t\r\n"
713: " ent-2 ' >\n"
714: " <e id='id-1'/>\n"
715: " <e id='id-2'/>\n"
716: "</doc>";
717:
718: XML_SetStartElementHandler(parser,
719: check_attr_contains_normalized_whitespace);
720: if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
721: xml_failure(parser);
722: }
723: END_TEST
724:
725:
726: /*
727: * XML declaration tests.
728: */
729:
730: START_TEST(test_xmldecl_misplaced)
731: {
732: expect_failure("\n"
733: "<?xml version='1.0'?>\n"
734: "<a/>",
735: XML_ERROR_MISPLACED_XML_PI,
736: "failed to report misplaced XML declaration");
737: }
738: END_TEST
739:
740: /* Regression test for SF bug #584832. */
741: static int XMLCALL
742: UnknownEncodingHandler(void *data,const XML_Char *encoding,XML_Encoding *info)
743: {
744: if (strcmp(encoding,"unsupported-encoding") == 0) {
745: int i;
746: for (i = 0; i < 256; ++i)
747: info->map[i] = i;
748: info->data = NULL;
749: info->convert = NULL;
750: info->release = NULL;
751: return XML_STATUS_OK;
752: }
753: return XML_STATUS_ERROR;
754: }
755:
756: START_TEST(test_unknown_encoding_internal_entity)
757: {
758: char *text =
759: "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
760: "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
761: "<test a='&foo;'/>";
762:
763: XML_SetUnknownEncodingHandler(parser, UnknownEncodingHandler, NULL);
764: if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
765: xml_failure(parser);
766: }
767: END_TEST
768:
769: /* Regression test for SF bug #620106. */
770: static int XMLCALL
771: external_entity_loader_set_encoding(XML_Parser parser,
772: const XML_Char *context,
773: const XML_Char *base,
774: const XML_Char *systemId,
775: const XML_Char *publicId)
776: {
777: /* This text says it's an unsupported encoding, but it's really
778: UTF-8, which we tell Expat using XML_SetEncoding().
779: */
780: char *text =
781: "<?xml encoding='iso-8859-3'?>"
782: "\xC3\xA9";
783: XML_Parser extparser;
784:
785: extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
786: if (extparser == NULL)
787: fail("Could not create external entity parser.");
788: if (!XML_SetEncoding(extparser, "utf-8"))
789: fail("XML_SetEncoding() ignored for external entity");
790: if ( XML_Parse(extparser, text, strlen(text), XML_TRUE)
791: == XML_STATUS_ERROR) {
792: xml_failure(parser);
793: return 0;
794: }
795: return 1;
796: }
797:
798: START_TEST(test_ext_entity_set_encoding)
799: {
800: char *text =
801: "<!DOCTYPE doc [\n"
802: " <!ENTITY en SYSTEM 'http://xml.libexpat.org/dummy.ent'>\n"
803: "]>\n"
804: "<doc>&en;</doc>";
805:
806: XML_SetExternalEntityRefHandler(parser,
807: external_entity_loader_set_encoding);
808: run_character_check(text, "\xC3\xA9");
809: }
810: END_TEST
811:
812: /* Test that no error is reported for unknown entities if we don't
813: read an external subset. This was fixed in Expat 1.95.5.
814: */
815: START_TEST(test_wfc_undeclared_entity_unread_external_subset) {
816: char *text =
817: "<!DOCTYPE doc SYSTEM 'foo'>\n"
818: "<doc>&entity;</doc>";
819:
820: if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
821: xml_failure(parser);
822: }
823: END_TEST
824:
825: /* Test that an error is reported for unknown entities if we don't
826: have an external subset.
827: */
828: START_TEST(test_wfc_undeclared_entity_no_external_subset) {
829: expect_failure("<doc>&entity;</doc>",
830: XML_ERROR_UNDEFINED_ENTITY,
831: "Parser did not report undefined entity w/out a DTD.");
832: }
833: END_TEST
834:
835: /* Test that an error is reported for unknown entities if we don't
836: read an external subset, but have been declared standalone.
837: */
838: START_TEST(test_wfc_undeclared_entity_standalone) {
839: char *text =
840: "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
841: "<!DOCTYPE doc SYSTEM 'foo'>\n"
842: "<doc>&entity;</doc>";
843:
844: expect_failure(text,
845: XML_ERROR_UNDEFINED_ENTITY,
846: "Parser did not report undefined entity (standalone).");
847: }
848: END_TEST
849:
850: static int XMLCALL
851: external_entity_loader(XML_Parser parser,
852: const XML_Char *context,
853: const XML_Char *base,
854: const XML_Char *systemId,
855: const XML_Char *publicId)
856: {
857: char *text = (char *)XML_GetUserData(parser);
858: XML_Parser extparser;
859:
860: extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
861: if (extparser == NULL)
862: fail("Could not create external entity parser.");
863: if ( XML_Parse(extparser, text, strlen(text), XML_TRUE)
864: == XML_STATUS_ERROR) {
865: xml_failure(parser);
866: return XML_STATUS_ERROR;
867: }
868: return XML_STATUS_OK;
869: }
870:
871: /* Test that an error is reported for unknown entities if we have read
872: an external subset, and standalone is true.
873: */
874: START_TEST(test_wfc_undeclared_entity_with_external_subset_standalone) {
875: char *text =
876: "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
877: "<!DOCTYPE doc SYSTEM 'foo'>\n"
878: "<doc>&entity;</doc>";
879: char *foo_text =
880: "<!ELEMENT doc (#PCDATA)*>";
881:
882: XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
883: XML_SetUserData(parser, foo_text);
884: XML_SetExternalEntityRefHandler(parser, external_entity_loader);
885: expect_failure(text,
886: XML_ERROR_UNDEFINED_ENTITY,
887: "Parser did not report undefined entity (external DTD).");
888: }
889: END_TEST
890:
891: /* Test that no error is reported for unknown entities if we have read
892: an external subset, and standalone is false.
893: */
894: START_TEST(test_wfc_undeclared_entity_with_external_subset) {
895: char *text =
896: "<?xml version='1.0' encoding='us-ascii'?>\n"
897: "<!DOCTYPE doc SYSTEM 'foo'>\n"
898: "<doc>&entity;</doc>";
899: char *foo_text =
900: "<!ELEMENT doc (#PCDATA)*>";
901:
902: XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
903: XML_SetUserData(parser, foo_text);
904: XML_SetExternalEntityRefHandler(parser, external_entity_loader);
905: if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
906: xml_failure(parser);
907: }
908: END_TEST
909:
910: START_TEST(test_wfc_no_recursive_entity_refs)
911: {
912: char *text =
913: "<!DOCTYPE doc [\n"
914: " <!ENTITY entity '&entity;'>\n"
915: "]>\n"
916: "<doc>&entity;</doc>";
917:
918: expect_failure(text,
919: XML_ERROR_RECURSIVE_ENTITY_REF,
920: "Parser did not report recursive entity reference.");
921: }
922: END_TEST
923:
924: /* Regression test for SF bug #483514. */
925: START_TEST(test_dtd_default_handling)
926: {
927: char *text =
928: "<!DOCTYPE doc [\n"
929: "<!ENTITY e SYSTEM 'http://xml.libexpat.org/e'>\n"
930: "<!NOTATION n SYSTEM 'http://xml.libexpat.org/n'>\n"
931: "<!ELEMENT doc EMPTY>\n"
932: "<!ATTLIST doc a CDATA #IMPLIED>\n"
933: "<?pi in dtd?>\n"
934: "<!--comment in dtd-->\n"
935: "]><doc/>";
936:
937: XML_SetDefaultHandler(parser, accumulate_characters);
938: XML_SetDoctypeDeclHandler(parser,
939: dummy_start_doctype_handler,
940: dummy_end_doctype_handler);
941: XML_SetEntityDeclHandler(parser, dummy_entity_decl_handler);
942: XML_SetNotationDeclHandler(parser, dummy_notation_decl_handler);
943: XML_SetElementDeclHandler(parser, dummy_element_decl_handler);
944: XML_SetAttlistDeclHandler(parser, dummy_attlist_decl_handler);
945: XML_SetProcessingInstructionHandler(parser, dummy_pi_handler);
946: XML_SetCommentHandler(parser, dummy_comment_handler);
947: run_character_check(text, "\n\n\n\n\n\n\n<doc/>");
948: }
949: END_TEST
950:
951: /* See related SF bug #673791.
952: When namespace processing is enabled, setting the namespace URI for
953: a prefix is not allowed; this test ensures that it *is* allowed
954: when namespace processing is not enabled.
955: (See Namespaces in XML, section 2.)
956: */
957: START_TEST(test_empty_ns_without_namespaces)
958: {
959: char *text =
960: "<doc xmlns:prefix='http://www.example.com/'>\n"
961: " <e xmlns:prefix=''/>\n"
962: "</doc>";
963:
964: if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
965: xml_failure(parser);
966: }
967: END_TEST
968:
969: /* Regression test for SF bug #824420.
970: Checks that an xmlns:prefix attribute set in an attribute's default
971: value isn't misinterpreted.
972: */
973: START_TEST(test_ns_in_attribute_default_without_namespaces)
974: {
975: char *text =
976: "<!DOCTYPE e:element [\n"
977: " <!ATTLIST e:element\n"
978: " xmlns:e CDATA 'http://example.com/'>\n"
979: " ]>\n"
980: "<e:element/>";
981:
982: if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
983: xml_failure(parser);
984: }
985: END_TEST
986:
987: static char *long_character_data_text =
988: "<?xml version='1.0' encoding='iso-8859-1'?><s>"
989: "012345678901234567890123456789012345678901234567890123456789"
990: "012345678901234567890123456789012345678901234567890123456789"
991: "012345678901234567890123456789012345678901234567890123456789"
992: "012345678901234567890123456789012345678901234567890123456789"
993: "012345678901234567890123456789012345678901234567890123456789"
994: "012345678901234567890123456789012345678901234567890123456789"
995: "012345678901234567890123456789012345678901234567890123456789"
996: "012345678901234567890123456789012345678901234567890123456789"
997: "012345678901234567890123456789012345678901234567890123456789"
998: "012345678901234567890123456789012345678901234567890123456789"
999: "012345678901234567890123456789012345678901234567890123456789"
1000: "012345678901234567890123456789012345678901234567890123456789"
1001: "012345678901234567890123456789012345678901234567890123456789"
1002: "012345678901234567890123456789012345678901234567890123456789"
1003: "012345678901234567890123456789012345678901234567890123456789"
1004: "012345678901234567890123456789012345678901234567890123456789"
1005: "012345678901234567890123456789012345678901234567890123456789"
1006: "012345678901234567890123456789012345678901234567890123456789"
1007: "012345678901234567890123456789012345678901234567890123456789"
1008: "012345678901234567890123456789012345678901234567890123456789"
1009: "</s>";
1010:
1011: static XML_Bool resumable = XML_FALSE;
1012:
1013: static void
1014: clearing_aborting_character_handler(void *userData,
1015: const XML_Char *s, int len)
1016: {
1017: XML_StopParser(parser, resumable);
1018: XML_SetCharacterDataHandler(parser, NULL);
1019: }
1020:
1021: /* Regression test for SF bug #1515266: missing check of stopped
1022: parser in doContext() 'for' loop. */
1023: START_TEST(test_stop_parser_between_char_data_calls)
1024: {
1025: /* The sample data must be big enough that there are two calls to
1026: the character data handler from within the inner "for" loop of
1027: the XML_TOK_DATA_CHARS case in doContent(), and the character
1028: handler must stop the parser and clear the character data
1029: handler.
1030: */
1031: char *text = long_character_data_text;
1032:
1033: XML_SetCharacterDataHandler(parser, clearing_aborting_character_handler);
1034: resumable = XML_FALSE;
1035: if (XML_Parse(parser, text, strlen(text), XML_TRUE) != XML_STATUS_ERROR)
1036: xml_failure(parser);
1037: if (XML_GetErrorCode(parser) != XML_ERROR_ABORTED)
1038: xml_failure(parser);
1039: }
1040: END_TEST
1041:
1042: /* Regression test for SF bug #1515266: missing check of stopped
1043: parser in doContext() 'for' loop. */
1044: START_TEST(test_suspend_parser_between_char_data_calls)
1045: {
1046: /* The sample data must be big enough that there are two calls to
1047: the character data handler from within the inner "for" loop of
1048: the XML_TOK_DATA_CHARS case in doContent(), and the character
1049: handler must stop the parser and clear the character data
1050: handler.
1051: */
1052: char *text = long_character_data_text;
1053:
1054: XML_SetCharacterDataHandler(parser, clearing_aborting_character_handler);
1055: resumable = XML_TRUE;
1056: if (XML_Parse(parser, text, strlen(text), XML_TRUE) != XML_STATUS_SUSPENDED)
1057: xml_failure(parser);
1058: if (XML_GetErrorCode(parser) != XML_ERROR_NONE)
1059: xml_failure(parser);
1060: }
1061: END_TEST
1062:
1063:
1064: /*
1065: * Namespaces tests.
1066: */
1067:
1068: static void
1069: namespace_setup(void)
1070: {
1071: parser = XML_ParserCreateNS(NULL, ' ');
1072: if (parser == NULL)
1073: fail("Parser not created.");
1074: }
1075:
1076: static void
1077: namespace_teardown(void)
1078: {
1079: basic_teardown();
1080: }
1081:
1082: /* Check that an element name and attribute name match the expected values.
1083: The expected values are passed as an array reference of string pointers
1084: provided as the userData argument; the first is the expected
1085: element name, and the second is the expected attribute name.
1086: */
1087: static void XMLCALL
1088: triplet_start_checker(void *userData, const XML_Char *name,
1089: const XML_Char **atts)
1090: {
1091: char **elemstr = (char **)userData;
1092: char buffer[1024];
1093: if (strcmp(elemstr[0], name) != 0) {
1094: sprintf(buffer, "unexpected start string: '%s'", name);
1095: fail(buffer);
1096: }
1097: if (strcmp(elemstr[1], atts[0]) != 0) {
1098: sprintf(buffer, "unexpected attribute string: '%s'", atts[0]);
1099: fail(buffer);
1100: }
1101: }
1102:
1103: /* Check that the element name passed to the end-element handler matches
1104: the expected value. The expected value is passed as the first element
1105: in an array of strings passed as the userData argument.
1106: */
1107: static void XMLCALL
1108: triplet_end_checker(void *userData, const XML_Char *name)
1109: {
1110: char **elemstr = (char **)userData;
1111: if (strcmp(elemstr[0], name) != 0) {
1112: char buffer[1024];
1113: sprintf(buffer, "unexpected end string: '%s'", name);
1114: fail(buffer);
1115: }
1116: }
1117:
1118: START_TEST(test_return_ns_triplet)
1119: {
1120: char *text =
1121: "<foo:e xmlns:foo='http://expat.sf.net/' bar:a='12'\n"
1122: " xmlns:bar='http://expat.sf.net/'></foo:e>";
1123: char *elemstr[] = {
1124: "http://expat.sf.net/ e foo",
1125: "http://expat.sf.net/ a bar"
1126: };
1127: XML_SetReturnNSTriplet(parser, XML_TRUE);
1128: XML_SetUserData(parser, elemstr);
1129: XML_SetElementHandler(parser, triplet_start_checker, triplet_end_checker);
1130: if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
1131: xml_failure(parser);
1132: }
1133: END_TEST
1134:
1135: static void XMLCALL
1136: overwrite_start_checker(void *userData, const XML_Char *name,
1137: const XML_Char **atts)
1138: {
1139: CharData *storage = (CharData *) userData;
1140: CharData_AppendString(storage, "start ");
1141: CharData_AppendXMLChars(storage, name, -1);
1142: while (*atts != NULL) {
1143: CharData_AppendString(storage, "\nattribute ");
1144: CharData_AppendXMLChars(storage, *atts, -1);
1145: atts += 2;
1146: }
1147: CharData_AppendString(storage, "\n");
1148: }
1149:
1150: static void XMLCALL
1151: overwrite_end_checker(void *userData, const XML_Char *name)
1152: {
1153: CharData *storage = (CharData *) userData;
1154: CharData_AppendString(storage, "end ");
1155: CharData_AppendXMLChars(storage, name, -1);
1156: CharData_AppendString(storage, "\n");
1157: }
1158:
1159: static void
1160: run_ns_tagname_overwrite_test(char *text, char *result)
1161: {
1162: CharData storage;
1163: CharData_Init(&storage);
1164: XML_SetUserData(parser, &storage);
1165: XML_SetElementHandler(parser,
1166: overwrite_start_checker, overwrite_end_checker);
1167: if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
1168: xml_failure(parser);
1169: CharData_CheckString(&storage, result);
1170: }
1171:
1172: /* Regression test for SF bug #566334. */
1173: START_TEST(test_ns_tagname_overwrite)
1174: {
1175: char *text =
1176: "<n:e xmlns:n='http://xml.libexpat.org/'>\n"
1177: " <n:f n:attr='foo'/>\n"
1178: " <n:g n:attr2='bar'/>\n"
1179: "</n:e>";
1180: char *result =
1181: "start http://xml.libexpat.org/ e\n"
1182: "start http://xml.libexpat.org/ f\n"
1183: "attribute http://xml.libexpat.org/ attr\n"
1184: "end http://xml.libexpat.org/ f\n"
1185: "start http://xml.libexpat.org/ g\n"
1186: "attribute http://xml.libexpat.org/ attr2\n"
1187: "end http://xml.libexpat.org/ g\n"
1188: "end http://xml.libexpat.org/ e\n";
1189: run_ns_tagname_overwrite_test(text, result);
1190: }
1191: END_TEST
1192:
1193: /* Regression test for SF bug #566334. */
1194: START_TEST(test_ns_tagname_overwrite_triplet)
1195: {
1196: char *text =
1197: "<n:e xmlns:n='http://xml.libexpat.org/'>\n"
1198: " <n:f n:attr='foo'/>\n"
1199: " <n:g n:attr2='bar'/>\n"
1200: "</n:e>";
1201: char *result =
1202: "start http://xml.libexpat.org/ e n\n"
1203: "start http://xml.libexpat.org/ f n\n"
1204: "attribute http://xml.libexpat.org/ attr n\n"
1205: "end http://xml.libexpat.org/ f n\n"
1206: "start http://xml.libexpat.org/ g n\n"
1207: "attribute http://xml.libexpat.org/ attr2 n\n"
1208: "end http://xml.libexpat.org/ g n\n"
1209: "end http://xml.libexpat.org/ e n\n";
1210: XML_SetReturnNSTriplet(parser, XML_TRUE);
1211: run_ns_tagname_overwrite_test(text, result);
1212: }
1213: END_TEST
1214:
1215:
1216: /* Regression test for SF bug #620343. */
1217: static void XMLCALL
1218: start_element_fail(void *userData,
1219: const XML_Char *name, const XML_Char **atts)
1220: {
1221: /* We should never get here. */
1222: fail("should never reach start_element_fail()");
1223: }
1224:
1225: static void XMLCALL
1226: start_ns_clearing_start_element(void *userData,
1227: const XML_Char *prefix,
1228: const XML_Char *uri)
1229: {
1230: XML_SetStartElementHandler((XML_Parser) userData, NULL);
1231: }
1232:
1233: START_TEST(test_start_ns_clears_start_element)
1234: {
1235: /* This needs to use separate start/end tags; using the empty tag
1236: syntax doesn't cause the problematic path through Expat to be
1237: taken.
1238: */
1239: char *text = "<e xmlns='http://xml.libexpat.org/'></e>";
1240:
1241: XML_SetStartElementHandler(parser, start_element_fail);
1242: XML_SetStartNamespaceDeclHandler(parser, start_ns_clearing_start_element);
1243: XML_UseParserAsHandlerArg(parser);
1244: if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
1245: xml_failure(parser);
1246: }
1247: END_TEST
1248:
1249: /* Regression test for SF bug #616863. */
1250: static int XMLCALL
1251: external_entity_handler(XML_Parser parser,
1252: const XML_Char *context,
1253: const XML_Char *base,
1254: const XML_Char *systemId,
1255: const XML_Char *publicId)
1256: {
1257: long callno = 1 + (long)XML_GetUserData(parser);
1258: char *text;
1259: XML_Parser p2;
1260:
1261: if (callno == 1)
1262: text = ("<!ELEMENT doc (e+)>\n"
1263: "<!ATTLIST doc xmlns CDATA #IMPLIED>\n"
1264: "<!ELEMENT e EMPTY>\n");
1265: else
1266: text = ("<?xml version='1.0' encoding='us-ascii'?>"
1267: "<e/>");
1268:
1269: XML_SetUserData(parser, (void *) callno);
1270: p2 = XML_ExternalEntityParserCreate(parser, context, NULL);
1271: if (XML_Parse(p2, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR) {
1272: xml_failure(p2);
1273: return 0;
1274: }
1275: XML_ParserFree(p2);
1276: return 1;
1277: }
1278:
1279: START_TEST(test_default_ns_from_ext_subset_and_ext_ge)
1280: {
1281: char *text =
1282: "<?xml version='1.0'?>\n"
1283: "<!DOCTYPE doc SYSTEM 'http://xml.libexpat.org/doc.dtd' [\n"
1284: " <!ENTITY en SYSTEM 'http://xml.libexpat.org/entity.ent'>\n"
1285: "]>\n"
1286: "<doc xmlns='http://xml.libexpat.org/ns1'>\n"
1287: "&en;\n"
1288: "</doc>";
1289:
1290: XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
1291: XML_SetExternalEntityRefHandler(parser, external_entity_handler);
1292: /* We actually need to set this handler to tickle this bug. */
1293: XML_SetStartElementHandler(parser, dummy_start_element);
1294: XML_SetUserData(parser, NULL);
1295: if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
1296: xml_failure(parser);
1297: }
1298: END_TEST
1299:
1300: /* Regression test #1 for SF bug #673791. */
1301: START_TEST(test_ns_prefix_with_empty_uri_1)
1302: {
1303: char *text =
1304: "<doc xmlns:prefix='http://xml.libexpat.org/'>\n"
1305: " <e xmlns:prefix=''/>\n"
1306: "</doc>";
1307:
1308: expect_failure(text,
1309: XML_ERROR_UNDECLARING_PREFIX,
1310: "Did not report re-setting namespace"
1311: " URI with prefix to ''.");
1312: }
1313: END_TEST
1314:
1315: /* Regression test #2 for SF bug #673791. */
1316: START_TEST(test_ns_prefix_with_empty_uri_2)
1317: {
1318: char *text =
1319: "<?xml version='1.0'?>\n"
1320: "<docelem xmlns:pre=''/>";
1321:
1322: expect_failure(text,
1323: XML_ERROR_UNDECLARING_PREFIX,
1324: "Did not report setting namespace URI with prefix to ''.");
1325: }
1326: END_TEST
1327:
1328: /* Regression test #3 for SF bug #673791. */
1329: START_TEST(test_ns_prefix_with_empty_uri_3)
1330: {
1331: char *text =
1332: "<!DOCTYPE doc [\n"
1333: " <!ELEMENT doc EMPTY>\n"
1334: " <!ATTLIST doc\n"
1335: " xmlns:prefix CDATA ''>\n"
1336: "]>\n"
1337: "<doc/>";
1338:
1339: expect_failure(text,
1340: XML_ERROR_UNDECLARING_PREFIX,
1341: "Didn't report attr default setting NS w/ prefix to ''.");
1342: }
1343: END_TEST
1344:
1345: /* Regression test #4 for SF bug #673791. */
1346: START_TEST(test_ns_prefix_with_empty_uri_4)
1347: {
1348: char *text =
1349: "<!DOCTYPE doc [\n"
1350: " <!ELEMENT prefix:doc EMPTY>\n"
1351: " <!ATTLIST prefix:doc\n"
1352: " xmlns:prefix CDATA 'http://xml.libexpat.org/'>\n"
1353: "]>\n"
1354: "<prefix:doc/>";
1355: /* Packaged info expected by the end element handler;
1356: the weird structuring lets us re-use the triplet_end_checker()
1357: function also used for another test. */
1358: char *elemstr[] = {
1359: "http://xml.libexpat.org/ doc prefix"
1360: };
1361: XML_SetReturnNSTriplet(parser, XML_TRUE);
1362: XML_SetUserData(parser, elemstr);
1363: XML_SetEndElementHandler(parser, triplet_end_checker);
1364: if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
1365: xml_failure(parser);
1366: }
1367: END_TEST
1368:
1369: START_TEST(test_ns_default_with_empty_uri)
1370: {
1371: char *text =
1372: "<doc xmlns='http://xml.libexpat.org/'>\n"
1373: " <e xmlns=''/>\n"
1374: "</doc>";
1375: if (XML_Parse(parser, text, strlen(text), XML_TRUE) == XML_STATUS_ERROR)
1376: xml_failure(parser);
1377: }
1378: END_TEST
1379:
1380: /* Regression test for SF bug #692964: two prefixes for one namespace. */
1381: START_TEST(test_ns_duplicate_attrs_diff_prefixes)
1382: {
1383: char *text =
1384: "<doc xmlns:a='http://xml.libexpat.org/a'\n"
1385: " xmlns:b='http://xml.libexpat.org/a'\n"
1386: " a:a='v' b:a='v' />";
1387: expect_failure(text,
1388: XML_ERROR_DUPLICATE_ATTRIBUTE,
1389: "did not report multiple attributes with same URI+name");
1390: }
1391: END_TEST
1392:
1393: /* Regression test for SF bug #695401: unbound prefix. */
1394: START_TEST(test_ns_unbound_prefix_on_attribute)
1395: {
1396: char *text = "<doc a:attr=''/>";
1397: expect_failure(text,
1398: XML_ERROR_UNBOUND_PREFIX,
1399: "did not report unbound prefix on attribute");
1400: }
1401: END_TEST
1402:
1403: /* Regression test for SF bug #695401: unbound prefix. */
1404: START_TEST(test_ns_unbound_prefix_on_element)
1405: {
1406: char *text = "<a:doc/>";
1407: expect_failure(text,
1408: XML_ERROR_UNBOUND_PREFIX,
1409: "did not report unbound prefix on element");
1410: }
1411: END_TEST
1412:
1413: static Suite *
1414: make_suite(void)
1415: {
1416: Suite *s = suite_create("basic");
1417: TCase *tc_basic = tcase_create("basic tests");
1418: TCase *tc_namespace = tcase_create("XML namespaces");
1419:
1420: suite_add_tcase(s, tc_basic);
1421: tcase_add_checked_fixture(tc_basic, basic_setup, basic_teardown);
1422: tcase_add_test(tc_basic, test_nul_byte);
1423: tcase_add_test(tc_basic, test_u0000_char);
1424: tcase_add_test(tc_basic, test_bom_utf8);
1425: tcase_add_test(tc_basic, test_bom_utf16_be);
1426: tcase_add_test(tc_basic, test_bom_utf16_le);
1427: tcase_add_test(tc_basic, test_illegal_utf8);
1428: tcase_add_test(tc_basic, test_utf16);
1429: tcase_add_test(tc_basic, test_utf16_le_epilog_newline);
1430: tcase_add_test(tc_basic, test_latin1_umlauts);
1431: /* Regression test for SF bug #491986. */
1432: tcase_add_test(tc_basic, test_danish_latin1);
1433: /* Regression test for SF bug #514281. */
1434: tcase_add_test(tc_basic, test_french_charref_hexidecimal);
1435: tcase_add_test(tc_basic, test_french_charref_decimal);
1436: tcase_add_test(tc_basic, test_french_latin1);
1437: tcase_add_test(tc_basic, test_french_utf8);
1438: tcase_add_test(tc_basic, test_utf8_false_rejection);
1439: tcase_add_test(tc_basic, test_line_number_after_parse);
1440: tcase_add_test(tc_basic, test_column_number_after_parse);
1441: tcase_add_test(tc_basic, test_line_and_column_numbers_inside_handlers);
1442: tcase_add_test(tc_basic, test_line_number_after_error);
1443: tcase_add_test(tc_basic, test_column_number_after_error);
1444: tcase_add_test(tc_basic, test_really_long_lines);
1445: tcase_add_test(tc_basic, test_end_element_events);
1446: tcase_add_test(tc_basic, test_attr_whitespace_normalization);
1447: tcase_add_test(tc_basic, test_xmldecl_misplaced);
1448: tcase_add_test(tc_basic, test_unknown_encoding_internal_entity);
1449: tcase_add_test(tc_basic,
1450: test_wfc_undeclared_entity_unread_external_subset);
1451: tcase_add_test(tc_basic, test_wfc_undeclared_entity_no_external_subset);
1452: tcase_add_test(tc_basic, test_wfc_undeclared_entity_standalone);
1453: tcase_add_test(tc_basic, test_wfc_undeclared_entity_with_external_subset);
1454: tcase_add_test(tc_basic,
1455: test_wfc_undeclared_entity_with_external_subset_standalone);
1456: tcase_add_test(tc_basic, test_wfc_no_recursive_entity_refs);
1457: tcase_add_test(tc_basic, test_ext_entity_set_encoding);
1458: tcase_add_test(tc_basic, test_dtd_default_handling);
1459: tcase_add_test(tc_basic, test_empty_ns_without_namespaces);
1460: tcase_add_test(tc_basic, test_ns_in_attribute_default_without_namespaces);
1461: tcase_add_test(tc_basic, test_stop_parser_between_char_data_calls);
1462: tcase_add_test(tc_basic, test_suspend_parser_between_char_data_calls);
1463:
1464: suite_add_tcase(s, tc_namespace);
1465: tcase_add_checked_fixture(tc_namespace,
1466: namespace_setup, namespace_teardown);
1467: tcase_add_test(tc_namespace, test_return_ns_triplet);
1468: tcase_add_test(tc_namespace, test_ns_tagname_overwrite);
1469: tcase_add_test(tc_namespace, test_ns_tagname_overwrite_triplet);
1470: tcase_add_test(tc_namespace, test_start_ns_clears_start_element);
1471: tcase_add_test(tc_namespace, test_default_ns_from_ext_subset_and_ext_ge);
1472: tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_1);
1473: tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_2);
1474: tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_3);
1475: tcase_add_test(tc_namespace, test_ns_prefix_with_empty_uri_4);
1476: tcase_add_test(tc_namespace, test_ns_default_with_empty_uri);
1477: tcase_add_test(tc_namespace, test_ns_duplicate_attrs_diff_prefixes);
1478: tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_attribute);
1479: tcase_add_test(tc_namespace, test_ns_unbound_prefix_on_element);
1480:
1481: return s;
1482: }
1483:
1484:
1485: int
1486: main(int argc, char *argv[])
1487: {
1488: int i, nf;
1489: int verbosity = CK_NORMAL;
1490: Suite *s = make_suite();
1491: SRunner *sr = srunner_create(s);
1492:
1493: /* run the tests for internal helper functions */
1494: testhelper_is_whitespace_normalized();
1495:
1496: for (i = 1; i < argc; ++i) {
1497: char *opt = argv[i];
1498: if (strcmp(opt, "-v") == 0 || strcmp(opt, "--verbose") == 0)
1499: verbosity = CK_VERBOSE;
1500: else if (strcmp(opt, "-q") == 0 || strcmp(opt, "--quiet") == 0)
1501: verbosity = CK_SILENT;
1502: else {
1503: fprintf(stderr, "runtests: unknown option '%s'\n", opt);
1504: return 2;
1505: }
1506: }
1507: if (verbosity != CK_SILENT)
1508: printf("Expat version: %s\n", XML_ExpatVersion());
1509: srunner_run_all(sr, verbosity);
1510: nf = srunner_ntests_failed(sr);
1511: srunner_free(sr);
1512:
1513: return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
1514: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>