Add ability to exclude mutex from tests

We need to be able to exclude mbedtls_test_info_mutex() from the normal
tests, as this mutex has to be locked to report mutex errors, and also
reports as leaked, due to where it is initialised / free'd.

Signed-off-by: Paul Elliott <paul.elliott@arm.com>
This commit is contained in:
Paul Elliott 2024-01-09 17:20:58 +00:00
parent 65064265c2
commit 0710ac4ec8

View File

@ -117,40 +117,62 @@ static void mbedtls_test_mutex_usage_error(mbedtls_threading_mutex_t *mutex,
* mbedtls_test_mutex_usage_check() will mark it as failed. */ * mbedtls_test_mutex_usage_check() will mark it as failed. */
} }
extern mbedtls_threading_mutex_t mbedtls_test_info_mutex;
static int mbedtls_test_mutex_can_test(mbedtls_threading_mutex_t *mutex)
{
/* If we attempt to run tests on this mutex then we are going to run into a
* couple of problems:
* 1. If any test on this mutex fails, we are going to deadlock when
* reporting that failure, as we already hold the mutex at that point.
* 2. Given the 'global' position of the initialization and free of this
* mutex, it will be shown as leaked on the first test run. */
if (mutex == &mbedtls_test_info_mutex) {
return 0;
}
return 1;
}
static void mbedtls_test_wrap_mutex_init(mbedtls_threading_mutex_t *mutex) static void mbedtls_test_wrap_mutex_init(mbedtls_threading_mutex_t *mutex)
{ {
mutex_functions.init(mutex); mutex_functions.init(mutex);
if (mutex_functions.lock(&mbedtls_test_mutex_mutex) == 0) { if (mbedtls_test_mutex_can_test(mutex)) {
mutex->state = MUTEX_IDLE; if (mutex_functions.lock(&mbedtls_test_mutex_mutex) == 0) {
++live_mutexes; mutex->state = MUTEX_IDLE;
++live_mutexes;
mutex_functions.unlock(&mbedtls_test_mutex_mutex); mutex_functions.unlock(&mbedtls_test_mutex_mutex);
}
} }
} }
static void mbedtls_test_wrap_mutex_free(mbedtls_threading_mutex_t *mutex) static void mbedtls_test_wrap_mutex_free(mbedtls_threading_mutex_t *mutex)
{ {
if (mutex_functions.lock(&mbedtls_test_mutex_mutex) == 0) { if (mbedtls_test_mutex_can_test(mutex)) {
if (mutex_functions.lock(&mbedtls_test_mutex_mutex) == 0) {
switch (mutex->state) { switch (mutex->state) {
case MUTEX_FREED: case MUTEX_FREED:
mbedtls_test_mutex_usage_error(mutex, "free without init or double free"); mbedtls_test_mutex_usage_error(mutex, "free without init or double free");
break; break;
case MUTEX_IDLE: case MUTEX_IDLE:
mutex->state = MUTEX_FREED; mutex->state = MUTEX_FREED;
--live_mutexes; --live_mutexes;
break; break;
case MUTEX_LOCKED: case MUTEX_LOCKED:
mbedtls_test_mutex_usage_error(mutex, "free without unlock"); mbedtls_test_mutex_usage_error(mutex, "free without unlock");
break; break;
default: default:
mbedtls_test_mutex_usage_error(mutex, "corrupted state"); mbedtls_test_mutex_usage_error(mutex, "corrupted state");
break; break;
}
mutex_functions.unlock(&mbedtls_test_mutex_mutex);
} }
mutex_functions.unlock(&mbedtls_test_mutex_mutex);
} }
mutex_functions.free(mutex); mutex_functions.free(mutex);
} }
@ -160,26 +182,30 @@ static int mbedtls_test_wrap_mutex_lock(mbedtls_threading_mutex_t *mutex)
* is to hold the passed in and internal mutex - otherwise we create a race * is to hold the passed in and internal mutex - otherwise we create a race
* condition. */ * condition. */
int ret = mutex_functions.lock(mutex); int ret = mutex_functions.lock(mutex);
if (mutex_functions.lock(&mbedtls_test_mutex_mutex) == 0) {
switch (mutex->state) {
case MUTEX_FREED:
mbedtls_test_mutex_usage_error(mutex, "lock without init");
break;
case MUTEX_IDLE:
if (ret == 0) {
mutex->state = MUTEX_LOCKED;
}
break;
case MUTEX_LOCKED:
mbedtls_test_mutex_usage_error(mutex, "double lock");
break;
default:
mbedtls_test_mutex_usage_error(mutex, "corrupted state");
break;
}
mutex_functions.unlock(&mbedtls_test_mutex_mutex); if (mbedtls_test_mutex_can_test(mutex)) {
if (mutex_functions.lock(&mbedtls_test_mutex_mutex) == 0) {
switch (mutex->state) {
case MUTEX_FREED:
mbedtls_test_mutex_usage_error(mutex, "lock without init");
break;
case MUTEX_IDLE:
if (ret == 0) {
mutex->state = MUTEX_LOCKED;
}
break;
case MUTEX_LOCKED:
mbedtls_test_mutex_usage_error(mutex, "double lock");
break;
default:
mbedtls_test_mutex_usage_error(mutex, "corrupted state");
break;
}
mutex_functions.unlock(&mbedtls_test_mutex_mutex);
}
} }
return ret; return ret;
} }
@ -188,23 +214,26 @@ static int mbedtls_test_wrap_mutex_unlock(mbedtls_threading_mutex_t *mutex)
/* Lock the internal mutex first and change state, so that the only way to /* Lock the internal mutex first and change state, so that the only way to
* change the state is to hold the passed in and internal mutex - otherwise * change the state is to hold the passed in and internal mutex - otherwise
* we create a race condition. */ * we create a race condition. */
if (mutex_functions.lock(&mbedtls_test_mutex_mutex) == 0) { if (mbedtls_test_mutex_can_test(mutex)) {
switch (mutex->state) { if (mutex_functions.lock(&mbedtls_test_mutex_mutex) == 0) {
case MUTEX_FREED: switch (mutex->state) {
mbedtls_test_mutex_usage_error(mutex, "unlock without init"); case MUTEX_FREED:
break; mbedtls_test_mutex_usage_error(mutex, "unlock without init");
case MUTEX_IDLE: break;
mbedtls_test_mutex_usage_error(mutex, "unlock without lock"); case MUTEX_IDLE:
break; mbedtls_test_mutex_usage_error(mutex, "unlock without lock");
case MUTEX_LOCKED: break;
mutex->state = MUTEX_IDLE; case MUTEX_LOCKED:
break; mutex->state = MUTEX_IDLE;
default: break;
mbedtls_test_mutex_usage_error(mutex, "corrupted state"); default:
break; mbedtls_test_mutex_usage_error(mutex, "corrupted state");
break;
}
mutex_functions.unlock(&mbedtls_test_mutex_mutex);
} }
mutex_functions.unlock(&mbedtls_test_mutex_mutex);
} }
return mutex_functions.unlock(mutex); return mutex_functions.unlock(mutex);
} }