blob: 4af02bf2fec40c4bcc0e2784b4db45e2ac80fef1 [file] [log] [blame]
Steve Foreman4f0d1de2021-09-20 14:06:32 -07001// Copyright 2022 Google LLC
Willy Tua2056e92021-10-10 13:36:16 -07002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Patrick Ventured2037c62019-03-15 10:29:47 -070015#include "errors.hpp"
Patrick Venturef085d912019-03-15 08:50:00 -070016#include "handler.hpp"
Patrick Venturec87de552020-05-20 20:25:39 -070017#include "handler_impl.hpp"
Patrick Venturef085d912019-03-15 08:50:00 -070018
Steve Foreman4f0d1de2021-09-20 14:06:32 -070019#include <systemd/sd-bus.h>
20
Patrick Williams444b5ea2023-05-19 13:56:42 -050021#include <nlohmann/json.hpp>
22#include <sdbusplus/message.hpp>
23#include <sdbusplus/test/sdbus_mock.hpp>
Michael Shen8d618532023-10-25 09:14:07 +000024#include <stdplus/print.hpp>
Patrick Williams444b5ea2023-05-19 13:56:42 -050025
Willy Tu6c71b0f2021-10-10 13:34:41 -070026#include <charconv>
27#include <filesystem>
Patrick Ventureab650002019-03-16 09:08:47 -070028#include <fstream>
Willy Tu6c71b0f2021-10-10 13:34:41 -070029#include <functional>
Patrick Venturef085d912019-03-15 08:50:00 -070030#include <string>
31#include <tuple>
32
33#include <gtest/gtest.h>
34
35namespace google
36{
37namespace ipmi
38{
39
Willy Tu6c71b0f2021-10-10 13:34:41 -070040using testing::_;
41using testing::Return;
42
Patrick Venturef085d912019-03-15 08:50:00 -070043TEST(HandlerTest, EthCheckValidHappy)
44{
Patrick Venturef085d912019-03-15 08:50:00 -070045 Handler h;
William A. Kennington IIIb69209b2021-07-13 13:22:24 -070046 std::tuple<std::uint8_t, std::string> result = h.getEthDetails("et");
47 EXPECT_EQ(12, std::get<0>(result));
48 EXPECT_STREQ("et", std::get<1>(result).c_str());
Patrick Venturef085d912019-03-15 08:50:00 -070049}
50
Patrick Ventured2037c62019-03-15 10:29:47 -070051TEST(HandlerTest, CableCheckIllegalPath)
52{
53 Handler h;
54 EXPECT_THROW(h.getRxPackets("eth0/../../"), IpmiException);
55}
56
Patrick Ventureab650002019-03-16 09:08:47 -070057TEST(HandlerTest, readNameFromConfigInstanceVariety)
58{
59 // Make sure it handles the failures and successes as we expect.
60 struct testCase
61 {
62 std::string type;
63 std::uint8_t instance;
64 std::string expectedName;
65 };
66
67 std::vector<testCase> tests = {
68 {"cpu", 5, ""},
69 {"cpu", 3, "CPU2"},
70 };
71
72 auto j2 = R"(
73 {
74 "cpu": [
75 {"instance": 1, "name": "CPU0"},
76 {"instance": 2, "name": "CPU1"},
77 {"instance": 3, "name": "CPU2"},
78 {"instance": 4, "name": "CPU3"}
79 ]
80 }
81 )"_json;
82
83 for (const auto& test : tests)
84 {
85 EXPECT_STREQ(test.expectedName.c_str(),
86 readNameFromConfig(test.type, test.instance, j2).c_str());
87 }
88}
89
90// TODO: If we can test with phosphor-logging in the future, there are more
91// failure cases.
92
93TEST(HandlerTest, getEntityNameWithNameNotFoundExcepts)
94{
95 const char* testFilename = "test.json";
96 std::string contents = R"({"cpu": [{"instance": 1, "name": "CPU0"}]})";
97 std::ofstream outputJson(testFilename);
98 outputJson << contents;
99 outputJson.flush();
100 outputJson.close();
101
102 Handler h(testFilename);
103 EXPECT_THROW(h.getEntityName(0x03, 2), IpmiException);
104 (void)std::remove(testFilename);
105}
106
107TEST(HandlerTest, getEntityNameWithNameFoundReturnsIt)
108{
109 const char* testFilename = "test.json";
110 std::string contents = R"({"cpu": [{"instance": 1, "name": "CPU0"}]})";
111 std::ofstream outputJson(testFilename);
112 outputJson << contents;
113 outputJson.flush();
114 outputJson.close();
115
116 Handler h(testFilename);
117 EXPECT_STREQ("CPU0", h.getEntityName(0x03, 1).c_str());
118 (void)std::remove(testFilename);
119}
120
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700121using ::testing::_;
122using ::testing::AnyNumber;
Willy Tu6c71b0f2021-10-10 13:34:41 -0700123using ::testing::ContainerEq;
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700124using ::testing::DoAll;
125using ::testing::ElementsAre;
126using ::testing::Eq;
127using ::testing::IsNull;
128using ::testing::MatcherCast;
129using ::testing::NotNull;
130using ::testing::Pointee;
131using ::testing::Return;
132using ::testing::ReturnNull;
133using ::testing::SafeMatcherCast;
134using ::testing::SetArgPointee;
135using ::testing::StrEq;
136using ::testing::StrictMock;
137using ::testing::StrNe;
138using ::testing::WithArg;
139
140class MockDbusHandler : public Handler
141{
142 public:
143 MockDbusHandler(sdbusplus::SdBusMock& mock,
144 const std::string& config = "") :
Patrick Williams8c0094e2024-08-16 15:22:37 -0400145 Handler(config), mock_(&mock)
Patrick Williams444b5ea2023-05-19 13:56:42 -0500146 {}
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700147
148 protected:
Patrick Williams65371222023-05-19 02:31:40 -0500149 sdbusplus::bus_t getDbus() const override
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700150 {
151 return sdbusplus::get_mocked_new(
152 const_cast<sdbusplus::SdBusMock*>(mock_));
153 }
154
155 private:
156 sdbusplus::SdBusMock* mock_;
157};
158
159ACTION_TEMPLATE(AssignReadVal, HAS_1_TEMPLATE_PARAMS(typename, T),
160 AND_1_VALUE_PARAMS(val))
161{
162 *static_cast<T*>(arg2) = val;
163}
164
165ACTION_P(TraceDbus, msg)
166{
Michael Shen8d618532023-10-25 09:14:07 +0000167 stdplus::print(stderr, "{}\n", msg);
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700168}
169
170ACTION_P(TraceDbus2, msg)
171{
Michael Shen8d618532023-10-25 09:14:07 +0000172 stdplus::print(stderr, "{}({:02x})\n", msg,
173 *static_cast<const uint8_t*>(arg2));
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700174}
175
176constexpr char object_path[] = "/com/google/customAccel/test/path";
177constexpr char property_grpc[] = "com.google.custom_accel.gRPC";
178constexpr char value_port[] = "Port";
179constexpr uint32_t port = 5000;
180
181constexpr char SD_BUS_TYPE_BYTE_STR[] = {SD_BUS_TYPE_BYTE, '\0'};
182
183// Returns an object that looks like:
184// "/com/google/customAccel/test/path": {
185// "com.google.custom_accel.gRPC" : {
186// "Port" : {
187// "type" : "u",
188// "data" : 5000
189// }
190// }
191// }
192void ExpectGetManagedObjects(StrictMock<sdbusplus::SdBusMock>& mock,
193 const char* obj_path = object_path)
194{
195 ::testing::InSequence s;
196
197 // These must be nullptr or sd_bus_message_unref will seg fault.
198 constexpr sd_bus_message* method = nullptr;
199 constexpr sd_bus_message* msg = nullptr;
200
201 EXPECT_CALL(mock, sd_bus_message_new_method_call(
202 _, // sd_bus *bus,
203 NotNull(), // sd_bus_message **m
204 StrEq("com.google.custom_accel"), StrEq("/"),
205 StrEq("org.freedesktop.DBus.ObjectManager"),
206 StrEq("GetManagedObjects")))
207 .WillOnce(DoAll(SetArgPointee<1>(method), Return(0)));
208
Willy Tu1209ccc2023-05-19 00:49:51 -0700209 EXPECT_CALL(mock, sd_bus_call(_, // sd_bus *bus,
210 method, // sd_bus_message *m
211 _, // uint64_t timeout
212 NotNull(), // sd_bus_error *ret_error
213 NotNull())) // sd_bus_message **reply
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700214 .WillOnce(DoAll(SetArgPointee<3>(SD_BUS_ERROR_NULL),
215 SetArgPointee<4>(msg), // reply
216 Return(0)));
217
218 EXPECT_CALL(mock, sd_bus_message_enter_container(msg, SD_BUS_TYPE_ARRAY,
219 StrEq("{oa{sa{sv}}}")))
220 .WillOnce(Return(1));
221
222 EXPECT_CALL(mock, sd_bus_message_at_end(msg, 0)).WillOnce(Return(0));
223
224 EXPECT_CALL(mock, sd_bus_message_enter_container(
225 msg, SD_BUS_TYPE_DICT_ENTRY, StrEq("oa{sa{sv}}")))
226 .WillOnce(Return(1));
227
228 EXPECT_CALL(mock, sd_bus_message_read_basic(msg, SD_BUS_TYPE_OBJECT_PATH,
229 NotNull()))
230 .WillOnce(DoAll(AssignReadVal<const char*>(obj_path), Return(1)));
231
232 EXPECT_CALL(mock, sd_bus_message_enter_container(msg, SD_BUS_TYPE_ARRAY,
233 StrEq("{sa{sv}}")))
234 .WillOnce(Return(1));
235
236 EXPECT_CALL(mock, sd_bus_message_at_end(msg, 0)).WillOnce(Return(0));
237
238 EXPECT_CALL(mock, sd_bus_message_enter_container(
239 msg, SD_BUS_TYPE_DICT_ENTRY, StrEq("sa{sv}")))
240 .WillOnce(Return(1));
241
242 EXPECT_CALL(mock,
243 sd_bus_message_read_basic(msg, SD_BUS_TYPE_STRING, NotNull()))
244 .WillOnce(DoAll(AssignReadVal<const char*>(property_grpc), Return(1)));
245
246 EXPECT_CALL(mock, sd_bus_message_enter_container(msg, SD_BUS_TYPE_ARRAY,
247 StrEq("{sv}")))
248 .WillOnce(Return(1));
249
250 EXPECT_CALL(mock, sd_bus_message_at_end(msg, 0)).WillOnce(Return(0));
251
252 EXPECT_CALL(mock, sd_bus_message_enter_container(
253 msg, SD_BUS_TYPE_DICT_ENTRY, StrEq("sv")))
254 .WillOnce(Return(1));
255
256 EXPECT_CALL(mock,
257 sd_bus_message_read_basic(msg, SD_BUS_TYPE_STRING, NotNull()))
258 .WillOnce(DoAll(AssignReadVal<const char*>(value_port), Return(1)));
259
260 EXPECT_CALL(
261 mock, sd_bus_message_verify_type(msg, SD_BUS_TYPE_VARIANT, StrNe("u")))
262 .Times(AnyNumber())
263 .WillRepeatedly(Return(0));
264
265 EXPECT_CALL(
266 mock, sd_bus_message_verify_type(msg, SD_BUS_TYPE_VARIANT, StrEq("u")))
267 .WillOnce(Return(1));
268
269 EXPECT_CALL(mock, sd_bus_message_enter_container(msg, SD_BUS_TYPE_VARIANT,
270 StrEq("u")))
271 .WillOnce(Return(1));
272
273 EXPECT_CALL(mock,
274 sd_bus_message_read_basic(msg, SD_BUS_TYPE_UINT32, NotNull()))
275 .WillOnce(DoAll(AssignReadVal<uint32_t>(port), Return(0)));
276
277 EXPECT_CALL(
278 mock, sd_bus_message_verify_type(msg, SD_BUS_TYPE_VARIANT, StrNe("u")))
279 .Times(AnyNumber())
280 .WillRepeatedly(Return(0));
281
282 EXPECT_CALL(mock, sd_bus_message_exit_container(msg))
283 .WillOnce(Return(1))
284 .WillOnce(Return(1));
285
286 EXPECT_CALL(mock, sd_bus_message_at_end(msg, 0)).WillOnce(Return(1));
287
288 EXPECT_CALL(mock, sd_bus_message_exit_container(msg))
289 .WillOnce(Return(1))
290 .WillOnce(Return(1));
291
292 EXPECT_CALL(mock, sd_bus_message_at_end(msg, 0)).WillOnce(Return(1));
293
294 EXPECT_CALL(mock, sd_bus_message_exit_container(msg))
295 .WillOnce(Return(1))
296 .WillOnce(Return(1));
297
298 EXPECT_CALL(mock, sd_bus_message_at_end(msg, 0)).WillOnce(Return(1));
299
300 EXPECT_CALL(mock, sd_bus_message_exit_container(msg)).WillOnce(Return(1));
301}
302
Michael Shen0e928ac2022-06-20 05:21:52 +0000303void ExpectSdBusError(StrictMock<sdbusplus::SdBusMock>& mock,
304 const std::string& service, const std::string& objPath,
305 const std::string& interface, const std::string& function)
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700306{
Patrick Williams8c0094e2024-08-16 15:22:37 -0400307 EXPECT_CALL(mock, sd_bus_message_new_method_call(
308 _, // sd_bus *bus,
309 NotNull(), // sd_bus_message **m
310 StrEq(service), StrEq(objPath), StrEq(interface),
311 StrEq(function)))
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700312 .WillOnce(Return(-ENOTCONN));
313}
314
315TEST(HandlerTest, accelOobDeviceCount_Success)
316{
317 StrictMock<sdbusplus::SdBusMock> mock;
318 MockDbusHandler h(mock);
319 ExpectGetManagedObjects(mock);
320 EXPECT_EQ(1, h.accelOobDeviceCount());
321}
322
323TEST(HandlerTest, accelOobDeviceCount_Fail)
324{
325 StrictMock<sdbusplus::SdBusMock> mock;
326 MockDbusHandler h(mock);
Michael Shen0e928ac2022-06-20 05:21:52 +0000327 ExpectSdBusError(mock, "com.google.custom_accel", "/",
328 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700329 EXPECT_THROW(h.accelOobDeviceCount(), IpmiException);
330}
331
332TEST(HandlerTest, accelOobDeviceName_Success)
333{
334 StrictMock<sdbusplus::SdBusMock> mock;
335 MockDbusHandler h(mock);
336 ExpectGetManagedObjects(mock);
337 EXPECT_EQ(std::string("test/path"), h.accelOobDeviceName(0));
338}
339
340TEST(HandlerTest, accelOobDeviceName_Fail)
341{
342 StrictMock<sdbusplus::SdBusMock> mock;
343 MockDbusHandler h(mock);
Michael Shen0e928ac2022-06-20 05:21:52 +0000344 ExpectSdBusError(mock, "com.google.custom_accel", "/",
345 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700346 EXPECT_THROW(h.accelOobDeviceName(0), IpmiException);
347}
348
349TEST(HandlerTest, accelOobDeviceName_OutOfRange)
350{
351 StrictMock<sdbusplus::SdBusMock> mock;
352 MockDbusHandler h(mock);
353 ExpectGetManagedObjects(mock);
354 EXPECT_THROW(h.accelOobDeviceName(1), IpmiException);
355}
356
357TEST(HandlerTest, accelOobDeviceName_InvalidName)
358{
359 constexpr char bad_object_path[] = "/com/google/customAccel2/bad/path";
360 StrictMock<sdbusplus::SdBusMock> mock;
361 MockDbusHandler h(mock);
362 ExpectGetManagedObjects(mock, bad_object_path);
363 EXPECT_THROW(h.accelOobDeviceName(0), IpmiException);
364}
365
366constexpr uint8_t NUM_BYTES_RETURNED_EQ_NUM_BYTES = 0xff;
367void ExpectRead(StrictMock<sdbusplus::SdBusMock>& mock, uint64_t address,
368 uint8_t num_bytes, uint64_t data, int sd_bus_call_return_value,
369 uint8_t num_bytes_returned = NUM_BYTES_RETURNED_EQ_NUM_BYTES)
370{
371 ::testing::InSequence s;
372
373 // These must be nullptr or sd_bus_message_unref will seg fault.
374 constexpr sd_bus_message* method = nullptr;
375 constexpr sd_bus_message* msg = nullptr;
376
377 EXPECT_CALL(mock, sd_bus_message_new_method_call(
378 _, // sd_bus *bus,
379 NotNull(), // sd_bus_message **m
380 StrEq("com.google.custom_accel"),
381 StrEq("/com/google/customAccel/test/path"),
382 StrEq("com.google.custom_accel.BAR"), StrEq("Read")))
383 .WillOnce(DoAll(SetArgPointee<1>(method), Return(0)));
384
Patrick Williams8c0094e2024-08-16 15:22:37 -0400385 EXPECT_CALL(mock,
386 sd_bus_message_append_basic(
387 method, SD_BUS_TYPE_UINT64,
388 MatcherCast<const void*>(SafeMatcherCast<const uint64_t*>(
389 Pointee(Eq(address))))))
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700390 .WillOnce(Return(1));
391
392 EXPECT_CALL(mock,
393 sd_bus_message_append_basic(
394 method, SD_BUS_TYPE_UINT64,
395 MatcherCast<const void*>(SafeMatcherCast<const uint64_t*>(
396 Pointee(Eq<uint64_t>(num_bytes))))))
397 .WillOnce(Return(1));
398
Willy Tu1209ccc2023-05-19 00:49:51 -0700399 EXPECT_CALL(mock, sd_bus_call(_, // sd_bus *bus,
400 method, // sd_bus_message *m
401 _, // uint64_t timeout
402 NotNull(), // sd_bus_error *ret_error
403 NotNull())) // sd_bus_message **reply
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700404 .WillOnce(DoAll(SetArgPointee<3>(SD_BUS_ERROR_NULL),
405 SetArgPointee<4>(msg), // reply
406 Return(sd_bus_call_return_value)));
407
408 if (sd_bus_call_return_value >= 0)
409 {
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700410 if (num_bytes_returned == NUM_BYTES_RETURNED_EQ_NUM_BYTES)
411 {
412 num_bytes_returned = num_bytes;
413 }
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700414
Willy Tu0aec7a32025-07-25 03:30:00 +0000415 uint64_t updatedData = 0;
416 for (size_t i = 0; i < num_bytes_returned; ++i)
417 {
418 updatedData <<= 8;
419 updatedData += (i >= 8) ? 0 : (data >> (i * 8)) & 0xff;
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700420 }
421
Willy Tu0aec7a32025-07-25 03:30:00 +0000422 auto read_array_callback =
423 [updatedData, num_bytes_returned](sd_bus_message*, char,
424 const void** p, size_t* sz) {
425 *p = &updatedData;
426 *sz = num_bytes_returned;
427 };
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700428
Willy Tu0aec7a32025-07-25 03:30:00 +0000429 EXPECT_CALL(mock, sd_bus_message_read_array(nullptr, SD_BUS_TYPE_BYTE,
430 testing::_, testing::_))
431 .WillOnce(DoAll(testing::Invoke(read_array_callback), Return(0)));
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700432 }
433}
434
435TEST(HandlerTest, accelOobRead_Success)
436{
437 StrictMock<sdbusplus::SdBusMock> mock;
438 MockDbusHandler h(mock);
439
440 constexpr uint64_t address = 0x123456789abcdef;
441 constexpr uint8_t num_bytes = sizeof(uint64_t);
442 constexpr int sd_bus_call_return_value = 1;
443 constexpr uint64_t data = 0x13579bdf02468ace;
444
445 ExpectRead(mock, address, num_bytes, data, sd_bus_call_return_value);
446 EXPECT_EQ(data, h.accelOobRead("test/path", address, num_bytes));
447}
448
449TEST(HandlerTest, accelOobRead_Fail)
450{
451 StrictMock<sdbusplus::SdBusMock> mock;
452 MockDbusHandler h(mock);
453
454 constexpr uint64_t address = 0x123456789abcdef;
455 constexpr uint8_t num_bytes = sizeof(uint64_t);
456 constexpr int sd_bus_call_return_value = -ENOTCONN;
457 constexpr uint64_t data = 0x13579bdf02468ace;
458
459 ExpectRead(mock, address, num_bytes, data, sd_bus_call_return_value);
460 EXPECT_THROW(h.accelOobRead("test/path", address, num_bytes),
461 IpmiException);
462}
463
464TEST(HandlerTest, accelOobRead_TooFewBytesReturned)
465{
466 StrictMock<sdbusplus::SdBusMock> mock;
467 MockDbusHandler h(mock);
468
469 constexpr uint64_t address = 0x123456789abcdef;
470 constexpr uint8_t num_bytes = sizeof(uint64_t);
471 constexpr int sd_bus_call_return_value = 1;
472 constexpr uint64_t data = 0x13579bdf02468ace;
473 constexpr uint8_t num_bytes_returned = num_bytes - 1;
474
475 ExpectRead(mock, address, num_bytes, data, sd_bus_call_return_value,
476 num_bytes_returned);
477 EXPECT_THROW(h.accelOobRead("test/path", address, num_bytes),
478 IpmiException);
479}
480
481TEST(HandlerTest, accelOobRead_TooManyBytesReturned)
482{
483 StrictMock<sdbusplus::SdBusMock> mock;
484 MockDbusHandler h(mock);
485
486 constexpr uint64_t address = 0x123456789abcdef;
487 constexpr uint8_t num_bytes = sizeof(uint64_t);
488 constexpr int sd_bus_call_return_value = 1;
489 constexpr uint64_t data = 0x13579bdf02468ace;
490 constexpr uint8_t num_bytes_returned = sizeof(uint64_t) + 1;
491
492 ExpectRead(mock, address, num_bytes, data, sd_bus_call_return_value,
493 num_bytes_returned);
494 EXPECT_THROW(h.accelOobRead("test/path", address, num_bytes),
495 IpmiException);
496}
497
Willy Tu0aec7a32025-07-25 03:30:00 +0000498static int on_array_append(sd_bus_message*, char, const void*, size_t)
499{
500 return 0;
501}
502
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700503void ExpectWrite(StrictMock<sdbusplus::SdBusMock>& mock, uint64_t address,
Willy Tu0aec7a32025-07-25 03:30:00 +0000504 uint8_t num_bytes, uint64_t, int sd_bus_call_return_value)
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700505{
506 ::testing::InSequence s;
507
508 // These must be nullptr or sd_bus_message_unref will seg fault.
509 constexpr sd_bus_message* method = nullptr;
510
511 EXPECT_CALL(mock, sd_bus_message_new_method_call(
512 _, // sd_bus *bus,
513 NotNull(), // sd_bus_message **m
514 StrEq("com.google.custom_accel"),
515 StrEq("/com/google/customAccel/test/path"),
516 StrEq("com.google.custom_accel.BAR"), StrEq("Write")))
517 .WillOnce(DoAll(TraceDbus("sd_bus_message_new_method_call"),
518 SetArgPointee<1>(method), Return(0)));
519
Patrick Williams8c0094e2024-08-16 15:22:37 -0400520 EXPECT_CALL(mock,
521 sd_bus_message_append_basic(
522 method, SD_BUS_TYPE_UINT64,
523 MatcherCast<const void*>(SafeMatcherCast<const uint64_t*>(
524 Pointee(Eq(address))))))
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700525 .WillOnce(DoAll(TraceDbus("sd_bus_message_append_basic(address) -> 1"),
526 Return(1)));
527
Willy Tu0aec7a32025-07-25 03:30:00 +0000528 EXPECT_CALL(
529 mock, sd_bus_message_append_array(nullptr, SD_BUS_TYPE_BYTE, testing::_,
530 num_bytes * sizeof(std::byte)))
531 .WillOnce(testing::Invoke(on_array_append));
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700532
533 EXPECT_CALL(mock, sd_bus_call(_, // sd_bus *bus,
534 method, // sd_bus_message *m
535 _, // uint64_t timeout
536 NotNull(), // sd_bus_error *ret_error
537 IsNull())) // sd_bus_message **reply
538 .WillOnce(DoAll(TraceDbus("sd_bus_call() -> ret_val"),
539 SetArgPointee<3>(SD_BUS_ERROR_NULL),
540 Return(sd_bus_call_return_value)));
541}
542
543TEST(HandlerTest, accelOobWrite_Success)
544{
545 StrictMock<sdbusplus::SdBusMock> mock;
546 MockDbusHandler h(mock);
547
548 constexpr uint64_t address = 0x123456789abcdef;
549 constexpr uint8_t num_bytes = sizeof(uint64_t);
550 constexpr int sd_bus_call_return_value = 1;
551 constexpr uint64_t data = 0x13579bdf02468ace;
552
553 ExpectWrite(mock, address, num_bytes, data, sd_bus_call_return_value);
554 EXPECT_NO_THROW(h.accelOobWrite("test/path", address, num_bytes, data));
555}
556
557TEST(HandlerTest, accelOobRead_TooManyBytesRequested)
558{
559 StrictMock<sdbusplus::SdBusMock> mock;
560 MockDbusHandler h(mock);
561
562 constexpr uint64_t address = 0x123456789abcdef;
563 constexpr uint8_t num_bytes = sizeof(uint64_t) + 1;
564 constexpr uint64_t data = 0x13579bdf02468ace;
565
566 EXPECT_THROW(h.accelOobWrite("test/path", address, num_bytes, data),
567 IpmiException);
568}
569
570TEST(HandlerTest, accelOobWrite_Fail)
571{
572 StrictMock<sdbusplus::SdBusMock> mock;
573 MockDbusHandler h(mock);
574
575 constexpr uint64_t address = 0x123456789abcdef;
576 constexpr uint8_t num_bytes = sizeof(uint64_t);
577 constexpr int sd_bus_call_return_value = -ENOTCONN;
578 constexpr uint64_t data = 0x13579bdf02468ace;
579
580 ExpectWrite(mock, address, num_bytes, data, sd_bus_call_return_value);
581 EXPECT_THROW(h.accelOobWrite("test/path", address, num_bytes, data),
582 IpmiException);
583}
584
Willy Tu6c71b0f2021-10-10 13:34:41 -0700585TEST(HandlerTest, PcieBifurcation)
586{
587 const std::string& testJson = "/tmp/test-json";
588 auto j = R"(
589 {
590 "1": [ 1, 3 ],
591 "3": [ 3, 6 ],
592 "4": [ 3, 4, 1 ],
593 "6": [ 8 ]
594 }
595 )"_json;
596
597 std::ofstream bifurcationJson(testJson);
598 bifurcationJson << j.dump();
599 bifurcationJson.flush();
600 bifurcationJson.close();
601
602 BifurcationStatic bifurcationHelper(testJson);
603 Handler h(std::ref(bifurcationHelper));
604
605 std::unordered_map<uint8_t, std::vector<uint8_t>> expectedMapping = {
606 {1, {1, 3}}, {3, {3, 6}}, {4, {3, 4, 1}}, {6, {8}}};
607 std::vector<uint8_t> invalidBus = {0, 2, 5, 7};
608
609 for (const auto& [bus, output] : expectedMapping)
610 {
611 EXPECT_THAT(h.pcieBifurcation(bus), ContainerEq(output));
612 }
613
614 for (const auto& bus : invalidBus)
615 {
616 EXPECT_TRUE(h.pcieBifurcation(bus).empty());
617 }
618
619 std::filesystem::remove(testJson.data());
620 bifurcationHelper = BifurcationStatic(testJson);
621 Handler h2(std::ref(bifurcationHelper));
622 for (uint8_t i = 0; i < 8; ++i)
623 {
624 auto bifurcation = h2.pcieBifurcation(i);
625 EXPECT_TRUE(bifurcation.empty());
626 }
627}
628
Brandon Kim559cb012024-05-03 09:12:07 +0000629TEST(HandlerTest, BmInstanceFailCase)
630{
631 StrictMock<sdbusplus::SdBusMock> mock;
632 MockDbusHandler h(mock);
633
634 // Invalid enum
635 EXPECT_THROW(h.getBMInstanceProperty(0x07), IpmiException);
636
637 // Valid enum but no path exists
638 EXPECT_THROW(h.getBMInstanceProperty(0x00), IpmiException);
639}
640
Patrick Venturef085d912019-03-15 08:50:00 -0700641// TODO: Add checks for other functions of handler.
642
643} // namespace ipmi
644} // namespace google