1 #include "common/instance_id.hpp" 2 #include "common/types.hpp" 3 #include "common/utils.hpp" 4 #include "mock_request.hpp" 5 #include "requester/handler.hpp" 6 #include "test/test_instance_id.hpp" 7 8 #include <libpldm/base.h> 9 #include <libpldm/transport.h> 10 11 #include <gmock/gmock.h> 12 #include <gtest/gtest.h> 13 14 using namespace pldm::requester; 15 using namespace std::chrono; 16 17 using ::testing::AtLeast; 18 using ::testing::Between; 19 using ::testing::Exactly; 20 using ::testing::NiceMock; 21 using ::testing::Return; 22 23 class HandlerTest : public testing::Test 24 { 25 protected: 26 HandlerTest() : event(sdeventplus::Event::get_default()), instanceIdDb() {} 27 28 int fd = 0; 29 mctp_eid_t eid = 0; 30 PldmTransport* pldmTransport = nullptr; 31 sdeventplus::Event event; 32 TestInstanceIdDb instanceIdDb; 33 34 /** @brief This function runs the sd_event_run in a loop till all the events 35 * in the testcase are dispatched and exits when there are no events 36 * for the timeout time. 37 * 38 * @param[in] timeout - maximum time to wait for an event 39 */ 40 void waitEventExpiry(milliseconds timeout) 41 { 42 while (1) 43 { 44 auto sleepTime = duration_cast<microseconds>(timeout); 45 // Returns 0 on timeout 46 if (!sd_event_run(event.get(), sleepTime.count())) 47 { 48 break; 49 } 50 } 51 } 52 53 public: 54 bool nullResponse = false; 55 bool validResponse = false; 56 int callbackCount = 0; 57 bool response2 = false; 58 59 void pldmResponseCallBack(mctp_eid_t /*eid*/, const pldm_msg* response, 60 size_t respMsgLen) 61 { 62 if (response == nullptr && respMsgLen == 0) 63 { 64 nullResponse = true; 65 } 66 else 67 { 68 validResponse = true; 69 } 70 callbackCount++; 71 } 72 }; 73 74 TEST_F(HandlerTest, singleRequestResponseScenario) 75 { 76 Handler<NiceMock<MockRequest>> reqHandler(pldmTransport, event, 77 instanceIdDb, false, seconds(1), 78 2, milliseconds(100)); 79 pldm::Request request{}; 80 auto instanceId = instanceIdDb.next(eid); 81 EXPECT_EQ(instanceId, 0); 82 auto rc = reqHandler.registerRequest( 83 eid, instanceId, 0, 0, std::move(request), 84 std::move(std::bind_front(&HandlerTest::pldmResponseCallBack, this))); 85 EXPECT_EQ(rc, PLDM_SUCCESS); 86 87 pldm::Response response(sizeof(pldm_msg_hdr) + sizeof(uint8_t)); 88 auto responsePtr = reinterpret_cast<const pldm_msg*>(response.data()); 89 reqHandler.handleResponse(eid, instanceId, 0, 0, responsePtr, 90 sizeof(response)); 91 92 EXPECT_EQ(validResponse, true); 93 } 94 95 TEST_F(HandlerTest, singleRequestInstanceIdTimerExpired) 96 { 97 Handler<NiceMock<MockRequest>> reqHandler(pldmTransport, event, 98 instanceIdDb, false, seconds(1), 99 2, milliseconds(100)); 100 pldm::Request request{}; 101 auto instanceId = instanceIdDb.next(eid); 102 EXPECT_EQ(instanceId, 0); 103 auto rc = reqHandler.registerRequest( 104 eid, instanceId, 0, 0, std::move(request), 105 std::move(std::bind_front(&HandlerTest::pldmResponseCallBack, this))); 106 EXPECT_EQ(rc, PLDM_SUCCESS); 107 108 // Waiting for 500ms so that the instance ID expiry callback is invoked 109 waitEventExpiry(milliseconds(500)); 110 111 EXPECT_EQ(nullResponse, true); 112 } 113 114 TEST_F(HandlerTest, multipleRequestResponseScenario) 115 { 116 Handler<NiceMock<MockRequest>> reqHandler(pldmTransport, event, 117 instanceIdDb, false, seconds(2), 118 2, milliseconds(100)); 119 pldm::Request request{}; 120 auto instanceId = instanceIdDb.next(eid); 121 EXPECT_EQ(instanceId, 0); 122 auto rc = reqHandler.registerRequest( 123 eid, instanceId, 0, 0, std::move(request), 124 std::move(std::bind_front(&HandlerTest::pldmResponseCallBack, this))); 125 EXPECT_EQ(rc, PLDM_SUCCESS); 126 127 pldm::Request requestNxt{}; 128 auto instanceIdNxt = instanceIdDb.next(eid); 129 EXPECT_EQ(instanceIdNxt, 1); 130 rc = reqHandler.registerRequest( 131 eid, instanceIdNxt, 0, 0, std::move(requestNxt), 132 std::move(std::bind_front(&HandlerTest::pldmResponseCallBack, this))); 133 EXPECT_EQ(rc, PLDM_SUCCESS); 134 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, instanceId, 0, 0, responsePtr, 138 sizeof(response)); 139 EXPECT_EQ(validResponse, true); 140 EXPECT_EQ(callbackCount, 1); 141 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, instanceIdNxt, 0, 0, responsePtr, 148 sizeof(response)); 149 150 EXPECT_EQ(validResponse, true); 151 EXPECT_EQ(callbackCount, 2); 152 } 153