#include "test/librbd/test_mock_fixture.h"
#include "test/librbd/test_support.h"
#include "test/librbd/mock/MockImageCtx.h"
+#include "test/librbd/mock/io/MockObjectDispatch.h"
#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
#include "common/bit_vector.hpp"
#include "librbd/AsyncRequest.h"
#include "librbd/internal.h"
#include "librbd/ObjectMap.h"
#include "librbd/Utils.h"
-#include "librbd/io/ObjectRequest.h"
#include "librbd/operation/TrimRequest.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include <boost/variant.hpp>
namespace librbd {
namespace {
void async_complete(int r) {
on_finish->complete(r);
+ delete this;
}
bool is_canceled() const {
namespace io {
-template <>
-struct ObjectRequest<librbd::MockTestImageCtx> : public ObjectRequestHandle {
- static ObjectRequest* s_instance;
- Context *on_finish = nullptr;
-
- static ObjectRequest* create_discard(librbd::MockTestImageCtx *ictx,
- const std::string &oid,
- uint64_t object_no,
- uint64_t object_off,
- uint64_t object_len,
- const ::SnapContext &snapc,
- bool disable_remove_on_clone,
- bool update_object_map,
- const ZTracer::Trace &parent_trace,
- Context *completion) {
- assert(s_instance != nullptr);
- EXPECT_FALSE(disable_remove_on_clone);
- s_instance->on_finish = completion;
- s_instance->construct(object_off, object_len, update_object_map);
- return s_instance;
+struct DiscardVisitor
+ : public boost::static_visitor<ObjectDispatchSpec::DiscardRequest*> {
+ ObjectDispatchSpec::DiscardRequest*
+ operator()(ObjectDispatchSpec::DiscardRequest& discard) const {
+ return &discard;
}
- ObjectRequest() {
- s_instance = this;
+ template <typename T>
+ ObjectDispatchSpec::DiscardRequest*
+ operator()(T& t) const {
+ return nullptr;
}
-
- MOCK_METHOD3(construct, void(uint64_t, uint64_t, bool));
- MOCK_METHOD0(send, void());
- MOCK_METHOD1(fail, void(int));
};
-ObjectRequest<librbd::MockTestImageCtx>* ObjectRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
-
} // namespace io
} // namespace librbd
class TestMockOperationTrimRequest : public TestMockFixture {
public:
typedef TrimRequest<MockTestImageCtx> MockTrimRequest;
- typedef librbd::io::ObjectRequest<MockTestImageCtx> MockObjectRequest;
int create_snapshot(const char *snap_name) {
librbd::ImageCtx *ictx;
}
void expect_object_discard(MockImageCtx &mock_image_ctx,
- MockObjectRequest &mock_object_request,
+ io::MockObjectDispatch& mock_io_object_dispatch,
uint64_t offset, uint64_t length,
- bool update_object_map, int ret_val) {
- EXPECT_CALL(mock_object_request, construct(offset, length,
- update_object_map));
- EXPECT_CALL(mock_object_request, send())
- .WillOnce(Invoke([&mock_image_ctx, &mock_object_request, ret_val]() {
- mock_image_ctx.op_work_queue->queue(mock_object_request.on_finish, ret_val);
- }));
+ bool update_object_map, int r) {
+ EXPECT_CALL(*mock_image_ctx.io_object_dispatcher, send(_))
+ .WillOnce(Invoke([&mock_image_ctx, offset, length, update_object_map, r]
+ (io::ObjectDispatchSpec* spec) {
+ auto discard = boost::apply_visitor(io::DiscardVisitor(), spec->request);
+ ASSERT_TRUE(discard != nullptr);
+ ASSERT_EQ(offset, discard->object_off);
+ ASSERT_EQ(length, discard->object_len);
+ int flags = 0;
+ if (!update_object_map) {
+ flags = io::OBJECT_DISCARD_FLAG_DISABLE_OBJECT_MAP_UPDATE;
+ }
+ ASSERT_EQ(flags, discard->discard_flags);
+
+ spec->dispatch_result = io::DISPATCH_RESULT_COMPLETE;
+ mock_image_ctx.op_work_queue->queue(&spec->dispatcher_ctx, r);
+ }));
}
};
true, 0);
// copy-up
+ io::MockObjectDispatch mock_io_object_dispatch;
expect_get_parent_overlap(mock_image_ctx, ictx->get_object_size());
expect_get_object_name(mock_image_ctx, 0, "object0");
-
- MockObjectRequest mock_object_request;
- expect_object_discard(mock_image_ctx, mock_object_request, 0,
+ expect_object_discard(mock_image_ctx, mock_io_object_dispatch, 0,
ictx->get_object_size(), false, 0);
// remove
EXPECT_CALL(mock_image_ctx, get_stripe_count()).WillOnce(Return(ictx->get_stripe_count()));
// boundary
- MockObjectRequest mock_object_request;
- expect_object_discard(mock_image_ctx, mock_object_request, 1,
+ io::MockObjectDispatch mock_io_object_dispatch;
+ expect_object_discard(mock_image_ctx, mock_io_object_dispatch, 1,
ictx->get_object_size() - 1, true, 0);
C_SaferCond cond_ctx;
false, 0);
// copy-up
+ io::MockObjectDispatch mock_io_object_dispatch;
expect_get_parent_overlap(mock_image_ctx, ictx->get_object_size());
expect_get_object_name(mock_image_ctx, 0, "object0");
-
- MockObjectRequest mock_object_request;
- expect_object_discard(mock_image_ctx, mock_object_request, 0,
+ expect_object_discard(mock_image_ctx, mock_io_object_dispatch, 0,
ictx->get_object_size(), false, -EINVAL);
C_SaferCond cond_ctx;
EXPECT_CALL(mock_image_ctx, get_stripe_count()).WillOnce(Return(ictx->get_stripe_count()));
// boundary
- MockObjectRequest mock_object_request;
- expect_object_discard(mock_image_ctx, mock_object_request, 1,
+ io::MockObjectDispatch mock_io_object_dispatch;
+ expect_object_discard(mock_image_ctx, mock_io_object_dispatch, 1,
ictx->get_object_size() - 1, true, -EINVAL);
C_SaferCond cond_ctx;