1 /*
2 lib - common code for testing lib/utilinux:my_system() function
3
4 Copyright (C) 2013-2021
5 Free Software Foundation, Inc.
6
7 Written by:
8 Slava Zanko <slavazanko@gmail.com>, 2013
9
10 This file is part of the Midnight Commander.
11
12 The Midnight Commander is free software: you can redistribute it
13 and/or modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation, either version 3 of the License,
15 or (at your option) any later version.
16
17 The Midnight Commander is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 */
25
26 #include <signal.h>
27 #include <unistd.h>
28
29 #include "lib/vfs/vfs.h"
30
31 /* sighandler_t is GNU extension */
32 #ifndef HAVE_SIGHANDLER_T
33 typedef void (*sighandler_t) (int);
34 #endif
35
36 /* --------------------------------------------------------------------------------------------- */
37
38 /* @CapturedValue */
39 static sigset_t *sigemptyset_set__captured;
40 /* @ThenReturnValue */
41 static int sigemptyset__return_value = 0;
42
43 /* @Mock */
44 int
sigemptyset(sigset_t * set)45 sigemptyset (sigset_t * set)
46 {
47 sigemptyset_set__captured = set;
48 return sigemptyset__return_value;
49 }
50
51 /* --------------------------------------------------------------------------------------------- */
52
53 /* @CapturedValue */
54 static GPtrArray *sigaction_signum__captured = NULL;
55 /* @CapturedValue */
56 static GPtrArray *sigaction_act__captured = NULL;
57 /* @CapturedValue */
58 static GPtrArray *sigaction_oldact__captured = NULL;
59 /* @ThenReturnValue */
60 static int sigaction__return_value = 0;
61
62 /* @Mock */
63 int
sigaction(int signum,const struct sigaction * act,struct sigaction * oldact)64 sigaction (int signum, const struct sigaction *act, struct sigaction *oldact)
65 {
66 int *tmp_signum;
67 struct sigaction *tmp_act;
68
69 /* store signum */
70 tmp_signum = g_new (int, 1);
71 memcpy (tmp_signum, &signum, sizeof (*tmp_signum));
72 if (sigaction_signum__captured != NULL)
73 g_ptr_array_add (sigaction_signum__captured, tmp_signum);
74
75 /* store act */
76 if (act != NULL)
77 {
78 tmp_act = g_new (struct sigaction, 1);
79 memcpy (tmp_act, act, sizeof (*tmp_act));
80 }
81 else
82 tmp_act = NULL;
83 if (sigaction_act__captured != NULL)
84 g_ptr_array_add (sigaction_act__captured, tmp_act);
85
86 /* store oldact */
87 if (oldact != NULL)
88 {
89 tmp_act = g_new (struct sigaction, 1);
90 memcpy (tmp_act, oldact, sizeof (*tmp_act));
91 }
92 else
93 tmp_act = NULL;
94 if (sigaction_oldact__captured != NULL)
95 g_ptr_array_add (sigaction_oldact__captured, tmp_act);
96
97 return sigaction__return_value;
98 }
99
100 static void
sigaction__init(void)101 sigaction__init (void)
102 {
103 sigaction_signum__captured = g_ptr_array_new ();
104 sigaction_act__captured = g_ptr_array_new ();
105 sigaction_oldact__captured = g_ptr_array_new ();
106 }
107
108 static void
sigaction__deinit(void)109 sigaction__deinit (void)
110 {
111 g_ptr_array_foreach (sigaction_signum__captured, (GFunc) g_free, NULL);
112 g_ptr_array_free (sigaction_signum__captured, TRUE);
113 sigaction_signum__captured = NULL;
114
115 g_ptr_array_foreach (sigaction_act__captured, (GFunc) g_free, NULL);
116 g_ptr_array_free (sigaction_act__captured, TRUE);
117 sigaction_act__captured = NULL;
118
119 g_ptr_array_foreach (sigaction_oldact__captured, (GFunc) g_free, NULL);
120 g_ptr_array_free (sigaction_oldact__captured, TRUE);
121 sigaction_oldact__captured = NULL;
122 }
123
124 /* --------------------------------------------------------------------------------------------- */
125
126 /* @CapturedValue */
127 static GPtrArray *signal_signum__captured;
128 /* @CapturedValue */
129 static GPtrArray *signal_handler__captured;
130 /* @ThenReturnValue */
131 static sighandler_t signal__return_value = NULL;
132
133 /* @Mock */
134 sighandler_t
signal(int signum,sighandler_t handler)135 signal (int signum, sighandler_t handler)
136 {
137 int *tmp_signum;
138 sighandler_t *tmp_handler;
139
140 /* store signum */
141 tmp_signum = g_new (int, 1);
142 memcpy (tmp_signum, &signum, sizeof (*tmp_signum));
143 g_ptr_array_add (signal_signum__captured, tmp_signum);
144
145 /* store handler */
146 if (handler != SIG_DFL)
147 {
148 tmp_handler = g_new (sighandler_t, 1);
149 memcpy (tmp_handler, handler, sizeof (*tmp_handler));
150 }
151 else
152 tmp_handler = (void *) SIG_DFL;
153 g_ptr_array_add (signal_handler__captured, tmp_handler);
154
155 return signal__return_value;
156 }
157
158 static void
signal__init(void)159 signal__init (void)
160 {
161 signal_signum__captured = g_ptr_array_new ();
162 signal_handler__captured = g_ptr_array_new ();
163 }
164
165 static void
signal__deinit(void)166 signal__deinit (void)
167 {
168 g_ptr_array_foreach (signal_signum__captured, (GFunc) g_free, NULL);
169 g_ptr_array_free (signal_signum__captured, TRUE);
170 signal_signum__captured = NULL;
171
172 g_ptr_array_foreach (signal_handler__captured, (GFunc) g_free, NULL);
173 g_ptr_array_free (signal_handler__captured, TRUE);
174 signal_handler__captured = NULL;
175 }
176
177 /* --------------------------------------------------------------------------------------------- */
178
179 /* @ThenReturnValue */
180 static pid_t fork__return_value;
181
182 /* @Mock */
183 pid_t
fork(void)184 fork (void)
185 {
186 return fork__return_value;
187 }
188
189 /* --------------------------------------------------------------------------------------------- */
190 /* @CapturedValue */
191 static int my_exit__status__captured;
192
193 /* @Mock */
194 void
my_exit(int status)195 my_exit (int status)
196 {
197 my_exit__status__captured = status;
198 }
199
200 /* --------------------------------------------------------------------------------------------- */
201
202 /* @CapturedValue */
203 static char *execvp__file__captured = NULL;
204 /* @CapturedValue */
205 static GPtrArray *execvp__args__captured;
206 /* @ThenReturnValue */
207 static int execvp__return_value = 0;
208
209 /* @Mock */
210 int
execvp(const char * file,char * const argv[])211 execvp (const char *file, char *const argv[])
212 {
213 char **one_arg;
214 execvp__file__captured = g_strdup (file);
215
216 for (one_arg = (char **) argv; *one_arg != NULL; one_arg++)
217 g_ptr_array_add (execvp__args__captured, g_strdup (*one_arg));
218
219 return execvp__return_value;
220 }
221
222 static void
execvp__init(void)223 execvp__init (void)
224 {
225 execvp__args__captured = g_ptr_array_new ();
226 }
227
228 static void
execvp__deinit(void)229 execvp__deinit (void)
230 {
231 g_ptr_array_foreach (execvp__args__captured, (GFunc) g_free, NULL);
232 g_ptr_array_free (execvp__args__captured, TRUE);
233 execvp__args__captured = NULL;
234 MC_PTR_FREE (execvp__file__captured);
235 }
236
237 /* --------------------------------------------------------------------------------------------- */
238
239 #define VERIFY_SIGACTION__ACT_IGNORED(_pntr) { \
240 struct sigaction *_act = (struct sigaction *) _pntr; \
241 mctest_assert_ptr_eq (_act->sa_handler, SIG_IGN); \
242 mctest_assert_int_eq (_act->sa_flags, 0); \
243 }
244
245 #define VERIFY_SIGACTION__IS_RESTORED(oldact_idx, act_idx) { \
246 struct sigaction *_oldact = (struct sigaction *) g_ptr_array_index(sigaction_oldact__captured, oldact_idx); \
247 struct sigaction *_act = (struct sigaction *) g_ptr_array_index(sigaction_act__captured, act_idx); \
248 ck_assert_msg (memcmp(_oldact, _act, sizeof(struct sigaction)) == 0, \
249 "sigaction(): oldact[%d] should be equals to act[%d]", oldact_idx, act_idx); \
250 }
251
252 /* @Verify */
253 #define VERIFY_SIGACTION_CALLS() { \
254 mctest_assert_int_eq (sigaction_signum__captured->len, 6); \
255 \
256 mctest_assert_int_eq (*((int *) g_ptr_array_index(sigaction_signum__captured, 0)), SIGINT); \
257 mctest_assert_int_eq (*((int *) g_ptr_array_index(sigaction_signum__captured, 1)), SIGQUIT); \
258 mctest_assert_int_eq (*((int *) g_ptr_array_index(sigaction_signum__captured, 2)), SIGTSTP); \
259 mctest_assert_int_eq (*((int *) g_ptr_array_index(sigaction_signum__captured, 3)), SIGINT); \
260 mctest_assert_int_eq (*((int *) g_ptr_array_index(sigaction_signum__captured, 4)), SIGQUIT); \
261 mctest_assert_int_eq (*((int *) g_ptr_array_index(sigaction_signum__captured, 5)), SIGTSTP); \
262 \
263 VERIFY_SIGACTION__ACT_IGNORED(g_ptr_array_index(sigaction_act__captured, 0)); \
264 VERIFY_SIGACTION__ACT_IGNORED(g_ptr_array_index(sigaction_act__captured, 1)); \
265 { \
266 struct sigaction *_act = g_ptr_array_index(sigaction_act__captured, 2); \
267 ck_assert_msg (memcmp (_act, &startup_handler, sizeof(struct sigaction)) == 0, \
268 "The 'act' in third call to sigaction() should be equals to startup_handler"); \
269 } \
270 \
271 VERIFY_SIGACTION__IS_RESTORED (0, 3); \
272 VERIFY_SIGACTION__IS_RESTORED (1, 4); \
273 VERIFY_SIGACTION__IS_RESTORED (2, 5); \
274 \
275 ck_assert_msg (g_ptr_array_index(sigaction_oldact__captured, 3) == NULL, \
276 "oldact in fourth call to sigaction() should be NULL"); \
277 ck_assert_msg (g_ptr_array_index(sigaction_oldact__captured, 4) == NULL, \
278 "oldact in fifth call to sigaction() should be NULL"); \
279 ck_assert_msg (g_ptr_array_index(sigaction_oldact__captured, 5) == NULL, \
280 "oldact in sixth call to sigaction() should be NULL"); \
281 }
282
283 /* --------------------------------------------------------------------------------------------- */
284
285 #define VERIFY_SIGNAL_HANDLER_IS_SIG_DFL(_idx) { \
286 sighandler_t *tmp_handler = (sighandler_t *) g_ptr_array_index(signal_handler__captured, _idx);\
287 mctest_assert_ptr_eq (tmp_handler, (sighandler_t *) SIG_DFL); \
288 }
289
290 /* @Verify */
291 #define VERIFY_SIGNAL_CALLS() { \
292 mctest_assert_int_eq (signal_signum__captured->len, 4); \
293 mctest_assert_int_eq (*((int *) g_ptr_array_index(signal_signum__captured, 0)), SIGINT); \
294 mctest_assert_int_eq (*((int *) g_ptr_array_index(signal_signum__captured, 1)), SIGQUIT); \
295 mctest_assert_int_eq (*((int *) g_ptr_array_index(signal_signum__captured, 2)), SIGTSTP); \
296 mctest_assert_int_eq (*((int *) g_ptr_array_index(signal_signum__captured, 3)), SIGCHLD); \
297 \
298 VERIFY_SIGNAL_HANDLER_IS_SIG_DFL (0); \
299 VERIFY_SIGNAL_HANDLER_IS_SIG_DFL (1); \
300 VERIFY_SIGNAL_HANDLER_IS_SIG_DFL (2); \
301 VERIFY_SIGNAL_HANDLER_IS_SIG_DFL (3); \
302 }
303
304 /* --------------------------------------------------------------------------------------------- */
305
306 /* @Before */
307 static void
setup(void)308 setup (void)
309 {
310 signal__return_value = NULL;
311
312 sigaction__init ();
313 signal__init ();
314 execvp__init ();
315 }
316
317 /* --------------------------------------------------------------------------------------------- */
318
319 /* @After */
320 static void
teardown(void)321 teardown (void)
322 {
323 execvp__deinit ();
324 signal__deinit ();
325 sigaction__deinit ();
326 }
327
328 /* --------------------------------------------------------------------------------------------- */
329