summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2008-03-11 22:03:28 +0000
committerJohn Mark Bell <jmb@netsurf-browser.org>2008-03-11 22:03:28 +0000
commit04e5f38a5e8e471db41dd010e2c7c0ae9b016601 (patch)
tree68fae9d93497ab8a697b0b5dc056d40928c96426 /test
parent5b37e1f0bfd10da6720a6587e39d3dee45f77e8d (diff)
downloadlibhubbub-04e5f38a5e8e471db41dd010e2c7c0ae9b016601.tar.gz
libhubbub-04e5f38a5e8e471db41dd010e2c7c0ae9b016601.tar.bz2
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
Diffstat (limited to 'test')
-rw-r--r--test/INDEX3
-rw-r--r--test/Makefile3
-rw-r--r--test/tree.c325
3 files changed, 329 insertions, 2 deletions
diff --git a/test/INDEX b/test/INDEX
index d43829b..fc45511 100644
--- a/test/INDEX
+++ b/test/INDEX
@@ -13,4 +13,5 @@ inputstream Buffered input stream html
parser Public parser API html
parser-utf16 Public parser API (utf-16 internally) html
tokeniser HTML tokeniser html
-tokeniser2 HTML tokeniser (again) tokeniser2 \ No newline at end of file
+tokeniser2 HTML tokeniser (again) tokeniser2
+tree Treebuilding API html
diff --git a/test/Makefile b/test/Makefile
index bf4670c..6df42d7 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -32,7 +32,8 @@ DEBUG =
# Objects
OBJS = aliases cscodec csdetect dict entities filter hubbub \
- inputstream parser parser-utf16 tokeniser tokeniser2
+ inputstream parser parser-utf16 tokeniser tokeniser2 \
+ tree
OBJS += regression/cscodec-segv regression/filter-segv
.PHONY: clean debug export release setup test
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 <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <hubbub/hubbub.h>
+#include <hubbub/parser.h>
+#include <hubbub/tree.h>
+
+#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 <aliases_file> <filename>\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,
+ &params) == HUBBUB_OK);
+
+ params.tree_handler = &tree_handler;
+ assert(hubbub_parser_setopt(parser, HUBBUB_PARSER_TREE_HANDLER,
+ &params) == HUBBUB_OK);
+
+ params.document_node = (void *) ++node_counter;
+ ref_node(NULL, (void *) node_counter);
+ assert(hubbub_parser_setopt(parser, HUBBUB_PARSER_DOCUMENT_NODE,
+ &params) == 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;
+}
+