Add tests for signal functions in os_calls.c
This commit is contained in:
parent
d11617adbe
commit
d098214531
251
tests/common/test_os_calls_signals.c
Normal file
251
tests/common/test_os_calls_signals.c
Normal file
@ -0,0 +1,251 @@
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "config_ac.h"
|
||||
#endif
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include "os_calls.h"
|
||||
|
||||
#include "test_common.h"
|
||||
|
||||
static tintptr g_wobj1 = 0;
|
||||
|
||||
/******************************************************************************/
|
||||
void
|
||||
os_calls_signals_init(void)
|
||||
{
|
||||
g_wobj1 = g_create_wait_obj("");
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void
|
||||
os_calls_signals_deinit(void)
|
||||
{
|
||||
g_delete_wait_obj(g_wobj1);
|
||||
g_wobj1 = 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* Set the global wait object g_wobj1
|
||||
*/
|
||||
static void
|
||||
set_wobj1(int signum)
|
||||
{
|
||||
g_set_wait_obj(g_wobj1);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* Sends a number of signals to the process and checks they are all delivered
|
||||
*
|
||||
* @param sig Signal number
|
||||
* @param count Number of signals to send
|
||||
*
|
||||
* The caller is expected to establish a signal handler before this call
|
||||
* which sets the global g_wobj1 on signal delivery */
|
||||
|
||||
static
|
||||
void send_multiple_signals(int sig, unsigned int count)
|
||||
{
|
||||
while (count-- > 0)
|
||||
{
|
||||
g_reset_wait_obj(g_wobj1);
|
||||
ck_assert_int_eq(g_is_wait_obj_set(g_wobj1), 0);
|
||||
// Expect the signal to be delivered synchronously
|
||||
raise(sig);
|
||||
ck_assert_int_ne(g_is_wait_obj_set(g_wobj1), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
START_TEST(test_g_set_alarm)
|
||||
{
|
||||
g_reset_wait_obj(g_wobj1);
|
||||
ck_assert_int_eq(g_is_wait_obj_set(g_wobj1), 0);
|
||||
|
||||
g_set_alarm(set_wobj1, 1);
|
||||
|
||||
g_obj_wait(&g_wobj1, 1, NULL, 0, 2000);
|
||||
|
||||
ck_assert_int_ne(g_is_wait_obj_set(g_wobj1), 0);
|
||||
|
||||
// Clean up
|
||||
g_set_alarm(NULL, 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/******************************************************************************/
|
||||
START_TEST(test_g_signal_child_stop_1)
|
||||
{
|
||||
struct exit_status e;
|
||||
|
||||
g_reset_wait_obj(g_wobj1);
|
||||
ck_assert_int_eq(g_is_wait_obj_set(g_wobj1), 0);
|
||||
|
||||
g_signal_child_stop(set_wobj1);
|
||||
|
||||
int pid = g_fork();
|
||||
|
||||
if (pid == 0)
|
||||
{
|
||||
g_exit(45);
|
||||
}
|
||||
ck_assert_int_ne(pid, 0);
|
||||
g_obj_wait(&g_wobj1, 1, NULL, 0, 2000);
|
||||
ck_assert_int_ne(g_is_wait_obj_set(g_wobj1), 0);
|
||||
|
||||
e = g_waitpid_status(pid);
|
||||
|
||||
ck_assert_int_eq(e.reason, E_XR_STATUS_CODE);
|
||||
ck_assert_int_eq(e.val, 45);
|
||||
|
||||
// Try another one to make sure the signal handler is still in place.
|
||||
// This one can generate a signal
|
||||
g_reset_wait_obj(g_wobj1);
|
||||
|
||||
pid = g_fork();
|
||||
if (pid == 0)
|
||||
{
|
||||
raise(SIGSEGV);
|
||||
}
|
||||
ck_assert_int_ne(pid, 0);
|
||||
g_obj_wait(&g_wobj1, 1, NULL, 0, 2000);
|
||||
ck_assert_int_ne(g_is_wait_obj_set(g_wobj1), 0);
|
||||
|
||||
e = g_waitpid_status(pid);
|
||||
|
||||
ck_assert_int_eq(e.reason, E_XR_SIGNAL);
|
||||
ck_assert_int_eq(e.val, SIGSEGV);
|
||||
|
||||
// Clean up
|
||||
g_signal_child_stop(NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/******************************************************************************/
|
||||
/* Checks that multiple children finishing do not interrupt
|
||||
* g_waitpid_status() */
|
||||
START_TEST(test_g_signal_child_stop_2)
|
||||
{
|
||||
#define CHILD_COUNT 20
|
||||
int pids[CHILD_COUNT];
|
||||
unsigned int i;
|
||||
|
||||
struct exit_status e;
|
||||
|
||||
g_reset_wait_obj(g_wobj1);
|
||||
ck_assert_int_eq(g_is_wait_obj_set(g_wobj1), 0);
|
||||
|
||||
g_signal_child_stop(set_wobj1);
|
||||
|
||||
for (i = 0 ; i < CHILD_COUNT; ++i)
|
||||
{
|
||||
int pid = g_fork();
|
||||
if (pid == 0)
|
||||
{
|
||||
g_sleep((i + 1) * 100);
|
||||
g_exit(i + 1);
|
||||
}
|
||||
ck_assert_int_ne(pid, 0);
|
||||
pids[i] = pid;
|
||||
}
|
||||
g_obj_wait(&g_wobj1, 1, NULL, 0, 2000);
|
||||
ck_assert_int_ne(g_is_wait_obj_set(g_wobj1), 0);
|
||||
|
||||
for (i = 0 ; i < CHILD_COUNT; ++i)
|
||||
{
|
||||
e = g_waitpid_status(pids[i]);
|
||||
ck_assert_int_eq(e.reason, E_XR_STATUS_CODE);
|
||||
ck_assert_int_eq(e.val, (i + 1));
|
||||
}
|
||||
|
||||
// Clean up
|
||||
g_signal_child_stop(NULL);
|
||||
#undef CHILD_COUNT
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
START_TEST(test_g_signal_segfault)
|
||||
{
|
||||
g_signal_segfault(set_wobj1);
|
||||
|
||||
// Only one signal can be received in this way. After handling
|
||||
// the signal the handler should be automatically reset.
|
||||
send_multiple_signals(SIGSEGV, 1);
|
||||
|
||||
g_signal_segfault(NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/******************************************************************************/
|
||||
START_TEST(test_g_signal_hang_up)
|
||||
{
|
||||
g_signal_hang_up(set_wobj1);
|
||||
|
||||
send_multiple_signals(SIGHUP, 5);
|
||||
|
||||
g_signal_hang_up(NULL);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
START_TEST(test_g_signal_user_interrupt)
|
||||
{
|
||||
g_signal_user_interrupt(set_wobj1);
|
||||
|
||||
send_multiple_signals(SIGINT, 5);
|
||||
|
||||
g_signal_user_interrupt(NULL);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
START_TEST(test_g_signal_terminate)
|
||||
{
|
||||
g_signal_terminate(set_wobj1);
|
||||
|
||||
send_multiple_signals(SIGTERM, 5);
|
||||
|
||||
g_signal_terminate(NULL);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
START_TEST(test_g_signal_pipe)
|
||||
{
|
||||
g_signal_pipe(set_wobj1);
|
||||
|
||||
send_multiple_signals(SIGPIPE, 5);
|
||||
|
||||
g_signal_pipe(NULL);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
START_TEST(test_g_signal_usr1)
|
||||
{
|
||||
g_signal_usr1(set_wobj1);
|
||||
|
||||
send_multiple_signals(SIGUSR1, 5);
|
||||
|
||||
g_signal_usr1(NULL);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
TCase *
|
||||
make_tcase_test_os_calls_signals(void)
|
||||
{
|
||||
TCase *tc = tcase_create("oscalls-signals");
|
||||
|
||||
tcase_add_test(tc, test_g_set_alarm);
|
||||
tcase_add_test(tc, test_g_signal_child_stop_1);
|
||||
tcase_add_test(tc, test_g_signal_child_stop_2);
|
||||
tcase_add_test(tc, test_g_signal_segfault);
|
||||
tcase_add_test(tc, test_g_signal_hang_up);
|
||||
tcase_add_test(tc, test_g_signal_user_interrupt);
|
||||
tcase_add_test(tc, test_g_signal_terminate);
|
||||
tcase_add_test(tc, test_g_signal_pipe);
|
||||
tcase_add_test(tc, test_g_signal_usr1);
|
||||
|
||||
return tc;
|
||||
}
|
Loading…
Reference in New Issue
Block a user