xref: /freebsd/contrib/atf/atf-c++/utils_test.cpp (revision 0677dfd1c4dadb62482e2c72fa4c6720902128a4)
1c243e490SMarcel Moolenaar // Copyright (c) 2007 The NetBSD Foundation, Inc.
2c243e490SMarcel Moolenaar // All rights reserved.
3c243e490SMarcel Moolenaar //
4c243e490SMarcel Moolenaar // Redistribution and use in source and binary forms, with or without
5c243e490SMarcel Moolenaar // modification, are permitted provided that the following conditions
6c243e490SMarcel Moolenaar // are met:
7c243e490SMarcel Moolenaar // 1. Redistributions of source code must retain the above copyright
8c243e490SMarcel Moolenaar //    notice, this list of conditions and the following disclaimer.
9c243e490SMarcel Moolenaar // 2. Redistributions in binary form must reproduce the above copyright
10c243e490SMarcel Moolenaar //    notice, this list of conditions and the following disclaimer in the
11c243e490SMarcel Moolenaar //    documentation and/or other materials provided with the distribution.
12c243e490SMarcel Moolenaar //
13c243e490SMarcel Moolenaar // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
14c243e490SMarcel Moolenaar // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
15c243e490SMarcel Moolenaar // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16c243e490SMarcel Moolenaar // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17c243e490SMarcel Moolenaar // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
18c243e490SMarcel Moolenaar // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19c243e490SMarcel Moolenaar // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
20c243e490SMarcel Moolenaar // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21c243e490SMarcel Moolenaar // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22c243e490SMarcel Moolenaar // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23c243e490SMarcel Moolenaar // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24c243e490SMarcel Moolenaar // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*0677dfd1SJulio Merino 
26*0677dfd1SJulio Merino #include "atf-c++/utils.hpp"
27c243e490SMarcel Moolenaar 
28a18eacbeSJulio Merino extern "C" {
29a18eacbeSJulio Merino #include <sys/stat.h>
30a18eacbeSJulio Merino #include <sys/wait.h>
31c243e490SMarcel Moolenaar 
32a18eacbeSJulio Merino #include <fcntl.h>
33a18eacbeSJulio Merino #include <unistd.h>
34a18eacbeSJulio Merino }
35a18eacbeSJulio Merino 
36a18eacbeSJulio Merino #include <cstdlib>
37a18eacbeSJulio Merino #include <iostream>
38a18eacbeSJulio Merino #include <set>
39*0677dfd1SJulio Merino #include <sstream>
40a18eacbeSJulio Merino #include <string>
41a18eacbeSJulio Merino #include <vector>
42c243e490SMarcel Moolenaar 
43*0677dfd1SJulio Merino #include <atf-c++.hpp>
44c243e490SMarcel Moolenaar 
45a18eacbeSJulio Merino static std::string
46*0677dfd1SJulio Merino read_file(const std::string& path)
47a18eacbeSJulio Merino {
48a18eacbeSJulio Merino     char buffer[1024];
49a18eacbeSJulio Merino 
50*0677dfd1SJulio Merino     const int fd = open(path.c_str(), O_RDONLY);
51a18eacbeSJulio Merino     if (fd == -1)
52*0677dfd1SJulio Merino         ATF_FAIL("Cannot open " + path);
53a18eacbeSJulio Merino     const ssize_t length = read(fd, buffer, sizeof(buffer) - 1);
54a18eacbeSJulio Merino     close(fd);
55a18eacbeSJulio Merino     ATF_REQUIRE(length != -1);
56a18eacbeSJulio Merino     if (length == sizeof(buffer) - 1)
57a18eacbeSJulio Merino         ATF_FAIL("Internal buffer not long enough to read temporary file");
58a18eacbeSJulio Merino     ((char *)buffer)[length] = '\0';
59a18eacbeSJulio Merino 
60a18eacbeSJulio Merino     return buffer;
61a18eacbeSJulio Merino }
62a18eacbeSJulio Merino 
63c243e490SMarcel Moolenaar // ------------------------------------------------------------------------
64a18eacbeSJulio Merino // Tests cases for the free functions.
65c243e490SMarcel Moolenaar // ------------------------------------------------------------------------
66c243e490SMarcel Moolenaar 
67a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(cat_file__empty);
68a18eacbeSJulio Merino ATF_TEST_CASE_BODY(cat_file__empty)
69c243e490SMarcel Moolenaar {
70a18eacbeSJulio Merino     atf::utils::create_file("file.txt", "");
71a18eacbeSJulio Merino     atf::utils::redirect(STDOUT_FILENO, "captured.txt");
72a18eacbeSJulio Merino     atf::utils::cat_file("file.txt", "PREFIX");
73a18eacbeSJulio Merino     std::cout.flush();
74a18eacbeSJulio Merino     close(STDOUT_FILENO);
75a18eacbeSJulio Merino 
76a18eacbeSJulio Merino     ATF_REQUIRE_EQ("", read_file("captured.txt"));
77c243e490SMarcel Moolenaar }
78c243e490SMarcel Moolenaar 
79a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(cat_file__one_line);
80a18eacbeSJulio Merino ATF_TEST_CASE_BODY(cat_file__one_line)
81c243e490SMarcel Moolenaar {
82a18eacbeSJulio Merino     atf::utils::create_file("file.txt", "This is a single line\n");
83a18eacbeSJulio Merino     atf::utils::redirect(STDOUT_FILENO, "captured.txt");
84a18eacbeSJulio Merino     atf::utils::cat_file("file.txt", "PREFIX");
85a18eacbeSJulio Merino     std::cout.flush();
86a18eacbeSJulio Merino     close(STDOUT_FILENO);
87a18eacbeSJulio Merino 
88a18eacbeSJulio Merino     ATF_REQUIRE_EQ("PREFIXThis is a single line\n", read_file("captured.txt"));
89c243e490SMarcel Moolenaar }
90c243e490SMarcel Moolenaar 
91a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(cat_file__several_lines);
92a18eacbeSJulio Merino ATF_TEST_CASE_BODY(cat_file__several_lines)
93c243e490SMarcel Moolenaar {
94a18eacbeSJulio Merino     atf::utils::create_file("file.txt", "First\nSecond line\nAnd third\n");
95a18eacbeSJulio Merino     atf::utils::redirect(STDOUT_FILENO, "captured.txt");
96a18eacbeSJulio Merino     atf::utils::cat_file("file.txt", ">");
97a18eacbeSJulio Merino     std::cout.flush();
98a18eacbeSJulio Merino     close(STDOUT_FILENO);
99a18eacbeSJulio Merino 
100a18eacbeSJulio Merino     ATF_REQUIRE_EQ(">First\n>Second line\n>And third\n",
101a18eacbeSJulio Merino                    read_file("captured.txt"));
102c243e490SMarcel Moolenaar }
103c243e490SMarcel Moolenaar 
104a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(cat_file__no_newline_eof);
105a18eacbeSJulio Merino ATF_TEST_CASE_BODY(cat_file__no_newline_eof)
106c243e490SMarcel Moolenaar {
107a18eacbeSJulio Merino     atf::utils::create_file("file.txt", "Foo\n bar baz");
108a18eacbeSJulio Merino     atf::utils::redirect(STDOUT_FILENO, "captured.txt");
109a18eacbeSJulio Merino     atf::utils::cat_file("file.txt", "PREFIX");
110a18eacbeSJulio Merino     std::cout.flush();
111a18eacbeSJulio Merino     close(STDOUT_FILENO);
112a18eacbeSJulio Merino 
113a18eacbeSJulio Merino     ATF_REQUIRE_EQ("PREFIXFoo\nPREFIX bar baz", read_file("captured.txt"));
114c243e490SMarcel Moolenaar }
115c243e490SMarcel Moolenaar 
116a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(compare_file__empty__match);
117a18eacbeSJulio Merino ATF_TEST_CASE_BODY(compare_file__empty__match)
118c243e490SMarcel Moolenaar {
119a18eacbeSJulio Merino     atf::utils::create_file("test.txt", "");
120a18eacbeSJulio Merino     ATF_REQUIRE(atf::utils::compare_file("test.txt", ""));
121c243e490SMarcel Moolenaar }
122c243e490SMarcel Moolenaar 
123a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(compare_file__empty__not_match);
124a18eacbeSJulio Merino ATF_TEST_CASE_BODY(compare_file__empty__not_match)
125c243e490SMarcel Moolenaar {
126a18eacbeSJulio Merino     atf::utils::create_file("test.txt", "");
127a18eacbeSJulio Merino     ATF_REQUIRE(!atf::utils::compare_file("test.txt", "\n"));
128a18eacbeSJulio Merino     ATF_REQUIRE(!atf::utils::compare_file("test.txt", "foo"));
129a18eacbeSJulio Merino     ATF_REQUIRE(!atf::utils::compare_file("test.txt", " "));
130c243e490SMarcel Moolenaar }
131c243e490SMarcel Moolenaar 
132a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(compare_file__short__match);
133a18eacbeSJulio Merino ATF_TEST_CASE_BODY(compare_file__short__match)
134c243e490SMarcel Moolenaar {
135a18eacbeSJulio Merino     atf::utils::create_file("test.txt", "this is a short file");
136a18eacbeSJulio Merino     ATF_REQUIRE(atf::utils::compare_file("test.txt", "this is a short file"));
137c243e490SMarcel Moolenaar }
138c243e490SMarcel Moolenaar 
139a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(compare_file__short__not_match);
140a18eacbeSJulio Merino ATF_TEST_CASE_BODY(compare_file__short__not_match)
141c243e490SMarcel Moolenaar {
142a18eacbeSJulio Merino     atf::utils::create_file("test.txt", "this is a short file");
143a18eacbeSJulio Merino     ATF_REQUIRE(!atf::utils::compare_file("test.txt", ""));
144a18eacbeSJulio Merino     ATF_REQUIRE(!atf::utils::compare_file("test.txt", "\n"));
145a18eacbeSJulio Merino     ATF_REQUIRE(!atf::utils::compare_file("test.txt", "this is a Short file"));
146a18eacbeSJulio Merino     ATF_REQUIRE(!atf::utils::compare_file("test.txt", "this is a short fil"));
147a18eacbeSJulio Merino     ATF_REQUIRE(!atf::utils::compare_file("test.txt", "this is a short file "));
148c243e490SMarcel Moolenaar }
149c243e490SMarcel Moolenaar 
150a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(compare_file__long__match);
151a18eacbeSJulio Merino ATF_TEST_CASE_BODY(compare_file__long__match)
152c243e490SMarcel Moolenaar {
153a18eacbeSJulio Merino     char long_contents[3456];
154a18eacbeSJulio Merino     size_t i = 0;
155a18eacbeSJulio Merino     for (; i < sizeof(long_contents) - 1; i++)
156a18eacbeSJulio Merino         long_contents[i] = '0' + (i % 10);
157a18eacbeSJulio Merino     long_contents[i] = '\0';
158a18eacbeSJulio Merino     atf::utils::create_file("test.txt", long_contents);
159c243e490SMarcel Moolenaar 
160a18eacbeSJulio Merino     ATF_REQUIRE(atf::utils::compare_file("test.txt", long_contents));
161c243e490SMarcel Moolenaar }
162c243e490SMarcel Moolenaar 
163a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(compare_file__long__not_match);
164a18eacbeSJulio Merino ATF_TEST_CASE_BODY(compare_file__long__not_match)
165c243e490SMarcel Moolenaar {
166a18eacbeSJulio Merino     char long_contents[3456];
167a18eacbeSJulio Merino     size_t i = 0;
168a18eacbeSJulio Merino     for (; i < sizeof(long_contents) - 1; i++)
169a18eacbeSJulio Merino         long_contents[i] = '0' + (i % 10);
170a18eacbeSJulio Merino     long_contents[i] = '\0';
171a18eacbeSJulio Merino     atf::utils::create_file("test.txt", long_contents);
172c243e490SMarcel Moolenaar 
173a18eacbeSJulio Merino     ATF_REQUIRE(!atf::utils::compare_file("test.txt", ""));
174a18eacbeSJulio Merino     ATF_REQUIRE(!atf::utils::compare_file("test.txt", "\n"));
175a18eacbeSJulio Merino     ATF_REQUIRE(!atf::utils::compare_file("test.txt", "0123456789"));
176a18eacbeSJulio Merino     long_contents[i - 1] = 'Z';
177a18eacbeSJulio Merino     ATF_REQUIRE(!atf::utils::compare_file("test.txt", long_contents));
178c243e490SMarcel Moolenaar }
179c243e490SMarcel Moolenaar 
180a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(copy_file__empty);
181a18eacbeSJulio Merino ATF_TEST_CASE_BODY(copy_file__empty)
182c243e490SMarcel Moolenaar {
183a18eacbeSJulio Merino     atf::utils::create_file("src.txt", "");
184a18eacbeSJulio Merino     ATF_REQUIRE(chmod("src.txt", 0520) != -1);
185c243e490SMarcel Moolenaar 
186a18eacbeSJulio Merino     atf::utils::copy_file("src.txt", "dest.txt");
187a18eacbeSJulio Merino     ATF_REQUIRE(atf::utils::compare_file("dest.txt", ""));
188a18eacbeSJulio Merino     struct stat sb;
189a18eacbeSJulio Merino     ATF_REQUIRE(stat("dest.txt", &sb) != -1);
190a18eacbeSJulio Merino     ATF_REQUIRE_EQ(0520, sb.st_mode & 0xfff);
191c243e490SMarcel Moolenaar }
192c243e490SMarcel Moolenaar 
193a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(copy_file__some_contents);
194a18eacbeSJulio Merino ATF_TEST_CASE_BODY(copy_file__some_contents)
195c243e490SMarcel Moolenaar {
196a18eacbeSJulio Merino     atf::utils::create_file("src.txt", "This is a\ntest file\n");
197a18eacbeSJulio Merino     atf::utils::copy_file("src.txt", "dest.txt");
198a18eacbeSJulio Merino     ATF_REQUIRE(atf::utils::compare_file("dest.txt", "This is a\ntest file\n"));
199c243e490SMarcel Moolenaar }
200c243e490SMarcel Moolenaar 
201a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(create_file);
202a18eacbeSJulio Merino ATF_TEST_CASE_BODY(create_file)
203c243e490SMarcel Moolenaar {
204a18eacbeSJulio Merino     atf::utils::create_file("test.txt", "This is a %d test");
205a18eacbeSJulio Merino 
206a18eacbeSJulio Merino     ATF_REQUIRE_EQ("This is a %d test", read_file("test.txt"));
207c243e490SMarcel Moolenaar }
208a18eacbeSJulio Merino 
209a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(file_exists);
210a18eacbeSJulio Merino ATF_TEST_CASE_BODY(file_exists)
211c243e490SMarcel Moolenaar {
212a18eacbeSJulio Merino     atf::utils::create_file("test.txt", "foo");
213c243e490SMarcel Moolenaar 
214a18eacbeSJulio Merino     ATF_REQUIRE( atf::utils::file_exists("test.txt"));
215a18eacbeSJulio Merino     ATF_REQUIRE( atf::utils::file_exists("./test.txt"));
216a18eacbeSJulio Merino     ATF_REQUIRE(!atf::utils::file_exists("./test.tx"));
217a18eacbeSJulio Merino     ATF_REQUIRE(!atf::utils::file_exists("test.txt2"));
218a18eacbeSJulio Merino }
219c243e490SMarcel Moolenaar 
220a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(fork);
221a18eacbeSJulio Merino ATF_TEST_CASE_BODY(fork)
222a18eacbeSJulio Merino {
223a18eacbeSJulio Merino     std::cout << "Should not get into child\n";
224a18eacbeSJulio Merino     std::cerr << "Should not get into child\n";
225a18eacbeSJulio Merino     pid_t pid = atf::utils::fork();
226a18eacbeSJulio Merino     if (pid == 0) {
227a18eacbeSJulio Merino         std::cout << "Child stdout\n";
228a18eacbeSJulio Merino         std::cerr << "Child stderr\n";
229a18eacbeSJulio Merino         exit(EXIT_SUCCESS);
230a18eacbeSJulio Merino     }
231c243e490SMarcel Moolenaar 
232a18eacbeSJulio Merino     int status;
233a18eacbeSJulio Merino     ATF_REQUIRE(waitpid(pid, &status, 0) != -1);
234a18eacbeSJulio Merino     ATF_REQUIRE(WIFEXITED(status));
235a18eacbeSJulio Merino     ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
236a18eacbeSJulio Merino 
237*0677dfd1SJulio Merino     std::ostringstream out_name;
238*0677dfd1SJulio Merino     out_name << "atf_utils_fork_" << pid << "_out.txt";
239*0677dfd1SJulio Merino     std::ostringstream err_name;
240*0677dfd1SJulio Merino     err_name << "atf_utils_fork_" << pid << "_err.txt";
241*0677dfd1SJulio Merino 
242*0677dfd1SJulio Merino     ATF_REQUIRE_EQ("Child stdout\n", read_file(out_name.str()));
243*0677dfd1SJulio Merino     ATF_REQUIRE_EQ("Child stderr\n", read_file(err_name.str()));
244a18eacbeSJulio Merino }
245a18eacbeSJulio Merino 
246a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(grep_collection__set);
247a18eacbeSJulio Merino ATF_TEST_CASE_BODY(grep_collection__set)
248a18eacbeSJulio Merino {
249a18eacbeSJulio Merino     std::set< std::string > strings;
250a18eacbeSJulio Merino     strings.insert("First");
251a18eacbeSJulio Merino     strings.insert("Second");
252a18eacbeSJulio Merino 
253a18eacbeSJulio Merino     ATF_REQUIRE( atf::utils::grep_collection("irs", strings));
254a18eacbeSJulio Merino     ATF_REQUIRE( atf::utils::grep_collection("cond", strings));
255a18eacbeSJulio Merino     ATF_REQUIRE(!atf::utils::grep_collection("Third", strings));
256a18eacbeSJulio Merino }
257a18eacbeSJulio Merino 
258a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(grep_collection__vector);
259a18eacbeSJulio Merino ATF_TEST_CASE_BODY(grep_collection__vector)
260a18eacbeSJulio Merino {
261a18eacbeSJulio Merino     std::vector< std::string > strings;
262a18eacbeSJulio Merino     strings.push_back("First");
263a18eacbeSJulio Merino     strings.push_back("Second");
264a18eacbeSJulio Merino 
265a18eacbeSJulio Merino     ATF_REQUIRE( atf::utils::grep_collection("irs", strings));
266a18eacbeSJulio Merino     ATF_REQUIRE( atf::utils::grep_collection("cond", strings));
267a18eacbeSJulio Merino     ATF_REQUIRE(!atf::utils::grep_collection("Third", strings));
268a18eacbeSJulio Merino }
269a18eacbeSJulio Merino 
270a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(grep_file);
271a18eacbeSJulio Merino ATF_TEST_CASE_BODY(grep_file)
272a18eacbeSJulio Merino {
273a18eacbeSJulio Merino     atf::utils::create_file("test.txt", "line1\nthe second line\naaaabbbb\n");
274a18eacbeSJulio Merino 
275a18eacbeSJulio Merino     ATF_REQUIRE(atf::utils::grep_file("line1", "test.txt"));
276a18eacbeSJulio Merino     ATF_REQUIRE(atf::utils::grep_file("second line", "test.txt"));
277a18eacbeSJulio Merino     ATF_REQUIRE(atf::utils::grep_file("aa.*bb", "test.txt"));
278a18eacbeSJulio Merino     ATF_REQUIRE(!atf::utils::grep_file("foo", "test.txt"));
279a18eacbeSJulio Merino     ATF_REQUIRE(!atf::utils::grep_file("bar", "test.txt"));
280a18eacbeSJulio Merino     ATF_REQUIRE(!atf::utils::grep_file("aaaaa", "test.txt"));
281a18eacbeSJulio Merino }
282a18eacbeSJulio Merino 
283a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(grep_string);
284a18eacbeSJulio Merino ATF_TEST_CASE_BODY(grep_string)
285a18eacbeSJulio Merino {
286a18eacbeSJulio Merino     const char *str = "a string - aaaabbbb";
287a18eacbeSJulio Merino     ATF_REQUIRE(atf::utils::grep_string("a string", str));
288a18eacbeSJulio Merino     ATF_REQUIRE(atf::utils::grep_string("^a string", str));
289a18eacbeSJulio Merino     ATF_REQUIRE(atf::utils::grep_string("aaaabbbb$", str));
290a18eacbeSJulio Merino     ATF_REQUIRE(atf::utils::grep_string("aa.*bb", str));
291a18eacbeSJulio Merino     ATF_REQUIRE(!atf::utils::grep_string("foo", str));
292a18eacbeSJulio Merino     ATF_REQUIRE(!atf::utils::grep_string("bar", str));
293a18eacbeSJulio Merino     ATF_REQUIRE(!atf::utils::grep_string("aaaaa", str));
294a18eacbeSJulio Merino }
295a18eacbeSJulio Merino 
296a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(redirect__stdout);
297a18eacbeSJulio Merino ATF_TEST_CASE_BODY(redirect__stdout)
298a18eacbeSJulio Merino {
299a18eacbeSJulio Merino     std::cout << "Buffer this";
300a18eacbeSJulio Merino     atf::utils::redirect(STDOUT_FILENO, "captured.txt");
301a18eacbeSJulio Merino     std::cout << "The printed message";
302a18eacbeSJulio Merino     std::cout.flush();
303a18eacbeSJulio Merino 
304a18eacbeSJulio Merino     ATF_REQUIRE_EQ("The printed message", read_file("captured.txt"));
305a18eacbeSJulio Merino }
306a18eacbeSJulio Merino 
307a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(redirect__stderr);
308a18eacbeSJulio Merino ATF_TEST_CASE_BODY(redirect__stderr)
309a18eacbeSJulio Merino {
310a18eacbeSJulio Merino     std::cerr << "Buffer this";
311a18eacbeSJulio Merino     atf::utils::redirect(STDERR_FILENO, "captured.txt");
312a18eacbeSJulio Merino     std::cerr << "The printed message";
313a18eacbeSJulio Merino     std::cerr.flush();
314a18eacbeSJulio Merino 
315a18eacbeSJulio Merino     ATF_REQUIRE_EQ("The printed message", read_file("captured.txt"));
316a18eacbeSJulio Merino }
317a18eacbeSJulio Merino 
318a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(redirect__other);
319a18eacbeSJulio Merino ATF_TEST_CASE_BODY(redirect__other)
320a18eacbeSJulio Merino {
321a18eacbeSJulio Merino     const std::string message = "Foo bar\nbaz\n";
322a18eacbeSJulio Merino     atf::utils::redirect(15, "captured.txt");
323a18eacbeSJulio Merino     ATF_REQUIRE(write(15, message.c_str(), message.length()) != -1);
324a18eacbeSJulio Merino     close(15);
325a18eacbeSJulio Merino 
326a18eacbeSJulio Merino     ATF_REQUIRE_EQ(message, read_file("captured.txt"));
327a18eacbeSJulio Merino }
328a18eacbeSJulio Merino 
329a18eacbeSJulio Merino static void
330a18eacbeSJulio Merino fork_and_wait(const int exitstatus, const char* expout, const char* experr)
331a18eacbeSJulio Merino {
332a18eacbeSJulio Merino     const pid_t pid = atf::utils::fork();
333a18eacbeSJulio Merino     if (pid == 0) {
334a18eacbeSJulio Merino         std::cout << "Some output\n";
335a18eacbeSJulio Merino         std::cerr << "Some error\n";
336a18eacbeSJulio Merino         exit(123);
337a18eacbeSJulio Merino     }
338a18eacbeSJulio Merino     atf::utils::wait(pid, exitstatus, expout, experr);
339a18eacbeSJulio Merino     exit(EXIT_SUCCESS);
340a18eacbeSJulio Merino }
341a18eacbeSJulio Merino 
342a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(wait__ok);
343a18eacbeSJulio Merino ATF_TEST_CASE_BODY(wait__ok)
344a18eacbeSJulio Merino {
345a18eacbeSJulio Merino     const pid_t control = fork();
346a18eacbeSJulio Merino     ATF_REQUIRE(control != -1);
347a18eacbeSJulio Merino     if (control == 0)
348a18eacbeSJulio Merino         fork_and_wait(123, "Some output\n", "Some error\n");
349a18eacbeSJulio Merino     else {
350a18eacbeSJulio Merino         int status;
351a18eacbeSJulio Merino         ATF_REQUIRE(waitpid(control, &status, 0) != -1);
352a18eacbeSJulio Merino         ATF_REQUIRE(WIFEXITED(status));
353a18eacbeSJulio Merino         ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
354a18eacbeSJulio Merino     }
355a18eacbeSJulio Merino }
356a18eacbeSJulio Merino 
357*0677dfd1SJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(wait__ok_nested);
358*0677dfd1SJulio Merino ATF_TEST_CASE_BODY(wait__ok_nested)
359*0677dfd1SJulio Merino {
360*0677dfd1SJulio Merino     const pid_t parent = atf::utils::fork();
361*0677dfd1SJulio Merino     ATF_REQUIRE(parent != -1);
362*0677dfd1SJulio Merino     if (parent == 0) {
363*0677dfd1SJulio Merino         const pid_t child = atf::utils::fork();
364*0677dfd1SJulio Merino         ATF_REQUIRE(child != -1);
365*0677dfd1SJulio Merino         if (child == 0) {
366*0677dfd1SJulio Merino             std::cerr.flush();
367*0677dfd1SJulio Merino             std::cout << "Child output\n";
368*0677dfd1SJulio Merino             std::cout.flush();
369*0677dfd1SJulio Merino             std::cerr << "Child error\n";
370*0677dfd1SJulio Merino             std::exit(50);
371*0677dfd1SJulio Merino         } else {
372*0677dfd1SJulio Merino             std::cout << "Parent output\n";
373*0677dfd1SJulio Merino             std::cerr << "Parent error\n";
374*0677dfd1SJulio Merino             atf::utils::wait(child, 50, "Child output\n", "Child error\n");
375*0677dfd1SJulio Merino             std::exit(40);
376*0677dfd1SJulio Merino         }
377*0677dfd1SJulio Merino     } else {
378*0677dfd1SJulio Merino         atf::utils::wait(parent, 40,
379*0677dfd1SJulio Merino                          "Parent output\n"
380*0677dfd1SJulio Merino                          "subprocess stdout: Child output\n"
381*0677dfd1SJulio Merino                          "subprocess stderr: Child error\n",
382*0677dfd1SJulio Merino                          "Parent error\n");
383*0677dfd1SJulio Merino     }
384*0677dfd1SJulio Merino }
385*0677dfd1SJulio Merino 
386a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(wait__invalid_exitstatus);
387a18eacbeSJulio Merino ATF_TEST_CASE_BODY(wait__invalid_exitstatus)
388a18eacbeSJulio Merino {
389a18eacbeSJulio Merino     const pid_t control = fork();
390a18eacbeSJulio Merino     ATF_REQUIRE(control != -1);
391a18eacbeSJulio Merino     if (control == 0)
392a18eacbeSJulio Merino         fork_and_wait(120, "Some output\n", "Some error\n");
393a18eacbeSJulio Merino     else {
394a18eacbeSJulio Merino         int status;
395a18eacbeSJulio Merino         ATF_REQUIRE(waitpid(control, &status, 0) != -1);
396a18eacbeSJulio Merino         ATF_REQUIRE(WIFEXITED(status));
397a18eacbeSJulio Merino         ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status));
398a18eacbeSJulio Merino     }
399a18eacbeSJulio Merino }
400a18eacbeSJulio Merino 
401a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(wait__invalid_stdout);
402a18eacbeSJulio Merino ATF_TEST_CASE_BODY(wait__invalid_stdout)
403a18eacbeSJulio Merino {
404a18eacbeSJulio Merino     const pid_t control = fork();
405a18eacbeSJulio Merino     ATF_REQUIRE(control != -1);
406a18eacbeSJulio Merino     if (control == 0)
407a18eacbeSJulio Merino         fork_and_wait(123, "Some output foo\n", "Some error\n");
408a18eacbeSJulio Merino     else {
409a18eacbeSJulio Merino         int status;
410a18eacbeSJulio Merino         ATF_REQUIRE(waitpid(control, &status, 0) != -1);
411a18eacbeSJulio Merino         ATF_REQUIRE(WIFEXITED(status));
412a18eacbeSJulio Merino         ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status));
413a18eacbeSJulio Merino     }
414a18eacbeSJulio Merino }
415a18eacbeSJulio Merino 
416a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(wait__invalid_stderr);
417a18eacbeSJulio Merino ATF_TEST_CASE_BODY(wait__invalid_stderr)
418a18eacbeSJulio Merino {
419a18eacbeSJulio Merino     const pid_t control = fork();
420a18eacbeSJulio Merino     ATF_REQUIRE(control != -1);
421a18eacbeSJulio Merino     if (control == 0)
422a18eacbeSJulio Merino         fork_and_wait(123, "Some output\n", "Some error foo\n");
423a18eacbeSJulio Merino     else {
424a18eacbeSJulio Merino         int status;
425a18eacbeSJulio Merino         ATF_REQUIRE(waitpid(control, &status, 0) != -1);
426a18eacbeSJulio Merino         ATF_REQUIRE(WIFEXITED(status));
427a18eacbeSJulio Merino         ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status));
428a18eacbeSJulio Merino     }
429a18eacbeSJulio Merino }
430a18eacbeSJulio Merino 
431a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(wait__save_stdout);
432a18eacbeSJulio Merino ATF_TEST_CASE_BODY(wait__save_stdout)
433a18eacbeSJulio Merino {
434a18eacbeSJulio Merino     const pid_t control = fork();
435a18eacbeSJulio Merino     ATF_REQUIRE(control != -1);
436a18eacbeSJulio Merino     if (control == 0)
437a18eacbeSJulio Merino         fork_and_wait(123, "save:my-output.txt", "Some error\n");
438a18eacbeSJulio Merino     else {
439a18eacbeSJulio Merino         int status;
440a18eacbeSJulio Merino         ATF_REQUIRE(waitpid(control, &status, 0) != -1);
441a18eacbeSJulio Merino         ATF_REQUIRE(WIFEXITED(status));
442a18eacbeSJulio Merino         ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
443a18eacbeSJulio Merino 
444a18eacbeSJulio Merino         ATF_REQUIRE(atf::utils::compare_file("my-output.txt", "Some output\n"));
445a18eacbeSJulio Merino     }
446a18eacbeSJulio Merino }
447a18eacbeSJulio Merino 
448a18eacbeSJulio Merino ATF_TEST_CASE_WITHOUT_HEAD(wait__save_stderr);
449a18eacbeSJulio Merino ATF_TEST_CASE_BODY(wait__save_stderr)
450a18eacbeSJulio Merino {
451a18eacbeSJulio Merino     const pid_t control = fork();
452a18eacbeSJulio Merino     ATF_REQUIRE(control != -1);
453a18eacbeSJulio Merino     if (control == 0)
454a18eacbeSJulio Merino         fork_and_wait(123, "Some output\n", "save:my-output.txt");
455a18eacbeSJulio Merino     else {
456a18eacbeSJulio Merino         int status;
457a18eacbeSJulio Merino         ATF_REQUIRE(waitpid(control, &status, 0) != -1);
458a18eacbeSJulio Merino         ATF_REQUIRE(WIFEXITED(status));
459a18eacbeSJulio Merino         ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
460a18eacbeSJulio Merino 
461a18eacbeSJulio Merino         ATF_REQUIRE(atf::utils::compare_file("my-output.txt", "Some error\n"));
462a18eacbeSJulio Merino     }
463c243e490SMarcel Moolenaar }
464c243e490SMarcel Moolenaar 
465c243e490SMarcel Moolenaar // ------------------------------------------------------------------------
466c243e490SMarcel Moolenaar // Main.
467c243e490SMarcel Moolenaar // ------------------------------------------------------------------------
468c243e490SMarcel Moolenaar 
469c243e490SMarcel Moolenaar ATF_INIT_TEST_CASES(tcs)
470c243e490SMarcel Moolenaar {
471a18eacbeSJulio Merino     // Add the test for the free functions.
472a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, cat_file__empty);
473a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, cat_file__one_line);
474a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, cat_file__several_lines);
475a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, cat_file__no_newline_eof);
476a18eacbeSJulio Merino 
477a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, compare_file__empty__match);
478a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, compare_file__empty__not_match);
479a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, compare_file__short__match);
480a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, compare_file__short__not_match);
481a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, compare_file__long__match);
482a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, compare_file__long__not_match);
483a18eacbeSJulio Merino 
484a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, copy_file__empty);
485a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, copy_file__some_contents);
486a18eacbeSJulio Merino 
487a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, create_file);
488a18eacbeSJulio Merino 
489a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, file_exists);
490a18eacbeSJulio Merino 
491a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, fork);
492a18eacbeSJulio Merino 
493a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, grep_collection__set);
494a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, grep_collection__vector);
495a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, grep_file);
496a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, grep_string);
497a18eacbeSJulio Merino 
498a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, redirect__stdout);
499a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, redirect__stderr);
500a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, redirect__other);
501a18eacbeSJulio Merino 
502a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, wait__ok);
503*0677dfd1SJulio Merino     ATF_ADD_TEST_CASE(tcs, wait__ok_nested);
504a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, wait__invalid_exitstatus);
505a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, wait__invalid_stdout);
506a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, wait__invalid_stderr);
507a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, wait__save_stdout);
508a18eacbeSJulio Merino     ATF_ADD_TEST_CASE(tcs, wait__save_stderr);
509c243e490SMarcel Moolenaar }
510