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