LCOV - code coverage report
Current view: top level - test - test-exec-util.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 236 248 95.2 %
Date: 2019-08-22 15:41:25 Functions: 12 14 85.7 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <errno.h>
       4             : #include <string.h>
       5             : #include <sys/stat.h>
       6             : #include <sys/wait.h>
       7             : #include <unistd.h>
       8             : 
       9             : #include "alloc-util.h"
      10             : #include "copy.h"
      11             : #include "def.h"
      12             : #include "env-util.h"
      13             : #include "exec-util.h"
      14             : #include "fd-util.h"
      15             : #include "fileio.h"
      16             : #include "fs-util.h"
      17             : #include "log.h"
      18             : #include "macro.h"
      19             : #include "path-util.h"
      20             : #include "rm-rf.h"
      21             : #include "string-util.h"
      22             : #include "strv.h"
      23             : #include "tests.h"
      24             : 
      25             : static int here = 0, here2 = 0, here3 = 0;
      26             : void *ignore_stdout_args[] = {&here, &here2, &here3};
      27             : 
      28             : /* noop handlers, just check that arguments are passed correctly */
      29           5 : static int ignore_stdout_func(int fd, void *arg) {
      30           5 :         assert(fd >= 0);
      31           5 :         assert(arg == &here);
      32           5 :         safe_close(fd);
      33             : 
      34           5 :         return 0;
      35             : }
      36           0 : static int ignore_stdout_func2(int fd, void *arg) {
      37           0 :         assert(fd >= 0);
      38           0 :         assert(arg == &here2);
      39           0 :         safe_close(fd);
      40             : 
      41           0 :         return 0;
      42             : }
      43           2 : static int ignore_stdout_func3(int fd, void *arg) {
      44           2 :         assert(fd >= 0);
      45           2 :         assert(arg == &here3);
      46           2 :         safe_close(fd);
      47             : 
      48           2 :         return 0;
      49             : }
      50             : 
      51             : static const gather_stdout_callback_t ignore_stdout[] = {
      52             :         ignore_stdout_func,
      53             :         ignore_stdout_func2,
      54             :         ignore_stdout_func3,
      55             : };
      56             : 
      57           2 : static void test_execute_directory(bool gather_stdout) {
      58           2 :         char template_lo[] = "/tmp/test-exec-util.lo.XXXXXXX";
      59           2 :         char template_hi[] = "/tmp/test-exec-util.hi.XXXXXXX";
      60           2 :         const char * dirs[] = {template_hi, template_lo, NULL};
      61             :         const char *name, *name2, *name3,
      62             :                 *overridden, *override,
      63             :                 *masked, *mask,
      64             :                 *masked2, *mask2,   /* the mask is non-executable */
      65             :                 *masked2e, *mask2e; /* the mask is executable */
      66             : 
      67           2 :         log_info("/* %s (%s) */", __func__, gather_stdout ? "gathering stdout" : "asynchronous");
      68             : 
      69           2 :         assert_se(mkdtemp(template_lo));
      70           2 :         assert_se(mkdtemp(template_hi));
      71             : 
      72          10 :         name = strjoina(template_lo, "/script");
      73          10 :         name2 = strjoina(template_hi, "/script2");
      74          10 :         name3 = strjoina(template_lo, "/useless");
      75          10 :         overridden = strjoina(template_lo, "/overridden");
      76          10 :         override = strjoina(template_hi, "/overridden");
      77          10 :         masked = strjoina(template_lo, "/masked");
      78          10 :         mask = strjoina(template_hi, "/masked");
      79          10 :         masked2 = strjoina(template_lo, "/masked2");
      80          10 :         mask2 = strjoina(template_hi, "/masked2");
      81          10 :         masked2e = strjoina(template_lo, "/masked2e");
      82          10 :         mask2e = strjoina(template_hi, "/masked2e");
      83             : 
      84           2 :         assert_se(write_string_file(name,
      85             :                                     "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works",
      86             :                                     WRITE_STRING_FILE_CREATE) == 0);
      87           2 :         assert_se(write_string_file(name2,
      88             :                                     "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works2",
      89             :                                     WRITE_STRING_FILE_CREATE) == 0);
      90           2 :         assert_se(write_string_file(overridden,
      91             :                                     "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed",
      92             :                                     WRITE_STRING_FILE_CREATE) == 0);
      93           2 :         assert_se(write_string_file(override,
      94             :                                     "#!/bin/sh\necho 'Executing '$0",
      95             :                                     WRITE_STRING_FILE_CREATE) == 0);
      96           2 :         assert_se(write_string_file(masked,
      97             :                                     "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed",
      98             :                                     WRITE_STRING_FILE_CREATE) == 0);
      99           2 :         assert_se(write_string_file(masked2,
     100             :                                     "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed",
     101             :                                     WRITE_STRING_FILE_CREATE) == 0);
     102           2 :         assert_se(write_string_file(masked2e,
     103             :                                     "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed",
     104             :                                     WRITE_STRING_FILE_CREATE) == 0);
     105           2 :         assert_se(symlink("/dev/null", mask) == 0);
     106           2 :         assert_se(touch(mask2) == 0);
     107           2 :         assert_se(touch(mask2e) == 0);
     108           2 :         assert_se(touch(name3) >= 0);
     109             : 
     110           2 :         assert_se(chmod(name, 0755) == 0);
     111           2 :         assert_se(chmod(name2, 0755) == 0);
     112           2 :         assert_se(chmod(overridden, 0755) == 0);
     113           2 :         assert_se(chmod(override, 0755) == 0);
     114           2 :         assert_se(chmod(masked, 0755) == 0);
     115           2 :         assert_se(chmod(masked2, 0755) == 0);
     116           2 :         assert_se(chmod(masked2e, 0755) == 0);
     117           2 :         assert_se(chmod(mask2e, 0755) == 0);
     118             : 
     119           2 :         if (gather_stdout)
     120           1 :                 execute_directories(dirs, DEFAULT_TIMEOUT_USEC, ignore_stdout, ignore_stdout_args, NULL, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS);
     121             :         else
     122           1 :                 execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, NULL, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS);
     123             : 
     124           2 :         assert_se(chdir(template_lo) == 0);
     125           2 :         assert_se(access("it_works", F_OK) >= 0);
     126           2 :         assert_se(access("failed", F_OK) < 0);
     127             : 
     128           2 :         assert_se(chdir(template_hi) == 0);
     129           2 :         assert_se(access("it_works2", F_OK) >= 0);
     130           2 :         assert_se(access("failed", F_OK) < 0);
     131             : 
     132           2 :         (void) rm_rf(template_lo, REMOVE_ROOT|REMOVE_PHYSICAL);
     133           2 :         (void) rm_rf(template_hi, REMOVE_ROOT|REMOVE_PHYSICAL);
     134           2 : }
     135             : 
     136           1 : static void test_execution_order(void) {
     137           1 :         char template_lo[] = "/tmp/test-exec-util-lo.XXXXXXX";
     138           1 :         char template_hi[] = "/tmp/test-exec-util-hi.XXXXXXX";
     139           1 :         const char *dirs[] = {template_hi, template_lo, NULL};
     140             :         const char *name, *name2, *name3, *overridden, *override, *masked, *mask;
     141             :         const char *output, *t;
     142           1 :         _cleanup_free_ char *contents = NULL;
     143             : 
     144           1 :         assert_se(mkdtemp(template_lo));
     145           1 :         assert_se(mkdtemp(template_hi));
     146             : 
     147           5 :         output = strjoina(template_hi, "/output");
     148             : 
     149           1 :         log_info("/* %s >>%s */", __func__, output);
     150             : 
     151             :         /* write files in "random" order */
     152           5 :         name2 = strjoina(template_lo, "/90-bar");
     153           5 :         name = strjoina(template_hi, "/80-foo");
     154           5 :         name3 = strjoina(template_lo, "/last");
     155           5 :         overridden = strjoina(template_lo, "/30-override");
     156           5 :         override = strjoina(template_hi, "/30-override");
     157           5 :         masked = strjoina(template_lo, "/10-masked");
     158           5 :         mask = strjoina(template_hi, "/10-masked");
     159             : 
     160           5 :         t = strjoina("#!/bin/sh\necho $(basename $0) >>", output);
     161           1 :         assert_se(write_string_file(name, t, WRITE_STRING_FILE_CREATE) == 0);
     162             : 
     163           5 :         t = strjoina("#!/bin/sh\necho $(basename $0) >>", output);
     164           1 :         assert_se(write_string_file(name2, t, WRITE_STRING_FILE_CREATE) == 0);
     165             : 
     166           5 :         t = strjoina("#!/bin/sh\necho $(basename $0) >>", output);
     167           1 :         assert_se(write_string_file(name3, t, WRITE_STRING_FILE_CREATE) == 0);
     168             : 
     169           5 :         t = strjoina("#!/bin/sh\necho OVERRIDDEN >>", output);
     170           1 :         assert_se(write_string_file(overridden, t, WRITE_STRING_FILE_CREATE) == 0);
     171             : 
     172           5 :         t = strjoina("#!/bin/sh\necho $(basename $0) >>", output);
     173           1 :         assert_se(write_string_file(override, t, WRITE_STRING_FILE_CREATE) == 0);
     174             : 
     175           5 :         t = strjoina("#!/bin/sh\necho MASKED >>", output);
     176           1 :         assert_se(write_string_file(masked, t, WRITE_STRING_FILE_CREATE) == 0);
     177             : 
     178           1 :         assert_se(symlink("/dev/null", mask) == 0);
     179             : 
     180           1 :         assert_se(chmod(name, 0755) == 0);
     181           1 :         assert_se(chmod(name2, 0755) == 0);
     182           1 :         assert_se(chmod(name3, 0755) == 0);
     183           1 :         assert_se(chmod(overridden, 0755) == 0);
     184           1 :         assert_se(chmod(override, 0755) == 0);
     185           1 :         assert_se(chmod(masked, 0755) == 0);
     186             : 
     187           1 :         execute_directories(dirs, DEFAULT_TIMEOUT_USEC, ignore_stdout, ignore_stdout_args, NULL, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS);
     188             : 
     189           1 :         assert_se(read_full_file(output, &contents, NULL) >= 0);
     190           1 :         assert_se(streq(contents, "30-override\n80-foo\n90-bar\nlast\n"));
     191             : 
     192           1 :         (void) rm_rf(template_lo, REMOVE_ROOT|REMOVE_PHYSICAL);
     193           1 :         (void) rm_rf(template_hi, REMOVE_ROOT|REMOVE_PHYSICAL);
     194           1 : }
     195             : 
     196           2 : static int gather_stdout_one(int fd, void *arg) {
     197           2 :         char ***s = arg, *t;
     198           2 :         char buf[128] = {};
     199             : 
     200           2 :         assert_se(s);
     201           2 :         assert_se(read(fd, buf, sizeof buf) >= 0);
     202           2 :         safe_close(fd);
     203             : 
     204           2 :         assert_se(t = strndup(buf, sizeof buf));
     205           2 :         assert_se(strv_push(s, t) >= 0);
     206             : 
     207           2 :         return 0;
     208             : }
     209           0 : static int gather_stdout_two(int fd, void *arg) {
     210           0 :         char ***s = arg, **t;
     211             : 
     212           0 :         STRV_FOREACH(t, *s)
     213           0 :                 assert_se(write(fd, *t, strlen(*t)) == (ssize_t) strlen(*t));
     214           0 :         safe_close(fd);
     215             : 
     216           0 :         return 0;
     217             : }
     218           1 : static int gather_stdout_three(int fd, void *arg) {
     219           1 :         char **s = arg;
     220           1 :         char buf[128] = {};
     221             : 
     222           1 :         assert_se(read(fd, buf, sizeof buf - 1) > 0);
     223           1 :         safe_close(fd);
     224           1 :         assert_se(*s = strndup(buf, sizeof buf));
     225             : 
     226           1 :         return 0;
     227             : }
     228             : 
     229             : const gather_stdout_callback_t gather_stdout[] = {
     230             :         gather_stdout_one,
     231             :         gather_stdout_two,
     232             :         gather_stdout_three,
     233             : };
     234             : 
     235           1 : static void test_stdout_gathering(void) {
     236           1 :         char template[] = "/tmp/test-exec-util.XXXXXXX";
     237           1 :         const char *dirs[] = {template, NULL};
     238             :         const char *name, *name2, *name3;
     239             :         int r;
     240             : 
     241           1 :         char **tmp = NULL; /* this is only used in the forked process, no cleanup here */
     242           1 :         _cleanup_free_ char *output = NULL;
     243             : 
     244           1 :         void* args[] = {&tmp, &tmp, &output};
     245             : 
     246           1 :         assert_se(mkdtemp(template));
     247             : 
     248           1 :         log_info("/* %s */", __func__);
     249             : 
     250             :         /* write files */
     251           5 :         name = strjoina(template, "/10-foo");
     252           5 :         name2 = strjoina(template, "/20-bar");
     253           5 :         name3 = strjoina(template, "/30-last");
     254             : 
     255           1 :         assert_se(write_string_file(name,
     256             :                                     "#!/bin/sh\necho a\necho b\necho c\n",
     257             :                                     WRITE_STRING_FILE_CREATE) == 0);
     258           1 :         assert_se(write_string_file(name2,
     259             :                                     "#!/bin/sh\necho d\n",
     260             :                                     WRITE_STRING_FILE_CREATE) == 0);
     261           1 :         assert_se(write_string_file(name3,
     262             :                                     "#!/bin/sh\nsleep 1",
     263             :                                     WRITE_STRING_FILE_CREATE) == 0);
     264             : 
     265           1 :         assert_se(chmod(name, 0755) == 0);
     266           1 :         assert_se(chmod(name2, 0755) == 0);
     267           1 :         assert_se(chmod(name3, 0755) == 0);
     268             : 
     269           1 :         r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_stdout, args, NULL, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS);
     270           1 :         assert_se(r >= 0);
     271             : 
     272           1 :         log_info("got: %s", output);
     273             : 
     274           1 :         assert_se(streq(output, "a\nb\nc\nd\n"));
     275           1 : }
     276             : 
     277           1 : static void test_environment_gathering(void) {
     278           1 :         char template[] = "/tmp/test-exec-util.XXXXXXX", **p;
     279           1 :         const char *dirs[] = {template, NULL};
     280             :         const char *name, *name2, *name3, *old;
     281             :         int r;
     282             : 
     283           1 :         char **tmp = NULL; /* this is only used in the forked process, no cleanup here */
     284           1 :         _cleanup_strv_free_ char **env = NULL;
     285             : 
     286           1 :         void* const args[] = { &tmp, &tmp, &env };
     287             : 
     288           1 :         assert_se(mkdtemp(template));
     289             : 
     290           1 :         log_info("/* %s */", __func__);
     291             : 
     292             :         /* write files */
     293           5 :         name = strjoina(template, "/10-foo");
     294           5 :         name2 = strjoina(template, "/20-bar");
     295           5 :         name3 = strjoina(template, "/30-last");
     296             : 
     297           1 :         assert_se(write_string_file(name,
     298             :                                     "#!/bin/sh\n"
     299             :                                     "echo A=23\n",
     300             :                                     WRITE_STRING_FILE_CREATE) == 0);
     301           1 :         assert_se(write_string_file(name2,
     302             :                                     "#!/bin/sh\n"
     303             :                                     "echo A=22:$A\n\n\n",            /* substitution from previous generator */
     304             :                                     WRITE_STRING_FILE_CREATE) == 0);
     305           1 :         assert_se(write_string_file(name3,
     306             :                                     "#!/bin/sh\n"
     307             :                                     "echo A=$A:24\n"
     308             :                                     "echo B=12\n"
     309             :                                     "echo C=000\n"
     310             :                                     "echo C=001\n"                    /* variable overwriting */
     311             :                                      /* various invalid entries */
     312             :                                     "echo unset A\n"
     313             :                                     "echo unset A=\n"
     314             :                                     "echo unset A=B\n"
     315             :                                     "echo unset \n"
     316             :                                     "echo A B=C\n"
     317             :                                     "echo A\n"
     318             :                                     /* test variable assignment without newline */
     319             :                                     "echo PATH=$PATH:/no/such/file",   /* no newline */
     320             :                                     WRITE_STRING_FILE_CREATE) == 0);
     321             : 
     322           1 :         assert_se(chmod(name, 0755) == 0);
     323           1 :         assert_se(chmod(name2, 0755) == 0);
     324           1 :         assert_se(chmod(name3, 0755) == 0);
     325             : 
     326             :         /* When booting in containers or without initramfs there might not be
     327             :          * any PATH in the environment and if there is no PATH /bin/sh built-in
     328             :          * PATH may leak and override systemd's DEFAULT_PATH which is not
     329             :          * good. Force our own PATH in environment, to prevent expansion of sh
     330             :          * built-in $PATH */
     331           1 :         old = getenv("PATH");
     332           1 :         r = setenv("PATH", "no-sh-built-in-path", 1);
     333           1 :         assert_se(r >= 0);
     334             : 
     335           1 :         r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_environment, args, NULL, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS);
     336           1 :         assert_se(r >= 0);
     337             : 
     338           5 :         STRV_FOREACH(p, env)
     339           4 :                 log_info("got env: \"%s\"", *p);
     340             : 
     341           1 :         assert_se(streq(strv_env_get(env, "A"), "22:23:24"));
     342           1 :         assert_se(streq(strv_env_get(env, "B"), "12"));
     343           1 :         assert_se(streq(strv_env_get(env, "C"), "001"));
     344           1 :         assert_se(streq(strv_env_get(env, "PATH"), "no-sh-built-in-path:/no/such/file"));
     345             : 
     346             :         /* now retest with "default" path passed in, as created by
     347             :          * manager_default_environment */
     348           1 :         env = strv_free(env);
     349           1 :         env = strv_new("PATH=" DEFAULT_PATH);
     350           1 :         assert_se(env);
     351             : 
     352           1 :         r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_environment, args, NULL, env, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS);
     353           1 :         assert_se(r >= 0);
     354             : 
     355           5 :         STRV_FOREACH(p, env)
     356           4 :                 log_info("got env: \"%s\"", *p);
     357             : 
     358           1 :         assert_se(streq(strv_env_get(env, "A"), "22:23:24"));
     359           1 :         assert_se(streq(strv_env_get(env, "B"), "12"));
     360           1 :         assert_se(streq(strv_env_get(env, "C"), "001"));
     361           1 :         assert_se(streq(strv_env_get(env, "PATH"), DEFAULT_PATH ":/no/such/file"));
     362             : 
     363             :         /* reset environ PATH */
     364           1 :         if (old)
     365           1 :                 (void) setenv("PATH", old, 1);
     366             :         else
     367           0 :                 (void) unsetenv("PATH");
     368           1 : }
     369             : 
     370           1 : static void test_error_catching(void) {
     371           1 :         char template[] = "/tmp/test-exec-util.XXXXXXX";
     372           1 :         const char *dirs[] = {template, NULL};
     373             :         const char *name, *name2, *name3;
     374             :         int r;
     375             : 
     376           1 :         assert_se(mkdtemp(template));
     377             : 
     378           1 :         log_info("/* %s */", __func__);
     379             : 
     380             :         /* write files */
     381           5 :         name = strjoina(template, "/10-foo");
     382           5 :         name2 = strjoina(template, "/20-bar");
     383           5 :         name3 = strjoina(template, "/30-last");
     384             : 
     385           1 :         assert_se(write_string_file(name,
     386             :                                     "#!/bin/sh\necho a\necho b\necho c\n",
     387             :                                     WRITE_STRING_FILE_CREATE) == 0);
     388           1 :         assert_se(write_string_file(name2,
     389             :                                     "#!/bin/sh\nexit 42\n",
     390             :                                     WRITE_STRING_FILE_CREATE) == 0);
     391           1 :         assert_se(write_string_file(name3,
     392             :                                     "#!/bin/sh\nexit 12",
     393             :                                     WRITE_STRING_FILE_CREATE) == 0);
     394             : 
     395           1 :         assert_se(chmod(name, 0755) == 0);
     396           1 :         assert_se(chmod(name2, 0755) == 0);
     397           1 :         assert_se(chmod(name3, 0755) == 0);
     398             : 
     399           1 :         r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, NULL, NULL, EXEC_DIR_NONE);
     400             : 
     401             :         /* we should exit with the error code of the first script that failed */
     402           1 :         assert_se(r == 42);
     403           1 : }
     404             : 
     405           1 : static void test_exec_command_flags_from_strv(void) {
     406           1 :         ExecCommandFlags flags = 0;
     407           1 :         char **valid_strv = STRV_MAKE("no-env-expand", "no-setuid", "ignore-failure");
     408           1 :         char **invalid_strv = STRV_MAKE("no-env-expand", "no-setuid", "nonexistent-option", "ignore-failure");
     409             :         int r;
     410             : 
     411           1 :         r = exec_command_flags_from_strv(valid_strv, &flags);
     412             : 
     413           1 :         assert_se(r == 0);
     414           1 :         assert_se(FLAGS_SET(flags, EXEC_COMMAND_NO_ENV_EXPAND));
     415           1 :         assert_se(FLAGS_SET(flags, EXEC_COMMAND_NO_SETUID));
     416           1 :         assert_se(FLAGS_SET(flags, EXEC_COMMAND_IGNORE_FAILURE));
     417           1 :         assert_se(!FLAGS_SET(flags, EXEC_COMMAND_AMBIENT_MAGIC));
     418           1 :         assert_se(!FLAGS_SET(flags, EXEC_COMMAND_FULLY_PRIVILEGED));
     419             : 
     420           1 :         r = exec_command_flags_from_strv(invalid_strv, &flags);
     421             : 
     422           1 :         assert_se(r == -EINVAL);
     423           1 : }
     424             : 
     425           1 : static void test_exec_command_flags_to_strv(void) {
     426           1 :         _cleanup_strv_free_ char **opts = NULL, **empty_opts = NULL, **invalid_opts = NULL;
     427           1 :         ExecCommandFlags flags = 0;
     428             :         int r;
     429             : 
     430           1 :         flags |= (EXEC_COMMAND_AMBIENT_MAGIC|EXEC_COMMAND_NO_ENV_EXPAND|EXEC_COMMAND_IGNORE_FAILURE);
     431             : 
     432           1 :         r = exec_command_flags_to_strv(flags, &opts);
     433             : 
     434           1 :         assert_se(r == 0);
     435           1 :         assert_se(strv_equal(opts, STRV_MAKE("ignore-failure", "ambient", "no-env-expand")));
     436             : 
     437           1 :         r = exec_command_flags_to_strv(0, &empty_opts);
     438             : 
     439           1 :         assert_se(r == 0);
     440           1 :         assert_se(strv_equal(empty_opts, STRV_MAKE_EMPTY));
     441             : 
     442           1 :         flags = _EXEC_COMMAND_FLAGS_INVALID;
     443             : 
     444           1 :         r = exec_command_flags_to_strv(flags, &invalid_opts);
     445             : 
     446           1 :         assert_se(r == -EINVAL);
     447           1 : }
     448             : 
     449           1 : int main(int argc, char *argv[]) {
     450           1 :         test_setup_logging(LOG_DEBUG);
     451             : 
     452           1 :         test_execute_directory(true);
     453           1 :         test_execute_directory(false);
     454           1 :         test_execution_order();
     455           1 :         test_stdout_gathering();
     456           1 :         test_environment_gathering();
     457           1 :         test_error_catching();
     458           1 :         test_exec_command_flags_from_strv();
     459           1 :         test_exec_command_flags_to_strv();
     460             : 
     461           1 :         return 0;
     462             : }

Generated by: LCOV version 1.14