blob: aa0655f780c1ee379673d5e97c2aa058f318d060 [file] [log] [blame]
Tom Joseph74f27c72021-05-16 07:58:53 -07001#include "libpldm/base.h"
2
3#include "common/types.hpp"
4#include "common/utils.hpp"
5#include "mock_request.hpp"
6#include "pldmd/dbus_impl_requester.hpp"
7#include "requester/handler.hpp"
8
9#include <gmock/gmock.h>
10#include <gtest/gtest.h>
11
12using namespace pldm::requester;
13using namespace std::chrono;
14
15using ::testing::AtLeast;
16using ::testing::Between;
17using ::testing::Exactly;
18using ::testing::NiceMock;
19using ::testing::Return;
20
21class HandlerTest : public testing::Test
22{
23 protected:
24 HandlerTest() :
25 event(sdeventplus::Event::get_default()),
26 dbusImplReq(pldm::utils::DBusHandler::getBus(),
27 "/xyz/openbmc_project/pldm")
28 {}
29
30 int fd = 0;
31 mctp_eid_t eid = 0;
32 sdeventplus::Event event;
33 pldm::dbus_api::Requester dbusImplReq;
34
35 /** @brief This function runs the sd_event_run in a loop till all the events
36 * in the testcase are dispatched and exits when there are no events
37 * for the timeout time.
38 *
39 * @param[in] timeout - maximum time to wait for an event
40 */
41 void waitEventExpiry(milliseconds timeout)
42 {
43 while (1)
44 {
45 auto sleepTime = duration_cast<microseconds>(timeout);
46 // Returns 0 on timeout
47 if (!sd_event_run(event.get(), sleepTime.count()))
48 {
49 break;
50 }
51 }
52 }
53
54 public:
55 bool nullResponse = false;
56 bool validResponse = false;
57 int callbackCount = 0;
58 bool response2 = false;
59
60 void pldmResponseCallBack(mctp_eid_t /*eid*/, const pldm_msg* response,
61 size_t respMsgLen)
62 {
63 if (response == nullptr && respMsgLen == 0)
64 {
65 nullResponse = true;
66 }
67 else
68 {
69 validResponse = true;
70 }
71 callbackCount++;
72 }
73};
74
75TEST_F(HandlerTest, singleRequestResponseScenario)
76{
77 Handler<NiceMock<MockRequest>> reqHandler(fd, event, dbusImplReq,
78 seconds(1), 2, milliseconds(100));
79 pldm::Request request{};
80 auto instanceId = dbusImplReq.getInstanceId(eid);
Tom Josepha5ed6582021-06-17 22:08:47 -070081 auto rc = reqHandler.registerRequest(
Tom Joseph74f27c72021-05-16 07:58:53 -070082 eid, instanceId, 0, 0, std::move(request),
83 std::move(std::bind_front(&HandlerTest::pldmResponseCallBack, this)));
Tom Josepha5ed6582021-06-17 22:08:47 -070084 EXPECT_EQ(rc, PLDM_SUCCESS);
Tom Joseph74f27c72021-05-16 07:58:53 -070085
86 pldm::Response response(sizeof(pldm_msg_hdr) + sizeof(uint8_t));
87 auto responsePtr = reinterpret_cast<const pldm_msg*>(response.data());
88 reqHandler.handleResponse(eid, instanceId, 0, 0, responsePtr,
89 sizeof(response));
90
91 // handleResponse() will free the instance ID after calling the response
92 // handler, so the same instance ID is granted next as well
Tom Josepha5ed6582021-06-17 22:08:47 -070093 EXPECT_EQ(validResponse, true);
94 EXPECT_EQ(instanceId, dbusImplReq.getInstanceId(eid));
Tom Joseph74f27c72021-05-16 07:58:53 -070095}
96
97TEST_F(HandlerTest, singleRequestInstanceIdTimerExpired)
98{
99 Handler<NiceMock<MockRequest>> reqHandler(fd, event, dbusImplReq,
100 seconds(1), 2, milliseconds(100));
101 pldm::Request request{};
102 auto instanceId = dbusImplReq.getInstanceId(eid);
Tom Josepha5ed6582021-06-17 22:08:47 -0700103 auto rc = reqHandler.registerRequest(
Tom Joseph74f27c72021-05-16 07:58:53 -0700104 eid, instanceId, 0, 0, std::move(request),
105 std::move(std::bind_front(&HandlerTest::pldmResponseCallBack, this)));
Tom Josepha5ed6582021-06-17 22:08:47 -0700106 EXPECT_EQ(rc, PLDM_SUCCESS);
Tom Joseph74f27c72021-05-16 07:58:53 -0700107
108 // Waiting for 500ms so that the instance ID expiry callback is invoked
109 waitEventExpiry(milliseconds(500));
110
111 // cleanup() will free the instance ID after calling the response
112 // handler will no response, so the same instance ID is granted next
Tom Josepha5ed6582021-06-17 22:08:47 -0700113 EXPECT_EQ(instanceId, dbusImplReq.getInstanceId(eid));
114 EXPECT_EQ(nullResponse, true);
Tom Joseph74f27c72021-05-16 07:58:53 -0700115}
116
117TEST_F(HandlerTest, multipleRequestResponseScenario)
118{
119 Handler<NiceMock<MockRequest>> reqHandler(fd, event, dbusImplReq,
120 seconds(2), 2, milliseconds(100));
121 pldm::Request request{};
122 auto instanceId = dbusImplReq.getInstanceId(eid);
Tom Josepha5ed6582021-06-17 22:08:47 -0700123 auto rc = reqHandler.registerRequest(
Tom Joseph74f27c72021-05-16 07:58:53 -0700124 eid, instanceId, 0, 0, std::move(request),
125 std::move(std::bind_front(&HandlerTest::pldmResponseCallBack, this)));
Tom Josepha5ed6582021-06-17 22:08:47 -0700126 EXPECT_EQ(rc, PLDM_SUCCESS);
Tom Joseph74f27c72021-05-16 07:58:53 -0700127
128 pldm::Request requestNxt{};
129 auto instanceIdNxt = dbusImplReq.getInstanceId(eid);
Tom Josepha5ed6582021-06-17 22:08:47 -0700130 rc = reqHandler.registerRequest(
Tom Joseph74f27c72021-05-16 07:58:53 -0700131 eid, instanceIdNxt, 0, 0, std::move(requestNxt),
132 std::move(std::bind_front(&HandlerTest::pldmResponseCallBack, this)));
Tom Josepha5ed6582021-06-17 22:08:47 -0700133 EXPECT_EQ(rc, PLDM_SUCCESS);
Tom Joseph74f27c72021-05-16 07:58:53 -0700134
135 pldm::Response response(sizeof(pldm_msg_hdr) + sizeof(uint8_t));
136 auto responsePtr = reinterpret_cast<const pldm_msg*>(response.data());
137 reqHandler.handleResponse(eid, instanceIdNxt, 0, 0, responsePtr,
138 sizeof(response));
Tom Josepha5ed6582021-06-17 22:08:47 -0700139 EXPECT_EQ(validResponse, true);
140 EXPECT_EQ(callbackCount, 1);
Tom Joseph74f27c72021-05-16 07:58:53 -0700141 validResponse = false;
142
143 // Waiting for 500ms and handle the response for the first request, to
144 // simulate a delayed response for the first request
145 waitEventExpiry(milliseconds(500));
146
147 reqHandler.handleResponse(eid, instanceId, 0, 0, responsePtr,
148 sizeof(response));
149
Tom Josepha5ed6582021-06-17 22:08:47 -0700150 EXPECT_EQ(validResponse, true);
151 EXPECT_EQ(callbackCount, 2);
152 EXPECT_EQ(instanceId, dbusImplReq.getInstanceId(eid));
Tom Joseph74f27c72021-05-16 07:58:53 -0700153}