libamxp  1.4.0
Patterns C Implementation
test_subproc.c File Reference
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <cmocka.h>
#include <amxc/amxc_variant.h>
#include <amxc/amxc_lqueue.h>
#include <amxp/amxp_subproc.h>
#include <amxp/amxp_syssig.h>
#include <amxp/amxp_slot.h>
#include "test_subproc.h"
#include <amxc/amxc_macros.h>

Go to the source code of this file.

Functions

static void slot_test_subproc_stop (UNUSED const char *const sig_name, UNUSED const amxc_var_t *const data, UNUSED void *const priv)
 
static void handle_events (void)
 
void test_subproc_new_delete (UNUSED void **state)
 
void test_subproc_open_fd (UNUSED void **state)
 
void test_subproc_vstart (UNUSED void **state)
 
void test_subproc_astart (UNUSED void **state)
 
void test_subproc_vstart_read_stdout (UNUSED void **state)
 
void test_subproc_start_read_stdout (UNUSED void **state)
 
void test_subproc_start_crashing_app (UNUSED void **state)
 
void test_subproc_kill (UNUSED void **state)
 
void test_subproc_wait (UNUSED void **state)
 
void test_subproc_helper_functions (UNUSED void **state)
 

Variables

static bool subproc_is_running = false
 

Function Documentation

◆ handle_events()

static void handle_events ( void  )
static

Definition at line 84 of file test_subproc.c.

84  {
85  printf("Handling events ");
86  while(amxp_signal_read() == 0) {
87  printf(".");
88  }
89  printf("\n");
90 }
int amxp_signal_read(void)
Reads from the amxp signal file descriptor.
Definition: amxp_signal.c:769

◆ slot_test_subproc_stop()

static void slot_test_subproc_stop ( UNUSED const char *const  sig_name,
UNUSED const amxc_var_t *const  data,
UNUSED void *const  priv 
)
static

Definition at line 77 of file test_subproc.c.

79  {
80  subproc_is_running = false;
81 }
static bool subproc_is_running
Definition: test_subproc.c:75

◆ test_subproc_astart()

void test_subproc_astart ( UNUSED void **  state)

Definition at line 171 of file test_subproc.c.

171  {
172  amxp_subproc_t* subproc = NULL;
173  amxc_array_t cmd;
174 
175  amxc_array_init(&cmd, 2);
176  amxc_array_append_data(&cmd, "ls");
177  amxc_array_append_data(&cmd, "-la");
178 
179  assert_int_equal(amxp_subproc_new(&subproc), 0);
180  assert_ptr_not_equal(subproc, NULL);
181 
183  assert_int_equal(amxp_subproc_astart(subproc, &cmd), 0);
184  subproc_is_running = true;
185  assert_true(amxp_subproc_is_running(subproc));
186  assert_int_equal(amxp_subproc_astart(subproc, &cmd), -1);
187 
188  while(amxp_syssig_read() == -1) {
189  printf("Waiting for sigchld");
190  sleep(1);
191  }
192 
193  handle_events();
194 
195  assert_false(subproc_is_running);
196  assert_false(amxp_subproc_is_running(subproc));
197 
198  assert_int_equal(amxp_subproc_astart(NULL, NULL), -1);
199  assert_int_equal(amxp_subproc_astart(subproc, NULL), -1);
200 
201  amxc_array_clean(&cmd, NULL);
202  assert_int_equal(amxp_subproc_astart(subproc, &cmd), -1);
203 
204  assert_int_equal(amxp_subproc_delete(&subproc), 0);
205  assert_ptr_equal(subproc, NULL);
206 }
int amxp_slot_connect(amxp_signal_mngr_t *const sig_mngr, const char *const sig_name, const char *const expression, amxp_slot_fn_t fn, void *const priv)
Connects a slot (function) to a named signal of a signal manager.
Definition: amxp_slot.c:300
bool amxp_subproc_is_running(const amxp_subproc_t *const subproc)
Checks if the child process is running.
Definition: amxp_subproc.c:423
int amxp_subproc_new(amxp_subproc_t **subproc)
Constructor function, creates a new child process data structure.
Definition: amxp_subproc.c:215
int amxp_subproc_astart(amxp_subproc_t *const subproc, amxc_array_t *cmd)
Start a child process.
Definition: amxp_subproc.c:365
amxp_signal_mngr_t * amxp_subproc_get_sigmngr(const amxp_subproc_t *const subproc)
Get the Signal managers of the child process.
Definition: amxp_subproc.c:419
int amxp_subproc_delete(amxp_subproc_t **subproc)
Destructor function, deletes a child process data structure.
Definition: amxp_subproc.c:239
int amxp_syssig_read(void)
Reads from the file descriptor.
Definition: amxp_syssig.c:114
Child process information structure.
Definition: amxp_subproc.h:87
static void slot_test_subproc_stop(UNUSED const char *const sig_name, UNUSED const amxc_var_t *const data, UNUSED void *const priv)
Definition: test_subproc.c:77
static void handle_events(void)
Definition: test_subproc.c:84

◆ test_subproc_helper_functions()

void test_subproc_helper_functions ( UNUSED void **  state)

Definition at line 427 of file test_subproc.c.

427  {
428  int result;
429  int err;
430  amxp_subproc_t* subproc = NULL;
431  char* cmd_sleep_1[] = { "sleep", "2", NULL};
432 
433 
434  result = amxp_subproc_ifexited(NULL);
435  assert_int_equal(result, -1);
436 
437  result = amxp_subproc_ifsignaled(NULL);
438  assert_int_equal(result, -1);
439 
440  result = amxp_subproc_get_exitstatus(NULL);
441  assert_int_equal(result, -1);
442 
443  result = amxp_subproc_get_termsig(NULL);
444  assert_int_equal(result, -1);
445 
446  assert_int_equal(amxp_subproc_new(&subproc), 0);
447  assert_ptr_not_equal(subproc, NULL);
448 
449  err = amxp_subproc_vstart(subproc, cmd_sleep_1);
450  assert_int_equal(err, 0);
451  assert_true(amxp_subproc_is_running(subproc));
452 
453  err = amxp_subproc_wait(subproc, -1);
454  assert_int_equal(err, 0);
455  assert_false(amxp_subproc_is_running(subproc));
456 
457  result = amxp_subproc_ifexited(subproc);
458  assert_int_equal(result, 1);
459 
460  result = amxp_subproc_get_exitstatus(subproc);
461  assert_int_equal(result, 0);
462 
463  assert_int_equal(amxp_subproc_delete(&subproc), 0);
464  assert_int_equal(amxp_subproc_new(&subproc), 0);
465 
466  assert_int_equal(amxp_subproc_start(subproc, "test_app/a.out", "crash", NULL), 0);
467  assert_true(amxp_subproc_is_running(subproc));
468 
469  err = amxp_subproc_wait(subproc, -1);
470  assert_int_equal(err, 0);
471  assert_false(amxp_subproc_is_running(subproc));
472 
473  result = amxp_subproc_ifexited(subproc);
474  assert_int_equal(result, 0);
475 
476  assert_int_equal(amxp_subproc_delete(&subproc), 0);
477  assert_int_equal(amxp_subproc_new(&subproc), 0);
478 
479  assert_int_equal(amxp_subproc_start(subproc, "test_app/a.out", "wsignal", NULL), 0);
480  assert_true(amxp_subproc_is_running(subproc));
481 
482  amxp_subproc_kill(subproc, SIGTERM);
483 
484  err = amxp_subproc_wait(subproc, -1);
485  assert_int_equal(err, 0);
486  assert_false(amxp_subproc_is_running(subproc));
487 
488  result = amxp_subproc_ifexited(subproc);
489  assert_int_equal(result, 0);
490 
491  result = amxp_subproc_ifsignaled(subproc);
492  assert_int_equal(result, 1);
493 
494  result = amxp_subproc_get_termsig(subproc);
495  assert_int_equal(result, SIGTERM);
496 
497  assert_int_equal(amxp_subproc_delete(&subproc), 0);
498  assert_ptr_equal(subproc, NULL);
499 }
int amxp_subproc_get_exitstatus(amxp_subproc_t *subproc)
Gets the exit code of the child process.
Definition: amxp_subproc.c:537
int amxp_subproc_start(amxp_subproc_t *const subproc, char *cmd,...)
Start a child process.
Definition: amxp_subproc.c:330
int amxp_subproc_kill(const amxp_subproc_t *const subproc, const int sig)
Sends a Linux signal to the child process.
Definition: amxp_subproc.c:391
int amxp_subproc_ifexited(amxp_subproc_t *subproc)
Checks if the child process terminated normally.
Definition: amxp_subproc.c:517
int amxp_subproc_wait(amxp_subproc_t *subproc, int timeout_msec)
Waits until the child process has stopped.
Definition: amxp_subproc.c:428
int amxp_subproc_vstart(amxp_subproc_t *const subproc, char **argv)
Start a child process.
Definition: amxp_subproc.c:288
int amxp_subproc_ifsignaled(amxp_subproc_t *subproc)
Checks if the child process was stopped because of an uncaught Linux signal.
Definition: amxp_subproc.c:527
int amxp_subproc_get_termsig(amxp_subproc_t *subproc)
Gets the Linux signal id that caused the child process to stop.
Definition: amxp_subproc.c:547

◆ test_subproc_kill()

void test_subproc_kill ( UNUSED void **  state)

Definition at line 302 of file test_subproc.c.

302  {
303  amxp_subproc_t* subproc = NULL;
304 
305  assert_int_equal(amxp_subproc_new(&subproc), 0);
306  assert_ptr_not_equal(subproc, NULL);
307 
309 
310  assert_int_equal(amxp_subproc_start(subproc, "test_app/a.out", "wsignal", NULL), 0);
311  subproc_is_running = true;
312  assert_true(amxp_subproc_is_running(subproc));
313 
314  while(amxp_syssig_read() == -1) {
315  amxp_subproc_kill(subproc, SIGTERM);
316  sleep(1);
317  }
318 
319  handle_events();
320 
321  assert_false(subproc_is_running);
322  assert_false(amxp_subproc_is_running(subproc));
323 
324  assert_int_equal(amxp_subproc_delete(&subproc), 0);
325  assert_ptr_equal(subproc, NULL);
326 }

◆ test_subproc_new_delete()

void test_subproc_new_delete ( UNUSED void **  state)

Definition at line 92 of file test_subproc.c.

92  {
93  amxp_subproc_t* subproc = NULL;
94 
95  assert_int_not_equal(amxp_subproc_new(NULL), 0);
96  assert_int_not_equal(amxp_subproc_delete(NULL), 0);
97 
98  assert_int_equal(amxp_subproc_new(&subproc), 0);
99  assert_ptr_not_equal(subproc, NULL);
100  assert_int_not_equal(amxp_subproc_new(&subproc), 0);
101 
102  assert_false(subproc->is_running);
103  assert_false(amxp_subproc_is_running(subproc));
104  assert_false(amxp_subproc_is_running(NULL));
105  assert_int_equal(subproc->pid, 0);
106  assert_int_equal(amxp_subproc_get_pid(subproc), 0);
107  assert_int_equal(amxp_subproc_get_pid(NULL), -1);
108  for(int i = 0; i < 3; i++) {
109  for(int j = 0; j < 2; j++) {
110  assert_int_equal(subproc->fd[i][j], -1);
111  }
112  }
113 
114  assert_int_equal(amxp_subproc_delete(&subproc), 0);
115  assert_ptr_equal(subproc, NULL);
116 }
pid_t amxp_subproc_get_pid(const amxp_subproc_t *const subproc)
Get the PID of a child process.
Definition: amxp_subproc.c:415
int fd[3][2]
Definition: amxp_subproc.h:91
bool is_running
Definition: amxp_subproc.h:90

◆ test_subproc_open_fd()

void test_subproc_open_fd ( UNUSED void **  state)

Definition at line 118 of file test_subproc.c.

118  {
119  amxp_subproc_t* subproc = NULL;
120  int fd = -1;
121 
122  assert_int_equal(amxp_subproc_new(&subproc), 0);
123  assert_ptr_not_equal(subproc, NULL);
124 
125  assert_int_equal(amxp_subproc_open_fd(NULL, STDIN_FILENO), -1);
126 
127  fd = amxp_subproc_open_fd(subproc, STDOUT_FILENO);
128  assert_int_not_equal(fd, -1);
129  assert_int_equal(amxp_subproc_open_fd(subproc, STDOUT_FILENO), fd);
130  assert_int_not_equal(amxp_subproc_open_fd(subproc, STDERR_FILENO), -1);
131  assert_int_not_equal(amxp_subproc_open_fd(subproc, STDIN_FILENO), -1);
132  assert_int_equal(amxp_subproc_open_fd(subproc, 999), -1);
133  assert_int_equal(amxp_subproc_open_fd(subproc, -1), -1);
134 
135  assert_int_equal(amxp_subproc_delete(&subproc), 0);
136  assert_ptr_equal(subproc, NULL);
137 }
int amxp_subproc_open_fd(amxp_subproc_t *subproc, int requested)
Opens standard file descriptor to the child process.
Definition: amxp_subproc.c:263

◆ test_subproc_start_crashing_app()

void test_subproc_start_crashing_app ( UNUSED void **  state)

Definition at line 277 of file test_subproc.c.

277  {
278  amxp_subproc_t* subproc = NULL;
279 
280  assert_int_equal(amxp_subproc_new(&subproc), 0);
281  assert_ptr_not_equal(subproc, NULL);
282 
284 
285  assert_int_equal(amxp_subproc_start(subproc, "test_app/a.out", "crash", NULL), 0);
286  subproc_is_running = true;
287  assert_true(amxp_subproc_is_running(subproc));
288 
289  while(amxp_syssig_read() == -1) {
290  sleep(1);
291  }
292 
293  handle_events();
294 
295  assert_false(subproc_is_running);
296  assert_false(amxp_subproc_is_running(subproc));
297 
298  assert_int_equal(amxp_subproc_delete(&subproc), 0);
299  assert_ptr_equal(subproc, NULL);
300 }

◆ test_subproc_start_read_stdout()

void test_subproc_start_read_stdout ( UNUSED void **  state)

Definition at line 242 of file test_subproc.c.

242  {
243  amxp_subproc_t* subproc = NULL;
244  char buffer[1024] = "";
245  int fd = -1;
246 
247  assert_int_equal(amxp_subproc_new(&subproc), 0);
248  assert_ptr_not_equal(subproc, NULL);
249 
250  fd = amxp_subproc_open_fd(subproc, STDOUT_FILENO);
251  assert_int_not_equal(fd, -1);
253 
254  assert_ptr_equal(amxp_subproc_find(subproc->pid - 1), NULL);
255 
256  for(int i = 0; i < 2; i++) {
257  assert_int_equal(amxp_subproc_start(subproc, "ls", "-la", NULL), 0);
258  subproc_is_running = true;
259  assert_true(amxp_subproc_is_running(subproc));
260 
261  while(amxp_syssig_read() == -1) {
262  while(read(fd, buffer, 1023) > 0) {
263  printf("%s", buffer);
264  }
265  }
266 
267  handle_events();
268 
269  assert_false(subproc_is_running);
270  assert_false(amxp_subproc_is_running(subproc));
271  }
272 
273  assert_int_equal(amxp_subproc_delete(&subproc), 0);
274  assert_ptr_equal(subproc, NULL);
275 }
amxp_subproc_t * amxp_subproc_find(const int pid)
Retrieve a amxp_subproc_t for a child process using it's process identifier.
Definition: amxp_subproc.c:402

◆ test_subproc_vstart()

void test_subproc_vstart ( UNUSED void **  state)

Definition at line 139 of file test_subproc.c.

139  {
140  amxp_subproc_t* subproc = NULL;
141  char* cmd[] = { "ls", "-la", NULL };
142  char* cmd2[] = { NULL };
143 
144  assert_int_equal(amxp_subproc_new(&subproc), 0);
145  assert_ptr_not_equal(subproc, NULL);
146 
148  assert_int_equal(amxp_subproc_vstart(subproc, cmd), 0);
149  subproc_is_running = true;
150  assert_true(amxp_subproc_is_running(subproc));
151  assert_int_equal(amxp_subproc_vstart(subproc, cmd), -1);
152 
153  while(amxp_syssig_read() == -1) {
154  printf("Waiting for sigchld");
155  sleep(1);
156  }
157 
158  handle_events();
159 
160  assert_false(subproc_is_running);
161  assert_false(amxp_subproc_is_running(subproc));
162 
163  assert_int_equal(amxp_subproc_vstart(NULL, NULL), -1);
164  assert_int_equal(amxp_subproc_vstart(subproc, NULL), -1);
165  assert_int_equal(amxp_subproc_vstart(subproc, cmd2), -1);
166 
167  assert_int_equal(amxp_subproc_delete(&subproc), 0);
168  assert_ptr_equal(subproc, NULL);
169 }

◆ test_subproc_vstart_read_stdout()

void test_subproc_vstart_read_stdout ( UNUSED void **  state)

Definition at line 208 of file test_subproc.c.

208  {
209  amxp_subproc_t* subproc = NULL;
210  char buffer[1024] = "";
211  int fd = -1;
212  char* cmd[] = { "ls", "-la", NULL };
213 
214  assert_int_equal(amxp_subproc_new(&subproc), 0);
215  assert_ptr_not_equal(subproc, NULL);
216 
217  fd = amxp_subproc_open_fd(subproc, STDOUT_FILENO);
218  assert_int_not_equal(fd, -1);
220 
221  for(int i = 0; i < 2; i++) {
222  assert_int_equal(amxp_subproc_vstart(subproc, cmd), 0);
223  subproc_is_running = true;
224  assert_true(amxp_subproc_is_running(subproc));
225 
226  while(amxp_syssig_read() == -1) {
227  while(read(fd, buffer, 1023) > 0) {
228  printf("%s", buffer);
229  }
230  }
231 
232  handle_events();
233 
234  assert_false(subproc_is_running);
235  assert_false(amxp_subproc_is_running(subproc));
236  }
237 
238  assert_int_equal(amxp_subproc_delete(&subproc), 0);
239  assert_ptr_equal(subproc, NULL);
240 }

◆ test_subproc_wait()

void test_subproc_wait ( UNUSED void **  state)

Definition at line 328 of file test_subproc.c.

328  {
329  int err;
330 
331  amxp_subproc_t* subproc_sleep_10 = NULL;
332  char* cmd_sleep_10[] = { "sleep", "10", NULL};
333 
334  amxp_subproc_t* subproc_sleep_2 = NULL;
335  char* cmd_sleep_2[] = { "sleep", "2", NULL};
336 
337  assert_int_equal(amxp_subproc_new(&subproc_sleep_10), 0);
338  assert_ptr_not_equal(subproc_sleep_10, NULL);
339 
340  assert_int_equal(amxp_subproc_new(&subproc_sleep_2), 0);
341  assert_ptr_not_equal(subproc_sleep_2, NULL);
342 
343  // Test general behaviour (-1 --> no timeout)
344  err = amxp_subproc_vstart_wait(subproc_sleep_2, -1, cmd_sleep_2);
345  assert_int_equal(err, 0);
346  assert_false(amxp_subproc_is_running(subproc_sleep_2));
347 
348  // Test timeout (500ms)
349  err = amxp_subproc_vstart_wait(subproc_sleep_2, 500, cmd_sleep_2);
350  assert_int_equal(err, 1);
351  assert_true(amxp_subproc_is_running(subproc_sleep_2));
352 
353  // wait for (sleep 2) child to finish
354  err = amxp_subproc_wait(subproc_sleep_2, -1);
355  assert_int_equal(err, 0);
356  assert_false(amxp_subproc_is_running(subproc_sleep_2));
357 
358  // test for case of short running async child and long running sync child
359  // --> short running child
360  err = amxp_subproc_vstart(subproc_sleep_2, cmd_sleep_2);
361  assert_int_equal(err, 0);
362  assert_true(amxp_subproc_is_running(subproc_sleep_2));
363 
364  // --> long running child (no timeout)
365  err = amxp_subproc_vstart_wait(subproc_sleep_10, -1, cmd_sleep_10);
366  assert_int_equal(err, 0);
367  assert_false(amxp_subproc_is_running(subproc_sleep_2));
368  assert_false(amxp_subproc_is_running(subproc_sleep_10));
369 
370  // test for case of short running async child and long running sync child
371  // --> short running child
372  err = amxp_subproc_vstart(subproc_sleep_2, cmd_sleep_2);
373  assert_int_equal(err, 0);
374  assert_true(amxp_subproc_is_running(subproc_sleep_2));
375 
376  // --> long running child (with timeout but will finish normally)
377  err = amxp_subproc_vstart_wait(subproc_sleep_10, 15000, cmd_sleep_10);
378  assert_int_equal(err, 0);
379  assert_false(amxp_subproc_is_running(subproc_sleep_2));
380  assert_false(amxp_subproc_is_running(subproc_sleep_10));
381 
382  // test for case of short running async child and long running sync child
383  // --> short running child
384  err = amxp_subproc_vstart(subproc_sleep_2, cmd_sleep_2);
385  assert_int_equal(err, 0);
386  assert_true(amxp_subproc_is_running(subproc_sleep_2));
387 
388  // --> long running child (with timeout)
389  err = amxp_subproc_vstart_wait(subproc_sleep_10, 7500, cmd_sleep_10);
390  assert_int_equal(err, 1);
391  assert_false(amxp_subproc_is_running(subproc_sleep_2));
392  assert_true(amxp_subproc_is_running(subproc_sleep_10));
393 
394  // wait for (sleep 10) child to finish
395  err = amxp_subproc_wait(subproc_sleep_10, -1);
396  assert_int_equal(err, 0);
397  assert_false(amxp_subproc_is_running(subproc_sleep_2));
398 
399  // argument checking
400  err = amxp_subproc_vstart_wait(NULL, 4000, cmd_sleep_2);
401  assert_int_not_equal(err, 0);
402 
403  err = amxp_subproc_vstart_wait(subproc_sleep_2, 4000, NULL);
404  assert_int_not_equal(err, 0);
405 
406  // amxp_subproc_start_wait
407  err = amxp_subproc_start_wait(subproc_sleep_2, 4000, "sleep", "1", NULL);
408  assert_int_equal(err, 0);
409  assert_false(amxp_subproc_is_running(subproc_sleep_2));
410 
411  // argument checking
412  err = amxp_subproc_start_wait(NULL, 4000, "sleep", "1", NULL);
413  assert_int_not_equal(err, 0);
414 
415  // argument checking -- unfortunately doesnt detect non existing commands
416  err = amxp_subproc_start_wait(subproc_sleep_2, 4000, "non_existing_command", "1", NULL);
417  assert_int_equal(err, 0);
418 
419  // cleanup test
420  assert_int_equal(amxp_subproc_delete(&subproc_sleep_10), 0);
421  assert_ptr_equal(subproc_sleep_10, NULL);
422 
423  assert_int_equal(amxp_subproc_delete(&subproc_sleep_2), 0);
424  assert_ptr_equal(subproc_sleep_2, NULL);
425 }
int amxp_subproc_start_wait(amxp_subproc_t *subproc, int timeout_msec, char *cmd,...)
Starts a child process and waits until it exits.
Definition: amxp_subproc.c:480
int amxp_subproc_vstart_wait(amxp_subproc_t *subproc, int timeout_msec, char **cmd)
Starts a child process and waits until it exits.
Definition: amxp_subproc.c:466

Variable Documentation

◆ subproc_is_running

bool subproc_is_running = false
static

Definition at line 75 of file test_subproc.c.