Annotation of embedaddon/expat/tests/runtests.c, revision 1.1.1.2

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>