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