From 949c3c5df40f2740090178b92268dd9620d55054 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Fri, 12 Sep 2014 11:12:22 -0700 Subject: [PATCH] Test if File::size can handle maximum file size. --- posix.cc | 4 ++-- test/posix-test.cc | 49 +++++++++++++++++++++++++++++++++++++++------- test/posix-test.h | 8 ++++++++ 3 files changed, 52 insertions(+), 9 deletions(-) diff --git a/posix.cc b/posix.cc index 7ef6b7b9..0608959b 100644 --- a/posix.cc +++ b/posix.cc @@ -145,7 +145,7 @@ void fmt::File::close() { fmt::LongLong fmt::File::size() const { #ifdef _WIN32 LARGE_INTEGER size = {}; - if (!GetFileSizeEx(_get_osfhandle(fd_), &size)) + if (!FMT_SYSTEM(GetFileSizeEx(_get_osfhandle(fd_), &size))) throw WindowsError(GetLastError(), "cannot get file size"); FMT_STATIC_ASSERT(sizeof(fmt::LongLong) >= sizeof(size.QuadPart), "return type of File::size is not large enough"); @@ -153,7 +153,7 @@ fmt::LongLong fmt::File::size() const { #else typedef struct stat Stat; Stat file_stat = Stat(); - if (fstat(fd_, &file_stat) == -1) + if (FMT_POSIX_CALL(fstat(fd_, &file_stat)) == -1) throw SystemError(errno, "cannot get file attributes"); FMT_STATIC_ASSERT(sizeof(fmt::LongLong) >= sizeof(file_stat.st_size), "return type of File::size is not large enough"); diff --git a/test/posix-test.cc b/test/posix-test.cc index 7b6c3f2e..c995de06 100644 --- a/test/posix-test.cc +++ b/test/posix-test.cc @@ -55,6 +55,15 @@ int fclose_count; int fileno_count; std::size_t read_nbyte; std::size_t write_nbyte; +bool increase_file_size; + +std::string TEST_FILE_CONTENT = "top secret, destroy before reading"; + +void WriteTestFile() { + BufferedFile bf("test", "w"); + bf.print(TEST_FILE_CONTENT); + bf.close(); +} } #define EMULATE_EINTR(func, error_result) \ @@ -70,12 +79,30 @@ int test::open(const char *path, int oflag, int mode) { EMULATE_EINTR(open, -1); return ::open(path, oflag, mode); } + +static off_t max_file_size() { return std::numeric_limits::max(); } + +int test::fstat(int fd, struct stat *buf) { + int result = ::fstat(fd, buf); + if (increase_file_size) + buf->st_size = max_file_size(); + return result; +} #else errno_t test::sopen_s( int* pfh, const char *filename, int oflag, int shflag, int pmode) { EMULATE_EINTR(open, EINTR); return _sopen_s(pfh, filename, oflag, shflag, pmode); } + +static LONGLONG max_file_size() {return std::numeric_limits::max(); } + +BOOL test::GetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize) { + BOOL result = GetFileSizeEx(hFile, lpFileSize); + if (increase_file_size) + lpFileSize->QuadPart = max_file_size(); + return result; +} #endif int test::close(int fildes) { @@ -195,16 +222,24 @@ TEST(FileTest, CloseNoRetry) { } TEST(FileTest, Size) { - BufferedFile bf("test", "w"); - std::string content = "top secret, destroy before reading"; - bf.print(content); - bf.close(); + WriteTestFile(); File f("test", File::RDONLY); - EXPECT_EQ(content.size(), f.size()); - // TODO: test if size can handle large file sizes - // TODO: test FMT_STATIC_ASSERT + EXPECT_EQ(TEST_FILE_CONTENT.size(), f.size()); + f.close(); + EXPECT_SYSTEM_ERROR(f.size(), EBADF, "cannot get file attributes"); } +TEST(FileTest, MaxSize) { + WriteTestFile(); + File f("test", File::RDONLY); + increase_file_size = true; + EXPECT_GE(f.size(), 0); + EXPECT_EQ(max_file_size(), f.size()); + increase_file_size = false; +} + +// TODO: test FMT_STATIC_ASSERT + TEST(FileTest, ReadRetry) { File read_end, write_end; File::pipe(read_end, write_end); diff --git a/test/posix-test.h b/test/posix-test.h index 355409fd..e960afc3 100644 --- a/test/posix-test.h +++ b/test/posix-test.h @@ -31,6 +31,12 @@ #include #include +#ifndef _WIN32 +struct stat; +#else +# include +#endif + namespace test { #ifndef _WIN32 @@ -38,11 +44,13 @@ namespace test { typedef size_t size_t; typedef ssize_t ssize_t; int open(const char *path, int oflag, int mode); +int fstat(int fd, struct stat *buf); #else typedef unsigned size_t; typedef int ssize_t; errno_t sopen_s( int* pfh, const char *filename, int oflag, int shflag, int pmode); +BOOL GetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize); #endif int close(int fildes);