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