blob: 549f1d0bc1baac33aa7ddae50ba448bfd9ff9315 [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 = "") :
145 Handler(config),
146 mock_(&mock)
Patrick Williams444b5ea2023-05-19 13:56:42 -0500147 {}
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700148
149 protected:
Patrick Williams65371222023-05-19 02:31:40 -0500150 sdbusplus::bus_t getDbus() const override
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700151 {
152 return sdbusplus::get_mocked_new(
153 const_cast<sdbusplus::SdBusMock*>(mock_));
154 }
155
156 private:
157 sdbusplus::SdBusMock* mock_;
158};
159
160ACTION_TEMPLATE(AssignReadVal, HAS_1_TEMPLATE_PARAMS(typename, T),
161 AND_1_VALUE_PARAMS(val))
162{
163 *static_cast<T*>(arg2) = val;
164}
165
166ACTION_P(TraceDbus, msg)
167{
Michael Shen8d618532023-10-25 09:14:07 +0000168 stdplus::print(stderr, "{}\n", msg);
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700169}
170
171ACTION_P(TraceDbus2, msg)
172{
Michael Shen8d618532023-10-25 09:14:07 +0000173 stdplus::print(stderr, "{}({:02x})\n", msg,
174 *static_cast<const uint8_t*>(arg2));
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700175}
176
177constexpr char object_path[] = "/com/google/customAccel/test/path";
178constexpr char property_grpc[] = "com.google.custom_accel.gRPC";
179constexpr char value_port[] = "Port";
180constexpr uint32_t port = 5000;
181
182constexpr char SD_BUS_TYPE_BYTE_STR[] = {SD_BUS_TYPE_BYTE, '\0'};
183
184// Returns an object that looks like:
185// "/com/google/customAccel/test/path": {
186// "com.google.custom_accel.gRPC" : {
187// "Port" : {
188// "type" : "u",
189// "data" : 5000
190// }
191// }
192// }
193void ExpectGetManagedObjects(StrictMock<sdbusplus::SdBusMock>& mock,
194 const char* obj_path = object_path)
195{
196 ::testing::InSequence s;
197
198 // These must be nullptr or sd_bus_message_unref will seg fault.
199 constexpr sd_bus_message* method = nullptr;
200 constexpr sd_bus_message* msg = nullptr;
201
202 EXPECT_CALL(mock, sd_bus_message_new_method_call(
203 _, // sd_bus *bus,
204 NotNull(), // sd_bus_message **m
205 StrEq("com.google.custom_accel"), StrEq("/"),
206 StrEq("org.freedesktop.DBus.ObjectManager"),
207 StrEq("GetManagedObjects")))
208 .WillOnce(DoAll(SetArgPointee<1>(method), Return(0)));
209
Willy Tu1209ccc2023-05-19 00:49:51 -0700210 EXPECT_CALL(mock, sd_bus_call(_, // sd_bus *bus,
211 method, // sd_bus_message *m
212 _, // uint64_t timeout
213 NotNull(), // sd_bus_error *ret_error
214 NotNull())) // sd_bus_message **reply
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700215 .WillOnce(DoAll(SetArgPointee<3>(SD_BUS_ERROR_NULL),
216 SetArgPointee<4>(msg), // reply
217 Return(0)));
218
219 EXPECT_CALL(mock, sd_bus_message_enter_container(msg, SD_BUS_TYPE_ARRAY,
220 StrEq("{oa{sa{sv}}}")))
221 .WillOnce(Return(1));
222
223 EXPECT_CALL(mock, sd_bus_message_at_end(msg, 0)).WillOnce(Return(0));
224
225 EXPECT_CALL(mock, sd_bus_message_enter_container(
226 msg, SD_BUS_TYPE_DICT_ENTRY, StrEq("oa{sa{sv}}")))
227 .WillOnce(Return(1));
228
229 EXPECT_CALL(mock, sd_bus_message_read_basic(msg, SD_BUS_TYPE_OBJECT_PATH,
230 NotNull()))
231 .WillOnce(DoAll(AssignReadVal<const char*>(obj_path), Return(1)));
232
233 EXPECT_CALL(mock, sd_bus_message_enter_container(msg, SD_BUS_TYPE_ARRAY,
234 StrEq("{sa{sv}}")))
235 .WillOnce(Return(1));
236
237 EXPECT_CALL(mock, sd_bus_message_at_end(msg, 0)).WillOnce(Return(0));
238
239 EXPECT_CALL(mock, sd_bus_message_enter_container(
240 msg, SD_BUS_TYPE_DICT_ENTRY, StrEq("sa{sv}")))
241 .WillOnce(Return(1));
242
243 EXPECT_CALL(mock,
244 sd_bus_message_read_basic(msg, SD_BUS_TYPE_STRING, NotNull()))
245 .WillOnce(DoAll(AssignReadVal<const char*>(property_grpc), Return(1)));
246
247 EXPECT_CALL(mock, sd_bus_message_enter_container(msg, SD_BUS_TYPE_ARRAY,
248 StrEq("{sv}")))
249 .WillOnce(Return(1));
250
251 EXPECT_CALL(mock, sd_bus_message_at_end(msg, 0)).WillOnce(Return(0));
252
253 EXPECT_CALL(mock, sd_bus_message_enter_container(
254 msg, SD_BUS_TYPE_DICT_ENTRY, StrEq("sv")))
255 .WillOnce(Return(1));
256
257 EXPECT_CALL(mock,
258 sd_bus_message_read_basic(msg, SD_BUS_TYPE_STRING, NotNull()))
259 .WillOnce(DoAll(AssignReadVal<const char*>(value_port), Return(1)));
260
261 EXPECT_CALL(
262 mock, sd_bus_message_verify_type(msg, SD_BUS_TYPE_VARIANT, StrNe("u")))
263 .Times(AnyNumber())
264 .WillRepeatedly(Return(0));
265
266 EXPECT_CALL(
267 mock, sd_bus_message_verify_type(msg, SD_BUS_TYPE_VARIANT, StrEq("u")))
268 .WillOnce(Return(1));
269
270 EXPECT_CALL(mock, sd_bus_message_enter_container(msg, SD_BUS_TYPE_VARIANT,
271 StrEq("u")))
272 .WillOnce(Return(1));
273
274 EXPECT_CALL(mock,
275 sd_bus_message_read_basic(msg, SD_BUS_TYPE_UINT32, NotNull()))
276 .WillOnce(DoAll(AssignReadVal<uint32_t>(port), Return(0)));
277
278 EXPECT_CALL(
279 mock, sd_bus_message_verify_type(msg, SD_BUS_TYPE_VARIANT, StrNe("u")))
280 .Times(AnyNumber())
281 .WillRepeatedly(Return(0));
282
283 EXPECT_CALL(mock, sd_bus_message_exit_container(msg))
284 .WillOnce(Return(1))
285 .WillOnce(Return(1));
286
287 EXPECT_CALL(mock, sd_bus_message_at_end(msg, 0)).WillOnce(Return(1));
288
289 EXPECT_CALL(mock, sd_bus_message_exit_container(msg))
290 .WillOnce(Return(1))
291 .WillOnce(Return(1));
292
293 EXPECT_CALL(mock, sd_bus_message_at_end(msg, 0)).WillOnce(Return(1));
294
295 EXPECT_CALL(mock, sd_bus_message_exit_container(msg))
296 .WillOnce(Return(1))
297 .WillOnce(Return(1));
298
299 EXPECT_CALL(mock, sd_bus_message_at_end(msg, 0)).WillOnce(Return(1));
300
301 EXPECT_CALL(mock, sd_bus_message_exit_container(msg)).WillOnce(Return(1));
302}
303
Michael Shen0e928ac2022-06-20 05:21:52 +0000304void ExpectSdBusError(StrictMock<sdbusplus::SdBusMock>& mock,
305 const std::string& service, const std::string& objPath,
306 const std::string& interface, const std::string& function)
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700307{
Michael Shen0e928ac2022-06-20 05:21:52 +0000308 EXPECT_CALL(
309 mock, sd_bus_message_new_method_call(_, // sd_bus *bus,
310 NotNull(), // sd_bus_message **m
311 StrEq(service), StrEq(objPath),
312 StrEq(interface), StrEq(function)))
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700313 .WillOnce(Return(-ENOTCONN));
314}
315
316TEST(HandlerTest, accelOobDeviceCount_Success)
317{
318 StrictMock<sdbusplus::SdBusMock> mock;
319 MockDbusHandler h(mock);
320 ExpectGetManagedObjects(mock);
321 EXPECT_EQ(1, h.accelOobDeviceCount());
322}
323
324TEST(HandlerTest, accelOobDeviceCount_Fail)
325{
326 StrictMock<sdbusplus::SdBusMock> mock;
327 MockDbusHandler h(mock);
Michael Shen0e928ac2022-06-20 05:21:52 +0000328 ExpectSdBusError(mock, "com.google.custom_accel", "/",
329 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700330 EXPECT_THROW(h.accelOobDeviceCount(), IpmiException);
331}
332
333TEST(HandlerTest, accelOobDeviceName_Success)
334{
335 StrictMock<sdbusplus::SdBusMock> mock;
336 MockDbusHandler h(mock);
337 ExpectGetManagedObjects(mock);
338 EXPECT_EQ(std::string("test/path"), h.accelOobDeviceName(0));
339}
340
341TEST(HandlerTest, accelOobDeviceName_Fail)
342{
343 StrictMock<sdbusplus::SdBusMock> mock;
344 MockDbusHandler h(mock);
Michael Shen0e928ac2022-06-20 05:21:52 +0000345 ExpectSdBusError(mock, "com.google.custom_accel", "/",
346 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700347 EXPECT_THROW(h.accelOobDeviceName(0), IpmiException);
348}
349
350TEST(HandlerTest, accelOobDeviceName_OutOfRange)
351{
352 StrictMock<sdbusplus::SdBusMock> mock;
353 MockDbusHandler h(mock);
354 ExpectGetManagedObjects(mock);
355 EXPECT_THROW(h.accelOobDeviceName(1), IpmiException);
356}
357
358TEST(HandlerTest, accelOobDeviceName_InvalidName)
359{
360 constexpr char bad_object_path[] = "/com/google/customAccel2/bad/path";
361 StrictMock<sdbusplus::SdBusMock> mock;
362 MockDbusHandler h(mock);
363 ExpectGetManagedObjects(mock, bad_object_path);
364 EXPECT_THROW(h.accelOobDeviceName(0), IpmiException);
365}
366
367constexpr uint8_t NUM_BYTES_RETURNED_EQ_NUM_BYTES = 0xff;
368void ExpectRead(StrictMock<sdbusplus::SdBusMock>& mock, uint64_t address,
369 uint8_t num_bytes, uint64_t data, int sd_bus_call_return_value,
370 uint8_t num_bytes_returned = NUM_BYTES_RETURNED_EQ_NUM_BYTES)
371{
372 ::testing::InSequence s;
373
374 // These must be nullptr or sd_bus_message_unref will seg fault.
375 constexpr sd_bus_message* method = nullptr;
376 constexpr sd_bus_message* msg = nullptr;
377
378 EXPECT_CALL(mock, sd_bus_message_new_method_call(
379 _, // sd_bus *bus,
380 NotNull(), // sd_bus_message **m
381 StrEq("com.google.custom_accel"),
382 StrEq("/com/google/customAccel/test/path"),
383 StrEq("com.google.custom_accel.BAR"), StrEq("Read")))
384 .WillOnce(DoAll(SetArgPointee<1>(method), Return(0)));
385
386 EXPECT_CALL(
387 mock, sd_bus_message_append_basic(
388 method, SD_BUS_TYPE_UINT64,
389 MatcherCast<const void*>(
390 SafeMatcherCast<const uint64_t*>(Pointee(Eq(address))))))
391 .WillOnce(Return(1));
392
393 EXPECT_CALL(mock,
394 sd_bus_message_append_basic(
395 method, SD_BUS_TYPE_UINT64,
396 MatcherCast<const void*>(SafeMatcherCast<const uint64_t*>(
397 Pointee(Eq<uint64_t>(num_bytes))))))
398 .WillOnce(Return(1));
399
Willy Tu1209ccc2023-05-19 00:49:51 -0700400 EXPECT_CALL(mock, sd_bus_call(_, // sd_bus *bus,
401 method, // sd_bus_message *m
402 _, // uint64_t timeout
403 NotNull(), // sd_bus_error *ret_error
404 NotNull())) // sd_bus_message **reply
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700405 .WillOnce(DoAll(SetArgPointee<3>(SD_BUS_ERROR_NULL),
406 SetArgPointee<4>(msg), // reply
407 Return(sd_bus_call_return_value)));
408
409 if (sd_bus_call_return_value >= 0)
410 {
411 EXPECT_CALL(mock,
412 sd_bus_message_enter_container(msg, SD_BUS_TYPE_ARRAY,
413 StrEq(SD_BUS_TYPE_BYTE_STR)))
414 .WillOnce(Return(1));
415
416 if (num_bytes_returned == NUM_BYTES_RETURNED_EQ_NUM_BYTES)
417 {
418 num_bytes_returned = num_bytes;
419 }
420 for (auto i = num_bytes_returned - 1; i >= 0; --i)
421 {
422 EXPECT_CALL(mock, sd_bus_message_at_end(msg, 0))
423 .WillOnce(Return(0));
424
Willy Tu1209ccc2023-05-19 00:49:51 -0700425 const uint8_t byte = (i >= 8) ? 0 : (data >> (8 * i)) & 0xff;
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700426 EXPECT_CALL(mock, sd_bus_message_read_basic(msg, SD_BUS_TYPE_BYTE,
427 NotNull()))
428 .WillOnce(DoAll(AssignReadVal<uint8_t>(byte), Return(1)));
429 }
430
431 EXPECT_CALL(mock, sd_bus_message_at_end(msg, 0)).WillOnce(Return(1));
432
433 EXPECT_CALL(mock, sd_bus_message_exit_container(msg))
434 .WillOnce(Return(1));
435 }
436}
437
438TEST(HandlerTest, accelOobRead_Success)
439{
440 StrictMock<sdbusplus::SdBusMock> mock;
441 MockDbusHandler h(mock);
442
443 constexpr uint64_t address = 0x123456789abcdef;
444 constexpr uint8_t num_bytes = sizeof(uint64_t);
445 constexpr int sd_bus_call_return_value = 1;
446 constexpr uint64_t data = 0x13579bdf02468ace;
447
448 ExpectRead(mock, address, num_bytes, data, sd_bus_call_return_value);
449 EXPECT_EQ(data, h.accelOobRead("test/path", address, num_bytes));
450}
451
452TEST(HandlerTest, accelOobRead_Fail)
453{
454 StrictMock<sdbusplus::SdBusMock> mock;
455 MockDbusHandler h(mock);
456
457 constexpr uint64_t address = 0x123456789abcdef;
458 constexpr uint8_t num_bytes = sizeof(uint64_t);
459 constexpr int sd_bus_call_return_value = -ENOTCONN;
460 constexpr uint64_t data = 0x13579bdf02468ace;
461
462 ExpectRead(mock, address, num_bytes, data, sd_bus_call_return_value);
463 EXPECT_THROW(h.accelOobRead("test/path", address, num_bytes),
464 IpmiException);
465}
466
467TEST(HandlerTest, accelOobRead_TooFewBytesReturned)
468{
469 StrictMock<sdbusplus::SdBusMock> mock;
470 MockDbusHandler h(mock);
471
472 constexpr uint64_t address = 0x123456789abcdef;
473 constexpr uint8_t num_bytes = sizeof(uint64_t);
474 constexpr int sd_bus_call_return_value = 1;
475 constexpr uint64_t data = 0x13579bdf02468ace;
476 constexpr uint8_t num_bytes_returned = num_bytes - 1;
477
478 ExpectRead(mock, address, num_bytes, data, sd_bus_call_return_value,
479 num_bytes_returned);
480 EXPECT_THROW(h.accelOobRead("test/path", address, num_bytes),
481 IpmiException);
482}
483
484TEST(HandlerTest, accelOobRead_TooManyBytesReturned)
485{
486 StrictMock<sdbusplus::SdBusMock> mock;
487 MockDbusHandler h(mock);
488
489 constexpr uint64_t address = 0x123456789abcdef;
490 constexpr uint8_t num_bytes = sizeof(uint64_t);
491 constexpr int sd_bus_call_return_value = 1;
492 constexpr uint64_t data = 0x13579bdf02468ace;
493 constexpr uint8_t num_bytes_returned = sizeof(uint64_t) + 1;
494
495 ExpectRead(mock, address, num_bytes, data, sd_bus_call_return_value,
496 num_bytes_returned);
497 EXPECT_THROW(h.accelOobRead("test/path", address, num_bytes),
498 IpmiException);
499}
500
501void ExpectWrite(StrictMock<sdbusplus::SdBusMock>& mock, uint64_t address,
502 uint8_t num_bytes, uint64_t data, int sd_bus_call_return_value)
503{
504 ::testing::InSequence s;
505
506 // These must be nullptr or sd_bus_message_unref will seg fault.
507 constexpr sd_bus_message* method = nullptr;
508
509 EXPECT_CALL(mock, sd_bus_message_new_method_call(
510 _, // sd_bus *bus,
511 NotNull(), // sd_bus_message **m
512 StrEq("com.google.custom_accel"),
513 StrEq("/com/google/customAccel/test/path"),
514 StrEq("com.google.custom_accel.BAR"), StrEq("Write")))
515 .WillOnce(DoAll(TraceDbus("sd_bus_message_new_method_call"),
516 SetArgPointee<1>(method), Return(0)));
517
518 EXPECT_CALL(
519 mock, sd_bus_message_append_basic(
520 method, SD_BUS_TYPE_UINT64,
521 MatcherCast<const void*>(
522 SafeMatcherCast<const uint64_t*>(Pointee(Eq(address))))))
523 .WillOnce(DoAll(TraceDbus("sd_bus_message_append_basic(address) -> 1"),
524 Return(1)));
525
526 EXPECT_CALL(mock,
527 sd_bus_message_open_container(method, SD_BUS_TYPE_ARRAY,
528 StrEq(SD_BUS_TYPE_BYTE_STR)))
529 .WillOnce(DoAll(TraceDbus("sd_bus_message_open_container(a, y) -> 0"),
530 Return(0)));
531
532 for (auto i = 0; i < num_bytes; ++i)
533 {
534 const uint8_t byte = (data >> (8 * i)) & 0xff;
535
536 EXPECT_CALL(
537 mock, sd_bus_message_append_basic(
538 method, SD_BUS_TYPE_BYTE,
539 MatcherCast<const void*>(
540 SafeMatcherCast<const uint8_t*>(Pointee(Eq(byte))))))
541 .WillOnce(
542 DoAll(TraceDbus2("sd_bus_message_append_basic"), Return(1)));
543 }
544
545 EXPECT_CALL(mock, sd_bus_message_close_container(method))
546 .WillOnce(DoAll(TraceDbus("sd_bus_message_close_container() -> 0"),
547 Return(0)));
548
549 EXPECT_CALL(mock, sd_bus_call(_, // sd_bus *bus,
550 method, // sd_bus_message *m
551 _, // uint64_t timeout
552 NotNull(), // sd_bus_error *ret_error
553 IsNull())) // sd_bus_message **reply
554 .WillOnce(DoAll(TraceDbus("sd_bus_call() -> ret_val"),
555 SetArgPointee<3>(SD_BUS_ERROR_NULL),
556 Return(sd_bus_call_return_value)));
557}
558
559TEST(HandlerTest, accelOobWrite_Success)
560{
561 StrictMock<sdbusplus::SdBusMock> mock;
562 MockDbusHandler h(mock);
563
564 constexpr uint64_t address = 0x123456789abcdef;
565 constexpr uint8_t num_bytes = sizeof(uint64_t);
566 constexpr int sd_bus_call_return_value = 1;
567 constexpr uint64_t data = 0x13579bdf02468ace;
568
569 ExpectWrite(mock, address, num_bytes, data, sd_bus_call_return_value);
570 EXPECT_NO_THROW(h.accelOobWrite("test/path", address, num_bytes, data));
571}
572
573TEST(HandlerTest, accelOobRead_TooManyBytesRequested)
574{
575 StrictMock<sdbusplus::SdBusMock> mock;
576 MockDbusHandler h(mock);
577
578 constexpr uint64_t address = 0x123456789abcdef;
579 constexpr uint8_t num_bytes = sizeof(uint64_t) + 1;
580 constexpr uint64_t data = 0x13579bdf02468ace;
581
582 EXPECT_THROW(h.accelOobWrite("test/path", address, num_bytes, data),
583 IpmiException);
584}
585
586TEST(HandlerTest, accelOobWrite_Fail)
587{
588 StrictMock<sdbusplus::SdBusMock> mock;
589 MockDbusHandler h(mock);
590
591 constexpr uint64_t address = 0x123456789abcdef;
592 constexpr uint8_t num_bytes = sizeof(uint64_t);
593 constexpr int sd_bus_call_return_value = -ENOTCONN;
594 constexpr uint64_t data = 0x13579bdf02468ace;
595
596 ExpectWrite(mock, address, num_bytes, data, sd_bus_call_return_value);
597 EXPECT_THROW(h.accelOobWrite("test/path", address, num_bytes, data),
598 IpmiException);
599}
600
Willy Tu6c71b0f2021-10-10 13:34:41 -0700601TEST(HandlerTest, PcieBifurcation)
602{
603 const std::string& testJson = "/tmp/test-json";
604 auto j = R"(
605 {
606 "1": [ 1, 3 ],
607 "3": [ 3, 6 ],
608 "4": [ 3, 4, 1 ],
609 "6": [ 8 ]
610 }
611 )"_json;
612
613 std::ofstream bifurcationJson(testJson);
614 bifurcationJson << j.dump();
615 bifurcationJson.flush();
616 bifurcationJson.close();
617
618 BifurcationStatic bifurcationHelper(testJson);
619 Handler h(std::ref(bifurcationHelper));
620
621 std::unordered_map<uint8_t, std::vector<uint8_t>> expectedMapping = {
622 {1, {1, 3}}, {3, {3, 6}}, {4, {3, 4, 1}}, {6, {8}}};
623 std::vector<uint8_t> invalidBus = {0, 2, 5, 7};
624
625 for (const auto& [bus, output] : expectedMapping)
626 {
627 EXPECT_THAT(h.pcieBifurcation(bus), ContainerEq(output));
628 }
629
630 for (const auto& bus : invalidBus)
631 {
632 EXPECT_TRUE(h.pcieBifurcation(bus).empty());
633 }
634
635 std::filesystem::remove(testJson.data());
636 bifurcationHelper = BifurcationStatic(testJson);
637 Handler h2(std::ref(bifurcationHelper));
638 for (uint8_t i = 0; i < 8; ++i)
639 {
640 auto bifurcation = h2.pcieBifurcation(i);
641 EXPECT_TRUE(bifurcation.empty());
642 }
643}
644
Patrick Venturef085d912019-03-15 08:50:00 -0700645// TODO: Add checks for other functions of handler.
646
647} // namespace ipmi
648} // namespace google