From 04e5f38a5e8e471db41dd010e2c7c0ae9b016601 Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Tue, 11 Mar 2008 22:03:28 +0000 Subject: More treebuilder (8.2.4.8) Make tree_handler a pointer rather than value. Check for tree_handler's presence in hubbub_treebuilder_token_handler rather than scattering checks all over the treebuilder code. Add test driver (doesn't actually build a tree but will exercise the core code correctly and verify that the treebuilder code releases all the node references it gains) Enhance quirks mode reporting to distinguish between standards, limited, and full quirks modes. svn path=/trunk/hubbub/; revision=3939 --- test/tree.c | 325 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 325 insertions(+) create mode 100644 test/tree.c (limited to 'test/tree.c') diff --git a/test/tree.c b/test/tree.c new file mode 100644 index 0000000..76cf438 --- /dev/null +++ b/test/tree.c @@ -0,0 +1,325 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include "utils/utils.h" + +#include "testutils.h" + +#define NODE_REF_CHUNK 1024 +static uint16_t *node_ref; +static uintptr_t node_ref_alloc; +static uintptr_t node_counter; + +#define GROW_REF \ + if (node_counter >= node_ref_alloc) { \ + uint16_t *temp = realloc(node_ref, \ + (node_ref_alloc + NODE_REF_CHUNK) * \ + sizeof(uint16_t)); \ + if (temp == NULL) { \ + printf("FAIL - no memory\n"); \ + exit(1); \ + } \ + node_ref = temp; \ + node_ref_alloc += NODE_REF_CHUNK; \ + } + +static const uint8_t *pbuffer; + +static void buffer_handler(const uint8_t *buffer, size_t len, void *pw); +static int create_comment(void *ctx, const hubbub_string *data, void **result); +static int create_doctype(void *ctx, const hubbub_string *qname, + const hubbub_string *public_id, const hubbub_string *system_id, + void **result); +static int create_element(void *ctx, const hubbub_tag *tag, void **result); +static int create_text(void *ctx, const hubbub_string *data, void **result); +static int ref_node(void *ctx, void *node); +static int unref_node(void *ctx, void *node); +static int append_child(void *ctx, void *parent, void *child, void **result); +static int insert_before(void *ctx, void *parent, void *child, void *ref_child, + void **result); +static int remove_child(void *ctx, void *parent, void *child, void **result); +static int clone_node(void *ctx, void *node, bool deep, void **result); +static int set_quirks_mode(void *ctx, hubbub_quirks_mode mode); + +static hubbub_tree_handler tree_handler = { + create_comment, + create_doctype, + create_element, + create_text, + ref_node, + unref_node, + append_child, + insert_before, + remove_child, + clone_node, + set_quirks_mode, + NULL +}; + +static void *myrealloc(void *ptr, size_t len, void *pw) +{ + UNUSED(pw); + + return realloc(ptr, len); +} + +int main(int argc, char **argv) +{ + hubbub_parser *parser; + hubbub_parser_optparams params; + FILE *fp; + size_t len, origlen; +#define CHUNK_SIZE (4096) + uint8_t buf[CHUNK_SIZE]; + const char *charset; + hubbub_charset_source cssource; + uint8_t *buffer; + bool passed = true; + + if (argc != 3) { + printf("Usage: %s \n", argv[0]); + return 1; + } + + node_ref = calloc(NODE_REF_CHUNK, sizeof(uint16_t)); + if (node_ref == NULL) { + printf("Failed allocating node_ref\n"); + return 1; + } + node_ref_alloc = NODE_REF_CHUNK; + + /* Initialise library */ + assert(hubbub_initialise(argv[1], myrealloc, NULL) == HUBBUB_OK); + + parser = hubbub_parser_create("UTF-8", "UTF-8", myrealloc, NULL); + assert(parser != NULL); + + params.buffer_handler.handler = buffer_handler; + params.buffer_handler.pw = NULL; + assert(hubbub_parser_setopt(parser, HUBBUB_PARSER_BUFFER_HANDLER, + ¶ms) == HUBBUB_OK); + + params.tree_handler = &tree_handler; + assert(hubbub_parser_setopt(parser, HUBBUB_PARSER_TREE_HANDLER, + ¶ms) == HUBBUB_OK); + + params.document_node = (void *) ++node_counter; + ref_node(NULL, (void *) node_counter); + assert(hubbub_parser_setopt(parser, HUBBUB_PARSER_DOCUMENT_NODE, + ¶ms) == HUBBUB_OK); + + fp = fopen(argv[2], "rb"); + if (fp == NULL) { + printf("Failed opening %s\n", argv[2]); + return 1; + } + + fseek(fp, 0, SEEK_END); + origlen = len = ftell(fp); + fseek(fp, 0, SEEK_SET); + + while (len >= CHUNK_SIZE) { + fread(buf, 1, CHUNK_SIZE, fp); + + assert(hubbub_parser_parse_chunk(parser, + buf, CHUNK_SIZE) == HUBBUB_OK); + + len -= CHUNK_SIZE; + } + + if (len > 0) { + fread(buf, 1, len, fp); + + assert(hubbub_parser_parse_chunk(parser, + buf, len) == HUBBUB_OK); + + len = 0; + + assert(hubbub_parser_completed(parser) == HUBBUB_OK); + } + + fclose(fp); + + charset = hubbub_parser_read_charset(parser, &cssource); + + printf("Charset: %s (from %d)\n", charset, cssource); + + assert(hubbub_parser_claim_buffer(parser, &buffer, &len) == + HUBBUB_OK); + + free(buffer); + + hubbub_parser_destroy(parser); + + assert(hubbub_finalise(myrealloc, NULL) == HUBBUB_OK); + + /* Ensure that all nodes have been released by the treebuilder */ + for (uintptr_t n = 1; n <= node_counter; n++) { + if (node_ref[n] != 0) { + printf("%u still referenced (=%u)\n", n, node_ref[n]); + passed = false; + } + } + + free(node_ref); + + printf("%s\n", passed ? "PASS" : "FAIL"); + + return 0; +} + +void buffer_handler(const uint8_t *buffer, size_t len, void *pw) +{ + UNUSED(len); + UNUSED(pw); + + pbuffer = buffer; +} + +int create_comment(void *ctx, const hubbub_string *data, void **result) +{ + printf("Creating (%u) [comment '%.*s']\n", ++node_counter, + data->len, pbuffer + data->data_off); + + GROW_REF + node_ref[node_counter] = 0; + + ref_node(ctx, (void *) node_counter); + + *result = (void *) node_counter; + + return 0; +} + +int create_doctype(void *ctx, const hubbub_string *qname, + const hubbub_string *public_id, const hubbub_string *system_id, + void **result) +{ + UNUSED(public_id); + UNUSED(system_id); + + printf("Creating (%u) [doctype '%.*s']\n", ++node_counter, + qname->len, pbuffer + qname->data_off); + + GROW_REF + node_ref[node_counter] = 0; + + ref_node(ctx, (void *) node_counter); + + *result = (void *) node_counter; + + return 0; +} + +int create_element(void *ctx, const hubbub_tag *tag, void **result) +{ + printf("Creating (%u) [element '%.*s']\n", ++node_counter, + tag->name.len, pbuffer + tag->name.data_off); + + GROW_REF + node_ref[node_counter] = 0; + + ref_node(ctx, (void *) node_counter); + + *result = (void *) node_counter; + + return 0; +} + +int create_text(void *ctx, const hubbub_string *data, void **result) +{ + printf("Creating (%u) [text '%.*s']\n", ++node_counter, + data->len, pbuffer + data->data_off); + + GROW_REF + node_ref[node_counter] = 0; + + ref_node(ctx, (void *) node_counter); + + *result = (void *) node_counter; + + return 0; +} + +int ref_node(void *ctx, void *node) +{ + UNUSED(ctx); + + printf("Referencing %u (=%u)\n", + (uintptr_t) node, ++node_ref[(uintptr_t) node]); + + return 0; +} + +int unref_node(void *ctx, void *node) +{ + UNUSED(ctx); + + printf("Unreferencing %u (=%u)\n", + (uintptr_t) node, --node_ref[(uintptr_t) node]); + + return 0; +} + +int append_child(void *ctx, void *parent, void *child, void **result) +{ + printf("Appending %u to %u\n", (uintptr_t) child, (uintptr_t) parent); + ref_node(ctx, child); + + *result = (void *) child; + + return 0; +} + +int insert_before(void *ctx, void *parent, void *child, void *ref_child, + void **result) +{ + printf("Inserting %u in %u before %u\n", (uintptr_t) child, + (uintptr_t) parent, (uintptr_t) ref_child); + ref_node(ctx, child); + + *result = (void *) child; + + return 0; +} + +int remove_child(void *ctx, void *parent, void *child, void **result) +{ + printf("Removing %u from %u\n", (uintptr_t) child, (uintptr_t) parent); + ref_node(ctx, child); + + *result = (void *) child; + + return 0; +} + +int clone_node(void *ctx, void *node, bool deep, void **result) +{ + printf("%sCloning %u -> %u\n", deep ? "Deep-" : "", + (uintptr_t) node, ++node_counter); + + GROW_REF + node_ref[node_counter] = 0; + + ref_node(ctx, (void *) node_counter); + + *result = (void *) node_counter; + + return 0; +} + +int set_quirks_mode(void *ctx, hubbub_quirks_mode mode) +{ + UNUSED(ctx); + + printf("Quirks mode = %u\n", mode); + + return 0; +} + -- cgit v1.2.3