1 // 2 // Automated Testing Framework (atf) 3 // 4 // Copyright (c) 2007 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, false).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, false).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 ATF_TEST_CASE_USE(h_build_c_o_ok); 195 run_h_tc< ATF_TEST_CASE_NAME(h_build_c_o_ok) >(); 196 ATF_REQUIRE(grep_file("stdout", "-o test.o")); 197 ATF_REQUIRE(grep_file("stdout", "-c test.c")); 198 199 ATF_TEST_CASE_USE(h_build_c_o_fail); 200 run_h_tc< ATF_TEST_CASE_NAME(h_build_c_o_fail) >(); 201 ATF_REQUIRE(grep_file("stdout", "-o test.o")); 202 ATF_REQUIRE(grep_file("stdout", "-c test.c")); 203 ATF_REQUIRE(grep_file("stderr", "test.c")); 204 ATF_REQUIRE(grep_file("stderr", "UNDEFINED_SYMBOL")); 205 } 206 207 ATF_TEST_CASE(build_cpp); 208 ATF_TEST_CASE_HEAD(build_cpp) 209 { 210 set_md_var("descr", "Tests the build_cpp function"); 211 } 212 ATF_TEST_CASE_BODY(build_cpp) 213 { 214 ATF_TEST_CASE_USE(h_build_cpp_ok); 215 run_h_tc< ATF_TEST_CASE_NAME(h_build_cpp_ok) >(); 216 ATF_REQUIRE(grep_file("stdout", "-o.*test.p")); 217 ATF_REQUIRE(grep_file("stdout", "test.c")); 218 ATF_REQUIRE(grep_file("test.p", "foo bar")); 219 220 ATF_TEST_CASE_USE(h_build_cpp_fail); 221 run_h_tc< ATF_TEST_CASE_NAME(h_build_cpp_fail) >(); 222 ATF_REQUIRE(grep_file("stdout", "-o test.p")); 223 ATF_REQUIRE(grep_file("stdout", "test.c")); 224 ATF_REQUIRE(grep_file("stderr", "test.c")); 225 ATF_REQUIRE(grep_file("stderr", "non-existent.h")); 226 } 227 228 ATF_TEST_CASE(build_cxx_o); 229 ATF_TEST_CASE_HEAD(build_cxx_o) 230 { 231 set_md_var("descr", "Tests the build_cxx_o function"); 232 } 233 ATF_TEST_CASE_BODY(build_cxx_o) 234 { 235 ATF_TEST_CASE_USE(h_build_cxx_o_ok); 236 run_h_tc< ATF_TEST_CASE_NAME(h_build_cxx_o_ok) >(); 237 ATF_REQUIRE(grep_file("stdout", "-o test.o")); 238 ATF_REQUIRE(grep_file("stdout", "-c test.cpp")); 239 240 ATF_TEST_CASE_USE(h_build_cxx_o_fail); 241 run_h_tc< ATF_TEST_CASE_NAME(h_build_cxx_o_fail) >(); 242 ATF_REQUIRE(grep_file("stdout", "-o test.o")); 243 ATF_REQUIRE(grep_file("stdout", "-c test.cpp")); 244 ATF_REQUIRE(grep_file("stderr", "test.cpp")); 245 ATF_REQUIRE(grep_file("stderr", "UNDEFINED_SYMBOL")); 246 } 247 248 ATF_TEST_CASE(exec_cleanup); 249 ATF_TEST_CASE_HEAD(exec_cleanup) 250 { 251 set_md_var("descr", "Tests that exec properly cleans up the temporary " 252 "files it creates"); 253 } 254 ATF_TEST_CASE_BODY(exec_cleanup) 255 { 256 std::auto_ptr< atf::fs::path > out; 257 std::auto_ptr< atf::fs::path > err; 258 259 { 260 std::auto_ptr< atf::check::check_result > r = 261 do_exec(this, "exit-success"); 262 out.reset(new atf::fs::path(r->stdout_path())); 263 err.reset(new atf::fs::path(r->stderr_path())); 264 ATF_REQUIRE(atf::fs::exists(*out.get())); 265 ATF_REQUIRE(atf::fs::exists(*err.get())); 266 } 267 ATF_REQUIRE(!atf::fs::exists(*out.get())); 268 ATF_REQUIRE(!atf::fs::exists(*err.get())); 269 } 270 271 ATF_TEST_CASE(exec_exitstatus); 272 ATF_TEST_CASE_HEAD(exec_exitstatus) 273 { 274 set_md_var("descr", "Tests that exec properly captures the exit " 275 "status of the executed command"); 276 } 277 ATF_TEST_CASE_BODY(exec_exitstatus) 278 { 279 { 280 std::auto_ptr< atf::check::check_result > r = 281 do_exec(this, "exit-success"); 282 ATF_REQUIRE(r->exited()); 283 ATF_REQUIRE(!r->signaled()); 284 ATF_REQUIRE_EQ(r->exitcode(), EXIT_SUCCESS); 285 } 286 287 { 288 std::auto_ptr< atf::check::check_result > r = 289 do_exec(this, "exit-failure"); 290 ATF_REQUIRE(r->exited()); 291 ATF_REQUIRE(!r->signaled()); 292 ATF_REQUIRE_EQ(r->exitcode(), EXIT_FAILURE); 293 } 294 295 { 296 std::auto_ptr< atf::check::check_result > r = 297 do_exec(this, "exit-signal"); 298 ATF_REQUIRE(!r->exited()); 299 ATF_REQUIRE(r->signaled()); 300 ATF_REQUIRE_EQ(r->termsig(), SIGKILL); 301 } 302 } 303 304 static 305 void 306 check_lines(const std::string& path, const char* outname, 307 const char* resname) 308 { 309 std::ifstream f(path.c_str()); 310 ATF_REQUIRE(f); 311 312 std::string line; 313 std::getline(f, line); 314 ATF_REQUIRE_EQ(line, std::string("Line 1 to ") + outname + " for " + 315 resname); 316 std::getline(f, line); 317 ATF_REQUIRE_EQ(line, std::string("Line 2 to ") + outname + " for " + 318 resname); 319 } 320 321 ATF_TEST_CASE(exec_stdout_stderr); 322 ATF_TEST_CASE_HEAD(exec_stdout_stderr) 323 { 324 set_md_var("descr", "Tests that exec properly captures the stdout " 325 "and stderr streams of the child process"); 326 } 327 ATF_TEST_CASE_BODY(exec_stdout_stderr) 328 { 329 std::auto_ptr< atf::check::check_result > r1 = 330 do_exec(this, "stdout-stderr", "result1"); 331 ATF_REQUIRE(r1->exited()); 332 ATF_REQUIRE_EQ(r1->exitcode(), EXIT_SUCCESS); 333 334 std::auto_ptr< atf::check::check_result > r2 = 335 do_exec(this, "stdout-stderr", "result2"); 336 ATF_REQUIRE(r2->exited()); 337 ATF_REQUIRE_EQ(r2->exitcode(), EXIT_SUCCESS); 338 339 const std::string out1 = r1->stdout_path(); 340 const std::string out2 = r2->stdout_path(); 341 const std::string err1 = r1->stderr_path(); 342 const std::string err2 = r2->stderr_path(); 343 344 ATF_REQUIRE(out1.find("check.XXXXXX") == std::string::npos); 345 ATF_REQUIRE(out2.find("check.XXXXXX") == std::string::npos); 346 ATF_REQUIRE(err1.find("check.XXXXXX") == std::string::npos); 347 ATF_REQUIRE(err2.find("check.XXXXXX") == std::string::npos); 348 349 ATF_REQUIRE(out1.find("/check") != std::string::npos); 350 ATF_REQUIRE(out2.find("/check") != std::string::npos); 351 ATF_REQUIRE(err1.find("/check") != std::string::npos); 352 ATF_REQUIRE(err2.find("/check") != std::string::npos); 353 354 ATF_REQUIRE(out1.find("/stdout") != std::string::npos); 355 ATF_REQUIRE(out2.find("/stdout") != std::string::npos); 356 ATF_REQUIRE(err1.find("/stderr") != std::string::npos); 357 ATF_REQUIRE(err2.find("/stderr") != std::string::npos); 358 359 ATF_REQUIRE(out1 != out2); 360 ATF_REQUIRE(err1 != err2); 361 362 check_lines(out1, "stdout", "result1"); 363 check_lines(out2, "stdout", "result2"); 364 check_lines(err1, "stderr", "result1"); 365 check_lines(err2, "stderr", "result2"); 366 } 367 368 ATF_TEST_CASE(exec_unknown); 369 ATF_TEST_CASE_HEAD(exec_unknown) 370 { 371 set_md_var("descr", "Tests that running a non-existing binary " 372 "is handled correctly"); 373 } 374 ATF_TEST_CASE_BODY(exec_unknown) 375 { 376 std::vector< std::string > argv; 377 argv.push_back(atf::config::get("atf_workdir") + "/non-existent"); 378 379 atf::process::argv_array argva(argv); 380 std::auto_ptr< atf::check::check_result > r = atf::check::exec(argva); 381 ATF_REQUIRE(r->exited()); 382 ATF_REQUIRE_EQ(r->exitcode(), 127); 383 } 384 385 // ------------------------------------------------------------------------ 386 // Tests cases for the header file. 387 // ------------------------------------------------------------------------ 388 389 HEADER_TC(include, "atf-c++/check.hpp"); 390 391 // ------------------------------------------------------------------------ 392 // Main. 393 // ------------------------------------------------------------------------ 394 395 ATF_INIT_TEST_CASES(tcs) 396 { 397 // Add the test cases for the free functions. 398 ATF_ADD_TEST_CASE(tcs, build_c_o); 399 ATF_ADD_TEST_CASE(tcs, build_cpp); 400 ATF_ADD_TEST_CASE(tcs, build_cxx_o); 401 ATF_ADD_TEST_CASE(tcs, exec_cleanup); 402 ATF_ADD_TEST_CASE(tcs, exec_exitstatus); 403 ATF_ADD_TEST_CASE(tcs, exec_stdout_stderr); 404 ATF_ADD_TEST_CASE(tcs, exec_unknown); 405 406 // Add the test cases for the header file. 407 ATF_ADD_TEST_CASE(tcs, include); 408 } 409