1 #include "libpldm/base.h" 2 3 #include "mock_request.hpp" 4 5 #include <sdbusplus/timer.hpp> 6 #include <sdeventplus/event.hpp> 7 8 #include <gmock/gmock.h> 9 #include <gtest/gtest.h> 10 11 using namespace pldm::requester; 12 using namespace std::chrono; 13 using ::testing::AtLeast; 14 using ::testing::Between; 15 using ::testing::Exactly; 16 using ::testing::Return; 17 18 class RequestIntfTest : public testing::Test 19 { 20 protected: 21 RequestIntfTest() : event(sdeventplus::Event::get_default()) 22 {} 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 */ 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 sdeventplus::Event event; 46 std::vector<uint8_t> requestMsg; 47 }; 48 49 TEST_F(RequestIntfTest, 0Retries100msTimeout) 50 { 51 MockRequest request(fd, eid, event, std::move(requestMsg), 0, 52 milliseconds(100), false); 53 EXPECT_CALL(request, send()) 54 .Times(Exactly(1)) 55 .WillOnce(Return(PLDM_SUCCESS)); 56 auto rc = request.start(); 57 EXPECT_EQ(rc, PLDM_SUCCESS); 58 } 59 60 TEST_F(RequestIntfTest, 2Retries100msTimeout) 61 { 62 MockRequest request(fd, eid, event, std::move(requestMsg), 2, 63 milliseconds(100), false); 64 // send() is called a total of 3 times, the original plus two retries 65 EXPECT_CALL(request, send()).Times(3).WillRepeatedly(Return(PLDM_SUCCESS)); 66 auto rc = request.start(); 67 EXPECT_EQ(rc, PLDM_SUCCESS); 68 waitEventExpiry(milliseconds(500)); 69 } 70 71 TEST_F(RequestIntfTest, 9Retries100msTimeoutRequestStoppedAfter1sec) 72 { 73 MockRequest request(fd, eid, event, std::move(requestMsg), 9, 74 milliseconds(100), false); 75 // send() will be called a total of 10 times, the original plus 9 retries. 76 // In a ideal scenario send() would have been called 10 times in 1 sec (when 77 // the timer is stopped) with a timeout of 100ms. Because there are delays 78 // in dispatch, the range is kept between 5 and 10. This recreates the 79 // situation where the Instance ID expires before the all the retries have 80 // been completed and the timer is stopped. 81 EXPECT_CALL(request, send()) 82 .Times(Between(5, 10)) 83 .WillRepeatedly(Return(PLDM_SUCCESS)); 84 auto rc = request.start(); 85 EXPECT_EQ(rc, PLDM_SUCCESS); 86 87 auto requestStopCallback = [&](void) { request.stop(); }; 88 phosphor::Timer timer(event.get(), requestStopCallback); 89 timer.start(duration_cast<microseconds>(seconds(1))); 90 91 waitEventExpiry(milliseconds(500)); 92 } 93 94 TEST_F(RequestIntfTest, 2Retries100msTimeoutsendReturnsError) 95 { 96 MockRequest request(fd, eid, event, std::move(requestMsg), 2, 97 milliseconds(100), false); 98 EXPECT_CALL(request, send()).Times(Exactly(1)).WillOnce(Return(PLDM_ERROR)); 99 auto rc = request.start(); 100 EXPECT_EQ(rc, PLDM_ERROR); 101 } 102