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