diff options
author | Jason Evans <jasone@canonware.com> | 2016-04-13 23:36:15 -0700 |
---|---|---|
committer | Jason Evans <jasone@canonware.com> | 2016-04-14 02:09:28 -0700 |
commit | b2c0d6322d2307458ae2b28545f8a5c9903d7ef5 (patch) | |
tree | 0ab71b856358e4705440ace0661ac4ed9c3e5766 /test | |
parent | 8413463f3a334f14c55589e57d3e82dd594ef479 (diff) | |
download | jemalloc-b2c0d6322d2307458ae2b28545f8a5c9903d7ef5.tar.gz |
Add witness, a simple online locking validator.
This resolves #358.
Diffstat (limited to 'test')
-rw-r--r-- | test/unit/junk.c | 4 | ||||
-rw-r--r-- | test/unit/prof_reset.c | 3 | ||||
-rw-r--r-- | test/unit/witness.c | 278 |
3 files changed, 282 insertions, 3 deletions
diff --git a/test/unit/junk.c b/test/unit/junk.c index fecf6fa..e251a12 100644 --- a/test/unit/junk.c +++ b/test/unit/junk.c @@ -53,10 +53,10 @@ arena_dalloc_junk_large_intercept(void *ptr, size_t usize) } static void -huge_dalloc_junk_intercept(void *ptr, size_t usize) +huge_dalloc_junk_intercept(tsd_t *tsd, void *ptr, size_t usize) { - huge_dalloc_junk_orig(ptr, usize); + huge_dalloc_junk_orig(tsd, ptr, usize); /* * The conditions under which junk filling actually occurs are nuanced * enough that it doesn't make sense to duplicate the decision logic in diff --git a/test/unit/prof_reset.c b/test/unit/prof_reset.c index 69983e5..83f51df 100644 --- a/test/unit/prof_reset.c +++ b/test/unit/prof_reset.c @@ -94,7 +94,8 @@ TEST_END bool prof_dump_header_intercepted = false; prof_cnt_t cnt_all_copy = {0, 0, 0, 0}; static bool -prof_dump_header_intercept(bool propagate_err, const prof_cnt_t *cnt_all) +prof_dump_header_intercept(tsd_t *tsd, bool propagate_err, + const prof_cnt_t *cnt_all) { prof_dump_header_intercepted = true; diff --git a/test/unit/witness.c b/test/unit/witness.c new file mode 100644 index 0000000..430d820 --- /dev/null +++ b/test/unit/witness.c @@ -0,0 +1,278 @@ +#include "test/jemalloc_test.h" + +static witness_lock_error_t *witness_lock_error_orig; +static witness_owner_error_t *witness_owner_error_orig; +static witness_not_owner_error_t *witness_not_owner_error_orig; +static witness_lockless_error_t *witness_lockless_error_orig; + +static bool saw_lock_error; +static bool saw_owner_error; +static bool saw_not_owner_error; +static bool saw_lockless_error; + +static void +witness_lock_error_intercept(const witness_list_t *witnesses, + const witness_t *witness) +{ + + saw_lock_error = true; +} + +static void +witness_owner_error_intercept(const witness_t *witness) +{ + + saw_owner_error = true; +} + +static void +witness_not_owner_error_intercept(const witness_t *witness) +{ + + saw_not_owner_error = true; +} + +static void +witness_lockless_error_intercept(const witness_list_t *witnesses) +{ + + saw_lockless_error = true; +} + +static int +witness_comp(const witness_t *a, const witness_t *b) +{ + + assert_u_eq(a->rank, b->rank, "Witnesses should have equal rank"); + + return (strcmp(a->name, b->name)); +} + +static int +witness_comp_reverse(const witness_t *a, const witness_t *b) +{ + + assert_u_eq(a->rank, b->rank, "Witnesses should have equal rank"); + + return (-strcmp(a->name, b->name)); +} + +TEST_BEGIN(test_witness) +{ + witness_t a, b; + tsd_t *tsd; + + test_skip_if(!config_debug); + + tsd = tsd_fetch(); + + witness_assert_lockless(tsd); + + witness_init(&a, "a", 1, NULL); + witness_assert_not_owner(tsd, &a); + witness_lock(tsd, &a); + witness_assert_owner(tsd, &a); + + witness_init(&b, "b", 2, NULL); + witness_assert_not_owner(tsd, &b); + witness_lock(tsd, &b); + witness_assert_owner(tsd, &b); + + witness_unlock(tsd, &a); + witness_unlock(tsd, &b); + + witness_assert_lockless(tsd); +} +TEST_END + +TEST_BEGIN(test_witness_comp) +{ + witness_t a, b, c, d; + tsd_t *tsd; + + test_skip_if(!config_debug); + + tsd = tsd_fetch(); + + witness_assert_lockless(tsd); + + witness_init(&a, "a", 1, witness_comp); + witness_assert_not_owner(tsd, &a); + witness_lock(tsd, &a); + witness_assert_owner(tsd, &a); + + witness_init(&b, "b", 1, witness_comp); + witness_assert_not_owner(tsd, &b); + witness_lock(tsd, &b); + witness_assert_owner(tsd, &b); + witness_unlock(tsd, &b); + + witness_lock_error_orig = witness_lock_error; + witness_lock_error = witness_lock_error_intercept; + saw_lock_error = false; + + witness_init(&c, "c", 1, witness_comp_reverse); + witness_assert_not_owner(tsd, &c); + assert_false(saw_lock_error, "Unexpected witness lock error"); + witness_lock(tsd, &c); + assert_true(saw_lock_error, "Expected witness lock error"); + witness_unlock(tsd, &c); + + saw_lock_error = false; + + witness_init(&d, "d", 1, NULL); + witness_assert_not_owner(tsd, &d); + assert_false(saw_lock_error, "Unexpected witness lock error"); + witness_lock(tsd, &d); + assert_true(saw_lock_error, "Expected witness lock error"); + witness_unlock(tsd, &d); + + witness_unlock(tsd, &a); + + witness_assert_lockless(tsd); + + witness_lock_error = witness_lock_error_orig; +} +TEST_END + +TEST_BEGIN(test_witness_reversal) +{ + witness_t a, b; + tsd_t *tsd; + + test_skip_if(!config_debug); + + witness_lock_error_orig = witness_lock_error; + witness_lock_error = witness_lock_error_intercept; + saw_lock_error = false; + + tsd = tsd_fetch(); + + witness_assert_lockless(tsd); + + witness_init(&a, "a", 1, NULL); + witness_init(&b, "b", 2, NULL); + + witness_lock(tsd, &b); + assert_false(saw_lock_error, "Unexpected witness lock error"); + witness_lock(tsd, &a); + assert_true(saw_lock_error, "Expected witness lock error"); + + witness_unlock(tsd, &a); + witness_unlock(tsd, &b); + + witness_assert_lockless(tsd); + + witness_lock_error = witness_lock_error_orig; +} +TEST_END + +TEST_BEGIN(test_witness_recursive) +{ + witness_t a; + tsd_t *tsd; + + test_skip_if(!config_debug); + + witness_not_owner_error_orig = witness_not_owner_error; + witness_not_owner_error = witness_not_owner_error_intercept; + saw_not_owner_error = false; + + witness_lock_error_orig = witness_lock_error; + witness_lock_error = witness_lock_error_intercept; + saw_lock_error = false; + + tsd = tsd_fetch(); + + witness_assert_lockless(tsd); + + witness_init(&a, "a", 1, NULL); + + witness_lock(tsd, &a); + assert_false(saw_lock_error, "Unexpected witness lock error"); + assert_false(saw_not_owner_error, "Unexpected witness not owner error"); + witness_lock(tsd, &a); + assert_true(saw_lock_error, "Expected witness lock error"); + assert_true(saw_not_owner_error, "Expected witness not owner error"); + + witness_unlock(tsd, &a); + + witness_assert_lockless(tsd); + + witness_owner_error = witness_owner_error_orig; + witness_lock_error = witness_lock_error_orig; + +} +TEST_END + +TEST_BEGIN(test_witness_unlock_not_owned) +{ + witness_t a; + tsd_t *tsd; + + test_skip_if(!config_debug); + + witness_owner_error_orig = witness_owner_error; + witness_owner_error = witness_owner_error_intercept; + saw_owner_error = false; + + tsd = tsd_fetch(); + + witness_assert_lockless(tsd); + + witness_init(&a, "a", 1, NULL); + + assert_false(saw_owner_error, "Unexpected owner error"); + witness_unlock(tsd, &a); + assert_true(saw_owner_error, "Expected owner error"); + + witness_assert_lockless(tsd); + + witness_owner_error = witness_owner_error_orig; +} +TEST_END + +TEST_BEGIN(test_witness_lockful) +{ + witness_t a; + tsd_t *tsd; + + test_skip_if(!config_debug); + + witness_lockless_error_orig = witness_lockless_error; + witness_lockless_error = witness_lockless_error_intercept; + saw_lockless_error = false; + + tsd = tsd_fetch(); + + witness_assert_lockless(tsd); + + witness_init(&a, "a", 1, NULL); + + assert_false(saw_lockless_error, "Unexpected lockless error"); + witness_assert_lockless(tsd); + + witness_lock(tsd, &a); + witness_assert_lockless(tsd); + assert_true(saw_lockless_error, "Expected lockless error"); + + witness_unlock(tsd, &a); + + witness_assert_lockless(tsd); + + witness_lockless_error = witness_lockless_error_orig; +} +TEST_END + +int +main(void) +{ + + return (test( + test_witness, + test_witness_comp, + test_witness_reversal, + test_witness_recursive, + test_witness_unlock_not_owned, + test_witness_lockful)); +} |