More posix tests.

This commit is contained in:
Victor Zverovich
2014-05-18 10:05:29 -07:00
parent e654f56210
commit f21fa23186
3 changed files with 58 additions and 10 deletions

View File

@ -136,8 +136,9 @@ std::streamsize File::write(const void *buffer, std::size_t count) {
} }
File File::dup(int fd) { File File::dup(int fd) {
int new_fd = 0; // Don't retry as dup doesn't return EINTR.
FMT_RETRY(new_fd, FMT_POSIX_CALL(dup(fd))); // http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html
int new_fd = FMT_POSIX_CALL(dup(fd));
if (new_fd == -1) if (new_fd == -1)
fmt::ThrowSystemError(errno, "cannot duplicate file descriptor {}") << fd; fmt::ThrowSystemError(errno, "cannot duplicate file descriptor {}") << fd;
return File(new_fd); return File(new_fd);
@ -168,10 +169,11 @@ void File::pipe(File &read_end, File &write_end) {
#ifdef _WIN32 #ifdef _WIN32
// Make the default pipe capacity same as on Linux 2.6.11+. // Make the default pipe capacity same as on Linux 2.6.11+.
enum { DEFAULT_CAPACITY = 65536 }; enum { DEFAULT_CAPACITY = 65536 };
int result = _pipe(fds, DEFAULT_CAPACITY, _O_BINARY); int result = FMT_POSIX_CALL(pipe(fds, DEFAULT_CAPACITY, _O_BINARY));
#else #else
// The pipe function doesn't return EINTR, so no need to retry. // Don't retry as the pipe function doesn't return EINTR.
int result = ::pipe(fds); // http://pubs.opengroup.org/onlinepubs/009696799/functions/pipe.html
int result = FMT_POSIX_CALL(pipe(fds));
#endif #endif
if (result != 0) if (result != 0)
fmt::ThrowSystemError(errno, "cannot create pipe"); 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 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; fd_ = -1;
return f; return file;
} }
void OutputRedirect::Flush() { void OutputRedirect::Flush() {

View File

@ -41,6 +41,7 @@ int fdopen_count;
int fileno_count; int fileno_count;
int read_count; int read_count;
int write_count; int write_count;
int pipe_count;
} }
#define EMULATE_EINTR(func, error_result) \ #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); return ::write(fildes, buf, nbyte);
} }
int test::pipe(int fildes[2]) {
EMULATE_EINTR(pipe, -1);
return ::pipe(fildes);
}
#ifndef _WIN32 #ifndef _WIN32
# define EXPECT_RETRY(statement, func, message) \ # define EXPECT_RETRY(statement, func, message) \
func##_count = 1; \ func##_count = 1; \
@ -180,10 +186,12 @@ TEST(FileTest, WriteRetry) {
#endif #endif
} }
TEST(FileTest, DupRetry) { TEST(FileTest, DupNoRetry) {
int stdout_fd = fileno(stdout); 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)); str(fmt::Format("cannot duplicate file descriptor {}") << stdout_fd));
dup_count = 0;
} }
TEST(FileTest, Dup2Retry) { TEST(FileTest, Dup2Retry) {
@ -193,5 +201,35 @@ TEST(FileTest, Dup2Retry) {
<< f1.descriptor() << f2.descriptor())); << 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 // TODO: test ConvertRWCount

View File

@ -56,6 +56,8 @@ int fileno(FILE *stream);
ssize_t read(int fildes, void *buf, size_t nbyte); ssize_t read(int fildes, void *buf, size_t nbyte);
ssize_t write(int fildes, const void *buf, size_t nbyte); ssize_t write(int fildes, const void *buf, size_t nbyte);
int pipe(int fildes[2]);
} // namespace test } // namespace test
#define FMT_POSIX_CALL(call) test::call #define FMT_POSIX_CALL(call) test::call