xref: /freebsd/contrib/atf/atf-c++/detail/process_test.cpp (revision 74036c4de983981ee2b23f91e285363293aa7c3c)
1 //
2 // Automated Testing Framework (atf)
3 //
4 // Copyright (c) 2008 The NetBSD Foundation, Inc.
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
9 // are met:
10 // 1. Redistributions of source code must retain the above copyright
11 //    notice, this list of conditions and the following disclaimer.
12 // 2. Redistributions in binary form must reproduce the above copyright
13 //    notice, this list of conditions and the following disclaimer in the
14 //    documentation and/or other materials provided with the distribution.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17 // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23 // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 //
29 
30 #include <cstdlib>
31 #include <cstring>
32 
33 #include "../macros.hpp"
34 
35 #include "process.hpp"
36 #include "test_helpers.hpp"
37 
38 // TODO: Testing the fork function is a huge task and I'm afraid of
39 // copy/pasting tons of stuff from the C version.  I'd rather not do that
40 // until some code can be shared, which cannot happen until the C++ binding
41 // is cleaned by a fair amount.  Instead... just rely (at the moment) on
42 // the system tests for the tools using this module.
43 
44 // ------------------------------------------------------------------------
45 // Auxiliary functions.
46 // ------------------------------------------------------------------------
47 
48 static
49 std::size_t
50 array_size(const char* const* array)
51 {
52     std::size_t size = 0;
53 
54     for (const char* const* ptr = array; *ptr != NULL; ptr++)
55         size++;
56 
57     return size;
58 }
59 
60 static
61 atf::process::status
62 exec_process_helpers(const atf::tests::tc& tc, const char* helper_name)
63 {
64     using atf::process::exec;
65 
66     std::vector< std::string > argv;
67     argv.push_back(get_process_helpers_path(tc, true).leaf_name());
68     argv.push_back(helper_name);
69 
70     return exec(get_process_helpers_path(tc, true),
71                 atf::process::argv_array(argv),
72                 atf::process::stream_inherit(),
73                 atf::process::stream_inherit());
74 }
75 
76 // ------------------------------------------------------------------------
77 // Tests for the "argv_array" type.
78 // ------------------------------------------------------------------------
79 
80 ATF_TEST_CASE(argv_array_init_carray);
81 ATF_TEST_CASE_HEAD(argv_array_init_carray)
82 {
83     set_md_var("descr", "Tests that argv_array is correctly constructed "
84                "from a C-style array of strings");
85 }
86 ATF_TEST_CASE_BODY(argv_array_init_carray)
87 {
88     {
89         const char* const carray[] = { NULL };
90         atf::process::argv_array argv(carray);
91 
92         ATF_REQUIRE_EQ(argv.size(), 0);
93     }
94 
95     {
96         const char* const carray[] = { "arg0", NULL };
97         atf::process::argv_array argv(carray);
98 
99         ATF_REQUIRE_EQ(argv.size(), 1);
100         ATF_REQUIRE(std::strcmp(argv[0], carray[0]) == 0);
101     }
102 
103     {
104         const char* const carray[] = { "arg0", "arg1", "arg2", NULL };
105         atf::process::argv_array argv(carray);
106 
107         ATF_REQUIRE_EQ(argv.size(), 3);
108         ATF_REQUIRE(std::strcmp(argv[0], carray[0]) == 0);
109         ATF_REQUIRE(std::strcmp(argv[1], carray[1]) == 0);
110         ATF_REQUIRE(std::strcmp(argv[2], carray[2]) == 0);
111     }
112 }
113 
114 ATF_TEST_CASE(argv_array_init_col);
115 ATF_TEST_CASE_HEAD(argv_array_init_col)
116 {
117     set_md_var("descr", "Tests that argv_array is correctly constructed "
118                "from a string collection");
119 }
120 ATF_TEST_CASE_BODY(argv_array_init_col)
121 {
122     {
123         std::vector< std::string > col;
124         atf::process::argv_array argv(col);
125 
126         ATF_REQUIRE_EQ(argv.size(), 0);
127     }
128 
129     {
130         std::vector< std::string > col;
131         col.push_back("arg0");
132         atf::process::argv_array argv(col);
133 
134         ATF_REQUIRE_EQ(argv.size(), 1);
135         ATF_REQUIRE_EQ(argv[0], col[0]);
136     }
137 
138     {
139         std::vector< std::string > col;
140         col.push_back("arg0");
141         col.push_back("arg1");
142         col.push_back("arg2");
143         atf::process::argv_array argv(col);
144 
145         ATF_REQUIRE_EQ(argv.size(), 3);
146         ATF_REQUIRE_EQ(argv[0], col[0]);
147         ATF_REQUIRE_EQ(argv[1], col[1]);
148         ATF_REQUIRE_EQ(argv[2], col[2]);
149     }
150 }
151 
152 ATF_TEST_CASE(argv_array_init_empty);
153 ATF_TEST_CASE_HEAD(argv_array_init_empty)
154 {
155     set_md_var("descr", "Tests that argv_array is correctly constructed "
156                "by the default constructor");
157 }
158 ATF_TEST_CASE_BODY(argv_array_init_empty)
159 {
160     atf::process::argv_array argv;
161 
162     ATF_REQUIRE_EQ(argv.size(), 0);
163 }
164 
165 ATF_TEST_CASE(argv_array_init_varargs);
166 ATF_TEST_CASE_HEAD(argv_array_init_varargs)
167 {
168     set_md_var("descr", "Tests that argv_array is correctly constructed "
169                "from a variable list of arguments");
170 }
171 ATF_TEST_CASE_BODY(argv_array_init_varargs)
172 {
173     {
174         atf::process::argv_array argv("arg0", NULL);
175 
176         ATF_REQUIRE_EQ(argv.size(), 1);
177         ATF_REQUIRE_EQ(argv[0], std::string("arg0"));
178     }
179 
180     {
181         atf::process::argv_array argv("arg0", "arg1", "arg2", NULL);
182 
183         ATF_REQUIRE_EQ(argv.size(), 3);
184         ATF_REQUIRE_EQ(argv[0], std::string("arg0"));
185         ATF_REQUIRE_EQ(argv[1], std::string("arg1"));
186         ATF_REQUIRE_EQ(argv[2], std::string("arg2"));
187     }
188 }
189 
190 ATF_TEST_CASE(argv_array_assign);
191 ATF_TEST_CASE_HEAD(argv_array_assign)
192 {
193     set_md_var("descr", "Tests that assigning an argv_array works");
194 }
195 ATF_TEST_CASE_BODY(argv_array_assign)
196 {
197     using atf::process::argv_array;
198 
199     const char* const carray1[] = { "arg1", NULL };
200     const char* const carray2[] = { "arg1", "arg2", NULL };
201 
202     std::auto_ptr< argv_array > argv1(new argv_array(carray1));
203     std::auto_ptr< argv_array > argv2(new argv_array(carray2));
204 
205     *argv2 = *argv1;
206     ATF_REQUIRE_EQ(argv2->size(), argv1->size());
207     ATF_REQUIRE(std::strcmp((*argv2)[0], (*argv1)[0]) == 0);
208 
209     ATF_REQUIRE(argv2->exec_argv() != argv1->exec_argv());
210     argv1.release();
211     {
212         const char* const* eargv2 = argv2->exec_argv();
213         ATF_REQUIRE(std::strcmp(eargv2[0], carray1[0]) == 0);
214         ATF_REQUIRE_EQ(eargv2[1], static_cast< const char* >(NULL));
215     }
216 
217     argv2.release();
218 }
219 
220 ATF_TEST_CASE(argv_array_copy);
221 ATF_TEST_CASE_HEAD(argv_array_copy)
222 {
223     set_md_var("descr", "Tests that copying an argv_array constructed from "
224                "a C-style array of strings works");
225 }
226 ATF_TEST_CASE_BODY(argv_array_copy)
227 {
228     using atf::process::argv_array;
229 
230     const char* const carray[] = { "arg0", NULL };
231 
232     std::auto_ptr< argv_array > argv1(new argv_array(carray));
233     std::auto_ptr< argv_array > argv2(new argv_array(*argv1));
234 
235     ATF_REQUIRE_EQ(argv2->size(), argv1->size());
236     ATF_REQUIRE(std::strcmp((*argv2)[0], (*argv1)[0]) == 0);
237 
238     ATF_REQUIRE(argv2->exec_argv() != argv1->exec_argv());
239     argv1.release();
240     {
241         const char* const* eargv2 = argv2->exec_argv();
242         ATF_REQUIRE(std::strcmp(eargv2[0], carray[0]) == 0);
243         ATF_REQUIRE_EQ(eargv2[1], static_cast< const char* >(NULL));
244     }
245 
246     argv2.release();
247 }
248 
249 ATF_TEST_CASE(argv_array_exec_argv);
250 ATF_TEST_CASE_HEAD(argv_array_exec_argv)
251 {
252     set_md_var("descr", "Tests that the exec argv provided by an argv_array "
253                "is correct");
254 }
255 ATF_TEST_CASE_BODY(argv_array_exec_argv)
256 {
257     using atf::process::argv_array;
258 
259     {
260         argv_array argv;
261         const char* const* eargv = argv.exec_argv();
262         ATF_REQUIRE_EQ(array_size(eargv), 0);
263         ATF_REQUIRE_EQ(eargv[0], static_cast< const char* >(NULL));
264     }
265 
266     {
267         const char* const carray[] = { "arg0", NULL };
268         argv_array argv(carray);
269         const char* const* eargv = argv.exec_argv();
270         ATF_REQUIRE_EQ(array_size(eargv), 1);
271         ATF_REQUIRE(std::strcmp(eargv[0], "arg0") == 0);
272         ATF_REQUIRE_EQ(eargv[1], static_cast< const char* >(NULL));
273     }
274 
275     {
276         std::vector< std::string > col;
277         col.push_back("arg0");
278         argv_array argv(col);
279         const char* const* eargv = argv.exec_argv();
280         ATF_REQUIRE_EQ(array_size(eargv), 1);
281         ATF_REQUIRE(std::strcmp(eargv[0], "arg0") == 0);
282         ATF_REQUIRE_EQ(eargv[1], static_cast< const char* >(NULL));
283     }
284 }
285 
286 ATF_TEST_CASE(argv_array_iter);
287 ATF_TEST_CASE_HEAD(argv_array_iter)
288 {
289     set_md_var("descr", "Tests that an argv_array can be iterated");
290 }
291 ATF_TEST_CASE_BODY(argv_array_iter)
292 {
293     using atf::process::argv_array;
294 
295     std::vector< std::string > vector;
296     vector.push_back("arg0");
297     vector.push_back("arg1");
298     vector.push_back("arg2");
299 
300     argv_array argv(vector);
301     ATF_REQUIRE_EQ(argv.size(), 3);
302     std::vector< std::string >::size_type pos = 0;
303     for (argv_array::const_iterator iter = argv.begin(); iter != argv.end();
304          iter++) {
305         ATF_REQUIRE_EQ(*iter, vector[pos]);
306         pos++;
307     }
308 }
309 
310 // ------------------------------------------------------------------------
311 // Tests cases for the free functions.
312 // ------------------------------------------------------------------------
313 
314 ATF_TEST_CASE(exec_failure);
315 ATF_TEST_CASE_HEAD(exec_failure)
316 {
317     set_md_var("descr", "Tests execing a command that reports failure");
318 }
319 ATF_TEST_CASE_BODY(exec_failure)
320 {
321     const atf::process::status s = exec_process_helpers(*this, "exit-failure");
322     ATF_REQUIRE(s.exited());
323     ATF_REQUIRE_EQ(s.exitstatus(), EXIT_FAILURE);
324 }
325 
326 ATF_TEST_CASE(exec_success);
327 ATF_TEST_CASE_HEAD(exec_success)
328 {
329     set_md_var("descr", "Tests execing a command that reports success");
330 }
331 ATF_TEST_CASE_BODY(exec_success)
332 {
333     const atf::process::status s = exec_process_helpers(*this, "exit-success");
334     ATF_REQUIRE(s.exited());
335     ATF_REQUIRE_EQ(s.exitstatus(), EXIT_SUCCESS);
336 }
337 
338 // ------------------------------------------------------------------------
339 // Main.
340 // ------------------------------------------------------------------------
341 
342 ATF_INIT_TEST_CASES(tcs)
343 {
344     // Add the test cases for the "argv_array" type.
345     ATF_ADD_TEST_CASE(tcs, argv_array_assign);
346     ATF_ADD_TEST_CASE(tcs, argv_array_copy);
347     ATF_ADD_TEST_CASE(tcs, argv_array_exec_argv);
348     ATF_ADD_TEST_CASE(tcs, argv_array_init_carray);
349     ATF_ADD_TEST_CASE(tcs, argv_array_init_col);
350     ATF_ADD_TEST_CASE(tcs, argv_array_init_empty);
351     ATF_ADD_TEST_CASE(tcs, argv_array_init_varargs);
352     ATF_ADD_TEST_CASE(tcs, argv_array_iter);
353 
354     // Add the test cases for the free functions.
355     ATF_ADD_TEST_CASE(tcs, exec_failure);
356     ATF_ADD_TEST_CASE(tcs, exec_success);
357 }
358