1240116Smarcel// Copyright (c) 2007 The NetBSD Foundation, Inc.
2240116Smarcel// All rights reserved.
3240116Smarcel//
4240116Smarcel// Redistribution and use in source and binary forms, with or without
5240116Smarcel// modification, are permitted provided that the following conditions
6240116Smarcel// are met:
7240116Smarcel// 1. Redistributions of source code must retain the above copyright
8240116Smarcel//    notice, this list of conditions and the following disclaimer.
9240116Smarcel// 2. Redistributions in binary form must reproduce the above copyright
10240116Smarcel//    notice, this list of conditions and the following disclaimer in the
11240116Smarcel//    documentation and/or other materials provided with the distribution.
12240116Smarcel//
13240116Smarcel// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
14240116Smarcel// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
15240116Smarcel// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16240116Smarcel// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17240116Smarcel// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
18240116Smarcel// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19240116Smarcel// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
20240116Smarcel// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21240116Smarcel// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22240116Smarcel// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23240116Smarcel// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24240116Smarcel// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25240116Smarcel
26273929Sjmmv#include "atf-c++/check.hpp"
27273929Sjmmv
28240116Smarcelextern "C" {
29240116Smarcel#include <fcntl.h>
30240116Smarcel#include <signal.h>
31240116Smarcel#include <unistd.h>
32240116Smarcel}
33240116Smarcel
34240116Smarcel#include <cstdlib>
35240116Smarcel#include <cstring>
36240116Smarcel#include <fstream>
37240116Smarcel#include <iostream>
38240116Smarcel#include <list>
39240116Smarcel#include <memory>
40240116Smarcel#include <vector>
41240116Smarcel
42240116Smarcel#include <atf-c++.hpp>
43240116Smarcel
44273929Sjmmv#include "atf-c++/detail/fs.hpp"
45273929Sjmmv#include "atf-c++/detail/process.hpp"
46273929Sjmmv#include "atf-c++/detail/test_helpers.hpp"
47273929Sjmmv#include "atf-c++/detail/text.hpp"
48273929Sjmmv#include "atf-c++/utils.hpp"
49240116Smarcel
50240116Smarcel// ------------------------------------------------------------------------
51240116Smarcel// Auxiliary functions.
52240116Smarcel// ------------------------------------------------------------------------
53240116Smarcel
54240116Smarcelstatic
55240116Smarcelstd::auto_ptr< atf::check::check_result >
56240116Smarceldo_exec(const atf::tests::tc* tc, const char* helper_name)
57240116Smarcel{
58240116Smarcel    std::vector< std::string > argv;
59251108Smarcel    argv.push_back(get_process_helpers_path(*tc, false).str());
60240116Smarcel    argv.push_back(helper_name);
61240116Smarcel    std::cout << "Executing " << argv[0] << " " << argv[1] << "\n";
62240116Smarcel
63240116Smarcel    atf::process::argv_array argva(argv);
64240116Smarcel    return atf::check::exec(argva);
65240116Smarcel}
66240116Smarcel
67240116Smarcelstatic
68240116Smarcelstd::auto_ptr< atf::check::check_result >
69240116Smarceldo_exec(const atf::tests::tc* tc, const char* helper_name, const char *carg2)
70240116Smarcel{
71240116Smarcel    std::vector< std::string > argv;
72251108Smarcel    argv.push_back(get_process_helpers_path(*tc, false).str());
73240116Smarcel    argv.push_back(helper_name);
74240116Smarcel    argv.push_back(carg2);
75240116Smarcel    std::cout << "Executing " << argv[0] << " " << argv[1] << " "
76240116Smarcel              << argv[2] << "\n";
77240116Smarcel
78240116Smarcel    atf::process::argv_array argva(argv);
79240116Smarcel    return atf::check::exec(argva);
80240116Smarcel}
81240116Smarcel
82240116Smarcel// ------------------------------------------------------------------------
83240116Smarcel// Helper test cases for the free functions.
84240116Smarcel// ------------------------------------------------------------------------
85240116Smarcel
86240116SmarcelATF_TEST_CASE(h_build_c_o_ok);
87240116SmarcelATF_TEST_CASE_HEAD(h_build_c_o_ok)
88240116Smarcel{
89240116Smarcel    set_md_var("descr", "Helper test case for build_c_o");
90240116Smarcel}
91240116SmarcelATF_TEST_CASE_BODY(h_build_c_o_ok)
92240116Smarcel{
93240116Smarcel    std::ofstream sfile("test.c");
94240116Smarcel    sfile << "#include <stdio.h>\n";
95240116Smarcel    sfile.close();
96240116Smarcel
97240116Smarcel    ATF_REQUIRE(atf::check::build_c_o("test.c", "test.o",
98240116Smarcel                                      atf::process::argv_array()));
99240116Smarcel}
100240116Smarcel
101240116SmarcelATF_TEST_CASE(h_build_c_o_fail);
102240116SmarcelATF_TEST_CASE_HEAD(h_build_c_o_fail)
103240116Smarcel{
104240116Smarcel    set_md_var("descr", "Helper test case for build_c_o");
105240116Smarcel}
106240116SmarcelATF_TEST_CASE_BODY(h_build_c_o_fail)
107240116Smarcel{
108240116Smarcel    std::ofstream sfile("test.c");
109240116Smarcel    sfile << "void foo(void) { int a = UNDEFINED_SYMBOL; }\n";
110240116Smarcel    sfile.close();
111240116Smarcel
112240116Smarcel    ATF_REQUIRE(!atf::check::build_c_o("test.c", "test.o",
113240116Smarcel                                       atf::process::argv_array()));
114240116Smarcel}
115240116Smarcel
116240116SmarcelATF_TEST_CASE(h_build_cpp_ok);
117240116SmarcelATF_TEST_CASE_HEAD(h_build_cpp_ok)
118240116Smarcel{
119240116Smarcel    set_md_var("descr", "Helper test case for build_cpp");
120240116Smarcel}
121240116SmarcelATF_TEST_CASE_BODY(h_build_cpp_ok)
122240116Smarcel{
123240116Smarcel    std::ofstream sfile("test.c");
124240116Smarcel    sfile << "#define A foo\n";
125240116Smarcel    sfile << "#define B bar\n";
126240116Smarcel    sfile << "A B\n";
127240116Smarcel    sfile.close();
128240116Smarcel
129240116Smarcel    ATF_REQUIRE(atf::check::build_cpp("test.c", "test.p",
130240116Smarcel                                      atf::process::argv_array()));
131240116Smarcel}
132240116Smarcel
133240116SmarcelATF_TEST_CASE(h_build_cpp_fail);
134240116SmarcelATF_TEST_CASE_HEAD(h_build_cpp_fail)
135240116Smarcel{
136240116Smarcel    set_md_var("descr", "Helper test case for build_cpp");
137240116Smarcel}
138240116SmarcelATF_TEST_CASE_BODY(h_build_cpp_fail)
139240116Smarcel{
140240116Smarcel    std::ofstream sfile("test.c");
141240116Smarcel    sfile << "#include \"./non-existent.h\"\n";
142240116Smarcel    sfile.close();
143240116Smarcel
144240116Smarcel    ATF_REQUIRE(!atf::check::build_cpp("test.c", "test.p",
145240116Smarcel                                       atf::process::argv_array()));
146240116Smarcel}
147240116Smarcel
148240116SmarcelATF_TEST_CASE(h_build_cxx_o_ok);
149240116SmarcelATF_TEST_CASE_HEAD(h_build_cxx_o_ok)
150240116Smarcel{
151240116Smarcel    set_md_var("descr", "Helper test case for build_cxx_o");
152240116Smarcel}
153240116SmarcelATF_TEST_CASE_BODY(h_build_cxx_o_ok)
154240116Smarcel{
155240116Smarcel    std::ofstream sfile("test.cpp");
156240116Smarcel    sfile << "#include <iostream>\n";
157240116Smarcel    sfile.close();
158240116Smarcel
159240116Smarcel    ATF_REQUIRE(atf::check::build_cxx_o("test.cpp", "test.o",
160240116Smarcel                                        atf::process::argv_array()));
161240116Smarcel}
162240116Smarcel
163240116SmarcelATF_TEST_CASE(h_build_cxx_o_fail);
164240116SmarcelATF_TEST_CASE_HEAD(h_build_cxx_o_fail)
165240116Smarcel{
166240116Smarcel    set_md_var("descr", "Helper test case for build_cxx_o");
167240116Smarcel}
168240116SmarcelATF_TEST_CASE_BODY(h_build_cxx_o_fail)
169240116Smarcel{
170240116Smarcel    std::ofstream sfile("test.cpp");
171240116Smarcel    sfile << "void foo(void) { int a = UNDEFINED_SYMBOL; }\n";
172240116Smarcel    sfile.close();
173240116Smarcel
174240116Smarcel    ATF_REQUIRE(!atf::check::build_cxx_o("test.cpp", "test.o",
175240116Smarcel                                         atf::process::argv_array()));
176240116Smarcel}
177240116Smarcel
178240116Smarcel// ------------------------------------------------------------------------
179240116Smarcel// Test cases for the free functions.
180240116Smarcel// ------------------------------------------------------------------------
181240116Smarcel
182240116SmarcelATF_TEST_CASE(build_c_o);
183240116SmarcelATF_TEST_CASE_HEAD(build_c_o)
184240116Smarcel{
185240116Smarcel    set_md_var("descr", "Tests the build_c_o function");
186240116Smarcel}
187240116SmarcelATF_TEST_CASE_BODY(build_c_o)
188240116Smarcel{
189240116Smarcel    ATF_TEST_CASE_USE(h_build_c_o_ok);
190240116Smarcel    run_h_tc< ATF_TEST_CASE_NAME(h_build_c_o_ok) >();
191258289Sjmmv    ATF_REQUIRE(atf::utils::grep_file("-o test.o", "stdout"));
192258289Sjmmv    ATF_REQUIRE(atf::utils::grep_file("-c test.c", "stdout"));
193240116Smarcel
194240116Smarcel    ATF_TEST_CASE_USE(h_build_c_o_fail);
195240116Smarcel    run_h_tc< ATF_TEST_CASE_NAME(h_build_c_o_fail) >();
196258289Sjmmv    ATF_REQUIRE(atf::utils::grep_file("-o test.o", "stdout"));
197258289Sjmmv    ATF_REQUIRE(atf::utils::grep_file("-c test.c", "stdout"));
198258289Sjmmv    ATF_REQUIRE(atf::utils::grep_file("test.c", "stderr"));
199258289Sjmmv    ATF_REQUIRE(atf::utils::grep_file("UNDEFINED_SYMBOL", "stderr"));
200240116Smarcel}
201240116Smarcel
202240116SmarcelATF_TEST_CASE(build_cpp);
203240116SmarcelATF_TEST_CASE_HEAD(build_cpp)
204240116Smarcel{
205240116Smarcel    set_md_var("descr", "Tests the build_cpp function");
206240116Smarcel}
207240116SmarcelATF_TEST_CASE_BODY(build_cpp)
208240116Smarcel{
209240116Smarcel    ATF_TEST_CASE_USE(h_build_cpp_ok);
210240116Smarcel    run_h_tc< ATF_TEST_CASE_NAME(h_build_cpp_ok) >();
211258289Sjmmv    ATF_REQUIRE(atf::utils::grep_file("-o.*test.p", "stdout"));
212258289Sjmmv    ATF_REQUIRE(atf::utils::grep_file("test.c", "stdout"));
213258289Sjmmv    ATF_REQUIRE(atf::utils::grep_file("foo bar", "test.p"));
214240116Smarcel
215240116Smarcel    ATF_TEST_CASE_USE(h_build_cpp_fail);
216240116Smarcel    run_h_tc< ATF_TEST_CASE_NAME(h_build_cpp_fail) >();
217258289Sjmmv    ATF_REQUIRE(atf::utils::grep_file("-o test.p", "stdout"));
218258289Sjmmv    ATF_REQUIRE(atf::utils::grep_file("test.c", "stdout"));
219258289Sjmmv    ATF_REQUIRE(atf::utils::grep_file("test.c", "stderr"));
220258289Sjmmv    ATF_REQUIRE(atf::utils::grep_file("non-existent.h", "stderr"));
221240116Smarcel}
222240116Smarcel
223240116SmarcelATF_TEST_CASE(build_cxx_o);
224240116SmarcelATF_TEST_CASE_HEAD(build_cxx_o)
225240116Smarcel{
226240116Smarcel    set_md_var("descr", "Tests the build_cxx_o function");
227240116Smarcel}
228240116SmarcelATF_TEST_CASE_BODY(build_cxx_o)
229240116Smarcel{
230240116Smarcel    ATF_TEST_CASE_USE(h_build_cxx_o_ok);
231240116Smarcel    run_h_tc< ATF_TEST_CASE_NAME(h_build_cxx_o_ok) >();
232258289Sjmmv    ATF_REQUIRE(atf::utils::grep_file("-o test.o", "stdout"));
233258289Sjmmv    ATF_REQUIRE(atf::utils::grep_file("-c test.cpp", "stdout"));
234240116Smarcel
235240116Smarcel    ATF_TEST_CASE_USE(h_build_cxx_o_fail);
236240116Smarcel    run_h_tc< ATF_TEST_CASE_NAME(h_build_cxx_o_fail) >();
237258289Sjmmv    ATF_REQUIRE(atf::utils::grep_file("-o test.o", "stdout"));
238258289Sjmmv    ATF_REQUIRE(atf::utils::grep_file("-c test.cpp", "stdout"));
239258289Sjmmv    ATF_REQUIRE(atf::utils::grep_file("test.cpp", "stderr"));
240258289Sjmmv    ATF_REQUIRE(atf::utils::grep_file("UNDEFINED_SYMBOL", "stderr"));
241240116Smarcel}
242240116Smarcel
243240116SmarcelATF_TEST_CASE(exec_cleanup);
244240116SmarcelATF_TEST_CASE_HEAD(exec_cleanup)
245240116Smarcel{
246240116Smarcel    set_md_var("descr", "Tests that exec properly cleans up the temporary "
247240116Smarcel               "files it creates");
248240116Smarcel}
249240116SmarcelATF_TEST_CASE_BODY(exec_cleanup)
250240116Smarcel{
251240116Smarcel    std::auto_ptr< atf::fs::path > out;
252240116Smarcel    std::auto_ptr< atf::fs::path > err;
253240116Smarcel
254240116Smarcel    {
255240116Smarcel        std::auto_ptr< atf::check::check_result > r =
256240116Smarcel            do_exec(this, "exit-success");
257240116Smarcel        out.reset(new atf::fs::path(r->stdout_path()));
258240116Smarcel        err.reset(new atf::fs::path(r->stderr_path()));
259240116Smarcel        ATF_REQUIRE(atf::fs::exists(*out.get()));
260240116Smarcel        ATF_REQUIRE(atf::fs::exists(*err.get()));
261240116Smarcel    }
262240116Smarcel    ATF_REQUIRE(!atf::fs::exists(*out.get()));
263240116Smarcel    ATF_REQUIRE(!atf::fs::exists(*err.get()));
264240116Smarcel}
265240116Smarcel
266240116SmarcelATF_TEST_CASE(exec_exitstatus);
267240116SmarcelATF_TEST_CASE_HEAD(exec_exitstatus)
268240116Smarcel{
269240116Smarcel    set_md_var("descr", "Tests that exec properly captures the exit "
270240116Smarcel               "status of the executed command");
271240116Smarcel}
272240116SmarcelATF_TEST_CASE_BODY(exec_exitstatus)
273240116Smarcel{
274240116Smarcel    {
275240116Smarcel        std::auto_ptr< atf::check::check_result > r =
276240116Smarcel            do_exec(this, "exit-success");
277240116Smarcel        ATF_REQUIRE(r->exited());
278240116Smarcel        ATF_REQUIRE(!r->signaled());
279240116Smarcel        ATF_REQUIRE_EQ(r->exitcode(), EXIT_SUCCESS);
280240116Smarcel    }
281240116Smarcel
282240116Smarcel    {
283240116Smarcel        std::auto_ptr< atf::check::check_result > r =
284240116Smarcel            do_exec(this, "exit-failure");
285240116Smarcel        ATF_REQUIRE(r->exited());
286240116Smarcel        ATF_REQUIRE(!r->signaled());
287240116Smarcel        ATF_REQUIRE_EQ(r->exitcode(), EXIT_FAILURE);
288240116Smarcel    }
289240116Smarcel
290240116Smarcel    {
291240116Smarcel        std::auto_ptr< atf::check::check_result > r =
292240116Smarcel            do_exec(this, "exit-signal");
293240116Smarcel        ATF_REQUIRE(!r->exited());
294240116Smarcel        ATF_REQUIRE(r->signaled());
295240116Smarcel        ATF_REQUIRE_EQ(r->termsig(), SIGKILL);
296240116Smarcel    }
297240116Smarcel}
298240116Smarcel
299240116Smarcelstatic
300240116Smarcelvoid
301240116Smarcelcheck_lines(const std::string& path, const char* outname,
302240116Smarcel            const char* resname)
303240116Smarcel{
304240116Smarcel    std::ifstream f(path.c_str());
305240116Smarcel    ATF_REQUIRE(f);
306240116Smarcel
307240116Smarcel    std::string line;
308240116Smarcel    std::getline(f, line);
309240116Smarcel    ATF_REQUIRE_EQ(line, std::string("Line 1 to ") + outname + " for " +
310240116Smarcel                    resname);
311240116Smarcel    std::getline(f, line);
312240116Smarcel    ATF_REQUIRE_EQ(line, std::string("Line 2 to ") + outname + " for " +
313240116Smarcel                    resname);
314240116Smarcel}
315240116Smarcel
316240116SmarcelATF_TEST_CASE(exec_stdout_stderr);
317240116SmarcelATF_TEST_CASE_HEAD(exec_stdout_stderr)
318240116Smarcel{
319240116Smarcel    set_md_var("descr", "Tests that exec properly captures the stdout "
320240116Smarcel               "and stderr streams of the child process");
321240116Smarcel}
322240116SmarcelATF_TEST_CASE_BODY(exec_stdout_stderr)
323240116Smarcel{
324240116Smarcel    std::auto_ptr< atf::check::check_result > r1 =
325240116Smarcel        do_exec(this, "stdout-stderr", "result1");
326240116Smarcel    ATF_REQUIRE(r1->exited());
327240116Smarcel    ATF_REQUIRE_EQ(r1->exitcode(), EXIT_SUCCESS);
328240116Smarcel
329240116Smarcel    std::auto_ptr< atf::check::check_result > r2 =
330240116Smarcel        do_exec(this, "stdout-stderr", "result2");
331240116Smarcel    ATF_REQUIRE(r2->exited());
332240116Smarcel    ATF_REQUIRE_EQ(r2->exitcode(), EXIT_SUCCESS);
333240116Smarcel
334240116Smarcel    const std::string out1 = r1->stdout_path();
335240116Smarcel    const std::string out2 = r2->stdout_path();
336240116Smarcel    const std::string err1 = r1->stderr_path();
337240116Smarcel    const std::string err2 = r2->stderr_path();
338240116Smarcel
339240116Smarcel    ATF_REQUIRE(out1.find("check.XXXXXX") == std::string::npos);
340240116Smarcel    ATF_REQUIRE(out2.find("check.XXXXXX") == std::string::npos);
341240116Smarcel    ATF_REQUIRE(err1.find("check.XXXXXX") == std::string::npos);
342240116Smarcel    ATF_REQUIRE(err2.find("check.XXXXXX") == std::string::npos);
343240116Smarcel
344240116Smarcel    ATF_REQUIRE(out1.find("/check") != std::string::npos);
345240116Smarcel    ATF_REQUIRE(out2.find("/check") != std::string::npos);
346240116Smarcel    ATF_REQUIRE(err1.find("/check") != std::string::npos);
347240116Smarcel    ATF_REQUIRE(err2.find("/check") != std::string::npos);
348240116Smarcel
349240116Smarcel    ATF_REQUIRE(out1.find("/stdout") != std::string::npos);
350240116Smarcel    ATF_REQUIRE(out2.find("/stdout") != std::string::npos);
351240116Smarcel    ATF_REQUIRE(err1.find("/stderr") != std::string::npos);
352240116Smarcel    ATF_REQUIRE(err2.find("/stderr") != std::string::npos);
353240116Smarcel
354240116Smarcel    ATF_REQUIRE(out1 != out2);
355240116Smarcel    ATF_REQUIRE(err1 != err2);
356240116Smarcel
357240116Smarcel    check_lines(out1, "stdout", "result1");
358240116Smarcel    check_lines(out2, "stdout", "result2");
359240116Smarcel    check_lines(err1, "stderr", "result1");
360240116Smarcel    check_lines(err2, "stderr", "result2");
361240116Smarcel}
362240116Smarcel
363240116SmarcelATF_TEST_CASE(exec_unknown);
364240116SmarcelATF_TEST_CASE_HEAD(exec_unknown)
365240116Smarcel{
366240116Smarcel    set_md_var("descr", "Tests that running a non-existing binary "
367240116Smarcel               "is handled correctly");
368240116Smarcel}
369240116SmarcelATF_TEST_CASE_BODY(exec_unknown)
370240116Smarcel{
371240116Smarcel    std::vector< std::string > argv;
372273929Sjmmv    argv.push_back("/foo/bar/non-existent");
373240116Smarcel
374240116Smarcel    atf::process::argv_array argva(argv);
375240116Smarcel    std::auto_ptr< atf::check::check_result > r = atf::check::exec(argva);
376240116Smarcel    ATF_REQUIRE(r->exited());
377240116Smarcel    ATF_REQUIRE_EQ(r->exitcode(), 127);
378240116Smarcel}
379240116Smarcel
380240116Smarcel// ------------------------------------------------------------------------
381240116Smarcel// Main.
382240116Smarcel// ------------------------------------------------------------------------
383240116Smarcel
384240116SmarcelATF_INIT_TEST_CASES(tcs)
385240116Smarcel{
386240116Smarcel    // Add the test cases for the free functions.
387240116Smarcel    ATF_ADD_TEST_CASE(tcs, build_c_o);
388240116Smarcel    ATF_ADD_TEST_CASE(tcs, build_cpp);
389240116Smarcel    ATF_ADD_TEST_CASE(tcs, build_cxx_o);
390240116Smarcel    ATF_ADD_TEST_CASE(tcs, exec_cleanup);
391240116Smarcel    ATF_ADD_TEST_CASE(tcs, exec_exitstatus);
392240116Smarcel    ATF_ADD_TEST_CASE(tcs, exec_stdout_stderr);
393240116Smarcel    ATF_ADD_TEST_CASE(tcs, exec_unknown);
394240116Smarcel}
395