blob: 2edb977f27ea64dde43e71f1d1caa1260400ba00 [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
Willy Tu6c71b0f2021-10-10 13:34:41 -070021#include <charconv>
22#include <filesystem>
Patrick Ventureab650002019-03-16 09:08:47 -070023#include <fstream>
Willy Tu6c71b0f2021-10-10 13:34:41 -070024#include <functional>
Patrick Ventureab650002019-03-16 09:08:47 -070025#include <nlohmann/json.hpp>
Steve Foreman4f0d1de2021-09-20 14:06:32 -070026#include <sdbusplus/message.hpp>
27#include <sdbusplus/test/sdbus_mock.hpp>
Patrick Venturef085d912019-03-15 08:50:00 -070028#include <string>
29#include <tuple>
30
31#include <gtest/gtest.h>
32
33namespace google
34{
35namespace ipmi
36{
37
Willy Tu6c71b0f2021-10-10 13:34:41 -070038using testing::_;
39using testing::Return;
40
Patrick Venturef085d912019-03-15 08:50:00 -070041TEST(HandlerTest, EthCheckValidHappy)
42{
Patrick Venturef085d912019-03-15 08:50:00 -070043 Handler h;
William A. Kennington IIIb69209b2021-07-13 13:22:24 -070044 std::tuple<std::uint8_t, std::string> result = h.getEthDetails("et");
45 EXPECT_EQ(12, std::get<0>(result));
46 EXPECT_STREQ("et", std::get<1>(result).c_str());
Patrick Venturef085d912019-03-15 08:50:00 -070047}
48
Patrick Ventured2037c62019-03-15 10:29:47 -070049TEST(HandlerTest, CableCheckIllegalPath)
50{
51 Handler h;
52 EXPECT_THROW(h.getRxPackets("eth0/../../"), IpmiException);
53}
54
Patrick Ventureab650002019-03-16 09:08:47 -070055TEST(HandlerTest, readNameFromConfigInstanceVariety)
56{
57 // Make sure it handles the failures and successes as we expect.
58 struct testCase
59 {
60 std::string type;
61 std::uint8_t instance;
62 std::string expectedName;
63 };
64
65 std::vector<testCase> tests = {
66 {"cpu", 5, ""},
67 {"cpu", 3, "CPU2"},
68 };
69
70 auto j2 = R"(
71 {
72 "cpu": [
73 {"instance": 1, "name": "CPU0"},
74 {"instance": 2, "name": "CPU1"},
75 {"instance": 3, "name": "CPU2"},
76 {"instance": 4, "name": "CPU3"}
77 ]
78 }
79 )"_json;
80
81 for (const auto& test : tests)
82 {
83 EXPECT_STREQ(test.expectedName.c_str(),
84 readNameFromConfig(test.type, test.instance, j2).c_str());
85 }
86}
87
88// TODO: If we can test with phosphor-logging in the future, there are more
89// failure cases.
90
91TEST(HandlerTest, getEntityNameWithNameNotFoundExcepts)
92{
93 const char* testFilename = "test.json";
94 std::string contents = R"({"cpu": [{"instance": 1, "name": "CPU0"}]})";
95 std::ofstream outputJson(testFilename);
96 outputJson << contents;
97 outputJson.flush();
98 outputJson.close();
99
100 Handler h(testFilename);
101 EXPECT_THROW(h.getEntityName(0x03, 2), IpmiException);
102 (void)std::remove(testFilename);
103}
104
105TEST(HandlerTest, getEntityNameWithNameFoundReturnsIt)
106{
107 const char* testFilename = "test.json";
108 std::string contents = R"({"cpu": [{"instance": 1, "name": "CPU0"}]})";
109 std::ofstream outputJson(testFilename);
110 outputJson << contents;
111 outputJson.flush();
112 outputJson.close();
113
114 Handler h(testFilename);
115 EXPECT_STREQ("CPU0", h.getEntityName(0x03, 1).c_str());
116 (void)std::remove(testFilename);
117}
118
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700119using ::testing::_;
120using ::testing::AnyNumber;
Willy Tu6c71b0f2021-10-10 13:34:41 -0700121using ::testing::ContainerEq;
Steve Foreman4f0d1de2021-09-20 14:06:32 -0700122using ::testing::DoAll;
123using ::testing::ElementsAre;
124using ::testing::Eq;
125using ::testing::IsNull;
126using ::testing::MatcherCast;
127using ::testing::NotNull;
128using ::testing::Pointee;
129using ::testing::Return;
130using ::testing::ReturnNull;
131using ::testing::SafeMatcherCast;
132using ::testing::SetArgPointee;
133using ::testing::StrEq;
134using ::testing::StrictMock;
135using ::testing::StrNe;
136using ::testing::WithArg;
137
138class MockDbusHandler : public Handler
139{
140 public:
141 MockDbusHandler(sdbusplus::SdBusMock& mock,
142 const std::string& config = "") :
143 Handler(config),
144 mock_(&mock)
145 {
146 }
147
148 protected:
149 sdbusplus::bus::bus accelOobGetDbus() const override
150 {
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{
167 std::fprintf(stderr, "%s\n", msg);
168}
169
170ACTION_P(TraceDbus2, msg)
171{
172 std::fprintf(stderr, "%s(%02x)\n", msg, *static_cast<const uint8_t*>(arg2));
173}
174
175constexpr char object_path[] = "/com/google/customAccel/test/path";
176constexpr char property_grpc[] = "com.google.custom_accel.gRPC";
177constexpr char value_port[] = "Port";
178constexpr uint32_t port = 5000;
179
180constexpr char SD_BUS_TYPE_BYTE_STR[] = {SD_BUS_TYPE_BYTE, '\0'};
181
182// Returns an object that looks like:
183// "/com/google/customAccel/test/path": {
184// "com.google.custom_accel.gRPC" : {
185// "Port" : {
186// "type" : "u",
187// "data" : 5000
188// }
189// }
190// }
191void ExpectGetManagedObjects(StrictMock<sdbusplus::SdBusMock>& mock,
192 const char* obj_path = object_path)
193{
194 ::testing::InSequence s;
195
196 // These must be nullptr or sd_bus_message_unref will seg fault.
197 constexpr sd_bus_message* method = nullptr;
198 constexpr sd_bus_message* msg = nullptr;
199
200 EXPECT_CALL(mock, sd_bus_message_new_method_call(
201 _, // sd_bus *bus,
202 NotNull(), // sd_bus_message **m
203 StrEq("com.google.custom_accel"), StrEq("/"),
204 StrEq("org.freedesktop.DBus.ObjectManager"),
205 StrEq("GetManagedObjects")))
206 .WillOnce(DoAll(SetArgPointee<1>(method), Return(0)));
207
208 EXPECT_CALL(mock, sd_bus_call(_, // sd_bus *bus,
209 method, // sd_bus_message *m
210 _, // uint64_t timeout
211 NotNull(), // sd_bus_error *ret_error
212 NotNull())) // sd_bus_message **reply
213 .WillOnce(DoAll(SetArgPointee<3>(SD_BUS_ERROR_NULL),
214 SetArgPointee<4>(msg), // reply
215 Return(0)));
216
217 EXPECT_CALL(mock, sd_bus_message_enter_container(msg, SD_BUS_TYPE_ARRAY,
218 StrEq("{oa{sa{sv}}}")))
219 .WillOnce(Return(1));
220
221 EXPECT_CALL(mock, sd_bus_message_at_end(msg, 0)).WillOnce(Return(0));
222
223 EXPECT_CALL(mock, sd_bus_message_enter_container(
224 msg, SD_BUS_TYPE_DICT_ENTRY, StrEq("oa{sa{sv}}")))
225 .WillOnce(Return(1));
226
227 EXPECT_CALL(mock, sd_bus_message_read_basic(msg, SD_BUS_TYPE_OBJECT_PATH,
228 NotNull()))
229 .WillOnce(DoAll(AssignReadVal<const char*>(obj_path), Return(1)));
230
231 EXPECT_CALL(mock, sd_bus_message_enter_container(msg, SD_BUS_TYPE_ARRAY,
232 StrEq("{sa{sv}}")))
233 .WillOnce(Return(1));
234
235 EXPECT_CALL(mock, sd_bus_message_at_end(msg, 0)).WillOnce(Return(0));
236
237 EXPECT_CALL(mock, sd_bus_message_enter_container(
238 msg, SD_BUS_TYPE_DICT_ENTRY, StrEq("sa{sv}")))
239 .WillOnce(Return(1));
240
241 EXPECT_CALL(mock,
242 sd_bus_message_read_basic(msg, SD_BUS_TYPE_STRING, NotNull()))
243 .WillOnce(DoAll(AssignReadVal<const char*>(property_grpc), Return(1)));
244
245 EXPECT_CALL(mock, sd_bus_message_enter_container(msg, SD_BUS_TYPE_ARRAY,
246 StrEq("{sv}")))
247 .WillOnce(Return(1));
248
249 EXPECT_CALL(mock, sd_bus_message_at_end(msg, 0)).WillOnce(Return(0));
250
251 EXPECT_CALL(mock, sd_bus_message_enter_container(
252 msg, SD_BUS_TYPE_DICT_ENTRY, StrEq("sv")))
253 .WillOnce(Return(1));
254
255 EXPECT_CALL(mock,
256 sd_bus_message_read_basic(msg, SD_BUS_TYPE_STRING, NotNull()))
257 .WillOnce(DoAll(AssignReadVal<const char*>(value_port), Return(1)));
258
259 EXPECT_CALL(
260 mock, sd_bus_message_verify_type(msg, SD_BUS_TYPE_VARIANT, StrNe("u")))
261 .Times(AnyNumber())
262 .WillRepeatedly(Return(0));
263
264 EXPECT_CALL(
265 mock, sd_bus_message_verify_type(msg, SD_BUS_TYPE_VARIANT, StrEq("u")))
266 .WillOnce(Return(1));
267
268 EXPECT_CALL(mock, sd_bus_message_enter_container(msg, SD_BUS_TYPE_VARIANT,
269 StrEq("u")))
270 .WillOnce(Return(1));
271
272 EXPECT_CALL(mock,
273 sd_bus_message_read_basic(msg, SD_BUS_TYPE_UINT32, NotNull()))
274 .WillOnce(DoAll(AssignReadVal<uint32_t>(port), Return(0)));
275
276 EXPECT_CALL(
277 mock, sd_bus_message_verify_type(msg, SD_BUS_TYPE_VARIANT, StrNe("u")))
278 .Times(AnyNumber())
279 .WillRepeatedly(Return(0));
280
281 EXPECT_CALL(mock, sd_bus_message_exit_container(msg))
282 .WillOnce(Return(1))
283 .WillOnce(Return(1));
284
285 EXPECT_CALL(mock, sd_bus_message_at_end(msg, 0)).WillOnce(Return(1));
286
287 EXPECT_CALL(mock, sd_bus_message_exit_container(msg))
288 .WillOnce(Return(1))
289 .WillOnce(Return(1));
290
291 EXPECT_CALL(mock, sd_bus_message_at_end(msg, 0)).WillOnce(Return(1));
292
293 EXPECT_CALL(mock, sd_bus_message_exit_container(msg))
294 .WillOnce(Return(1))
295 .WillOnce(Return(1));
296
297 EXPECT_CALL(mock, sd_bus_message_at_end(msg, 0)).WillOnce(Return(1));
298
299 EXPECT_CALL(mock, sd_bus_message_exit_container(msg)).WillOnce(Return(1));
300}
301
302void ExpectSdBusError(StrictMock<sdbusplus::SdBusMock>& mock)
303{
304 EXPECT_CALL(mock, sd_bus_message_new_method_call(
305 _, // sd_bus *bus,
306 NotNull(), // sd_bus_message **m
307 StrEq("com.google.custom_accel"), StrEq("/"),
308 StrEq("org.freedesktop.DBus.ObjectManager"),
309 StrEq("GetManagedObjects")))
310 .WillOnce(Return(-ENOTCONN));
311}
312
313TEST(HandlerTest, accelOobDeviceCount_Success)
314{
315 StrictMock<sdbusplus::SdBusMock> mock;
316 MockDbusHandler h(mock);
317 ExpectGetManagedObjects(mock);
318 EXPECT_EQ(1, h.accelOobDeviceCount());
319}
320
321TEST(HandlerTest, accelOobDeviceCount_Fail)
322{
323 StrictMock<sdbusplus::SdBusMock> mock;
324 MockDbusHandler h(mock);
325 ExpectSdBusError(mock);
326 EXPECT_THROW(h.accelOobDeviceCount(), IpmiException);
327}
328
329TEST(HandlerTest, accelOobDeviceName_Success)
330{
331 StrictMock<sdbusplus::SdBusMock> mock;
332 MockDbusHandler h(mock);
333 ExpectGetManagedObjects(mock);
334 EXPECT_EQ(std::string("test/path"), h.accelOobDeviceName(0));
335}
336
337TEST(HandlerTest, accelOobDeviceName_Fail)
338{
339 StrictMock<sdbusplus::SdBusMock> mock;
340 MockDbusHandler h(mock);
341 ExpectSdBusError(mock);
342 EXPECT_THROW(h.accelOobDeviceName(0), IpmiException);
343}
344
345TEST(HandlerTest, accelOobDeviceName_OutOfRange)
346{
347 StrictMock<sdbusplus::SdBusMock> mock;
348 MockDbusHandler h(mock);
349 ExpectGetManagedObjects(mock);
350 EXPECT_THROW(h.accelOobDeviceName(1), IpmiException);
351}
352
353TEST(HandlerTest, accelOobDeviceName_InvalidName)
354{
355 constexpr char bad_object_path[] = "/com/google/customAccel2/bad/path";
356 StrictMock<sdbusplus::SdBusMock> mock;
357 MockDbusHandler h(mock);
358 ExpectGetManagedObjects(mock, bad_object_path);
359 EXPECT_THROW(h.accelOobDeviceName(0), IpmiException);
360}
361
362constexpr uint8_t NUM_BYTES_RETURNED_EQ_NUM_BYTES = 0xff;
363void ExpectRead(StrictMock<sdbusplus::SdBusMock>& mock, uint64_t address,
364 uint8_t num_bytes, uint64_t data, int sd_bus_call_return_value,
365 uint8_t num_bytes_returned = NUM_BYTES_RETURNED_EQ_NUM_BYTES)
366{
367 ::testing::InSequence s;
368
369 // These must be nullptr or sd_bus_message_unref will seg fault.
370 constexpr sd_bus_message* method = nullptr;
371 constexpr sd_bus_message* msg = nullptr;
372
373 EXPECT_CALL(mock, sd_bus_message_new_method_call(
374 _, // sd_bus *bus,
375 NotNull(), // sd_bus_message **m
376 StrEq("com.google.custom_accel"),
377 StrEq("/com/google/customAccel/test/path"),
378 StrEq("com.google.custom_accel.BAR"), StrEq("Read")))
379 .WillOnce(DoAll(SetArgPointee<1>(method), Return(0)));
380
381 EXPECT_CALL(
382 mock, sd_bus_message_append_basic(
383 method, SD_BUS_TYPE_UINT64,
384 MatcherCast<const void*>(
385 SafeMatcherCast<const uint64_t*>(Pointee(Eq(address))))))
386 .WillOnce(Return(1));
387
388 EXPECT_CALL(mock,
389 sd_bus_message_append_basic(
390 method, SD_BUS_TYPE_UINT64,
391 MatcherCast<const void*>(SafeMatcherCast<const uint64_t*>(
392 Pointee(Eq<uint64_t>(num_bytes))))))
393 .WillOnce(Return(1));
394
395 EXPECT_CALL(mock, sd_bus_call(_, // sd_bus *bus,
396 method, // sd_bus_message *m
397 _, // uint64_t timeout
398 NotNull(), // sd_bus_error *ret_error
399 NotNull())) // sd_bus_message **reply
400 .WillOnce(DoAll(SetArgPointee<3>(SD_BUS_ERROR_NULL),
401 SetArgPointee<4>(msg), // reply
402 Return(sd_bus_call_return_value)));
403
404 if (sd_bus_call_return_value >= 0)
405 {
406 EXPECT_CALL(mock,
407 sd_bus_message_enter_container(msg, SD_BUS_TYPE_ARRAY,
408 StrEq(SD_BUS_TYPE_BYTE_STR)))
409 .WillOnce(Return(1));
410
411 if (num_bytes_returned == NUM_BYTES_RETURNED_EQ_NUM_BYTES)
412 {
413 num_bytes_returned = num_bytes;
414 }
415 for (auto i = num_bytes_returned - 1; i >= 0; --i)
416 {
417 EXPECT_CALL(mock, sd_bus_message_at_end(msg, 0))
418 .WillOnce(Return(0));
419
420 const uint8_t byte = (data >> (8 * i)) & 0xff;
421 EXPECT_CALL(mock, sd_bus_message_read_basic(msg, SD_BUS_TYPE_BYTE,
422 NotNull()))
423 .WillOnce(DoAll(AssignReadVal<uint8_t>(byte), Return(1)));
424 }
425
426 EXPECT_CALL(mock, sd_bus_message_at_end(msg, 0)).WillOnce(Return(1));
427
428 EXPECT_CALL(mock, sd_bus_message_exit_container(msg))
429 .WillOnce(Return(1));
430 }
431}
432
433TEST(HandlerTest, accelOobRead_Success)
434{
435 StrictMock<sdbusplus::SdBusMock> mock;
436 MockDbusHandler h(mock);
437
438 constexpr uint64_t address = 0x123456789abcdef;
439 constexpr uint8_t num_bytes = sizeof(uint64_t);
440 constexpr int sd_bus_call_return_value = 1;
441 constexpr uint64_t data = 0x13579bdf02468ace;
442
443 ExpectRead(mock, address, num_bytes, data, sd_bus_call_return_value);
444 EXPECT_EQ(data, h.accelOobRead("test/path", address, num_bytes));
445}
446
447TEST(HandlerTest, accelOobRead_Fail)
448{
449 StrictMock<sdbusplus::SdBusMock> mock;
450 MockDbusHandler h(mock);
451
452 constexpr uint64_t address = 0x123456789abcdef;
453 constexpr uint8_t num_bytes = sizeof(uint64_t);
454 constexpr int sd_bus_call_return_value = -ENOTCONN;
455 constexpr uint64_t data = 0x13579bdf02468ace;
456
457 ExpectRead(mock, address, num_bytes, data, sd_bus_call_return_value);
458 EXPECT_THROW(h.accelOobRead("test/path", address, num_bytes),
459 IpmiException);
460}
461
462TEST(HandlerTest, accelOobRead_TooFewBytesReturned)
463{
464 StrictMock<sdbusplus::SdBusMock> mock;
465 MockDbusHandler h(mock);
466
467 constexpr uint64_t address = 0x123456789abcdef;
468 constexpr uint8_t num_bytes = sizeof(uint64_t);
469 constexpr int sd_bus_call_return_value = 1;
470 constexpr uint64_t data = 0x13579bdf02468ace;
471 constexpr uint8_t num_bytes_returned = num_bytes - 1;
472
473 ExpectRead(mock, address, num_bytes, data, sd_bus_call_return_value,
474 num_bytes_returned);
475 EXPECT_THROW(h.accelOobRead("test/path", address, num_bytes),
476 IpmiException);
477}
478
479TEST(HandlerTest, accelOobRead_TooManyBytesReturned)
480{
481 StrictMock<sdbusplus::SdBusMock> mock;
482 MockDbusHandler h(mock);
483
484 constexpr uint64_t address = 0x123456789abcdef;
485 constexpr uint8_t num_bytes = sizeof(uint64_t);
486 constexpr int sd_bus_call_return_value = 1;
487 constexpr uint64_t data = 0x13579bdf02468ace;
488 constexpr uint8_t num_bytes_returned = sizeof(uint64_t) + 1;
489
490 ExpectRead(mock, address, num_bytes, data, sd_bus_call_return_value,
491 num_bytes_returned);
492 EXPECT_THROW(h.accelOobRead("test/path", address, num_bytes),
493 IpmiException);
494}
495
496void ExpectWrite(StrictMock<sdbusplus::SdBusMock>& mock, uint64_t address,
497 uint8_t num_bytes, uint64_t data, int sd_bus_call_return_value)
498{
499 ::testing::InSequence s;
500
501 // These must be nullptr or sd_bus_message_unref will seg fault.
502 constexpr sd_bus_message* method = nullptr;
503
504 EXPECT_CALL(mock, sd_bus_message_new_method_call(
505 _, // sd_bus *bus,
506 NotNull(), // sd_bus_message **m
507 StrEq("com.google.custom_accel"),
508 StrEq("/com/google/customAccel/test/path"),
509 StrEq("com.google.custom_accel.BAR"), StrEq("Write")))
510 .WillOnce(DoAll(TraceDbus("sd_bus_message_new_method_call"),
511 SetArgPointee<1>(method), Return(0)));
512
513 EXPECT_CALL(
514 mock, sd_bus_message_append_basic(
515 method, SD_BUS_TYPE_UINT64,
516 MatcherCast<const void*>(
517 SafeMatcherCast<const uint64_t*>(Pointee(Eq(address))))))
518 .WillOnce(DoAll(TraceDbus("sd_bus_message_append_basic(address) -> 1"),
519 Return(1)));
520
521 EXPECT_CALL(mock,
522 sd_bus_message_open_container(method, SD_BUS_TYPE_ARRAY,
523 StrEq(SD_BUS_TYPE_BYTE_STR)))
524 .WillOnce(DoAll(TraceDbus("sd_bus_message_open_container(a, y) -> 0"),
525 Return(0)));
526
527 for (auto i = 0; i < num_bytes; ++i)
528 {
529 const uint8_t byte = (data >> (8 * i)) & 0xff;
530
531 EXPECT_CALL(
532 mock, sd_bus_message_append_basic(
533 method, SD_BUS_TYPE_BYTE,
534 MatcherCast<const void*>(
535 SafeMatcherCast<const uint8_t*>(Pointee(Eq(byte))))))
536 .WillOnce(
537 DoAll(TraceDbus2("sd_bus_message_append_basic"), Return(1)));
538 }
539
540 EXPECT_CALL(mock, sd_bus_message_close_container(method))
541 .WillOnce(DoAll(TraceDbus("sd_bus_message_close_container() -> 0"),
542 Return(0)));
543
544 EXPECT_CALL(mock, sd_bus_call(_, // sd_bus *bus,
545 method, // sd_bus_message *m
546 _, // uint64_t timeout
547 NotNull(), // sd_bus_error *ret_error
548 IsNull())) // sd_bus_message **reply
549 .WillOnce(DoAll(TraceDbus("sd_bus_call() -> ret_val"),
550 SetArgPointee<3>(SD_BUS_ERROR_NULL),
551 Return(sd_bus_call_return_value)));
552}
553
554TEST(HandlerTest, accelOobWrite_Success)
555{
556 StrictMock<sdbusplus::SdBusMock> mock;
557 MockDbusHandler h(mock);
558
559 constexpr uint64_t address = 0x123456789abcdef;
560 constexpr uint8_t num_bytes = sizeof(uint64_t);
561 constexpr int sd_bus_call_return_value = 1;
562 constexpr uint64_t data = 0x13579bdf02468ace;
563
564 ExpectWrite(mock, address, num_bytes, data, sd_bus_call_return_value);
565 EXPECT_NO_THROW(h.accelOobWrite("test/path", address, num_bytes, data));
566}
567
568TEST(HandlerTest, accelOobRead_TooManyBytesRequested)
569{
570 StrictMock<sdbusplus::SdBusMock> mock;
571 MockDbusHandler h(mock);
572
573 constexpr uint64_t address = 0x123456789abcdef;
574 constexpr uint8_t num_bytes = sizeof(uint64_t) + 1;
575 constexpr uint64_t data = 0x13579bdf02468ace;
576
577 EXPECT_THROW(h.accelOobWrite("test/path", address, num_bytes, data),
578 IpmiException);
579}
580
581TEST(HandlerTest, accelOobWrite_Fail)
582{
583 StrictMock<sdbusplus::SdBusMock> mock;
584 MockDbusHandler h(mock);
585
586 constexpr uint64_t address = 0x123456789abcdef;
587 constexpr uint8_t num_bytes = sizeof(uint64_t);
588 constexpr int sd_bus_call_return_value = -ENOTCONN;
589 constexpr uint64_t data = 0x13579bdf02468ace;
590
591 ExpectWrite(mock, address, num_bytes, data, sd_bus_call_return_value);
592 EXPECT_THROW(h.accelOobWrite("test/path", address, num_bytes, data),
593 IpmiException);
594}
595
Willy Tu6c71b0f2021-10-10 13:34:41 -0700596TEST(HandlerTest, PcieBifurcation)
597{
598 const std::string& testJson = "/tmp/test-json";
599 auto j = R"(
600 {
601 "1": [ 1, 3 ],
602 "3": [ 3, 6 ],
603 "4": [ 3, 4, 1 ],
604 "6": [ 8 ]
605 }
606 )"_json;
607
608 std::ofstream bifurcationJson(testJson);
609 bifurcationJson << j.dump();
610 bifurcationJson.flush();
611 bifurcationJson.close();
612
613 BifurcationStatic bifurcationHelper(testJson);
614 Handler h(std::ref(bifurcationHelper));
615
616 std::unordered_map<uint8_t, std::vector<uint8_t>> expectedMapping = {
617 {1, {1, 3}}, {3, {3, 6}}, {4, {3, 4, 1}}, {6, {8}}};
618 std::vector<uint8_t> invalidBus = {0, 2, 5, 7};
619
620 for (const auto& [bus, output] : expectedMapping)
621 {
622 EXPECT_THAT(h.pcieBifurcation(bus), ContainerEq(output));
623 }
624
625 for (const auto& bus : invalidBus)
626 {
627 EXPECT_TRUE(h.pcieBifurcation(bus).empty());
628 }
629
630 std::filesystem::remove(testJson.data());
631 bifurcationHelper = BifurcationStatic(testJson);
632 Handler h2(std::ref(bifurcationHelper));
633 for (uint8_t i = 0; i < 8; ++i)
634 {
635 auto bifurcation = h2.pcieBifurcation(i);
636 EXPECT_TRUE(bifurcation.empty());
637 }
638}
639
Patrick Venturef085d912019-03-15 08:50:00 -0700640// TODO: Add checks for other functions of handler.
641
642} // namespace ipmi
643} // namespace google