libxml / tests /tests_HTMLparser_htmlParseComment.c
AryaWu's picture
Upload folder using huggingface_hub
6baed57 verified
#include "unity/unity.h"
#include <libxml/HTMLparser.h>
#include <stdlib.h>
#include <string.h>
/* Wrapper for the static function under test (provided in the module) */
void test_htmlParseComment(htmlParserCtxtPtr ctxt, int bogus);
/* Capture structure for SAX comment callback */
typedef struct {
int count;
char *last;
} CommentCapture;
static void free_capture(CommentCapture *cap) {
if (cap->last) {
free(cap->last);
cap->last = NULL;
}
cap->count = 0;
}
static void comment_cb(void *ctx, const xmlChar *value) {
CommentCapture *cap = (CommentCapture *)ctx;
cap->count++;
/* Copy the comment text into an owned buffer (ASCII-safe) */
const char *val = (const char *)value;
size_t n = strlen(val);
free_capture(cap);
cap->last = (char *)malloc(n + 1);
if (cap->last) {
memcpy(cap->last, val, n + 1);
}
}
/* Helper to create a parser context with given input buffer */
static htmlParserCtxtPtr make_ctxt(const char *data) {
if (data == NULL) data = "";
int len = (int)strlen(data);
htmlParserCtxtPtr ctxt = htmlCreateMemoryParserCtxt(data, len);
return ctxt;
}
void setUp(void) {
/* Setup code here, or leave empty */
}
void tearDown(void) {
/* Cleanup code here, or leave empty */
}
/* Bogus comment: content is read until '>', which is then skipped */
void test_htmlParseComment_bogus_basic(void) {
CommentCapture cap = {0, NULL};
htmlParserCtxtPtr ctxt = make_ctxt("hello>");
TEST_ASSERT_NOT_NULL(ctxt);
xmlSAXHandler sax;
memset(&sax, 0, sizeof(sax));
sax.comment = comment_cb;
ctxt->sax = &sax;
ctxt->userData = &cap;
ctxt->disableSAX = 0;
test_htmlParseComment(ctxt, 1);
TEST_ASSERT_EQUAL_INT(1, cap.count);
TEST_ASSERT_NOT_NULL(cap.last);
TEST_ASSERT_EQUAL_STRING("hello", cap.last);
free_capture(&cap);
htmlFreeParserCtxt(ctxt);
}
/* Bogus comment without closing '>' should still emit collected content */
void test_htmlParseComment_bogus_no_terminator(void) {
CommentCapture cap = {0, NULL};
htmlParserCtxtPtr ctxt = make_ctxt("noend");
TEST_ASSERT_NOT_NULL(ctxt);
xmlSAXHandler sax;
memset(&sax, 0, sizeof(sax));
sax.comment = comment_cb;
ctxt->sax = &sax;
ctxt->userData = &cap;
ctxt->disableSAX = 0;
test_htmlParseComment(ctxt, 1);
TEST_ASSERT_EQUAL_INT(1, cap.count);
TEST_ASSERT_NOT_NULL(cap.last);
TEST_ASSERT_EQUAL_STRING("noend", cap.last);
free_capture(&cap);
htmlFreeParserCtxt(ctxt);
}
/* Non-bogus: immediate '>' produces an empty comment */
void test_htmlParseComment_nonbogus_immediate_gt(void) {
CommentCapture cap = {0, NULL};
htmlParserCtxtPtr ctxt = make_ctxt(">");
TEST_ASSERT_NOT_NULL(ctxt);
xmlSAXHandler sax;
memset(&sax, 0, sizeof(sax));
sax.comment = comment_cb;
ctxt->sax = &sax;
ctxt->userData = &cap;
ctxt->disableSAX = 0;
test_htmlParseComment(ctxt, 0);
TEST_ASSERT_EQUAL_INT(1, cap.count);
TEST_ASSERT_NOT_NULL(cap.last);
TEST_ASSERT_EQUAL_STRING("", cap.last);
free_capture(&cap);
htmlFreeParserCtxt(ctxt);
}
/* Non-bogus: immediate "->" also produces an empty comment */
void test_htmlParseComment_nonbogus_immediate_arrow(void) {
CommentCapture cap = {0, NULL};
htmlParserCtxtPtr ctxt = make_ctxt("->");
TEST_ASSERT_NOT_NULL(ctxt);
xmlSAXHandler sax;
memset(&sax, 0, sizeof(sax));
sax.comment = comment_cb;
ctxt->sax = &sax;
ctxt->userData = &cap;
ctxt->disableSAX = 0;
test_htmlParseComment(ctxt, 0);
TEST_ASSERT_EQUAL_INT(1, cap.count);
TEST_ASSERT_NOT_NULL(cap.last);
TEST_ASSERT_EQUAL_STRING("", cap.last);
free_capture(&cap);
htmlFreeParserCtxt(ctxt);
}
/* Non-bogus: parse data until '-' is encountered; expect content before '-' */
void test_htmlParseComment_nonbogus_until_dash(void) {
CommentCapture cap = {0, NULL};
htmlParserCtxtPtr ctxt = make_ctxt("abc-def->");
TEST_ASSERT_NOT_NULL(ctxt);
xmlSAXHandler sax;
memset(&sax, 0, sizeof(sax));
sax.comment = comment_cb;
ctxt->sax = &sax;
ctxt->userData = &cap;
ctxt->disableSAX = 0;
test_htmlParseComment(ctxt, 0);
TEST_ASSERT_EQUAL_INT(1, cap.count);
TEST_ASSERT_NOT_NULL(cap.last);
TEST_ASSERT_EQUAL_STRING("abc", cap.last);
free_capture(&cap);
htmlFreeParserCtxt(ctxt);
}
/* Ensure no callback is emitted when SAX is disabled */
void test_htmlParseComment_SAX_disabled(void) {
CommentCapture cap = {0, NULL};
htmlParserCtxtPtr ctxt = make_ctxt("ignored>");
TEST_ASSERT_NOT_NULL(ctxt);
xmlSAXHandler sax;
memset(&sax, 0, sizeof(sax));
sax.comment = comment_cb;
ctxt->sax = &sax;
ctxt->userData = &cap;
ctxt->disableSAX = 1; /* Disable SAX */
test_htmlParseComment(ctxt, 1);
TEST_ASSERT_EQUAL_INT(0, cap.count);
TEST_ASSERT_NULL(cap.last);
free_capture(&cap);
htmlFreeParserCtxt(ctxt);
}
/* Ensure safe behavior when ctxt->sax is NULL */
void test_htmlParseComment_null_sax(void) {
CommentCapture cap = {0, NULL};
htmlParserCtxtPtr ctxt = make_ctxt("hello>");
TEST_ASSERT_NOT_NULL(ctxt);
ctxt->sax = NULL; /* No SAX handler */
ctxt->userData = &cap;
ctxt->disableSAX = 0;
test_htmlParseComment(ctxt, 1);
TEST_ASSERT_EQUAL_INT(0, cap.count);
TEST_ASSERT_NULL(cap.last);
free_capture(&cap);
htmlFreeParserCtxt(ctxt);
}
int main(void) {
/* Initialize libxml2 parser library */
xmlInitParser();
UNITY_BEGIN();
RUN_TEST(test_htmlParseComment_bogus_basic);
RUN_TEST(test_htmlParseComment_bogus_no_terminator);
RUN_TEST(test_htmlParseComment_nonbogus_immediate_gt);
RUN_TEST(test_htmlParseComment_nonbogus_immediate_arrow);
RUN_TEST(test_htmlParseComment_nonbogus_until_dash);
RUN_TEST(test_htmlParseComment_SAX_disabled);
RUN_TEST(test_htmlParseComment_null_sax);
int rc = UNITY_END();
/* Cleanup libxml2 global state */
xmlCleanupParser();
return rc;
}