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 <sys/stat.h> 32 33 #include <signal.h> 34 #include <unistd.h> 35 } 36 37 #include <cstdlib> 38 #include <fstream> 39 #include <iomanip> 40 #include <ios> 41 #include <iostream> 42 #include <string> 43 44 #include <atf-c++.hpp> 45 46 #include "env.hpp" 47 #include "fs.hpp" 48 #include "process.hpp" 49 50 // ------------------------------------------------------------------------ 51 // Auxiliary functions. 52 // ------------------------------------------------------------------------ 53 54 static 55 void 56 touch(const std::string& path) 57 { 58 std::ofstream os(path.c_str()); 59 if (!os) 60 ATF_FAIL("Could not create file " + path); 61 os.close(); 62 } 63 64 // ------------------------------------------------------------------------ 65 // Helper tests for "atf-run_test". 66 // ------------------------------------------------------------------------ 67 68 ATF_TEST_CASE(pass); 69 ATF_TEST_CASE_HEAD(pass) 70 { 71 set_md_var("descr", "Helper test case for the t_integration test program"); 72 } 73 ATF_TEST_CASE_BODY(pass) 74 { 75 } 76 77 ATF_TEST_CASE(config); 78 ATF_TEST_CASE_HEAD(config) 79 { 80 set_md_var("descr", "Helper test case for the t_integration test program"); 81 } 82 ATF_TEST_CASE_BODY(config) 83 { 84 std::cout << "1st: " << get_config_var("1st") << "\n"; 85 std::cout << "2nd: " << get_config_var("2nd") << "\n"; 86 std::cout << "3rd: " << get_config_var("3rd") << "\n"; 87 std::cout << "4th: " << get_config_var("4th") << "\n"; 88 } 89 90 ATF_TEST_CASE(fds); 91 ATF_TEST_CASE_HEAD(fds) 92 { 93 set_md_var("descr", "Helper test case for the t_integration test program"); 94 } 95 ATF_TEST_CASE_BODY(fds) 96 { 97 std::cout << "msg1 to stdout" << "\n"; 98 std::cout << "msg2 to stdout" << "\n"; 99 std::cerr << "msg1 to stderr" << "\n"; 100 std::cerr << "msg2 to stderr" << "\n"; 101 } 102 103 ATF_TEST_CASE_WITHOUT_HEAD(mux_streams); 104 ATF_TEST_CASE_BODY(mux_streams) 105 { 106 for (size_t i = 0; i < 10000; i++) { 107 switch (i % 5) { 108 case 0: 109 std::cout << "stdout " << i << "\n"; 110 break; 111 case 1: 112 std::cerr << "stderr " << i << "\n"; 113 break; 114 case 2: 115 std::cout << "stdout " << i << "\n"; 116 std::cerr << "stderr " << i << "\n"; 117 break; 118 case 3: 119 std::cout << "stdout " << i << "\n"; 120 std::cout << "stdout " << i << "\n"; 121 std::cerr << "stderr " << i << "\n"; 122 break; 123 case 4: 124 std::cout << "stdout " << i << "\n"; 125 std::cerr << "stderr " << i << "\n"; 126 std::cerr << "stderr " << i << "\n"; 127 break; 128 default: 129 std::abort(); 130 } 131 } 132 } 133 134 ATF_TEST_CASE(testvar); 135 ATF_TEST_CASE_HEAD(testvar) 136 { 137 set_md_var("descr", "Helper test case for the t_integration test program"); 138 } 139 ATF_TEST_CASE_BODY(testvar) 140 { 141 if (!has_config_var("testvar")) 142 fail("testvar variable not defined"); 143 std::cout << "testvar: " << get_config_var("testvar") << "\n"; 144 } 145 146 ATF_TEST_CASE(env_list); 147 ATF_TEST_CASE_HEAD(env_list) 148 { 149 set_md_var("descr", "Helper test case for the t_integration test program"); 150 } 151 ATF_TEST_CASE_BODY(env_list) 152 { 153 const tools::process::status s = 154 tools::process::exec(tools::fs::path("env"), 155 tools::process::argv_array("env", NULL), 156 tools::process::stream_inherit(), 157 tools::process::stream_inherit()); 158 ATF_REQUIRE(s.exited()); 159 ATF_REQUIRE(s.exitstatus() == EXIT_SUCCESS); 160 } 161 162 ATF_TEST_CASE(env_home); 163 ATF_TEST_CASE_HEAD(env_home) 164 { 165 set_md_var("descr", "Helper test case for the t_integration test program"); 166 } 167 ATF_TEST_CASE_BODY(env_home) 168 { 169 ATF_REQUIRE(tools::env::has("HOME")); 170 tools::fs::path p(tools::env::get("HOME")); 171 tools::fs::file_info fi1(p); 172 tools::fs::file_info fi2(tools::fs::path(".")); 173 ATF_REQUIRE_EQ(fi1.get_device(), fi2.get_device()); 174 ATF_REQUIRE_EQ(fi1.get_inode(), fi2.get_inode()); 175 } 176 177 ATF_TEST_CASE(read_stdin); 178 ATF_TEST_CASE_HEAD(read_stdin) 179 { 180 set_md_var("descr", "Helper test case for the t_integration test program"); 181 } 182 ATF_TEST_CASE_BODY(read_stdin) 183 { 184 char buf[100]; 185 ssize_t len = ::read(STDIN_FILENO, buf, sizeof(buf) - 1); 186 ATF_REQUIRE(len != -1); 187 188 buf[len + 1] = '\0'; 189 for (ssize_t i = 0; i < len; i++) { 190 if (buf[i] != '\0') { 191 fail("The stdin of the test case does not seem to be /dev/zero; " 192 "got '" + std::string(buf) + "'"); 193 } 194 } 195 } 196 197 ATF_TEST_CASE(umask); 198 ATF_TEST_CASE_HEAD(umask) 199 { 200 set_md_var("descr", "Helper test case for the t_integration test program"); 201 } 202 ATF_TEST_CASE_BODY(umask) 203 { 204 mode_t m = ::umask(0); 205 std::cout << "umask: " << std::setw(4) << std::setfill('0') 206 << std::oct << m << "\n"; 207 (void)::umask(m); 208 } 209 210 ATF_TEST_CASE_WITH_CLEANUP(cleanup_states); 211 ATF_TEST_CASE_HEAD(cleanup_states) 212 { 213 set_md_var("descr", "Helper test case for the t_integration test program"); 214 } 215 ATF_TEST_CASE_BODY(cleanup_states) 216 { 217 touch(get_config_var("statedir") + "/to-delete"); 218 touch(get_config_var("statedir") + "/to-stay"); 219 220 if (get_config_var("state") == "fail") 221 ATF_FAIL("On purpose"); 222 else if (get_config_var("state") == "skip") 223 ATF_SKIP("On purpose"); 224 } 225 ATF_TEST_CASE_CLEANUP(cleanup_states) 226 { 227 tools::fs::remove(tools::fs::path(get_config_var("statedir") + "/to-delete")); 228 } 229 230 ATF_TEST_CASE_WITH_CLEANUP(cleanup_curdir); 231 ATF_TEST_CASE_HEAD(cleanup_curdir) 232 { 233 set_md_var("descr", "Helper test case for the t_integration test program"); 234 } 235 ATF_TEST_CASE_BODY(cleanup_curdir) 236 { 237 std::ofstream os("oldvalue"); 238 if (!os) 239 ATF_FAIL("Failed to create oldvalue file"); 240 os << 1234; 241 os.close(); 242 } 243 ATF_TEST_CASE_CLEANUP(cleanup_curdir) 244 { 245 std::ifstream is("oldvalue"); 246 if (is) { 247 int i; 248 is >> i; 249 std::cout << "Old value: " << i << "\n"; 250 is.close(); 251 } 252 } 253 254 ATF_TEST_CASE(require_arch); 255 ATF_TEST_CASE_HEAD(require_arch) 256 { 257 set_md_var("descr", "Helper test case for the t_integration test program"); 258 set_md_var("require.arch", get_config_var("arch", "not-set")); 259 } 260 ATF_TEST_CASE_BODY(require_arch) 261 { 262 } 263 264 ATF_TEST_CASE(require_config); 265 ATF_TEST_CASE_HEAD(require_config) 266 { 267 set_md_var("descr", "Helper test case for the t_integration test program"); 268 set_md_var("require.config", "var1 var2"); 269 } 270 ATF_TEST_CASE_BODY(require_config) 271 { 272 std::cout << "var1: " << get_config_var("var1") << "\n"; 273 std::cout << "var2: " << get_config_var("var2") << "\n"; 274 } 275 276 ATF_TEST_CASE(require_files); 277 ATF_TEST_CASE_HEAD(require_files) 278 { 279 set_md_var("descr", "Helper test case for the t_integration test program"); 280 set_md_var("require.files", get_config_var("files", "not-set")); 281 } 282 ATF_TEST_CASE_BODY(require_files) 283 { 284 } 285 286 ATF_TEST_CASE(require_machine); 287 ATF_TEST_CASE_HEAD(require_machine) 288 { 289 set_md_var("descr", "Helper test case for the t_integration test program"); 290 set_md_var("require.machine", get_config_var("machine", "not-set")); 291 } 292 ATF_TEST_CASE_BODY(require_machine) 293 { 294 } 295 296 ATF_TEST_CASE(require_progs); 297 ATF_TEST_CASE_HEAD(require_progs) 298 { 299 set_md_var("descr", "Helper test case for the t_integration test program"); 300 set_md_var("require.progs", get_config_var("progs", "not-set")); 301 } 302 ATF_TEST_CASE_BODY(require_progs) 303 { 304 } 305 306 ATF_TEST_CASE(require_user); 307 ATF_TEST_CASE_HEAD(require_user) 308 { 309 set_md_var("descr", "Helper test case for the t_integration test program"); 310 set_md_var("require.user", get_config_var("user", "not-set")); 311 } 312 ATF_TEST_CASE_BODY(require_user) 313 { 314 } 315 316 ATF_TEST_CASE(timeout); 317 ATF_TEST_CASE_HEAD(timeout) 318 { 319 set_md_var("descr", "Helper test case for the t_integration test program"); 320 set_md_var("timeout", "1"); 321 } 322 ATF_TEST_CASE_BODY(timeout) 323 { 324 sleep(10); 325 touch(get_config_var("statedir") + "/finished"); 326 } 327 328 ATF_TEST_CASE(timeout_forkexit); 329 ATF_TEST_CASE_HEAD(timeout_forkexit) 330 { 331 set_md_var("descr", "Helper test case for the t_integration test program"); 332 } 333 ATF_TEST_CASE_BODY(timeout_forkexit) 334 { 335 pid_t pid = fork(); 336 ATF_REQUIRE(pid != -1); 337 338 if (pid == 0) { 339 sigset_t mask; 340 sigemptyset(&mask); 341 342 std::cout << "Waiting in subprocess\n"; 343 std::cout.flush(); 344 ::sigsuspend(&mask); 345 346 touch(get_config_var("statedir") + "/child-finished"); 347 std::cout << "Subprocess exiting\n"; 348 std::cout.flush(); 349 exit(EXIT_SUCCESS); 350 } else { 351 // Don't wait for the child process and let atf-run deal with it. 352 touch(get_config_var("statedir") + "/parent-finished"); 353 std::cout << "Parent process exiting\n"; 354 ATF_PASS(); 355 } 356 } 357 358 ATF_TEST_CASE(use_fs); 359 ATF_TEST_CASE_HEAD(use_fs) 360 { 361 set_md_var("descr", "Helper test case for the t_integration test program"); 362 set_md_var("use.fs", "this-is-deprecated"); 363 } 364 ATF_TEST_CASE_BODY(use_fs) 365 { 366 touch("test-file"); 367 } 368 369 // ------------------------------------------------------------------------ 370 // Helper tests for "atf-report_test". 371 // ------------------------------------------------------------------------ 372 373 ATF_TEST_CASE(diff); 374 ATF_TEST_CASE_HEAD(diff) 375 { 376 set_md_var("descr", "Helper test case for the t_integration program"); 377 } 378 ATF_TEST_CASE_BODY(diff) 379 { 380 std::cout << "--- a 2007-11-04 14:00:41.000000000 +0100\n"; 381 std::cout << "+++ b 2007-11-04 14:00:48.000000000 +0100\n"; 382 std::cout << "@@ -1,7 +1,7 @@\n"; 383 std::cout << " This test is meant to simulate a diff.\n"; 384 std::cout << " Blank space at beginning of context lines must be " 385 "preserved.\n"; 386 std::cout << " \n"; 387 std::cout << "-First original line.\n"; 388 std::cout << "-Second original line.\n"; 389 std::cout << "+First modified line.\n"; 390 std::cout << "+Second modified line.\n"; 391 std::cout << " \n"; 392 std::cout << " EOF\n"; 393 } 394 395 // ------------------------------------------------------------------------ 396 // Main. 397 // ------------------------------------------------------------------------ 398 399 ATF_INIT_TEST_CASES(tcs) 400 { 401 std::string which = tools::env::get("TESTCASE"); 402 403 // Add helper tests for atf-run_test. 404 if (which == "pass") 405 ATF_ADD_TEST_CASE(tcs, pass); 406 if (which == "config") 407 ATF_ADD_TEST_CASE(tcs, config); 408 if (which == "fds") 409 ATF_ADD_TEST_CASE(tcs, fds); 410 if (which == "mux_streams") 411 ATF_ADD_TEST_CASE(tcs, mux_streams); 412 if (which == "testvar") 413 ATF_ADD_TEST_CASE(tcs, testvar); 414 if (which == "env_list") 415 ATF_ADD_TEST_CASE(tcs, env_list); 416 if (which == "env_home") 417 ATF_ADD_TEST_CASE(tcs, env_home); 418 if (which == "read_stdin") 419 ATF_ADD_TEST_CASE(tcs, read_stdin); 420 if (which == "umask") 421 ATF_ADD_TEST_CASE(tcs, umask); 422 if (which == "cleanup_states") 423 ATF_ADD_TEST_CASE(tcs, cleanup_states); 424 if (which == "cleanup_curdir") 425 ATF_ADD_TEST_CASE(tcs, cleanup_curdir); 426 if (which == "require_arch") 427 ATF_ADD_TEST_CASE(tcs, require_arch); 428 if (which == "require_config") 429 ATF_ADD_TEST_CASE(tcs, require_config); 430 if (which == "require_files") 431 ATF_ADD_TEST_CASE(tcs, require_files); 432 if (which == "require_machine") 433 ATF_ADD_TEST_CASE(tcs, require_machine); 434 if (which == "require_progs") 435 ATF_ADD_TEST_CASE(tcs, require_progs); 436 if (which == "require_user") 437 ATF_ADD_TEST_CASE(tcs, require_user); 438 if (which == "timeout") 439 ATF_ADD_TEST_CASE(tcs, timeout); 440 if (which == "timeout_forkexit") 441 ATF_ADD_TEST_CASE(tcs, timeout_forkexit); 442 if (which == "use_fs") 443 ATF_ADD_TEST_CASE(tcs, use_fs); 444 445 // Add helper tests for atf-report_test. 446 if (which == "diff") 447 ATF_ADD_TEST_CASE(tcs, diff); 448 } 449