blob: 7230b08eec392253c371d19847e1adc413f14e19 [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);
81 reqHandler.registerRequest(
82 eid, instanceId, 0, 0, std::move(request),
83 std::move(std::bind_front(&HandlerTest::pldmResponseCallBack, this)));
84
85 pldm::Response response(sizeof(pldm_msg_hdr) + sizeof(uint8_t));
86 auto responsePtr = reinterpret_cast<const pldm_msg*>(response.data());
87 reqHandler.handleResponse(eid, instanceId, 0, 0, responsePtr,
88 sizeof(response));
89
90 // handleResponse() will free the instance ID after calling the response
91 // handler, so the same instance ID is granted next as well
92 ASSERT_EQ(validResponse, true);
93 ASSERT_EQ(instanceId, dbusImplReq.getInstanceId(eid));
94}
95
96TEST_F(HandlerTest, singleRequestInstanceIdTimerExpired)
97{
98 Handler<NiceMock<MockRequest>> reqHandler(fd, event, dbusImplReq,
99 seconds(1), 2, milliseconds(100));
100 pldm::Request request{};
101 auto instanceId = dbusImplReq.getInstanceId(eid);
102 reqHandler.registerRequest(
103 eid, instanceId, 0, 0, std::move(request),
104 std::move(std::bind_front(&HandlerTest::pldmResponseCallBack, this)));
105
106 // Waiting for 500ms so that the instance ID expiry callback is invoked
107 waitEventExpiry(milliseconds(500));
108
109 // cleanup() will free the instance ID after calling the response
110 // handler will no response, so the same instance ID is granted next
111 ASSERT_EQ(instanceId, dbusImplReq.getInstanceId(eid));
112 ASSERT_EQ(nullResponse, true);
113}
114
115TEST_F(HandlerTest, multipleRequestResponseScenario)
116{
117 Handler<NiceMock<MockRequest>> reqHandler(fd, event, dbusImplReq,
118 seconds(2), 2, milliseconds(100));
119 pldm::Request request{};
120 auto instanceId = dbusImplReq.getInstanceId(eid);
121 reqHandler.registerRequest(
122 eid, instanceId, 0, 0, std::move(request),
123 std::move(std::bind_front(&HandlerTest::pldmResponseCallBack, this)));
124
125 pldm::Request requestNxt{};
126 auto instanceIdNxt = dbusImplReq.getInstanceId(eid);
127 reqHandler.registerRequest(
128 eid, instanceIdNxt, 0, 0, std::move(requestNxt),
129 std::move(std::bind_front(&HandlerTest::pldmResponseCallBack, this)));
130
131 pldm::Response response(sizeof(pldm_msg_hdr) + sizeof(uint8_t));
132 auto responsePtr = reinterpret_cast<const pldm_msg*>(response.data());
133 reqHandler.handleResponse(eid, instanceIdNxt, 0, 0, responsePtr,
134 sizeof(response));
135 ASSERT_EQ(validResponse, true);
136 ASSERT_EQ(callbackCount, 1);
137 validResponse = false;
138
139 // Waiting for 500ms and handle the response for the first request, to
140 // simulate a delayed response for the first request
141 waitEventExpiry(milliseconds(500));
142
143 reqHandler.handleResponse(eid, instanceId, 0, 0, responsePtr,
144 sizeof(response));
145
146 ASSERT_EQ(validResponse, true);
147 ASSERT_EQ(callbackCount, 2);
148 ASSERT_EQ(instanceId, dbusImplReq.getInstanceId(eid));
149}