core/expat-2.0.1/tests/runtests.c
changeset 300 b6d834208d33
parent 296 ea3dbc023c80
equal deleted inserted replaced
299:f06c5eba524d 300:b6d834208d33
       
     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>&#0;</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>&#xE9;&#xE8;&#xE0;&#xE7;&#xEA;&#xC8;</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>&#233;&#232;&#224;&#231;&#234;&#200;</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 &#228; &#246; &#252; &#x00E4; &#x0F6; &#xFC; >'\n"
       
   394         "  >\xE4 \xF6 \xFC &#228; &#246; &#252; &#x00E4; &#x0F6; &#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 '&#38;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 }