xref: /netbsd-src/external/bsd/atf/dist/tools/io_test.cpp (revision d780102efefa02003390cc43ea410dbd0ebb4a85)
1*d780102eSjmmv //
2*d780102eSjmmv // Automated Testing Framework (atf)
3*d780102eSjmmv //
4*d780102eSjmmv // Copyright (c) 2007 The NetBSD Foundation, Inc.
5*d780102eSjmmv // All rights reserved.
6*d780102eSjmmv //
7*d780102eSjmmv // Redistribution and use in source and binary forms, with or without
8*d780102eSjmmv // modification, are permitted provided that the following conditions
9*d780102eSjmmv // are met:
10*d780102eSjmmv // 1. Redistributions of source code must retain the above copyright
11*d780102eSjmmv //    notice, this list of conditions and the following disclaimer.
12*d780102eSjmmv // 2. Redistributions in binary form must reproduce the above copyright
13*d780102eSjmmv //    notice, this list of conditions and the following disclaimer in the
14*d780102eSjmmv //    documentation and/or other materials provided with the distribution.
15*d780102eSjmmv //
16*d780102eSjmmv // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17*d780102eSjmmv // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18*d780102eSjmmv // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19*d780102eSjmmv // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20*d780102eSjmmv // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21*d780102eSjmmv // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*d780102eSjmmv // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23*d780102eSjmmv // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*d780102eSjmmv // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25*d780102eSjmmv // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26*d780102eSjmmv // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27*d780102eSjmmv // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*d780102eSjmmv //
29*d780102eSjmmv 
30*d780102eSjmmv extern "C" {
31*d780102eSjmmv #include <sys/stat.h>
32*d780102eSjmmv #include <sys/wait.h>
33*d780102eSjmmv 
34*d780102eSjmmv #include <fcntl.h>
35*d780102eSjmmv #include <unistd.h>
36*d780102eSjmmv }
37*d780102eSjmmv 
38*d780102eSjmmv #include <cassert>
39*d780102eSjmmv #include <cerrno>
40*d780102eSjmmv #include <cstddef>
41*d780102eSjmmv #include <cstdlib>
42*d780102eSjmmv #include <cstring>
43*d780102eSjmmv #include <fstream>
44*d780102eSjmmv #include <iostream>
45*d780102eSjmmv #include <istream>
46*d780102eSjmmv #include <ostream>
47*d780102eSjmmv 
48*d780102eSjmmv #include <atf-c++.hpp>
49*d780102eSjmmv 
50*d780102eSjmmv #include "io.hpp"
51*d780102eSjmmv #include "signals.hpp"
52*d780102eSjmmv 
53*d780102eSjmmv // ------------------------------------------------------------------------
54*d780102eSjmmv // Auxiliary functions.
55*d780102eSjmmv // ------------------------------------------------------------------------
56*d780102eSjmmv 
57*d780102eSjmmv static
58*d780102eSjmmv void
systembuf_check_data(std::istream & is,std::size_t length)59*d780102eSjmmv systembuf_check_data(std::istream& is, std::size_t length)
60*d780102eSjmmv {
61*d780102eSjmmv     char ch = 'A', chr;
62*d780102eSjmmv     std::size_t cnt = 0;
63*d780102eSjmmv     while (is >> chr) {
64*d780102eSjmmv         ATF_REQUIRE_EQ(ch, chr);
65*d780102eSjmmv         if (ch == 'Z')
66*d780102eSjmmv             ch = 'A';
67*d780102eSjmmv         else
68*d780102eSjmmv             ch++;
69*d780102eSjmmv         cnt++;
70*d780102eSjmmv     }
71*d780102eSjmmv     ATF_REQUIRE_EQ(cnt, length);
72*d780102eSjmmv }
73*d780102eSjmmv 
74*d780102eSjmmv static
75*d780102eSjmmv void
systembuf_write_data(std::ostream & os,std::size_t length)76*d780102eSjmmv systembuf_write_data(std::ostream& os, std::size_t length)
77*d780102eSjmmv {
78*d780102eSjmmv     char ch = 'A';
79*d780102eSjmmv     for (std::size_t i = 0; i < length; i++) {
80*d780102eSjmmv         os << ch;
81*d780102eSjmmv         if (ch == 'Z')
82*d780102eSjmmv             ch = 'A';
83*d780102eSjmmv         else
84*d780102eSjmmv             ch++;
85*d780102eSjmmv     }
86*d780102eSjmmv     os.flush();
87*d780102eSjmmv }
88*d780102eSjmmv 
89*d780102eSjmmv static
90*d780102eSjmmv void
systembuf_test_read(std::size_t length,std::size_t bufsize)91*d780102eSjmmv systembuf_test_read(std::size_t length, std::size_t bufsize)
92*d780102eSjmmv {
93*d780102eSjmmv     using tools::io::systembuf;
94*d780102eSjmmv 
95*d780102eSjmmv     std::ofstream f("test_read.txt");
96*d780102eSjmmv     systembuf_write_data(f, length);
97*d780102eSjmmv     f.close();
98*d780102eSjmmv 
99*d780102eSjmmv     int fd = ::open("test_read.txt", O_RDONLY);
100*d780102eSjmmv     ATF_REQUIRE(fd != -1);
101*d780102eSjmmv     systembuf sb(fd, bufsize);
102*d780102eSjmmv     std::istream is(&sb);
103*d780102eSjmmv     systembuf_check_data(is, length);
104*d780102eSjmmv     ::close(fd);
105*d780102eSjmmv     ::unlink("test_read.txt");
106*d780102eSjmmv }
107*d780102eSjmmv 
108*d780102eSjmmv static
109*d780102eSjmmv void
systembuf_test_write(std::size_t length,std::size_t bufsize)110*d780102eSjmmv systembuf_test_write(std::size_t length, std::size_t bufsize)
111*d780102eSjmmv {
112*d780102eSjmmv     using tools::io::systembuf;
113*d780102eSjmmv 
114*d780102eSjmmv     int fd = ::open("test_write.txt", O_WRONLY | O_CREAT | O_TRUNC,
115*d780102eSjmmv                     S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
116*d780102eSjmmv     ATF_REQUIRE(fd != -1);
117*d780102eSjmmv     systembuf sb(fd, bufsize);
118*d780102eSjmmv     std::ostream os(&sb);
119*d780102eSjmmv     systembuf_write_data(os, length);
120*d780102eSjmmv     ::close(fd);
121*d780102eSjmmv 
122*d780102eSjmmv     std::ifstream is("test_write.txt");
123*d780102eSjmmv     systembuf_check_data(is, length);
124*d780102eSjmmv     is.close();
125*d780102eSjmmv     ::unlink("test_write.txt");
126*d780102eSjmmv }
127*d780102eSjmmv 
128*d780102eSjmmv // ------------------------------------------------------------------------
129*d780102eSjmmv // Test cases for the "file_handle" class.
130*d780102eSjmmv // ------------------------------------------------------------------------
131*d780102eSjmmv 
132*d780102eSjmmv ATF_TEST_CASE(file_handle_ctor);
ATF_TEST_CASE_HEAD(file_handle_ctor)133*d780102eSjmmv ATF_TEST_CASE_HEAD(file_handle_ctor)
134*d780102eSjmmv {
135*d780102eSjmmv     set_md_var("descr", "Tests file_handle's constructors");
136*d780102eSjmmv }
ATF_TEST_CASE_BODY(file_handle_ctor)137*d780102eSjmmv ATF_TEST_CASE_BODY(file_handle_ctor)
138*d780102eSjmmv {
139*d780102eSjmmv     using tools::io::file_handle;
140*d780102eSjmmv 
141*d780102eSjmmv     file_handle fh1;
142*d780102eSjmmv     ATF_REQUIRE(!fh1.is_valid());
143*d780102eSjmmv 
144*d780102eSjmmv     file_handle fh2(STDOUT_FILENO);
145*d780102eSjmmv     ATF_REQUIRE(fh2.is_valid());
146*d780102eSjmmv     fh2.disown();
147*d780102eSjmmv }
148*d780102eSjmmv 
149*d780102eSjmmv ATF_TEST_CASE(file_handle_copy);
ATF_TEST_CASE_HEAD(file_handle_copy)150*d780102eSjmmv ATF_TEST_CASE_HEAD(file_handle_copy)
151*d780102eSjmmv {
152*d780102eSjmmv     set_md_var("descr", "Tests file_handle's copy constructor");
153*d780102eSjmmv }
ATF_TEST_CASE_BODY(file_handle_copy)154*d780102eSjmmv ATF_TEST_CASE_BODY(file_handle_copy)
155*d780102eSjmmv {
156*d780102eSjmmv     using tools::io::file_handle;
157*d780102eSjmmv 
158*d780102eSjmmv     file_handle fh1;
159*d780102eSjmmv     file_handle fh2(STDOUT_FILENO);
160*d780102eSjmmv 
161*d780102eSjmmv     file_handle fh3(fh2);
162*d780102eSjmmv     ATF_REQUIRE(!fh2.is_valid());
163*d780102eSjmmv     ATF_REQUIRE(fh3.is_valid());
164*d780102eSjmmv 
165*d780102eSjmmv     fh1 = fh3;
166*d780102eSjmmv     ATF_REQUIRE(!fh3.is_valid());
167*d780102eSjmmv     ATF_REQUIRE(fh1.is_valid());
168*d780102eSjmmv 
169*d780102eSjmmv     fh1.disown();
170*d780102eSjmmv }
171*d780102eSjmmv 
172*d780102eSjmmv ATF_TEST_CASE(file_handle_get);
ATF_TEST_CASE_HEAD(file_handle_get)173*d780102eSjmmv ATF_TEST_CASE_HEAD(file_handle_get)
174*d780102eSjmmv {
175*d780102eSjmmv     set_md_var("descr", "Tests the file_handle::get method");
176*d780102eSjmmv }
ATF_TEST_CASE_BODY(file_handle_get)177*d780102eSjmmv ATF_TEST_CASE_BODY(file_handle_get)
178*d780102eSjmmv {
179*d780102eSjmmv     using tools::io::file_handle;
180*d780102eSjmmv 
181*d780102eSjmmv     file_handle fh1(STDOUT_FILENO);
182*d780102eSjmmv     ATF_REQUIRE_EQ(fh1.get(), STDOUT_FILENO);
183*d780102eSjmmv }
184*d780102eSjmmv 
185*d780102eSjmmv ATF_TEST_CASE(file_handle_posix_remap);
ATF_TEST_CASE_HEAD(file_handle_posix_remap)186*d780102eSjmmv ATF_TEST_CASE_HEAD(file_handle_posix_remap)
187*d780102eSjmmv {
188*d780102eSjmmv     set_md_var("descr", "Tests the file_handle::posix_remap method");
189*d780102eSjmmv }
ATF_TEST_CASE_BODY(file_handle_posix_remap)190*d780102eSjmmv ATF_TEST_CASE_BODY(file_handle_posix_remap)
191*d780102eSjmmv {
192*d780102eSjmmv     using tools::io::file_handle;
193*d780102eSjmmv 
194*d780102eSjmmv     int pfd[2];
195*d780102eSjmmv 
196*d780102eSjmmv     ATF_REQUIRE(::pipe(pfd) != -1);
197*d780102eSjmmv     file_handle rend(pfd[0]);
198*d780102eSjmmv     file_handle wend(pfd[1]);
199*d780102eSjmmv 
200*d780102eSjmmv     ATF_REQUIRE(rend.get() != 10);
201*d780102eSjmmv     ATF_REQUIRE(wend.get() != 10);
202*d780102eSjmmv     wend.posix_remap(10);
203*d780102eSjmmv     ATF_REQUIRE_EQ(wend.get(), 10);
204*d780102eSjmmv     ATF_REQUIRE(::write(wend.get(), "test-posix-remap", 16) != -1);
205*d780102eSjmmv     {
206*d780102eSjmmv         char buf[17];
207*d780102eSjmmv         ATF_REQUIRE_EQ(::read(rend.get(), buf, sizeof(buf)), 16);
208*d780102eSjmmv         buf[16] = '\0';
209*d780102eSjmmv         ATF_REQUIRE(std::strcmp(buf, "test-posix-remap") == 0);
210*d780102eSjmmv     }
211*d780102eSjmmv 
212*d780102eSjmmv     // Redo previous to ensure that remapping over the same descriptor
213*d780102eSjmmv     // has no side-effects.
214*d780102eSjmmv     ATF_REQUIRE_EQ(wend.get(), 10);
215*d780102eSjmmv     wend.posix_remap(10);
216*d780102eSjmmv     ATF_REQUIRE_EQ(wend.get(), 10);
217*d780102eSjmmv     ATF_REQUIRE(::write(wend.get(), "test-posix-remap", 16) != -1);
218*d780102eSjmmv     {
219*d780102eSjmmv         char buf[17];
220*d780102eSjmmv         ATF_REQUIRE_EQ(::read(rend.get(), buf, sizeof(buf)), 16);
221*d780102eSjmmv         buf[16] = '\0';
222*d780102eSjmmv         ATF_REQUIRE(std::strcmp(buf, "test-posix-remap") == 0);
223*d780102eSjmmv     }
224*d780102eSjmmv }
225*d780102eSjmmv 
226*d780102eSjmmv // ------------------------------------------------------------------------
227*d780102eSjmmv // Test cases for the "systembuf" class.
228*d780102eSjmmv // ------------------------------------------------------------------------
229*d780102eSjmmv 
230*d780102eSjmmv ATF_TEST_CASE(systembuf_short_read);
ATF_TEST_CASE_HEAD(systembuf_short_read)231*d780102eSjmmv ATF_TEST_CASE_HEAD(systembuf_short_read)
232*d780102eSjmmv {
233*d780102eSjmmv     set_md_var("descr", "Tests that a short read (one that fits in the "
234*d780102eSjmmv                "internal buffer) works when using systembuf");
235*d780102eSjmmv }
ATF_TEST_CASE_BODY(systembuf_short_read)236*d780102eSjmmv ATF_TEST_CASE_BODY(systembuf_short_read)
237*d780102eSjmmv {
238*d780102eSjmmv     systembuf_test_read(64, 1024);
239*d780102eSjmmv }
240*d780102eSjmmv 
241*d780102eSjmmv ATF_TEST_CASE(systembuf_long_read);
ATF_TEST_CASE_HEAD(systembuf_long_read)242*d780102eSjmmv ATF_TEST_CASE_HEAD(systembuf_long_read)
243*d780102eSjmmv {
244*d780102eSjmmv     set_md_var("descr", "Tests that a long read (one that does not fit in "
245*d780102eSjmmv                "the internal buffer) works when using systembuf");
246*d780102eSjmmv }
ATF_TEST_CASE_BODY(systembuf_long_read)247*d780102eSjmmv ATF_TEST_CASE_BODY(systembuf_long_read)
248*d780102eSjmmv {
249*d780102eSjmmv     systembuf_test_read(64 * 1024, 1024);
250*d780102eSjmmv }
251*d780102eSjmmv 
252*d780102eSjmmv ATF_TEST_CASE(systembuf_short_write);
ATF_TEST_CASE_HEAD(systembuf_short_write)253*d780102eSjmmv ATF_TEST_CASE_HEAD(systembuf_short_write)
254*d780102eSjmmv {
255*d780102eSjmmv     set_md_var("descr", "Tests that a short write (one that fits in the "
256*d780102eSjmmv                "internal buffer) works when using systembuf");
257*d780102eSjmmv }
ATF_TEST_CASE_BODY(systembuf_short_write)258*d780102eSjmmv ATF_TEST_CASE_BODY(systembuf_short_write)
259*d780102eSjmmv {
260*d780102eSjmmv     systembuf_test_write(64, 1024);
261*d780102eSjmmv }
262*d780102eSjmmv 
263*d780102eSjmmv ATF_TEST_CASE(systembuf_long_write);
ATF_TEST_CASE_HEAD(systembuf_long_write)264*d780102eSjmmv ATF_TEST_CASE_HEAD(systembuf_long_write)
265*d780102eSjmmv {
266*d780102eSjmmv     set_md_var("descr", "Tests that a long write (one that does not fit "
267*d780102eSjmmv                "in the internal buffer) works when using systembuf");
268*d780102eSjmmv }
ATF_TEST_CASE_BODY(systembuf_long_write)269*d780102eSjmmv ATF_TEST_CASE_BODY(systembuf_long_write)
270*d780102eSjmmv {
271*d780102eSjmmv     systembuf_test_write(64 * 1024, 1024);
272*d780102eSjmmv }
273*d780102eSjmmv 
274*d780102eSjmmv // ------------------------------------------------------------------------
275*d780102eSjmmv // Test cases for the "pistream" class.
276*d780102eSjmmv // ------------------------------------------------------------------------
277*d780102eSjmmv 
278*d780102eSjmmv ATF_TEST_CASE(pistream);
ATF_TEST_CASE_HEAD(pistream)279*d780102eSjmmv ATF_TEST_CASE_HEAD(pistream)
280*d780102eSjmmv {
281*d780102eSjmmv     set_md_var("descr", "Tests the pistream class");
282*d780102eSjmmv }
ATF_TEST_CASE_BODY(pistream)283*d780102eSjmmv ATF_TEST_CASE_BODY(pistream)
284*d780102eSjmmv {
285*d780102eSjmmv     using tools::io::file_handle;
286*d780102eSjmmv     using tools::io::pistream;
287*d780102eSjmmv     using tools::io::systembuf;
288*d780102eSjmmv 
289*d780102eSjmmv     int fds[2];
290*d780102eSjmmv     ATF_REQUIRE(::pipe(fds) != -1);
291*d780102eSjmmv 
292*d780102eSjmmv     pistream rend(fds[0]);
293*d780102eSjmmv 
294*d780102eSjmmv     systembuf wbuf(fds[1]);
295*d780102eSjmmv     std::ostream wend(&wbuf);
296*d780102eSjmmv 
297*d780102eSjmmv     // XXX This assumes that the pipe's buffer is big enough to accept
298*d780102eSjmmv     // the data written without blocking!
299*d780102eSjmmv     wend << "1Test 1message\n";
300*d780102eSjmmv     wend.flush();
301*d780102eSjmmv     std::string tmp;
302*d780102eSjmmv     rend >> tmp;
303*d780102eSjmmv     ATF_REQUIRE_EQ(tmp, "1Test");
304*d780102eSjmmv     rend >> tmp;
305*d780102eSjmmv     ATF_REQUIRE_EQ(tmp, "1message");
306*d780102eSjmmv }
307*d780102eSjmmv 
308*d780102eSjmmv // ------------------------------------------------------------------------
309*d780102eSjmmv // Tests for the "muxer" class.
310*d780102eSjmmv // ------------------------------------------------------------------------
311*d780102eSjmmv 
312*d780102eSjmmv namespace {
313*d780102eSjmmv 
314*d780102eSjmmv static void
check_stream(std::ostream & os)315*d780102eSjmmv check_stream(std::ostream& os)
316*d780102eSjmmv {
317*d780102eSjmmv     // If we receive a signal while writing to the stream, the bad bit gets set.
318*d780102eSjmmv     // Things seem to behave fine afterwards if we clear such error condition.
319*d780102eSjmmv     // However, I'm not sure if it's safe to query errno at this point.
320*d780102eSjmmv     ATF_REQUIRE(os.good() || (os.bad() && errno == EINTR));
321*d780102eSjmmv     os.clear();
322*d780102eSjmmv }
323*d780102eSjmmv 
324*d780102eSjmmv class mock_muxer : public tools::io::muxer {
line_callback(const size_t index,const std::string & line)325*d780102eSjmmv     void line_callback(const size_t index, const std::string& line)
326*d780102eSjmmv     {
327*d780102eSjmmv         // The following should be enabled but causes the output to be so big
328*d780102eSjmmv         // that it is annoying.  Reenable at some point if we make atf store
329*d780102eSjmmv         // the output of the test cases in some other way (e.g. only if a test
330*d780102eSjmmv         // failes), because this message is the only help in seeing how the
331*d780102eSjmmv         // test fails.
332*d780102eSjmmv         //std::cout << "line_callback(" << index << ", " << line << ")\n";
333*d780102eSjmmv         check_stream(std::cout);
334*d780102eSjmmv         switch (index) {
335*d780102eSjmmv         case 0: lines0.push_back(line); break;
336*d780102eSjmmv         case 1: lines1.push_back(line); break;
337*d780102eSjmmv         default: ATF_REQUIRE(false);
338*d780102eSjmmv         }
339*d780102eSjmmv     }
340*d780102eSjmmv 
341*d780102eSjmmv public:
mock_muxer(const int * fds,const size_t nfds,const size_t bufsize)342*d780102eSjmmv     mock_muxer(const int* fds, const size_t nfds, const size_t bufsize) :
343*d780102eSjmmv         muxer(fds, nfds, bufsize) {}
344*d780102eSjmmv 
345*d780102eSjmmv     std::vector< std::string > lines0;
346*d780102eSjmmv     std::vector< std::string > lines1;
347*d780102eSjmmv };
348*d780102eSjmmv 
349*d780102eSjmmv static bool child_finished = false;
sigchld_handler(int signo)350*d780102eSjmmv static void sigchld_handler(int signo)
351*d780102eSjmmv {
352*d780102eSjmmv     assert(signo == SIGCHLD);
353*d780102eSjmmv     child_finished = true;
354*d780102eSjmmv }
355*d780102eSjmmv 
356*d780102eSjmmv static void
child_printer(const int pipeout[2],const int pipeerr[2],const size_t iterations)357*d780102eSjmmv child_printer(const int pipeout[2], const int pipeerr[2],
358*d780102eSjmmv               const size_t iterations)
359*d780102eSjmmv {
360*d780102eSjmmv     ::close(pipeout[0]);
361*d780102eSjmmv     ::close(pipeerr[0]);
362*d780102eSjmmv     ATF_REQUIRE(::dup2(pipeout[1], STDOUT_FILENO) != -1);
363*d780102eSjmmv     ATF_REQUIRE(::dup2(pipeerr[1], STDERR_FILENO) != -1);
364*d780102eSjmmv     ::close(pipeout[1]);
365*d780102eSjmmv     ::close(pipeerr[1]);
366*d780102eSjmmv 
367*d780102eSjmmv     for (size_t i = 0; i < iterations; i++) {
368*d780102eSjmmv         std::cout << "stdout " << i << "\n";
369*d780102eSjmmv         std::cerr << "stderr " << i << "\n";
370*d780102eSjmmv     }
371*d780102eSjmmv 
372*d780102eSjmmv     std::cout << "stdout eof\n";
373*d780102eSjmmv     std::cerr << "stderr eof\n";
374*d780102eSjmmv     std::exit(EXIT_SUCCESS);
375*d780102eSjmmv }
376*d780102eSjmmv 
377*d780102eSjmmv static void
muxer_test(const size_t bufsize,const size_t iterations)378*d780102eSjmmv muxer_test(const size_t bufsize, const size_t iterations)
379*d780102eSjmmv {
380*d780102eSjmmv     int pipeout[2], pipeerr[2];
381*d780102eSjmmv     ATF_REQUIRE(pipe(pipeout) != -1);
382*d780102eSjmmv     ATF_REQUIRE(pipe(pipeerr) != -1);
383*d780102eSjmmv 
384*d780102eSjmmv     tools::signals::signal_programmer sigchld(SIGCHLD, sigchld_handler);
385*d780102eSjmmv 
386*d780102eSjmmv     std::cout.flush();
387*d780102eSjmmv     std::cerr.flush();
388*d780102eSjmmv 
389*d780102eSjmmv     pid_t pid = ::fork();
390*d780102eSjmmv     ATF_REQUIRE(pid != -1);
391*d780102eSjmmv     if (pid == 0) {
392*d780102eSjmmv         sigchld.unprogram();
393*d780102eSjmmv         child_printer(pipeout, pipeerr, iterations);
394*d780102eSjmmv         std::abort();
395*d780102eSjmmv     }
396*d780102eSjmmv     ::close(pipeout[1]);
397*d780102eSjmmv     ::close(pipeerr[1]);
398*d780102eSjmmv 
399*d780102eSjmmv     int fds[2] = {pipeout[0], pipeerr[0]};
400*d780102eSjmmv     mock_muxer mux(fds, 2, bufsize);
401*d780102eSjmmv 
402*d780102eSjmmv     mux.mux(child_finished);
403*d780102eSjmmv     check_stream(std::cout);
404*d780102eSjmmv     std::cout << "mux done\n";
405*d780102eSjmmv 
406*d780102eSjmmv     mux.flush();
407*d780102eSjmmv     std::cout << "flush done\n";
408*d780102eSjmmv     check_stream(std::cout);
409*d780102eSjmmv 
410*d780102eSjmmv     sigchld.unprogram();
411*d780102eSjmmv     int status;
412*d780102eSjmmv     ATF_REQUIRE(::waitpid(pid, &status, 0) != -1);
413*d780102eSjmmv     ATF_REQUIRE(WIFEXITED(status));
414*d780102eSjmmv     ATF_REQUIRE(WEXITSTATUS(status) == EXIT_SUCCESS);
415*d780102eSjmmv 
416*d780102eSjmmv     ATF_REQUIRE(std::cout.good());
417*d780102eSjmmv     ATF_REQUIRE(std::cerr.good());
418*d780102eSjmmv     for (size_t i = 0; i < iterations; i++) {
419*d780102eSjmmv         std::ostringstream exp0, exp1;
420*d780102eSjmmv         exp0 << "stdout " << i;
421*d780102eSjmmv         exp1 << "stderr " << i;
422*d780102eSjmmv 
423*d780102eSjmmv         ATF_REQUIRE(mux.lines0.size() > i);
424*d780102eSjmmv         ATF_REQUIRE_EQ(exp0.str(), mux.lines0[i]);
425*d780102eSjmmv         ATF_REQUIRE(mux.lines1.size() > i);
426*d780102eSjmmv         ATF_REQUIRE_EQ(exp1.str(), mux.lines1[i]);
427*d780102eSjmmv     }
428*d780102eSjmmv     ATF_REQUIRE_EQ("stdout eof", mux.lines0[iterations]);
429*d780102eSjmmv     ATF_REQUIRE_EQ("stderr eof", mux.lines1[iterations]);
430*d780102eSjmmv     std::cout << "all done\n";
431*d780102eSjmmv }
432*d780102eSjmmv 
433*d780102eSjmmv } // anonymous namespace
434*d780102eSjmmv 
435*d780102eSjmmv ATF_TEST_CASE_WITHOUT_HEAD(muxer_small_buffer);
ATF_TEST_CASE_BODY(muxer_small_buffer)436*d780102eSjmmv ATF_TEST_CASE_BODY(muxer_small_buffer)
437*d780102eSjmmv {
438*d780102eSjmmv     muxer_test(4, 20000);
439*d780102eSjmmv }
440*d780102eSjmmv 
441*d780102eSjmmv ATF_TEST_CASE_WITHOUT_HEAD(muxer_large_buffer);
ATF_TEST_CASE_BODY(muxer_large_buffer)442*d780102eSjmmv ATF_TEST_CASE_BODY(muxer_large_buffer)
443*d780102eSjmmv {
444*d780102eSjmmv     muxer_test(1024, 50000);
445*d780102eSjmmv }
446*d780102eSjmmv 
447*d780102eSjmmv // ------------------------------------------------------------------------
448*d780102eSjmmv // Main.
449*d780102eSjmmv // ------------------------------------------------------------------------
450*d780102eSjmmv 
ATF_INIT_TEST_CASES(tcs)451*d780102eSjmmv ATF_INIT_TEST_CASES(tcs)
452*d780102eSjmmv {
453*d780102eSjmmv     // Add the tests for the "file_handle" class.
454*d780102eSjmmv     ATF_ADD_TEST_CASE(tcs, file_handle_ctor);
455*d780102eSjmmv     ATF_ADD_TEST_CASE(tcs, file_handle_copy);
456*d780102eSjmmv     ATF_ADD_TEST_CASE(tcs, file_handle_get);
457*d780102eSjmmv     ATF_ADD_TEST_CASE(tcs, file_handle_posix_remap);
458*d780102eSjmmv 
459*d780102eSjmmv     // Add the tests for the "systembuf" class.
460*d780102eSjmmv     ATF_ADD_TEST_CASE(tcs, systembuf_short_read);
461*d780102eSjmmv     ATF_ADD_TEST_CASE(tcs, systembuf_long_read);
462*d780102eSjmmv     ATF_ADD_TEST_CASE(tcs, systembuf_short_write);
463*d780102eSjmmv     ATF_ADD_TEST_CASE(tcs, systembuf_long_write);
464*d780102eSjmmv 
465*d780102eSjmmv     // Add the tests for the "pistream" class.
466*d780102eSjmmv     ATF_ADD_TEST_CASE(tcs, pistream);
467*d780102eSjmmv 
468*d780102eSjmmv     // Add the tests for the "muxer" class.
469*d780102eSjmmv     ATF_ADD_TEST_CASE(tcs, muxer_small_buffer);
470*d780102eSjmmv     ATF_ADD_TEST_CASE(tcs, muxer_large_buffer);
471*d780102eSjmmv }
472