1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <gmock/gmock.h>
18 #include <gtest/gtest.h>
19 
20 #include "aidl/GpuCapacityNode.h"
21 
22 using testing::Invoke;
23 using testing::Return, testing::_, testing::Eq, testing::StrEq, testing::NiceMock;
24 
25 namespace aidl {
26 namespace google {
27 namespace hardware {
28 namespace power {
29 namespace impl {
30 namespace pixel {
31 
32 struct MockFdInterface : FdInterface {
33     MOCK_METHOD(int, open, (const char *, int), (const, final));
34     MOCK_METHOD(int, write, (int, const char *, size_t), (const, final));
35     MOCK_METHOD(ssize_t, read, (int, void *, size_t), (const, final));
36     MOCK_METHOD(off_t, lseek, (int, off_t, int), (const, final));
37     MOCK_METHOD(int, close, (int), (const, final));
38 };
39 
40 struct FdInterfaceWrapper : FdInterface {
FdInterfaceWrapperaidl::google::hardware::power::impl::pixel::FdInterfaceWrapper41     FdInterfaceWrapper(std::shared_ptr<FdInterface> const &wrapped) : wrapped_(wrapped) {}
42 
openaidl::google::hardware::power::impl::pixel::FdInterfaceWrapper43     int open(const char *path, int flags) const final { return wrapped_->open(path, flags); }
44 
writeaidl::google::hardware::power::impl::pixel::FdInterfaceWrapper45     int write(int fd, const char *data, size_t count) const final {
46         return wrapped_->write(fd, data, count);
47     }
readaidl::google::hardware::power::impl::pixel::FdInterfaceWrapper48     ssize_t read(int fd, void *data, size_t count) const final {
49         return wrapped_->read(fd, data, count);
50     }
lseekaidl::google::hardware::power::impl::pixel::FdInterfaceWrapper51     off_t lseek(int fd, off_t offset, int whence) const final {
52         return wrapped_->lseek(fd, offset, whence);
53     }
54 
closeaidl::google::hardware::power::impl::pixel::FdInterfaceWrapper55     int close(int fd) const final { return wrapped_->close(fd); }
56     std::shared_ptr<FdInterface> const wrapped_;
57 };
58 
59 struct GpuCapacityNodeTest : ::testing::Test {
GpuCapacityNodeTestaidl::google::hardware::power::impl::pixel::GpuCapacityNodeTest60     GpuCapacityNodeTest() : mock_fd_interface(std::make_shared<NiceMock<MockFdInterface>>()) {}
61     std::shared_ptr<MockFdInterface> mock_fd_interface;
62     std::string const path = "/path/example";
63     std::string const headroom_path = "/path/example/capacity_headroom";
64     std::string const freq_path = "/path/example/cur_freq";
65     int const fake_fd = 33;
66     int const another_fake_fd = 34;
67     int const invalid_fake_fd = -33;
68     Cycles const capacity{11503};
69     std::string const capacity_str = "11503";
70 };
71 
TEST_F(GpuCapacityNodeTest,OpensCorrectNode)72 TEST_F(GpuCapacityNodeTest, OpensCorrectNode) {
73     EXPECT_CALL(*mock_fd_interface, close(fake_fd)).Times(1).WillOnce(Return(0));
74     EXPECT_CALL(*mock_fd_interface, close(another_fake_fd)).Times(1).WillOnce(Return(0));
75     GpuCapacityNode capacity_node(std::make_unique<FdInterfaceWrapper>(mock_fd_interface), fake_fd,
76                                   another_fake_fd, path);
77 }
78 
TEST_F(GpuCapacityNodeTest,OpensCorrectNodeHelper)79 TEST_F(GpuCapacityNodeTest, OpensCorrectNodeHelper) {
80     EXPECT_CALL(*mock_fd_interface, open(StrEq(headroom_path), O_RDWR | O_CLOEXEC | O_NONBLOCK))
81             .Times(1)
82             .WillOnce(Return(fake_fd));
83     EXPECT_CALL(*mock_fd_interface, open(StrEq(freq_path), O_RDONLY | O_CLOEXEC | O_NONBLOCK))
84             .Times(1)
85             .WillOnce(Return(another_fake_fd));
86     EXPECT_CALL(*mock_fd_interface, close(another_fake_fd)).Times(1).WillOnce(Return(0));
87     EXPECT_CALL(*mock_fd_interface, close(fake_fd)).Times(1).WillOnce(Return(0));
88     auto const node = GpuCapacityNode::init_gpu_capacity_node(
89             std::make_unique<FdInterfaceWrapper>(mock_fd_interface), path);
90 }
91 
TEST_F(GpuCapacityNodeTest,node_open_helper_failure_one)92 TEST_F(GpuCapacityNodeTest, node_open_helper_failure_one) {
93     EXPECT_CALL(*mock_fd_interface, open(_, _)).Times(1).WillOnce(Return(invalid_fake_fd));
94     EXPECT_CALL(*mock_fd_interface, close(0)).Times(0);
95     auto const node = GpuCapacityNode::init_gpu_capacity_node(
96             std::make_unique<FdInterfaceWrapper>(mock_fd_interface), path);
97     EXPECT_THAT(node, testing::Eq(nullptr));
98 }
99 
TEST_F(GpuCapacityNodeTest,node_open_helper_failure_two)100 TEST_F(GpuCapacityNodeTest, node_open_helper_failure_two) {
101     testing::Sequence seq;
102     EXPECT_CALL(*mock_fd_interface, open(_, _)).InSequence(seq).WillOnce(Return(fake_fd));
103     EXPECT_CALL(*mock_fd_interface, open(_, _)).InSequence(seq).WillOnce(Return(invalid_fake_fd));
104     EXPECT_CALL(*mock_fd_interface, close(fake_fd)).Times(1);
105     auto const node = GpuCapacityNode::init_gpu_capacity_node(
106             std::make_unique<FdInterfaceWrapper>(mock_fd_interface), path);
107     EXPECT_THAT(node, testing::Eq(nullptr));
108 }
109 
TEST_F(GpuCapacityNodeTest,writes_correct_value_to_node)110 TEST_F(GpuCapacityNodeTest, writes_correct_value_to_node) {
111     EXPECT_CALL(*mock_fd_interface, write(fake_fd, StrEq(capacity_str), capacity_str.size()))
112             .Times(1);
113     GpuCapacityNode capacity_node(std::make_unique<FdInterfaceWrapper>(mock_fd_interface), fake_fd,
114                                   another_fake_fd, path);
115     EXPECT_THAT(capacity_node.set_gpu_capacity(capacity), Eq(true));
116 }
117 
TEST_F(GpuCapacityNodeTest,writes_failure)118 TEST_F(GpuCapacityNodeTest, writes_failure) {
119     EXPECT_CALL(*mock_fd_interface, write(_, _, _)).Times(1).WillOnce(Return(-12));
120     GpuCapacityNode capacity_node(std::make_unique<FdInterfaceWrapper>(mock_fd_interface), fake_fd,
121                                   another_fake_fd, path);
122     EXPECT_THAT(capacity_node.set_gpu_capacity(capacity), Eq(false));
123 }
124 
TEST_F(GpuCapacityNodeTest,reads_freq_correctly)125 TEST_F(GpuCapacityNodeTest, reads_freq_correctly) {
126     static constexpr auto value = "100";
127     testing::Sequence seq;
128     EXPECT_CALL(*mock_fd_interface, read(another_fake_fd, _, _))
129             .InSequence(seq)
130             .WillOnce(Invoke([&](auto, void *buf, size_t len) {
131                 strncpy(static_cast<char *>(buf), value, len);
132                 return 3;
133             }));
134     EXPECT_CALL(*mock_fd_interface, read(another_fake_fd, _, _))
135             .InSequence(seq)
136             .WillOnce(Return(0));
137     EXPECT_CALL(*mock_fd_interface, lseek(another_fake_fd, 0, SEEK_SET))
138             .InSequence(seq)
139             .WillOnce(Return(0));
140 
141     GpuCapacityNode capacity_node(std::make_unique<FdInterfaceWrapper>(mock_fd_interface), fake_fd,
142                                   another_fake_fd, path);
143     auto const frequency = capacity_node.gpu_frequency();
144     ASSERT_TRUE(frequency);
145     EXPECT_THAT(*frequency, Eq(Frequency(100000)));
146 }
147 
TEST_F(GpuCapacityNodeTest,reads_freq_correctly_partial)148 TEST_F(GpuCapacityNodeTest, reads_freq_correctly_partial) {
149     static constexpr auto value = "100";
150     int i = 0;
151     testing::Sequence seq;
152     EXPECT_CALL(*mock_fd_interface, read(another_fake_fd, _, _))
153             .Times(4)
154             .WillRepeatedly(Invoke([&](auto, void *buf, size_t) {
155                 if (i >= 3) {
156                     return 0;
157                 }
158                 auto c = reinterpret_cast<char *>(buf);
159                 *c = value[i++];
160                 return 1;
161             }));
162     EXPECT_CALL(*mock_fd_interface, lseek(another_fake_fd, 0, SEEK_SET)).WillOnce(Return(0));
163 
164     GpuCapacityNode capacity_node(std::make_unique<FdInterfaceWrapper>(mock_fd_interface), fake_fd,
165                                   another_fake_fd, path);
166     auto const frequency = capacity_node.gpu_frequency();
167     ASSERT_TRUE(frequency);
168     EXPECT_THAT(*frequency, Eq(Frequency(100000)));
169 }
170 
TEST_F(GpuCapacityNodeTest,reads_freq_correctly_full)171 TEST_F(GpuCapacityNodeTest, reads_freq_correctly_full) {
172     testing::Sequence seq;
173     EXPECT_CALL(*mock_fd_interface, read(another_fake_fd, _, _))
174             .Times(1)
175             .WillRepeatedly(Invoke([&](auto, void *buf, size_t size) {
176                 auto c = reinterpret_cast<char *>(buf);
177                 for (auto i = 0u; i < size; i++) {
178                     c[i] = i < 3 ? '1' : '\0';
179                 }
180                 return size;
181             }));
182     EXPECT_CALL(*mock_fd_interface, lseek(another_fake_fd, 0, SEEK_SET)).WillOnce(Return(0));
183 
184     GpuCapacityNode capacity_node(std::make_unique<FdInterfaceWrapper>(mock_fd_interface), fake_fd,
185                                   another_fake_fd, path);
186     auto const frequency = capacity_node.gpu_frequency();
187     ASSERT_TRUE(frequency);
188     EXPECT_THAT(*frequency, Eq(Frequency(111000)));
189 }
190 
TEST_F(GpuCapacityNodeTest,read_failure)191 TEST_F(GpuCapacityNodeTest, read_failure) {
192     EXPECT_CALL(*mock_fd_interface, read(another_fake_fd, _, _)).Times(1).WillOnce(Return(-1));
193 
194     GpuCapacityNode capacity_node(std::make_unique<FdInterfaceWrapper>(mock_fd_interface), fake_fd,
195                                   another_fake_fd, path);
196     auto const frequency = capacity_node.gpu_frequency();
197     EXPECT_FALSE(frequency);
198 }
199 
TEST_F(GpuCapacityNodeTest,lseek_failure)200 TEST_F(GpuCapacityNodeTest, lseek_failure) {
201     testing::Sequence seq;
202     EXPECT_CALL(*mock_fd_interface, read(_, _, _)).InSequence(seq).WillOnce(Return(7));
203     EXPECT_CALL(*mock_fd_interface, read(_, _, _)).InSequence(seq).WillOnce(Return(0));
204     EXPECT_CALL(*mock_fd_interface, lseek(_, _, _)).InSequence(seq).WillOnce(Return(-1));
205 
206     GpuCapacityNode capacity_node(std::make_unique<FdInterfaceWrapper>(mock_fd_interface), fake_fd,
207                                   another_fake_fd, path);
208     auto const frequency = capacity_node.gpu_frequency();
209     EXPECT_FALSE(frequency);
210 }
211 
TEST_F(GpuCapacityNodeTest,truncates_positive_floats)212 TEST_F(GpuCapacityNodeTest, truncates_positive_floats) {
213     static constexpr auto value = "1068.2";
214     EXPECT_CALL(*mock_fd_interface, read(another_fake_fd, _, _))
215             .Times(2)
216             .WillOnce(Invoke([&](auto, void *buf, size_t len) {
217                 strncpy(static_cast<char *>(buf), value, len);
218                 return 6;
219             }))
220             .WillOnce(Return(0));
221 
222     GpuCapacityNode capacity_node(std::make_unique<FdInterfaceWrapper>(mock_fd_interface), fake_fd,
223                                   another_fake_fd, path);
224     auto const frequency = capacity_node.gpu_frequency();
225     ASSERT_TRUE(frequency);
226     EXPECT_THAT(*frequency, Eq(Frequency(1068000)));
227 }
228 
TEST_F(GpuCapacityNodeTest,nonsense_returned_from_frequency)229 TEST_F(GpuCapacityNodeTest, nonsense_returned_from_frequency) {
230     static constexpr auto value = "zappyzapzoo";
231     EXPECT_CALL(*mock_fd_interface, read(another_fake_fd, _, _))
232             .Times(1)
233             .WillOnce(Invoke([&](auto, void *buf, size_t len) {
234                 strncpy(static_cast<char *>(buf), value, len);
235                 return 0;
236             }));
237 
238     GpuCapacityNode capacity_node(std::make_unique<FdInterfaceWrapper>(mock_fd_interface), fake_fd,
239                                   another_fake_fd, path);
240     EXPECT_FALSE(capacity_node.gpu_frequency());
241 }
242 
TEST_F(GpuCapacityNodeTest,nonsense_returned_from_frequency2)243 TEST_F(GpuCapacityNodeTest, nonsense_returned_from_frequency2) {
244     static constexpr auto value = "-1068";
245     EXPECT_CALL(*mock_fd_interface, read(another_fake_fd, _, _))
246             .Times(1)
247             .WillOnce(Invoke([&](auto, void *buf, size_t len) {
248                 strncpy(static_cast<char *>(buf), value, len);
249                 return 0;
250             }));
251 
252     GpuCapacityNode capacity_node(std::make_unique<FdInterfaceWrapper>(mock_fd_interface), fake_fd,
253                                   another_fake_fd, path);
254     EXPECT_FALSE(capacity_node.gpu_frequency());
255 }
256 
TEST_F(GpuCapacityNodeTest,nonsense_returned_from_frequency4)257 TEST_F(GpuCapacityNodeTest, nonsense_returned_from_frequency4) {
258     static constexpr auto value = "0";
259     EXPECT_CALL(*mock_fd_interface, read(another_fake_fd, _, _))
260             .Times(1)
261             .WillOnce(Invoke([&](auto, void *buf, size_t len) {
262                 strncpy(static_cast<char *>(buf), value, len);
263                 return 0;
264             }));
265 
266     GpuCapacityNode capacity_node(std::make_unique<FdInterfaceWrapper>(mock_fd_interface), fake_fd,
267                                   another_fake_fd, path);
268     EXPECT_FALSE(capacity_node.gpu_frequency());
269 }
270 
271 }  // namespace pixel
272 }  // namespace impl
273 }  // namespace power
274 }  // namespace hardware
275 }  // namespace google
276 }  // namespace aidl
277