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