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