xref: /freebsd/contrib/atf/atf-c++/utils_test.cpp (revision 38f0b757fd84d17d0fc24739a7cda160c4516d81)
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