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:
DevMemTest()24 DevMemTest() : devmem(std::make_unique<DevMemDevice>(&sys_mock)) {}
25
26 internal::InternalSysMock sys_mock;
27 std::unique_ptr<DevMemDevice> devmem;
28 };
29
TEST_F(DevMemTest,OpenFromReadFails)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
TEST_F(DevMemTest,MmapFromReadFails)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
TEST_F(DevMemTest,CopiesOutOfMmap)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
TEST_F(DevMemTest,OpenFromWriteFails)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
TEST_F(DevMemTest,MmapFromWriteFails)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
TEST_F(DevMemTest,CopiesIntoMmap)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
PpcMemTest()106 PpcMemTest() : devmem(std::make_unique<PpcMemDevice>(path, &sys_mock)) {}
107
108 internal::InternalSysMock sys_mock;
109 std::unique_ptr<PpcMemDevice> devmem;
110 };
111
TEST_F(PpcMemTest,OpenFromReadFails)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
TEST_F(PpcMemTest,PreadFails)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
TEST_F(PpcMemTest,PreadReadWorks)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
TEST_F(PpcMemTest,OpenFromWriteFails)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
TEST_F(PpcMemTest,PwriteFails)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
TEST_F(PpcMemTest,PwriteWorks)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