diff options
author | Daniel Silverstone <dsilvers@netsurf-browser.org> | 2009-02-14 17:12:25 +0000 |
---|---|---|
committer | Daniel Silverstone <dsilvers@netsurf-browser.org> | 2009-02-14 17:12:25 +0000 |
commit | df34246db5414c223618bb2107e94565ff444a84 (patch) | |
tree | e864ba1b9fc83da4e349b36029af8eb80ce798ef | |
parent | 41124cff3e5e20f7b7542bdfec653ef8e852c306 (diff) | |
download | libwapcaplet-df34246db5414c223618bb2107e94565ff444a84.tar.gz |
More tests, some fixes. All the API appears to work
svn path=/trunk/libwapcaplet/; revision=6503
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | src/libwapcaplet.c | 57 | ||||
-rw-r--r-- | test/basictests.c | 417 |
3 files changed, 447 insertions, 29 deletions
@@ -21,7 +21,7 @@ CFLAGS := -Iinclude -Wall -Werror ifeq ($(TARGET),debug) CFLAGS += -O0 -g else -CFLAGS += -O2 +CFLAGS += -O2 -DNDEBUG endif diff --git a/src/libwapcaplet.c b/src/libwapcaplet.c index cc80627..7b9817a 100644 --- a/src/libwapcaplet.c +++ b/src/libwapcaplet.c @@ -30,29 +30,6 @@ lwc_calculate_hash(const char *str, size_t len) return z; } -static inline char -dolower(const char c) -{ - if (c >= 'A' && c <= 'Z') - return c + 'a' - 'A'; - return c; -} - -static inline lwc_hash -lwc_calculate_lcase_hash(const char *str, size_t len) -{ - lwc_hash z = 0x811c9dc5; - - - while (len > 0) { - z *= 0x01000193; - z ^= dolower(*str++); - len--; - } - - return z; -} - struct lwc_string_s { lwc_string ** prevptr; lwc_string * next; @@ -161,7 +138,7 @@ __lwc_context_intern(lwc_context *ctx, while (str != NULL) { if ((str->hash == h) && (str->len == slen)) { - if (compare(s, CSTR_OF(str), slen) == 0) { + if (compare(CSTR_OF(str), s, slen) == 0) { str->refcnt++; *ret = str; return lwc_error_ok; @@ -177,7 +154,8 @@ __lwc_context_intern(lwc_context *ctx, str->prevptr = &(ctx->buckets[bucket]); str->next = ctx->buckets[bucket]; - ctx->buckets[bucket]->prevptr = &(str->next); + if (str->next != NULL) + str->next->prevptr = &(str->next); ctx->buckets[bucket] = str; str->len = slen; @@ -239,7 +217,9 @@ lwc_context_string_unref(lwc_context *ctx, lwc_string *str) return; *(str->prevptr) = str->next; - str->next->prevptr = str->prevptr; + + if (str->next != NULL) + str->next->prevptr = str->prevptr; if (str->insensitive != NULL) lwc_context_string_unref(ctx, str->insensitive); @@ -247,6 +227,31 @@ lwc_context_string_unref(lwc_context *ctx, lwc_string *str) LWC_FREE(str); } +/**** Shonky caseless bits ****/ + +static inline char +dolower(const char c) +{ + if (c >= 'A' && c <= 'Z') + return c + 'a' - 'A'; + return c; +} + +static inline lwc_hash +lwc_calculate_lcase_hash(const char *str, size_t len) +{ + lwc_hash z = 0x811c9dc5; + + + while (len > 0) { + z *= 0x01000193; + z ^= dolower(*str++); + len--; + } + + return z; +} + static int lwc_lcase_strcmp(const char *s1, const char *s2, size_t n) { diff --git a/test/basictests.c b/test/basictests.c index 1e0a828..ee7c2cb 100644 --- a/test/basictests.c +++ b/test/basictests.c @@ -11,7 +11,17 @@ #include "tests.h" -START_TEST (test_lwc_context_creation_bad_alloc) +static void *last_pw = NULL; +static void * +trivial_alloc_fn(void *p, size_t s, void *pw) +{ + last_pw = pw; + return realloc(p, s); +} + +#ifndef NDEBUG +/* All the basic assert() tests */ +START_TEST (test_lwc_context_creation_bad_alloc_aborts) { lwc_context *ctx = NULL; lwc_error err; @@ -20,7 +30,336 @@ START_TEST (test_lwc_context_creation_bad_alloc) } END_TEST +START_TEST (test_lwc_context_destruction_aborts) +{ + lwc_context_unref(NULL); +} +END_TEST + +START_TEST (test_lwc_context_ref_aborts) +{ + lwc_context_ref(NULL); +} +END_TEST + +START_TEST (test_lwc_context_unref_aborts) +{ + lwc_context_unref(NULL); +} +END_TEST + +START_TEST (test_lwc_context_intern_aborts1) +{ + lwc_context_intern(NULL, NULL, 0, NULL); +} +END_TEST + +START_TEST (test_lwc_context_intern_aborts2) +{ + lwc_context *ctx; + + fail_unless(lwc_create_context(trivial_alloc_fn, NULL, &ctx) == lwc_error_ok, + "Unable to create context"); + + lwc_context_intern(ctx, NULL, 0, NULL); +} +END_TEST + +START_TEST (test_lwc_context_intern_aborts3) +{ + lwc_context *ctx; + + fail_unless(lwc_create_context(trivial_alloc_fn, NULL, &ctx) == lwc_error_ok, + "Unable to create context"); + + lwc_context_intern(ctx, "A", 1, NULL); +} +END_TEST + +START_TEST (test_lwc_context_intern_substring_aborts1) +{ + lwc_context_intern_substring(NULL, NULL, 0, 0, NULL); +} +END_TEST + +START_TEST (test_lwc_context_intern_substring_aborts2) +{ + lwc_context *ctx; + fail_unless(lwc_create_context(trivial_alloc_fn, NULL, &ctx) == lwc_error_ok, + "Unable to create context"); + + lwc_context_intern_substring(ctx, NULL, 0, 0, NULL); +} +END_TEST + +START_TEST (test_lwc_context_intern_substring_aborts3) +{ + lwc_context *ctx; + lwc_string *str; + fail_unless(lwc_create_context(trivial_alloc_fn, NULL, &ctx) == lwc_error_ok, + "Unable to create context"); + fail_unless(lwc_context_intern(ctx, "Jam", 3, &str) == lwc_error_ok, + "unable to intern 'Jam'"); + + lwc_context_intern_substring(ctx, str, 100, 1, NULL); +} +END_TEST + +START_TEST (test_lwc_context_intern_substring_aborts4) +{ + lwc_context *ctx; + lwc_string *str; + fail_unless(lwc_create_context(trivial_alloc_fn, NULL, &ctx) == lwc_error_ok, + "Unable to create context"); + fail_unless(lwc_context_intern(ctx, "Jam", 3, &str) == lwc_error_ok, + "unable to intern 'Jam'"); + + lwc_context_intern_substring(ctx, str, 1, 10, NULL); +} +END_TEST + +START_TEST (test_lwc_context_intern_substring_aborts5) +{ + lwc_context *ctx; + lwc_string *str; + fail_unless(lwc_create_context(trivial_alloc_fn, NULL, &ctx) == lwc_error_ok, + "Unable to create context"); + fail_unless(lwc_context_intern(ctx, "Jam", 3, &str) == lwc_error_ok, + "unable to intern 'Jam'"); + + lwc_context_intern_substring(ctx, str, 1, 2, NULL); +} +END_TEST + +START_TEST (test_lwc_context_string_ref_aborts1) +{ + lwc_context_string_ref(NULL, NULL); +} +END_TEST + +START_TEST (test_lwc_context_string_ref_aborts2) +{ + lwc_context *ctx; + fail_unless(lwc_create_context(trivial_alloc_fn, NULL, &ctx) == lwc_error_ok, + "Unable to create context"); + lwc_context_string_ref(ctx, NULL); +} +END_TEST + +START_TEST (test_lwc_context_string_unref_aborts1) +{ + lwc_context_string_unref(NULL, NULL); +} +END_TEST + +START_TEST (test_lwc_context_string_unref_aborts2) +{ + lwc_context *ctx; + fail_unless(lwc_create_context(trivial_alloc_fn, NULL, &ctx) == lwc_error_ok, + "Unable to create context"); + lwc_context_string_unref(ctx, NULL); +} +END_TEST + +#endif + +START_TEST (test_lwc_context_creation_ok) +{ + lwc_context *ctx = NULL; + lwc_error err; + + err = lwc_create_context(trivial_alloc_fn, NULL, &ctx); + fail_unless(ctx != NULL, + "Unable to create context"); + fail_unless(err == lwc_error_ok, + "Created context but returned !ok"); +} +END_TEST + +START_TEST (test_lwc_context_destruction_ok) +{ + lwc_context *ctx = NULL; + + fail_unless(lwc_create_context(trivial_alloc_fn, NULL, &ctx) == lwc_error_ok, + "Unable to create context"); + + lwc_context_unref(ctx); +} +END_TEST + +START_TEST (test_lwc_reffed_context_destruction_ok) +{ + lwc_context *ctx = NULL; + + fail_unless(lwc_create_context(trivial_alloc_fn, NULL, &ctx) == lwc_error_ok, + "Unable to create context"); + + lwc_context_ref(ctx); /* make the weak ref strong */ + + lwc_context_unref(ctx); +} +END_TEST + +/**** The next set of tests need a fixture set ****/ + +static lwc_context *shared_ctx; + +static void +with_simple_context_setup(void) +{ + fail_unless(lwc_create_context(trivial_alloc_fn, NULL, + &shared_ctx) == lwc_error_ok, + "Unable to create context"); + lwc_context_ref(shared_ctx); +} + +static void +with_simple_context_teardown(void) +{ + lwc_context_unref(shared_ctx); +} + +START_TEST (test_lwc_context_intern_ok) +{ + lwc_string *str = NULL; + fail_unless(lwc_context_intern(shared_ctx, "A", 1, &str) == lwc_error_ok, + "Unable to intern a simple string"); + fail_unless(str != NULL, + "Returned OK but str was still NULL"); +} +END_TEST + +START_TEST (test_lwc_context_intern_twice_ok) +{ + lwc_string *str1 = NULL, *str2 = NULL; + fail_unless(lwc_context_intern(shared_ctx, "A", 1, &str1) == lwc_error_ok, + "Unable to intern a simple string"); + fail_unless(str1 != NULL, + "Returned OK but str was still NULL"); + fail_unless(lwc_context_intern(shared_ctx, "B", 1, &str2) == lwc_error_ok, + "Unable to intern a simple string"); + fail_unless(str2 != NULL, + "Returned OK but str was still NULL"); +} +END_TEST + +START_TEST (test_lwc_context_intern_twice_same_ok) +{ + lwc_string *str1 = NULL, *str2 = NULL; + fail_unless(lwc_context_intern(shared_ctx, "A", 1, &str1) == lwc_error_ok, + "Unable to intern a simple string"); + fail_unless(str1 != NULL, + "Returned OK but str was still NULL"); + fail_unless(lwc_context_intern(shared_ctx, "A", 1, &str2) == lwc_error_ok, + "Unable to intern a simple string"); + fail_unless(str2 != NULL, + "Returned OK but str was still NULL"); +} +END_TEST + +/**** The next set of tests need a fixture set with some strings ****/ + +static lwc_string *intern_one = NULL, *intern_two = NULL, *intern_three = NULL; + +static void +with_filled_context_setup(void) +{ + fail_unless(lwc_create_context(trivial_alloc_fn, NULL, + &shared_ctx) == lwc_error_ok, + "Unable to create context"); + lwc_context_ref(shared_ctx); + + fail_unless(lwc_context_intern(shared_ctx, "one", 3, &intern_one) == lwc_error_ok, + "Unable to intern 'one'"); + fail_unless(lwc_context_intern(shared_ctx, "two", 3, &intern_two) == lwc_error_ok, + "Unable to intern 'one'"); + fail_unless(lwc_context_intern(shared_ctx, "three", 5, &intern_three) == lwc_error_ok, + "Unable to intern 'one'"); + + fail_unless(intern_one != intern_two, "'one' == 'two'"); + fail_unless(intern_one != intern_three, "'one' == 'three'"); + fail_unless(intern_two != intern_three, "'two' == 'three'"); +} + +static void +with_filled_context_teardown(void) +{ + lwc_context_unref(shared_ctx); +} + +START_TEST (test_lwc_interning_works) +{ + lwc_string *new_one = NULL; + + fail_unless(lwc_context_intern(shared_ctx, "one", 3, &new_one) == lwc_error_ok, + "Unable to re-intern 'one'"); + + fail_unless(new_one == intern_one, + "Internalising of the string failed"); +} +END_TEST + +START_TEST (test_lwc_intern_substring) +{ + lwc_string *new_hre = NULL, *sub_hre = NULL; + + fail_unless(lwc_context_intern(shared_ctx, "hre", 3, + &new_hre) == lwc_error_ok, + "Unable to intern 'hre'"); + fail_unless(lwc_context_intern_substring(shared_ctx, intern_three, + 1, 3, &sub_hre) == lwc_error_ok, + "Unable to re-intern 'hre' by substring"); + fail_unless(new_hre == sub_hre, + "'hre' != 'hre' -- wow!"); +} +END_TEST + +START_TEST (test_lwc_context_string_ref_ok) +{ + fail_unless(lwc_context_string_ref(shared_ctx, intern_one) == intern_one, + "Oddly, reffing a string didn't return it"); +} +END_TEST + +START_TEST (test_lwc_context_string_unref_ok) +{ + lwc_context_string_unref(shared_ctx, intern_one); +} +END_TEST + +START_TEST (test_lwc_context_string_isequal_ok) +{ + bool result = true; + fail_unless((lwc_context_string_isequal(shared_ctx, intern_one, + intern_two, &result)) == lwc_error_ok, + "Failure comparing 'one' and 'two'"); + fail_unless(result == false, + "'one' == 'two' ?!"); +} +END_TEST + +START_TEST (test_lwc_context_string_caseless_isequal_ok) +{ + bool result = true; + lwc_string *new_ONE; + + fail_unless(lwc_context_intern(shared_ctx, "ONE", 3, &new_ONE) == lwc_error_ok, + "Failure interning 'ONE'"); + + fail_unless((lwc_context_string_isequal(shared_ctx, intern_one, new_ONE, + &result)) == lwc_error_ok); + fail_unless(result == false, + "'one' == 'ONE' ?!"); + + fail_unless((lwc_context_string_caseless_isequal(shared_ctx, intern_one, + new_ONE, &result)) == lwc_error_ok, + "Failure comparing 'one' and 'two'"); + fail_unless(result == true, + "'one' !~= 'ONE' ?!"); +} +END_TEST +/**** And the suites are set up here ****/ void lwc_basic_suite(SRunner *sr) @@ -28,8 +367,82 @@ lwc_basic_suite(SRunner *sr) Suite *s = suite_create("libwapcaplet: Basic tests"); TCase *tc_basic = tcase_create("Creation/Destruction"); - tcase_add_test_raise_signal(tc_basic, test_lwc_context_creation_bad_alloc, SIGABRT); +#ifndef NDEBUG + tcase_add_test_raise_signal(tc_basic, + test_lwc_context_creation_bad_alloc_aborts, + SIGABRT); + tcase_add_test_raise_signal(tc_basic, + test_lwc_context_destruction_aborts, + SIGABRT); + tcase_add_test_raise_signal(tc_basic, + test_lwc_context_ref_aborts, + SIGABRT); + tcase_add_test_raise_signal(tc_basic, + test_lwc_context_unref_aborts, + SIGABRT); + tcase_add_test_raise_signal(tc_basic, + test_lwc_context_intern_aborts1, + SIGABRT); + tcase_add_test_raise_signal(tc_basic, + test_lwc_context_intern_aborts2, + SIGABRT); + tcase_add_test_raise_signal(tc_basic, + test_lwc_context_intern_aborts3, + SIGABRT); + tcase_add_test_raise_signal(tc_basic, + test_lwc_context_intern_substring_aborts1, + SIGABRT); + tcase_add_test_raise_signal(tc_basic, + test_lwc_context_intern_substring_aborts2, + SIGABRT); + tcase_add_test_raise_signal(tc_basic, + test_lwc_context_intern_substring_aborts3, + SIGABRT); + tcase_add_test_raise_signal(tc_basic, + test_lwc_context_intern_substring_aborts4, + SIGABRT); + tcase_add_test_raise_signal(tc_basic, + test_lwc_context_intern_substring_aborts5, + SIGABRT); + tcase_add_test_raise_signal(tc_basic, + test_lwc_context_string_ref_aborts1, + SIGABRT); + tcase_add_test_raise_signal(tc_basic, + test_lwc_context_string_ref_aborts2, + SIGABRT); + tcase_add_test_raise_signal(tc_basic, + test_lwc_context_string_unref_aborts1, + SIGABRT); + tcase_add_test_raise_signal(tc_basic, + test_lwc_context_string_unref_aborts2, + SIGABRT); +#endif + + tcase_add_test(tc_basic, test_lwc_context_creation_ok); + tcase_add_test(tc_basic, test_lwc_context_destruction_ok); + tcase_add_test(tc_basic, test_lwc_reffed_context_destruction_ok); + suite_add_tcase(s, tc_basic); + + tc_basic = tcase_create("Ops with a context"); + tcase_add_checked_fixture(tc_basic, with_simple_context_setup, + with_simple_context_teardown); + tcase_add_test(tc_basic, test_lwc_context_intern_ok); + tcase_add_test(tc_basic, test_lwc_context_intern_twice_ok); + tcase_add_test(tc_basic, test_lwc_context_intern_twice_same_ok); suite_add_tcase(s, tc_basic); + + tc_basic = tcase_create("Ops with a filled context"); + + tcase_add_checked_fixture(tc_basic, with_filled_context_setup, + with_filled_context_teardown); + tcase_add_test(tc_basic, test_lwc_interning_works); + tcase_add_test(tc_basic, test_lwc_intern_substring); + tcase_add_test(tc_basic, test_lwc_context_string_ref_ok); + tcase_add_test(tc_basic, test_lwc_context_string_unref_ok); + tcase_add_test(tc_basic, test_lwc_context_string_isequal_ok); + tcase_add_test(tc_basic, test_lwc_context_string_caseless_isequal_ok); + suite_add_tcase(s, tc_basic); + srunner_add_suite(sr, s); } |