#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, void *oa, const witness_t *b, void *ob) { assert_u_eq(a->rank, b->rank, "Witnesses should have equal rank"); assert(oa == (void *)a); assert(ob == (void *)b); return strcmp(a->name, b->name); } static int witness_comp_reverse(const witness_t *a, void *oa, const witness_t *b, void *ob) { assert_u_eq(a->rank, b->rank, "Witnesses should have equal rank"); assert(oa == (void *)a); assert(ob == (void *)b); return -strcmp(a->name, b->name); } TEST_BEGIN(test_witness) { witness_t a, b; tsdn_t *tsdn; test_skip_if(!config_debug); tsdn = tsdn_fetch(); witness_assert_lockless(tsdn); witness_init(&a, "a", 1, NULL, NULL); witness_assert_not_owner(tsdn, &a); witness_lock(tsdn, &a); witness_assert_owner(tsdn, &a); witness_init(&b, "b", 2, NULL, NULL); witness_assert_not_owner(tsdn, &b); witness_lock(tsdn, &b); witness_assert_owner(tsdn, &b); witness_unlock(tsdn, &a); witness_unlock(tsdn, &b); witness_assert_lockless(tsdn); } TEST_END TEST_BEGIN(test_witness_comp) { witness_t a, b, c, d; tsdn_t *tsdn; test_skip_if(!config_debug); tsdn = tsdn_fetch(); witness_assert_lockless(tsdn); witness_init(&a, "a", 1, witness_comp, &a); witness_assert_not_owner(tsdn, &a); witness_lock(tsdn, &a); witness_assert_owner(tsdn, &a); witness_init(&b, "b", 1, witness_comp, &b); witness_assert_not_owner(tsdn, &b); witness_lock(tsdn, &b); witness_assert_owner(tsdn, &b); witness_unlock(tsdn, &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, &c); witness_assert_not_owner(tsdn, &c); assert_false(saw_lock_error, "Unexpected witness lock error"); witness_lock(tsdn, &c); assert_true(saw_lock_error, "Expected witness lock error"); witness_unlock(tsdn, &c); saw_lock_error = false; witness_init(&d, "d", 1, NULL, NULL); witness_assert_not_owner(tsdn, &d); assert_false(saw_lock_error, "Unexpected witness lock error"); witness_lock(tsdn, &d); assert_true(saw_lock_error, "Expected witness lock error"); witness_unlock(tsdn, &d); witness_unlock(tsdn, &a); witness_assert_lockless(tsdn); witness_lock_error = witness_lock_error_orig; } TEST_END TEST_BEGIN(test_witness_reversal) { witness_t a, b; tsdn_t *tsdn; test_skip_if(!config_debug); witness_lock_error_orig = witness_lock_error; witness_lock_error = witness_lock_error_intercept; saw_lock_error = false; tsdn = tsdn_fetch(); witness_assert_lockless(tsdn); witness_init(&a, "a", 1, NULL, NULL); witness_init(&b, "b", 2, NULL, NULL); witness_lock(tsdn, &b); assert_false(saw_lock_error, "Unexpected witness lock error"); witness_lock(tsdn, &a); assert_true(saw_lock_error, "Expected witness lock error"); witness_unlock(tsdn, &a); witness_unlock(tsdn, &b); witness_assert_lockless(tsdn); witness_lock_error = witness_lock_error_orig; } TEST_END TEST_BEGIN(test_witness_recursive) { witness_t a; tsdn_t *tsdn; 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; tsdn = tsdn_fetch(); witness_assert_lockless(tsdn); witness_init(&a, "a", 1, NULL, NULL); witness_lock(tsdn, &a); assert_false(saw_lock_error, "Unexpected witness lock error"); assert_false(saw_not_owner_error, "Unexpected witness not owner error"); witness_lock(tsdn, &a); assert_true(saw_lock_error, "Expected witness lock error"); assert_true(saw_not_owner_error, "Expected witness not owner error"); witness_unlock(tsdn, &a); witness_assert_lockless(tsdn); 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; tsdn_t *tsdn; test_skip_if(!config_debug); witness_owner_error_orig = witness_owner_error; witness_owner_error = witness_owner_error_intercept; saw_owner_error = false; tsdn = tsdn_fetch(); witness_assert_lockless(tsdn); witness_init(&a, "a", 1, NULL, NULL); assert_false(saw_owner_error, "Unexpected owner error"); witness_unlock(tsdn, &a); assert_true(saw_owner_error, "Expected owner error"); witness_assert_lockless(tsdn); witness_owner_error = witness_owner_error_orig; } TEST_END TEST_BEGIN(test_witness_lockful) { witness_t a; tsdn_t *tsdn; test_skip_if(!config_debug); witness_lockless_error_orig = witness_lockless_error; witness_lockless_error = witness_lockless_error_intercept; saw_lockless_error = false; tsdn = tsdn_fetch(); witness_assert_lockless(tsdn); witness_init(&a, "a", 1, NULL, NULL); assert_false(saw_lockless_error, "Unexpected lockless error"); witness_assert_lockless(tsdn); witness_lock(tsdn, &a); witness_assert_lockless(tsdn); assert_true(saw_lockless_error, "Expected lockless error"); witness_unlock(tsdn, &a); witness_assert_lockless(tsdn); 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); }