Skip to content

Commit d098214

Browse files
committed
Add tests for signal functions in os_calls.c
1 parent d11617a commit d098214

File tree

1 file changed

+251
-0
lines changed

1 file changed

+251
-0
lines changed
Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
2+
#if defined(HAVE_CONFIG_H)
3+
#include "config_ac.h"
4+
#endif
5+
6+
#include <signal.h>
7+
8+
#include "os_calls.h"
9+
10+
#include "test_common.h"
11+
12+
static tintptr g_wobj1 = 0;
13+
14+
/******************************************************************************/
15+
void
16+
os_calls_signals_init(void)
17+
{
18+
g_wobj1 = g_create_wait_obj("");
19+
}
20+
21+
/******************************************************************************/
22+
void
23+
os_calls_signals_deinit(void)
24+
{
25+
g_delete_wait_obj(g_wobj1);
26+
g_wobj1 = 0;
27+
}
28+
29+
/******************************************************************************/
30+
/**
31+
* Set the global wait object g_wobj1
32+
*/
33+
static void
34+
set_wobj1(int signum)
35+
{
36+
g_set_wait_obj(g_wobj1);
37+
}
38+
39+
/******************************************************************************/
40+
/**
41+
* Sends a number of signals to the process and checks they are all delivered
42+
*
43+
* @param sig Signal number
44+
* @param count Number of signals to send
45+
*
46+
* The caller is expected to establish a signal handler before this call
47+
* which sets the global g_wobj1 on signal delivery */
48+
49+
static
50+
void send_multiple_signals(int sig, unsigned int count)
51+
{
52+
while (count-- > 0)
53+
{
54+
g_reset_wait_obj(g_wobj1);
55+
ck_assert_int_eq(g_is_wait_obj_set(g_wobj1), 0);
56+
// Expect the signal to be delivered synchronously
57+
raise(sig);
58+
ck_assert_int_ne(g_is_wait_obj_set(g_wobj1), 0);
59+
}
60+
}
61+
62+
/******************************************************************************/
63+
START_TEST(test_g_set_alarm)
64+
{
65+
g_reset_wait_obj(g_wobj1);
66+
ck_assert_int_eq(g_is_wait_obj_set(g_wobj1), 0);
67+
68+
g_set_alarm(set_wobj1, 1);
69+
70+
g_obj_wait(&g_wobj1, 1, NULL, 0, 2000);
71+
72+
ck_assert_int_ne(g_is_wait_obj_set(g_wobj1), 0);
73+
74+
// Clean up
75+
g_set_alarm(NULL, 0);
76+
}
77+
END_TEST
78+
79+
/******************************************************************************/
80+
START_TEST(test_g_signal_child_stop_1)
81+
{
82+
struct exit_status e;
83+
84+
g_reset_wait_obj(g_wobj1);
85+
ck_assert_int_eq(g_is_wait_obj_set(g_wobj1), 0);
86+
87+
g_signal_child_stop(set_wobj1);
88+
89+
int pid = g_fork();
90+
91+
if (pid == 0)
92+
{
93+
g_exit(45);
94+
}
95+
ck_assert_int_ne(pid, 0);
96+
g_obj_wait(&g_wobj1, 1, NULL, 0, 2000);
97+
ck_assert_int_ne(g_is_wait_obj_set(g_wobj1), 0);
98+
99+
e = g_waitpid_status(pid);
100+
101+
ck_assert_int_eq(e.reason, E_XR_STATUS_CODE);
102+
ck_assert_int_eq(e.val, 45);
103+
104+
// Try another one to make sure the signal handler is still in place.
105+
// This one can generate a signal
106+
g_reset_wait_obj(g_wobj1);
107+
108+
pid = g_fork();
109+
if (pid == 0)
110+
{
111+
raise(SIGSEGV);
112+
}
113+
ck_assert_int_ne(pid, 0);
114+
g_obj_wait(&g_wobj1, 1, NULL, 0, 2000);
115+
ck_assert_int_ne(g_is_wait_obj_set(g_wobj1), 0);
116+
117+
e = g_waitpid_status(pid);
118+
119+
ck_assert_int_eq(e.reason, E_XR_SIGNAL);
120+
ck_assert_int_eq(e.val, SIGSEGV);
121+
122+
// Clean up
123+
g_signal_child_stop(NULL);
124+
}
125+
END_TEST
126+
127+
/******************************************************************************/
128+
/* Checks that multiple children finishing do not interrupt
129+
* g_waitpid_status() */
130+
START_TEST(test_g_signal_child_stop_2)
131+
{
132+
#define CHILD_COUNT 20
133+
int pids[CHILD_COUNT];
134+
unsigned int i;
135+
136+
struct exit_status e;
137+
138+
g_reset_wait_obj(g_wobj1);
139+
ck_assert_int_eq(g_is_wait_obj_set(g_wobj1), 0);
140+
141+
g_signal_child_stop(set_wobj1);
142+
143+
for (i = 0 ; i < CHILD_COUNT; ++i)
144+
{
145+
int pid = g_fork();
146+
if (pid == 0)
147+
{
148+
g_sleep((i + 1) * 100);
149+
g_exit(i + 1);
150+
}
151+
ck_assert_int_ne(pid, 0);
152+
pids[i] = pid;
153+
}
154+
g_obj_wait(&g_wobj1, 1, NULL, 0, 2000);
155+
ck_assert_int_ne(g_is_wait_obj_set(g_wobj1), 0);
156+
157+
for (i = 0 ; i < CHILD_COUNT; ++i)
158+
{
159+
e = g_waitpid_status(pids[i]);
160+
ck_assert_int_eq(e.reason, E_XR_STATUS_CODE);
161+
ck_assert_int_eq(e.val, (i + 1));
162+
}
163+
164+
// Clean up
165+
g_signal_child_stop(NULL);
166+
#undef CHILD_COUNT
167+
}
168+
END_TEST
169+
170+
171+
/******************************************************************************/
172+
START_TEST(test_g_signal_segfault)
173+
{
174+
g_signal_segfault(set_wobj1);
175+
176+
// Only one signal can be received in this way. After handling
177+
// the signal the handler should be automatically reset.
178+
send_multiple_signals(SIGSEGV, 1);
179+
180+
g_signal_segfault(NULL);
181+
}
182+
END_TEST
183+
184+
/******************************************************************************/
185+
START_TEST(test_g_signal_hang_up)
186+
{
187+
g_signal_hang_up(set_wobj1);
188+
189+
send_multiple_signals(SIGHUP, 5);
190+
191+
g_signal_hang_up(NULL);
192+
}
193+
194+
/******************************************************************************/
195+
START_TEST(test_g_signal_user_interrupt)
196+
{
197+
g_signal_user_interrupt(set_wobj1);
198+
199+
send_multiple_signals(SIGINT, 5);
200+
201+
g_signal_user_interrupt(NULL);
202+
}
203+
204+
/******************************************************************************/
205+
START_TEST(test_g_signal_terminate)
206+
{
207+
g_signal_terminate(set_wobj1);
208+
209+
send_multiple_signals(SIGTERM, 5);
210+
211+
g_signal_terminate(NULL);
212+
}
213+
214+
/******************************************************************************/
215+
START_TEST(test_g_signal_pipe)
216+
{
217+
g_signal_pipe(set_wobj1);
218+
219+
send_multiple_signals(SIGPIPE, 5);
220+
221+
g_signal_pipe(NULL);
222+
}
223+
224+
/******************************************************************************/
225+
START_TEST(test_g_signal_usr1)
226+
{
227+
g_signal_usr1(set_wobj1);
228+
229+
send_multiple_signals(SIGUSR1, 5);
230+
231+
g_signal_usr1(NULL);
232+
}
233+
234+
/******************************************************************************/
235+
TCase *
236+
make_tcase_test_os_calls_signals(void)
237+
{
238+
TCase *tc = tcase_create("oscalls-signals");
239+
240+
tcase_add_test(tc, test_g_set_alarm);
241+
tcase_add_test(tc, test_g_signal_child_stop_1);
242+
tcase_add_test(tc, test_g_signal_child_stop_2);
243+
tcase_add_test(tc, test_g_signal_segfault);
244+
tcase_add_test(tc, test_g_signal_hang_up);
245+
tcase_add_test(tc, test_g_signal_user_interrupt);
246+
tcase_add_test(tc, test_g_signal_terminate);
247+
tcase_add_test(tc, test_g_signal_pipe);
248+
tcase_add_test(tc, test_g_signal_usr1);
249+
250+
return tc;
251+
}

0 commit comments

Comments
 (0)