Add BufferedFile::fileno.

This commit is contained in:
Victor Zverovich 2014-05-06 06:45:53 -07:00
parent d286efd3d2
commit fb4ccac951
3 changed files with 51 additions and 33 deletions

View File

@ -255,6 +255,32 @@ bool IsClosed(int fd) {
return result == -1 && errno == EBADF;
}
// Attempts to read count characters from a file.
std::string Read(File &f, std::size_t count) {
std::string buffer(count, '\0');
std::streamsize offset = 0, n = 0;
do {
n = f.read(&buffer[offset], count - offset);
offset += n;
} while (offset < count && n != 0);
buffer.resize(offset);
return buffer;
}
// Attempts to write a string to a file.
void Write(File &f, fmt::StringRef s) {
std::size_t num_chars_left = s.size();
const char *ptr = s.c_str();
do {
std::streamsize count = f.write(ptr, num_chars_left);
ptr += count;
num_chars_left -= count;
} while (num_chars_left != 0);
}
#define EXPECT_READ(file, expected_content) \
EXPECT_EQ(expected_content, Read(file, std::strlen(expected_content)))
TEST(ErrorCodeTest, Ctor) {
EXPECT_EQ(0, ErrorCode().get());
EXPECT_EQ(42, ErrorCode(42).get());
@ -294,7 +320,7 @@ TEST(BufferedFileTest, MoveAssignment) {
TEST(BufferedFileTest, MoveAssignmentClosesFile) {
BufferedFile bf = OpenFile(".travis.yml");
BufferedFile bf2 = OpenFile("CMakeLists.txt");
int old_fd = fileno(bf2.get());
int old_fd = bf2.fileno();
bf2 = std::move(bf);
EXPECT_TRUE(IsClosed(old_fd));
}
@ -314,7 +340,7 @@ TEST(BufferedFileTest, MoveFromTemporaryInAssignment) {
TEST(BufferedFileTest, MoveFromTemporaryInAssignmentClosesFile) {
BufferedFile f = OpenFile(".travis.yml");
int old_fd = fileno(f.get());
int old_fd = f.fileno();
f = OpenFile(".travis.yml");
EXPECT_TRUE(IsClosed(old_fd));
}
@ -323,7 +349,7 @@ TEST(BufferedFileTest, CloseFileInDtor) {
int fd = 0;
{
BufferedFile f = OpenFile(".travis.yml");
fd = fileno(f.get());
fd = f.fileno();
}
EXPECT_TRUE(IsClosed(fd));
}
@ -335,14 +361,14 @@ TEST(BufferedFileTest, CloseErrorInDtor) {
// the system may recycle closed file descriptor when redirecting the
// output in EXPECT_STDERR and the second close will break output
// redirection.
close(fileno(f->get()));
close(f->fileno());
SUPPRESS_ASSERT(delete f);
}, FormatSystemErrorMessage(EBADF, "cannot close file") + "\n");
}
TEST(BufferedFileTest, Close) {
BufferedFile f = OpenFile(".travis.yml");
int fd = fileno(f.get());
int fd = f.fileno();
f.close();
EXPECT_TRUE(f.get() == 0);
EXPECT_TRUE(IsClosed(fd));
@ -350,11 +376,20 @@ TEST(BufferedFileTest, Close) {
TEST(BufferedFileTest, CloseError) {
BufferedFile f = OpenFile(".travis.yml");
close(fileno(f.get()));
close(f.fileno());
EXPECT_SYSTEM_ERROR_NOASSERT(f.close(), EBADF, "cannot close file");
EXPECT_TRUE(f.get() == 0);
}
TEST(BufferedFileTest, Fileno) {
BufferedFile f;
EXPECT_DEATH(f.fileno(), "");
f = OpenFile(".travis.yml");
EXPECT_TRUE(f.fileno() != -1);
File dup = File::dup(f.fileno());
EXPECT_READ(dup, "language: cpp");
}
TEST(FileTest, DefaultCtor) {
File f;
EXPECT_EQ(-1, f.descriptor());
@ -460,32 +495,6 @@ TEST(FileTest, CloseError) {
EXPECT_EQ(-1, f.descriptor());
}
// Attempts to read count characters from a file.
std::string Read(File &f, std::size_t count) {
std::string buffer(count, '\0');
std::streamsize offset = 0, n = 0;
do {
n = f.read(&buffer[offset], count - offset);
offset += n;
} while (offset < count && n != 0);
buffer.resize(offset);
return buffer;
}
// Attempts to write a string to a file.
void Write(File &f, fmt::StringRef s) {
std::size_t num_chars_left = s.size();
const char *ptr = s.c_str();
do {
std::streamsize count = f.write(ptr, num_chars_left);
ptr += count;
num_chars_left -= count;
} while (num_chars_left != 0);
}
#define EXPECT_READ(file, expected_content) \
EXPECT_EQ(expected_content, Read(file, std::strlen(expected_content)))
TEST(FileTest, Read) {
File f(".travis.yml", File::RDONLY);
EXPECT_READ(f, "language: cpp");
@ -601,7 +610,7 @@ TEST(OutputRedirectTest, FlushErrorInCtor) {
TEST(OutputRedirectTest, DupErrorInCtor) {
BufferedFile f = OpenFile(".travis.yml");
int fd = fileno(f.get());
int fd = f.fileno();
File dup = File::dup(fd);
close(fd);
OutputRedirect *redir = 0;

View File

@ -65,6 +65,13 @@ void BufferedFile::close() {
fmt::ThrowSystemError(errno, "cannot close file");
}
int BufferedFile::fileno() const {
int fd = ::FMT_POSIX(fileno(file_));
if (fd == -1)
fmt::ThrowSystemError(errno, "cannot get file descriptor");
return fd;
}
File::File(const char *path, int oflag) {
int mode = S_IRUSR | S_IWUSR;
#ifdef _WIN32

View File

@ -191,6 +191,8 @@ class BufferedFile {
// Returns the pointer to a FILE object representing this file.
std::FILE *get() const { return file_; }
int fileno() const;
};
// A file. Closed file is represented by a File object with descriptor -1.