1 /* Copyright (c) 2010 The NetBSD Foundation, Inc.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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. */
26 #include "atf-c/utils.h"
40 #include "atf-c/detail/dynstr.h"
41 #include "atf-c/detail/test_helpers.h"
43 /** Reads the contents of a file into a buffer.
45 * Up to buflen-1 characters are read into buffer. If this function returns,
46 * the contents read into the buffer are guaranteed to be nul-terminated.
47 * Note, however, that if the file contains any nul characters itself,
48 * comparing it "as a string" will not work.
50 * \param path The file to be read, which must exist.
51 * \param buffer Buffer into which to store the file contents.
52 * \param buflen Size of the target buffer.
54 * \return The count of bytes read. */
56 read_file(const char *path, void *const buffer, const size_t buflen)
58 const int fd = open(path, O_RDONLY);
59 ATF_REQUIRE_MSG(fd != -1, "Cannot open %s", path);
60 const ssize_t length = read(fd, buffer, buflen - 1);
62 ATF_REQUIRE(length != -1);
63 ((char *)buffer)[length] = '\0';
67 ATF_TC_WITHOUT_HEAD(cat_file__empty);
68 ATF_TC_BODY(cat_file__empty, tc)
70 atf_utils_create_file("file.txt", "%s", "");
71 atf_utils_redirect(STDOUT_FILENO, "captured.txt");
72 atf_utils_cat_file("file.txt", "PREFIX");
77 read_file("captured.txt", buffer, sizeof(buffer));
78 ATF_REQUIRE_STREQ("", buffer);
81 ATF_TC_WITHOUT_HEAD(cat_file__one_line);
82 ATF_TC_BODY(cat_file__one_line, tc)
84 atf_utils_create_file("file.txt", "This is a single line\n");
85 atf_utils_redirect(STDOUT_FILENO, "captured.txt");
86 atf_utils_cat_file("file.txt", "PREFIX");
91 read_file("captured.txt", buffer, sizeof(buffer));
92 ATF_REQUIRE_STREQ("PREFIXThis is a single line\n", buffer);
95 ATF_TC_WITHOUT_HEAD(cat_file__several_lines);
96 ATF_TC_BODY(cat_file__several_lines, tc)
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", ">");
102 close(STDOUT_FILENO);
105 read_file("captured.txt", buffer, sizeof(buffer));
106 ATF_REQUIRE_STREQ(">First\n>Second line\n>And third\n", buffer);
109 ATF_TC_WITHOUT_HEAD(cat_file__no_newline_eof);
110 ATF_TC_BODY(cat_file__no_newline_eof, tc)
112 atf_utils_create_file("file.txt", "Foo\n bar baz");
113 atf_utils_redirect(STDOUT_FILENO, "captured.txt");
114 atf_utils_cat_file("file.txt", "PREFIX");
116 close(STDOUT_FILENO);
119 read_file("captured.txt", buffer, sizeof(buffer));
120 ATF_REQUIRE_STREQ("PREFIXFoo\nPREFIX bar baz", buffer);
123 ATF_TC_WITHOUT_HEAD(compare_file__empty__match);
124 ATF_TC_BODY(compare_file__empty__match, tc)
126 atf_utils_create_file("test.txt", "%s", "");
127 ATF_REQUIRE(atf_utils_compare_file("test.txt", ""));
130 ATF_TC_WITHOUT_HEAD(compare_file__empty__not_match);
131 ATF_TC_BODY(compare_file__empty__not_match, tc)
133 atf_utils_create_file("test.txt", "%s", "");
134 ATF_REQUIRE(!atf_utils_compare_file("test.txt", "\n"));
135 ATF_REQUIRE(!atf_utils_compare_file("test.txt", "foo"));
136 ATF_REQUIRE(!atf_utils_compare_file("test.txt", " "));
139 ATF_TC_WITHOUT_HEAD(compare_file__short__match);
140 ATF_TC_BODY(compare_file__short__match, tc)
142 atf_utils_create_file("test.txt", "this is a short file");
143 ATF_REQUIRE(atf_utils_compare_file("test.txt", "this is a short file"));
146 ATF_TC_WITHOUT_HEAD(compare_file__short__not_match);
147 ATF_TC_BODY(compare_file__short__not_match, tc)
149 atf_utils_create_file("test.txt", "this is a short file");
150 ATF_REQUIRE(!atf_utils_compare_file("test.txt", ""));
151 ATF_REQUIRE(!atf_utils_compare_file("test.txt", "\n"));
152 ATF_REQUIRE(!atf_utils_compare_file("test.txt", "this is a Short file"));
153 ATF_REQUIRE(!atf_utils_compare_file("test.txt", "this is a short fil"));
154 ATF_REQUIRE(!atf_utils_compare_file("test.txt", "this is a short file "));
157 ATF_TC_WITHOUT_HEAD(compare_file__long__match);
158 ATF_TC_BODY(compare_file__long__match, tc)
160 char long_contents[3456];
162 for (; i < sizeof(long_contents) - 1; i++)
163 long_contents[i] = '0' + (i % 10);
164 long_contents[i] = '\0';
165 atf_utils_create_file("test.txt", "%s", long_contents);
167 ATF_REQUIRE(atf_utils_compare_file("test.txt", long_contents));
170 ATF_TC_WITHOUT_HEAD(compare_file__long__not_match);
171 ATF_TC_BODY(compare_file__long__not_match, tc)
173 char long_contents[3456];
175 for (; i < sizeof(long_contents) - 1; i++)
176 long_contents[i] = '0' + (i % 10);
177 long_contents[i] = '\0';
178 atf_utils_create_file("test.txt", "%s", long_contents);
180 ATF_REQUIRE(!atf_utils_compare_file("test.txt", ""));
181 ATF_REQUIRE(!atf_utils_compare_file("test.txt", "\n"));
182 ATF_REQUIRE(!atf_utils_compare_file("test.txt", "0123456789"));
183 long_contents[i - 1] = 'Z';
184 ATF_REQUIRE(!atf_utils_compare_file("test.txt", long_contents));
187 ATF_TC_WITHOUT_HEAD(copy_file__empty);
188 ATF_TC_BODY(copy_file__empty, tc)
190 atf_utils_create_file("src.txt", "%s", "");
191 ATF_REQUIRE(chmod("src.txt", 0520) != -1);
193 atf_utils_copy_file("src.txt", "dest.txt");
194 ATF_REQUIRE(atf_utils_compare_file("dest.txt", ""));
196 ATF_REQUIRE(stat("dest.txt", &sb) != -1);
197 ATF_REQUIRE_EQ(0520, sb.st_mode & 0xfff);
200 ATF_TC_WITHOUT_HEAD(copy_file__some_contents);
201 ATF_TC_BODY(copy_file__some_contents, tc)
203 atf_utils_create_file("src.txt", "This is a\ntest file\n");
204 atf_utils_copy_file("src.txt", "dest.txt");
205 ATF_REQUIRE(atf_utils_compare_file("dest.txt", "This is a\ntest file\n"));
208 ATF_TC_WITHOUT_HEAD(create_file);
209 ATF_TC_BODY(create_file, tc)
211 atf_utils_create_file("test.txt", "This is a test with %d", 12345);
214 read_file("test.txt", buffer, sizeof(buffer));
215 ATF_REQUIRE_STREQ("This is a test with 12345", buffer);
218 ATF_TC_WITHOUT_HEAD(file_exists);
219 ATF_TC_BODY(file_exists, tc)
221 atf_utils_create_file("test.txt", "foo");
223 ATF_REQUIRE( atf_utils_file_exists("test.txt"));
224 ATF_REQUIRE( atf_utils_file_exists("./test.txt"));
225 ATF_REQUIRE(!atf_utils_file_exists("./test.tx"));
226 ATF_REQUIRE(!atf_utils_file_exists("test.txt2"));
229 ATF_TC_WITHOUT_HEAD(fork);
230 ATF_TC_BODY(fork, tc)
232 fprintf(stdout, "Should not get into child\n");
233 fprintf(stderr, "Should not get into child\n");
234 pid_t pid = atf_utils_fork();
236 fprintf(stdout, "Child stdout\n");
237 fprintf(stderr, "Child stderr\n");
242 ATF_REQUIRE(waitpid(pid, &status, 0) != -1);
243 ATF_REQUIRE(WIFEXITED(status));
244 ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
246 atf_dynstr_t out_name;
247 RE(atf_dynstr_init_fmt(&out_name, "atf_utils_fork_%d_out.txt", (int)pid));
248 atf_dynstr_t err_name;
249 RE(atf_dynstr_init_fmt(&err_name, "atf_utils_fork_%d_err.txt", (int)pid));
252 read_file(atf_dynstr_cstring(&out_name), buffer, sizeof(buffer));
253 ATF_REQUIRE_STREQ("Child stdout\n", buffer);
254 read_file(atf_dynstr_cstring(&err_name), buffer, sizeof(buffer));
255 ATF_REQUIRE_STREQ("Child stderr\n", buffer);
257 atf_dynstr_fini(&err_name);
258 atf_dynstr_fini(&out_name);
261 ATF_TC_WITHOUT_HEAD(free_charpp__empty);
262 ATF_TC_BODY(free_charpp__empty, tc)
264 char **array = malloc(sizeof(char *) * 1);
267 atf_utils_free_charpp(array);
270 ATF_TC_WITHOUT_HEAD(free_charpp__some);
271 ATF_TC_BODY(free_charpp__some, tc)
273 char **array = malloc(sizeof(char *) * 4);
274 array[0] = strdup("first");
275 array[1] = strdup("second");
276 array[2] = strdup("third");
279 atf_utils_free_charpp(array);
282 ATF_TC_WITHOUT_HEAD(grep_file);
283 ATF_TC_BODY(grep_file, tc)
285 atf_utils_create_file("test.txt", "line1\nthe second line\naaaabbbb\n");
287 ATF_CHECK(atf_utils_grep_file("line1", "test.txt"));
288 ATF_CHECK(atf_utils_grep_file("line%d", "test.txt", 1));
289 ATF_CHECK(atf_utils_grep_file("second line", "test.txt"));
290 ATF_CHECK(atf_utils_grep_file("aa.*bb", "test.txt"));
291 ATF_CHECK(!atf_utils_grep_file("foo", "test.txt"));
292 ATF_CHECK(!atf_utils_grep_file("bar", "test.txt"));
293 ATF_CHECK(!atf_utils_grep_file("aaaaa", "test.txt"));
296 ATF_TC_WITHOUT_HEAD(grep_string);
297 ATF_TC_BODY(grep_string, tc)
299 const char *str = "a string - aaaabbbb";
300 ATF_CHECK(atf_utils_grep_string("a string", str));
301 ATF_CHECK(atf_utils_grep_string("^a string", str));
302 ATF_CHECK(atf_utils_grep_string("aaaabbbb$", str));
303 ATF_CHECK(atf_utils_grep_string("a%s*bb", str, "a."));
304 ATF_CHECK(!atf_utils_grep_string("foo", str));
305 ATF_CHECK(!atf_utils_grep_string("bar", str));
306 ATF_CHECK(!atf_utils_grep_string("aaaaa", str));
309 ATF_TC_WITHOUT_HEAD(readline__none);
310 ATF_TC_BODY(readline__none, tc)
312 atf_utils_create_file("empty.txt", "%s", "");
314 const int fd = open("empty.txt", O_RDONLY);
315 ATF_REQUIRE(fd != -1);
316 ATF_REQUIRE(atf_utils_readline(fd) == NULL);
320 ATF_TC_WITHOUT_HEAD(readline__some);
321 ATF_TC_BODY(readline__some, tc)
323 const char *l1 = "First line with % formatting % characters %";
324 const char *l2 = "Second line; much longer than the first one";
325 const char *l3 = "Last line, without terminator";
327 atf_utils_create_file("test.txt", "%s\n%s\n%s", l1, l2, l3);
329 const int fd = open("test.txt", O_RDONLY);
330 ATF_REQUIRE(fd != -1);
334 line = atf_utils_readline(fd);
335 ATF_REQUIRE_STREQ(l1, line);
338 line = atf_utils_readline(fd);
339 ATF_REQUIRE_STREQ(l2, line);
342 line = atf_utils_readline(fd);
343 ATF_REQUIRE_STREQ(l3, line);
349 ATF_TC_WITHOUT_HEAD(redirect__stdout);
350 ATF_TC_BODY(redirect__stdout, tc)
352 printf("Buffer this");
353 atf_utils_redirect(STDOUT_FILENO, "captured.txt");
354 printf("The printed message");
358 read_file("captured.txt", buffer, sizeof(buffer));
359 ATF_REQUIRE_STREQ("The printed message", buffer);
362 ATF_TC_WITHOUT_HEAD(redirect__stderr);
363 ATF_TC_BODY(redirect__stderr, tc)
365 fprintf(stderr, "Buffer this");
366 atf_utils_redirect(STDERR_FILENO, "captured.txt");
367 fprintf(stderr, "The printed message");
371 read_file("captured.txt", buffer, sizeof(buffer));
372 ATF_REQUIRE_STREQ("The printed message", buffer);
375 ATF_TC_WITHOUT_HEAD(redirect__other);
376 ATF_TC_BODY(redirect__other, tc)
378 const char *message = "Foo bar\nbaz\n";
379 atf_utils_redirect(15, "captured.txt");
380 ATF_REQUIRE(write(15, message, strlen(message)) != -1);
384 read_file("captured.txt", buffer, sizeof(buffer));
385 ATF_REQUIRE_STREQ(message, buffer);
389 fork_and_wait(const int exitstatus, const char* expout, const char* experr)
391 const pid_t pid = atf_utils_fork();
392 ATF_REQUIRE(pid != -1);
394 fprintf(stdout, "Some output\n");
395 fprintf(stderr, "Some error\n");
398 atf_utils_wait(pid, exitstatus, expout, experr);
402 ATF_TC_WITHOUT_HEAD(wait__ok);
403 ATF_TC_BODY(wait__ok, tc)
405 const pid_t control = fork();
406 ATF_REQUIRE(control != -1);
408 fork_and_wait(123, "Some output\n", "Some error\n");
411 ATF_REQUIRE(waitpid(control, &status, 0) != -1);
412 ATF_REQUIRE(WIFEXITED(status));
413 ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
417 ATF_TC_WITHOUT_HEAD(wait__ok_nested);
418 ATF_TC_BODY(wait__ok_nested, tc)
420 const pid_t parent = atf_utils_fork();
421 ATF_REQUIRE(parent != -1);
423 const pid_t child = atf_utils_fork();
424 ATF_REQUIRE(child != -1);
427 fprintf(stdout, "Child output\n");
429 fprintf(stderr, "Child error\n");
432 fprintf(stdout, "Parent output\n");
433 fprintf(stderr, "Parent error\n");
434 atf_utils_wait(child, 50, "Child output\n", "Child error\n");
438 atf_utils_wait(parent, 40,
440 "subprocess stdout: Child output\n"
441 "subprocess stderr: Child error\n",
446 ATF_TC_WITHOUT_HEAD(wait__invalid_exitstatus);
447 ATF_TC_BODY(wait__invalid_exitstatus, tc)
449 const pid_t control = fork();
450 ATF_REQUIRE(control != -1);
452 fork_and_wait(120, "Some output\n", "Some error\n");
455 ATF_REQUIRE(waitpid(control, &status, 0) != -1);
456 ATF_REQUIRE(WIFEXITED(status));
457 ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status));
461 ATF_TC_WITHOUT_HEAD(wait__invalid_stdout);
462 ATF_TC_BODY(wait__invalid_stdout, tc)
464 const pid_t control = fork();
465 ATF_REQUIRE(control != -1);
467 fork_and_wait(123, "Some output foo\n", "Some error\n");
470 ATF_REQUIRE(waitpid(control, &status, 0) != -1);
471 ATF_REQUIRE(WIFEXITED(status));
472 ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status));
476 ATF_TC_WITHOUT_HEAD(wait__invalid_stderr);
477 ATF_TC_BODY(wait__invalid_stderr, tc)
479 const pid_t control = fork();
480 ATF_REQUIRE(control != -1);
482 fork_and_wait(123, "Some output\n", "Some error foo\n");
485 ATF_REQUIRE(waitpid(control, &status, 0) != -1);
486 ATF_REQUIRE(WIFEXITED(status));
487 ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status));
491 ATF_TC_WITHOUT_HEAD(wait__save_stdout);
492 ATF_TC_BODY(wait__save_stdout, tc)
494 const pid_t control = fork();
495 ATF_REQUIRE(control != -1);
497 fork_and_wait(123, "save:my-output.txt", "Some error\n");
500 ATF_REQUIRE(waitpid(control, &status, 0) != -1);
501 ATF_REQUIRE(WIFEXITED(status));
502 ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
504 ATF_REQUIRE(atf_utils_compare_file("my-output.txt", "Some output\n"));
508 ATF_TC_WITHOUT_HEAD(wait__save_stderr);
509 ATF_TC_BODY(wait__save_stderr, tc)
511 const pid_t control = fork();
512 ATF_REQUIRE(control != -1);
514 fork_and_wait(123, "Some output\n", "save:my-output.txt");
517 ATF_REQUIRE(waitpid(control, &status, 0) != -1);
518 ATF_REQUIRE(WIFEXITED(status));
519 ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
521 ATF_REQUIRE(atf_utils_compare_file("my-output.txt", "Some error\n"));
527 ATF_TP_ADD_TC(tp, cat_file__empty);
528 ATF_TP_ADD_TC(tp, cat_file__one_line);
529 ATF_TP_ADD_TC(tp, cat_file__several_lines);
530 ATF_TP_ADD_TC(tp, cat_file__no_newline_eof);
532 ATF_TP_ADD_TC(tp, compare_file__empty__match);
533 ATF_TP_ADD_TC(tp, compare_file__empty__not_match);
534 ATF_TP_ADD_TC(tp, compare_file__short__match);
535 ATF_TP_ADD_TC(tp, compare_file__short__not_match);
536 ATF_TP_ADD_TC(tp, compare_file__long__match);
537 ATF_TP_ADD_TC(tp, compare_file__long__not_match);
539 ATF_TP_ADD_TC(tp, copy_file__empty);
540 ATF_TP_ADD_TC(tp, copy_file__some_contents);
542 ATF_TP_ADD_TC(tp, create_file);
544 ATF_TP_ADD_TC(tp, file_exists);
546 ATF_TP_ADD_TC(tp, fork);
548 ATF_TP_ADD_TC(tp, free_charpp__empty);
549 ATF_TP_ADD_TC(tp, free_charpp__some);
551 ATF_TP_ADD_TC(tp, grep_file);
552 ATF_TP_ADD_TC(tp, grep_string);
554 ATF_TP_ADD_TC(tp, readline__none);
555 ATF_TP_ADD_TC(tp, readline__some);
557 ATF_TP_ADD_TC(tp, redirect__stdout);
558 ATF_TP_ADD_TC(tp, redirect__stderr);
559 ATF_TP_ADD_TC(tp, redirect__other);
561 ATF_TP_ADD_TC(tp, wait__ok);
562 ATF_TP_ADD_TC(tp, wait__ok_nested);
563 ATF_TP_ADD_TC(tp, wait__save_stdout);
564 ATF_TP_ADD_TC(tp, wait__save_stderr);
565 ATF_TP_ADD_TC(tp, wait__invalid_exitstatus);
566 ATF_TP_ADD_TC(tp, wait__invalid_stdout);
567 ATF_TP_ADD_TC(tp, wait__invalid_stderr);
569 return atf_no_error();