libamxp  1.4.0
Patterns C Implementation
test_proc_ctrl.c
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** SPDX-License-Identifier: BSD-2-Clause-Patent
4 **
5 ** SPDX-FileCopyrightText: Copyright (c) 2023 SoftAtHome
6 **
7 ** Redistribution and use in source and binary forms, with or without modification,
8 ** are permitted provided that the following conditions are met:
9 **
10 ** 1. Redistributions of source code must retain the above copyright notice,
11 ** this list of conditions and the following disclaimer.
12 **
13 ** 2. Redistributions in binary form must reproduce the above copyright notice,
14 ** this list of conditions and the following disclaimer in the documentation
15 ** and/or other materials provided with the distribution.
16 **
17 ** Subject to the terms and conditions of this license, each copyright holder
18 ** and contributor hereby grants to those receiving rights under this license
19 ** a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable
20 ** (except for failure to satisfy the conditions of this license) patent license
21 ** to make, have made, use, offer to sell, sell, import, and otherwise transfer
22 ** this software, where such license applies only to those patent claims, already
23 ** acquired or hereafter acquired, licensable by such copyright holder or contributor
24 ** that are necessarily infringed by:
25 **
26 ** (a) their Contribution(s) (the licensed copyrights of copyright holders and
27 ** non-copyrightable additions of contributors, in source or binary form) alone;
28 ** or
29 **
30 ** (b) combination of their Contribution(s) with the work of authorship to which
31 ** such Contribution(s) was added by such copyright holder or contributor, if,
32 ** at the time the Contribution is added, such addition causes such combination
33 ** to be necessarily infringed. The patent license shall not apply to any other
34 ** combinations which include the Contribution.
35 **
36 ** Except as expressly stated above, no rights or licenses from any copyright
37 ** holder or contributor is granted under this license, whether expressly, by
38 ** implication, estoppel or otherwise.
39 **
40 ** DISCLAIMER
41 **
42 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
43 ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
46 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
48 ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
49 ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50 ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
51 ** USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 **
53 ****************************************************************************/
54 
55 #ifndef _GNU_SOURCE
56 #define _GNU_SOURCE
57 #endif
58 
59 #include <stdlib.h>
60 #include <stdio.h>
61 #include <setjmp.h>
62 #include <stdarg.h>
63 #include <cmocka.h>
64 #include <string.h>
65 
66 #include <amxc/amxc.h>
67 #include <amxp/amxp.h>
68 
69 #include "test_proc_ctrl.h"
70 
71 static amxc_string_t path;
72 
73 #include <amxc/amxc_macros.h>
74 int __wrap_kill(pid_t pid, int sig);
75 
76 FILE* __wrap_fopen(const char* pathname, const char* mode);
77 FILE* __real_fopen(const char* pathname, const char* mode);
78 
79 ssize_t __wrap_getline(char** lineptr, size_t* n, FILE* stream);
80 ssize_t __real_getline(char** lineptr, size_t* n, FILE* stream);
81 
82 int __wrap_amxc_var_init(amxc_var_t* const var);
83 int __real_amxc_var_init(amxc_var_t* const var);
84 
85 static void read_sigalrm(void) {
86  sigset_t mask;
87  int sfd;
88  struct signalfd_siginfo fdsi;
89  ssize_t s;
90 
91  sigemptyset(&mask);
92  sigaddset(&mask, SIGALRM);
93 
94  sigprocmask(SIG_BLOCK, &mask, NULL);
95 
96  sfd = signalfd(-1, &mask, 0);
97  s = read(sfd, &fdsi, sizeof(struct signalfd_siginfo));
98  assert_int_equal(s, sizeof(struct signalfd_siginfo));
99  if(fdsi.ssi_signo == SIGALRM) {
100  printf("Got SIGALRM\n");
101  } else {
102  printf("Read unexpected signal\n");
103  }
104 }
105 
106 static void handle_events(void) {
107  printf("Handling events ");
108  while(amxp_signal_read() == 0) {
109  printf(".");
110  }
111  printf("\n");
112 }
113 
114 static int test_cmd_builder(amxc_array_t* cmd, UNUSED amxc_var_t* settings) {
115  int rv = mock();
116 
117  if(rv == 0) {
118  amxc_array_append_data(cmd, strdup("sleep "));
119  amxc_array_append_data(cmd, strdup("10m"));
120  }
121 
122  return rv;
123 }
124 
125 int __wrap_kill(UNUSED pid_t pid, UNUSED int sig) {
126  return 0;
127 }
128 
129 FILE* __wrap_fopen(const char* pathname, const char* mode) {
130  const char* f = amxc_string_get(&path, 0);
131  if(f != NULL) {
132  if(strcmp(pathname, f) == 0) {
133  return __real_fopen("./test_child_pids.txt", mode);
134  } else {
135  return __real_fopen(pathname, mode);
136  }
137  } else {
138  return __real_fopen(pathname, mode);
139  }
140 }
141 
142 int __wrap_amxc_var_init(amxc_var_t* const var) {
143  int rv = mock();
144 
145  if(rv == 0) {
146  rv = __real_amxc_var_init(var);
147  }
148 
149  return rv;
150 }
151 
152 ssize_t __wrap_getline(char** lineptr, size_t* n, FILE* stream) {
153  ssize_t rv = mock();
154 
155  if(rv == 0) {
156  return __real_getline(lineptr, n, stream);
157  }
158 
159  return rv;
160 }
161 
162 void test_proc_ctrl_new_delete(UNUSED void** state) {
163  amxp_proc_ctrl_t* ctrl = NULL;
164 
165  will_return(__wrap_amxc_var_init, 0);
166  assert_int_equal(amxp_proc_ctrl_new(&ctrl, test_cmd_builder), 0);
167  assert_non_null(ctrl);
168  assert_non_null(ctrl->proc);
169  assert_non_null(ctrl->timer);
170  assert_int_equal(amxc_var_type_of(&ctrl->child_proc_pids), AMXC_VAR_ID_NULL);
171 
172  amxp_proc_ctrl_delete(&ctrl);
173  assert_null(ctrl);
174 
175  will_return(__wrap_amxc_var_init, -1);
176  assert_int_not_equal(amxp_proc_ctrl_new(&ctrl, test_cmd_builder), 0);
177  assert_null(ctrl);
178 
179  assert_int_not_equal(amxp_proc_ctrl_new(NULL, test_cmd_builder), 0);
180  assert_int_not_equal(amxp_proc_ctrl_new(&ctrl, NULL), 0);
181  assert_null(ctrl);
182  amxp_proc_ctrl_delete(NULL);
183 }
184 
185 void test_proc_ctrl_start_stop(UNUSED void** state) {
186  amxc_var_t settings;
187  amxp_proc_ctrl_t* ctrl = NULL;
188 
189  will_return_always(__wrap_amxc_var_init, 0);
190  will_return_always(__wrap_getline, 0);
191 
192  amxc_var_init(&settings);
193 
194  assert_int_equal(amxp_proc_ctrl_new(&ctrl, test_cmd_builder), 0);
195 
196  will_return(test_cmd_builder, 0);
197  assert_int_equal(amxp_proc_ctrl_start(ctrl, 0, &settings), 0);
198  assert_true(ctrl->proc->is_running);
199 
200  assert_int_equal(amxp_proc_ctrl_stop(ctrl), 0);
201  assert_false(ctrl->proc->is_running);
202 
203  will_return(test_cmd_builder, -1);
204  assert_int_not_equal(amxp_proc_ctrl_start(ctrl, 0, &settings), 0);
205 
206  will_return(test_cmd_builder, 0);
207  assert_int_equal(amxp_proc_ctrl_start(ctrl, 0, NULL), 0);
208  assert_true(ctrl->proc->is_running);
209 
210  assert_int_equal(amxp_proc_ctrl_stop(ctrl), 0);
211  handle_events();
212  assert_false(ctrl->proc->is_running);
213 
214  amxp_proc_ctrl_delete(&ctrl);
215 
216  assert_int_not_equal(amxp_proc_ctrl_start(NULL, 0, &settings), 0);
217  assert_int_not_equal(amxp_proc_ctrl_stop(NULL), 0);
218 
219  amxc_var_clean(&settings);
220 }
221 
223  amxc_var_t settings;
224  amxp_proc_ctrl_t* ctrl = NULL;
225 
226  will_return_always(__wrap_amxc_var_init, 0);
227  will_return_always(__wrap_getline, 0);
228 
229  amxc_var_init(&settings);
230 
231  assert_int_equal(amxp_proc_ctrl_new(&ctrl, test_cmd_builder), 0);
232 
233  will_return(test_cmd_builder, 0);
234  assert_int_equal(amxp_proc_ctrl_start(ctrl, 1, &settings), 0);
235  assert_true(ctrl->proc->is_running);
236 
237  read_sigalrm();
240  handle_events();
241 
242  assert_false(amxp_subproc_is_running(ctrl->proc));
243 
244  amxp_proc_ctrl_delete(&ctrl);
245  amxc_var_clean(&settings);
246 }
247 
249  amxc_var_t settings;
250  amxp_proc_ctrl_t* ctrl = NULL;
251 
252  will_return_always(__wrap_amxc_var_init, 0);
253  will_return_always(__wrap_getline, 0);
254 
255  amxc_var_init(&settings);
256 
257  assert_int_equal(amxp_proc_ctrl_new(&ctrl, test_cmd_builder), 0);
258 
259  will_return(test_cmd_builder, 0);
260  assert_int_equal(amxp_proc_ctrl_start(ctrl, 0, &settings), 0);
261  assert_true(ctrl->proc->is_running);
262 
264 
265  read_sigalrm();
268  handle_events();
269 
270  assert_false(amxp_subproc_is_running(ctrl->proc));
271 
272  amxp_proc_ctrl_delete(&ctrl);
273  amxc_var_clean(&settings);
274 }
275 
276 void test_proc_can_stop_timer(UNUSED void** state) {
277  amxc_var_t settings;
278  amxp_proc_ctrl_t* ctrl = NULL;
279 
280  will_return_always(__wrap_amxc_var_init, 0);
281  will_return_always(__wrap_getline, 0);
282 
283  amxc_var_init(&settings);
284 
285  assert_int_equal(amxp_proc_ctrl_new(&ctrl, test_cmd_builder), 0);
286 
287  will_return(test_cmd_builder, 0);
288  assert_int_equal(amxp_proc_ctrl_start(ctrl, 1, &settings), 0);
289  assert_true(ctrl->proc->is_running);
290  assert_int_equal(amxp_timer_get_state(ctrl->timer), amxp_timer_running);
293  assert_int_equal(amxp_timer_get_state(ctrl->timer), amxp_timer_running);
294 
296  assert_int_equal(amxp_timer_get_state(ctrl->timer), amxp_timer_off);
297 
298  amxp_proc_ctrl_delete(&ctrl);
299  amxc_var_clean(&settings);
300 }
301 
303  amxc_var_t settings;
304  amxp_proc_ctrl_t* ctrl = NULL;
305 
306  amxc_string_init(&path, 0);
307  will_return_always(__wrap_amxc_var_init, 0);
308  will_return_always(__wrap_getline, 0);
309  will_return_always(test_cmd_builder, 0);
310 
311  amxc_var_init(&settings);
312 
313  assert_int_equal(amxp_proc_ctrl_new(&ctrl, test_cmd_builder), 0);
314  assert_int_equal(amxp_proc_ctrl_start(ctrl, 0, &settings), 0);
315 
316  amxc_string_setf(&path, "/proc/%d/task/%d/children", ctrl->proc->pid, ctrl->proc->pid);
317  assert_int_equal(amxp_proc_ctrl_get_child_pids(ctrl), 3);
319 
320  amxp_proc_ctrl_delete(&ctrl);
321  amxc_string_clean(&path);
322  amxc_var_clean(&settings);
323 }
static sigset_t mask
Definition: amxp_syssig.c:68
#define UNUSED
Definition: main.c:68
int amxp_proc_ctrl_stop(amxp_proc_ctrl_t *proc)
Stops the child process.
void amxp_proc_ctrl_set_active_duration(amxp_proc_ctrl_t *proc, uint32_t minutes)
Sets the active time durations.
int amxp_proc_ctrl_new(amxp_proc_ctrl_t **proc, amxp_proc_ctrl_cmd_t cmd_build_fn)
Allocates and initializes an amxp_proc_ctrl_t.
int amxp_proc_ctrl_start(amxp_proc_ctrl_t *proc, uint32_t minutes, amxc_var_t *settings)
Launches the child process.
void amxp_proc_ctrl_delete(amxp_proc_ctrl_t **proc)
Clean-up and frees previously allocated memory.
void amxp_proc_ctrl_stop_childs(amxp_proc_ctrl_t *proc)
Stop all child processes of the child process.
int amxp_proc_ctrl_get_child_pids(amxp_proc_ctrl_t *proc)
Fetches the process ids of the children of the launched child process.
int amxp_signal_read(void)
Reads from the amxp signal file descriptor.
Definition: amxp_signal.c:769
bool amxp_subproc_is_running(const amxp_subproc_t *const subproc)
Checks if the child process is running.
Definition: amxp_subproc.c:423
amxp_timer_state_t amxp_timer_get_state(amxp_timer_t *timer)
Get the timer's state.
Definition: amxp_timer.c:334
void amxp_timers_check(void)
Check all timers and call the callback function when the timer is in Timer expired state.
Definition: amxp_timer.c:183
void amxp_timers_calculate(void)
Caclulates the remaining time of all timers.
Definition: amxp_timer.c:144
@ amxp_timer_off
Definition: amxp_timer.h:149
@ amxp_timer_running
Definition: amxp_timer.h:151
Structure containing the child process control.
amxp_timer_t * timer
amxc_var_t child_proc_pids
amxp_subproc_t * proc
bool is_running
Definition: amxp_subproc.h:90
int __wrap_kill(pid_t pid, int sig)
static int test_cmd_builder(amxc_array_t *cmd, UNUSED amxc_var_t *settings)
int __real_amxc_var_init(amxc_var_t *const var)
int __wrap_amxc_var_init(amxc_var_t *const var)
FILE * __real_fopen(const char *pathname, const char *mode)
void test_proc_is_stopped_when_timer_expires(UNUSED void **state)
ssize_t __real_getline(char **lineptr, size_t *n, FILE *stream)
static void read_sigalrm(void)
void test_proc_ctrl_start_stop(UNUSED void **state)
void test_proc_can_stop_children(UNUSED void **state)
void test_proc_ctrl_new_delete(UNUSED void **state)
ssize_t __wrap_getline(char **lineptr, size_t *n, FILE *stream)
void test_proc_can_stop_timer(UNUSED void **state)
static amxc_string_t path
void test_proc_is_stopped_when_timer_is_set_after_start(UNUSED void **state)
static void handle_events(void)
FILE * __wrap_fopen(const char *pathname, const char *mode)