xml/xmlexpatparser/src/expat-1.95.5/tests/runtests.c
changeset 0 e35f40988205
equal deleted inserted replaced
-1:000000000000 0:e35f40988205
       
     1 /* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
       
     2    See the file COPYING for copying permission.
       
     3 */
       
     4 #include <assert.h>
       
     5 #include <check.h>
       
     6 #include <stdlib.h>
       
     7 #include <stdio.h>
       
     8 #include <string.h>
       
     9 
       
    10 #include "expat.h"
       
    11 #include "chardata.h"
       
    12 
       
    13 
       
    14 static XML_Parser parser;
       
    15 
       
    16 
       
    17 static void
       
    18 basic_setup(void)
       
    19 {
       
    20     parser = XML_ParserCreate(NULL);
       
    21     if (parser == NULL)
       
    22         fail("Parser not created.");
       
    23 }
       
    24 
       
    25 static void
       
    26 basic_teardown(void)
       
    27 {
       
    28     if (parser != NULL)
       
    29         XML_ParserFree(parser);
       
    30 }
       
    31 
       
    32 /* Generate a failure using the parser state to create an error message;
       
    33    this should be used when the parser reports an error we weren't
       
    34    expecting.
       
    35 */
       
    36 static void
       
    37 _xml_failure(XML_Parser parser, const char *file, int line)
       
    38 {
       
    39     char buffer[1024];
       
    40     sprintf(buffer,
       
    41             "\n    %s (line %d, offset %d)\n    reported from %s, line %d",
       
    42             XML_ErrorString(XML_GetErrorCode(parser)),
       
    43             XML_GetCurrentLineNumber(parser),
       
    44             XML_GetCurrentColumnNumber(parser),
       
    45             file, line);
       
    46     fail(buffer);
       
    47 }
       
    48 
       
    49 #define xml_failure(parser) _xml_failure((parser), __FILE__, __LINE__)
       
    50 
       
    51 static void
       
    52 _expect_failure(char *text, enum XML_Error errorCode, char *errorMessage,
       
    53                 char *file, int lineno)
       
    54 {
       
    55     if (XML_Parse(parser, text, strlen(text), 1) == XML_STATUS_OK)
       
    56         fail(errorMessage);
       
    57     if (XML_GetErrorCode(parser) != errorCode)
       
    58         _xml_failure(parser, file, lineno);
       
    59 }
       
    60 
       
    61 #define expect_failure(text, errorCode, errorMessage) \
       
    62         _expect_failure((text), (errorCode), (errorMessage), \
       
    63                         __FILE__, __LINE__)
       
    64 
       
    65 
       
    66 /*
       
    67  * Character & encoding tests.
       
    68  */
       
    69 
       
    70 START_TEST(test_nul_byte)
       
    71 {
       
    72     char text[] = "<doc>\0</doc>";
       
    73 
       
    74     /* test that a NUL byte (in US-ASCII data) is an error */
       
    75     if (XML_Parse(parser, text, sizeof(text) - 1, 1) == XML_STATUS_OK)
       
    76         fail("Parser did not report error on NUL-byte.");
       
    77     if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)
       
    78         xml_failure(parser);
       
    79 }
       
    80 END_TEST
       
    81 
       
    82 
       
    83 START_TEST(test_u0000_char)
       
    84 {
       
    85     /* test that a NUL byte (in US-ASCII data) is an error */
       
    86     expect_failure("<doc>&#0;</doc>",
       
    87                    XML_ERROR_BAD_CHAR_REF,
       
    88                    "Parser did not report error on NUL-byte.");
       
    89 }
       
    90 END_TEST
       
    91 
       
    92 START_TEST(test_bom_utf8)
       
    93 {
       
    94     /* This test is really just making sure we don't core on a UTF-8 BOM. */
       
    95     char *text = "\357\273\277<e/>";
       
    96 
       
    97     if (XML_Parse(parser, text, strlen(text), 1) == XML_STATUS_ERROR)
       
    98         xml_failure(parser);
       
    99 }
       
   100 END_TEST
       
   101 
       
   102 START_TEST(test_bom_utf16_be)
       
   103 {
       
   104     char text[] = "\376\377\0<\0e\0/\0>";
       
   105 
       
   106     if (XML_Parse(parser, text, sizeof(text) - 1, 1) == XML_STATUS_ERROR)
       
   107         xml_failure(parser);
       
   108 }
       
   109 END_TEST
       
   110 
       
   111 START_TEST(test_bom_utf16_le)
       
   112 {
       
   113     char text[] = "\377\376<\0e\0/\0>\0";
       
   114 
       
   115     if (XML_Parse(parser, text, sizeof(text) - 1, 1) == XML_STATUS_ERROR)
       
   116         xml_failure(parser);
       
   117 }
       
   118 END_TEST
       
   119 
       
   120 static void
       
   121 accumulate_characters(void *userData, const XML_Char *s, int len)
       
   122 {
       
   123     CharData_AppendXMLChars((CharData *)userData, s, len);
       
   124 }
       
   125 
       
   126 static void
       
   127 accumulate_attribute(void *userData, const XML_Char *name,
       
   128                      const XML_Char **atts)
       
   129 {
       
   130     CharData *storage = (CharData *)userData;
       
   131     if (storage->count < 0 && atts != NULL && atts[0] != NULL) {
       
   132         /* "accumulate" the value of the first attribute we see */
       
   133         CharData_AppendXMLChars(storage, atts[1], -1);
       
   134     }
       
   135 }
       
   136 
       
   137 
       
   138 static void
       
   139 run_character_check(XML_Char *text, XML_Char *expected)
       
   140 {
       
   141     CharData storage;
       
   142 
       
   143     CharData_Init(&storage);
       
   144     XML_SetUserData(parser, &storage);
       
   145     XML_SetCharacterDataHandler(parser, accumulate_characters);
       
   146     if (XML_Parse(parser, text, strlen(text), 1) == XML_STATUS_ERROR)
       
   147         xml_failure(parser);
       
   148     CharData_CheckXMLChars(&storage, expected);
       
   149 }
       
   150 
       
   151 static void
       
   152 run_attribute_check(XML_Char *text, XML_Char *expected)
       
   153 {
       
   154     CharData storage;
       
   155 
       
   156     CharData_Init(&storage);
       
   157     XML_SetUserData(parser, &storage);
       
   158     XML_SetStartElementHandler(parser, accumulate_attribute);
       
   159     if (XML_Parse(parser, text, strlen(text), 1) == XML_STATUS_ERROR)
       
   160         xml_failure(parser);
       
   161     CharData_CheckXMLChars(&storage, expected);
       
   162 }
       
   163 
       
   164 /* Regression test for SF bug #491986. */
       
   165 START_TEST(test_danish_latin1)
       
   166 {
       
   167     char *text =
       
   168         "<?xml version='1.0' encoding='iso-8859-1'?>\n"
       
   169         "<e>Jørgen æøåÆØÅ</e>";
       
   170     run_character_check(text,
       
   171              "J\xC3\xB8rgen \xC3\xA6\xC3\xB8\xC3\xA5\xC3\x86\xC3\x98\xC3\x85");
       
   172 }
       
   173 END_TEST
       
   174 
       
   175 
       
   176 /* Regression test for SF bug #514281. */
       
   177 START_TEST(test_french_charref_hexidecimal)
       
   178 {
       
   179     char *text =
       
   180         "<?xml version='1.0' encoding='iso-8859-1'?>\n"
       
   181         "<doc>&#xE9;&#xE8;&#xE0;&#xE7;&#xEA;&#xC8;</doc>";
       
   182     run_character_check(text,
       
   183                         "\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
       
   184 }
       
   185 END_TEST
       
   186 
       
   187 START_TEST(test_french_charref_decimal)
       
   188 {
       
   189     char *text =
       
   190         "<?xml version='1.0' encoding='iso-8859-1'?>\n"
       
   191         "<doc>&#233;&#232;&#224;&#231;&#234;&#200;</doc>";
       
   192     run_character_check(text,
       
   193                         "\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
       
   194 }
       
   195 END_TEST
       
   196 
       
   197 START_TEST(test_french_latin1)
       
   198 {
       
   199     char *text =
       
   200         "<?xml version='1.0' encoding='iso-8859-1'?>\n"
       
   201         "<doc>\xE9\xE8\xE0\xE7\xEa\xC8</doc>";
       
   202     run_character_check(text,
       
   203                         "\xC3\xA9\xC3\xA8\xC3\xA0\xC3\xA7\xC3\xAA\xC3\x88");
       
   204 }
       
   205 END_TEST
       
   206 
       
   207 START_TEST(test_french_utf8)
       
   208 {
       
   209     char *text =
       
   210         "<?xml version='1.0' encoding='utf-8'?>\n"
       
   211         "<doc>\xC3\xA9</doc>";
       
   212     run_character_check(text, "\xC3\xA9");
       
   213 }
       
   214 END_TEST
       
   215 
       
   216 /* Regression test for SF bug #600479.
       
   217    XXX There should be a test that exercises all legal XML Unicode
       
   218    characters as PCDATA and attribute value content, and XML Name
       
   219    characters as part of element and attribute names.
       
   220 */
       
   221 START_TEST(test_utf8_false_rejection)
       
   222 {
       
   223     char *text = "<doc>\xEF\xBA\xBF</doc>";
       
   224     run_character_check(text, "\xEF\xBA\xBF");
       
   225 }
       
   226 END_TEST
       
   227 
       
   228 /* Regression test for SF bug #477667.
       
   229    This test assures that any 8-bit character followed by a 7-bit
       
   230    character will not be mistakenly interpreted as a valid UTF-8
       
   231    sequence.
       
   232 */
       
   233 START_TEST(test_illegal_utf8)
       
   234 {
       
   235     char text[100];
       
   236     int i;
       
   237 
       
   238     for (i = 128; i <= 255; ++i) {
       
   239         sprintf(text, "<e>%ccd</e>", i);
       
   240         if (XML_Parse(parser, text, strlen(text), 1) == XML_STATUS_OK) {
       
   241             sprintf(text,
       
   242                     "expected token error for '%c' (ordinal %d) in UTF-8 text",
       
   243                     i, i);
       
   244             fail(text);
       
   245         }
       
   246         else if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)
       
   247             xml_failure(parser);
       
   248         /* Reset the parser since we use the same parser repeatedly. */
       
   249         XML_ParserReset(parser, NULL);
       
   250     }
       
   251 }
       
   252 END_TEST
       
   253 
       
   254 START_TEST(test_utf16)
       
   255 {
       
   256     /* <?xml version="1.0" encoding="UTF-16"?>
       
   257        <doc a='123'>some text</doc>
       
   258     */
       
   259     char text[] =
       
   260         "\000<\000?\000x\000m\000\154\000 \000v\000e\000r\000s\000i\000o"
       
   261         "\000n\000=\000'\0001\000.\000\060\000'\000 \000e\000n\000c\000o"
       
   262         "\000d\000i\000n\000g\000=\000'\000U\000T\000F\000-\0001\000\066"
       
   263         "\000'\000?\000>\000\n"
       
   264         "\000<\000d\000o\000c\000 \000a\000=\000'\0001\0002\0003\000'"
       
   265         "\000>\000s\000o\000m\000e\000 \000t\000e\000x\000t\000<\000/"
       
   266         "\000d\000o\000c\000>";
       
   267     if (XML_Parse(parser, text, sizeof(text) - 1, 1) == XML_STATUS_ERROR)
       
   268         xml_failure(parser);
       
   269 }
       
   270 END_TEST
       
   271 
       
   272 START_TEST(test_utf16_le_epilog_newline)
       
   273 {
       
   274     int first_chunk_bytes = 17;
       
   275     char text[] = 
       
   276         "\xFF\xFE"                      /* BOM */
       
   277         "<\000e\000/\000>\000"          /* document element */
       
   278         "\r\000\n\000\r\000\n\000";     /* epilog */
       
   279 
       
   280     if (first_chunk_bytes >= sizeof(text) - 1)
       
   281         fail("bad value of first_chunk_bytes");
       
   282     if (XML_Parse(parser, text, first_chunk_bytes, 0) == XML_STATUS_ERROR)
       
   283         xml_failure(parser);
       
   284     else {
       
   285         enum XML_Status rc;
       
   286         rc = XML_Parse(parser, text + first_chunk_bytes,
       
   287                        sizeof(text) - first_chunk_bytes - 1, 1);
       
   288         if (rc == XML_STATUS_ERROR)
       
   289             xml_failure(parser);
       
   290     }
       
   291 }
       
   292 END_TEST
       
   293 
       
   294 /* Regression test for SF bug #481609. */
       
   295 START_TEST(test_latin1_umlauts)
       
   296 {
       
   297     char *text =
       
   298         "<?xml version='1.0' encoding='iso-8859-1'?>\n"
       
   299         "<e a='ä ö ü &#228; &#246; &#252; &#x00E4; &#x0F6; &#xFC;'\n"
       
   300         "  >ä ö ü &#228; &#246; &#252; &#x00E4; &#x0F6; &#xFC;</e>";
       
   301     char *utf8 =
       
   302         "\xC3\xA4 \xC3\xB6 \xC3\xBC "
       
   303         "\xC3\xA4 \xC3\xB6 \xC3\xBC "
       
   304         "\xC3\xA4 \xC3\xB6 \xC3\xBC";
       
   305     run_character_check(text, utf8);
       
   306     XML_ParserReset(parser, NULL);
       
   307     run_attribute_check(text, utf8);
       
   308 }
       
   309 END_TEST
       
   310 
       
   311 /* Regression test for SF bug #422239 (maybe).
       
   312    It's not clear that this reproduces enough of the context
       
   313    of the reported bug.
       
   314 */
       
   315 START_TEST(test_line_count)
       
   316 {
       
   317     char *text =
       
   318         "<e>\n"
       
   319         "  <e/>\n"
       
   320         "</e>";
       
   321     int lineno;
       
   322     if (XML_Parse(parser, text, strlen(text), 1) == XML_STATUS_ERROR)
       
   323         xml_failure(parser);
       
   324     lineno = XML_GetCurrentLineNumber(parser);
       
   325     if (lineno != 3) {
       
   326         char buffer[100];
       
   327         sprintf(buffer, "expected 3 lines, saw %d", lineno);
       
   328         fail(buffer);
       
   329     }
       
   330 }
       
   331 END_TEST
       
   332 
       
   333 /* Regression test for SF bug #478332. */
       
   334 START_TEST(test_really_long_lines)
       
   335 {
       
   336     /* This parses an input line longer than INIT_DATA_BUF_SIZE
       
   337        characters long (defined to be 1024 in xmlparse.c).  We take a
       
   338        really cheesy approach to building the input buffer, because
       
   339        this avoids writing bugs in buffer-filling code.
       
   340     */
       
   341     char *text =
       
   342         "<e>"
       
   343         /* 64 chars */
       
   344         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
       
   345         /* until we have at least 1024 characters on the line: */
       
   346         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
       
   347         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
       
   348         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
       
   349         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
       
   350         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
       
   351         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
       
   352         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
       
   353         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
       
   354         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
       
   355         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
       
   356         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
       
   357         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
       
   358         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
       
   359         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
       
   360         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
       
   361         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-+"
       
   362         "</e>";
       
   363     if (XML_Parse(parser, text, strlen(text), 1) == XML_STATUS_ERROR)
       
   364         xml_failure(parser);
       
   365 }
       
   366 END_TEST
       
   367 
       
   368 
       
   369 /*
       
   370  * Element event tests.
       
   371  */
       
   372 
       
   373 static void
       
   374 end_element_event_handler(void *userData, const XML_Char *name)
       
   375 {
       
   376     CharData *storage = (CharData *) userData;
       
   377     CharData_AppendString(storage, "/");
       
   378     CharData_AppendXMLChars(storage, name, -1);
       
   379 }
       
   380 
       
   381 START_TEST(test_end_element_events)
       
   382 {
       
   383     char *text = "<a><b><c/></b><d><f/></d></a>";
       
   384     char *expected = "/c/b/f/d/a";
       
   385     CharData storage;
       
   386 
       
   387     CharData_Init(&storage);
       
   388     XML_SetUserData(parser, &storage);
       
   389     XML_SetEndElementHandler(parser, end_element_event_handler);
       
   390     if (XML_Parse(parser, text, strlen(text), 1) == XML_STATUS_ERROR)
       
   391         xml_failure(parser);
       
   392     CharData_CheckString(&storage, expected);
       
   393 }
       
   394 END_TEST
       
   395 
       
   396 
       
   397 /*
       
   398  * Attribute tests.
       
   399  */
       
   400 
       
   401 /* Helpers used by the following test; this checks any "attr" and "refs"
       
   402    attributes to make sure whitespace has been normalized.
       
   403 
       
   404    Return true if whitespace has been normalized in a string, using
       
   405    the rules for attribute value normalization.  The 'is_cdata' flag
       
   406    is needed since CDATA attributes don't need to have multiple
       
   407    whitespace characters collapsed to a single space, while other
       
   408    attribute data types do.  (Section 3.3.3 of the recommendation.)
       
   409 */
       
   410 static int
       
   411 is_whitespace_normalized(const XML_Char *s, int is_cdata)
       
   412 {
       
   413     int blanks = 0;
       
   414     int at_start = 1;
       
   415     while (*s) {
       
   416         if (*s == ' ')
       
   417             ++blanks;
       
   418         else if (*s == '\t' || *s == '\n' || *s == '\r')
       
   419             return 0;
       
   420         else {
       
   421             if (at_start) {
       
   422                 at_start = 0;
       
   423                 if (blanks && !is_cdata)
       
   424                     /* illegal leading blanks */
       
   425                     return 0;
       
   426             }
       
   427             else if (blanks > 1 && !is_cdata)
       
   428                 return 0;
       
   429             blanks = 0;
       
   430         }
       
   431         ++s;
       
   432     }
       
   433     if (blanks && !is_cdata)
       
   434         return 0;
       
   435     return 1;
       
   436 }
       
   437 
       
   438 /* Check the attribute whitespace checker: */
       
   439 static void
       
   440 testhelper_is_whitespace_normalized(void)
       
   441 {
       
   442     assert(is_whitespace_normalized("abc", 0));
       
   443     assert(is_whitespace_normalized("abc", 1));
       
   444     assert(is_whitespace_normalized("abc def ghi", 0));
       
   445     assert(is_whitespace_normalized("abc def ghi", 1));
       
   446     assert(!is_whitespace_normalized(" abc def ghi", 0));
       
   447     assert(is_whitespace_normalized(" abc def ghi", 1));
       
   448     assert(!is_whitespace_normalized("abc  def ghi", 0));
       
   449     assert(is_whitespace_normalized("abc  def ghi", 1));
       
   450     assert(!is_whitespace_normalized("abc def ghi ", 0));
       
   451     assert(is_whitespace_normalized("abc def ghi ", 1));
       
   452     assert(!is_whitespace_normalized(" ", 0));
       
   453     assert(is_whitespace_normalized(" ", 1));
       
   454     assert(!is_whitespace_normalized("\t", 0));
       
   455     assert(!is_whitespace_normalized("\t", 1));
       
   456     assert(!is_whitespace_normalized("\n", 0));
       
   457     assert(!is_whitespace_normalized("\n", 1));
       
   458     assert(!is_whitespace_normalized("\r", 0));
       
   459     assert(!is_whitespace_normalized("\r", 1));
       
   460     assert(!is_whitespace_normalized("abc\t def", 1));
       
   461 }
       
   462 
       
   463 static void
       
   464 check_attr_contains_normalized_whitespace(void *userData,
       
   465                                           const XML_Char *name,
       
   466                                           const XML_Char **atts)
       
   467 {
       
   468     int i;
       
   469     for (i = 0; atts[i] != NULL; i += 2) {
       
   470         const XML_Char *attrname = atts[i];
       
   471         const XML_Char *value = atts[i + 1];
       
   472         if (strcmp("attr", attrname) == 0
       
   473             || strcmp("ents", attrname) == 0
       
   474             || strcmp("refs", attrname) == 0) {
       
   475             if (!is_whitespace_normalized(value, 0)) {
       
   476                 char buffer[256];
       
   477                 sprintf(buffer, "attribute value not normalized: %s='%s'",
       
   478                         attrname, value);
       
   479                 fail(buffer);
       
   480             }
       
   481         }
       
   482     }
       
   483 }
       
   484 
       
   485 START_TEST(test_attr_whitespace_normalization)
       
   486 {
       
   487     char *text =
       
   488         "<!DOCTYPE doc [\n"
       
   489         "  <!ATTLIST doc\n"
       
   490         "            attr NMTOKENS #REQUIRED\n"
       
   491         "            ents ENTITIES #REQUIRED\n"
       
   492         "            refs IDREFS   #REQUIRED>\n"
       
   493         "]>\n"
       
   494         "<doc attr='    a  b c\t\td\te\t' refs=' id-1   \t  id-2\t\t'  \n"
       
   495         "     ents=' ent-1   \t\r\n"
       
   496         "            ent-2  ' >\n"
       
   497         "  <e id='id-1'/>\n"
       
   498         "  <e id='id-2'/>\n"
       
   499         "</doc>";
       
   500 
       
   501     XML_SetStartElementHandler(parser,
       
   502                                check_attr_contains_normalized_whitespace);
       
   503     if (XML_Parse(parser, text, strlen(text), 1) == XML_STATUS_ERROR)
       
   504         xml_failure(parser);
       
   505 }
       
   506 END_TEST
       
   507 
       
   508 
       
   509 /*
       
   510  * XML declaration tests.
       
   511  */
       
   512 
       
   513 START_TEST(test_xmldecl_misplaced)
       
   514 {
       
   515     expect_failure("\n"
       
   516                    "<?xml version='1.0'?>\n"
       
   517                    "<a/>",
       
   518                    XML_ERROR_MISPLACED_XML_PI,
       
   519                    "failed to report misplaced XML declaration");
       
   520 }
       
   521 END_TEST
       
   522 
       
   523 /* Regression test for SF bug #584832. */
       
   524 static int
       
   525 UnknownEncodingHandler(void *data,const XML_Char *encoding,XML_Encoding *info)
       
   526 {
       
   527     if (strcmp(encoding,"unsupported-encoding") == 0) {
       
   528         int i;
       
   529         for (i = 0; i < 256; ++i)
       
   530             info->map[i] = i;
       
   531         info->data=NULL;
       
   532         info->convert=NULL;
       
   533         info->release=NULL;
       
   534         return 1;
       
   535     }
       
   536     return 0;
       
   537 }
       
   538 
       
   539 START_TEST(test_unknown_encoding_internal_entity)
       
   540 {
       
   541     char *text =
       
   542         "<?xml version='1.0' encoding='unsupported-encoding'?>\n"
       
   543         "<!DOCTYPE test [<!ENTITY foo 'bar'>]>\n"
       
   544         "<test a='&foo;'/>";
       
   545 
       
   546     XML_SetUnknownEncodingHandler(parser, UnknownEncodingHandler, NULL);
       
   547     if (XML_Parse(parser, text, strlen(text), 1) == XML_STATUS_ERROR)
       
   548         xml_failure(parser);
       
   549 }
       
   550 END_TEST
       
   551 
       
   552 /* Test that no error is reported for unknown entities if we don't
       
   553    read an external subset.  This was fixed in Expat 1.95.5.
       
   554 */
       
   555 START_TEST(test_wfc_undeclared_entity_unread_external_subset) {
       
   556     char *text =
       
   557         "<!DOCTYPE doc SYSTEM 'foo'>\n"
       
   558         "<doc>&entity;</doc>";
       
   559 
       
   560     if (XML_Parse(parser, text, strlen(text), 1) == XML_STATUS_ERROR)
       
   561         xml_failure(parser);
       
   562 }
       
   563 END_TEST
       
   564 
       
   565 /* Test that an error is reported for unknown entities if we don't
       
   566    have an external subset.
       
   567 */
       
   568 START_TEST(test_wfc_undeclared_entity_no_external_subset) {
       
   569     expect_failure("<doc>&entity;</doc>",
       
   570                    XML_ERROR_UNDEFINED_ENTITY,
       
   571                    "Parser did not report undefined entity w/out a DTD.");
       
   572 }
       
   573 END_TEST
       
   574 
       
   575 /* Test that an error is reported for unknown entities if we don't
       
   576    read an external subset, but have been declared standalone.
       
   577 */
       
   578 START_TEST(test_wfc_undeclared_entity_standalone) {
       
   579     char *text =
       
   580         "<?xml version='1.0' encoding='us-ascii' standalone='yes'?>\n"
       
   581         "<!DOCTYPE doc SYSTEM 'foo'>\n"
       
   582         "<doc>&entity;</doc>";
       
   583 
       
   584     expect_failure(text,
       
   585                    XML_ERROR_UNDEFINED_ENTITY,
       
   586                    "Parser did not report undefined entity (standalone).");
       
   587 }
       
   588 END_TEST
       
   589 
       
   590 static int
       
   591 external_entity_loader(XML_Parser parser,
       
   592                        const XML_Char *context,
       
   593                        const XML_Char *base,
       
   594                        const XML_Char *systemId,
       
   595                        const XML_Char *publicId)
       
   596 {
       
   597     char *text = (char *)XML_GetUserData(parser);
       
   598     XML_Parser extparser;
       
   599 
       
   600     extparser = XML_ExternalEntityParserCreate(parser, context, NULL);
       
   601     if (extparser == NULL)
       
   602         fail("Could not create external entity parser.");
       
   603     if (XML_Parse(extparser, text, strlen(text), 1) == XML_STATUS_ERROR) {
       
   604         xml_failure(parser);
       
   605         return 0;
       
   606     }
       
   607     return 1;
       
   608 }
       
   609 
       
   610 /* Test that an error is reported for unknown entities if we have read
       
   611    an external subset.
       
   612 */
       
   613 START_TEST(test_wfc_undeclared_entity_with_external_subset) {
       
   614     char *text =
       
   615         "<?xml version='1.0' encoding='us-ascii'?>\n"
       
   616         "<!DOCTYPE doc SYSTEM 'foo'>\n"
       
   617         "<doc>&entity;</doc>";
       
   618     char *foo_text =
       
   619         "<!ELEMENT doc (#PCDATA)*>";
       
   620 
       
   621     XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
       
   622     XML_SetUserData(parser, foo_text);
       
   623     XML_SetExternalEntityRefHandler(parser, external_entity_loader);
       
   624     expect_failure(text,
       
   625                    XML_ERROR_UNDEFINED_ENTITY,
       
   626                    "Parser did not report undefined entity with DTD.");
       
   627 }
       
   628 END_TEST
       
   629 
       
   630 START_TEST(test_wfc_no_recursive_entity_refs)
       
   631 {
       
   632     char *text =
       
   633         "<!DOCTYPE doc [\n"
       
   634         "  <!ENTITY entity '&#38;entity;'>\n"
       
   635         "]>\n"
       
   636         "<doc>&entity;</doc>";
       
   637 
       
   638     expect_failure(text,
       
   639                    XML_ERROR_RECURSIVE_ENTITY_REF,
       
   640                    "Parser did not report recursive entity reference.");
       
   641 }
       
   642 END_TEST
       
   643 
       
   644 
       
   645 /*
       
   646  * Namespaces tests.
       
   647  */
       
   648 
       
   649 static void
       
   650 namespace_setup(void)
       
   651 {
       
   652     parser = XML_ParserCreateNS(NULL, ' ');
       
   653     if (parser == NULL)
       
   654         fail("Parser not created.");
       
   655 }
       
   656 
       
   657 static void
       
   658 namespace_teardown(void)
       
   659 {
       
   660     basic_teardown();
       
   661 }
       
   662 
       
   663 /* Check that an element name and attribute name match the expected values.
       
   664    The expected values are passed as an array reference of string pointers
       
   665    provided as the userData argument; the first is the expected
       
   666    element name, and the second is the expected attribute name.
       
   667 */
       
   668 static void
       
   669 triplet_start_checker(void *userData, const XML_Char *name,
       
   670                       const XML_Char **atts)
       
   671 {
       
   672     char **elemstr = (char **)userData;
       
   673     char buffer[1024];
       
   674     if (strcmp(elemstr[0], name) != 0) {
       
   675         sprintf(buffer, "unexpected start string: '%s'", name);
       
   676         fail(buffer);
       
   677     }
       
   678     if (strcmp(elemstr[1], atts[0]) != 0) {
       
   679         sprintf(buffer, "unexpected attribute string: '%s'", atts[0]);
       
   680         fail(buffer);
       
   681     }
       
   682 }
       
   683 
       
   684 /* Check that the element name passed to the end-element handler matches
       
   685    the expected value.  The expected value is passed as the first element
       
   686    in an array of strings passed as the userData argument.
       
   687 */
       
   688 static void
       
   689 triplet_end_checker(void *userData, const XML_Char *name)
       
   690 {
       
   691     char **elemstr = (char **)userData;
       
   692     if (strcmp(elemstr[0], name) != 0) {
       
   693         char buffer[1024];
       
   694         sprintf(buffer, "unexpected end string: '%s'", name);
       
   695         fail(buffer);
       
   696     }
       
   697 }
       
   698 
       
   699 START_TEST(test_return_ns_triplet)
       
   700 {
       
   701     char *text =
       
   702         "<foo:e xmlns:foo='http://expat.sf.net/' bar:a='12'\n"
       
   703         "       xmlns:bar='http://expat.sf.net/'></foo:e>";
       
   704     char *elemstr[] = {
       
   705         "http://expat.sf.net/ e foo",
       
   706         "http://expat.sf.net/ a bar"
       
   707     };
       
   708     XML_SetReturnNSTriplet(parser, 1);
       
   709     XML_SetUserData(parser, elemstr);
       
   710     XML_SetElementHandler(parser, triplet_start_checker, triplet_end_checker);
       
   711     if (XML_Parse(parser, text, strlen(text), 1) == XML_STATUS_ERROR)
       
   712         xml_failure(parser);
       
   713 }
       
   714 END_TEST
       
   715 
       
   716 static void
       
   717 overwrite_start_checker(void *userData, const XML_Char *name,
       
   718                         const XML_Char **atts)
       
   719 {
       
   720     CharData *storage = (CharData *) userData;
       
   721     CharData_AppendString(storage, "start ");
       
   722     CharData_AppendXMLChars(storage, name, -1);
       
   723     while (*atts != NULL) {
       
   724         CharData_AppendString(storage, "\nattribute ");
       
   725         CharData_AppendXMLChars(storage, *atts, -1);
       
   726         atts += 2;
       
   727     }
       
   728     CharData_AppendString(storage, "\n");
       
   729 }
       
   730 
       
   731 static void
       
   732 overwrite_end_checker(void *userData, const XML_Char *name)
       
   733 {
       
   734     CharData *storage = (CharData *) userData;
       
   735     CharData_AppendString(storage, "end ");
       
   736     CharData_AppendXMLChars(storage, name, -1);
       
   737     CharData_AppendString(storage, "\n");
       
   738 }
       
   739 
       
   740 static void
       
   741 run_ns_tagname_overwrite_test(char *text, char *result)
       
   742 {
       
   743     CharData storage;
       
   744     CharData_Init(&storage);
       
   745     XML_SetUserData(parser, &storage);
       
   746     XML_SetElementHandler(parser,
       
   747                           overwrite_start_checker, overwrite_end_checker);
       
   748     if (XML_Parse(parser, text, strlen(text), 1) == XML_STATUS_ERROR)
       
   749         xml_failure(parser);
       
   750     CharData_CheckString(&storage, result);
       
   751 }
       
   752 
       
   753 /* Regression test for SF bug #566334. */
       
   754 START_TEST(test_ns_tagname_overwrite)
       
   755 {
       
   756     char *text =
       
   757         "<n:e xmlns:n='http://xml.libexpat.org/'>\n"
       
   758         "  <n:f n:attr='foo'/>\n"
       
   759         "  <n:g n:attr2='bar'/>\n"
       
   760         "</n:e>";
       
   761     char *result =
       
   762         "start http://xml.libexpat.org/ e\n"
       
   763         "start http://xml.libexpat.org/ f\n"
       
   764         "attribute http://xml.libexpat.org/ attr\n"
       
   765         "end http://xml.libexpat.org/ f\n"
       
   766         "start http://xml.libexpat.org/ g\n"
       
   767         "attribute http://xml.libexpat.org/ attr2\n"
       
   768         "end http://xml.libexpat.org/ g\n"
       
   769         "end http://xml.libexpat.org/ e\n";
       
   770     run_ns_tagname_overwrite_test(text, result);
       
   771 }
       
   772 END_TEST
       
   773 
       
   774 /* Regression test for SF bug #566334. */
       
   775 START_TEST(test_ns_tagname_overwrite_triplet)
       
   776 {
       
   777     char *text =
       
   778         "<n:e xmlns:n='http://xml.libexpat.org/'>\n"
       
   779         "  <n:f n:attr='foo'/>\n"
       
   780         "  <n:g n:attr2='bar'/>\n"
       
   781         "</n:e>";
       
   782     char *result =
       
   783         "start http://xml.libexpat.org/ e n\n"
       
   784         "start http://xml.libexpat.org/ f n\n"
       
   785         "attribute http://xml.libexpat.org/ attr n\n"
       
   786         "end http://xml.libexpat.org/ f n\n"
       
   787         "start http://xml.libexpat.org/ g n\n"
       
   788         "attribute http://xml.libexpat.org/ attr2 n\n"
       
   789         "end http://xml.libexpat.org/ g n\n"
       
   790         "end http://xml.libexpat.org/ e n\n";
       
   791     XML_SetReturnNSTriplet(parser, 1);
       
   792     run_ns_tagname_overwrite_test(text, result);
       
   793 }
       
   794 END_TEST
       
   795 
       
   796 static Suite *
       
   797 make_basic_suite(void)
       
   798 {
       
   799     Suite *s = suite_create("basic");
       
   800     TCase *tc_basic = tcase_create("basic tests");
       
   801     TCase *tc_namespace = tcase_create("XML namespaces");
       
   802 
       
   803     suite_add_tcase(s, tc_basic);
       
   804     tcase_add_checked_fixture(tc_basic, basic_setup, basic_teardown);
       
   805     tcase_add_test(tc_basic, test_nul_byte);
       
   806     tcase_add_test(tc_basic, test_u0000_char);
       
   807     tcase_add_test(tc_basic, test_bom_utf8);
       
   808     tcase_add_test(tc_basic, test_bom_utf16_be);
       
   809     tcase_add_test(tc_basic, test_bom_utf16_le);
       
   810     tcase_add_test(tc_basic, test_illegal_utf8);
       
   811     tcase_add_test(tc_basic, test_utf16);
       
   812     tcase_add_test(tc_basic, test_utf16_le_epilog_newline);
       
   813     tcase_add_test(tc_basic, test_latin1_umlauts);
       
   814     /* Regression test for SF bug #491986. */
       
   815     tcase_add_test(tc_basic, test_danish_latin1);
       
   816     /* Regression test for SF bug #514281. */
       
   817     tcase_add_test(tc_basic, test_french_charref_hexidecimal);
       
   818     tcase_add_test(tc_basic, test_french_charref_decimal);
       
   819     tcase_add_test(tc_basic, test_french_latin1);
       
   820     tcase_add_test(tc_basic, test_french_utf8);
       
   821     tcase_add_test(tc_basic, test_utf8_false_rejection);
       
   822     tcase_add_test(tc_basic, test_line_count);
       
   823     tcase_add_test(tc_basic, test_really_long_lines);
       
   824     tcase_add_test(tc_basic, test_end_element_events);
       
   825     tcase_add_test(tc_basic, test_attr_whitespace_normalization);
       
   826     tcase_add_test(tc_basic, test_xmldecl_misplaced);
       
   827     tcase_add_test(tc_basic, test_unknown_encoding_internal_entity);
       
   828     tcase_add_test(tc_basic,
       
   829                    test_wfc_undeclared_entity_unread_external_subset);
       
   830     tcase_add_test(tc_basic, test_wfc_undeclared_entity_no_external_subset);
       
   831     tcase_add_test(tc_basic, test_wfc_undeclared_entity_standalone);
       
   832     tcase_add_test(tc_basic, test_wfc_undeclared_entity_with_external_subset);
       
   833     tcase_add_test(tc_basic, test_wfc_no_recursive_entity_refs);
       
   834 
       
   835     suite_add_tcase(s, tc_namespace);
       
   836     tcase_add_checked_fixture(tc_namespace,
       
   837                               namespace_setup, namespace_teardown);
       
   838     tcase_add_test(tc_namespace, test_return_ns_triplet);
       
   839     tcase_add_test(tc_namespace, test_ns_tagname_overwrite);
       
   840     tcase_add_test(tc_namespace, test_ns_tagname_overwrite_triplet);
       
   841 
       
   842     return s;
       
   843 }
       
   844 
       
   845 
       
   846 int
       
   847 main(int argc, char *argv[])
       
   848 {
       
   849     int i, nf;
       
   850     int forking = 0, forking_set = 0;
       
   851     int verbosity = CK_NORMAL;
       
   852     Suite *s = make_basic_suite();
       
   853     SRunner *sr = srunner_create(s);
       
   854 
       
   855     /* run the tests for internal helper functions */
       
   856     testhelper_is_whitespace_normalized();
       
   857 
       
   858     for (i = 1; i < argc; ++i) {
       
   859         char *opt = argv[i];
       
   860         if (strcmp(opt, "-v") == 0 || strcmp(opt, "--verbose") == 0)
       
   861             verbosity = CK_VERBOSE;
       
   862         else if (strcmp(opt, "-q") == 0 || strcmp(opt, "--quiet") == 0)
       
   863             verbosity = CK_SILENT;
       
   864         else if (strcmp(opt, "-f") == 0 || strcmp(opt, "--fork") == 0) {
       
   865             forking = 1;
       
   866             forking_set = 1;
       
   867         }
       
   868         else if (strcmp(opt, "-n") == 0 || strcmp(opt, "--no-fork") == 0) {
       
   869             forking = 0;
       
   870             forking_set = 1;
       
   871         }
       
   872         else {
       
   873             fprintf(stderr, "runtests: unknown option '%s'\n", opt);
       
   874             return 2;
       
   875         }
       
   876     }
       
   877     if (forking_set)
       
   878         srunner_set_fork_status(sr, forking ? CK_FORK : CK_NOFORK);
       
   879     srunner_run_all(sr, verbosity);
       
   880     nf = srunner_ntests_failed(sr);
       
   881     srunner_free(sr);
       
   882     suite_free(s);
       
   883 
       
   884     return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
       
   885 }