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