xref: /openbmc/pldm/requester/test/request_test.cpp (revision 35535cf2a389efd9efcd01ffab32497320398f79)
11ed5f7a6SRashmica Gupta #include "common/transport.hpp"
274f27c73STom Joseph #include "mock_request.hpp"
374f27c73STom Joseph 
4c453e164SGeorge Liu #include <libpldm/base.h>
5c453e164SGeorge Liu 
674f27c73STom Joseph #include <sdbusplus/timer.hpp>
774f27c73STom Joseph #include <sdeventplus/event.hpp>
874f27c73STom Joseph 
974f27c73STom Joseph #include <gmock/gmock.h>
1074f27c73STom Joseph #include <gtest/gtest.h>
1174f27c73STom Joseph 
1274f27c73STom Joseph using namespace pldm::requester;
1374f27c73STom Joseph using namespace std::chrono;
1474f27c73STom Joseph using ::testing::AtLeast;
1574f27c73STom Joseph using ::testing::Between;
1674f27c73STom Joseph using ::testing::Exactly;
1774f27c73STom Joseph using ::testing::Return;
1874f27c73STom Joseph 
1974f27c73STom Joseph class RequestIntfTest : public testing::Test
2074f27c73STom Joseph {
2174f27c73STom Joseph   protected:
RequestIntfTest()226da4f91bSPatrick Williams     RequestIntfTest() : event(sdeventplus::Event::get_default()) {}
2374f27c73STom Joseph 
2474f27c73STom Joseph     /** @brief This function runs the sd_event_run in a loop till all the events
2574f27c73STom Joseph      *         in the testcase are dispatched and exits when there are no events
2674f27c73STom Joseph      *         for the timeout time.
2774f27c73STom Joseph      *
2874f27c73STom Joseph      *  @param[in] timeout - maximum time to wait for an event
2974f27c73STom Joseph      */
waitEventExpiry(milliseconds timeout)3074f27c73STom Joseph     void waitEventExpiry(milliseconds timeout)
3174f27c73STom Joseph     {
3274f27c73STom Joseph         while (1)
3374f27c73STom Joseph         {
3474f27c73STom Joseph             auto sleepTime = duration_cast<microseconds>(timeout);
3574f27c73STom Joseph             // Returns 0 on timeout
3674f27c73STom Joseph             if (!sd_event_run(event.get(), sleepTime.count()))
3774f27c73STom Joseph             {
3874f27c73STom Joseph                 break;
3974f27c73STom Joseph             }
4074f27c73STom Joseph         }
4174f27c73STom Joseph     }
4274f27c73STom Joseph 
4374f27c73STom Joseph     int fd = 0;
4474f27c73STom Joseph     mctp_eid_t eid = 0;
451ed5f7a6SRashmica Gupta     PldmTransport* pldmTransport = nullptr;
4674f27c73STom Joseph     sdeventplus::Event event;
4774f27c73STom Joseph };
4874f27c73STom Joseph 
4974f27c73STom Joseph TEST_F(RequestIntfTest, 0Retries100msTimeout)
5074f27c73STom Joseph {
511ed5f7a6SRashmica Gupta     std::vector<uint8_t> requestMsg;
521ed5f7a6SRashmica Gupta     MockRequest request(pldmTransport, eid, event, std::move(requestMsg), 0,
531ed5f7a6SRashmica Gupta                         milliseconds(100), false);
5474f27c73STom Joseph     EXPECT_CALL(request, send())
5574f27c73STom Joseph         .Times(Exactly(1))
5674f27c73STom Joseph         .WillOnce(Return(PLDM_SUCCESS));
5774f27c73STom Joseph     auto rc = request.start();
58a5ed6585STom Joseph     EXPECT_EQ(rc, PLDM_SUCCESS);
5974f27c73STom Joseph }
6074f27c73STom Joseph 
6174f27c73STom Joseph TEST_F(RequestIntfTest, 2Retries100msTimeout)
6274f27c73STom Joseph {
631ed5f7a6SRashmica Gupta     std::vector<uint8_t> requestMsg;
641ed5f7a6SRashmica Gupta     MockRequest request(pldmTransport, eid, event, std::move(requestMsg), 2,
651ed5f7a6SRashmica Gupta                         milliseconds(100), false);
6674f27c73STom Joseph     // send() is called a total of 3 times, the original plus two retries
6774f27c73STom Joseph     EXPECT_CALL(request, send()).Times(3).WillRepeatedly(Return(PLDM_SUCCESS));
6874f27c73STom Joseph     auto rc = request.start();
69a5ed6585STom Joseph     EXPECT_EQ(rc, PLDM_SUCCESS);
7074f27c73STom Joseph     waitEventExpiry(milliseconds(500));
7174f27c73STom Joseph }
7274f27c73STom Joseph 
7374f27c73STom Joseph TEST_F(RequestIntfTest, 9Retries100msTimeoutRequestStoppedAfter1sec)
7474f27c73STom Joseph {
751ed5f7a6SRashmica Gupta     std::vector<uint8_t> requestMsg;
761ed5f7a6SRashmica Gupta     MockRequest request(pldmTransport, eid, event, std::move(requestMsg), 9,
771ed5f7a6SRashmica Gupta                         milliseconds(100), false);
7874f27c73STom Joseph     // send() will be called a total of 10 times, the original plus 9 retries.
7974f27c73STom Joseph     // In a ideal scenario send() would have been called 10 times in 1 sec (when
8074f27c73STom Joseph     // the timer is stopped) with a timeout of 100ms. Because there are delays
8174f27c73STom Joseph     // in dispatch, the range is kept between 5 and 10. This recreates the
8274f27c73STom Joseph     // situation where the Instance ID expires before the all the retries have
8374f27c73STom Joseph     // been completed and the timer is stopped.
8474f27c73STom Joseph     EXPECT_CALL(request, send())
8574f27c73STom Joseph         .Times(Between(5, 10))
8674f27c73STom Joseph         .WillRepeatedly(Return(PLDM_SUCCESS));
8774f27c73STom Joseph     auto rc = request.start();
88a5ed6585STom Joseph     EXPECT_EQ(rc, PLDM_SUCCESS);
8974f27c73STom Joseph 
__anon6eeae7e50102(void) 9074f27c73STom Joseph     auto requestStopCallback = [&](void) { request.stop(); };
91*35535cf2SPatrick Williams     sdbusplus::Timer timer(event.get(), requestStopCallback);
9274f27c73STom Joseph     timer.start(duration_cast<microseconds>(seconds(1)));
9374f27c73STom Joseph 
9474f27c73STom Joseph     waitEventExpiry(milliseconds(500));
9574f27c73STom Joseph }
9674f27c73STom Joseph 
9774f27c73STom Joseph TEST_F(RequestIntfTest, 2Retries100msTimeoutsendReturnsError)
9874f27c73STom Joseph {
991ed5f7a6SRashmica Gupta     std::vector<uint8_t> requestMsg;
1001ed5f7a6SRashmica Gupta     MockRequest request(pldmTransport, eid, event, std::move(requestMsg), 2,
1011ed5f7a6SRashmica Gupta                         milliseconds(100), false);
10274f27c73STom Joseph     EXPECT_CALL(request, send()).Times(Exactly(1)).WillOnce(Return(PLDM_ERROR));
10374f27c73STom Joseph     auto rc = request.start();
104a5ed6585STom Joseph     EXPECT_EQ(rc, PLDM_ERROR);
10574f27c73STom Joseph }
106