1 #include "internal_sys_mock.hpp" 2 #include "io.hpp" 3 4 #include <sys/mman.h> 5 6 #include <memory> 7 8 #include <gmock/gmock.h> 9 #include <gtest/gtest.h> 10 11 namespace host_tool 12 { 13 namespace 14 { 15 16 using ::testing::_; 17 using ::testing::Eq; 18 using ::testing::Return; 19 using ::testing::StrEq; 20 21 class DevMemTest : public ::testing::Test 22 { 23 protected: 24 DevMemTest() : devmem(std::make_unique<DevMemDevice>(&sys_mock)) {} 25 26 internal::InternalSysMock sys_mock; 27 std::unique_ptr<DevMemDevice> devmem; 28 }; 29 30 TEST_F(DevMemTest, OpenFromReadFails) 31 { 32 EXPECT_CALL(sys_mock, open(_, _)).WillOnce(Return(-1)); 33 34 char destination; 35 EXPECT_FALSE(devmem->read(/*offset*/ 0, /*length*/ 1, &destination)); 36 } 37 38 TEST_F(DevMemTest, MmapFromReadFails) 39 { 40 int fd = 1; 41 EXPECT_CALL(sys_mock, open(_, _)).WillOnce(Return(fd)); 42 EXPECT_CALL(sys_mock, getpagesize()).WillOnce(Return(4096)); 43 EXPECT_CALL(sys_mock, mmap(0, _, _, _, fd, _)).WillOnce(Return(MAP_FAILED)); 44 EXPECT_CALL(sys_mock, close(fd)); 45 46 char destination; 47 EXPECT_FALSE(devmem->read(/*offset*/ 0, /*length*/ 1, &destination)); 48 } 49 50 TEST_F(DevMemTest, CopiesOutOfMmap) 51 { 52 int fd = 1; 53 char source = 'a'; 54 EXPECT_CALL(sys_mock, open(_, _)).WillOnce(Return(fd)); 55 EXPECT_CALL(sys_mock, getpagesize()).WillOnce(Return(4096)); 56 EXPECT_CALL(sys_mock, mmap(0, _, _, _, fd, _)).WillOnce(Return(&source)); 57 EXPECT_CALL(sys_mock, munmap(_, _)); 58 EXPECT_CALL(sys_mock, close(fd)); 59 60 char destination = 'b'; 61 EXPECT_TRUE(devmem->read(/*offset*/ 0, /*length*/ 1, &destination)); 62 EXPECT_THAT(destination, Eq('a')); 63 } 64 65 TEST_F(DevMemTest, OpenFromWriteFails) 66 { 67 EXPECT_CALL(sys_mock, open(_, _)).WillOnce(Return(-1)); 68 69 char source; 70 EXPECT_FALSE(devmem->write(/*offset*/ 0, /*length*/ 1, &source)); 71 } 72 73 TEST_F(DevMemTest, MmapFromWriteFails) 74 { 75 int fd = 1; 76 EXPECT_CALL(sys_mock, open(_, _)).WillOnce(Return(fd)); 77 EXPECT_CALL(sys_mock, getpagesize()).WillOnce(Return(4096)); 78 EXPECT_CALL(sys_mock, mmap(0, _, _, _, fd, _)).WillOnce(Return(MAP_FAILED)); 79 EXPECT_CALL(sys_mock, close(fd)); 80 81 char source; 82 EXPECT_FALSE(devmem->write(/*offset*/ 0, /*length*/ 1, &source)); 83 } 84 85 TEST_F(DevMemTest, CopiesIntoMmap) 86 { 87 int fd = 1; 88 char destination = 'b'; 89 EXPECT_CALL(sys_mock, open(_, _)).WillOnce(Return(fd)); 90 EXPECT_CALL(sys_mock, getpagesize()).WillOnce(Return(4096)); 91 EXPECT_CALL(sys_mock, mmap(0, _, _, _, fd, _)) 92 .WillOnce(Return(&destination)); 93 EXPECT_CALL(sys_mock, munmap(_, _)); 94 EXPECT_CALL(sys_mock, close(fd)); 95 96 char source = 'a'; 97 EXPECT_TRUE(devmem->write(/*offset*/ 0, /*length*/ 1, &source)); 98 EXPECT_THAT(destination, Eq('a')); 99 } 100 101 class PpcMemTest : public ::testing::Test 102 { 103 protected: 104 static constexpr char path[] = "/dev/fun"; 105 106 PpcMemTest() : devmem(std::make_unique<PpcMemDevice>(path, &sys_mock)) {} 107 108 internal::InternalSysMock sys_mock; 109 std::unique_ptr<PpcMemDevice> devmem; 110 }; 111 112 TEST_F(PpcMemTest, OpenFromReadFails) 113 { 114 EXPECT_CALL(sys_mock, open(StrEq(path), _)).WillOnce(Return(-1)); 115 116 char destination = 'b'; 117 EXPECT_FALSE(devmem->read(/*offset*/ 0, /*length*/ 1, &destination)); 118 } 119 120 TEST_F(PpcMemTest, PreadFails) 121 { 122 int fd = 1; 123 EXPECT_CALL(sys_mock, open(StrEq(path), _)).WillOnce(Return(fd)); 124 EXPECT_CALL(sys_mock, pread(fd, _, 1, 0)).WillOnce(Return(-1)); 125 126 char destination = 'b'; 127 EXPECT_FALSE(devmem->read(/*offset*/ 0, /*length*/ 1, &destination)); 128 } 129 130 TEST_F(PpcMemTest, PreadReadWorks) 131 { 132 int fd = 1; 133 EXPECT_CALL(sys_mock, open(StrEq(path), _)).WillOnce(Return(fd)); 134 EXPECT_CALL(sys_mock, pread(fd, _, 1, 0)).WillOnce(Return(0)); 135 EXPECT_CALL(sys_mock, close(fd)); 136 137 /* Test does not validate byte is copied because that's part of pread and 138 * not the code. 139 */ 140 char destination = 'b'; 141 EXPECT_TRUE(devmem->read(/*offset*/ 0, /*length*/ 1, &destination)); 142 } 143 144 TEST_F(PpcMemTest, OpenFromWriteFails) 145 { 146 EXPECT_CALL(sys_mock, open(StrEq(path), _)).WillOnce(Return(-1)); 147 148 char source = 'a'; 149 EXPECT_FALSE(devmem->write(/*offset*/ 0, /*length*/ 1, &source)); 150 } 151 152 TEST_F(PpcMemTest, PwriteFails) 153 { 154 int fd = 1; 155 EXPECT_CALL(sys_mock, open(StrEq(path), _)).WillOnce(Return(fd)); 156 EXPECT_CALL(sys_mock, pwrite(fd, _, 1, 0)).WillOnce(Return(-1)); 157 158 char source = 'a'; 159 EXPECT_FALSE(devmem->write(/*offset*/ 0, /*length*/ 1, &source)); 160 } 161 162 TEST_F(PpcMemTest, PwriteWorks) 163 { 164 int fd = 1; 165 EXPECT_CALL(sys_mock, open(StrEq(path), _)).WillOnce(Return(fd)); 166 EXPECT_CALL(sys_mock, pwrite(fd, _, 1, 0)).WillOnce(Return(0)); 167 168 /* Test does not validate byte is copied because that's part of pwrite and 169 * not the code. 170 */ 171 char source = 'a'; 172 EXPECT_TRUE(devmem->write(/*offset*/ 0, /*length*/ 1, &source)); 173 } 174 175 } // namespace 176 } // namespace host_tool 177