1 #include "common/transport.hpp" 2 #include "mock_request.hpp" 3 4 #include <libpldm/base.h> 5 6 #include <sdbusplus/timer.hpp> 7 #include <sdeventplus/event.hpp> 8 9 #include <gmock/gmock.h> 10 #include <gtest/gtest.h> 11 12 using namespace pldm::requester; 13 using namespace std::chrono; 14 using ::testing::AtLeast; 15 using ::testing::Between; 16 using ::testing::Exactly; 17 using ::testing::Return; 18 19 class RequestIntfTest : public testing::Test 20 { 21 protected: RequestIntfTest()22 RequestIntfTest() : event(sdeventplus::Event::get_default()) {} 23 24 /** @brief This function runs the sd_event_run in a loop till all the events 25 * in the testcase are dispatched and exits when there are no events 26 * for the timeout time. 27 * 28 * @param[in] timeout - maximum time to wait for an event 29 */ waitEventExpiry(milliseconds timeout)30 void waitEventExpiry(milliseconds timeout) 31 { 32 while (1) 33 { 34 auto sleepTime = duration_cast<microseconds>(timeout); 35 // Returns 0 on timeout 36 if (!sd_event_run(event.get(), sleepTime.count())) 37 { 38 break; 39 } 40 } 41 } 42 43 int fd = 0; 44 mctp_eid_t eid = 0; 45 PldmTransport* pldmTransport = nullptr; 46 sdeventplus::Event event; 47 }; 48 49 TEST_F(RequestIntfTest, 0Retries100msTimeout) 50 { 51 std::vector<uint8_t> requestMsg; 52 MockRequest request(pldmTransport, eid, event, std::move(requestMsg), 0, 53 milliseconds(100), false); 54 EXPECT_CALL(request, send()) 55 .Times(Exactly(1)) 56 .WillOnce(Return(PLDM_SUCCESS)); 57 auto rc = request.start(); 58 EXPECT_EQ(rc, PLDM_SUCCESS); 59 } 60 61 TEST_F(RequestIntfTest, 2Retries100msTimeout) 62 { 63 std::vector<uint8_t> requestMsg; 64 MockRequest request(pldmTransport, eid, event, std::move(requestMsg), 2, 65 milliseconds(100), false); 66 // send() is called a total of 3 times, the original plus two retries 67 EXPECT_CALL(request, send()).Times(3).WillRepeatedly(Return(PLDM_SUCCESS)); 68 auto rc = request.start(); 69 EXPECT_EQ(rc, PLDM_SUCCESS); 70 waitEventExpiry(milliseconds(500)); 71 } 72 73 TEST_F(RequestIntfTest, 9Retries100msTimeoutRequestStoppedAfter1sec) 74 { 75 std::vector<uint8_t> requestMsg; 76 MockRequest request(pldmTransport, eid, event, std::move(requestMsg), 9, 77 milliseconds(100), false); 78 // send() will be called a total of 10 times, the original plus 9 retries. 79 // In a ideal scenario send() would have been called 10 times in 1 sec (when 80 // the timer is stopped) with a timeout of 100ms. Because there are delays 81 // in dispatch, the range is kept between 5 and 10. This recreates the 82 // situation where the Instance ID expires before the all the retries have 83 // been completed and the timer is stopped. 84 EXPECT_CALL(request, send()) 85 .Times(Between(5, 10)) 86 .WillRepeatedly(Return(PLDM_SUCCESS)); 87 auto rc = request.start(); 88 EXPECT_EQ(rc, PLDM_SUCCESS); 89 __anon6eeae7e50102(void) 90 auto requestStopCallback = [&](void) { request.stop(); }; 91 sdbusplus::Timer timer(event.get(), requestStopCallback); 92 timer.start(duration_cast<microseconds>(seconds(1))); 93 94 waitEventExpiry(milliseconds(500)); 95 } 96 97 TEST_F(RequestIntfTest, 2Retries100msTimeoutsendReturnsError) 98 { 99 std::vector<uint8_t> requestMsg; 100 MockRequest request(pldmTransport, eid, event, std::move(requestMsg), 2, 101 milliseconds(100), false); 102 EXPECT_CALL(request, send()).Times(Exactly(1)).WillOnce(Return(PLDM_ERROR)); 103 auto rc = request.start(); 104 EXPECT_EQ(rc, PLDM_ERROR); 105 } 106