From afc79d5912a34b4e5471722ffbf1ec0f8459a2a7 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Fri, 5 Aug 2016 22:34:44 +0100 Subject: [PATCH] Improve user option testing and API parameter checking --- test/data/Choices-all | 113 +++++++++ test/data/Choices-full | 18 ++ test/data/Choices-short | 17 ++ test/nsoption.c | 496 +++++++++++++++++++++++++++++++++++----- utils/nsoption.c | 47 +++- 5 files changed, 627 insertions(+), 64 deletions(-) create mode 100644 test/data/Choices-all create mode 100644 test/data/Choices-full create mode 100644 test/data/Choices-short diff --git a/test/data/Choices-all b/test/data/Choices-all new file mode 100644 index 000000000..a9add1d04 --- /dev/null +++ b/test/data/Choices-all @@ -0,0 +1,113 @@ +http_proxy:0 +http_proxy_host: +http_proxy_port:8080 +http_proxy_auth:0 +http_proxy_auth_user: +http_proxy_auth_pass: +http_proxy_noproxy:localhost +font_size:128 +font_min_size:85 +font_sans:Sans +font_serif:Serif +font_mono:Monospace +font_cursive:Serif +font_fantasy:Serif +accept_language:en +accept_charset: +memory_cache_size:12582912 +disc_cache_size:1073741824 +disc_cache_age:28 +block_advertisements:0 +do_not_track:0 +minimum_gif_delay:10 +send_referer:1 +foreground_images:1 +background_images:1 +animate_images:1 +enable_javascript:1 +script_timeout:10 +expire_url:28 +font_default:0 +ca_bundle: +ca_path:/etc/ssl/certs +cookie_file:/home/vince/.netsurf/Cookies +cookie_jar:/home/vince/.netsurf/Cookies +homepage_url:about:welcome +search_url_bar:0 +search_provider:0 +url_suggestion:1 +window_x:0 +window_y:0 +window_width:0 +window_height:0 +window_screen_width:0 +window_screen_height:0 +toolbar_status_size:6667 +scale:100 +incremental_reflow:1 +min_reflow_period:25 +core_select_menu:1 +display_decoded_idn:0 +max_fetchers:24 +max_fetchers_per_host:5 +max_cached_fetch_handles:6 +max_retried_fetches:1 +curl_fetch_timeout:30 +suppress_curl_debug:1 +target_blank:1 +button_2_tab:1 +margin_top:10 +margin_bottom:10 +margin_left:10 +margin_right:10 +export_scale:70 +suppress_images:0 +remove_backgrounds:0 +enable_loosening:1 +enable_PDF_compression:1 +enable_PDF_password:0 +sys_colour_ActiveBorder:d3d3d3 +sys_colour_ActiveCaption:f1f1f1 +sys_colour_AppWorkspace:f1f1f1 +sys_colour_Background:6e6e6e +sys_colour_ButtonFace:f9f9f9 +sys_colour_ButtonHighlight:ffffff +sys_colour_ButtonShadow:aeaeae +sys_colour_ButtonText:4c4c4c +sys_colour_CaptionText:4c4c4c +sys_colour_GrayText:505050 +sys_colour_Highlight:0008c0 +sys_colour_HighlightText:ffffff +sys_colour_InactiveBorder:f1f1f1 +sys_colour_InactiveCaption:e6e6e6 +sys_colour_InactiveCaptionText:a6a6a6 +sys_colour_InfoBackground:efdf8f +sys_colour_InfoText:000000 +sys_colour_Menu:f1f1f1 +sys_colour_MenuText:4e4e4e +sys_colour_Scrollbar:cccccc +sys_colour_ThreeDDarkShadow:aeaeae +sys_colour_ThreeDFace:f9f9f9 +sys_colour_ThreeDHighlight:ffffff +sys_colour_ThreeDLightShadow:ffffff +sys_colour_ThreeDShadow:d5d5d5 +sys_colour_Window:f1f1f1 +sys_colour_WindowFrame:4e4e4e +sys_colour_WindowText:000000 +render_resample:1 +downloads_clear:0 +request_overwrite:1 +downloads_directory:/home/vince +url_file:/home/vince/.netsurf/URLs +show_single_tab:1 +button_type:1 +disable_popups:0 +disable_plugins:0 +history_age:0 +hover_urls:0 +focus_new:0 +new_blank:0 +hotlist_path:/home/vince/.netsurf/Hotlist +developer_view:0 +position_tab:0 +toolbar_order: diff --git a/test/data/Choices-full b/test/data/Choices-full new file mode 100644 index 000000000..2667a6aa6 --- /dev/null +++ b/test/data/Choices-full @@ -0,0 +1,18 @@ +http_proxy_host:bar +font_sans:Sans +font_serif:Serif +font_mono:Monospace +font_cursive:Serif +font_fantasy:Serif +accept_language:en +enable_javascript:1 +ca_path:/etc/ssl/certs +cookie_file:/home/vince/.netsurf/Cookies +cookie_jar:/home/vince/.netsurf/Cookies +homepage_url:about:welcome +core_select_menu:1 +downloads_directory:/home/vince +url_file:/home/vince/.netsurf/URLs +show_single_tab:1 +button_type:1 +hotlist_path:/home/vince/.netsurf/Hotlist diff --git a/test/data/Choices-short b/test/data/Choices-short new file mode 100644 index 000000000..5d4d5b54e --- /dev/null +++ b/test/data/Choices-short @@ -0,0 +1,17 @@ +font_sans:Sans +font_serif:Serif +font_mono:Monospace +font_cursive:Serif +font_fantasy:Serif +accept_language:en +enable_javascript:1 +ca_path:/etc/ssl/certs +cookie_file:/home/vince/.netsurf/Cookies +cookie_jar:/home/vince/.netsurf/Cookies +homepage_url:about:welcome +core_select_menu:1 +downloads_directory:/home/vince +url_file:/home/vince/.netsurf/URLs +show_single_tab:1 +button_type:1 +hotlist_path:/home/vince/.netsurf/Hotlist diff --git a/test/nsoption.c b/test/nsoption.c index 0f079e9f7..73acbd25a 100644 --- a/test/nsoption.c +++ b/test/nsoption.c @@ -1,88 +1,474 @@ -#include -#include +/* + * Copyright 2016 Vincent Sanders + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file + * Tests for user option processing + */ + +#include #include +#include #include #include -#include +#include +#include #include "utils/errors.h" #include "utils/log.h" #include "utils/nsoption.h" +const char *test_choices_path = "test/data/Choices"; +const char *test_choices_short_path = "test/data/Choices-short"; +const char *test_choices_all_path = "test/data/Choices-all"; +const char *test_choices_full_path = "test/data/Choices-full"; nserror gui_options_init_defaults(struct nsoption_s *defaults) { -#if defined(riscos) /* Set defaults for absent option strings */ nsoption_setnull_charp(ca_bundle, strdup("NetSurf:Resources.ca-bundle")); nsoption_setnull_charp(cookie_file, strdup("NetSurf:Cookies")); - nsoption_setnull_charp(cookie_jar, strdup(CHOICES_PREFIX "Cookies")); + nsoption_setnull_charp(cookie_jar, strdup("Cookies")); if (nsoption_charp(ca_bundle) == NULL || nsoption_charp(cookie_file) == NULL || nsoption_charp(cookie_jar) == NULL) { return NSERROR_BAD_PARAMETER; } -#elif defined(nsgtk) - char *hdir = getenv("HOME"); - char buf[PATH_MAX]; - - /* Set defaults for absent option strings */ - snprintf(buf, PATH_MAX, "%s/.netsurf/Cookies", hdir); - nsoption_setnull_charp(cookie_file, strdup(buf)); - nsoption_setnull_charp(cookie_jar, strdup(buf)); - if (nsoption_charp(cookie_file) == NULL || - nsoption_charp(cookie_jar) == NULL) { - return NSERROR_BAD_PARAMETER; - } - - if (nsoption_charp(downloads_directory) == NULL) { - snprintf(buf, PATH_MAX, "%s/", hdir); - nsoption_set_charp(downloads_directory, strdup(buf)); - } - - if (nsoption_charp(url_file) == NULL) { - snprintf(buf, PATH_MAX, "%s/.netsurf/URLs", hdir); - nsoption_set_charp(url_file, strdup(buf)); - } - - if (nsoption_charp(hotlist_path) == NULL) { - snprintf(buf, PATH_MAX, "%s/.netsurf/Hotlist", hdir); - nsoption_set_charp(hotlist_path, strdup(buf)); - } - - nsoption_setnull_charp(ca_path, strdup("/etc/ssl/certs")); - - if (nsoption_charp(url_file) == NULL || - nsoption_charp(ca_path) == NULL || - nsoption_charp(downloads_directory) == NULL || - nsoption_charp(hotlist_path) == NULL) { - return NSERROR_BAD_PARAMETER; - } - -#endif return NSERROR_OK; } -int main(int argc, char**argv) +/** + * compare two files contents + */ +static int cmp(const char *f1, const char *f2) { + int res = 0; + FILE *fp1; + FILE *fp2; + int ch1; + int ch2; + + fp1 = fopen(f1, "r"); + if (fp1 == NULL) { + return -1; + } + fp2 = fopen(f2, "r"); + if (fp2 == NULL) { + fclose(fp1); + return -1; + } + + while (res == 0) { + ch1 = fgetc(fp1); + ch2 = fgetc(fp2); + + if (ch1 != ch2) { + res = 1; + } + + if (ch1 == EOF) { + break; + } + } + + fclose(fp1); + fclose(fp2); + return res; +} + + +/** + * Test full options session from start to finish + */ +START_TEST(nsoption_session_test) +{ + nserror res; + int argc = 2; + char *argv[] = { "nsoption", "--http_proxy_host=fooo", NULL}; + char *outnam; + + res = nsoption_init(gui_options_init_defaults, NULL, NULL); + ck_assert_int_eq(res, NSERROR_OK); + + /* read from file */ + res = nsoption_read(test_choices_path, NULL); + ck_assert_int_eq(res, NSERROR_OK); + + /* overlay commandline */ + res = nsoption_commandline(&argc, &argv[0], NULL); + ck_assert_int_eq(res, NSERROR_OK); + + /* change an option */ + nsoption_set_charp(http_proxy_host, strdup("bar")); + + /* write options out */ + outnam = tmpnam(NULL); + res = nsoption_write(outnam, NULL, NULL); + ck_assert_int_eq(res, NSERROR_OK); + + /* check for the correct answer */ + ck_assert_int_eq(cmp(outnam, test_choices_full_path), 0); + + unlink(outnam); + + res = nsoption_finalise(NULL, NULL); + ck_assert_int_eq(res, NSERROR_OK); + +} +END_TEST + +TCase *nsoption_session_case_create(void) +{ + TCase *tc; + tc = tcase_create("Full session"); + + tcase_add_test(tc, nsoption_session_test); + + return tc; +} + + +/** + * Test dumping option file + */ +START_TEST(nsoption_dump_test) +{ + nserror res; + char *outnam; FILE *fp; - verbose_log = false; + res = nsoption_read(test_choices_path, NULL); + ck_assert_int_eq(res, NSERROR_OK); - nsoption_init(gui_options_init_defaults, NULL, NULL); - - nsoption_read("test/data/Choices", NULL); - - nsoption_write("Choices-short", NULL, NULL); - - fp = fopen("Choices-all", "w"); - - nsoption_dump(fp, NULL); + outnam = tmpnam(NULL); + fp = fopen(outnam, "w"); + res = nsoption_dump(fp, NULL); fclose(fp); - return 0; + ck_assert_int_eq(res, NSERROR_OK); + + ck_assert_int_eq(cmp(outnam, test_choices_all_path), 0); + + unlink(outnam); +} +END_TEST + +/** + * Test writing option file + */ +START_TEST(nsoption_write_test) +{ + nserror res; + char *outnam; + + res = nsoption_read(test_choices_path, NULL); + ck_assert_int_eq(res, NSERROR_OK); + + outnam = tmpnam(NULL); + + res = nsoption_write(outnam, NULL, NULL); + ck_assert_int_eq(res, NSERROR_OK); + + ck_assert_int_eq(cmp(outnam, test_choices_short_path), 0); + + unlink(outnam); +} +END_TEST + +/** + * Test reading option file + */ +START_TEST(nsoption_read_test) +{ + nserror res; + res = nsoption_read(test_choices_path, NULL); + ck_assert_int_eq(res, NSERROR_OK); + + ck_assert(nsoption_charp(homepage_url) != NULL); + ck_assert_str_eq(nsoption_charp(homepage_url), "about:welcome"); +} +END_TEST + +/** + * Test commandline string value setting + */ +START_TEST(nsoption_commandline_test) +{ + nserror res; + int argc = 2; + char *argv[] = { "nsoption", "--http_proxy_host=fooo", NULL}; + + /* commandline */ + res = nsoption_commandline(&argc, &argv[0], NULL); + ck_assert_int_eq(res, NSERROR_OK); + + ck_assert(nsoption_charp(http_proxy_host) != NULL); + ck_assert_str_eq(nsoption_charp(http_proxy_host), "fooo"); +} +END_TEST + +static void nsoption_create(void) +{ + nserror res; + res = nsoption_init(NULL, NULL, NULL); + ck_assert_int_eq(res, NSERROR_OK); +} + +static void nsoption_teardown(void) +{ + nserror res; + + res = nsoption_finalise(NULL, NULL); + ck_assert_int_eq(res, NSERROR_OK); +} + +TCase *nsoption_case_create(void) +{ + TCase *tc; + tc = tcase_create("File operations"); + + /* ensure options are initialised and finalised for every test */ + tcase_add_unchecked_fixture(tc, + nsoption_create, + nsoption_teardown); + + tcase_add_test(tc, nsoption_commandline_test); + tcase_add_test(tc, nsoption_read_test); + tcase_add_test(tc, nsoption_write_test); + tcase_add_test(tc, nsoption_dump_test); + + return tc; +} + + +/** + * Test finalisation without init + */ +START_TEST(nsoption_api_fini_no_init_test) +{ + nserror res; + + /* attempt to finalise without init */ + res = nsoption_finalise(NULL, NULL); + ck_assert_int_eq(res, NSERROR_BAD_PARAMETER); +} +END_TEST + +/** + * Test read without path + */ +START_TEST(nsoption_api_read_no_path_test) +{ + nserror res; + + /* read with no path or init */ + res = nsoption_read(NULL, NULL); + ck_assert_int_eq(res, NSERROR_BAD_PARAMETER); +} +END_TEST + +/** + * Test read without init + */ +START_TEST(nsoption_api_read_no_init_test) +{ + nserror res; + + /* read with path but no init */ + res = nsoption_read(test_choices_path, NULL); + ck_assert_int_eq(res, NSERROR_BAD_PARAMETER); +} +END_TEST + +/** + * Test write without path + */ +START_TEST(nsoption_api_write_no_path_test) +{ + nserror res; + + /* write with no path or init */ + res = nsoption_write(NULL, NULL, NULL); + ck_assert_int_eq(res, NSERROR_BAD_PARAMETER); +} +END_TEST + +/** + * Test write without init + */ +START_TEST(nsoption_api_write_no_init_test) +{ + nserror res; + + /* write with path but no init */ + res = nsoption_write(test_choices_path, NULL, NULL); + ck_assert_int_eq(res, NSERROR_BAD_PARAMETER); + +} +END_TEST + +/** + * Test dump without path + */ +START_TEST(nsoption_api_dump_no_path_test) +{ + nserror res; + + /* write with no path or init */ + res = nsoption_dump(NULL, NULL); + ck_assert_int_eq(res, NSERROR_BAD_PARAMETER); +} +END_TEST + +/** + * Test dump without init + */ +START_TEST(nsoption_api_dump_no_init_test) +{ + nserror res; + FILE *outf; + + outf = tmpfile(); + ck_assert(outf != NULL); + + /* write with path but no init */ + res = nsoption_dump(outf, NULL); + ck_assert_int_eq(res, NSERROR_BAD_PARAMETER); + + fclose(outf); +} +END_TEST + +/** + * Test commandline without args + */ +START_TEST(nsoption_api_commandline_no_args_test) +{ + nserror res; + int argc = 2; + char *argv[] = { "nsoption", "--http_proxy_host=fooo", NULL}; + + /* commandline with no argument count or init */ + res = nsoption_commandline(NULL, &argv[0], NULL); + ck_assert_int_eq(res, NSERROR_BAD_PARAMETER); + + /* commandline with no argument vector or init */ + res = nsoption_commandline(&argc, NULL, NULL); + ck_assert_int_eq(res, NSERROR_BAD_PARAMETER); +} +END_TEST + +/** + * Test commandline without init + */ +START_TEST(nsoption_api_commandline_no_init_test) +{ + nserror res; + int argc = 2; + char *argv[] = { "nsoption", "--http_proxy_host=fooo", NULL}; + + /* write with path but no init */ + res = nsoption_commandline(&argc, &argv[0], NULL); + ck_assert_int_eq(res, NSERROR_BAD_PARAMETER); +} +END_TEST + + +/** + * Test default initialisation and repeated finalisation + */ +START_TEST(nsoption_api_fini_twice_test) +{ + nserror res; + res = nsoption_init(NULL, NULL, NULL); + ck_assert_int_eq(res, NSERROR_OK); + + res = nsoption_finalise(NULL, NULL); + ck_assert_int_eq(res, NSERROR_OK); + + res = nsoption_finalise(NULL, NULL); + ck_assert_int_eq(res, NSERROR_BAD_PARAMETER); +} +END_TEST + + +/** + * Test default initialisation and finalisation + */ +START_TEST(nsoption_api_init_def_test) +{ + nserror res; + res = nsoption_init(NULL, NULL, NULL); + ck_assert_int_eq(res, NSERROR_OK); + + res = nsoption_finalise(NULL, NULL); + ck_assert_int_eq(res, NSERROR_OK); +} +END_TEST + +TCase *nsoption_api_case_create(void) +{ + TCase *tc; + tc = tcase_create("API checks"); + + tcase_add_test(tc, nsoption_api_fini_no_init_test); + tcase_add_test(tc, nsoption_api_read_no_path_test); + tcase_add_test(tc, nsoption_api_read_no_init_test); + tcase_add_test(tc, nsoption_api_write_no_path_test); + tcase_add_test(tc, nsoption_api_write_no_init_test); + tcase_add_test(tc, nsoption_api_dump_no_path_test); + tcase_add_test(tc, nsoption_api_dump_no_init_test); + tcase_add_test(tc, nsoption_api_commandline_no_args_test); + tcase_add_test(tc, nsoption_api_commandline_no_init_test); + tcase_add_test(tc, nsoption_api_init_def_test); + tcase_add_test(tc, nsoption_api_fini_twice_test); + + return tc; +} + + +Suite *nsoption_suite_create(void) +{ + Suite *s; + s = suite_create("User options"); + + suite_add_tcase(s, nsoption_api_case_create()); + suite_add_tcase(s, nsoption_case_create()); + suite_add_tcase(s, nsoption_session_case_create()); + + return s; +} + +int main(int argc, char **argv) +{ + int number_failed; + SRunner *sr; + + sr = srunner_create(nsoption_suite_create()); + + srunner_run_all(sr, CK_ENV); + + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + + return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/utils/nsoption.c b/utils/nsoption.c index 7e7766622..e4354bf3f 100644 --- a/utils/nsoption.c +++ b/utils/nsoption.c @@ -583,21 +583,32 @@ nsoption_init(nsoption_set_default_t *set_defaults, /* exported interface documented in utils/nsoption.h */ nserror nsoption_finalise(struct nsoption_s *opts, struct nsoption_s *defs) { + nserror res; + /* check to see if global table selected */ if (opts == NULL) { - opts = nsoptions; + res = nsoption_free(nsoptions); + if (res == NSERROR_OK) { + nsoptions = NULL; + } + } else { + res = nsoption_free(opts); + } + if (res != NSERROR_OK) { + return res; } - - nsoption_free(opts); /* check to see if global table selected */ if (defs == NULL) { - defs = nsoptions_default; + res = nsoption_free(nsoptions_default); + if (res == NSERROR_OK) { + nsoptions_default = NULL; + } + } else { + res = nsoption_free(defs); } - nsoption_free(defs); - - return NSERROR_OK; + return res; } @@ -621,6 +632,10 @@ nsoption_read(const char *path, struct nsoption_s *opts) /** @todo is this and API bug not being a parameter */ defs = nsoptions_default; + if ((opts == NULL) || (defs == NULL)) { + return NSERROR_BAD_PARAMETER; + } + fp = fopen(path, "r"); if (!fp) { LOG("Failed to open file '%s'", path); @@ -687,6 +702,10 @@ nsoption_write(const char *path, defs = nsoptions_default; } + if ((opts == NULL) || (defs == NULL)) { + return NSERROR_BAD_PARAMETER; + } + fp = fopen(path, "w"); if (!fp) { LOG("failed to open file '%s' for writing", path); @@ -708,10 +727,13 @@ nsoption_dump(FILE *outf, struct nsoption_s *opts) return NSERROR_BAD_PARAMETER; } - /* check to see if global table selected */ + /* check to see if global table selected and available */ if (opts == NULL) { opts = nsoptions; } + if (opts == NULL) { + return NSERROR_BAD_PARAMETER; + } return nsoption_output(outf, opts, NULL, true); } @@ -728,10 +750,17 @@ nsoption_commandline(int *pargc, char **argv, struct nsoption_s *opts) int mv_loop; unsigned int entry_loop; - /* check to see if global table selected */ + if ((pargc == NULL) || (argv == NULL)) { + return NSERROR_BAD_PARAMETER; + } + + /* check to see if global table selected and available */ if (opts == NULL) { opts = nsoptions; } + if (opts == NULL) { + return NSERROR_BAD_PARAMETER; + } while (idx < *pargc) { arg = argv[idx];