| #include "internal_sys_mock.hpp" |
| #include "io.hpp" |
| |
| #include <sys/mman.h> |
| |
| #include <memory> |
| |
| #include <gmock/gmock.h> |
| #include <gtest/gtest.h> |
| |
| namespace host_tool |
| { |
| namespace |
| { |
| |
| using ::testing::_; |
| using ::testing::Eq; |
| using ::testing::Return; |
| using ::testing::StrEq; |
| |
| class DevMemTest : public ::testing::Test |
| { |
| protected: |
| DevMemTest() : devmem(std::make_unique<DevMemDevice>(&sys_mock)) |
| {} |
| |
| internal::InternalSysMock sys_mock; |
| std::unique_ptr<DevMemDevice> devmem; |
| }; |
| |
| TEST_F(DevMemTest, OpenFromReadFails) |
| { |
| EXPECT_CALL(sys_mock, open(_, _)).WillOnce(Return(-1)); |
| |
| char destination; |
| EXPECT_FALSE(devmem->read(/*offset*/ 0, /*length*/ 1, &destination)); |
| } |
| |
| TEST_F(DevMemTest, MmapFromReadFails) |
| { |
| int fd = 1; |
| EXPECT_CALL(sys_mock, open(_, _)).WillOnce(Return(fd)); |
| EXPECT_CALL(sys_mock, getpagesize()).WillOnce(Return(4096)); |
| EXPECT_CALL(sys_mock, mmap(0, _, _, _, fd, _)).WillOnce(Return(MAP_FAILED)); |
| EXPECT_CALL(sys_mock, close(fd)); |
| |
| char destination; |
| EXPECT_FALSE(devmem->read(/*offset*/ 0, /*length*/ 1, &destination)); |
| } |
| |
| TEST_F(DevMemTest, CopiesOutOfMmap) |
| { |
| int fd = 1; |
| char source = 'a'; |
| EXPECT_CALL(sys_mock, open(_, _)).WillOnce(Return(fd)); |
| EXPECT_CALL(sys_mock, getpagesize()).WillOnce(Return(4096)); |
| EXPECT_CALL(sys_mock, mmap(0, _, _, _, fd, _)).WillOnce(Return(&source)); |
| EXPECT_CALL(sys_mock, munmap(_, _)); |
| EXPECT_CALL(sys_mock, close(fd)); |
| |
| char destination = 'b'; |
| EXPECT_TRUE(devmem->read(/*offset*/ 0, /*length*/ 1, &destination)); |
| EXPECT_THAT(destination, Eq('a')); |
| } |
| |
| TEST_F(DevMemTest, OpenFromWriteFails) |
| { |
| EXPECT_CALL(sys_mock, open(_, _)).WillOnce(Return(-1)); |
| |
| char source; |
| EXPECT_FALSE(devmem->write(/*offset*/ 0, /*length*/ 1, &source)); |
| } |
| |
| TEST_F(DevMemTest, MmapFromWriteFails) |
| { |
| int fd = 1; |
| EXPECT_CALL(sys_mock, open(_, _)).WillOnce(Return(fd)); |
| EXPECT_CALL(sys_mock, getpagesize()).WillOnce(Return(4096)); |
| EXPECT_CALL(sys_mock, mmap(0, _, _, _, fd, _)).WillOnce(Return(MAP_FAILED)); |
| EXPECT_CALL(sys_mock, close(fd)); |
| |
| char source; |
| EXPECT_FALSE(devmem->write(/*offset*/ 0, /*length*/ 1, &source)); |
| } |
| |
| TEST_F(DevMemTest, CopiesIntoMmap) |
| { |
| int fd = 1; |
| char destination = 'b'; |
| EXPECT_CALL(sys_mock, open(_, _)).WillOnce(Return(fd)); |
| EXPECT_CALL(sys_mock, getpagesize()).WillOnce(Return(4096)); |
| EXPECT_CALL(sys_mock, mmap(0, _, _, _, fd, _)) |
| .WillOnce(Return(&destination)); |
| EXPECT_CALL(sys_mock, munmap(_, _)); |
| EXPECT_CALL(sys_mock, close(fd)); |
| |
| char source = 'a'; |
| EXPECT_TRUE(devmem->write(/*offset*/ 0, /*length*/ 1, &source)); |
| EXPECT_THAT(destination, Eq('a')); |
| } |
| |
| class PpcMemTest : public ::testing::Test |
| { |
| protected: |
| static constexpr char path[] = "/dev/fun"; |
| |
| PpcMemTest() : devmem(std::make_unique<PpcMemDevice>(path, &sys_mock)) |
| {} |
| |
| internal::InternalSysMock sys_mock; |
| std::unique_ptr<PpcMemDevice> devmem; |
| }; |
| |
| TEST_F(PpcMemTest, OpenFromReadFails) |
| { |
| EXPECT_CALL(sys_mock, open(StrEq(path), _)).WillOnce(Return(-1)); |
| |
| char destination = 'b'; |
| EXPECT_FALSE(devmem->read(/*offset*/ 0, /*length*/ 1, &destination)); |
| } |
| |
| TEST_F(PpcMemTest, PreadFails) |
| { |
| int fd = 1; |
| EXPECT_CALL(sys_mock, open(StrEq(path), _)).WillOnce(Return(fd)); |
| EXPECT_CALL(sys_mock, pread(fd, _, 1, 0)).WillOnce(Return(-1)); |
| |
| char destination = 'b'; |
| EXPECT_FALSE(devmem->read(/*offset*/ 0, /*length*/ 1, &destination)); |
| } |
| |
| TEST_F(PpcMemTest, PreadReadWorks) |
| { |
| int fd = 1; |
| EXPECT_CALL(sys_mock, open(StrEq(path), _)).WillOnce(Return(fd)); |
| EXPECT_CALL(sys_mock, pread(fd, _, 1, 0)).WillOnce(Return(0)); |
| EXPECT_CALL(sys_mock, close(fd)); |
| |
| /* Test does not validate byte is copied because that's part of pread and |
| * not the code. |
| */ |
| char destination = 'b'; |
| EXPECT_TRUE(devmem->read(/*offset*/ 0, /*length*/ 1, &destination)); |
| } |
| |
| TEST_F(PpcMemTest, OpenFromWriteFails) |
| { |
| EXPECT_CALL(sys_mock, open(StrEq(path), _)).WillOnce(Return(-1)); |
| |
| char source = 'a'; |
| EXPECT_FALSE(devmem->write(/*offset*/ 0, /*length*/ 1, &source)); |
| } |
| |
| TEST_F(PpcMemTest, PwriteFails) |
| { |
| int fd = 1; |
| EXPECT_CALL(sys_mock, open(StrEq(path), _)).WillOnce(Return(fd)); |
| EXPECT_CALL(sys_mock, pwrite(fd, _, 1, 0)).WillOnce(Return(-1)); |
| |
| char source = 'a'; |
| EXPECT_FALSE(devmem->write(/*offset*/ 0, /*length*/ 1, &source)); |
| } |
| |
| TEST_F(PpcMemTest, PwriteWorks) |
| { |
| int fd = 1; |
| EXPECT_CALL(sys_mock, open(StrEq(path), _)).WillOnce(Return(fd)); |
| EXPECT_CALL(sys_mock, pwrite(fd, _, 1, 0)).WillOnce(Return(0)); |
| |
| /* Test does not validate byte is copied because that's part of pwrite and |
| * not the code. |
| */ |
| char source = 'a'; |
| EXPECT_TRUE(devmem->write(/*offset*/ 0, /*length*/ 1, &source)); |
| } |
| |
| } // namespace |
| } // namespace host_tool |