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