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 "atf-c++/check.hpp" 47 #include "atf-c++/config.hpp" 48 #include "atf-c++/fs.hpp" 49 #include "atf-c++/process.hpp" 50 #include "atf-c++/text.hpp" 51 #include "atf-c++/utils.hpp" 52 53 #include "test_helpers.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(tc->get_config_var("srcdir") + "/../atf-c/h_check"); 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(tc->get_config_var("srcdir") + "/../atf-c/h_check"); 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_CHECK(atf::check::build_c_o(atf::fs::path("test.c"), 103 atf::fs::path("test.o"), 104 atf::process::argv_array())); 105 } 106 107 ATF_TEST_CASE(h_build_c_o_fail); 108 ATF_TEST_CASE_HEAD(h_build_c_o_fail) 109 { 110 set_md_var("descr", "Helper test case for build_c_o"); 111 } 112 ATF_TEST_CASE_BODY(h_build_c_o_fail) 113 { 114 std::ofstream sfile("test.c"); 115 sfile << "void foo(void) { int a = UNDEFINED_SYMBOL; }\n"; 116 sfile.close(); 117 118 ATF_CHECK(!atf::check::build_c_o(atf::fs::path("test.c"), 119 atf::fs::path("test.o"), 120 atf::process::argv_array())); 121 } 122 123 ATF_TEST_CASE(h_build_cpp_ok); 124 ATF_TEST_CASE_HEAD(h_build_cpp_ok) 125 { 126 set_md_var("descr", "Helper test case for build_cpp"); 127 } 128 ATF_TEST_CASE_BODY(h_build_cpp_ok) 129 { 130 std::ofstream sfile("test.c"); 131 sfile << "#define A foo\n"; 132 sfile << "#define B bar\n"; 133 sfile << "A B\n"; 134 sfile.close(); 135 136 ATF_CHECK(atf::check::build_cpp(atf::fs::path("test.c"), 137 atf::fs::path("test.p"), 138 atf::process::argv_array())); 139 } 140 141 ATF_TEST_CASE(h_build_cpp_fail); 142 ATF_TEST_CASE_HEAD(h_build_cpp_fail) 143 { 144 set_md_var("descr", "Helper test case for build_cpp"); 145 } 146 ATF_TEST_CASE_BODY(h_build_cpp_fail) 147 { 148 std::ofstream sfile("test.c"); 149 sfile << "#include \"./non-existent.h\"\n"; 150 sfile.close(); 151 152 ATF_CHECK(!atf::check::build_cpp(atf::fs::path("test.c"), 153 atf::fs::path("test.p"), 154 atf::process::argv_array())); 155 } 156 157 ATF_TEST_CASE(h_build_cxx_o_ok); 158 ATF_TEST_CASE_HEAD(h_build_cxx_o_ok) 159 { 160 set_md_var("descr", "Helper test case for build_cxx_o"); 161 } 162 ATF_TEST_CASE_BODY(h_build_cxx_o_ok) 163 { 164 std::ofstream sfile("test.cpp"); 165 sfile << "#include <iostream>\n"; 166 sfile.close(); 167 168 ATF_CHECK(atf::check::build_cxx_o(atf::fs::path("test.cpp"), 169 atf::fs::path("test.o"), 170 atf::process::argv_array())); 171 } 172 173 ATF_TEST_CASE(h_build_cxx_o_fail); 174 ATF_TEST_CASE_HEAD(h_build_cxx_o_fail) 175 { 176 set_md_var("descr", "Helper test case for build_cxx_o"); 177 } 178 ATF_TEST_CASE_BODY(h_build_cxx_o_fail) 179 { 180 std::ofstream sfile("test.cpp"); 181 sfile << "void foo(void) { int a = UNDEFINED_SYMBOL; }\n"; 182 sfile.close(); 183 184 ATF_CHECK(!atf::check::build_cxx_o(atf::fs::path("test.cpp"), 185 atf::fs::path("test.o"), 186 atf::process::argv_array())); 187 } 188 189 // ------------------------------------------------------------------------ 190 // Test cases for the free functions. 191 // ------------------------------------------------------------------------ 192 193 ATF_TEST_CASE(build_c_o); 194 ATF_TEST_CASE_HEAD(build_c_o) 195 { 196 set_md_var("descr", "Tests the build_c_o function"); 197 } 198 ATF_TEST_CASE_BODY(build_c_o) 199 { 200 run_h_tc< ATF_TEST_CASE_NAME(h_build_c_o_ok) >(); 201 ATF_CHECK(grep_file("stdout", "-o test.o")); 202 ATF_CHECK(grep_file("stdout", "-c test.c")); 203 204 run_h_tc< ATF_TEST_CASE_NAME(h_build_c_o_fail) >(); 205 ATF_CHECK(grep_file("stdout", "-o test.o")); 206 ATF_CHECK(grep_file("stdout", "-c test.c")); 207 ATF_CHECK(grep_file("stderr", "test.c")); 208 ATF_CHECK(grep_file("stderr", "UNDEFINED_SYMBOL")); 209 } 210 211 ATF_TEST_CASE(build_cpp); 212 ATF_TEST_CASE_HEAD(build_cpp) 213 { 214 set_md_var("descr", "Tests the build_cpp function"); 215 } 216 ATF_TEST_CASE_BODY(build_cpp) 217 { 218 run_h_tc< ATF_TEST_CASE_NAME(h_build_cpp_ok) >(); 219 ATF_CHECK(grep_file("stdout", "-o.*test.p")); 220 ATF_CHECK(grep_file("stdout", "test.c")); 221 ATF_CHECK(grep_file("test.p", "foo bar")); 222 223 run_h_tc< ATF_TEST_CASE_NAME(h_build_cpp_fail) >(); 224 ATF_CHECK(grep_file("stdout", "-o test.p")); 225 ATF_CHECK(grep_file("stdout", "test.c")); 226 ATF_CHECK(grep_file("stderr", "test.c")); 227 ATF_CHECK(grep_file("stderr", "non-existent.h")); 228 } 229 230 ATF_TEST_CASE(build_cxx_o); 231 ATF_TEST_CASE_HEAD(build_cxx_o) 232 { 233 set_md_var("descr", "Tests the build_cxx_o function"); 234 } 235 ATF_TEST_CASE_BODY(build_cxx_o) 236 { 237 run_h_tc< ATF_TEST_CASE_NAME(h_build_cxx_o_ok) >(); 238 ATF_CHECK(grep_file("stdout", "-o test.o")); 239 ATF_CHECK(grep_file("stdout", "-c test.cpp")); 240 241 run_h_tc< ATF_TEST_CASE_NAME(h_build_cxx_o_fail) >(); 242 ATF_CHECK(grep_file("stdout", "-o test.o")); 243 ATF_CHECK(grep_file("stdout", "-c test.cpp")); 244 ATF_CHECK(grep_file("stderr", "test.cpp")); 245 ATF_CHECK(grep_file("stderr", "UNDEFINED_SYMBOL")); 246 } 247 248 ATF_TEST_CASE(exec_argv); 249 ATF_TEST_CASE_HEAD(exec_argv) 250 { 251 set_md_var("descr", "Tests that exec preserves the provided argv"); 252 } 253 ATF_TEST_CASE_BODY(exec_argv) 254 { 255 const atf::check::check_result r = do_exec(this, "exit-success"); 256 ATF_CHECK_EQUAL(r.argv().size(), 2); 257 ATF_CHECK_EQUAL(r.argv()[0], 258 get_config_var("srcdir") + "/../atf-c/h_check"); 259 ATF_CHECK_EQUAL(r.argv()[1], "exit-success"); 260 } 261 262 ATF_TEST_CASE(exec_cleanup); 263 ATF_TEST_CASE_HEAD(exec_cleanup) 264 { 265 set_md_var("descr", "Tests that exec properly cleans up the temporary " 266 "files it creates"); 267 } 268 ATF_TEST_CASE_BODY(exec_cleanup) 269 { 270 std::auto_ptr< atf::fs::path > out; 271 std::auto_ptr< atf::fs::path > err; 272 273 { 274 const atf::check::check_result r = do_exec(this, "exit-success"); 275 out.reset(new atf::fs::path(r.stdout_path())); 276 err.reset(new atf::fs::path(r.stderr_path())); 277 ATF_CHECK(atf::fs::exists(*out.get())); 278 ATF_CHECK(atf::fs::exists(*err.get())); 279 } 280 ATF_CHECK(!atf::fs::exists(*out.get())); 281 ATF_CHECK(!atf::fs::exists(*err.get())); 282 } 283 284 ATF_TEST_CASE(exec_exitstatus); 285 ATF_TEST_CASE_HEAD(exec_exitstatus) 286 { 287 set_md_var("descr", "Tests that exec properly captures the exit " 288 "status of the executed command"); 289 } 290 ATF_TEST_CASE_BODY(exec_exitstatus) 291 { 292 { 293 atf::check::check_result r = do_exec(this, "exit-success"); 294 ATF_CHECK(r.exited()); 295 ATF_CHECK(!r.signaled()); 296 ATF_CHECK_EQUAL(r.exitcode(), EXIT_SUCCESS); 297 } 298 299 { 300 atf::check::check_result r = do_exec(this, "exit-failure"); 301 ATF_CHECK(r.exited()); 302 ATF_CHECK(!r.signaled()); 303 ATF_CHECK_EQUAL(r.exitcode(), EXIT_FAILURE); 304 } 305 306 { 307 atf::check::check_result r = do_exec(this, "exit-signal"); 308 ATF_CHECK(!r.exited()); 309 ATF_CHECK(r.signaled()); 310 ATF_CHECK_EQUAL(r.termsig(), SIGKILL); 311 } 312 } 313 314 static 315 void 316 check_lines(const atf::fs::path& path, const char* outname, 317 const char* resname) 318 { 319 std::ifstream f(path.c_str()); 320 ATF_CHECK(f); 321 322 std::string line; 323 std::getline(f, line); 324 ATF_CHECK_EQUAL(line, std::string("Line 1 to ") + outname + " for " + 325 resname); 326 std::getline(f, line); 327 ATF_CHECK_EQUAL(line, std::string("Line 2 to ") + outname + " for " + 328 resname); 329 } 330 331 ATF_TEST_CASE(exec_stdout_stderr); 332 ATF_TEST_CASE_HEAD(exec_stdout_stderr) 333 { 334 set_md_var("descr", "Tests that exec properly captures the stdout " 335 "and stderr streams of the child process"); 336 } 337 ATF_TEST_CASE_BODY(exec_stdout_stderr) 338 { 339 const atf::check::check_result r1 = do_exec(this, "stdout-stderr", 340 "result1"); 341 ATF_CHECK(r1.exited()); 342 ATF_CHECK_EQUAL(r1.exitcode(), EXIT_SUCCESS); 343 344 const atf::check::check_result r2 = do_exec(this, "stdout-stderr", 345 "result2"); 346 ATF_CHECK(r2.exited()); 347 ATF_CHECK_EQUAL(r2.exitcode(), EXIT_SUCCESS); 348 349 const atf::fs::path& out1 = r1.stdout_path(); 350 const atf::fs::path& out2 = r2.stdout_path(); 351 const atf::fs::path& err1 = r1.stderr_path(); 352 const atf::fs::path& err2 = r2.stderr_path(); 353 354 ATF_CHECK(out1.str().find("check.XXXXXX") == std::string::npos); 355 ATF_CHECK(out2.str().find("check.XXXXXX") == std::string::npos); 356 ATF_CHECK(err1.str().find("check.XXXXXX") == std::string::npos); 357 ATF_CHECK(err2.str().find("check.XXXXXX") == std::string::npos); 358 359 ATF_CHECK(out1.str().find("/check") != std::string::npos); 360 ATF_CHECK(out2.str().find("/check") != std::string::npos); 361 ATF_CHECK(err1.str().find("/check") != std::string::npos); 362 ATF_CHECK(err2.str().find("/check") != std::string::npos); 363 364 ATF_CHECK(out1.str().find("/stdout") != std::string::npos); 365 ATF_CHECK(out2.str().find("/stdout") != std::string::npos); 366 ATF_CHECK(err1.str().find("/stderr") != std::string::npos); 367 ATF_CHECK(err2.str().find("/stderr") != std::string::npos); 368 369 ATF_CHECK(out1 != out2); 370 ATF_CHECK(err1 != err2); 371 372 check_lines(out1, "stdout", "result1"); 373 check_lines(out2, "stdout", "result2"); 374 check_lines(err1, "stderr", "result1"); 375 check_lines(err2, "stderr", "result2"); 376 } 377 378 ATF_TEST_CASE(exec_unknown); 379 ATF_TEST_CASE_HEAD(exec_unknown) 380 { 381 set_md_var("descr", "Tests that running a non-existing binary " 382 "is handled correctly"); 383 } 384 ATF_TEST_CASE_BODY(exec_unknown) 385 { 386 std::vector< std::string > argv; 387 argv.push_back(atf::config::get("atf_workdir") + "/non-existent"); 388 389 atf::process::argv_array argva(argv); 390 const atf::check::check_result r = atf::check::exec(argva); 391 ATF_CHECK(r.exited()); 392 ATF_CHECK_EQUAL(r.exitcode(), 127); 393 } 394 395 // ------------------------------------------------------------------------ 396 // Tests cases for the header file. 397 // ------------------------------------------------------------------------ 398 399 HEADER_TC(include, "atf-c++/check.hpp"); 400 401 // ------------------------------------------------------------------------ 402 // Main. 403 // ------------------------------------------------------------------------ 404 405 ATF_INIT_TEST_CASES(tcs) 406 { 407 // Add the test cases for the free functions. 408 ATF_ADD_TEST_CASE(tcs, build_c_o); 409 ATF_ADD_TEST_CASE(tcs, build_cpp); 410 ATF_ADD_TEST_CASE(tcs, build_cxx_o); 411 ATF_ADD_TEST_CASE(tcs, exec_argv); 412 ATF_ADD_TEST_CASE(tcs, exec_cleanup); 413 ATF_ADD_TEST_CASE(tcs, exec_exitstatus); 414 ATF_ADD_TEST_CASE(tcs, exec_stdout_stderr); 415 ATF_ADD_TEST_CASE(tcs, exec_unknown); 416 417 // Add the test cases for the header file. 418 ATF_ADD_TEST_CASE(tcs, include); 419 } 420