0
0
mirror of https://github.com/zeromq/libzmq.git synced 2024-12-25 22:30:51 +08:00
libzmq/tests/test_timers.cpp
Luca Boccassi da31917f4f Relicense from LGPL3 + exceptions to Mozilla Public License version 2.0
Relicense permission collected from all relevant authors as tallied at:
https://github.com/rlenferink/libzmq-relicense/blob/master/checklist.md
The relicense grants are collected under RELICENSE/ and will be moved
to the above repository in a later commit.

Fixes https://github.com/zeromq/libzmq/issues/2376
2023-06-05 20:31:47 +01:00

196 lines
6.0 KiB
C++

/* SPDX-License-Identifier: MPL-2.0 */
#define __STDC_LIMIT_MACROS // to define SIZE_MAX with older compilers
#include "testutil.hpp"
#include "testutil_unity.hpp"
void setUp ()
{
}
void tearDown ()
{
}
void handler (int timer_id_, void *arg_)
{
(void) timer_id_; // Stop 'unused' compiler warnings
*(static_cast<bool *> (arg_)) = true;
}
int sleep_and_execute (void *timers_)
{
int timeout = zmq_timers_timeout (timers_);
// Sleep methods are inaccurate, so we sleep in a loop until time arrived
while (timeout > 0) {
msleep (timeout);
timeout = zmq_timers_timeout (timers_);
}
return zmq_timers_execute (timers_);
}
void test_null_timer_pointers ()
{
void *timers = NULL;
TEST_ASSERT_FAILURE_ERRNO (EFAULT, zmq_timers_destroy (&timers));
// TODO this currently triggers an access violation
#if 0
TEST_ASSERT_FAILURE_ERRNO(EFAULT, zmq_timers_destroy (NULL));
#endif
const size_t dummy_interval = 100;
const int dummy_timer_id = 1;
TEST_ASSERT_FAILURE_ERRNO (
EFAULT, zmq_timers_add (timers, dummy_interval, &handler, NULL));
TEST_ASSERT_FAILURE_ERRNO (
EFAULT, zmq_timers_add (&timers, dummy_interval, &handler, NULL));
TEST_ASSERT_FAILURE_ERRNO (EFAULT,
zmq_timers_cancel (timers, dummy_timer_id));
TEST_ASSERT_FAILURE_ERRNO (EFAULT,
zmq_timers_cancel (&timers, dummy_timer_id));
TEST_ASSERT_FAILURE_ERRNO (
EFAULT, zmq_timers_set_interval (timers, dummy_timer_id, dummy_interval));
TEST_ASSERT_FAILURE_ERRNO (
EFAULT,
zmq_timers_set_interval (&timers, dummy_timer_id, dummy_interval));
TEST_ASSERT_FAILURE_ERRNO (EFAULT,
zmq_timers_reset (timers, dummy_timer_id));
TEST_ASSERT_FAILURE_ERRNO (EFAULT,
zmq_timers_reset (&timers, dummy_timer_id));
TEST_ASSERT_FAILURE_ERRNO (EFAULT, zmq_timers_timeout (timers));
TEST_ASSERT_FAILURE_ERRNO (EFAULT, zmq_timers_timeout (&timers));
TEST_ASSERT_FAILURE_ERRNO (EFAULT, zmq_timers_execute (timers));
TEST_ASSERT_FAILURE_ERRNO (EFAULT, zmq_timers_execute (&timers));
}
void test_corner_cases ()
{
void *timers = zmq_timers_new ();
TEST_ASSERT_NOT_NULL (timers);
const size_t dummy_interval = SIZE_MAX;
const int dummy_timer_id = 1;
// attempt to cancel non-existent timer
TEST_ASSERT_FAILURE_ERRNO (EINVAL,
zmq_timers_cancel (timers, dummy_timer_id));
// attempt to set interval of non-existent timer
TEST_ASSERT_FAILURE_ERRNO (
EINVAL, zmq_timers_set_interval (timers, dummy_timer_id, dummy_interval));
// attempt to reset non-existent timer
TEST_ASSERT_FAILURE_ERRNO (EINVAL,
zmq_timers_reset (timers, dummy_timer_id));
// attempt to add NULL handler
TEST_ASSERT_FAILURE_ERRNO (
EFAULT, zmq_timers_add (timers, dummy_interval, NULL, NULL));
const int timer_id = TEST_ASSERT_SUCCESS_ERRNO (
zmq_timers_add (timers, dummy_interval, handler, NULL));
// attempt to cancel timer twice
// TODO should this case really be an error? canceling twice could be allowed
TEST_ASSERT_SUCCESS_ERRNO (zmq_timers_cancel (timers, timer_id));
TEST_ASSERT_FAILURE_ERRNO (EINVAL, zmq_timers_cancel (timers, timer_id));
// timeout without any timers active
TEST_ASSERT_FAILURE_ERRNO (EINVAL, zmq_timers_timeout (timers));
// cleanup
TEST_ASSERT_SUCCESS_ERRNO (zmq_timers_destroy (&timers));
}
void test_timers ()
{
void *timers = zmq_timers_new ();
TEST_ASSERT_NOT_NULL (timers);
bool timer_invoked = false;
const unsigned long full_timeout = 100;
void *const stopwatch = zmq_stopwatch_start ();
const int timer_id = TEST_ASSERT_SUCCESS_ERRNO (
zmq_timers_add (timers, full_timeout, handler, &timer_invoked));
// Timer should not have been invoked yet
TEST_ASSERT_SUCCESS_ERRNO (zmq_timers_execute (timers));
if (zmq_stopwatch_intermediate (stopwatch) < full_timeout) {
TEST_ASSERT_FALSE (timer_invoked);
}
// Wait half the time and check again
long timeout = TEST_ASSERT_SUCCESS_ERRNO (zmq_timers_timeout (timers));
msleep (timeout / 2);
TEST_ASSERT_SUCCESS_ERRNO (zmq_timers_execute (timers));
if (zmq_stopwatch_intermediate (stopwatch) < full_timeout) {
TEST_ASSERT_FALSE (timer_invoked);
}
// Wait until the end
TEST_ASSERT_SUCCESS_ERRNO (sleep_and_execute (timers));
TEST_ASSERT_TRUE (timer_invoked);
timer_invoked = false;
// Wait half the time and check again
timeout = TEST_ASSERT_SUCCESS_ERRNO (zmq_timers_timeout (timers));
msleep (timeout / 2);
TEST_ASSERT_SUCCESS_ERRNO (zmq_timers_execute (timers));
if (zmq_stopwatch_intermediate (stopwatch) < 2 * full_timeout) {
TEST_ASSERT_FALSE (timer_invoked);
}
// Reset timer and wait half of the time left
TEST_ASSERT_SUCCESS_ERRNO (zmq_timers_reset (timers, timer_id));
msleep (timeout / 2);
TEST_ASSERT_SUCCESS_ERRNO (zmq_timers_execute (timers));
if (zmq_stopwatch_stop (stopwatch) < 2 * full_timeout) {
TEST_ASSERT_FALSE (timer_invoked);
}
// Wait until the end
TEST_ASSERT_SUCCESS_ERRNO (sleep_and_execute (timers));
TEST_ASSERT_TRUE (timer_invoked);
timer_invoked = false;
// reschedule
TEST_ASSERT_SUCCESS_ERRNO (zmq_timers_set_interval (timers, timer_id, 50));
TEST_ASSERT_SUCCESS_ERRNO (sleep_and_execute (timers));
TEST_ASSERT_TRUE (timer_invoked);
timer_invoked = false;
// cancel timer
timeout = TEST_ASSERT_SUCCESS_ERRNO (zmq_timers_timeout (timers));
TEST_ASSERT_SUCCESS_ERRNO (zmq_timers_cancel (timers, timer_id));
msleep (timeout * 2);
TEST_ASSERT_SUCCESS_ERRNO (zmq_timers_execute (timers));
TEST_ASSERT_FALSE (timer_invoked);
TEST_ASSERT_SUCCESS_ERRNO (zmq_timers_destroy (&timers));
}
int main ()
{
setup_test_environment ();
UNITY_BEGIN ();
RUN_TEST (test_timers);
RUN_TEST (test_null_timer_pointers);
RUN_TEST (test_corner_cases);
return UNITY_END ();
}