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