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