|
|
#include "unity/unity.h" |
|
|
#include <libxml/HTMLparser.h> |
|
|
|
|
|
#include <stdlib.h> |
|
|
#include <string.h> |
|
|
|
|
|
|
|
|
extern void test_htmlCharDataSAXCallback(htmlParserCtxtPtr ctxt, const xmlChar *buf, int size, int mode); |
|
|
|
|
|
typedef struct { |
|
|
int chars_calls; |
|
|
int ign_calls; |
|
|
int cdata_calls; |
|
|
char chars_text[512]; |
|
|
char ign_text[512]; |
|
|
char cdata_text[512]; |
|
|
} Capture; |
|
|
|
|
|
static void reset_capture(Capture *cap) { |
|
|
if (!cap) return; |
|
|
memset(cap, 0, sizeof(*cap)); |
|
|
} |
|
|
|
|
|
static void cb_characters(void *userData, const xmlChar *ch, int len) { |
|
|
Capture *cap = (Capture *)userData; |
|
|
if (!cap || !ch || len <= 0) return; |
|
|
int copy = len; |
|
|
if (copy > (int)(sizeof(cap->chars_text) - 1 - (int)strlen(cap->chars_text))) |
|
|
copy = (int)(sizeof(cap->chars_text) - 1 - strlen(cap->chars_text)); |
|
|
strncat(cap->chars_text, (const char *)ch, copy); |
|
|
cap->chars_calls++; |
|
|
} |
|
|
|
|
|
static void cb_ignorableWhitespace(void *userData, const xmlChar *ch, int len) { |
|
|
Capture *cap = (Capture *)userData; |
|
|
if (!cap || !ch || len <= 0) return; |
|
|
int copy = len; |
|
|
if (copy > (int)(sizeof(cap->ign_text) - 1 - (int)strlen(cap->ign_text))) |
|
|
copy = (int)(sizeof(cap->ign_text) - 1 - strlen(cap->ign_text)); |
|
|
strncat(cap->ign_text, (const char *)ch, copy); |
|
|
cap->ign_calls++; |
|
|
} |
|
|
|
|
|
static void cb_cdataBlock(void *userData, const xmlChar *ch, int len) { |
|
|
Capture *cap = (Capture *)userData; |
|
|
if (!cap || !ch || len <= 0) return; |
|
|
int copy = len; |
|
|
if (copy > (int)(sizeof(cap->cdata_text) - 1 - (int)strlen(cap->cdata_text))) |
|
|
copy = (int)(sizeof(cap->cdata_text) - 1 - strlen(cap->cdata_text)); |
|
|
strncat(cap->cdata_text, (const char *)ch, copy); |
|
|
cap->cdata_calls++; |
|
|
} |
|
|
|
|
|
static void prepare_sax(xmlSAXHandler *sax, |
|
|
xmlCharactersSAXFunc chars, |
|
|
xmlIgnorableWhitespaceSAXFunc ign, |
|
|
xmlCDataBlockSAXFunc cdata) { |
|
|
memset(sax, 0, sizeof(*sax)); |
|
|
sax->characters = chars; |
|
|
sax->ignorableWhitespace = ign; |
|
|
sax->cdataBlock = cdata; |
|
|
} |
|
|
|
|
|
void setUp(void) { |
|
|
|
|
|
} |
|
|
|
|
|
void tearDown(void) { |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void test_htmlCharDataSAXCallback_null_sax(void) { |
|
|
htmlParserCtxtPtr ctxt = htmlNewParserCtxt(); |
|
|
TEST_ASSERT_NOT_NULL(ctxt); |
|
|
|
|
|
Capture cap; |
|
|
reset_capture(&cap); |
|
|
|
|
|
ctxt->sax = NULL; |
|
|
ctxt->userData = ∩ |
|
|
ctxt->disableSAX = 0; |
|
|
ctxt->keepBlanks = 0; |
|
|
ctxt->name = (const xmlChar *)"div"; |
|
|
|
|
|
const char *data = "abc"; |
|
|
test_htmlCharDataSAXCallback(ctxt, (const xmlChar *)data, (int)strlen(data), 0); |
|
|
|
|
|
TEST_ASSERT_EQUAL_INT(0, cap.chars_calls); |
|
|
TEST_ASSERT_EQUAL_INT(0, cap.ign_calls); |
|
|
TEST_ASSERT_EQUAL_INT(0, cap.cdata_calls); |
|
|
|
|
|
htmlFreeParserCtxt(ctxt); |
|
|
} |
|
|
|
|
|
|
|
|
void test_htmlCharDataSAXCallback_disabled_sax(void) { |
|
|
htmlParserCtxtPtr ctxt = htmlNewParserCtxt(); |
|
|
TEST_ASSERT_NOT_NULL(ctxt); |
|
|
|
|
|
xmlSAXHandler sax; |
|
|
Capture cap; |
|
|
reset_capture(&cap); |
|
|
prepare_sax(&sax, cb_characters, cb_ignorableWhitespace, cb_cdataBlock); |
|
|
|
|
|
ctxt->sax = &sax; |
|
|
ctxt->userData = ∩ |
|
|
ctxt->disableSAX = 1; |
|
|
ctxt->keepBlanks = 0; |
|
|
ctxt->name = (const xmlChar *)"div"; |
|
|
|
|
|
const char *data = "abc"; |
|
|
test_htmlCharDataSAXCallback(ctxt, (const xmlChar *)data, (int)strlen(data), 0); |
|
|
|
|
|
TEST_ASSERT_EQUAL_INT(0, cap.chars_calls); |
|
|
TEST_ASSERT_EQUAL_INT(0, cap.ign_calls); |
|
|
TEST_ASSERT_EQUAL_INT(0, cap.cdata_calls); |
|
|
|
|
|
htmlFreeParserCtxt(ctxt); |
|
|
} |
|
|
|
|
|
|
|
|
void test_htmlCharDataSAXCallback_html_leading_ws_keepBlanks_false(void) { |
|
|
htmlParserCtxtPtr ctxt = htmlNewParserCtxt(); |
|
|
TEST_ASSERT_NOT_NULL(ctxt); |
|
|
|
|
|
xmlSAXHandler sax; |
|
|
Capture cap; |
|
|
reset_capture(&cap); |
|
|
prepare_sax(&sax, cb_characters, cb_ignorableWhitespace, cb_cdataBlock); |
|
|
|
|
|
ctxt->sax = &sax; |
|
|
ctxt->userData = ∩ |
|
|
ctxt->disableSAX = 0; |
|
|
ctxt->keepBlanks = 0; |
|
|
ctxt->name = (const xmlChar *)"html"; |
|
|
|
|
|
const char *data = " \t\nabc"; |
|
|
test_htmlCharDataSAXCallback(ctxt, (const xmlChar *)data, (int)strlen(data), 0); |
|
|
|
|
|
TEST_ASSERT_EQUAL_INT(1, cap.ign_calls); |
|
|
TEST_ASSERT_EQUAL_STRING(" \t\n", cap.ign_text); |
|
|
|
|
|
TEST_ASSERT_EQUAL_INT(1, cap.chars_calls); |
|
|
TEST_ASSERT_EQUAL_STRING("abc", cap.chars_text); |
|
|
|
|
|
TEST_ASSERT_EQUAL_INT(0, cap.cdata_calls); |
|
|
|
|
|
htmlFreeParserCtxt(ctxt); |
|
|
} |
|
|
|
|
|
|
|
|
void test_htmlCharDataSAXCallback_head_leading_ws_keepBlanks_true(void) { |
|
|
htmlParserCtxtPtr ctxt = htmlNewParserCtxt(); |
|
|
TEST_ASSERT_NOT_NULL(ctxt); |
|
|
|
|
|
xmlSAXHandler sax; |
|
|
Capture cap; |
|
|
reset_capture(&cap); |
|
|
prepare_sax(&sax, cb_characters, cb_ignorableWhitespace, cb_cdataBlock); |
|
|
|
|
|
ctxt->sax = &sax; |
|
|
ctxt->userData = ∩ |
|
|
ctxt->disableSAX = 0; |
|
|
ctxt->keepBlanks = 1; |
|
|
ctxt->name = (const xmlChar *)"head"; |
|
|
|
|
|
const char *data = " abc"; |
|
|
test_htmlCharDataSAXCallback(ctxt, (const xmlChar *)data, (int)strlen(data), 0); |
|
|
|
|
|
TEST_ASSERT_EQUAL_INT(2, cap.chars_calls); |
|
|
TEST_ASSERT_EQUAL_STRING(" abc", cap.chars_text); |
|
|
|
|
|
TEST_ASSERT_EQUAL_INT(0, cap.ign_calls); |
|
|
TEST_ASSERT_EQUAL_INT(0, cap.cdata_calls); |
|
|
|
|
|
htmlFreeParserCtxt(ctxt); |
|
|
} |
|
|
|
|
|
|
|
|
void test_htmlCharDataSAXCallback_html_only_ws_keepBlanks_false(void) { |
|
|
htmlParserCtxtPtr ctxt = htmlNewParserCtxt(); |
|
|
TEST_ASSERT_NOT_NULL(ctxt); |
|
|
|
|
|
xmlSAXHandler sax; |
|
|
Capture cap; |
|
|
reset_capture(&cap); |
|
|
prepare_sax(&sax, cb_characters, cb_ignorableWhitespace, cb_cdataBlock); |
|
|
|
|
|
ctxt->sax = &sax; |
|
|
ctxt->userData = ∩ |
|
|
ctxt->disableSAX = 0; |
|
|
ctxt->keepBlanks = 0; |
|
|
ctxt->name = (const xmlChar *)"html"; |
|
|
|
|
|
const char *data = " "; |
|
|
test_htmlCharDataSAXCallback(ctxt, (const xmlChar *)data, (int)strlen(data), 0); |
|
|
|
|
|
TEST_ASSERT_EQUAL_INT(1, cap.ign_calls); |
|
|
TEST_ASSERT_EQUAL_STRING(" ", cap.ign_text); |
|
|
|
|
|
TEST_ASSERT_EQUAL_INT(0, cap.chars_calls); |
|
|
TEST_ASSERT_EQUAL_INT(0, cap.cdata_calls); |
|
|
|
|
|
htmlFreeParserCtxt(ctxt); |
|
|
} |
|
|
|
|
|
|
|
|
void test_htmlCharDataSAXCallback_cdata_mode_nonzero(void) { |
|
|
htmlParserCtxtPtr ctxt = htmlNewParserCtxt(); |
|
|
TEST_ASSERT_NOT_NULL(ctxt); |
|
|
|
|
|
xmlSAXHandler sax; |
|
|
Capture cap; |
|
|
reset_capture(&cap); |
|
|
prepare_sax(&sax, cb_characters, cb_ignorableWhitespace, cb_cdataBlock); |
|
|
|
|
|
ctxt->sax = &sax; |
|
|
ctxt->userData = ∩ |
|
|
ctxt->disableSAX = 0; |
|
|
ctxt->keepBlanks = 0; |
|
|
ctxt->name = (const xmlChar *)"div"; |
|
|
|
|
|
const char *data = " CDATA <kept> "; |
|
|
|
|
|
int mode = 9999; |
|
|
test_htmlCharDataSAXCallback(ctxt, (const xmlChar *)data, (int)strlen(data), mode); |
|
|
|
|
|
TEST_ASSERT_EQUAL_INT(0, cap.ign_calls); |
|
|
TEST_ASSERT_EQUAL_INT(0, cap.chars_calls); |
|
|
TEST_ASSERT_EQUAL_INT(1, cap.cdata_calls); |
|
|
TEST_ASSERT_EQUAL_STRING(" CDATA <kept> ", cap.cdata_text); |
|
|
|
|
|
htmlFreeParserCtxt(ctxt); |
|
|
} |
|
|
|
|
|
|
|
|
void test_htmlCharDataSAXCallback_nonzero_mode_no_cdataBlock_falls_back(void) { |
|
|
htmlParserCtxtPtr ctxt = htmlNewParserCtxt(); |
|
|
TEST_ASSERT_NOT_NULL(ctxt); |
|
|
|
|
|
xmlSAXHandler sax; |
|
|
Capture cap; |
|
|
reset_capture(&cap); |
|
|
|
|
|
prepare_sax(&sax, cb_characters, cb_ignorableWhitespace, NULL); |
|
|
|
|
|
ctxt->sax = &sax; |
|
|
ctxt->userData = ∩ |
|
|
ctxt->disableSAX = 0; |
|
|
ctxt->keepBlanks = 1; |
|
|
ctxt->name = (const xmlChar *)"div"; |
|
|
|
|
|
const char *data = "abc"; |
|
|
int mode = 9999; |
|
|
test_htmlCharDataSAXCallback(ctxt, (const xmlChar *)data, (int)strlen(data), mode); |
|
|
|
|
|
TEST_ASSERT_EQUAL_INT(1, cap.chars_calls); |
|
|
TEST_ASSERT_EQUAL_STRING("abc", cap.chars_text); |
|
|
TEST_ASSERT_EQUAL_INT(0, cap.ign_calls); |
|
|
TEST_ASSERT_EQUAL_INT(0, cap.cdata_calls); |
|
|
|
|
|
htmlFreeParserCtxt(ctxt); |
|
|
} |
|
|
|
|
|
int main(void) { |
|
|
UNITY_BEGIN(); |
|
|
RUN_TEST(test_htmlCharDataSAXCallback_null_sax); |
|
|
RUN_TEST(test_htmlCharDataSAXCallback_disabled_sax); |
|
|
RUN_TEST(test_htmlCharDataSAXCallback_html_leading_ws_keepBlanks_false); |
|
|
RUN_TEST(test_htmlCharDataSAXCallback_head_leading_ws_keepBlanks_true); |
|
|
RUN_TEST(test_htmlCharDataSAXCallback_html_only_ws_keepBlanks_false); |
|
|
RUN_TEST(test_htmlCharDataSAXCallback_cdata_mode_nonzero); |
|
|
RUN_TEST(test_htmlCharDataSAXCallback_nonzero_mode_no_cdataBlock_falls_back); |
|
|
return UNITY_END(); |
|
|
} |