Annotation of embedaddon/expat/tests/runtests.c, revision 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>