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