1 // Copyright (c) 2007 The NetBSD Foundation, Inc. 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions 6 // are met: 7 // 1. Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // 2. Redistributions in binary form must reproduce the above copyright 10 // notice, this list of conditions and the following disclaimer in the 11 // documentation and/or other materials provided with the distribution. 12 // 13 // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 14 // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 15 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 16 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 18 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 20 // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 24 // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 26 #include "atf-c++/utils.hpp" 27 28 extern "C" { 29 #include <sys/stat.h> 30 #include <sys/wait.h> 31 32 #include <fcntl.h> 33 #include <unistd.h> 34 } 35 36 #include <cstdlib> 37 #include <iostream> 38 #include <set> 39 #include <sstream> 40 #include <string> 41 #include <vector> 42 43 #include <atf-c++.hpp> 44 45 static std::string 46 read_file(const std::string& path) 47 { 48 char buffer[1024]; 49 50 const int fd = open(path.c_str(), O_RDONLY); 51 if (fd == -1) 52 ATF_FAIL("Cannot open " + path); 53 const ssize_t length = read(fd, buffer, sizeof(buffer) - 1); 54 close(fd); 55 ATF_REQUIRE(length != -1); 56 if (length == sizeof(buffer) - 1) 57 ATF_FAIL("Internal buffer not long enough to read temporary file"); 58 ((char *)buffer)[length] = '\0'; 59 60 return buffer; 61 } 62 63 // ------------------------------------------------------------------------ 64 // Tests cases for the free functions. 65 // ------------------------------------------------------------------------ 66 67 ATF_TEST_CASE_WITHOUT_HEAD(cat_file__empty); 68 ATF_TEST_CASE_BODY(cat_file__empty) 69 { 70 atf::utils::create_file("file.txt", ""); 71 atf::utils::redirect(STDOUT_FILENO, "captured.txt"); 72 atf::utils::cat_file("file.txt", "PREFIX"); 73 std::cout.flush(); 74 close(STDOUT_FILENO); 75 76 ATF_REQUIRE_EQ("", read_file("captured.txt")); 77 } 78 79 ATF_TEST_CASE_WITHOUT_HEAD(cat_file__one_line); 80 ATF_TEST_CASE_BODY(cat_file__one_line) 81 { 82 atf::utils::create_file("file.txt", "This is a single line\n"); 83 atf::utils::redirect(STDOUT_FILENO, "captured.txt"); 84 atf::utils::cat_file("file.txt", "PREFIX"); 85 std::cout.flush(); 86 close(STDOUT_FILENO); 87 88 ATF_REQUIRE_EQ("PREFIXThis is a single line\n", read_file("captured.txt")); 89 } 90 91 ATF_TEST_CASE_WITHOUT_HEAD(cat_file__several_lines); 92 ATF_TEST_CASE_BODY(cat_file__several_lines) 93 { 94 atf::utils::create_file("file.txt", "First\nSecond line\nAnd third\n"); 95 atf::utils::redirect(STDOUT_FILENO, "captured.txt"); 96 atf::utils::cat_file("file.txt", ">"); 97 std::cout.flush(); 98 close(STDOUT_FILENO); 99 100 ATF_REQUIRE_EQ(">First\n>Second line\n>And third\n", 101 read_file("captured.txt")); 102 } 103 104 ATF_TEST_CASE_WITHOUT_HEAD(cat_file__no_newline_eof); 105 ATF_TEST_CASE_BODY(cat_file__no_newline_eof) 106 { 107 atf::utils::create_file("file.txt", "Foo\n bar baz"); 108 atf::utils::redirect(STDOUT_FILENO, "captured.txt"); 109 atf::utils::cat_file("file.txt", "PREFIX"); 110 std::cout.flush(); 111 close(STDOUT_FILENO); 112 113 ATF_REQUIRE_EQ("PREFIXFoo\nPREFIX bar baz", read_file("captured.txt")); 114 } 115 116 ATF_TEST_CASE_WITHOUT_HEAD(compare_file__empty__match); 117 ATF_TEST_CASE_BODY(compare_file__empty__match) 118 { 119 atf::utils::create_file("test.txt", ""); 120 ATF_REQUIRE(atf::utils::compare_file("test.txt", "")); 121 } 122 123 ATF_TEST_CASE_WITHOUT_HEAD(compare_file__empty__not_match); 124 ATF_TEST_CASE_BODY(compare_file__empty__not_match) 125 { 126 atf::utils::create_file("test.txt", ""); 127 ATF_REQUIRE(!atf::utils::compare_file("test.txt", "\n")); 128 ATF_REQUIRE(!atf::utils::compare_file("test.txt", "foo")); 129 ATF_REQUIRE(!atf::utils::compare_file("test.txt", " ")); 130 } 131 132 ATF_TEST_CASE_WITHOUT_HEAD(compare_file__short__match); 133 ATF_TEST_CASE_BODY(compare_file__short__match) 134 { 135 atf::utils::create_file("test.txt", "this is a short file"); 136 ATF_REQUIRE(atf::utils::compare_file("test.txt", "this is a short file")); 137 } 138 139 ATF_TEST_CASE_WITHOUT_HEAD(compare_file__short__not_match); 140 ATF_TEST_CASE_BODY(compare_file__short__not_match) 141 { 142 atf::utils::create_file("test.txt", "this is a short file"); 143 ATF_REQUIRE(!atf::utils::compare_file("test.txt", "")); 144 ATF_REQUIRE(!atf::utils::compare_file("test.txt", "\n")); 145 ATF_REQUIRE(!atf::utils::compare_file("test.txt", "this is a Short file")); 146 ATF_REQUIRE(!atf::utils::compare_file("test.txt", "this is a short fil")); 147 ATF_REQUIRE(!atf::utils::compare_file("test.txt", "this is a short file ")); 148 } 149 150 ATF_TEST_CASE_WITHOUT_HEAD(compare_file__long__match); 151 ATF_TEST_CASE_BODY(compare_file__long__match) 152 { 153 char long_contents[3456]; 154 size_t i = 0; 155 for (; i < sizeof(long_contents) - 1; i++) 156 long_contents[i] = '0' + (i % 10); 157 long_contents[i] = '\0'; 158 atf::utils::create_file("test.txt", long_contents); 159 160 ATF_REQUIRE(atf::utils::compare_file("test.txt", long_contents)); 161 } 162 163 ATF_TEST_CASE_WITHOUT_HEAD(compare_file__long__not_match); 164 ATF_TEST_CASE_BODY(compare_file__long__not_match) 165 { 166 char long_contents[3456]; 167 size_t i = 0; 168 for (; i < sizeof(long_contents) - 1; i++) 169 long_contents[i] = '0' + (i % 10); 170 long_contents[i] = '\0'; 171 atf::utils::create_file("test.txt", long_contents); 172 173 ATF_REQUIRE(!atf::utils::compare_file("test.txt", "")); 174 ATF_REQUIRE(!atf::utils::compare_file("test.txt", "\n")); 175 ATF_REQUIRE(!atf::utils::compare_file("test.txt", "0123456789")); 176 long_contents[i - 1] = 'Z'; 177 ATF_REQUIRE(!atf::utils::compare_file("test.txt", long_contents)); 178 } 179 180 ATF_TEST_CASE_WITHOUT_HEAD(copy_file__empty); 181 ATF_TEST_CASE_BODY(copy_file__empty) 182 { 183 atf::utils::create_file("src.txt", ""); 184 ATF_REQUIRE(chmod("src.txt", 0520) != -1); 185 186 atf::utils::copy_file("src.txt", "dest.txt"); 187 ATF_REQUIRE(atf::utils::compare_file("dest.txt", "")); 188 struct stat sb; 189 ATF_REQUIRE(stat("dest.txt", &sb) != -1); 190 ATF_REQUIRE_EQ(0520, sb.st_mode & 0xfff); 191 } 192 193 ATF_TEST_CASE_WITHOUT_HEAD(copy_file__some_contents); 194 ATF_TEST_CASE_BODY(copy_file__some_contents) 195 { 196 atf::utils::create_file("src.txt", "This is a\ntest file\n"); 197 atf::utils::copy_file("src.txt", "dest.txt"); 198 ATF_REQUIRE(atf::utils::compare_file("dest.txt", "This is a\ntest file\n")); 199 } 200 201 ATF_TEST_CASE_WITHOUT_HEAD(create_file); 202 ATF_TEST_CASE_BODY(create_file) 203 { 204 atf::utils::create_file("test.txt", "This is a %d test"); 205 206 ATF_REQUIRE_EQ("This is a %d test", read_file("test.txt")); 207 } 208 209 ATF_TEST_CASE_WITHOUT_HEAD(file_exists); 210 ATF_TEST_CASE_BODY(file_exists) 211 { 212 atf::utils::create_file("test.txt", "foo"); 213 214 ATF_REQUIRE( atf::utils::file_exists("test.txt")); 215 ATF_REQUIRE( atf::utils::file_exists("./test.txt")); 216 ATF_REQUIRE(!atf::utils::file_exists("./test.tx")); 217 ATF_REQUIRE(!atf::utils::file_exists("test.txt2")); 218 } 219 220 ATF_TEST_CASE_WITHOUT_HEAD(fork); 221 ATF_TEST_CASE_BODY(fork) 222 { 223 std::cout << "Should not get into child\n"; 224 std::cerr << "Should not get into child\n"; 225 pid_t pid = atf::utils::fork(); 226 if (pid == 0) { 227 std::cout << "Child stdout\n"; 228 std::cerr << "Child stderr\n"; 229 exit(EXIT_SUCCESS); 230 } 231 232 int status; 233 ATF_REQUIRE(waitpid(pid, &status, 0) != -1); 234 ATF_REQUIRE(WIFEXITED(status)); 235 ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); 236 237 std::ostringstream out_name; 238 out_name << "atf_utils_fork_" << pid << "_out.txt"; 239 std::ostringstream err_name; 240 err_name << "atf_utils_fork_" << pid << "_err.txt"; 241 242 ATF_REQUIRE_EQ("Child stdout\n", read_file(out_name.str())); 243 ATF_REQUIRE_EQ("Child stderr\n", read_file(err_name.str())); 244 } 245 246 ATF_TEST_CASE_WITHOUT_HEAD(grep_collection__set); 247 ATF_TEST_CASE_BODY(grep_collection__set) 248 { 249 std::set< std::string > strings; 250 strings.insert("First"); 251 strings.insert("Second"); 252 253 ATF_REQUIRE( atf::utils::grep_collection("irs", strings)); 254 ATF_REQUIRE( atf::utils::grep_collection("cond", strings)); 255 ATF_REQUIRE(!atf::utils::grep_collection("Third", strings)); 256 } 257 258 ATF_TEST_CASE_WITHOUT_HEAD(grep_collection__vector); 259 ATF_TEST_CASE_BODY(grep_collection__vector) 260 { 261 std::vector< std::string > strings; 262 strings.push_back("First"); 263 strings.push_back("Second"); 264 265 ATF_REQUIRE( atf::utils::grep_collection("irs", strings)); 266 ATF_REQUIRE( atf::utils::grep_collection("cond", strings)); 267 ATF_REQUIRE(!atf::utils::grep_collection("Third", strings)); 268 } 269 270 ATF_TEST_CASE_WITHOUT_HEAD(grep_file); 271 ATF_TEST_CASE_BODY(grep_file) 272 { 273 atf::utils::create_file("test.txt", "line1\nthe second line\naaaabbbb\n"); 274 275 ATF_REQUIRE(atf::utils::grep_file("line1", "test.txt")); 276 ATF_REQUIRE(atf::utils::grep_file("second line", "test.txt")); 277 ATF_REQUIRE(atf::utils::grep_file("aa.*bb", "test.txt")); 278 ATF_REQUIRE(!atf::utils::grep_file("foo", "test.txt")); 279 ATF_REQUIRE(!atf::utils::grep_file("bar", "test.txt")); 280 ATF_REQUIRE(!atf::utils::grep_file("aaaaa", "test.txt")); 281 } 282 283 ATF_TEST_CASE_WITHOUT_HEAD(grep_string); 284 ATF_TEST_CASE_BODY(grep_string) 285 { 286 const char *str = "a string - aaaabbbb"; 287 ATF_REQUIRE(atf::utils::grep_string("a string", str)); 288 ATF_REQUIRE(atf::utils::grep_string("^a string", str)); 289 ATF_REQUIRE(atf::utils::grep_string("aaaabbbb$", str)); 290 ATF_REQUIRE(atf::utils::grep_string("aa.*bb", str)); 291 ATF_REQUIRE(!atf::utils::grep_string("foo", str)); 292 ATF_REQUIRE(!atf::utils::grep_string("bar", str)); 293 ATF_REQUIRE(!atf::utils::grep_string("aaaaa", str)); 294 } 295 296 ATF_TEST_CASE_WITHOUT_HEAD(redirect__stdout); 297 ATF_TEST_CASE_BODY(redirect__stdout) 298 { 299 std::cout << "Buffer this"; 300 atf::utils::redirect(STDOUT_FILENO, "captured.txt"); 301 std::cout << "The printed message"; 302 std::cout.flush(); 303 304 ATF_REQUIRE_EQ("The printed message", read_file("captured.txt")); 305 } 306 307 ATF_TEST_CASE_WITHOUT_HEAD(redirect__stderr); 308 ATF_TEST_CASE_BODY(redirect__stderr) 309 { 310 std::cerr << "Buffer this"; 311 atf::utils::redirect(STDERR_FILENO, "captured.txt"); 312 std::cerr << "The printed message"; 313 std::cerr.flush(); 314 315 ATF_REQUIRE_EQ("The printed message", read_file("captured.txt")); 316 } 317 318 ATF_TEST_CASE_WITHOUT_HEAD(redirect__other); 319 ATF_TEST_CASE_BODY(redirect__other) 320 { 321 const std::string message = "Foo bar\nbaz\n"; 322 atf::utils::redirect(15, "captured.txt"); 323 ATF_REQUIRE(write(15, message.c_str(), message.length()) != -1); 324 close(15); 325 326 ATF_REQUIRE_EQ(message, read_file("captured.txt")); 327 } 328 329 static void 330 fork_and_wait(const int exitstatus, const char* expout, const char* experr) 331 { 332 const pid_t pid = atf::utils::fork(); 333 if (pid == 0) { 334 std::cout << "Some output\n"; 335 std::cerr << "Some error\n"; 336 exit(123); 337 } 338 atf::utils::wait(pid, exitstatus, expout, experr); 339 exit(EXIT_SUCCESS); 340 } 341 342 ATF_TEST_CASE_WITHOUT_HEAD(wait__ok); 343 ATF_TEST_CASE_BODY(wait__ok) 344 { 345 const pid_t control = fork(); 346 ATF_REQUIRE(control != -1); 347 if (control == 0) 348 fork_and_wait(123, "Some output\n", "Some error\n"); 349 else { 350 int status; 351 ATF_REQUIRE(waitpid(control, &status, 0) != -1); 352 ATF_REQUIRE(WIFEXITED(status)); 353 ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); 354 } 355 } 356 357 ATF_TEST_CASE_WITHOUT_HEAD(wait__ok_nested); 358 ATF_TEST_CASE_BODY(wait__ok_nested) 359 { 360 const pid_t parent = atf::utils::fork(); 361 ATF_REQUIRE(parent != -1); 362 if (parent == 0) { 363 const pid_t child = atf::utils::fork(); 364 ATF_REQUIRE(child != -1); 365 if (child == 0) { 366 std::cerr.flush(); 367 std::cout << "Child output\n"; 368 std::cout.flush(); 369 std::cerr << "Child error\n"; 370 std::exit(50); 371 } else { 372 std::cout << "Parent output\n"; 373 std::cerr << "Parent error\n"; 374 atf::utils::wait(child, 50, "Child output\n", "Child error\n"); 375 std::exit(40); 376 } 377 } else { 378 atf::utils::wait(parent, 40, 379 "Parent output\n" 380 "subprocess stdout: Child output\n" 381 "subprocess stderr: Child error\n", 382 "Parent error\n"); 383 } 384 } 385 386 ATF_TEST_CASE_WITHOUT_HEAD(wait__invalid_exitstatus); 387 ATF_TEST_CASE_BODY(wait__invalid_exitstatus) 388 { 389 const pid_t control = fork(); 390 ATF_REQUIRE(control != -1); 391 if (control == 0) 392 fork_and_wait(120, "Some output\n", "Some error\n"); 393 else { 394 int status; 395 ATF_REQUIRE(waitpid(control, &status, 0) != -1); 396 ATF_REQUIRE(WIFEXITED(status)); 397 ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status)); 398 } 399 } 400 401 ATF_TEST_CASE_WITHOUT_HEAD(wait__invalid_stdout); 402 ATF_TEST_CASE_BODY(wait__invalid_stdout) 403 { 404 const pid_t control = fork(); 405 ATF_REQUIRE(control != -1); 406 if (control == 0) 407 fork_and_wait(123, "Some output foo\n", "Some error\n"); 408 else { 409 int status; 410 ATF_REQUIRE(waitpid(control, &status, 0) != -1); 411 ATF_REQUIRE(WIFEXITED(status)); 412 ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status)); 413 } 414 } 415 416 ATF_TEST_CASE_WITHOUT_HEAD(wait__invalid_stderr); 417 ATF_TEST_CASE_BODY(wait__invalid_stderr) 418 { 419 const pid_t control = fork(); 420 ATF_REQUIRE(control != -1); 421 if (control == 0) 422 fork_and_wait(123, "Some output\n", "Some error foo\n"); 423 else { 424 int status; 425 ATF_REQUIRE(waitpid(control, &status, 0) != -1); 426 ATF_REQUIRE(WIFEXITED(status)); 427 ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status)); 428 } 429 } 430 431 ATF_TEST_CASE_WITHOUT_HEAD(wait__save_stdout); 432 ATF_TEST_CASE_BODY(wait__save_stdout) 433 { 434 const pid_t control = fork(); 435 ATF_REQUIRE(control != -1); 436 if (control == 0) 437 fork_and_wait(123, "save:my-output.txt", "Some error\n"); 438 else { 439 int status; 440 ATF_REQUIRE(waitpid(control, &status, 0) != -1); 441 ATF_REQUIRE(WIFEXITED(status)); 442 ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); 443 444 ATF_REQUIRE(atf::utils::compare_file("my-output.txt", "Some output\n")); 445 } 446 } 447 448 ATF_TEST_CASE_WITHOUT_HEAD(wait__save_stderr); 449 ATF_TEST_CASE_BODY(wait__save_stderr) 450 { 451 const pid_t control = fork(); 452 ATF_REQUIRE(control != -1); 453 if (control == 0) 454 fork_and_wait(123, "Some output\n", "save:my-output.txt"); 455 else { 456 int status; 457 ATF_REQUIRE(waitpid(control, &status, 0) != -1); 458 ATF_REQUIRE(WIFEXITED(status)); 459 ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); 460 461 ATF_REQUIRE(atf::utils::compare_file("my-output.txt", "Some error\n")); 462 } 463 } 464 465 // ------------------------------------------------------------------------ 466 // Main. 467 // ------------------------------------------------------------------------ 468 469 ATF_INIT_TEST_CASES(tcs) 470 { 471 // Add the test for the free functions. 472 ATF_ADD_TEST_CASE(tcs, cat_file__empty); 473 ATF_ADD_TEST_CASE(tcs, cat_file__one_line); 474 ATF_ADD_TEST_CASE(tcs, cat_file__several_lines); 475 ATF_ADD_TEST_CASE(tcs, cat_file__no_newline_eof); 476 477 ATF_ADD_TEST_CASE(tcs, compare_file__empty__match); 478 ATF_ADD_TEST_CASE(tcs, compare_file__empty__not_match); 479 ATF_ADD_TEST_CASE(tcs, compare_file__short__match); 480 ATF_ADD_TEST_CASE(tcs, compare_file__short__not_match); 481 ATF_ADD_TEST_CASE(tcs, compare_file__long__match); 482 ATF_ADD_TEST_CASE(tcs, compare_file__long__not_match); 483 484 ATF_ADD_TEST_CASE(tcs, copy_file__empty); 485 ATF_ADD_TEST_CASE(tcs, copy_file__some_contents); 486 487 ATF_ADD_TEST_CASE(tcs, create_file); 488 489 ATF_ADD_TEST_CASE(tcs, file_exists); 490 491 ATF_ADD_TEST_CASE(tcs, fork); 492 493 ATF_ADD_TEST_CASE(tcs, grep_collection__set); 494 ATF_ADD_TEST_CASE(tcs, grep_collection__vector); 495 ATF_ADD_TEST_CASE(tcs, grep_file); 496 ATF_ADD_TEST_CASE(tcs, grep_string); 497 498 ATF_ADD_TEST_CASE(tcs, redirect__stdout); 499 ATF_ADD_TEST_CASE(tcs, redirect__stderr); 500 ATF_ADD_TEST_CASE(tcs, redirect__other); 501 502 ATF_ADD_TEST_CASE(tcs, wait__ok); 503 ATF_ADD_TEST_CASE(tcs, wait__ok_nested); 504 ATF_ADD_TEST_CASE(tcs, wait__invalid_exitstatus); 505 ATF_ADD_TEST_CASE(tcs, wait__invalid_stdout); 506 ATF_ADD_TEST_CASE(tcs, wait__invalid_stderr); 507 ATF_ADD_TEST_CASE(tcs, wait__save_stdout); 508 ATF_ADD_TEST_CASE(tcs, wait__save_stderr); 509 } 510