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 28extern "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 54static 55std::auto_ptr< atf::check::check_result > 56do_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 67static 68std::auto_ptr< atf::check::check_result > 69do_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 86ATF_TEST_CASE(h_build_c_o_ok); 87ATF_TEST_CASE_HEAD(h_build_c_o_ok) 88{ 89 set_md_var("descr", "Helper test case for build_c_o"); 90} 91ATF_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 101ATF_TEST_CASE(h_build_c_o_fail); 102ATF_TEST_CASE_HEAD(h_build_c_o_fail) 103{ 104 set_md_var("descr", "Helper test case for build_c_o"); 105} 106ATF_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 116ATF_TEST_CASE(h_build_cpp_ok); 117ATF_TEST_CASE_HEAD(h_build_cpp_ok) 118{ 119 set_md_var("descr", "Helper test case for build_cpp"); 120} 121ATF_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 133ATF_TEST_CASE(h_build_cpp_fail); 134ATF_TEST_CASE_HEAD(h_build_cpp_fail) 135{ 136 set_md_var("descr", "Helper test case for build_cpp"); 137} 138ATF_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 148ATF_TEST_CASE(h_build_cxx_o_ok); 149ATF_TEST_CASE_HEAD(h_build_cxx_o_ok) 150{ 151 set_md_var("descr", "Helper test case for build_cxx_o"); 152} 153ATF_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 163ATF_TEST_CASE(h_build_cxx_o_fail); 164ATF_TEST_CASE_HEAD(h_build_cxx_o_fail) 165{ 166 set_md_var("descr", "Helper test case for build_cxx_o"); 167} 168ATF_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 182ATF_TEST_CASE(build_c_o); 183ATF_TEST_CASE_HEAD(build_c_o) 184{ 185 set_md_var("descr", "Tests the build_c_o function"); 186} 187ATF_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 202ATF_TEST_CASE(build_cpp); 203ATF_TEST_CASE_HEAD(build_cpp) 204{ 205 set_md_var("descr", "Tests the build_cpp function"); 206} 207ATF_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 223ATF_TEST_CASE(build_cxx_o); 224ATF_TEST_CASE_HEAD(build_cxx_o) 225{ 226 set_md_var("descr", "Tests the build_cxx_o function"); 227} 228ATF_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 243ATF_TEST_CASE(exec_cleanup); 244ATF_TEST_CASE_HEAD(exec_cleanup) 245{ 246 set_md_var("descr", "Tests that exec properly cleans up the temporary " 247 "files it creates"); 248} 249ATF_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 266ATF_TEST_CASE(exec_exitstatus); 267ATF_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} 272ATF_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 299static 300void 301check_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 316ATF_TEST_CASE(exec_stdout_stderr); 317ATF_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} 322ATF_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 363ATF_TEST_CASE(exec_unknown); 364ATF_TEST_CASE_HEAD(exec_unknown) 365{ 366 set_md_var("descr", "Tests that running a non-existing binary " 367 "is handled correctly"); 368} 369ATF_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 384ATF_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