blob: 142c9e9c7455c6327820f8143ba5521a57d42499 [file]
#include "NVMeCache.hpp"
#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
class TestNVMeNestedRefresh : public testing::Test
{
public:
boost::asio::io_context io;
std::shared_ptr<Scheduler<std::chrono::steady_clock>> scheduler;
TestNVMeNestedRefresh()
{
scheduler = std::make_shared<Scheduler<std::chrono::steady_clock>>(io);
}
};
class MetricMock : public MetricBase<std::chrono::steady_clock>
{
public:
explicit MetricMock(
std::shared_ptr<Scheduler<std::chrono::steady_clock>> scheduler) :
MetricBase<std::chrono::steady_clock>(
std::move(scheduler), std::chrono::steady_clock::duration::max())
{}
MOCK_METHOD(
void, readDevice,
(std::function<void(std::error_code ec, size_t size, bool complete)> &&
cb),
(noexcept, override));
MOCK_METHOD((std::string_view), getIdentifier, (),
(const, noexcept, override));
MOCK_METHOD(bool, isCacheValid, (), (const, noexcept, override));
MOCK_METHOD((std::tuple<std::chrono::time_point<ClockType>,
std::chrono::time_point<ClockType>,
std::span<const uint8_t>>),
getCache, (), (const, noexcept, override));
};
TEST_F(TestNVMeNestedRefresh, NestedRefresh)
{
auto mtx = std::make_shared<MetricMock>(scheduler);
EXPECT_CALL(*mtx, readDevice)
.WillRepeatedly(
[](std::function<void(std::error_code ec, size_t size,
bool complete)>&& cb) { cb({}, 0, true); });
scheduler->start();
scheduler->dequeue();
bool cb1Called = false;
bool cb2Called = false;
mtx->refresh([&](std::error_code ec) {
EXPECT_FALSE(ec);
cb1Called = true;
// Issue 1: isRefreshing() should be false when the callback is
// triggered for completion In the bugged version, it is still true.
EXPECT_FALSE(mtx->isRefreshing());
// Issue 2: Nested refresh
mtx->refresh([&](std::error_code ec) {
EXPECT_FALSE(ec);
cb2Called = true;
});
});
io.run_one(); // Run the first refresh
io.poll(); // Run any remaining handlers
EXPECT_TRUE(cb1Called);
// In the bugged version, cb2 will NEVER be called because it was cleared
// and task->refreshing was reset to false by the first refresh completion
// logic.
EXPECT_TRUE(cb2Called);
}
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}