/* * This file is part of LibNSLayout's tests * Licensed under the ISC License, http://opensource.org/licenses/ISC * Copyright 2015 Michael Drake */ #include #include #include #include #include #include #include #ifndef UNUSED #define UNUSED(x) (void)(x) #endif static nslayout_error test_loader_nslayout_test_callback( nslayout_layout *layout, void *pw, nslayout_request *req) { UNUSED(req); UNUSED(layout); UNUSED(pw); return NSLAYOUT_OK; } struct test_loader_ctx { dom_hubbub_parser *parser; dom_document *doc; unsigned char *buffer; size_t buffer_size; FILE *handle; css_select_ctx *css_ctx; css_stylesheet *css_sheet; }; static bool test_loader_doc_load_start( const char *file, size_t buffer_size, struct test_loader_ctx *load_ctx) { dom_hubbub_parser_params params; dom_hubbub_error error; size_t chunk_length; params.enc = NULL; params.fix_enc = true; params.enable_script = false; params.msg = NULL; params.script = NULL; params.ctx = NULL; params.daf = NULL; load_ctx->buffer = malloc(buffer_size); if (load_ctx->buffer == NULL) { return false; } load_ctx->buffer_size = buffer_size; /* Create Hubbub parser */ error = dom_hubbub_parser_create(¶ms, &load_ctx->parser, &load_ctx->doc); if (error != DOM_HUBBUB_OK) { free(load_ctx->buffer); return false; } /* Open input file */ load_ctx->handle = fopen(file, "rb"); if (load_ctx->handle == NULL) { dom_hubbub_parser_destroy(load_ctx->parser); free(load_ctx->buffer); return false; } /* Parse input file in chunks */ chunk_length = buffer_size; chunk_length = fread(load_ctx->buffer, 1, load_ctx->buffer_size, load_ctx->handle); error = dom_hubbub_parser_parse_chunk(load_ctx->parser, load_ctx->buffer, chunk_length); if (error != DOM_HUBBUB_OK) { dom_hubbub_parser_destroy(load_ctx->parser); printf("Parsing errors occur\n"); return false; } return true; } static bool test_loader_doc_load_next( struct test_loader_ctx *load_ctx, bool *complete) { dom_hubbub_error error; int chunk_length; /* Parse input file in chunks */ chunk_length = fread(load_ctx->buffer, 1, load_ctx->buffer_size, load_ctx->handle); if (chunk_length != 0) { error = dom_hubbub_parser_parse_chunk(load_ctx->parser, load_ctx->buffer, chunk_length); if (error != DOM_HUBBUB_OK) { dom_hubbub_parser_destroy(load_ctx->parser); printf("Parsing errors occur\n"); return false; } *complete = false; return true; } *complete = true; /* Done parsing file */ error = dom_hubbub_parser_completed(load_ctx->parser); if (error != DOM_HUBBUB_OK) { dom_hubbub_parser_destroy(load_ctx->parser); printf("Parsing error when construct DOM\n"); return false; } /* Finished with parser */ dom_hubbub_parser_destroy(load_ctx->parser); /* Close input file */ if (fclose(load_ctx->handle) != 0) { printf("Can't close test input file\n"); return false; } return true; } static css_error test_loader_resolve_url(void *pw, const char *base, lwc_string *rel, lwc_string **abs) { UNUSED(pw); UNUSED(base); /* No join implementation; just copy rel to abs for now. */ *abs = lwc_string_ref(rel); return CSS_OK; } static bool test_loader_css_fini(struct test_loader_ctx *load_ctx) { css_error css_err = CSS_OK; if (load_ctx->css_ctx != NULL) { css_err = css_select_ctx_destroy(load_ctx->css_ctx); if (css_err != CSS_OK) { printf("ERROR: css_select_ctx_destroy\n"); } } if (load_ctx->css_sheet != NULL) { css_err = css_stylesheet_destroy(load_ctx->css_sheet); if (css_err != CSS_OK) { printf("ERROR: css_stylesheet_destroy\n"); } } return (css_err == CSS_OK); } static bool test_loader_css_init(struct test_loader_ctx *load_ctx) { css_error css_err; css_stylesheet_params params; const char *ua_style = "div, p, h1, h2, h3, h4, h5 {display:block}"; params.params_version = CSS_STYLESHEET_PARAMS_VERSION_1; params.level = CSS_LEVEL_21; params.charset = "UTF-8"; params.url = "foo"; params.title = "foo"; params.allow_quirks = false; params.inline_style = false; params.resolve = test_loader_resolve_url; params.resolve_pw = NULL; params.import = NULL; params.import_pw = NULL; params.color = NULL; params.color_pw = NULL; params.font = NULL; params.font_pw = NULL; /* create a stylesheet */ css_err = css_stylesheet_create(¶ms, &load_ctx->css_sheet); if (css_err != CSS_OK) { printf("ERROR: css_stylesheet_create\n"); goto fail; } css_err = css_stylesheet_append_data(load_ctx->css_sheet, (const uint8_t *) ua_style, sizeof ua_style); if (css_err != CSS_OK && css_err != CSS_NEEDDATA) { printf("ERROR: css_stylesheet_append_data\n"); goto fail; } css_err = css_stylesheet_data_done(load_ctx->css_sheet); if (css_err != CSS_OK) { printf("ERROR: css_stylesheet_data_done\n"); goto fail; } /* Create a selection context (with no sheets added) */ css_err = css_select_ctx_create(&load_ctx->css_ctx); if (css_err != CSS_OK) { printf("ERROR: css_select_ctx_create\n"); goto fail; } css_err = css_select_ctx_append_sheet(load_ctx->css_ctx, load_ctx->css_sheet, CSS_ORIGIN_UA, CSS_MEDIA_ALL); if (css_err != CSS_OK) { printf("ERROR: css_select_ctx_append_sheet\n"); goto fail; } return true; fail: test_loader_css_fini(load_ctx); return false; } static bool test_loader(const char *document_path, css_media_type media, size_t chunk_size) { nslayout_layout *layout = NULL; nslayout_error error; struct test_loader_ctx load_ctx; bool complete = false; bool ret = false; printf("Test loader\n"); load_ctx.parser = NULL; load_ctx.doc = NULL; load_ctx.buffer = NULL; load_ctx.buffer_size = 0; load_ctx.handle = NULL; load_ctx.css_sheet = NULL; load_ctx.css_ctx = NULL; printf("Starting load\n"); if (!test_loader_doc_load_start(document_path, chunk_size, &load_ctx)) { printf("ERROR: doc_load_start\n"); goto fail; } printf("Creating style context\n"); if (!test_loader_css_init(&load_ctx)) { printf("ERROR: create_style_context\n"); goto fail; } printf("Creating nsl layout\n"); error = nslayout_layout_create(load_ctx.doc, load_ctx.css_ctx, &media, test_loader_nslayout_test_callback, NULL, &layout); if (error != NSLAYOUT_OK) { goto fail; } while (!complete) { printf("Loading a chunk of the document\n"); if (!test_loader_doc_load_next(&load_ctx, &complete)) { printf("ERROR: doc_load_next\n"); goto fail; } } printf("Destroying layout\n"); error = nslayout_layout_destroy(layout); layout = NULL; ret = (error == NSLAYOUT_OK); fail: if (layout != NULL) { nslayout_layout_destroy(layout); } test_loader_css_fini(&load_ctx); dom_node_unref(load_ctx.doc); free(load_ctx.buffer); return ret; }