From a7e0d672a7d797f0f3e6dbb5553396e98d3ad299 Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 13 May 2019 08:48:53 +0800 Subject: [PATCH] Cover kernel file writer. --- trunk/src/kernel/srs_kernel_file.cpp | 15 ++- trunk/src/kernel/srs_kernel_file.hpp | 5 + trunk/src/utest/srs_utest_kernel.cpp | 135 +++++++++++++++++++++++++++ 3 files changed, 150 insertions(+), 5 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_file.cpp b/trunk/src/kernel/srs_kernel_file.cpp index 46e229678..67eafd557 100644 --- a/trunk/src/kernel/srs_kernel_file.cpp +++ b/trunk/src/kernel/srs_kernel_file.cpp @@ -36,6 +36,11 @@ using namespace std; #include #include +// For utest to mock it. +_srs_open_t _srs_open_fn = ::open; +_srs_write_t _srs_write_fn = ::write; +_srs_lseek_t _srs_lseek_fn = ::lseek; + SrsFileWriter::SrsFileWriter() { fd = -1; @@ -57,7 +62,7 @@ srs_error_t SrsFileWriter::open(string p) int flags = O_CREAT|O_WRONLY|O_TRUNC; mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH; - if ((fd = ::open(p.c_str(), flags, mode)) < 0) { + if ((fd = _srs_open_fn(p.c_str(), flags, mode)) < 0) { return srs_error_new(ERROR_SYSTEM_FILE_OPENE, "open file %s failed", p.c_str()); } @@ -107,13 +112,13 @@ bool SrsFileWriter::is_open() void SrsFileWriter::seek2(int64_t offset) { - off_t r0 = ::lseek(fd, (off_t)offset, SEEK_SET); + off_t r0 = _srs_lseek_fn(fd, (off_t)offset, SEEK_SET); srs_assert(r0 != -1); } int64_t SrsFileWriter::tellg() { - return (int64_t)::lseek(fd, 0, SEEK_CUR); + return (int64_t)_srs_lseek_fn(fd, 0, SEEK_CUR); } srs_error_t SrsFileWriter::write(void* buf, size_t count, ssize_t* pnwrite) @@ -122,7 +127,7 @@ srs_error_t SrsFileWriter::write(void* buf, size_t count, ssize_t* pnwrite) ssize_t nwrite; // TODO: FIXME: use st_write. - if ((nwrite = ::write(fd, buf, count)) < 0) { + if ((nwrite = _srs_write_fn(fd, buf, count)) < 0) { return srs_error_new(ERROR_SYSTEM_FILE_WRITE, "write to file %s failed", path.c_str()); } @@ -156,7 +161,7 @@ srs_error_t SrsFileWriter::writev(const iovec* iov, int iovcnt, ssize_t* pnwrite srs_error_t SrsFileWriter::lseek(off_t offset, int whence, off_t* seeked) { - off_t sk = ::lseek(fd, offset, whence); + off_t sk = _srs_lseek_fn(fd, offset, whence); if (sk < 0) { return srs_error_new(ERROR_SYSTEM_FILE_SEEK, "seek file"); } diff --git a/trunk/src/kernel/srs_kernel_file.hpp b/trunk/src/kernel/srs_kernel_file.hpp index 770b645a7..acf2d5d0e 100644 --- a/trunk/src/kernel/srs_kernel_file.hpp +++ b/trunk/src/kernel/srs_kernel_file.hpp @@ -108,5 +108,10 @@ public: virtual srs_error_t lseek(off_t offset, int whence, off_t* seeked); }; +// For utest to mock it. +typedef int (*_srs_open_t)(const char* path, int oflag, ...); +typedef ssize_t (*_srs_write_t)(int fildes, const void* buf, size_t nbyte); +typedef off_t (*_srs_lseek_t)(int fildes, off_t offset, int whence); + #endif diff --git a/trunk/src/utest/srs_utest_kernel.cpp b/trunk/src/utest/srs_utest_kernel.cpp index 990754ce1..3c61e58c3 100644 --- a/trunk/src/utest/srs_utest_kernel.cpp +++ b/trunk/src/utest/srs_utest_kernel.cpp @@ -2971,6 +2971,141 @@ VOID TEST(KernelFileTest, FileWriteReader) } } +// Mock the system call hooks. +extern _srs_open_t _srs_open_fn; +extern _srs_write_t _srs_write_fn; +extern _srs_lseek_t _srs_lseek_fn; + +int mock_open(const char* /*path*/, int /*oflag*/, ...) { + return -1; +} + +ssize_t mock_write(int /*fildes*/, const void* /*buf*/, size_t /*nbyte*/) { + return -1; +} + +off_t mock_lseek(int /*fildes*/, off_t /*offset*/, int /*whence*/) { + return -1; +} + +class MockSystemIO +{ +private: + _srs_open_t oo; + _srs_write_t ow; + _srs_lseek_t os; +public: + MockSystemIO(_srs_open_t o = NULL, _srs_write_t w = NULL, _srs_lseek_t s = NULL) { + oo = _srs_open_fn; + ow = _srs_write_fn; + os = _srs_lseek_fn; + if (o) { + _srs_open_fn = o; + } + if (w) { + _srs_write_fn = w; + } + if (s) { + _srs_lseek_fn = s; + } + } + virtual ~MockSystemIO() { + if (oo) { + _srs_open_fn = oo; + } + if (ow) { + _srs_write_fn = ow; + } + if (os) { + _srs_lseek_fn = os; + } + } +}; + +VOID TEST(KernelFileTest, WriteSpecialCase) +{ + srs_error_t err; + + // Should fail when open multiple times. + if (true) { + SrsFileWriter f; + HELPER_EXPECT_SUCCESS(f.open("/dev/null")); + HELPER_EXPECT_FAILED(f.open("/dev/null")); + } + + // Should fail when open multiple times. + if (true) { + SrsFileWriter f; + HELPER_EXPECT_SUCCESS(f.open_append("/dev/null")); + HELPER_EXPECT_FAILED(f.open_append("/dev/null")); + } + + // Always fail. + if (true) { + MockSystemIO _mockio(mock_open); + SrsFileWriter f; + HELPER_EXPECT_FAILED(f.open("/dev/null")); + HELPER_EXPECT_FAILED(f.open("/dev/null")); + } + if (true) { + MockSystemIO _mockio(mock_open); + SrsFileWriter f; + HELPER_EXPECT_FAILED(f.open_append("/dev/null")); + HELPER_EXPECT_FAILED(f.open_append("/dev/null")); + } + + // Should ok for write, writev or lseek. + if (true) { + SrsFileWriter f; + HELPER_EXPECT_SUCCESS(f.open("/dev/null")); + + ssize_t nn = 0; + HELPER_EXPECT_SUCCESS(f.write((void*)"Hello", 5, &nn)); + EXPECT_EQ(5, nn); + + iovec iovs[3]; + iovs[0].iov_base = (void*)"H"; + iovs[0].iov_len = 1; + iovs[1].iov_base = (void*)"e"; + iovs[1].iov_len = 1; + iovs[2].iov_base = (void*)"llo"; + iovs[2].iov_len = 3; + nn = 0; + HELPER_EXPECT_SUCCESS(f.writev(iovs, 3, &nn)); + EXPECT_EQ(5, nn); + + off_t seeked = 0; + HELPER_EXPECT_SUCCESS(f.lseek(0, SEEK_CUR, &seeked)); + EXPECT_EQ(0, seeked); + } + + // Always fail. + if (true) { + MockSystemIO _mockio(NULL, mock_write); + SrsFileWriter f; + HELPER_EXPECT_SUCCESS(f.open("/dev/null")); + + ssize_t nn = 0; + HELPER_EXPECT_FAILED(f.write((void*)"Hello", 5, &nn)); + + iovec iovs[3]; + iovs[0].iov_base = (void*)"H"; + iovs[0].iov_len = 1; + iovs[1].iov_base = (void*)"e"; + iovs[1].iov_len = 1; + iovs[2].iov_base = (void*)"llo"; + iovs[2].iov_len = 3; + HELPER_EXPECT_FAILED(f.writev(iovs, 3, NULL)); + } + if (true) { + MockSystemIO _mockio(NULL, NULL, mock_lseek); + SrsFileWriter f; + HELPER_EXPECT_SUCCESS(f.open("/dev/null")); + + HELPER_EXPECT_FAILED(f.lseek(0, 0, NULL)); + } +} + VOID TEST(KernelFLVTest, CoverAll) { if (true) {