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 #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 49 static std::string 50 read_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 71 ATF_TEST_CASE_WITHOUT_HEAD(cat_file__empty); 72 ATF_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 83 ATF_TEST_CASE_WITHOUT_HEAD(cat_file__one_line); 84 ATF_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 95 ATF_TEST_CASE_WITHOUT_HEAD(cat_file__several_lines); 96 ATF_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 108 ATF_TEST_CASE_WITHOUT_HEAD(cat_file__no_newline_eof); 109 ATF_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 120 ATF_TEST_CASE_WITHOUT_HEAD(compare_file__empty__match); 121 ATF_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 127 ATF_TEST_CASE_WITHOUT_HEAD(compare_file__empty__not_match); 128 ATF_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 136 ATF_TEST_CASE_WITHOUT_HEAD(compare_file__short__match); 137 ATF_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 143 ATF_TEST_CASE_WITHOUT_HEAD(compare_file__short__not_match); 144 ATF_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 154 ATF_TEST_CASE_WITHOUT_HEAD(compare_file__long__match); 155 ATF_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 167 ATF_TEST_CASE_WITHOUT_HEAD(compare_file__long__not_match); 168 ATF_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 184 ATF_TEST_CASE_WITHOUT_HEAD(copy_file__empty); 185 ATF_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 197 ATF_TEST_CASE_WITHOUT_HEAD(copy_file__some_contents); 198 ATF_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 205 ATF_TEST_CASE_WITHOUT_HEAD(create_file); 206 ATF_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 213 ATF_TEST_CASE_WITHOUT_HEAD(file_exists); 214 ATF_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 224 ATF_TEST_CASE_WITHOUT_HEAD(fork); 225 ATF_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 245 ATF_TEST_CASE_WITHOUT_HEAD(grep_collection__set); 246 ATF_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 257 ATF_TEST_CASE_WITHOUT_HEAD(grep_collection__vector); 258 ATF_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 269 ATF_TEST_CASE_WITHOUT_HEAD(grep_file); 270 ATF_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 282 ATF_TEST_CASE_WITHOUT_HEAD(grep_string); 283 ATF_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 295 ATF_TEST_CASE_WITHOUT_HEAD(redirect__stdout); 296 ATF_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 306 ATF_TEST_CASE_WITHOUT_HEAD(redirect__stderr); 307 ATF_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 317 ATF_TEST_CASE_WITHOUT_HEAD(redirect__other); 318 ATF_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 328 static void 329 fork_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 341 ATF_TEST_CASE_WITHOUT_HEAD(wait__ok); 342 ATF_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 356 ATF_TEST_CASE_WITHOUT_HEAD(wait__invalid_exitstatus); 357 ATF_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 371 ATF_TEST_CASE_WITHOUT_HEAD(wait__invalid_stdout); 372 ATF_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 386 ATF_TEST_CASE_WITHOUT_HEAD(wait__invalid_stderr); 387 ATF_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 401 ATF_TEST_CASE_WITHOUT_HEAD(wait__save_stdout); 402 ATF_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 418 ATF_TEST_CASE_WITHOUT_HEAD(wait__save_stderr); 419 ATF_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 439 HEADER_TC(include, "atf-c++/utils.hpp"); 440 441 // ------------------------------------------------------------------------ 442 // Main. 443 // ------------------------------------------------------------------------ 444 445 ATF_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