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
48static
49std::size_t
50array_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
60static
61atf::process::status
62exec_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
80ATF_TEST_CASE(argv_array_init_carray);
81ATF_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}
86ATF_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
114ATF_TEST_CASE(argv_array_init_col);
115ATF_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}
120ATF_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
152ATF_TEST_CASE(argv_array_init_empty);
153ATF_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}
158ATF_TEST_CASE_BODY(argv_array_init_empty)
159{
160    atf::process::argv_array argv;
161
162    ATF_REQUIRE_EQ(argv.size(), 0);
163}
164
165ATF_TEST_CASE(argv_array_init_varargs);
166ATF_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}
171ATF_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
190ATF_TEST_CASE(argv_array_assign);
191ATF_TEST_CASE_HEAD(argv_array_assign)
192{
193    set_md_var("descr", "Tests that assigning an argv_array works");
194}
195ATF_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
220ATF_TEST_CASE(argv_array_copy);
221ATF_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}
226ATF_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
249ATF_TEST_CASE(argv_array_exec_argv);
250ATF_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}
255ATF_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
286ATF_TEST_CASE(argv_array_iter);
287ATF_TEST_CASE_HEAD(argv_array_iter)
288{
289    set_md_var("descr", "Tests that an argv_array can be iterated");
290}
291ATF_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
314ATF_TEST_CASE(exec_failure);
315ATF_TEST_CASE_HEAD(exec_failure)
316{
317    set_md_var("descr", "Tests execing a command that reports failure");
318}
319ATF_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
326ATF_TEST_CASE(exec_success);
327ATF_TEST_CASE_HEAD(exec_success)
328{
329    set_md_var("descr", "Tests execing a command that reports success");
330}
331ATF_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
342ATF_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