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