From 19fcec84d8d7d21e796c7624e521b60d28ee21ed Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:45:59 +0200 Subject: Adding upstream version 16.2.11+ds. Signed-off-by: Daniel Baumann --- src/test/librbd/operation/test_mock_Request.cc | 175 +++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 src/test/librbd/operation/test_mock_Request.cc (limited to 'src/test/librbd/operation/test_mock_Request.cc') diff --git a/src/test/librbd/operation/test_mock_Request.cc b/src/test/librbd/operation/test_mock_Request.cc new file mode 100644 index 000000000..5c5e7a375 --- /dev/null +++ b/src/test/librbd/operation/test_mock_Request.cc @@ -0,0 +1,175 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "test/librbd/test_mock_fixture.h" +#include "test/librbd/test_support.h" +#include "test/librbd/mock/MockImageCtx.h" +#include "test/librbd/mock/MockJournal.h" +#include "librbd/AsyncRequest.h" +#include "librbd/operation/Request.h" + +namespace librbd { +namespace { + +struct MockTestImageCtx : public MockImageCtx { + MockTestImageCtx(ImageCtx &image_ctx) : MockImageCtx(image_ctx) { + } +}; + +} // anonymous namespace + +template <> +struct AsyncRequest { + librbd::MockTestImageCtx &m_image_ctx; + Context *m_on_finish; + + AsyncRequest(librbd::MockTestImageCtx &image_ctx, Context *on_finish) + : m_image_ctx(image_ctx), m_on_finish(on_finish) { + } + virtual ~AsyncRequest() { + } + + virtual void finish(int r) { + m_on_finish->complete(r); + } + virtual void finish_and_destroy(int r) { + finish(r); + delete this; + } +}; + +} // namespace librbd + +#include "librbd/operation/Request.cc" + +namespace librbd { +namespace journal { + +std::ostream& operator<<(std::ostream& os, const Event&) { + return os; +} + +} // namespace journal + +namespace operation { + +using ::testing::InSequence; +using ::testing::Invoke; +using ::testing::Return; + +struct MockRequest : public Request { + MockRequest(librbd::MockTestImageCtx &image_ctx, Context *on_finish, + uint64_t journal_op_tid) + : Request(image_ctx, on_finish, journal_op_tid) { + } + + void complete(int r) { + finish_and_destroy(r); + } + + void send_op_impl(int r) { + bool appending = append_op_event< + MockRequest, &MockRequest::handle_send>(this); + if (!appending) { + complete(r); + } + } + MOCK_METHOD1(should_complete, bool(int)); + MOCK_METHOD0(send_op, void()); + MOCK_METHOD1(handle_send, Context*(int*)); + MOCK_CONST_METHOD0(can_affect_io, bool()); + MOCK_CONST_METHOD1(create_event, journal::Event(uint64_t)); +}; + +struct TestMockOperationRequest : public TestMockFixture { + void expect_can_affect_io(MockRequest &mock_request, bool can_affect) { + EXPECT_CALL(mock_request, can_affect_io()) + .WillOnce(Return(can_affect)); + } + + void expect_is_journal_replaying(MockJournal &mock_journal, bool replaying) { + EXPECT_CALL(mock_journal, is_journal_replaying()) + .WillOnce(Return(replaying)); + } + + void expect_is_journal_appending(MockJournal &mock_journal, bool appending) { + EXPECT_CALL(mock_journal, is_journal_appending()) + .WillOnce(Return(appending)); + } + + void expect_send_op(MockRequest &mock_request, int r) { + EXPECT_CALL(mock_request, send_op()) + .WillOnce(Invoke([&mock_request, r]() { + mock_request.complete(r); + })); + } + + void expect_send_op_affects_io(MockImageCtx &mock_image_ctx, + MockRequest &mock_request, int r) { + EXPECT_CALL(mock_request, send_op()) + .WillOnce(Invoke([&mock_image_ctx, &mock_request, r]() { + mock_image_ctx.image_ctx->op_work_queue->queue( + new LambdaContext([&mock_request, r](int _) { + mock_request.send_op_impl(r); + }), 0); + })); + } + +}; + +TEST_F(TestMockOperationRequest, SendJournalDisabled) { + REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); + + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + MockJournal mock_journal; + mock_image_ctx.journal = &mock_journal; + + C_SaferCond ctx; + MockRequest *mock_request = new MockRequest(mock_image_ctx, &ctx, 0); + + InSequence seq; + expect_can_affect_io(*mock_request, false); + expect_is_journal_appending(mock_journal, false); + expect_send_op(*mock_request, 0); + + { + std::shared_lock owner_locker{mock_image_ctx.owner_lock}; + mock_request->send(); + } + + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockOperationRequest, SendAffectsIOJournalDisabled) { + REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); + + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + MockJournal mock_journal; + mock_image_ctx.journal = &mock_journal; + + C_SaferCond ctx; + MockRequest *mock_request = new MockRequest(mock_image_ctx, &ctx, 0); + + InSequence seq; + expect_can_affect_io(*mock_request, true); + expect_send_op_affects_io(mock_image_ctx, *mock_request, 0); + expect_can_affect_io(*mock_request, true); + expect_is_journal_replaying(mock_journal, false); + expect_is_journal_appending(mock_journal, false); + + { + std::shared_lock owner_locker{mock_image_ctx.owner_lock}; + mock_request->send(); + } + + ASSERT_EQ(0, ctx.wait()); +} + +} // namespace operation +} // namespace librbd -- cgit v1.2.3