Basic unit test for condition variables.
This commit is contained in:
parent
e47a90a976
commit
7a63005220
|
@ -437,7 +437,7 @@ AC_CHECK_FUNCS(
|
|||
sysconf \
|
||||
sysctl \
|
||||
uname \
|
||||
usleep \
|
||||
usleep \
|
||||
vasprintf \
|
||||
_vscprintf
|
||||
)
|
||||
|
|
|
@ -1258,6 +1258,24 @@ test_stats(void *arg)
|
|||
tor_free(s);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
passthrough_test_setup(const struct testcase_t *testcase)
|
||||
{
|
||||
return testcase->setup_data;
|
||||
}
|
||||
static int
|
||||
passthrough_test_cleanup(const struct testcase_t *testcase, void *ptr)
|
||||
{
|
||||
(void)testcase;
|
||||
(void)ptr;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const struct testcase_setup_t passthrough_setup = {
|
||||
passthrough_test_setup, passthrough_test_cleanup
|
||||
};
|
||||
|
||||
#define ENT(name) \
|
||||
{ #name, test_ ## name , 0, NULL, NULL }
|
||||
#define FORK(name) \
|
||||
|
|
|
@ -158,5 +158,7 @@ crypto_pk_t *pk_generate(int idx);
|
|||
#define NS_MOCK(name) MOCK(name, NS(name))
|
||||
#define NS_UNMOCK(name) UNMOCK(name)
|
||||
|
||||
extern const struct testcase_setup_t passthrough_setup;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1975,30 +1975,14 @@ test_crypto_siphash(void *arg)
|
|||
;
|
||||
}
|
||||
|
||||
static void *
|
||||
pass_data_setup_fn(const struct testcase_t *testcase)
|
||||
{
|
||||
return testcase->setup_data;
|
||||
}
|
||||
static int
|
||||
pass_data_cleanup_fn(const struct testcase_t *testcase, void *ptr)
|
||||
{
|
||||
(void)ptr;
|
||||
(void)testcase;
|
||||
return 1;
|
||||
}
|
||||
static const struct testcase_setup_t pass_data = {
|
||||
pass_data_setup_fn, pass_data_cleanup_fn
|
||||
};
|
||||
|
||||
#define CRYPTO_LEGACY(name) \
|
||||
{ #name, test_crypto_ ## name , 0, NULL, NULL }
|
||||
|
||||
struct testcase_t crypto_tests[] = {
|
||||
CRYPTO_LEGACY(formats),
|
||||
CRYPTO_LEGACY(rng),
|
||||
{ "aes_AES", test_crypto_aes, TT_FORK, &pass_data, (void*)"aes" },
|
||||
{ "aes_EVP", test_crypto_aes, TT_FORK, &pass_data, (void*)"evp" },
|
||||
{ "aes_AES", test_crypto_aes, TT_FORK, &passthrough_setup, (void*)"aes" },
|
||||
{ "aes_EVP", test_crypto_aes, TT_FORK, &passthrough_setup, (void*)"evp" },
|
||||
CRYPTO_LEGACY(sha),
|
||||
CRYPTO_LEGACY(pk),
|
||||
{ "pk_fingerprints", test_crypto_pk_fingerprints, TT_FORK, NULL, NULL },
|
||||
|
@ -2006,23 +1990,25 @@ struct testcase_t crypto_tests[] = {
|
|||
CRYPTO_LEGACY(dh),
|
||||
CRYPTO_LEGACY(s2k_rfc2440),
|
||||
#ifdef HAVE_LIBSCRYPT_H
|
||||
{ "s2k_scrypt", test_crypto_s2k_general, 0, &pass_data,
|
||||
{ "s2k_scrypt", test_crypto_s2k_general, 0, &passthrough_setup,
|
||||
(void*)"scrypt" },
|
||||
{ "s2k_scrypt_low", test_crypto_s2k_general, 0, &pass_data,
|
||||
{ "s2k_scrypt_low", test_crypto_s2k_general, 0, &passthrough_setup,
|
||||
(void*)"scrypt-low" },
|
||||
#endif
|
||||
{ "s2k_pbkdf2", test_crypto_s2k_general, 0, &pass_data,
|
||||
{ "s2k_pbkdf2", test_crypto_s2k_general, 0, &passthrough_setup,
|
||||
(void*)"pbkdf2" },
|
||||
{ "s2k_rfc2440_general", test_crypto_s2k_general, 0, &pass_data,
|
||||
{ "s2k_rfc2440_general", test_crypto_s2k_general, 0, &passthrough_setup,
|
||||
(void*)"rfc2440" },
|
||||
{ "s2k_rfc2440_legacy", test_crypto_s2k_general, 0, &pass_data,
|
||||
{ "s2k_rfc2440_legacy", test_crypto_s2k_general, 0, &passthrough_setup,
|
||||
(void*)"rfc2440-legacy" },
|
||||
{ "s2k_errors", test_crypto_s2k_errors, 0, NULL, NULL },
|
||||
{ "scrypt_vectors", test_crypto_scrypt_vectors, 0, NULL, NULL },
|
||||
{ "pbkdf2_vectors", test_crypto_pbkdf2_vectors, 0, NULL, NULL },
|
||||
{ "pwbox", test_crypto_pwbox, 0, NULL, NULL },
|
||||
{ "aes_iv_AES", test_crypto_aes_iv, TT_FORK, &pass_data, (void*)"aes" },
|
||||
{ "aes_iv_EVP", test_crypto_aes_iv, TT_FORK, &pass_data, (void*)"evp" },
|
||||
{ "aes_iv_AES", test_crypto_aes_iv, TT_FORK, &passthrough_setup,
|
||||
(void*)"aes" },
|
||||
{ "aes_iv_EVP", test_crypto_aes_iv, TT_FORK, &passthrough_setup,
|
||||
(void*)"evp" },
|
||||
CRYPTO_LEGACY(base32_decode),
|
||||
{ "kdf_TAP", test_crypto_kdf_TAP, 0, NULL, NULL },
|
||||
{ "hkdf_sha256", test_crypto_hkdf_sha256, 0, NULL, NULL },
|
||||
|
|
|
@ -144,11 +144,159 @@ test_threads_basic(void *arg)
|
|||
tor_mutex_free(thread_test_start2_);
|
||||
}
|
||||
|
||||
#define THREAD_TEST(name) \
|
||||
typedef struct cv_testinfo_s {
|
||||
tor_cond_t *cond;
|
||||
tor_mutex_t *mutex;
|
||||
int value;
|
||||
int addend;
|
||||
int shutdown;
|
||||
int n_shutdown;
|
||||
int n_wakeups;
|
||||
int n_timeouts;
|
||||
int n_threads;
|
||||
const struct timeval *tv;
|
||||
} cv_testinfo_t;
|
||||
|
||||
static cv_testinfo_t *
|
||||
cv_testinfo_new(void)
|
||||
{
|
||||
cv_testinfo_t *i = tor_malloc_zero(sizeof(*i));
|
||||
i->cond = tor_cond_new();
|
||||
i->mutex = tor_mutex_new_nonrecursive();
|
||||
return i;
|
||||
}
|
||||
|
||||
static void
|
||||
cv_testinfo_free(cv_testinfo_t *i)
|
||||
{
|
||||
if (!i)
|
||||
return;
|
||||
tor_cond_free(i->cond);
|
||||
tor_mutex_free(i->mutex);
|
||||
tor_free(i);
|
||||
}
|
||||
|
||||
static void cv_test_thr_fn_(void *arg) ATTR_NORETURN;
|
||||
|
||||
static void
|
||||
cv_test_thr_fn_(void *arg)
|
||||
{
|
||||
cv_testinfo_t *i = arg;
|
||||
int tid, r;
|
||||
|
||||
tor_mutex_acquire(i->mutex);
|
||||
tid = i->n_threads++;
|
||||
tor_mutex_release(i->mutex);
|
||||
(void) tid;
|
||||
|
||||
tor_mutex_acquire(i->mutex);
|
||||
while (1) {
|
||||
if (i->addend) {
|
||||
i->value += i->addend;
|
||||
i->addend = 0;
|
||||
}
|
||||
|
||||
if (i->shutdown) {
|
||||
++i->n_shutdown;
|
||||
i->shutdown = 0;
|
||||
tor_mutex_release(i->mutex);
|
||||
spawn_exit();
|
||||
}
|
||||
r = tor_cond_wait(i->cond, i->mutex, i->tv);
|
||||
++i->n_wakeups;
|
||||
if (r == 1) {
|
||||
++i->n_timeouts;
|
||||
tor_mutex_release(i->mutex);
|
||||
spawn_exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_threads_conditionvar(void *arg)
|
||||
{
|
||||
cv_testinfo_t *ti=NULL;
|
||||
const struct timeval msec100 = { 0, 100*1000 };
|
||||
const int timeout = !strcmp(arg, "tv");
|
||||
|
||||
ti = cv_testinfo_new();
|
||||
if (timeout) {
|
||||
ti->tv = &msec100;
|
||||
}
|
||||
spawn_func(cv_test_thr_fn_, ti);
|
||||
spawn_func(cv_test_thr_fn_, ti);
|
||||
spawn_func(cv_test_thr_fn_, ti);
|
||||
spawn_func(cv_test_thr_fn_, ti);
|
||||
|
||||
tor_mutex_acquire(ti->mutex);
|
||||
ti->addend = 7;
|
||||
ti->shutdown = 1;
|
||||
tor_cond_signal_one(ti->cond);
|
||||
tor_mutex_release(ti->mutex);
|
||||
|
||||
#define SPIN() \
|
||||
while (1) { \
|
||||
tor_mutex_acquire(ti->mutex); \
|
||||
if (ti->addend == 0) { \
|
||||
break; \
|
||||
} \
|
||||
tor_mutex_release(ti->mutex); \
|
||||
}
|
||||
|
||||
SPIN();
|
||||
|
||||
ti->addend = 30;
|
||||
ti->shutdown = 1;
|
||||
tor_cond_signal_all(ti->cond);
|
||||
tor_mutex_release(ti->mutex);
|
||||
SPIN();
|
||||
|
||||
ti->addend = 1000;
|
||||
if (! timeout) ti->shutdown = 1;
|
||||
tor_cond_signal_one(ti->cond);
|
||||
tor_mutex_release(ti->mutex);
|
||||
SPIN();
|
||||
ti->addend = 300;
|
||||
if (! timeout) ti->shutdown = 1;
|
||||
tor_cond_signal_all(ti->cond);
|
||||
tor_mutex_release(ti->mutex);
|
||||
|
||||
SPIN();
|
||||
tor_mutex_release(ti->mutex);
|
||||
|
||||
tt_int_op(ti->value, ==, 1337);
|
||||
if (!timeout) {
|
||||
tt_int_op(ti->n_shutdown, ==, 4);
|
||||
} else {
|
||||
#ifdef _WIN32
|
||||
Sleep(500); /* msec */
|
||||
#elif defined(HAVE_USLEEP)
|
||||
usleep(500*1000); /* usec */
|
||||
#else
|
||||
{
|
||||
struct tv = { 0, 500*1000 };
|
||||
select(0, NULL, NULL, NULL, &tv);
|
||||
}
|
||||
#endif
|
||||
tor_mutex_acquire(ti->mutex);
|
||||
tt_int_op(ti->n_shutdown, ==, 2);
|
||||
tt_int_op(ti->n_timeouts, ==, 2);
|
||||
tor_mutex_release(ti->mutex);
|
||||
}
|
||||
|
||||
done:
|
||||
cv_testinfo_free(ti);
|
||||
}
|
||||
|
||||
#define THREAD_TEST(name) \
|
||||
{ #name, test_threads_##name, TT_FORK, NULL, NULL }
|
||||
|
||||
struct testcase_t thread_tests[] = {
|
||||
THREAD_TEST(basic),
|
||||
{ "conditionvar", test_threads_conditionvar, TT_FORK,
|
||||
&passthrough_setup, (void*)"no-tv" },
|
||||
{ "conditionvar_timeout", test_threads_conditionvar, TT_FORK,
|
||||
&passthrough_setup, (void*)"tv" },
|
||||
END_OF_TESTCASES
|
||||
};
|
||||
|
||||
|
|
|
@ -4646,23 +4646,6 @@ test_util_socket(void *arg)
|
|||
tor_close_socket(fd4);
|
||||
}
|
||||
|
||||
static void *
|
||||
socketpair_test_setup(const struct testcase_t *testcase)
|
||||
{
|
||||
return testcase->setup_data;
|
||||
}
|
||||
static int
|
||||
socketpair_test_cleanup(const struct testcase_t *testcase, void *ptr)
|
||||
{
|
||||
(void)testcase;
|
||||
(void)ptr;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct testcase_setup_t socketpair_setup = {
|
||||
socketpair_test_setup, socketpair_test_cleanup
|
||||
};
|
||||
|
||||
/* Test for socketpair and ersatz_socketpair(). We test them both, since
|
||||
* the latter is a tolerably good way to exersize tor_accept_socket(). */
|
||||
static void
|
||||
|
@ -4837,10 +4820,10 @@ struct testcase_t util_tests[] = {
|
|||
UTIL_TEST(mathlog, 0),
|
||||
UTIL_TEST(weak_random, 0),
|
||||
UTIL_TEST(socket, TT_FORK),
|
||||
{ "socketpair", test_util_socketpair, TT_FORK, &socketpair_setup,
|
||||
{ "socketpair", test_util_socketpair, TT_FORK, &passthrough_setup,
|
||||
(void*)"0" },
|
||||
{ "socketpair_ersatz", test_util_socketpair, TT_FORK,
|
||||
&socketpair_setup, (void*)"1" },
|
||||
&passthrough_setup, (void*)"1" },
|
||||
UTIL_TEST(max_mem, 0),
|
||||
UTIL_TEST(hostname_validation, 0),
|
||||
UTIL_TEST(ipv4_validation, 0),
|
||||
|
|
Loading…
Reference in New Issue