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::reset_resultsfile(); 339 atf::utils::wait(pid, exitstatus, expout, experr); 340 exit(EXIT_SUCCESS); 341 } 342 343 ATF_TEST_CASE_WITHOUT_HEAD(wait__ok); 344 ATF_TEST_CASE_BODY(wait__ok) 345 { 346 const pid_t control = fork(); 347 ATF_REQUIRE(control != -1); 348 if (control == 0) 349 fork_and_wait(123, "Some output\n", "Some error\n"); 350 else { 351 int status; 352 ATF_REQUIRE(waitpid(control, &status, 0) != -1); 353 ATF_REQUIRE(WIFEXITED(status)); 354 ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); 355 } 356 } 357 358 ATF_TEST_CASE_WITHOUT_HEAD(wait__ok_nested); 359 ATF_TEST_CASE_BODY(wait__ok_nested) 360 { 361 const pid_t parent = atf::utils::fork(); 362 ATF_REQUIRE(parent != -1); 363 if (parent == 0) { 364 const pid_t child = atf::utils::fork(); 365 ATF_REQUIRE(child != -1); 366 if (child == 0) { 367 std::cerr.flush(); 368 std::cout << "Child output\n"; 369 std::cout.flush(); 370 std::cerr << "Child error\n"; 371 std::exit(50); 372 } else { 373 std::cout << "Parent output\n"; 374 std::cerr << "Parent error\n"; 375 atf::utils::wait(child, 50, "Child output\n", "Child error\n"); 376 std::exit(40); 377 } 378 } else { 379 atf::utils::wait(parent, 40, 380 "Parent output\n" 381 "subprocess stdout: Child output\n" 382 "subprocess stderr: Child error\n", 383 "Parent error\n"); 384 } 385 } 386 387 ATF_TEST_CASE_WITHOUT_HEAD(wait__invalid_exitstatus); 388 ATF_TEST_CASE_BODY(wait__invalid_exitstatus) 389 { 390 const pid_t control = fork(); 391 ATF_REQUIRE(control != -1); 392 if (control == 0) 393 fork_and_wait(120, "Some output\n", "Some error\n"); 394 else { 395 int status; 396 ATF_REQUIRE(waitpid(control, &status, 0) != -1); 397 ATF_REQUIRE(WIFEXITED(status)); 398 ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status)); 399 } 400 } 401 402 ATF_TEST_CASE_WITHOUT_HEAD(wait__invalid_stdout); 403 ATF_TEST_CASE_BODY(wait__invalid_stdout) 404 { 405 const pid_t control = fork(); 406 ATF_REQUIRE(control != -1); 407 if (control == 0) 408 fork_and_wait(123, "Some output foo\n", "Some error\n"); 409 else { 410 int status; 411 ATF_REQUIRE(waitpid(control, &status, 0) != -1); 412 ATF_REQUIRE(WIFEXITED(status)); 413 ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status)); 414 } 415 } 416 417 ATF_TEST_CASE_WITHOUT_HEAD(wait__invalid_stderr); 418 ATF_TEST_CASE_BODY(wait__invalid_stderr) 419 { 420 const pid_t control = fork(); 421 ATF_REQUIRE(control != -1); 422 if (control == 0) 423 fork_and_wait(123, "Some output\n", "Some error foo\n"); 424 else { 425 int status; 426 ATF_REQUIRE(waitpid(control, &status, 0) != -1); 427 ATF_REQUIRE(WIFEXITED(status)); 428 ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status)); 429 } 430 } 431 432 ATF_TEST_CASE_WITHOUT_HEAD(wait__save_stdout); 433 ATF_TEST_CASE_BODY(wait__save_stdout) 434 { 435 const pid_t control = fork(); 436 ATF_REQUIRE(control != -1); 437 if (control == 0) 438 fork_and_wait(123, "save:my-output.txt", "Some error\n"); 439 else { 440 int status; 441 ATF_REQUIRE(waitpid(control, &status, 0) != -1); 442 ATF_REQUIRE(WIFEXITED(status)); 443 ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); 444 445 ATF_REQUIRE(atf::utils::compare_file("my-output.txt", "Some output\n")); 446 } 447 } 448 449 ATF_TEST_CASE_WITHOUT_HEAD(wait__save_stderr); 450 ATF_TEST_CASE_BODY(wait__save_stderr) 451 { 452 const pid_t control = fork(); 453 ATF_REQUIRE(control != -1); 454 if (control == 0) 455 fork_and_wait(123, "Some output\n", "save:my-output.txt"); 456 else { 457 int status; 458 ATF_REQUIRE(waitpid(control, &status, 0) != -1); 459 ATF_REQUIRE(WIFEXITED(status)); 460 ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); 461 462 ATF_REQUIRE(atf::utils::compare_file("my-output.txt", "Some error\n")); 463 } 464 } 465 466 // ------------------------------------------------------------------------ 467 // Main. 468 // ------------------------------------------------------------------------ 469 470 ATF_INIT_TEST_CASES(tcs) 471 { 472 // Add the test for the free functions. 473 ATF_ADD_TEST_CASE(tcs, cat_file__empty); 474 ATF_ADD_TEST_CASE(tcs, cat_file__one_line); 475 ATF_ADD_TEST_CASE(tcs, cat_file__several_lines); 476 ATF_ADD_TEST_CASE(tcs, cat_file__no_newline_eof); 477 478 ATF_ADD_TEST_CASE(tcs, compare_file__empty__match); 479 ATF_ADD_TEST_CASE(tcs, compare_file__empty__not_match); 480 ATF_ADD_TEST_CASE(tcs, compare_file__short__match); 481 ATF_ADD_TEST_CASE(tcs, compare_file__short__not_match); 482 ATF_ADD_TEST_CASE(tcs, compare_file__long__match); 483 ATF_ADD_TEST_CASE(tcs, compare_file__long__not_match); 484 485 ATF_ADD_TEST_CASE(tcs, copy_file__empty); 486 ATF_ADD_TEST_CASE(tcs, copy_file__some_contents); 487 488 ATF_ADD_TEST_CASE(tcs, create_file); 489 490 ATF_ADD_TEST_CASE(tcs, file_exists); 491 492 ATF_ADD_TEST_CASE(tcs, fork); 493 494 ATF_ADD_TEST_CASE(tcs, grep_collection__set); 495 ATF_ADD_TEST_CASE(tcs, grep_collection__vector); 496 ATF_ADD_TEST_CASE(tcs, grep_file); 497 ATF_ADD_TEST_CASE(tcs, grep_string); 498 499 ATF_ADD_TEST_CASE(tcs, redirect__stdout); 500 ATF_ADD_TEST_CASE(tcs, redirect__stderr); 501 ATF_ADD_TEST_CASE(tcs, redirect__other); 502 503 ATF_ADD_TEST_CASE(tcs, wait__ok); 504 ATF_ADD_TEST_CASE(tcs, wait__ok_nested); 505 ATF_ADD_TEST_CASE(tcs, wait__invalid_exitstatus); 506 ATF_ADD_TEST_CASE(tcs, wait__invalid_stdout); 507 ATF_ADD_TEST_CASE(tcs, wait__invalid_stderr); 508 ATF_ADD_TEST_CASE(tcs, wait__save_stdout); 509 ATF_ADD_TEST_CASE(tcs, wait__save_stderr); 510 } 511