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