mirror of
https://github.com/libexpat/libexpat.git
synced 2025-04-06 13:45:00 +00:00
tests: Make test_default_current insensitive to callback chunking
Instead of testing the exact number and sequence of callbacks, we now test that we get the exact data lengths and sequence of callbacks. The checks become much more verbose, but will now accept any buffer fill strategy -- single bytes, multiple bytes, or any combination thereof.
This commit is contained in:
parent
a4a4552313
commit
7474fe3d3f
3 changed files with 236 additions and 71 deletions
|
@ -1837,84 +1837,208 @@ START_TEST(test_default_current) {
|
|||
"<!ENTITY entity '%'>\n"
|
||||
"]>\n"
|
||||
"<doc>&entity;</doc>";
|
||||
CharData storage;
|
||||
|
||||
set_subtest("with defaulting");
|
||||
XML_SetDefaultHandler(g_parser, record_default_handler);
|
||||
XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
|
||||
CharData_Init(&storage);
|
||||
XML_SetUserData(g_parser, &storage);
|
||||
if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
|
||||
== XML_STATUS_ERROR)
|
||||
xml_failure(g_parser);
|
||||
CharData_CheckXMLChars(&storage, XCS("DCDCDCDCDCDD"));
|
||||
{
|
||||
struct handler_record_list storage;
|
||||
storage.count = 0;
|
||||
XML_SetDefaultHandler(g_parser, record_default_handler);
|
||||
XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
|
||||
XML_SetUserData(g_parser, &storage);
|
||||
if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
|
||||
== XML_STATUS_ERROR)
|
||||
xml_failure(g_parser);
|
||||
int i = 0;
|
||||
assert_record_handler_called(&storage, i++, "record_default_handler", 5);
|
||||
// we should have gotten one or more cdata callbacks, totaling 5 chars
|
||||
int cdata_len_remaining = 5;
|
||||
while (cdata_len_remaining > 0) {
|
||||
const struct handler_record_entry *c_entry
|
||||
= handler_record_get(&storage, i++);
|
||||
fail_unless(strcmp(c_entry->name, "record_cdata_handler") == 0);
|
||||
fail_unless(c_entry->arg > 0);
|
||||
fail_unless(c_entry->arg <= cdata_len_remaining);
|
||||
cdata_len_remaining -= c_entry->arg;
|
||||
// default handler must follow, with the exact same len argument.
|
||||
assert_record_handler_called(&storage, i++, "record_default_handler",
|
||||
c_entry->arg);
|
||||
}
|
||||
assert_record_handler_called(&storage, i++, "record_default_handler", 6);
|
||||
fail_unless(storage.count == i);
|
||||
}
|
||||
|
||||
/* Again, without the defaulting */
|
||||
set_subtest("no defaulting");
|
||||
XML_ParserReset(g_parser, NULL);
|
||||
XML_SetDefaultHandler(g_parser, record_default_handler);
|
||||
XML_SetCharacterDataHandler(g_parser, record_cdata_nodefault_handler);
|
||||
CharData_Init(&storage);
|
||||
XML_SetUserData(g_parser, &storage);
|
||||
if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
|
||||
== XML_STATUS_ERROR)
|
||||
xml_failure(g_parser);
|
||||
CharData_CheckXMLChars(&storage, XCS("DcccccD"));
|
||||
{
|
||||
struct handler_record_list storage;
|
||||
storage.count = 0;
|
||||
XML_ParserReset(g_parser, NULL);
|
||||
XML_SetDefaultHandler(g_parser, record_default_handler);
|
||||
XML_SetCharacterDataHandler(g_parser, record_cdata_nodefault_handler);
|
||||
XML_SetUserData(g_parser, &storage);
|
||||
if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
|
||||
== XML_STATUS_ERROR)
|
||||
xml_failure(g_parser);
|
||||
int i = 0;
|
||||
assert_record_handler_called(&storage, i++, "record_default_handler", 5);
|
||||
// we should have gotten one or more cdata callbacks, totaling 5 chars
|
||||
int cdata_len_remaining = 5;
|
||||
while (cdata_len_remaining > 0) {
|
||||
const struct handler_record_entry *c_entry
|
||||
= handler_record_get(&storage, i++);
|
||||
fail_unless(strcmp(c_entry->name, "record_cdata_nodefault_handler") == 0);
|
||||
fail_unless(c_entry->arg > 0);
|
||||
fail_unless(c_entry->arg <= cdata_len_remaining);
|
||||
cdata_len_remaining -= c_entry->arg;
|
||||
}
|
||||
assert_record_handler_called(&storage, i++, "record_default_handler", 6);
|
||||
fail_unless(storage.count == i);
|
||||
}
|
||||
|
||||
/* Now with an internal entity to complicate matters */
|
||||
set_subtest("with internal entity");
|
||||
XML_ParserReset(g_parser, NULL);
|
||||
XML_SetDefaultHandler(g_parser, record_default_handler);
|
||||
XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
|
||||
CharData_Init(&storage);
|
||||
XML_SetUserData(g_parser, &storage);
|
||||
if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
|
||||
XML_TRUE)
|
||||
== XML_STATUS_ERROR)
|
||||
xml_failure(g_parser);
|
||||
/* The default handler suppresses the entity */
|
||||
CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDDD"));
|
||||
{
|
||||
struct handler_record_list storage;
|
||||
storage.count = 0;
|
||||
XML_ParserReset(g_parser, NULL);
|
||||
XML_SetDefaultHandler(g_parser, record_default_handler);
|
||||
XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
|
||||
XML_SetUserData(g_parser, &storage);
|
||||
if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
|
||||
XML_TRUE)
|
||||
== XML_STATUS_ERROR)
|
||||
xml_failure(g_parser);
|
||||
/* The default handler suppresses the entity */
|
||||
assert_record_handler_called(&storage, 0, "record_default_handler", 9);
|
||||
assert_record_handler_called(&storage, 1, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 2, "record_default_handler", 3);
|
||||
assert_record_handler_called(&storage, 3, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 4, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 5, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 6, "record_default_handler", 8);
|
||||
assert_record_handler_called(&storage, 7, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 8, "record_default_handler", 6);
|
||||
assert_record_handler_called(&storage, 9, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 10, "record_default_handler", 7);
|
||||
assert_record_handler_called(&storage, 11, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 12, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 13, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 14, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 15, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 16, "record_default_handler", 5);
|
||||
assert_record_handler_called(&storage, 17, "record_default_handler", 8);
|
||||
assert_record_handler_called(&storage, 18, "record_default_handler", 6);
|
||||
fail_unless(storage.count == 19);
|
||||
}
|
||||
|
||||
/* Again, with a skip handler */
|
||||
set_subtest("with skip handler");
|
||||
XML_ParserReset(g_parser, NULL);
|
||||
XML_SetDefaultHandler(g_parser, record_default_handler);
|
||||
XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
|
||||
XML_SetSkippedEntityHandler(g_parser, record_skip_handler);
|
||||
CharData_Init(&storage);
|
||||
XML_SetUserData(g_parser, &storage);
|
||||
if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
|
||||
XML_TRUE)
|
||||
== XML_STATUS_ERROR)
|
||||
xml_failure(g_parser);
|
||||
/* The default handler suppresses the entity */
|
||||
CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDeD"));
|
||||
{
|
||||
struct handler_record_list storage;
|
||||
storage.count = 0;
|
||||
XML_ParserReset(g_parser, NULL);
|
||||
XML_SetDefaultHandler(g_parser, record_default_handler);
|
||||
XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
|
||||
XML_SetSkippedEntityHandler(g_parser, record_skip_handler);
|
||||
XML_SetUserData(g_parser, &storage);
|
||||
if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
|
||||
XML_TRUE)
|
||||
== XML_STATUS_ERROR)
|
||||
xml_failure(g_parser);
|
||||
/* The default handler suppresses the entity */
|
||||
assert_record_handler_called(&storage, 0, "record_default_handler", 9);
|
||||
assert_record_handler_called(&storage, 1, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 2, "record_default_handler", 3);
|
||||
assert_record_handler_called(&storage, 3, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 4, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 5, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 6, "record_default_handler", 8);
|
||||
assert_record_handler_called(&storage, 7, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 8, "record_default_handler", 6);
|
||||
assert_record_handler_called(&storage, 9, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 10, "record_default_handler", 7);
|
||||
assert_record_handler_called(&storage, 11, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 12, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 13, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 14, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 15, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 16, "record_default_handler", 5);
|
||||
assert_record_handler_called(&storage, 17, "record_skip_handler", 0);
|
||||
assert_record_handler_called(&storage, 18, "record_default_handler", 6);
|
||||
fail_unless(storage.count == 19);
|
||||
}
|
||||
|
||||
/* This time, allow the entity through */
|
||||
set_subtest("allow entity");
|
||||
XML_ParserReset(g_parser, NULL);
|
||||
XML_SetDefaultHandlerExpand(g_parser, record_default_handler);
|
||||
XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
|
||||
CharData_Init(&storage);
|
||||
XML_SetUserData(g_parser, &storage);
|
||||
if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
|
||||
XML_TRUE)
|
||||
== XML_STATUS_ERROR)
|
||||
xml_failure(g_parser);
|
||||
CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDCDD"));
|
||||
{
|
||||
struct handler_record_list storage;
|
||||
storage.count = 0;
|
||||
XML_ParserReset(g_parser, NULL);
|
||||
XML_SetDefaultHandlerExpand(g_parser, record_default_handler);
|
||||
XML_SetCharacterDataHandler(g_parser, record_cdata_handler);
|
||||
XML_SetUserData(g_parser, &storage);
|
||||
if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
|
||||
XML_TRUE)
|
||||
== XML_STATUS_ERROR)
|
||||
xml_failure(g_parser);
|
||||
assert_record_handler_called(&storage, 0, "record_default_handler", 9);
|
||||
assert_record_handler_called(&storage, 1, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 2, "record_default_handler", 3);
|
||||
assert_record_handler_called(&storage, 3, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 4, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 5, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 6, "record_default_handler", 8);
|
||||
assert_record_handler_called(&storage, 7, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 8, "record_default_handler", 6);
|
||||
assert_record_handler_called(&storage, 9, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 10, "record_default_handler", 7);
|
||||
assert_record_handler_called(&storage, 11, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 12, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 13, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 14, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 15, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 16, "record_default_handler", 5);
|
||||
assert_record_handler_called(&storage, 17, "record_cdata_handler", 1);
|
||||
assert_record_handler_called(&storage, 18, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 19, "record_default_handler", 6);
|
||||
fail_unless(storage.count == 20);
|
||||
}
|
||||
|
||||
/* Finally, without passing the cdata to the default handler */
|
||||
set_subtest("not passing cdata");
|
||||
XML_ParserReset(g_parser, NULL);
|
||||
XML_SetDefaultHandlerExpand(g_parser, record_default_handler);
|
||||
XML_SetCharacterDataHandler(g_parser, record_cdata_nodefault_handler);
|
||||
CharData_Init(&storage);
|
||||
XML_SetUserData(g_parser, &storage);
|
||||
if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
|
||||
XML_TRUE)
|
||||
== XML_STATUS_ERROR)
|
||||
xml_failure(g_parser);
|
||||
CharData_CheckXMLChars(&storage, XCS("DDDDDDDDDDDDDDDDDcD"));
|
||||
{
|
||||
struct handler_record_list storage;
|
||||
storage.count = 0;
|
||||
XML_ParserReset(g_parser, NULL);
|
||||
XML_SetDefaultHandlerExpand(g_parser, record_default_handler);
|
||||
XML_SetCharacterDataHandler(g_parser, record_cdata_nodefault_handler);
|
||||
XML_SetUserData(g_parser, &storage);
|
||||
if (_XML_Parse_SINGLE_BYTES(g_parser, entity_text, (int)strlen(entity_text),
|
||||
XML_TRUE)
|
||||
== XML_STATUS_ERROR)
|
||||
xml_failure(g_parser);
|
||||
assert_record_handler_called(&storage, 0, "record_default_handler", 9);
|
||||
assert_record_handler_called(&storage, 1, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 2, "record_default_handler", 3);
|
||||
assert_record_handler_called(&storage, 3, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 4, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 5, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 6, "record_default_handler", 8);
|
||||
assert_record_handler_called(&storage, 7, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 8, "record_default_handler", 6);
|
||||
assert_record_handler_called(&storage, 9, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 10, "record_default_handler", 7);
|
||||
assert_record_handler_called(&storage, 11, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 12, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 13, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 14, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 15, "record_default_handler", 1);
|
||||
assert_record_handler_called(&storage, 16, "record_default_handler", 5);
|
||||
assert_record_handler_called(&storage, 17, "record_cdata_nodefault_handler",
|
||||
1);
|
||||
assert_record_handler_called(&storage, 18, "record_default_handler", 6);
|
||||
fail_unless(storage.count == 19);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
Copyright (c) 2019 David Loffredo <loffredo@steptools.com>
|
||||
Copyright (c) 2020 Tim Gates <tim.gates@iress.com>
|
||||
Copyright (c) 2021 Donghee Na <donghee.na@python.org>
|
||||
Copyright (c) 2023 Sony Corporation / Snild Dolkow <snild@sony.com>
|
||||
Licensed under the MIT license:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
|
@ -1646,36 +1647,43 @@ ext2_accumulate_characters(void *userData, const XML_Char *s, int len) {
|
|||
accumulate_characters(test_data->storage, s, len);
|
||||
}
|
||||
|
||||
/* Handlers that record their invocation by single characters */
|
||||
/* Handlers that record their function name and int arg. */
|
||||
|
||||
static void
|
||||
record_call(struct handler_record_list *const rec, const char *funcname,
|
||||
const int arg) {
|
||||
const int max_entries = sizeof(rec->entries) / sizeof(rec->entries[0]);
|
||||
fail_unless(rec->count < max_entries);
|
||||
struct handler_record_entry *const e = &rec->entries[rec->count++];
|
||||
e->name = funcname;
|
||||
e->arg = arg;
|
||||
}
|
||||
|
||||
void XMLCALL
|
||||
record_default_handler(void *userData, const XML_Char *s, int len) {
|
||||
UNUSED_P(s);
|
||||
UNUSED_P(len);
|
||||
CharData_AppendXMLChars((CharData *)userData, XCS("D"), 1);
|
||||
record_call((struct handler_record_list *)userData, __func__, len);
|
||||
}
|
||||
|
||||
void XMLCALL
|
||||
record_cdata_handler(void *userData, const XML_Char *s, int len) {
|
||||
UNUSED_P(s);
|
||||
UNUSED_P(len);
|
||||
CharData_AppendXMLChars((CharData *)userData, XCS("C"), 1);
|
||||
record_call((struct handler_record_list *)userData, __func__, len);
|
||||
XML_DefaultCurrent(g_parser);
|
||||
}
|
||||
|
||||
void XMLCALL
|
||||
record_cdata_nodefault_handler(void *userData, const XML_Char *s, int len) {
|
||||
UNUSED_P(s);
|
||||
UNUSED_P(len);
|
||||
CharData_AppendXMLChars((CharData *)userData, XCS("c"), 1);
|
||||
record_call((struct handler_record_list *)userData, __func__, len);
|
||||
}
|
||||
|
||||
void XMLCALL
|
||||
record_skip_handler(void *userData, const XML_Char *entityName,
|
||||
int is_parameter_entity) {
|
||||
UNUSED_P(entityName);
|
||||
CharData_AppendXMLChars((CharData *)userData,
|
||||
is_parameter_entity ? XCS("E") : XCS("e"), 1);
|
||||
record_call((struct handler_record_list *)userData, __func__,
|
||||
is_parameter_entity);
|
||||
}
|
||||
|
||||
void XMLCALL
|
||||
|
@ -1693,6 +1701,13 @@ record_element_end_handler(void *userData, const XML_Char *name) {
|
|||
CharData_AppendXMLChars(storage, name, -1);
|
||||
}
|
||||
|
||||
const struct handler_record_entry *
|
||||
_handler_record_get(const struct handler_record_list *storage, const int index,
|
||||
const char *file, const int line) {
|
||||
_fail_unless(storage->count > index, file, line, "too few handler calls");
|
||||
return &storage->entries[index];
|
||||
}
|
||||
|
||||
/* Entity Declaration Handlers */
|
||||
static const XML_Char *entity_name_to_match = NULL;
|
||||
static const XML_Char *entity_value_to_match = NULL;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
Copyright (c) 2019 David Loffredo <loffredo@steptools.com>
|
||||
Copyright (c) 2020 Tim Gates <tim.gates@iress.com>
|
||||
Copyright (c) 2021 Donghee Na <donghee.na@python.org>
|
||||
Copyright (c) 2023 Sony Corporation / Snild Dolkow <snild@sony.com>
|
||||
Licensed under the MIT license:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
|
@ -471,7 +472,16 @@ extern void XMLCALL byte_character_handler(void *userData, const XML_Char *s,
|
|||
extern void XMLCALL ext2_accumulate_characters(void *userData,
|
||||
const XML_Char *s, int len);
|
||||
|
||||
/* Handlers that record their invocation by single characters */
|
||||
/* Handlers that record their `len` arg and a single identifying character */
|
||||
|
||||
struct handler_record_entry {
|
||||
const char *name;
|
||||
int arg;
|
||||
};
|
||||
struct handler_record_list {
|
||||
int count;
|
||||
struct handler_record_entry entries[50]; // arbitrary big-enough max count
|
||||
};
|
||||
|
||||
extern void XMLCALL record_default_handler(void *userData, const XML_Char *s,
|
||||
int len);
|
||||
|
@ -493,6 +503,22 @@ extern void XMLCALL record_element_start_handler(void *userData,
|
|||
extern void XMLCALL record_element_end_handler(void *userData,
|
||||
const XML_Char *name);
|
||||
|
||||
extern const struct handler_record_entry *
|
||||
_handler_record_get(const struct handler_record_list *storage, const int index,
|
||||
const char *file, const int line);
|
||||
|
||||
# define handler_record_get(storage, index) \
|
||||
_handler_record_get((storage), (index), __FILE__, __LINE__)
|
||||
|
||||
# define assert_record_handler_called(storage, index, expected_name, \
|
||||
expected_arg) \
|
||||
do { \
|
||||
const struct handler_record_entry *e \
|
||||
= handler_record_get(storage, index); \
|
||||
fail_unless(strcmp(e->name, expected_name) == 0); \
|
||||
fail_unless(e->arg == (expected_arg)); \
|
||||
} while (0)
|
||||
|
||||
/* Entity Declaration Handlers */
|
||||
# define ENTITY_MATCH_FAIL (-1)
|
||||
# define ENTITY_MATCH_NOT_FOUND (0)
|
||||
|
|
Loading…
Add table
Reference in a new issue