xref: /freebsd/contrib/atf/atf-c++/check_test.cpp (revision 8f0ea33f2bbf3a6aa80235f0a02fa5f2780c2b17)
1 // Copyright (c) 2007 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++/check.hpp"
27 
28 extern "C" {
29 #include <fcntl.h>
30 #include <signal.h>
31 #include <unistd.h>
32 }
33 
34 #include <cstdlib>
35 #include <cstring>
36 #include <fstream>
37 #include <iostream>
38 #include <list>
39 #include <memory>
40 #include <vector>
41 
42 #include <atf-c++.hpp>
43 
44 #include "atf-c++/detail/fs.hpp"
45 #include "atf-c++/detail/process.hpp"
46 #include "atf-c++/detail/test_helpers.hpp"
47 #include "atf-c++/detail/text.hpp"
48 #include "atf-c++/utils.hpp"
49 
50 // ------------------------------------------------------------------------
51 // Auxiliary functions.
52 // ------------------------------------------------------------------------
53 
54 static
55 std::auto_ptr< atf::check::check_result >
do_exec(const atf::tests::tc * tc,const char * helper_name)56 do_exec(const atf::tests::tc* tc, const char* helper_name)
57 {
58     std::vector< std::string > argv;
59     argv.push_back(get_process_helpers_path(*tc, false).str());
60     argv.push_back(helper_name);
61     std::cout << "Executing " << argv[0] << " " << argv[1] << "\n";
62 
63     atf::process::argv_array argva(argv);
64     return atf::check::exec(argva);
65 }
66 
67 static
68 std::auto_ptr< atf::check::check_result >
do_exec(const atf::tests::tc * tc,const char * helper_name,const char * carg2)69 do_exec(const atf::tests::tc* tc, const char* helper_name, const char *carg2)
70 {
71     std::vector< std::string > argv;
72     argv.push_back(get_process_helpers_path(*tc, false).str());
73     argv.push_back(helper_name);
74     argv.push_back(carg2);
75     std::cout << "Executing " << argv[0] << " " << argv[1] << " "
76               << argv[2] << "\n";
77 
78     atf::process::argv_array argva(argv);
79     return atf::check::exec(argva);
80 }
81 
82 // ------------------------------------------------------------------------
83 // Helper test cases for the free functions.
84 // ------------------------------------------------------------------------
85 
86 ATF_TEST_CASE(h_build_c_o_ok);
ATF_TEST_CASE_HEAD(h_build_c_o_ok)87 ATF_TEST_CASE_HEAD(h_build_c_o_ok)
88 {
89     set_md_var("descr", "Helper test case for build_c_o");
90 }
ATF_TEST_CASE_BODY(h_build_c_o_ok)91 ATF_TEST_CASE_BODY(h_build_c_o_ok)
92 {
93     std::ofstream sfile("test.c");
94     sfile << "#include <stdio.h>\n";
95     sfile.close();
96 
97     ATF_REQUIRE(atf::check::build_c_o("test.c", "test.o",
98                                       atf::process::argv_array()));
99 }
100 
101 ATF_TEST_CASE(h_build_c_o_fail);
ATF_TEST_CASE_HEAD(h_build_c_o_fail)102 ATF_TEST_CASE_HEAD(h_build_c_o_fail)
103 {
104     set_md_var("descr", "Helper test case for build_c_o");
105 }
ATF_TEST_CASE_BODY(h_build_c_o_fail)106 ATF_TEST_CASE_BODY(h_build_c_o_fail)
107 {
108     std::ofstream sfile("test.c");
109     sfile << "void foo(void) { int a = UNDEFINED_SYMBOL; }\n";
110     sfile.close();
111 
112     ATF_REQUIRE(!atf::check::build_c_o("test.c", "test.o",
113                                        atf::process::argv_array()));
114 }
115 
116 ATF_TEST_CASE(h_build_cpp_ok);
ATF_TEST_CASE_HEAD(h_build_cpp_ok)117 ATF_TEST_CASE_HEAD(h_build_cpp_ok)
118 {
119     set_md_var("descr", "Helper test case for build_cpp");
120 }
ATF_TEST_CASE_BODY(h_build_cpp_ok)121 ATF_TEST_CASE_BODY(h_build_cpp_ok)
122 {
123     std::ofstream sfile("test.c");
124     sfile << "#define A foo\n";
125     sfile << "#define B bar\n";
126     sfile << "A B\n";
127     sfile.close();
128 
129     ATF_REQUIRE(atf::check::build_cpp("test.c", "test.p",
130                                       atf::process::argv_array()));
131 }
132 
133 ATF_TEST_CASE(h_build_cpp_fail);
ATF_TEST_CASE_HEAD(h_build_cpp_fail)134 ATF_TEST_CASE_HEAD(h_build_cpp_fail)
135 {
136     set_md_var("descr", "Helper test case for build_cpp");
137 }
ATF_TEST_CASE_BODY(h_build_cpp_fail)138 ATF_TEST_CASE_BODY(h_build_cpp_fail)
139 {
140     std::ofstream sfile("test.c");
141     sfile << "#include \"./non-existent.h\"\n";
142     sfile.close();
143 
144     ATF_REQUIRE(!atf::check::build_cpp("test.c", "test.p",
145                                        atf::process::argv_array()));
146 }
147 
148 ATF_TEST_CASE(h_build_cxx_o_ok);
ATF_TEST_CASE_HEAD(h_build_cxx_o_ok)149 ATF_TEST_CASE_HEAD(h_build_cxx_o_ok)
150 {
151     set_md_var("descr", "Helper test case for build_cxx_o");
152 }
ATF_TEST_CASE_BODY(h_build_cxx_o_ok)153 ATF_TEST_CASE_BODY(h_build_cxx_o_ok)
154 {
155     std::ofstream sfile("test.cpp");
156     sfile << "#include <iostream>\n";
157     sfile.close();
158 
159     ATF_REQUIRE(atf::check::build_cxx_o("test.cpp", "test.o",
160                                         atf::process::argv_array()));
161 }
162 
163 ATF_TEST_CASE(h_build_cxx_o_fail);
ATF_TEST_CASE_HEAD(h_build_cxx_o_fail)164 ATF_TEST_CASE_HEAD(h_build_cxx_o_fail)
165 {
166     set_md_var("descr", "Helper test case for build_cxx_o");
167 }
ATF_TEST_CASE_BODY(h_build_cxx_o_fail)168 ATF_TEST_CASE_BODY(h_build_cxx_o_fail)
169 {
170     std::ofstream sfile("test.cpp");
171     sfile << "void foo(void) { int a = UNDEFINED_SYMBOL; }\n";
172     sfile.close();
173 
174     ATF_REQUIRE(!atf::check::build_cxx_o("test.cpp", "test.o",
175                                          atf::process::argv_array()));
176 }
177 
178 // ------------------------------------------------------------------------
179 // Test cases for the free functions.
180 // ------------------------------------------------------------------------
181 
182 ATF_TEST_CASE(build_c_o);
ATF_TEST_CASE_HEAD(build_c_o)183 ATF_TEST_CASE_HEAD(build_c_o)
184 {
185     set_md_var("descr", "Tests the build_c_o function");
186 }
ATF_TEST_CASE_BODY(build_c_o)187 ATF_TEST_CASE_BODY(build_c_o)
188 {
189     ATF_TEST_CASE_USE(h_build_c_o_ok);
190     run_h_tc< ATF_TEST_CASE_NAME(h_build_c_o_ok) >();
191     ATF_REQUIRE(atf::utils::grep_file("-o test.o", "stdout"));
192     ATF_REQUIRE(atf::utils::grep_file("-c test.c", "stdout"));
193 
194     ATF_TEST_CASE_USE(h_build_c_o_fail);
195     run_h_tc< ATF_TEST_CASE_NAME(h_build_c_o_fail) >();
196     ATF_REQUIRE(atf::utils::grep_file("-o test.o", "stdout"));
197     ATF_REQUIRE(atf::utils::grep_file("-c test.c", "stdout"));
198     ATF_REQUIRE(atf::utils::grep_file("test.c", "stderr"));
199     ATF_REQUIRE(atf::utils::grep_file("UNDEFINED_SYMBOL", "stderr"));
200 }
201 
202 ATF_TEST_CASE(build_cpp);
ATF_TEST_CASE_HEAD(build_cpp)203 ATF_TEST_CASE_HEAD(build_cpp)
204 {
205     set_md_var("descr", "Tests the build_cpp function");
206 }
ATF_TEST_CASE_BODY(build_cpp)207 ATF_TEST_CASE_BODY(build_cpp)
208 {
209     ATF_TEST_CASE_USE(h_build_cpp_ok);
210     run_h_tc< ATF_TEST_CASE_NAME(h_build_cpp_ok) >();
211     ATF_REQUIRE(atf::utils::grep_file("-o.*test.p", "stdout"));
212     ATF_REQUIRE(atf::utils::grep_file("test.c", "stdout"));
213     ATF_REQUIRE(atf::utils::grep_file("foo bar", "test.p"));
214 
215     ATF_TEST_CASE_USE(h_build_cpp_fail);
216     run_h_tc< ATF_TEST_CASE_NAME(h_build_cpp_fail) >();
217     ATF_REQUIRE(atf::utils::grep_file("-o test.p", "stdout"));
218     ATF_REQUIRE(atf::utils::grep_file("test.c", "stdout"));
219     ATF_REQUIRE(atf::utils::grep_file("test.c", "stderr"));
220     ATF_REQUIRE(atf::utils::grep_file("non-existent.h", "stderr"));
221 }
222 
223 ATF_TEST_CASE(build_cxx_o);
ATF_TEST_CASE_HEAD(build_cxx_o)224 ATF_TEST_CASE_HEAD(build_cxx_o)
225 {
226     set_md_var("descr", "Tests the build_cxx_o function");
227 }
ATF_TEST_CASE_BODY(build_cxx_o)228 ATF_TEST_CASE_BODY(build_cxx_o)
229 {
230     ATF_TEST_CASE_USE(h_build_cxx_o_ok);
231     run_h_tc< ATF_TEST_CASE_NAME(h_build_cxx_o_ok) >();
232     ATF_REQUIRE(atf::utils::grep_file("-o test.o", "stdout"));
233     ATF_REQUIRE(atf::utils::grep_file("-c test.cpp", "stdout"));
234 
235     ATF_TEST_CASE_USE(h_build_cxx_o_fail);
236     run_h_tc< ATF_TEST_CASE_NAME(h_build_cxx_o_fail) >();
237     ATF_REQUIRE(atf::utils::grep_file("-o test.o", "stdout"));
238     ATF_REQUIRE(atf::utils::grep_file("-c test.cpp", "stdout"));
239     ATF_REQUIRE(atf::utils::grep_file("test.cpp", "stderr"));
240     ATF_REQUIRE(atf::utils::grep_file("UNDEFINED_SYMBOL", "stderr"));
241 }
242 
243 ATF_TEST_CASE(exec_cleanup);
ATF_TEST_CASE_HEAD(exec_cleanup)244 ATF_TEST_CASE_HEAD(exec_cleanup)
245 {
246     set_md_var("descr", "Tests that exec properly cleans up the temporary "
247                "files it creates");
248 }
ATF_TEST_CASE_BODY(exec_cleanup)249 ATF_TEST_CASE_BODY(exec_cleanup)
250 {
251     std::auto_ptr< atf::fs::path > out;
252     std::auto_ptr< atf::fs::path > err;
253 
254     {
255         std::auto_ptr< atf::check::check_result > r =
256             do_exec(this, "exit-success");
257         out.reset(new atf::fs::path(r->stdout_path()));
258         err.reset(new atf::fs::path(r->stderr_path()));
259         ATF_REQUIRE(atf::fs::exists(*out.get()));
260         ATF_REQUIRE(atf::fs::exists(*err.get()));
261     }
262     ATF_REQUIRE(!atf::fs::exists(*out.get()));
263     ATF_REQUIRE(!atf::fs::exists(*err.get()));
264 }
265 
266 ATF_TEST_CASE(exec_exitstatus);
ATF_TEST_CASE_HEAD(exec_exitstatus)267 ATF_TEST_CASE_HEAD(exec_exitstatus)
268 {
269     set_md_var("descr", "Tests that exec properly captures the exit "
270                "status of the executed command");
271 }
ATF_TEST_CASE_BODY(exec_exitstatus)272 ATF_TEST_CASE_BODY(exec_exitstatus)
273 {
274     {
275         std::auto_ptr< atf::check::check_result > r =
276             do_exec(this, "exit-success");
277         ATF_REQUIRE(r->exited());
278         ATF_REQUIRE(!r->signaled());
279         ATF_REQUIRE_EQ(r->exitcode(), EXIT_SUCCESS);
280     }
281 
282     {
283         std::auto_ptr< atf::check::check_result > r =
284             do_exec(this, "exit-failure");
285         ATF_REQUIRE(r->exited());
286         ATF_REQUIRE(!r->signaled());
287         ATF_REQUIRE_EQ(r->exitcode(), EXIT_FAILURE);
288     }
289 
290     {
291         std::auto_ptr< atf::check::check_result > r =
292             do_exec(this, "exit-signal");
293         ATF_REQUIRE(!r->exited());
294         ATF_REQUIRE(r->signaled());
295         ATF_REQUIRE_EQ(r->termsig(), SIGKILL);
296     }
297 }
298 
299 static
300 void
check_lines(const std::string & path,const char * outname,const char * resname)301 check_lines(const std::string& path, const char* outname,
302             const char* resname)
303 {
304     std::ifstream f(path.c_str());
305     ATF_REQUIRE(f);
306 
307     std::string line;
308     std::getline(f, line);
309     ATF_REQUIRE_EQ(line, std::string("Line 1 to ") + outname + " for " +
310                     resname);
311     std::getline(f, line);
312     ATF_REQUIRE_EQ(line, std::string("Line 2 to ") + outname + " for " +
313                     resname);
314 }
315 
316 ATF_TEST_CASE(exec_stdout_stderr);
ATF_TEST_CASE_HEAD(exec_stdout_stderr)317 ATF_TEST_CASE_HEAD(exec_stdout_stderr)
318 {
319     set_md_var("descr", "Tests that exec properly captures the stdout "
320                "and stderr streams of the child process");
321 }
ATF_TEST_CASE_BODY(exec_stdout_stderr)322 ATF_TEST_CASE_BODY(exec_stdout_stderr)
323 {
324     std::auto_ptr< atf::check::check_result > r1 =
325         do_exec(this, "stdout-stderr", "result1");
326     ATF_REQUIRE(r1->exited());
327     ATF_REQUIRE_EQ(r1->exitcode(), EXIT_SUCCESS);
328 
329     std::auto_ptr< atf::check::check_result > r2 =
330         do_exec(this, "stdout-stderr", "result2");
331     ATF_REQUIRE(r2->exited());
332     ATF_REQUIRE_EQ(r2->exitcode(), EXIT_SUCCESS);
333 
334     const std::string out1 = r1->stdout_path();
335     const std::string out2 = r2->stdout_path();
336     const std::string err1 = r1->stderr_path();
337     const std::string err2 = r2->stderr_path();
338 
339     ATF_REQUIRE(out1.find("check.XXXXXX") == std::string::npos);
340     ATF_REQUIRE(out2.find("check.XXXXXX") == std::string::npos);
341     ATF_REQUIRE(err1.find("check.XXXXXX") == std::string::npos);
342     ATF_REQUIRE(err2.find("check.XXXXXX") == std::string::npos);
343 
344     ATF_REQUIRE(out1.find("/check") != std::string::npos);
345     ATF_REQUIRE(out2.find("/check") != std::string::npos);
346     ATF_REQUIRE(err1.find("/check") != std::string::npos);
347     ATF_REQUIRE(err2.find("/check") != std::string::npos);
348 
349     ATF_REQUIRE(out1.find("/stdout") != std::string::npos);
350     ATF_REQUIRE(out2.find("/stdout") != std::string::npos);
351     ATF_REQUIRE(err1.find("/stderr") != std::string::npos);
352     ATF_REQUIRE(err2.find("/stderr") != std::string::npos);
353 
354     ATF_REQUIRE(out1 != out2);
355     ATF_REQUIRE(err1 != err2);
356 
357     check_lines(out1, "stdout", "result1");
358     check_lines(out2, "stdout", "result2");
359     check_lines(err1, "stderr", "result1");
360     check_lines(err2, "stderr", "result2");
361 }
362 
363 ATF_TEST_CASE(exec_unknown);
ATF_TEST_CASE_HEAD(exec_unknown)364 ATF_TEST_CASE_HEAD(exec_unknown)
365 {
366     set_md_var("descr", "Tests that running a non-existing binary "
367                "is handled correctly");
368 }
ATF_TEST_CASE_BODY(exec_unknown)369 ATF_TEST_CASE_BODY(exec_unknown)
370 {
371     std::vector< std::string > argv;
372     argv.push_back("/foo/bar/non-existent");
373 
374     atf::process::argv_array argva(argv);
375     std::auto_ptr< atf::check::check_result > r = atf::check::exec(argva);
376     ATF_REQUIRE(r->exited());
377     ATF_REQUIRE_EQ(r->exitcode(), 127);
378 }
379 
380 // ------------------------------------------------------------------------
381 // Main.
382 // ------------------------------------------------------------------------
383 
ATF_INIT_TEST_CASES(tcs)384 ATF_INIT_TEST_CASES(tcs)
385 {
386     // Add the test cases for the free functions.
387     ATF_ADD_TEST_CASE(tcs, build_c_o);
388     ATF_ADD_TEST_CASE(tcs, build_cpp);
389     ATF_ADD_TEST_CASE(tcs, build_cxx_o);
390     ATF_ADD_TEST_CASE(tcs, exec_cleanup);
391     ATF_ADD_TEST_CASE(tcs, exec_exitstatus);
392     ATF_ADD_TEST_CASE(tcs, exec_stdout_stderr);
393     ATF_ADD_TEST_CASE(tcs, exec_unknown);
394 }
395