allow path lookup for pipestream
[libi2ncommon] / test / test_pipestream.cpp
1 /*
2  *  The software in this package is distributed under the GNU General
3  *  Public License version 2 (with a special exception described below).
4  *
5  *  A copy of GNU General Public License (GPL) is included in this distribution,
6  *  in the file COPYING.GPL.
7  *
8  *  As a special exception, if other files instantiate templates or use macros
9  *  or inline functions from this file, or you compile this file and link it
10  *  with other works to produce a work based on this file, this file
11  *  does not by itself cause the resulting work to be covered
12  *  by the GNU General Public License.
13  *
14  *  However the source code for this file must still be made available
15  *  in accordance with section (3) of the GNU General Public License.
16  *
17  *  This exception does not invalidate any other reasons why a work based
18  *  on this file might be covered by the GNU General Public License.
19  *
20  * @file
21  *
22  * unit tests for the module "pipestream"
23  *
24  * Copyright 2018 by Intra2net AG
25  */
26
27 #define BOOST_TEST_IGNORE_NON_ZERO_CHILD_CODE
28
29 #define BOOST_TEST_DYN_LINK
30 #include <boost/test/unit_test.hpp>
31
32 #include "stringfunc.hxx"
33 #include "pipestream.hxx"
34
35 #define TO_CHARP_TOK(x) #x
36 #define TO_CHARP(x) TO_CHARP_TOK(x)
37
38 BOOST_AUTO_TEST_SUITE(pipestream)
39
40     BOOST_AUTO_TEST_SUITE(read)
41
42         # define ENOUGH_ZEROS 42
43         const char *const zero_bytes_argv [] =
44                 { "/usr/bin/head", "-c", TO_CHARP(ENOUGH_ZEROS), "/dev/zero", NULL };
45
46         BOOST_AUTO_TEST_CASE(abspath_zeros_shell_ok)
47         {
48             const std::string result =
49                     capture_exec (I2n::join_string (zero_bytes_argv, " "));
50
51             BOOST_CHECK_EQUAL(result.size (), ENOUGH_ZEROS);
52         }
53
54         BOOST_AUTO_TEST_CASE(abspath_zeros_shell_ok_result)
55         {
56             ExecResult exres = ExecResult ();
57             const std::string result =
58                     capture_exec (I2n::join_string (zero_bytes_argv, " "),
59                                   exres);
60
61             BOOST_CHECK(exres.normal_exit);
62             BOOST_CHECK_EQUAL(exres.return_code, 0);
63             BOOST_CHECK(!exres.terminated_by_signal);
64             BOOST_CHECK_EQUAL(result.size (), ENOUGH_ZEROS);
65         }
66
67         BOOST_AUTO_TEST_CASE(abspath_zeros_noshell_ok)
68         {
69             const std::string result = capture_exec (zero_bytes_argv);
70
71             BOOST_CHECK_EQUAL(result.size (), ENOUGH_ZEROS);
72         }
73
74         BOOST_AUTO_TEST_CASE(abspath_zeros_noshell_ok_strvec)
75         {
76             std::vector<std::string> argvec;
77             const char *const *argp = zero_bytes_argv;
78             const char *       cur  = NULL;
79
80             while ((cur = *argp++) != NULL) {
81                 argvec.push_back (std::string (cur));
82             }
83
84             const std::string result = capture_exec (argvec);
85
86             BOOST_CHECK_EQUAL(result.size (), ENOUGH_ZEROS);
87         }
88
89         BOOST_AUTO_TEST_CASE(abspath_zeros_noshell_ok_result)
90         {
91             ExecResult exres = ExecResult ();
92             const std::string result = capture_exec (zero_bytes_argv, exres);
93
94             BOOST_CHECK(exres.normal_exit);
95             BOOST_CHECK_EQUAL(exres.return_code, 0);
96             BOOST_CHECK(!exres.terminated_by_signal);
97             BOOST_CHECK_EQUAL(result.size (), ENOUGH_ZEROS);
98         }
99
100         const char *const bad_command [] = { "/does_not_exist", NULL };
101
102         BOOST_AUTO_TEST_CASE(abspath_bad_shell_fail)
103         {
104             assert (access(bad_command [0], X_OK) != 0);
105
106             ExecResult exres = ExecResult ();
107             /*
108              * Note that the next line will make the unit test spew a message
109              * to stderr which cannot be prevented due to the limitations of
110              * popen(3).
111              */
112             const std::string result =
113                     capture_exec (I2n::join_string (bad_command, " "));
114
115             BOOST_CHECK_EQUAL(result.size (), 0);
116         }
117
118         BOOST_AUTO_TEST_CASE(abspath_bad_noshell_fail)
119         {
120             assert (access(bad_command [0], X_OK) != 0);
121
122             ExecResult exres = ExecResult ();
123             const std::string result = capture_exec (bad_command, exres);
124
125             BOOST_CHECK(!exres.terminated_by_signal);
126             BOOST_CHECK_EQUAL(result.size (), 0);
127         }
128
129         BOOST_AUTO_TEST_CASE(abspath_bad_noshell_stderr)
130         {
131             assert (access(bad_command [0], X_OK) != 0);
132
133             ExecResult exres = ExecResult ();
134             const std::string result = capture_exec (bad_command, exres, false, true);
135
136             BOOST_CHECK(!exres.terminated_by_signal);
137             BOOST_CHECK_EQUAL(result.size (), 0);
138         }
139
140         const char *const false_argv_abs [] = { "/bin/false", NULL };
141         const char *const true_argv_abs  [] = { "/bin/true" , NULL };
142         const char *const false_argv_rel [] = { "false"     , NULL };
143         const char *const true_argv_rel  [] = { "true"      , NULL };
144
145         BOOST_AUTO_TEST_CASE(abspath_false_noshell_fail_exit)
146         {
147             ExecResult exres = ExecResult ();
148             const std::string result =
149                 capture_exec (false_argv_abs, exres, true, false, false);
150
151             BOOST_CHECK(exres.normal_exit);
152             BOOST_CHECK_EQUAL(exres.return_code, EXIT_FAILURE);
153             BOOST_CHECK_EQUAL(result.size (), 0);
154         }
155
156         BOOST_AUTO_TEST_CASE(abspath_false_shell_fail_exit)
157         {
158             ExecResult exres = ExecResult ();
159             const std::string result =
160                     capture_exec (std::string (false_argv_abs [0]), exres);
161
162             BOOST_CHECK(exres.normal_exit);
163             BOOST_CHECK_EQUAL(exres.return_code, EXIT_FAILURE);
164             BOOST_CHECK_EQUAL(result.size (), 0);
165         }
166
167         BOOST_AUTO_TEST_CASE(relpath_true_noshell_ok)
168         {
169             ExecResult exres = ExecResult ();
170             const std::string result =
171                 capture_exec (true_argv_rel, exres, true, false, true);
172
173             BOOST_CHECK(exres.normal_exit);
174             BOOST_CHECK_EQUAL(exres.return_code, EXIT_SUCCESS);
175             BOOST_CHECK_EQUAL(result.size (), 0);
176         }
177
178         BOOST_AUTO_TEST_CASE(relpath_true_noshell_fail)
179         {
180             ExecResult exres = ExecResult ();
181             const std::string result =
182                 capture_exec (true_argv_rel, exres, true, false, false);
183
184             BOOST_CHECK(exres.normal_exit);
185             /* no return code check since we couln't exit */
186             BOOST_CHECK_EQUAL(result.size (), 0);
187         }
188
189         BOOST_AUTO_TEST_CASE(abspath_true_noshell_ok)
190         {
191             ExecResult exres = ExecResult ();
192             const std::string result =
193                 capture_exec (true_argv_abs, exres, true, false, true);
194
195             BOOST_CHECK(exres.normal_exit);
196             BOOST_CHECK_EQUAL(exres.return_code, EXIT_SUCCESS);
197             BOOST_CHECK_EQUAL(result.size (), 0);
198         }
199
200         BOOST_AUTO_TEST_CASE(relpath_false_noshell_fail)
201         {
202             ExecResult exres = ExecResult ();
203             const std::string result =
204                 capture_exec (false_argv_rel, exres, true, false, true);
205
206             BOOST_CHECK(exres.normal_exit);
207             /* no return code check since we couln't exit */
208             BOOST_CHECK_EQUAL(result.size (), 0);
209         }
210
211     BOOST_AUTO_TEST_SUITE_END() /* [pipestream->read] */
212
213 BOOST_AUTO_TEST_SUITE_END() /* [pipestream] */
214