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