utils_test.cpp revision 260029
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#include <sys/wait.h> 33 34#include <fcntl.h> 35#include <unistd.h> 36} 37 38#include <cstdlib> 39#include <iostream> 40#include <set> 41#include <string> 42#include <vector> 43 44#include "macros.hpp" 45#include "utils.hpp" 46 47#include "detail/test_helpers.hpp" 48 49static std::string 50read_file(const char *path) 51{ 52 char buffer[1024]; 53 54 const int fd = open(path, O_RDONLY); 55 if (fd == -1) 56 ATF_FAIL("Cannot open " + std::string(path)); 57 const ssize_t length = read(fd, buffer, sizeof(buffer) - 1); 58 close(fd); 59 ATF_REQUIRE(length != -1); 60 if (length == sizeof(buffer) - 1) 61 ATF_FAIL("Internal buffer not long enough to read temporary file"); 62 ((char *)buffer)[length] = '\0'; 63 64 return buffer; 65} 66 67// ------------------------------------------------------------------------ 68// Tests cases for the free functions. 69// ------------------------------------------------------------------------ 70 71ATF_TEST_CASE_WITHOUT_HEAD(cat_file__empty); 72ATF_TEST_CASE_BODY(cat_file__empty) 73{ 74 atf::utils::create_file("file.txt", ""); 75 atf::utils::redirect(STDOUT_FILENO, "captured.txt"); 76 atf::utils::cat_file("file.txt", "PREFIX"); 77 std::cout.flush(); 78 close(STDOUT_FILENO); 79 80 ATF_REQUIRE_EQ("", read_file("captured.txt")); 81} 82 83ATF_TEST_CASE_WITHOUT_HEAD(cat_file__one_line); 84ATF_TEST_CASE_BODY(cat_file__one_line) 85{ 86 atf::utils::create_file("file.txt", "This is a single line\n"); 87 atf::utils::redirect(STDOUT_FILENO, "captured.txt"); 88 atf::utils::cat_file("file.txt", "PREFIX"); 89 std::cout.flush(); 90 close(STDOUT_FILENO); 91 92 ATF_REQUIRE_EQ("PREFIXThis is a single line\n", read_file("captured.txt")); 93} 94 95ATF_TEST_CASE_WITHOUT_HEAD(cat_file__several_lines); 96ATF_TEST_CASE_BODY(cat_file__several_lines) 97{ 98 atf::utils::create_file("file.txt", "First\nSecond line\nAnd third\n"); 99 atf::utils::redirect(STDOUT_FILENO, "captured.txt"); 100 atf::utils::cat_file("file.txt", ">"); 101 std::cout.flush(); 102 close(STDOUT_FILENO); 103 104 ATF_REQUIRE_EQ(">First\n>Second line\n>And third\n", 105 read_file("captured.txt")); 106} 107 108ATF_TEST_CASE_WITHOUT_HEAD(cat_file__no_newline_eof); 109ATF_TEST_CASE_BODY(cat_file__no_newline_eof) 110{ 111 atf::utils::create_file("file.txt", "Foo\n bar baz"); 112 atf::utils::redirect(STDOUT_FILENO, "captured.txt"); 113 atf::utils::cat_file("file.txt", "PREFIX"); 114 std::cout.flush(); 115 close(STDOUT_FILENO); 116 117 ATF_REQUIRE_EQ("PREFIXFoo\nPREFIX bar baz", read_file("captured.txt")); 118} 119 120ATF_TEST_CASE_WITHOUT_HEAD(compare_file__empty__match); 121ATF_TEST_CASE_BODY(compare_file__empty__match) 122{ 123 atf::utils::create_file("test.txt", ""); 124 ATF_REQUIRE(atf::utils::compare_file("test.txt", "")); 125} 126 127ATF_TEST_CASE_WITHOUT_HEAD(compare_file__empty__not_match); 128ATF_TEST_CASE_BODY(compare_file__empty__not_match) 129{ 130 atf::utils::create_file("test.txt", ""); 131 ATF_REQUIRE(!atf::utils::compare_file("test.txt", "\n")); 132 ATF_REQUIRE(!atf::utils::compare_file("test.txt", "foo")); 133 ATF_REQUIRE(!atf::utils::compare_file("test.txt", " ")); 134} 135 136ATF_TEST_CASE_WITHOUT_HEAD(compare_file__short__match); 137ATF_TEST_CASE_BODY(compare_file__short__match) 138{ 139 atf::utils::create_file("test.txt", "this is a short file"); 140 ATF_REQUIRE(atf::utils::compare_file("test.txt", "this is a short file")); 141} 142 143ATF_TEST_CASE_WITHOUT_HEAD(compare_file__short__not_match); 144ATF_TEST_CASE_BODY(compare_file__short__not_match) 145{ 146 atf::utils::create_file("test.txt", "this is a short file"); 147 ATF_REQUIRE(!atf::utils::compare_file("test.txt", "")); 148 ATF_REQUIRE(!atf::utils::compare_file("test.txt", "\n")); 149 ATF_REQUIRE(!atf::utils::compare_file("test.txt", "this is a Short file")); 150 ATF_REQUIRE(!atf::utils::compare_file("test.txt", "this is a short fil")); 151 ATF_REQUIRE(!atf::utils::compare_file("test.txt", "this is a short file ")); 152} 153 154ATF_TEST_CASE_WITHOUT_HEAD(compare_file__long__match); 155ATF_TEST_CASE_BODY(compare_file__long__match) 156{ 157 char long_contents[3456]; 158 size_t i = 0; 159 for (; i < sizeof(long_contents) - 1; i++) 160 long_contents[i] = '0' + (i % 10); 161 long_contents[i] = '\0'; 162 atf::utils::create_file("test.txt", long_contents); 163 164 ATF_REQUIRE(atf::utils::compare_file("test.txt", long_contents)); 165} 166 167ATF_TEST_CASE_WITHOUT_HEAD(compare_file__long__not_match); 168ATF_TEST_CASE_BODY(compare_file__long__not_match) 169{ 170 char long_contents[3456]; 171 size_t i = 0; 172 for (; i < sizeof(long_contents) - 1; i++) 173 long_contents[i] = '0' + (i % 10); 174 long_contents[i] = '\0'; 175 atf::utils::create_file("test.txt", long_contents); 176 177 ATF_REQUIRE(!atf::utils::compare_file("test.txt", "")); 178 ATF_REQUIRE(!atf::utils::compare_file("test.txt", "\n")); 179 ATF_REQUIRE(!atf::utils::compare_file("test.txt", "0123456789")); 180 long_contents[i - 1] = 'Z'; 181 ATF_REQUIRE(!atf::utils::compare_file("test.txt", long_contents)); 182} 183 184ATF_TEST_CASE_WITHOUT_HEAD(copy_file__empty); 185ATF_TEST_CASE_BODY(copy_file__empty) 186{ 187 atf::utils::create_file("src.txt", ""); 188 ATF_REQUIRE(chmod("src.txt", 0520) != -1); 189 190 atf::utils::copy_file("src.txt", "dest.txt"); 191 ATF_REQUIRE(atf::utils::compare_file("dest.txt", "")); 192 struct stat sb; 193 ATF_REQUIRE(stat("dest.txt", &sb) != -1); 194 ATF_REQUIRE_EQ(0520, sb.st_mode & 0xfff); 195} 196 197ATF_TEST_CASE_WITHOUT_HEAD(copy_file__some_contents); 198ATF_TEST_CASE_BODY(copy_file__some_contents) 199{ 200 atf::utils::create_file("src.txt", "This is a\ntest file\n"); 201 atf::utils::copy_file("src.txt", "dest.txt"); 202 ATF_REQUIRE(atf::utils::compare_file("dest.txt", "This is a\ntest file\n")); 203} 204 205ATF_TEST_CASE_WITHOUT_HEAD(create_file); 206ATF_TEST_CASE_BODY(create_file) 207{ 208 atf::utils::create_file("test.txt", "This is a %d test"); 209 210 ATF_REQUIRE_EQ("This is a %d test", read_file("test.txt")); 211} 212 213ATF_TEST_CASE_WITHOUT_HEAD(file_exists); 214ATF_TEST_CASE_BODY(file_exists) 215{ 216 atf::utils::create_file("test.txt", "foo"); 217 218 ATF_REQUIRE( atf::utils::file_exists("test.txt")); 219 ATF_REQUIRE( atf::utils::file_exists("./test.txt")); 220 ATF_REQUIRE(!atf::utils::file_exists("./test.tx")); 221 ATF_REQUIRE(!atf::utils::file_exists("test.txt2")); 222} 223 224ATF_TEST_CASE_WITHOUT_HEAD(fork); 225ATF_TEST_CASE_BODY(fork) 226{ 227 std::cout << "Should not get into child\n"; 228 std::cerr << "Should not get into child\n"; 229 pid_t pid = atf::utils::fork(); 230 if (pid == 0) { 231 std::cout << "Child stdout\n"; 232 std::cerr << "Child stderr\n"; 233 exit(EXIT_SUCCESS); 234 } 235 236 int status; 237 ATF_REQUIRE(waitpid(pid, &status, 0) != -1); 238 ATF_REQUIRE(WIFEXITED(status)); 239 ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); 240 241 ATF_REQUIRE_EQ("Child stdout\n", read_file("atf_utils_fork_out.txt")); 242 ATF_REQUIRE_EQ("Child stderr\n", read_file("atf_utils_fork_err.txt")); 243} 244 245ATF_TEST_CASE_WITHOUT_HEAD(grep_collection__set); 246ATF_TEST_CASE_BODY(grep_collection__set) 247{ 248 std::set< std::string > strings; 249 strings.insert("First"); 250 strings.insert("Second"); 251 252 ATF_REQUIRE( atf::utils::grep_collection("irs", strings)); 253 ATF_REQUIRE( atf::utils::grep_collection("cond", strings)); 254 ATF_REQUIRE(!atf::utils::grep_collection("Third", strings)); 255} 256 257ATF_TEST_CASE_WITHOUT_HEAD(grep_collection__vector); 258ATF_TEST_CASE_BODY(grep_collection__vector) 259{ 260 std::vector< std::string > strings; 261 strings.push_back("First"); 262 strings.push_back("Second"); 263 264 ATF_REQUIRE( atf::utils::grep_collection("irs", strings)); 265 ATF_REQUIRE( atf::utils::grep_collection("cond", strings)); 266 ATF_REQUIRE(!atf::utils::grep_collection("Third", strings)); 267} 268 269ATF_TEST_CASE_WITHOUT_HEAD(grep_file); 270ATF_TEST_CASE_BODY(grep_file) 271{ 272 atf::utils::create_file("test.txt", "line1\nthe second line\naaaabbbb\n"); 273 274 ATF_REQUIRE(atf::utils::grep_file("line1", "test.txt")); 275 ATF_REQUIRE(atf::utils::grep_file("second line", "test.txt")); 276 ATF_REQUIRE(atf::utils::grep_file("aa.*bb", "test.txt")); 277 ATF_REQUIRE(!atf::utils::grep_file("foo", "test.txt")); 278 ATF_REQUIRE(!atf::utils::grep_file("bar", "test.txt")); 279 ATF_REQUIRE(!atf::utils::grep_file("aaaaa", "test.txt")); 280} 281 282ATF_TEST_CASE_WITHOUT_HEAD(grep_string); 283ATF_TEST_CASE_BODY(grep_string) 284{ 285 const char *str = "a string - aaaabbbb"; 286 ATF_REQUIRE(atf::utils::grep_string("a string", str)); 287 ATF_REQUIRE(atf::utils::grep_string("^a string", str)); 288 ATF_REQUIRE(atf::utils::grep_string("aaaabbbb$", str)); 289 ATF_REQUIRE(atf::utils::grep_string("aa.*bb", str)); 290 ATF_REQUIRE(!atf::utils::grep_string("foo", str)); 291 ATF_REQUIRE(!atf::utils::grep_string("bar", str)); 292 ATF_REQUIRE(!atf::utils::grep_string("aaaaa", str)); 293} 294 295ATF_TEST_CASE_WITHOUT_HEAD(redirect__stdout); 296ATF_TEST_CASE_BODY(redirect__stdout) 297{ 298 std::cout << "Buffer this"; 299 atf::utils::redirect(STDOUT_FILENO, "captured.txt"); 300 std::cout << "The printed message"; 301 std::cout.flush(); 302 303 ATF_REQUIRE_EQ("The printed message", read_file("captured.txt")); 304} 305 306ATF_TEST_CASE_WITHOUT_HEAD(redirect__stderr); 307ATF_TEST_CASE_BODY(redirect__stderr) 308{ 309 std::cerr << "Buffer this"; 310 atf::utils::redirect(STDERR_FILENO, "captured.txt"); 311 std::cerr << "The printed message"; 312 std::cerr.flush(); 313 314 ATF_REQUIRE_EQ("The printed message", read_file("captured.txt")); 315} 316 317ATF_TEST_CASE_WITHOUT_HEAD(redirect__other); 318ATF_TEST_CASE_BODY(redirect__other) 319{ 320 const std::string message = "Foo bar\nbaz\n"; 321 atf::utils::redirect(15, "captured.txt"); 322 ATF_REQUIRE(write(15, message.c_str(), message.length()) != -1); 323 close(15); 324 325 ATF_REQUIRE_EQ(message, read_file("captured.txt")); 326} 327 328static void 329fork_and_wait(const int exitstatus, const char* expout, const char* experr) 330{ 331 const pid_t pid = atf::utils::fork(); 332 if (pid == 0) { 333 std::cout << "Some output\n"; 334 std::cerr << "Some error\n"; 335 exit(123); 336 } 337 atf::utils::wait(pid, exitstatus, expout, experr); 338 exit(EXIT_SUCCESS); 339} 340 341ATF_TEST_CASE_WITHOUT_HEAD(wait__ok); 342ATF_TEST_CASE_BODY(wait__ok) 343{ 344 const pid_t control = fork(); 345 ATF_REQUIRE(control != -1); 346 if (control == 0) 347 fork_and_wait(123, "Some output\n", "Some error\n"); 348 else { 349 int status; 350 ATF_REQUIRE(waitpid(control, &status, 0) != -1); 351 ATF_REQUIRE(WIFEXITED(status)); 352 ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); 353 } 354} 355 356ATF_TEST_CASE_WITHOUT_HEAD(wait__invalid_exitstatus); 357ATF_TEST_CASE_BODY(wait__invalid_exitstatus) 358{ 359 const pid_t control = fork(); 360 ATF_REQUIRE(control != -1); 361 if (control == 0) 362 fork_and_wait(120, "Some output\n", "Some error\n"); 363 else { 364 int status; 365 ATF_REQUIRE(waitpid(control, &status, 0) != -1); 366 ATF_REQUIRE(WIFEXITED(status)); 367 ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status)); 368 } 369} 370 371ATF_TEST_CASE_WITHOUT_HEAD(wait__invalid_stdout); 372ATF_TEST_CASE_BODY(wait__invalid_stdout) 373{ 374 const pid_t control = fork(); 375 ATF_REQUIRE(control != -1); 376 if (control == 0) 377 fork_and_wait(123, "Some output foo\n", "Some error\n"); 378 else { 379 int status; 380 ATF_REQUIRE(waitpid(control, &status, 0) != -1); 381 ATF_REQUIRE(WIFEXITED(status)); 382 ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status)); 383 } 384} 385 386ATF_TEST_CASE_WITHOUT_HEAD(wait__invalid_stderr); 387ATF_TEST_CASE_BODY(wait__invalid_stderr) 388{ 389 const pid_t control = fork(); 390 ATF_REQUIRE(control != -1); 391 if (control == 0) 392 fork_and_wait(123, "Some output\n", "Some error foo\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 401ATF_TEST_CASE_WITHOUT_HEAD(wait__save_stdout); 402ATF_TEST_CASE_BODY(wait__save_stdout) 403{ 404 const pid_t control = fork(); 405 ATF_REQUIRE(control != -1); 406 if (control == 0) 407 fork_and_wait(123, "save:my-output.txt", "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_SUCCESS, WEXITSTATUS(status)); 413 414 ATF_REQUIRE(atf::utils::compare_file("my-output.txt", "Some output\n")); 415 } 416} 417 418ATF_TEST_CASE_WITHOUT_HEAD(wait__save_stderr); 419ATF_TEST_CASE_BODY(wait__save_stderr) 420{ 421 const pid_t control = fork(); 422 ATF_REQUIRE(control != -1); 423 if (control == 0) 424 fork_and_wait(123, "Some output\n", "save:my-output.txt"); 425 else { 426 int status; 427 ATF_REQUIRE(waitpid(control, &status, 0) != -1); 428 ATF_REQUIRE(WIFEXITED(status)); 429 ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); 430 431 ATF_REQUIRE(atf::utils::compare_file("my-output.txt", "Some error\n")); 432 } 433} 434 435// ------------------------------------------------------------------------ 436// Tests cases for the header file. 437// ------------------------------------------------------------------------ 438 439HEADER_TC(include, "atf-c++/utils.hpp"); 440 441// ------------------------------------------------------------------------ 442// Main. 443// ------------------------------------------------------------------------ 444 445ATF_INIT_TEST_CASES(tcs) 446{ 447 // Add the test for the free functions. 448 ATF_ADD_TEST_CASE(tcs, cat_file__empty); 449 ATF_ADD_TEST_CASE(tcs, cat_file__one_line); 450 ATF_ADD_TEST_CASE(tcs, cat_file__several_lines); 451 ATF_ADD_TEST_CASE(tcs, cat_file__no_newline_eof); 452 453 ATF_ADD_TEST_CASE(tcs, compare_file__empty__match); 454 ATF_ADD_TEST_CASE(tcs, compare_file__empty__not_match); 455 ATF_ADD_TEST_CASE(tcs, compare_file__short__match); 456 ATF_ADD_TEST_CASE(tcs, compare_file__short__not_match); 457 ATF_ADD_TEST_CASE(tcs, compare_file__long__match); 458 ATF_ADD_TEST_CASE(tcs, compare_file__long__not_match); 459 460 ATF_ADD_TEST_CASE(tcs, copy_file__empty); 461 ATF_ADD_TEST_CASE(tcs, copy_file__some_contents); 462 463 ATF_ADD_TEST_CASE(tcs, create_file); 464 465 ATF_ADD_TEST_CASE(tcs, file_exists); 466 467 ATF_ADD_TEST_CASE(tcs, fork); 468 469 ATF_ADD_TEST_CASE(tcs, grep_collection__set); 470 ATF_ADD_TEST_CASE(tcs, grep_collection__vector); 471 ATF_ADD_TEST_CASE(tcs, grep_file); 472 ATF_ADD_TEST_CASE(tcs, grep_string); 473 474 ATF_ADD_TEST_CASE(tcs, redirect__stdout); 475 ATF_ADD_TEST_CASE(tcs, redirect__stderr); 476 ATF_ADD_TEST_CASE(tcs, redirect__other); 477 478 ATF_ADD_TEST_CASE(tcs, wait__ok); 479 ATF_ADD_TEST_CASE(tcs, wait__invalid_exitstatus); 480 ATF_ADD_TEST_CASE(tcs, wait__invalid_stdout); 481 ATF_ADD_TEST_CASE(tcs, wait__invalid_stderr); 482 ATF_ADD_TEST_CASE(tcs, wait__save_stdout); 483 ATF_ADD_TEST_CASE(tcs, wait__save_stderr); 484 485 // Add the test cases for the header file. 486 ATF_ADD_TEST_CASE(tcs, include); 487} 488