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 <atf-c++.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
array_size(const char * const * array)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 tools::process::status
exec_process_helpers(const atf::tests::tc & tc,const char * helper_name)62 exec_process_helpers(const atf::tests::tc& tc, const char* helper_name)
63 {
64     using tools::process::exec;
65 
66     const tools::fs::path helpers = tools::fs::path(tc.get_config_var("srcdir")) /
67         "process_helpers";
68 
69     std::vector< std::string > argv;
70     argv.push_back(helpers.leaf_name());
71     argv.push_back(helper_name);
72 
73     return exec(helpers,
74                 tools::process::argv_array(argv),
75                 tools::process::stream_inherit(),
76                 tools::process::stream_inherit());
77 }
78 
79 // ------------------------------------------------------------------------
80 // Tests for the "argv_array" type.
81 // ------------------------------------------------------------------------
82 
83 ATF_TEST_CASE(argv_array_init_carray);
ATF_TEST_CASE_HEAD(argv_array_init_carray)84 ATF_TEST_CASE_HEAD(argv_array_init_carray)
85 {
86     set_md_var("descr", "Tests that argv_array is correctly constructed "
87                "from a C-style array of strings");
88 }
ATF_TEST_CASE_BODY(argv_array_init_carray)89 ATF_TEST_CASE_BODY(argv_array_init_carray)
90 {
91     {
92         const char* const carray[] = { NULL };
93         tools::process::argv_array argv(carray);
94 
95         ATF_REQUIRE_EQ(argv.size(), 0);
96     }
97 
98     {
99         const char* const carray[] = { "arg0", NULL };
100         tools::process::argv_array argv(carray);
101 
102         ATF_REQUIRE_EQ(argv.size(), 1);
103         ATF_REQUIRE(std::strcmp(argv[0], carray[0]) == 0);
104     }
105 
106     {
107         const char* const carray[] = { "arg0", "arg1", "arg2", NULL };
108         tools::process::argv_array argv(carray);
109 
110         ATF_REQUIRE_EQ(argv.size(), 3);
111         ATF_REQUIRE(std::strcmp(argv[0], carray[0]) == 0);
112         ATF_REQUIRE(std::strcmp(argv[1], carray[1]) == 0);
113         ATF_REQUIRE(std::strcmp(argv[2], carray[2]) == 0);
114     }
115 }
116 
117 ATF_TEST_CASE(argv_array_init_col);
ATF_TEST_CASE_HEAD(argv_array_init_col)118 ATF_TEST_CASE_HEAD(argv_array_init_col)
119 {
120     set_md_var("descr", "Tests that argv_array is correctly constructed "
121                "from a string collection");
122 }
ATF_TEST_CASE_BODY(argv_array_init_col)123 ATF_TEST_CASE_BODY(argv_array_init_col)
124 {
125     {
126         std::vector< std::string > col;
127         tools::process::argv_array argv(col);
128 
129         ATF_REQUIRE_EQ(argv.size(), 0);
130     }
131 
132     {
133         std::vector< std::string > col;
134         col.push_back("arg0");
135         tools::process::argv_array argv(col);
136 
137         ATF_REQUIRE_EQ(argv.size(), 1);
138         ATF_REQUIRE_EQ(argv[0], col[0]);
139     }
140 
141     {
142         std::vector< std::string > col;
143         col.push_back("arg0");
144         col.push_back("arg1");
145         col.push_back("arg2");
146         tools::process::argv_array argv(col);
147 
148         ATF_REQUIRE_EQ(argv.size(), 3);
149         ATF_REQUIRE_EQ(argv[0], col[0]);
150         ATF_REQUIRE_EQ(argv[1], col[1]);
151         ATF_REQUIRE_EQ(argv[2], col[2]);
152     }
153 }
154 
155 ATF_TEST_CASE(argv_array_init_empty);
ATF_TEST_CASE_HEAD(argv_array_init_empty)156 ATF_TEST_CASE_HEAD(argv_array_init_empty)
157 {
158     set_md_var("descr", "Tests that argv_array is correctly constructed "
159                "by the default constructor");
160 }
ATF_TEST_CASE_BODY(argv_array_init_empty)161 ATF_TEST_CASE_BODY(argv_array_init_empty)
162 {
163     tools::process::argv_array argv;
164 
165     ATF_REQUIRE_EQ(argv.size(), 0);
166 }
167 
168 ATF_TEST_CASE(argv_array_init_varargs);
ATF_TEST_CASE_HEAD(argv_array_init_varargs)169 ATF_TEST_CASE_HEAD(argv_array_init_varargs)
170 {
171     set_md_var("descr", "Tests that argv_array is correctly constructed "
172                "from a variable list of arguments");
173 }
ATF_TEST_CASE_BODY(argv_array_init_varargs)174 ATF_TEST_CASE_BODY(argv_array_init_varargs)
175 {
176     {
177         tools::process::argv_array argv("arg0", NULL);
178 
179         ATF_REQUIRE_EQ(argv.size(), 1);
180         ATF_REQUIRE_EQ(argv[0], std::string("arg0"));
181     }
182 
183     {
184         tools::process::argv_array argv("arg0", "arg1", "arg2", NULL);
185 
186         ATF_REQUIRE_EQ(argv.size(), 3);
187         ATF_REQUIRE_EQ(argv[0], std::string("arg0"));
188         ATF_REQUIRE_EQ(argv[1], std::string("arg1"));
189         ATF_REQUIRE_EQ(argv[2], std::string("arg2"));
190     }
191 }
192 
193 ATF_TEST_CASE(argv_array_assign);
ATF_TEST_CASE_HEAD(argv_array_assign)194 ATF_TEST_CASE_HEAD(argv_array_assign)
195 {
196     set_md_var("descr", "Tests that assigning an argv_array works");
197 }
ATF_TEST_CASE_BODY(argv_array_assign)198 ATF_TEST_CASE_BODY(argv_array_assign)
199 {
200     using tools::process::argv_array;
201 
202     const char* const carray1[] = { "arg1", NULL };
203     const char* const carray2[] = { "arg1", "arg2", NULL };
204 
205     std::auto_ptr< argv_array > argv1(new argv_array(carray1));
206     std::auto_ptr< argv_array > argv2(new argv_array(carray2));
207 
208     *argv2 = *argv1;
209     ATF_REQUIRE_EQ(argv2->size(), argv1->size());
210     ATF_REQUIRE(std::strcmp((*argv2)[0], (*argv1)[0]) == 0);
211 
212     ATF_REQUIRE(argv2->exec_argv() != argv1->exec_argv());
213     argv1.release();
214     {
215         const char* const* eargv2 = argv2->exec_argv();
216         ATF_REQUIRE(std::strcmp(eargv2[0], carray1[0]) == 0);
217         ATF_REQUIRE_EQ(eargv2[1], static_cast< const char* >(NULL));
218     }
219 
220     argv2.release();
221 }
222 
223 ATF_TEST_CASE(argv_array_copy);
ATF_TEST_CASE_HEAD(argv_array_copy)224 ATF_TEST_CASE_HEAD(argv_array_copy)
225 {
226     set_md_var("descr", "Tests that copying an argv_array constructed from "
227                "a C-style array of strings works");
228 }
ATF_TEST_CASE_BODY(argv_array_copy)229 ATF_TEST_CASE_BODY(argv_array_copy)
230 {
231     using tools::process::argv_array;
232 
233     const char* const carray[] = { "arg0", NULL };
234 
235     std::auto_ptr< argv_array > argv1(new argv_array(carray));
236     std::auto_ptr< argv_array > argv2(new argv_array(*argv1));
237 
238     ATF_REQUIRE_EQ(argv2->size(), argv1->size());
239     ATF_REQUIRE(std::strcmp((*argv2)[0], (*argv1)[0]) == 0);
240 
241     ATF_REQUIRE(argv2->exec_argv() != argv1->exec_argv());
242     argv1.release();
243     {
244         const char* const* eargv2 = argv2->exec_argv();
245         ATF_REQUIRE(std::strcmp(eargv2[0], carray[0]) == 0);
246         ATF_REQUIRE_EQ(eargv2[1], static_cast< const char* >(NULL));
247     }
248 
249     argv2.release();
250 }
251 
252 ATF_TEST_CASE(argv_array_exec_argv);
ATF_TEST_CASE_HEAD(argv_array_exec_argv)253 ATF_TEST_CASE_HEAD(argv_array_exec_argv)
254 {
255     set_md_var("descr", "Tests that the exec argv provided by an argv_array "
256                "is correct");
257 }
ATF_TEST_CASE_BODY(argv_array_exec_argv)258 ATF_TEST_CASE_BODY(argv_array_exec_argv)
259 {
260     using tools::process::argv_array;
261 
262     {
263         argv_array argv;
264         const char* const* eargv = argv.exec_argv();
265         ATF_REQUIRE_EQ(array_size(eargv), 0);
266         ATF_REQUIRE_EQ(eargv[0], static_cast< const char* >(NULL));
267     }
268 
269     {
270         const char* const carray[] = { "arg0", NULL };
271         argv_array argv(carray);
272         const char* const* eargv = argv.exec_argv();
273         ATF_REQUIRE_EQ(array_size(eargv), 1);
274         ATF_REQUIRE(std::strcmp(eargv[0], "arg0") == 0);
275         ATF_REQUIRE_EQ(eargv[1], static_cast< const char* >(NULL));
276     }
277 
278     {
279         std::vector< std::string > col;
280         col.push_back("arg0");
281         argv_array argv(col);
282         const char* const* eargv = argv.exec_argv();
283         ATF_REQUIRE_EQ(array_size(eargv), 1);
284         ATF_REQUIRE(std::strcmp(eargv[0], "arg0") == 0);
285         ATF_REQUIRE_EQ(eargv[1], static_cast< const char* >(NULL));
286     }
287 }
288 
289 ATF_TEST_CASE(argv_array_iter);
ATF_TEST_CASE_HEAD(argv_array_iter)290 ATF_TEST_CASE_HEAD(argv_array_iter)
291 {
292     set_md_var("descr", "Tests that an argv_array can be iterated");
293 }
ATF_TEST_CASE_BODY(argv_array_iter)294 ATF_TEST_CASE_BODY(argv_array_iter)
295 {
296     using tools::process::argv_array;
297 
298     std::vector< std::string > vector;
299     vector.push_back("arg0");
300     vector.push_back("arg1");
301     vector.push_back("arg2");
302 
303     argv_array argv(vector);
304     ATF_REQUIRE_EQ(argv.size(), 3);
305     std::vector< std::string >::size_type pos = 0;
306     for (argv_array::const_iterator iter = argv.begin(); iter != argv.end();
307          iter++) {
308         ATF_REQUIRE_EQ(*iter, vector[pos]);
309         pos++;
310     }
311 }
312 
313 // ------------------------------------------------------------------------
314 // Tests cases for the free functions.
315 // ------------------------------------------------------------------------
316 
317 ATF_TEST_CASE(exec_failure);
ATF_TEST_CASE_HEAD(exec_failure)318 ATF_TEST_CASE_HEAD(exec_failure)
319 {
320     set_md_var("descr", "Tests execing a command that reports failure");
321 }
ATF_TEST_CASE_BODY(exec_failure)322 ATF_TEST_CASE_BODY(exec_failure)
323 {
324     const tools::process::status s = exec_process_helpers(*this, "exit-failure");
325     ATF_REQUIRE(s.exited());
326     ATF_REQUIRE_EQ(s.exitstatus(), EXIT_FAILURE);
327 }
328 
329 ATF_TEST_CASE(exec_success);
ATF_TEST_CASE_HEAD(exec_success)330 ATF_TEST_CASE_HEAD(exec_success)
331 {
332     set_md_var("descr", "Tests execing a command that reports success");
333 }
ATF_TEST_CASE_BODY(exec_success)334 ATF_TEST_CASE_BODY(exec_success)
335 {
336     const tools::process::status s = exec_process_helpers(*this, "exit-success");
337     ATF_REQUIRE(s.exited());
338     ATF_REQUIRE_EQ(s.exitstatus(), EXIT_SUCCESS);
339 }
340 
341 // ------------------------------------------------------------------------
342 // Main.
343 // ------------------------------------------------------------------------
344 
ATF_INIT_TEST_CASES(tcs)345 ATF_INIT_TEST_CASES(tcs)
346 {
347     // Add the test cases for the "argv_array" type.
348     ATF_ADD_TEST_CASE(tcs, argv_array_assign);
349     ATF_ADD_TEST_CASE(tcs, argv_array_copy);
350     ATF_ADD_TEST_CASE(tcs, argv_array_exec_argv);
351     ATF_ADD_TEST_CASE(tcs, argv_array_init_carray);
352     ATF_ADD_TEST_CASE(tcs, argv_array_init_col);
353     ATF_ADD_TEST_CASE(tcs, argv_array_init_empty);
354     ATF_ADD_TEST_CASE(tcs, argv_array_init_varargs);
355     ATF_ADD_TEST_CASE(tcs, argv_array_iter);
356 
357     // Add the test cases for the free functions.
358     ATF_ADD_TEST_CASE(tcs, exec_failure);
359     ATF_ADD_TEST_CASE(tcs, exec_success);
360 }
361