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