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 > 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 > 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); 87 ATF_TEST_CASE_HEAD(h_build_c_o_ok) 88 { 89 set_md_var("descr", "Helper test case for build_c_o"); 90 } 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); 102 ATF_TEST_CASE_HEAD(h_build_c_o_fail) 103 { 104 set_md_var("descr", "Helper test case for build_c_o"); 105 } 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); 117 ATF_TEST_CASE_HEAD(h_build_cpp_ok) 118 { 119 set_md_var("descr", "Helper test case for build_cpp"); 120 } 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); 134 ATF_TEST_CASE_HEAD(h_build_cpp_fail) 135 { 136 set_md_var("descr", "Helper test case for build_cpp"); 137 } 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); 149 ATF_TEST_CASE_HEAD(h_build_cxx_o_ok) 150 { 151 set_md_var("descr", "Helper test case for build_cxx_o"); 152 } 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); 164 ATF_TEST_CASE_HEAD(h_build_cxx_o_fail) 165 { 166 set_md_var("descr", "Helper test case for build_cxx_o"); 167 } 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); 183 ATF_TEST_CASE_HEAD(build_c_o) 184 { 185 set_md_var("descr", "Tests the build_c_o function"); 186 } 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); 203 ATF_TEST_CASE_HEAD(build_cpp) 204 { 205 set_md_var("descr", "Tests the build_cpp function"); 206 } 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); 224 ATF_TEST_CASE_HEAD(build_cxx_o) 225 { 226 set_md_var("descr", "Tests the build_cxx_o function"); 227 } 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); 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 } 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); 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 } 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 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); 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 } 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); 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 } 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 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