From f21fa231865b797d53740ceeb8a3143862f904bf Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Sun, 18 May 2014 10:05:29 -0700 Subject: [PATCH] More posix tests. --- test/gtest-extra.cc | 22 +++++++++++++++------- test/posix-test.cc | 44 +++++++++++++++++++++++++++++++++++++++++--- test/posix-test.h | 2 ++ 3 files changed, 58 insertions(+), 10 deletions(-) diff --git a/test/gtest-extra.cc b/test/gtest-extra.cc index 4281f274..28cbe6ee 100644 --- a/test/gtest-extra.cc +++ b/test/gtest-extra.cc @@ -136,8 +136,9 @@ std::streamsize File::write(const void *buffer, std::size_t count) { } File File::dup(int fd) { - int new_fd = 0; - FMT_RETRY(new_fd, FMT_POSIX_CALL(dup(fd))); + // Don't retry as dup doesn't return EINTR. + // http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html + int new_fd = FMT_POSIX_CALL(dup(fd)); if (new_fd == -1) fmt::ThrowSystemError(errno, "cannot duplicate file descriptor {}") << fd; return File(new_fd); @@ -168,10 +169,11 @@ void File::pipe(File &read_end, File &write_end) { #ifdef _WIN32 // Make the default pipe capacity same as on Linux 2.6.11+. enum { DEFAULT_CAPACITY = 65536 }; - int result = _pipe(fds, DEFAULT_CAPACITY, _O_BINARY); + int result = FMT_POSIX_CALL(pipe(fds, DEFAULT_CAPACITY, _O_BINARY)); #else - // The pipe function doesn't return EINTR, so no need to retry. - int result = ::pipe(fds); + // Don't retry as the pipe function doesn't return EINTR. + // http://pubs.opengroup.org/onlinepubs/009696799/functions/pipe.html + int result = FMT_POSIX_CALL(pipe(fds)); #endif if (result != 0) fmt::ThrowSystemError(errno, "cannot create pipe"); @@ -182,9 +184,15 @@ void File::pipe(File &read_end, File &write_end) { } BufferedFile File::fdopen(const char *mode) { - BufferedFile f(FMT_POSIX_CALL(fdopen(fd_, mode))); + // Don't retry as fdopen doesn't return EINTR. + FILE *f = FMT_POSIX_CALL(fdopen(fd_, mode)); + if (!f) { + fmt::ThrowSystemError(errno, + "cannot associate stream with file descriptor"); + } + BufferedFile file(f); fd_ = -1; - return f; + return file; } void OutputRedirect::Flush() { diff --git a/test/posix-test.cc b/test/posix-test.cc index d5a42b4a..3635d929 100644 --- a/test/posix-test.cc +++ b/test/posix-test.cc @@ -41,6 +41,7 @@ int fdopen_count; int fileno_count; int read_count; int write_count; +int pipe_count; } #define EMULATE_EINTR(func, error_result) \ @@ -101,6 +102,11 @@ test::ssize_t test::write(int fildes, const void *buf, test::size_t nbyte) { return ::write(fildes, buf, nbyte); } +int test::pipe(int fildes[2]) { + EMULATE_EINTR(pipe, -1); + return ::pipe(fildes); +} + #ifndef _WIN32 # define EXPECT_RETRY(statement, func, message) \ func##_count = 1; \ @@ -180,10 +186,12 @@ TEST(FileTest, WriteRetry) { #endif } -TEST(FileTest, DupRetry) { +TEST(FileTest, DupNoRetry) { int stdout_fd = fileno(stdout); - EXPECT_RETRY(File::dup(stdout_fd), dup, + dup_count = 1; + EXPECT_SYSTEM_ERROR(File::dup(stdout_fd), EINTR, str(fmt::Format("cannot duplicate file descriptor {}") << stdout_fd)); + dup_count = 0; } TEST(FileTest, Dup2Retry) { @@ -193,5 +201,35 @@ TEST(FileTest, Dup2Retry) { << f1.descriptor() << f2.descriptor())); } -// TODO: test retry on EINTR in dup2, pipe, fdopen +TEST(FileTest, Dup2NoExceptRetry) { + File f1 = File::dup(fileno(stdout)), f2 = File::dup(fileno(stdout)); + ErrorCode ec; + dup2_count = 1; + f1.dup2(f2.descriptor(), ec); +#ifndef _WIN32 + EXPECT_EQ(4, dup2_count); +#else + EXPECT_EQ(EINTR, ec.get()); +#endif + dup2_count = 0; +} + +TEST(FileTest, PipeNoRetry) { + File read_end, write_end; + pipe_count = 1; + EXPECT_SYSTEM_ERROR( + File::pipe(read_end, write_end), EINTR, "cannot create pipe"); + pipe_count = 0; +} + +TEST(FileTest, FdopenNoRetry) { + File read_end, write_end; + File::pipe(read_end, write_end); + fdopen_count = 1; + EXPECT_SYSTEM_ERROR(read_end.fdopen("r"), + EINTR, "cannot associate stream with file descriptor"); + fdopen_count = 0; +} + +// TODO: test retry on EINTR in fclose & fileno // TODO: test ConvertRWCount diff --git a/test/posix-test.h b/test/posix-test.h index 11d2124f..5ae30ecd 100644 --- a/test/posix-test.h +++ b/test/posix-test.h @@ -56,6 +56,8 @@ int fileno(FILE *stream); ssize_t read(int fildes, void *buf, size_t nbyte); ssize_t write(int fildes, const void *buf, size_t nbyte); +int pipe(int fildes[2]); + } // namespace test #define FMT_POSIX_CALL(call) test::call