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