1240116Smarcel// 2240116Smarcel// Automated Testing Framework (atf) 3240116Smarcel// 4240116Smarcel// Copyright (c) 2007 The NetBSD Foundation, Inc. 5240116Smarcel// All rights reserved. 6240116Smarcel// 7240116Smarcel// Redistribution and use in source and binary forms, with or without 8240116Smarcel// modification, are permitted provided that the following conditions 9240116Smarcel// are met: 10240116Smarcel// 1. Redistributions of source code must retain the above copyright 11240116Smarcel// notice, this list of conditions and the following disclaimer. 12240116Smarcel// 2. Redistributions in binary form must reproduce the above copyright 13240116Smarcel// notice, this list of conditions and the following disclaimer in the 14240116Smarcel// documentation and/or other materials provided with the distribution. 15240116Smarcel// 16240116Smarcel// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 17240116Smarcel// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 18240116Smarcel// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19240116Smarcel// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20240116Smarcel// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 21240116Smarcel// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22240116Smarcel// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 23240116Smarcel// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24240116Smarcel// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25240116Smarcel// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26240116Smarcel// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27240116Smarcel// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28240116Smarcel// 29240116Smarcel 30240116Smarcelextern "C" { 31240116Smarcel#include <sys/stat.h> 32240116Smarcel#include <sys/wait.h> 33240116Smarcel 34240116Smarcel#include <fcntl.h> 35240116Smarcel#include <unistd.h> 36240116Smarcel} 37240116Smarcel 38240116Smarcel#include <cerrno> 39240116Smarcel#include <cstddef> 40240116Smarcel#include <cstdlib> 41240116Smarcel#include <cstring> 42240116Smarcel#include <fstream> 43240116Smarcel#include <iostream> 44240116Smarcel#include <istream> 45240116Smarcel#include <ostream> 46240116Smarcel 47240116Smarcel#include "../atf-c++/detail/sanity.hpp" 48240116Smarcel#include "../atf-c++/macros.hpp" 49240116Smarcel 50240116Smarcel#include "io.hpp" 51240116Smarcel#include "signals.hpp" 52240116Smarcel 53240116Smarcel// ------------------------------------------------------------------------ 54240116Smarcel// Auxiliary functions. 55240116Smarcel// ------------------------------------------------------------------------ 56240116Smarcel 57240116Smarcelstatic 58240116Smarcelvoid 59240116Smarcelsystembuf_check_data(std::istream& is, std::size_t length) 60240116Smarcel{ 61240116Smarcel char ch = 'A', chr; 62240116Smarcel std::size_t cnt = 0; 63240116Smarcel while (is >> chr) { 64240116Smarcel ATF_REQUIRE_EQ(ch, chr); 65240116Smarcel if (ch == 'Z') 66240116Smarcel ch = 'A'; 67240116Smarcel else 68240116Smarcel ch++; 69240116Smarcel cnt++; 70240116Smarcel } 71240116Smarcel ATF_REQUIRE_EQ(cnt, length); 72240116Smarcel} 73240116Smarcel 74240116Smarcelstatic 75240116Smarcelvoid 76240116Smarcelsystembuf_write_data(std::ostream& os, std::size_t length) 77240116Smarcel{ 78240116Smarcel char ch = 'A'; 79240116Smarcel for (std::size_t i = 0; i < length; i++) { 80240116Smarcel os << ch; 81240116Smarcel if (ch == 'Z') 82240116Smarcel ch = 'A'; 83240116Smarcel else 84240116Smarcel ch++; 85240116Smarcel } 86240116Smarcel os.flush(); 87240116Smarcel} 88240116Smarcel 89240116Smarcelstatic 90240116Smarcelvoid 91240116Smarcelsystembuf_test_read(std::size_t length, std::size_t bufsize) 92240116Smarcel{ 93240116Smarcel using atf::atf_run::systembuf; 94240116Smarcel 95240116Smarcel std::ofstream f("test_read.txt"); 96240116Smarcel systembuf_write_data(f, length); 97240116Smarcel f.close(); 98240116Smarcel 99240116Smarcel int fd = ::open("test_read.txt", O_RDONLY); 100240116Smarcel ATF_REQUIRE(fd != -1); 101240116Smarcel systembuf sb(fd, bufsize); 102240116Smarcel std::istream is(&sb); 103240116Smarcel systembuf_check_data(is, length); 104240116Smarcel ::close(fd); 105240116Smarcel ::unlink("test_read.txt"); 106240116Smarcel} 107240116Smarcel 108240116Smarcelstatic 109240116Smarcelvoid 110240116Smarcelsystembuf_test_write(std::size_t length, std::size_t bufsize) 111240116Smarcel{ 112240116Smarcel using atf::atf_run::systembuf; 113240116Smarcel 114240116Smarcel int fd = ::open("test_write.txt", O_WRONLY | O_CREAT | O_TRUNC, 115240116Smarcel S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 116240116Smarcel ATF_REQUIRE(fd != -1); 117240116Smarcel systembuf sb(fd, bufsize); 118240116Smarcel std::ostream os(&sb); 119240116Smarcel systembuf_write_data(os, length); 120240116Smarcel ::close(fd); 121240116Smarcel 122240116Smarcel std::ifstream is("test_write.txt"); 123240116Smarcel systembuf_check_data(is, length); 124240116Smarcel is.close(); 125240116Smarcel ::unlink("test_write.txt"); 126240116Smarcel} 127240116Smarcel 128240116Smarcel// ------------------------------------------------------------------------ 129240116Smarcel// Test cases for the "file_handle" class. 130240116Smarcel// ------------------------------------------------------------------------ 131240116Smarcel 132240116SmarcelATF_TEST_CASE(file_handle_ctor); 133240116SmarcelATF_TEST_CASE_HEAD(file_handle_ctor) 134240116Smarcel{ 135240116Smarcel set_md_var("descr", "Tests file_handle's constructors"); 136240116Smarcel} 137240116SmarcelATF_TEST_CASE_BODY(file_handle_ctor) 138240116Smarcel{ 139240116Smarcel using atf::atf_run::file_handle; 140240116Smarcel 141240116Smarcel file_handle fh1; 142240116Smarcel ATF_REQUIRE(!fh1.is_valid()); 143240116Smarcel 144240116Smarcel file_handle fh2(STDOUT_FILENO); 145240116Smarcel ATF_REQUIRE(fh2.is_valid()); 146240116Smarcel fh2.disown(); 147240116Smarcel} 148240116Smarcel 149240116SmarcelATF_TEST_CASE(file_handle_copy); 150240116SmarcelATF_TEST_CASE_HEAD(file_handle_copy) 151240116Smarcel{ 152240116Smarcel set_md_var("descr", "Tests file_handle's copy constructor"); 153240116Smarcel} 154240116SmarcelATF_TEST_CASE_BODY(file_handle_copy) 155240116Smarcel{ 156240116Smarcel using atf::atf_run::file_handle; 157240116Smarcel 158240116Smarcel file_handle fh1; 159240116Smarcel file_handle fh2(STDOUT_FILENO); 160240116Smarcel 161240116Smarcel file_handle fh3(fh2); 162240116Smarcel ATF_REQUIRE(!fh2.is_valid()); 163240116Smarcel ATF_REQUIRE(fh3.is_valid()); 164240116Smarcel 165240116Smarcel fh1 = fh3; 166240116Smarcel ATF_REQUIRE(!fh3.is_valid()); 167240116Smarcel ATF_REQUIRE(fh1.is_valid()); 168240116Smarcel 169240116Smarcel fh1.disown(); 170240116Smarcel} 171240116Smarcel 172240116SmarcelATF_TEST_CASE(file_handle_get); 173240116SmarcelATF_TEST_CASE_HEAD(file_handle_get) 174240116Smarcel{ 175240116Smarcel set_md_var("descr", "Tests the file_handle::get method"); 176240116Smarcel} 177240116SmarcelATF_TEST_CASE_BODY(file_handle_get) 178240116Smarcel{ 179240116Smarcel using atf::atf_run::file_handle; 180240116Smarcel 181240116Smarcel file_handle fh1(STDOUT_FILENO); 182240116Smarcel ATF_REQUIRE_EQ(fh1.get(), STDOUT_FILENO); 183240116Smarcel} 184240116Smarcel 185240116SmarcelATF_TEST_CASE(file_handle_posix_remap); 186240116SmarcelATF_TEST_CASE_HEAD(file_handle_posix_remap) 187240116Smarcel{ 188240116Smarcel set_md_var("descr", "Tests the file_handle::posix_remap method"); 189240116Smarcel} 190240116SmarcelATF_TEST_CASE_BODY(file_handle_posix_remap) 191240116Smarcel{ 192240116Smarcel using atf::atf_run::file_handle; 193240116Smarcel 194240116Smarcel int pfd[2]; 195240116Smarcel 196240116Smarcel ATF_REQUIRE(::pipe(pfd) != -1); 197240116Smarcel file_handle rend(pfd[0]); 198240116Smarcel file_handle wend(pfd[1]); 199240116Smarcel 200240116Smarcel ATF_REQUIRE(rend.get() != 10); 201240116Smarcel ATF_REQUIRE(wend.get() != 10); 202240116Smarcel wend.posix_remap(10); 203240116Smarcel ATF_REQUIRE_EQ(wend.get(), 10); 204240116Smarcel ATF_REQUIRE(::write(wend.get(), "test-posix-remap", 16) != -1); 205240116Smarcel { 206240116Smarcel char buf[17]; 207240116Smarcel ATF_REQUIRE_EQ(::read(rend.get(), buf, sizeof(buf)), 16); 208240116Smarcel buf[16] = '\0'; 209240116Smarcel ATF_REQUIRE(std::strcmp(buf, "test-posix-remap") == 0); 210240116Smarcel } 211240116Smarcel 212240116Smarcel // Redo previous to ensure that remapping over the same descriptor 213240116Smarcel // has no side-effects. 214240116Smarcel ATF_REQUIRE_EQ(wend.get(), 10); 215240116Smarcel wend.posix_remap(10); 216240116Smarcel ATF_REQUIRE_EQ(wend.get(), 10); 217240116Smarcel ATF_REQUIRE(::write(wend.get(), "test-posix-remap", 16) != -1); 218240116Smarcel { 219240116Smarcel char buf[17]; 220240116Smarcel ATF_REQUIRE_EQ(::read(rend.get(), buf, sizeof(buf)), 16); 221240116Smarcel buf[16] = '\0'; 222240116Smarcel ATF_REQUIRE(std::strcmp(buf, "test-posix-remap") == 0); 223240116Smarcel } 224240116Smarcel} 225240116Smarcel 226240116Smarcel// ------------------------------------------------------------------------ 227240116Smarcel// Test cases for the "systembuf" class. 228240116Smarcel// ------------------------------------------------------------------------ 229240116Smarcel 230240116SmarcelATF_TEST_CASE(systembuf_short_read); 231240116SmarcelATF_TEST_CASE_HEAD(systembuf_short_read) 232240116Smarcel{ 233240116Smarcel set_md_var("descr", "Tests that a short read (one that fits in the " 234240116Smarcel "internal buffer) works when using systembuf"); 235240116Smarcel} 236240116SmarcelATF_TEST_CASE_BODY(systembuf_short_read) 237240116Smarcel{ 238240116Smarcel systembuf_test_read(64, 1024); 239240116Smarcel} 240240116Smarcel 241240116SmarcelATF_TEST_CASE(systembuf_long_read); 242240116SmarcelATF_TEST_CASE_HEAD(systembuf_long_read) 243240116Smarcel{ 244240116Smarcel set_md_var("descr", "Tests that a long read (one that does not fit in " 245240116Smarcel "the internal buffer) works when using systembuf"); 246240116Smarcel} 247240116SmarcelATF_TEST_CASE_BODY(systembuf_long_read) 248240116Smarcel{ 249240116Smarcel systembuf_test_read(64 * 1024, 1024); 250240116Smarcel} 251240116Smarcel 252240116SmarcelATF_TEST_CASE(systembuf_short_write); 253240116SmarcelATF_TEST_CASE_HEAD(systembuf_short_write) 254240116Smarcel{ 255240116Smarcel set_md_var("descr", "Tests that a short write (one that fits in the " 256240116Smarcel "internal buffer) works when using systembuf"); 257240116Smarcel} 258240116SmarcelATF_TEST_CASE_BODY(systembuf_short_write) 259240116Smarcel{ 260240116Smarcel systembuf_test_write(64, 1024); 261240116Smarcel} 262240116Smarcel 263240116SmarcelATF_TEST_CASE(systembuf_long_write); 264240116SmarcelATF_TEST_CASE_HEAD(systembuf_long_write) 265240116Smarcel{ 266240116Smarcel set_md_var("descr", "Tests that a long write (one that does not fit " 267240116Smarcel "in the internal buffer) works when using systembuf"); 268240116Smarcel} 269240116SmarcelATF_TEST_CASE_BODY(systembuf_long_write) 270240116Smarcel{ 271240116Smarcel systembuf_test_write(64 * 1024, 1024); 272240116Smarcel} 273240116Smarcel 274240116Smarcel// ------------------------------------------------------------------------ 275240116Smarcel// Test cases for the "pistream" class. 276240116Smarcel// ------------------------------------------------------------------------ 277240116Smarcel 278240116SmarcelATF_TEST_CASE(pistream); 279240116SmarcelATF_TEST_CASE_HEAD(pistream) 280240116Smarcel{ 281240116Smarcel set_md_var("descr", "Tests the pistream class"); 282240116Smarcel} 283240116SmarcelATF_TEST_CASE_BODY(pistream) 284240116Smarcel{ 285240116Smarcel using atf::atf_run::file_handle; 286240116Smarcel using atf::atf_run::pistream; 287240116Smarcel using atf::atf_run::systembuf; 288240116Smarcel 289240116Smarcel int fds[2]; 290240116Smarcel ATF_REQUIRE(::pipe(fds) != -1); 291240116Smarcel 292240116Smarcel pistream rend(fds[0]); 293240116Smarcel 294240116Smarcel systembuf wbuf(fds[1]); 295240116Smarcel std::ostream wend(&wbuf); 296240116Smarcel 297240116Smarcel // XXX This assumes that the pipe's buffer is big enough to accept 298240116Smarcel // the data written without blocking! 299240116Smarcel wend << "1Test 1message\n"; 300240116Smarcel wend.flush(); 301240116Smarcel std::string tmp; 302240116Smarcel rend >> tmp; 303240116Smarcel ATF_REQUIRE_EQ(tmp, "1Test"); 304240116Smarcel rend >> tmp; 305240116Smarcel ATF_REQUIRE_EQ(tmp, "1message"); 306240116Smarcel} 307240116Smarcel 308240116Smarcel// ------------------------------------------------------------------------ 309240116Smarcel// Tests for the "muxer" class. 310240116Smarcel// ------------------------------------------------------------------------ 311240116Smarcel 312240116Smarcelnamespace { 313240116Smarcel 314240116Smarcelstatic void 315240116Smarcelcheck_stream(std::ostream& os) 316240116Smarcel{ 317240116Smarcel // If we receive a signal while writing to the stream, the bad bit gets set. 318240116Smarcel // Things seem to behave fine afterwards if we clear such error condition. 319240116Smarcel // However, I'm not sure if it's safe to query errno at this point. 320240116Smarcel ATF_REQUIRE(os.good() || (os.bad() && errno == EINTR)); 321240116Smarcel os.clear(); 322240116Smarcel} 323240116Smarcel 324240116Smarcelclass mock_muxer : public atf::atf_run::muxer { 325240116Smarcel void line_callback(const size_t index, const std::string& line) 326240116Smarcel { 327240116Smarcel // The following should be enabled but causes the output to be so big 328240116Smarcel // that it is annoying. Reenable at some point if we make atf store 329240116Smarcel // the output of the test cases in some other way (e.g. only if a test 330240116Smarcel // failes), because this message is the only help in seeing how the 331240116Smarcel // test fails. 332240116Smarcel //std::cout << "line_callback(" << index << ", " << line << ")\n"; 333240116Smarcel check_stream(std::cout); 334240116Smarcel switch (index) { 335240116Smarcel case 0: lines0.push_back(line); break; 336240116Smarcel case 1: lines1.push_back(line); break; 337240116Smarcel default: ATF_REQUIRE(false); 338240116Smarcel } 339240116Smarcel } 340240116Smarcel 341240116Smarcelpublic: 342240116Smarcel mock_muxer(const int* fds, const size_t nfds, const size_t bufsize) : 343240116Smarcel muxer(fds, nfds, bufsize) {} 344240116Smarcel 345240116Smarcel std::vector< std::string > lines0; 346240116Smarcel std::vector< std::string > lines1; 347240116Smarcel}; 348240116Smarcel 349240116Smarcelstatic bool child_finished = false; 350240116Smarcelstatic void sigchld_handler(int signo) 351240116Smarcel{ 352240116Smarcel INV(signo == SIGCHLD); 353240116Smarcel child_finished = true; 354240116Smarcel} 355240116Smarcel 356240116Smarcelstatic void 357240116Smarcelchild_printer(const int pipeout[2], const int pipeerr[2], 358240116Smarcel const size_t iterations) 359240116Smarcel{ 360240116Smarcel ::close(pipeout[0]); 361240116Smarcel ::close(pipeerr[0]); 362240116Smarcel ATF_REQUIRE(::dup2(pipeout[1], STDOUT_FILENO) != -1); 363240116Smarcel ATF_REQUIRE(::dup2(pipeerr[1], STDERR_FILENO) != -1); 364240116Smarcel ::close(pipeout[1]); 365240116Smarcel ::close(pipeerr[1]); 366240116Smarcel 367240116Smarcel for (size_t i = 0; i < iterations; i++) { 368240116Smarcel std::cout << "stdout " << i << "\n"; 369240116Smarcel std::cerr << "stderr " << i << "\n"; 370240116Smarcel } 371240116Smarcel 372240116Smarcel std::cout << "stdout eof\n"; 373240116Smarcel std::cerr << "stderr eof\n"; 374240116Smarcel std::exit(EXIT_SUCCESS); 375240116Smarcel} 376240116Smarcel 377240116Smarcelstatic void 378240116Smarcelmuxer_test(const size_t bufsize, const size_t iterations) 379240116Smarcel{ 380240116Smarcel int pipeout[2], pipeerr[2]; 381240116Smarcel ATF_REQUIRE(pipe(pipeout) != -1); 382240116Smarcel ATF_REQUIRE(pipe(pipeerr) != -1); 383240116Smarcel 384240116Smarcel atf::atf_run::signal_programmer sigchld(SIGCHLD, sigchld_handler); 385240116Smarcel 386240116Smarcel std::cout.flush(); 387240116Smarcel std::cerr.flush(); 388240116Smarcel 389240116Smarcel pid_t pid = ::fork(); 390240116Smarcel ATF_REQUIRE(pid != -1); 391240116Smarcel if (pid == 0) { 392240116Smarcel sigchld.unprogram(); 393240116Smarcel child_printer(pipeout, pipeerr, iterations); 394240116Smarcel UNREACHABLE; 395240116Smarcel } 396240116Smarcel ::close(pipeout[1]); 397240116Smarcel ::close(pipeerr[1]); 398240116Smarcel 399240116Smarcel int fds[2] = {pipeout[0], pipeerr[0]}; 400240116Smarcel mock_muxer mux(fds, 2, bufsize); 401240116Smarcel 402240116Smarcel mux.mux(child_finished); 403240116Smarcel check_stream(std::cout); 404240116Smarcel std::cout << "mux done\n"; 405240116Smarcel 406240116Smarcel mux.flush(); 407240116Smarcel std::cout << "flush done\n"; 408240116Smarcel check_stream(std::cout); 409240116Smarcel 410240116Smarcel sigchld.unprogram(); 411240116Smarcel int status; 412240116Smarcel ATF_REQUIRE(::waitpid(pid, &status, 0) != -1); 413240116Smarcel ATF_REQUIRE(WIFEXITED(status)); 414240116Smarcel ATF_REQUIRE(WEXITSTATUS(status) == EXIT_SUCCESS); 415240116Smarcel 416240116Smarcel ATF_REQUIRE(std::cout.good()); 417240116Smarcel ATF_REQUIRE(std::cerr.good()); 418240116Smarcel for (size_t i = 0; i < iterations; i++) { 419240116Smarcel std::ostringstream exp0, exp1; 420240116Smarcel exp0 << "stdout " << i; 421240116Smarcel exp1 << "stderr " << i; 422240116Smarcel 423240116Smarcel ATF_REQUIRE(mux.lines0.size() > i); 424240116Smarcel ATF_REQUIRE_EQ(exp0.str(), mux.lines0[i]); 425240116Smarcel ATF_REQUIRE(mux.lines1.size() > i); 426240116Smarcel ATF_REQUIRE_EQ(exp1.str(), mux.lines1[i]); 427240116Smarcel } 428240116Smarcel ATF_REQUIRE_EQ("stdout eof", mux.lines0[iterations]); 429240116Smarcel ATF_REQUIRE_EQ("stderr eof", mux.lines1[iterations]); 430240116Smarcel std::cout << "all done\n"; 431240116Smarcel} 432240116Smarcel 433240116Smarcel} // anonymous namespace 434240116Smarcel 435240116SmarcelATF_TEST_CASE_WITHOUT_HEAD(muxer_small_buffer); 436240116SmarcelATF_TEST_CASE_BODY(muxer_small_buffer) 437240116Smarcel{ 438240116Smarcel muxer_test(4, 20000); 439240116Smarcel} 440240116Smarcel 441240116SmarcelATF_TEST_CASE_WITHOUT_HEAD(muxer_large_buffer); 442240116SmarcelATF_TEST_CASE_BODY(muxer_large_buffer) 443240116Smarcel{ 444240116Smarcel muxer_test(1024, 50000); 445240116Smarcel} 446240116Smarcel 447240116Smarcel// ------------------------------------------------------------------------ 448240116Smarcel// Main. 449240116Smarcel// ------------------------------------------------------------------------ 450240116Smarcel 451240116SmarcelATF_INIT_TEST_CASES(tcs) 452240116Smarcel{ 453240116Smarcel // Add the tests for the "file_handle" class. 454240116Smarcel ATF_ADD_TEST_CASE(tcs, file_handle_ctor); 455240116Smarcel ATF_ADD_TEST_CASE(tcs, file_handle_copy); 456240116Smarcel ATF_ADD_TEST_CASE(tcs, file_handle_get); 457240116Smarcel ATF_ADD_TEST_CASE(tcs, file_handle_posix_remap); 458240116Smarcel 459240116Smarcel // Add the tests for the "systembuf" class. 460240116Smarcel ATF_ADD_TEST_CASE(tcs, systembuf_short_read); 461240116Smarcel ATF_ADD_TEST_CASE(tcs, systembuf_long_read); 462240116Smarcel ATF_ADD_TEST_CASE(tcs, systembuf_short_write); 463240116Smarcel ATF_ADD_TEST_CASE(tcs, systembuf_long_write); 464240116Smarcel 465240116Smarcel // Add the tests for the "pistream" class. 466240116Smarcel ATF_ADD_TEST_CASE(tcs, pistream); 467240116Smarcel 468240116Smarcel // Add the tests for the "muxer" class. 469240116Smarcel ATF_ADD_TEST_CASE(tcs, muxer_small_buffer); 470240116Smarcel ATF_ADD_TEST_CASE(tcs, muxer_large_buffer); 471240116Smarcel} 472