blob: 51b337d1100f406957bea07386332a418497185c [file] [log] [blame]
#include "common/transport.hpp"
#include "mock_request.hpp"
#include <libpldm/base.h>
#include <sdbusplus/timer.hpp>
#include <sdeventplus/event.hpp>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
using namespace pldm::requester;
using namespace std::chrono;
using ::testing::AtLeast;
using ::testing::Between;
using ::testing::Exactly;
using ::testing::Return;
class RequestIntfTest : public testing::Test
{
protected:
RequestIntfTest() : event(sdeventplus::Event::get_default()) {}
/** @brief This function runs the sd_event_run in a loop till all the events
* in the testcase are dispatched and exits when there are no events
* for the timeout time.
*
* @param[in] timeout - maximum time to wait for an event
*/
void waitEventExpiry(milliseconds timeout)
{
while (1)
{
auto sleepTime = duration_cast<microseconds>(timeout);
// Returns 0 on timeout
if (!sd_event_run(event.get(), sleepTime.count()))
{
break;
}
}
}
int fd = 0;
mctp_eid_t eid = 0;
PldmTransport* pldmTransport = nullptr;
sdeventplus::Event event;
};
TEST_F(RequestIntfTest, 0Retries100msTimeout)
{
std::vector<uint8_t> requestMsg;
MockRequest request(pldmTransport, eid, event, std::move(requestMsg), 0,
milliseconds(100), false);
EXPECT_CALL(request, send())
.Times(Exactly(1))
.WillOnce(Return(PLDM_SUCCESS));
auto rc = request.start();
EXPECT_EQ(rc, PLDM_SUCCESS);
}
TEST_F(RequestIntfTest, 2Retries100msTimeout)
{
std::vector<uint8_t> requestMsg;
MockRequest request(pldmTransport, eid, event, std::move(requestMsg), 2,
milliseconds(100), false);
// send() is called a total of 3 times, the original plus two retries
EXPECT_CALL(request, send()).Times(3).WillRepeatedly(Return(PLDM_SUCCESS));
auto rc = request.start();
EXPECT_EQ(rc, PLDM_SUCCESS);
waitEventExpiry(milliseconds(500));
}
TEST_F(RequestIntfTest, 9Retries100msTimeoutRequestStoppedAfter1sec)
{
std::vector<uint8_t> requestMsg;
MockRequest request(pldmTransport, eid, event, std::move(requestMsg), 9,
milliseconds(100), false);
// send() will be called a total of 10 times, the original plus 9 retries.
// In a ideal scenario send() would have been called 10 times in 1 sec (when
// the timer is stopped) with a timeout of 100ms. Because there are delays
// in dispatch, the range is kept between 5 and 10. This recreates the
// situation where the Instance ID expires before the all the retries have
// been completed and the timer is stopped.
EXPECT_CALL(request, send())
.Times(Between(5, 10))
.WillRepeatedly(Return(PLDM_SUCCESS));
auto rc = request.start();
EXPECT_EQ(rc, PLDM_SUCCESS);
auto requestStopCallback = [&](void) { request.stop(); };
phosphor::Timer timer(event.get(), requestStopCallback);
timer.start(duration_cast<microseconds>(seconds(1)));
waitEventExpiry(milliseconds(500));
}
TEST_F(RequestIntfTest, 2Retries100msTimeoutsendReturnsError)
{
std::vector<uint8_t> requestMsg;
MockRequest request(pldmTransport, eid, event, std::move(requestMsg), 2,
milliseconds(100), false);
EXPECT_CALL(request, send()).Times(Exactly(1)).WillOnce(Return(PLDM_ERROR));
auto rc = request.start();
EXPECT_EQ(rc, PLDM_ERROR);
}