summaryrefslogtreecommitdiffstats
path: root/src/test
diff options
context:
space:
mode:
authoroliveiradan <doliveirabrz@gmail.com>2017-05-09 05:28:07 +0200
committeroliveiradan <doliveirabrz@gmail.com>2017-05-12 20:55:54 +0200
commitc582dc76313cc3fe52f4a9263d18d17bbe91c52a (patch)
tree3312512ab0b06a133ed17368a2b3994234eab899 /src/test
parentcommon/ceph_context: config diff get option refactored (diff)
parentMerge pull request #14984 from dmick/wip-osd-dup (diff)
downloadceph-c582dc76313cc3fe52f4a9263d18d17bbe91c52a.tar.xz
ceph-c582dc76313cc3fe52f4a9263d18d17bbe91c52a.zip
Merge remote-tracking branch 'upstream/master' into SebastienHan_config_diff_get_fr
Diffstat (limited to 'src/test')
-rwxr-xr-xsrc/test/encoding/generate-corpus-objects.sh58
-rw-r--r--src/test/librbd/journal/test_mock_PromoteRequest.cc125
-rw-r--r--src/test/librbd/operation/test_mock_SnapshotRollbackRequest.cc4
-rw-r--r--src/test/librbd/test_librbd.cc1
-rw-r--r--src/test/objectstore/Allocator_test.cc16
-rwxr-xr-xsrc/test/osd/osd-dup.sh3
-rw-r--r--src/test/rbd_mirror/image_replayer/test_mock_BootstrapRequest.cc234
7 files changed, 393 insertions, 48 deletions
diff --git a/src/test/encoding/generate-corpus-objects.sh b/src/test/encoding/generate-corpus-objects.sh
new file mode 100755
index 00000000000..6f84181ecf4
--- /dev/null
+++ b/src/test/encoding/generate-corpus-objects.sh
@@ -0,0 +1,58 @@
+#!/bin/bash -ex
+
+BDIR=`pwd`
+
+p=$1
+echo path $p
+test ! -d $p
+mkdir $p
+strings bin/ceph-osd | grep "^$p/%s__%d.%x"
+
+v=`git describe | cut -c 2-`
+echo version $v
+
+echo 'binaries look ok, vstarting'
+echo
+
+MON=3 MDS=3 OSD=5 MDS=3 MGR=2 RGW=1 ../src/vstart.sh -x -n -l --bluestore -e
+
+export PATH=bin:$PATH
+
+# do some work to generate a hopefully braod set of object instances
+
+echo 'starting some background work'
+../qa/workunits/rados/test.sh &
+../qa/workunits/rbd/test_librbd.sh &
+../qa/workunits/libcephfs/test.sh &
+../qa/workunits/rgw/run-s3tests.sh &
+ceph-syn --syn makedirs 3 3 3 &
+
+echo 'waiting a bit'
+
+sleep 10
+echo 'triggering some recovery'
+
+kill -9 `cat out/osd.0.pid`
+sleep 10
+ceph osd out 0
+sleep 10
+init-ceph start osd.0
+ceph osd in 0
+
+sleep 5
+echo 'triggering mds work'
+bin/ceph mds fail 0
+
+echo 'waiting for worker to join (and ignoring errors)'
+wait || true
+
+echo 'importing'
+../src/test/encoding/import.sh $p $v ../ceph-object-corpus/archive
+
+for d in ../ceph-object-corpus/archive/$v/objects/*
+do
+ echo prune $d
+ ../ceph-object-corpus/bin/prune.sh $d 25
+done
+
+echo 'done'
diff --git a/src/test/librbd/journal/test_mock_PromoteRequest.cc b/src/test/librbd/journal/test_mock_PromoteRequest.cc
index 805e76aaed4..209249955b1 100644
--- a/src/test/librbd/journal/test_mock_PromoteRequest.cc
+++ b/src/test/librbd/journal/test_mock_PromoteRequest.cc
@@ -24,6 +24,7 @@ namespace journal {
template <>
struct TypeTraits<MockTestImageCtx> {
typedef ::journal::MockJournalerProxy Journaler;
+ typedef ::journal::MockFutureProxy Future;
};
template <>
@@ -63,7 +64,9 @@ namespace librbd {
namespace journal {
using ::testing::_;
+using ::testing::A;
using ::testing::InSequence;
+using ::testing::Return;
using ::testing::WithArg;
class TestMockJournalPromoteRequest : public TestMockFixture {
@@ -95,6 +98,35 @@ public:
.WillOnce(WithArg<3>(CompleteContext(r, static_cast<ContextWQ*>(NULL))));
}
+ void expect_append_journaler(::journal::MockJournaler &mock_journaler) {
+ EXPECT_CALL(mock_journaler, append(_, _))
+ .WillOnce(Return(::journal::MockFutureProxy()));
+ }
+
+ void expect_future_flush(::journal::MockFuture &mock_future, int r) {
+ EXPECT_CALL(mock_future, flush(_))
+ .WillOnce(CompleteContext(r, static_cast<ContextWQ*>(NULL)));
+ }
+
+ void expect_future_committed(::journal::MockJournaler &mock_journaler) {
+ EXPECT_CALL(mock_journaler, committed(A<const ::journal::MockFutureProxy &>()));
+ }
+
+ void expect_flush_commit_position(::journal::MockJournaler &mock_journaler,
+ int r) {
+ EXPECT_CALL(mock_journaler, flush_commit_position(_))
+ .WillOnce(CompleteContext(r, static_cast<ContextWQ*>(NULL)));
+ }
+
+ void expect_start_append(::journal::MockJournaler &mock_journaler) {
+ EXPECT_CALL(mock_journaler, start_append(_, _, _));
+ }
+
+ void expect_stop_append(::journal::MockJournaler &mock_journaler, int r) {
+ EXPECT_CALL(mock_journaler, stop_append(_))
+ .WillOnce(CompleteContext(r, static_cast<ContextWQ*>(NULL)));
+ }
+
void expect_shut_down_journaler(::journal::MockJournaler &mock_journaler,
int r) {
EXPECT_CALL(mock_journaler, shut_down(_))
@@ -120,6 +152,15 @@ TEST_F(TestMockJournalPromoteRequest, SuccessOrderly) {
expect_open_journaler(mock_image_ctx, mock_open_request, 0);
expect_allocate_tag(mock_journaler,
{Journal<>::ORPHAN_MIRROR_UUID, true, 567, 1}, 0);
+
+ ::journal::MockFuture mock_future;
+ expect_start_append(mock_journaler);
+ expect_append_journaler(mock_journaler);
+ expect_future_flush(mock_future, 0);
+ expect_future_committed(mock_journaler);
+ expect_flush_commit_position(mock_journaler, 0);
+ expect_stop_append(mock_journaler, 0);
+
expect_shut_down_journaler(mock_journaler, 0);
C_SaferCond ctx;
@@ -145,6 +186,15 @@ TEST_F(TestMockJournalPromoteRequest, SuccessForced) {
expect_open_journaler(mock_image_ctx, mock_open_request, 0);
expect_allocate_tag(mock_journaler,
{Journal<>::LOCAL_MIRROR_UUID, true, 567, 0}, 0);
+
+ ::journal::MockFuture mock_future;
+ expect_start_append(mock_journaler);
+ expect_append_journaler(mock_journaler);
+ expect_future_flush(mock_future, 0);
+ expect_future_committed(mock_journaler);
+ expect_flush_commit_position(mock_journaler, 0);
+ expect_stop_append(mock_journaler, 0);
+
expect_shut_down_journaler(mock_journaler, 0);
C_SaferCond ctx;
@@ -201,6 +251,72 @@ TEST_F(TestMockJournalPromoteRequest, AllocateTagError) {
ASSERT_EQ(-EBADMSG, ctx.wait());
}
+TEST_F(TestMockJournalPromoteRequest, AppendEventError) {
+ REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
+
+ librbd::ImageCtx *ictx;
+ ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+ MockTestImageCtx mock_image_ctx(*ictx);
+ ::journal::MockJournaler mock_journaler;
+ MockOpenRequest mock_open_request;
+
+ expect_op_work_queue(mock_image_ctx);
+
+ InSequence seq;
+ expect_construct_journaler(mock_journaler);
+ expect_open_journaler(mock_image_ctx, mock_open_request, 0);
+ expect_allocate_tag(mock_journaler,
+ {Journal<>::ORPHAN_MIRROR_UUID, true, 567, 1}, 0);
+
+ ::journal::MockFuture mock_future;
+ expect_start_append(mock_journaler);
+ expect_append_journaler(mock_journaler);
+ expect_future_flush(mock_future, -EPERM);
+ expect_stop_append(mock_journaler, 0);
+
+ expect_shut_down_journaler(mock_journaler, 0);
+
+ C_SaferCond ctx;
+ auto req = MockPromoteRequest::create(&mock_image_ctx, false, &ctx);
+ req->send();
+ ASSERT_EQ(-EPERM, ctx.wait());
+}
+
+TEST_F(TestMockJournalPromoteRequest, CommitEventError) {
+ REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
+
+ librbd::ImageCtx *ictx;
+ ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+ MockTestImageCtx mock_image_ctx(*ictx);
+ ::journal::MockJournaler mock_journaler;
+ MockOpenRequest mock_open_request;
+
+ expect_op_work_queue(mock_image_ctx);
+
+ InSequence seq;
+ expect_construct_journaler(mock_journaler);
+ expect_open_journaler(mock_image_ctx, mock_open_request, 0);
+ expect_allocate_tag(mock_journaler,
+ {Journal<>::ORPHAN_MIRROR_UUID, true, 567, 1}, 0);
+
+ ::journal::MockFuture mock_future;
+ expect_start_append(mock_journaler);
+ expect_append_journaler(mock_journaler);
+ expect_future_flush(mock_future, 0);
+ expect_future_committed(mock_journaler);
+ expect_flush_commit_position(mock_journaler, -EINVAL);
+ expect_stop_append(mock_journaler, 0);
+
+ expect_shut_down_journaler(mock_journaler, 0);
+
+ C_SaferCond ctx;
+ auto req = MockPromoteRequest::create(&mock_image_ctx, false, &ctx);
+ req->send();
+ ASSERT_EQ(-EINVAL, ctx.wait());
+}
+
TEST_F(TestMockJournalPromoteRequest, ShutDownError) {
REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
@@ -218,6 +334,15 @@ TEST_F(TestMockJournalPromoteRequest, ShutDownError) {
expect_open_journaler(mock_image_ctx, mock_open_request, 0);
expect_allocate_tag(mock_journaler,
{Journal<>::LOCAL_MIRROR_UUID, true, 567, 0}, 0);
+
+ ::journal::MockFuture mock_future;
+ expect_start_append(mock_journaler);
+ expect_append_journaler(mock_journaler);
+ expect_future_flush(mock_future, 0);
+ expect_future_committed(mock_journaler);
+ expect_flush_commit_position(mock_journaler, 0);
+ expect_stop_append(mock_journaler, 0);
+
expect_shut_down_journaler(mock_journaler, -EINVAL);
C_SaferCond ctx;
diff --git a/src/test/librbd/operation/test_mock_SnapshotRollbackRequest.cc b/src/test/librbd/operation/test_mock_SnapshotRollbackRequest.cc
index 1f8b4addf05..1341864720e 100644
--- a/src/test/librbd/operation/test_mock_SnapshotRollbackRequest.cc
+++ b/src/test/librbd/operation/test_mock_SnapshotRollbackRequest.cc
@@ -70,10 +70,6 @@ struct AsyncRequest<MockOperationImageCtx> : public AsyncRequest<MockImageCtx> {
#include "librbd/operation/Request.cc"
#include "librbd/operation/SnapshotRollbackRequest.cc"
-template class librbd::AsyncRequest<librbd::MockImageCtx>;
-template class librbd::AsyncObjectThrottle<librbd::MockImageCtx>;
-template class librbd::operation::Request<librbd::MockImageCtx>;
-
namespace librbd {
namespace operation {
diff --git a/src/test/librbd/test_librbd.cc b/src/test/librbd/test_librbd.cc
index edda51c77b4..f16fbcca2a9 100644
--- a/src/test/librbd/test_librbd.cc
+++ b/src/test/librbd/test_librbd.cc
@@ -84,6 +84,7 @@ static int get_features(bool *old_format, uint64_t *features)
cout << "using new format!" << std::endl;
} else {
*old_format = true;
+ *features = 0;
cout << "using old format" << std::endl;
}
diff --git a/src/test/objectstore/Allocator_test.cc b/src/test/objectstore/Allocator_test.cc
index 3a408265962..65f8e47bd08 100644
--- a/src/test/objectstore/Allocator_test.cc
+++ b/src/test/objectstore/Allocator_test.cc
@@ -200,6 +200,22 @@ TEST_P(AllocTest, test_alloc_failure)
}
}
+TEST_P(AllocTest, test_alloc_big)
+{
+ int64_t block_size = 4096;
+ int64_t blocks = 104857600;
+ int64_t mas = 4096;
+ init_alloc(blocks*block_size, block_size);
+ alloc->init_add_free(2*block_size, (blocks-2)*block_size);
+ for (int64_t big = mas; big < 1048576*128; big*=2) {
+ cout << big << std::endl;
+ EXPECT_EQ(alloc->reserve(big), 0);
+ AllocExtentVector extents;
+ EXPECT_EQ(big,
+ alloc->allocate(big, mas, 0, &extents));
+ }
+}
+
TEST_P(AllocTest, test_alloc_hint_bmap)
{
if (GetParam() == std::string("stupid")) {
diff --git a/src/test/osd/osd-dup.sh b/src/test/osd/osd-dup.sh
index 264d27ddfdb..f82a85b9080 100755
--- a/src/test/osd/osd-dup.sh
+++ b/src/test/osd/osd-dup.sh
@@ -12,6 +12,9 @@ function run() {
CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
CEPH_ARGS+="--mon-host=$CEPH_MON "
CEPH_ARGS+="--enable-experimental-unrecoverable-data-corrupting-features bluestore "
+ # avoid running out of fds in rados bench
+ CEPH_ARGS+="--filestore_wbthrottle_xfs_ios_hard_limit=900 "
+ CEPH_ARGS+="--filestore_wbthrottle_btrfs_ios_hard_limit=900 "
local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
for func in $funcs ; do
setup $dir || return 1
diff --git a/src/test/rbd_mirror/image_replayer/test_mock_BootstrapRequest.cc b/src/test/rbd_mirror/image_replayer/test_mock_BootstrapRequest.cc
index b31ab74fb58..a7c7b27b7a4 100644
--- a/src/test/rbd_mirror/image_replayer/test_mock_BootstrapRequest.cc
+++ b/src/test/rbd_mirror/image_replayer/test_mock_BootstrapRequest.cc
@@ -3,7 +3,6 @@
#include "test/rbd_mirror/test_mock_fixture.h"
#include "librbd/journal/TypeTraits.h"
-#include "tools/rbd_mirror/ImageSync.h"
#include "tools/rbd_mirror/ImageSyncThrottler.h"
#include "tools/rbd_mirror/Threads.h"
#include "tools/rbd_mirror/image_replayer/BootstrapRequest.h"
@@ -45,40 +44,6 @@ namespace mirror {
class ProgressContext;
template<>
-struct ImageSync<librbd::MockTestImageCtx> {
- static ImageSync* s_instance;
- Context *on_finish = nullptr;
-
- static ImageSync* create(librbd::MockTestImageCtx *local_image_ctx,
- librbd::MockTestImageCtx *remote_image_ctx,
- SafeTimer *timer, Mutex *timer_lock,
- const std::string &mirror_uuid,
- ::journal::MockJournaler *journaler,
- librbd::journal::MirrorPeerClientMeta *client_meta,
- ContextWQ *work_queue, Context *on_finish,
- ProgressContext *progress_ctx = nullptr) {
- assert(s_instance != nullptr);
- return s_instance;
- }
-
- ImageSync() {
- assert(s_instance == nullptr);
- s_instance = this;
- }
-
- void put() {
- }
-
- void get() {
- }
-
- MOCK_METHOD0(send, void());
- MOCK_METHOD0(cancel, void());
-};
-
-ImageSync<librbd::MockTestImageCtx>* ImageSync<librbd::MockTestImageCtx>::s_instance = nullptr;
-
-template<>
struct ImageSyncThrottler<librbd::MockTestImageCtx> {
MOCK_METHOD10(start_sync, void(librbd::MockTestImageCtx *local_image_ctx,
librbd::MockTestImageCtx *remote_image_ctx,
@@ -124,6 +89,7 @@ struct CloseImageRequest<librbd::MockTestImageCtx> {
template<>
struct CreateImageRequest<librbd::MockTestImageCtx> {
static CreateImageRequest* s_instance;
+ std::string *local_image_id = nullptr;
Context *on_finish = nullptr;
static CreateImageRequest* create(librados::IoCtx &local_io_ctx,
@@ -135,7 +101,7 @@ struct CreateImageRequest<librbd::MockTestImageCtx> {
std::string *local_image_id,
Context *on_finish) {
assert(s_instance != nullptr);
- *local_image_id = "local image id";
+ s_instance->local_image_id = local_image_id;
s_instance->on_finish = on_finish;
return s_instance;
}
@@ -278,6 +244,7 @@ public:
typedef ImageSyncThrottlerRef<librbd::MockTestImageCtx> MockImageSyncThrottler;
typedef BootstrapRequest<librbd::MockTestImageCtx> MockBootstrapRequest;
typedef CloseImageRequest<librbd::MockTestImageCtx> MockCloseImageRequest;
+ typedef CreateImageRequest<librbd::MockTestImageCtx> MockCreateImageRequest;
typedef IsPrimaryRequest<librbd::MockTestImageCtx> MockIsPrimaryRequest;
typedef OpenImageRequest<librbd::MockTestImageCtx> MockOpenImageRequest;
typedef OpenLocalImageRequest<librbd::MockTestImageCtx> MockOpenLocalImageRequest;
@@ -321,6 +288,18 @@ public:
}))));
}
+ void expect_journaler_register_client(::journal::MockJournaler &mock_journaler,
+ const librbd::journal::ClientData &client_data,
+ int r) {
+ bufferlist bl;
+ ::encode(client_data, bl);
+
+ EXPECT_CALL(mock_journaler, register_client(ContentsEqual(bl), _))
+ .WillOnce(WithArg<1>(Invoke([this, r](Context *on_finish) {
+ m_threads->work_queue->queue(on_finish, r);
+ })));
+ }
+
void expect_journaler_update_client(::journal::MockJournaler &mock_journaler,
const librbd::journal::ClientData &client_data,
int r) {
@@ -346,12 +325,12 @@ public:
void expect_open_local_image(MockOpenLocalImageRequest &mock_open_local_image_request,
librados::IoCtx &io_ctx, const std::string &image_id,
- librbd::MockTestImageCtx &mock_image_ctx, int r) {
+ librbd::MockTestImageCtx *mock_image_ctx, int r) {
EXPECT_CALL(mock_open_local_image_request,
construct(IsSameIoCtx(&io_ctx), image_id));
EXPECT_CALL(mock_open_local_image_request, send())
- .WillOnce(Invoke([this, &mock_open_local_image_request, &mock_image_ctx, r]() {
- *mock_open_local_image_request.image_ctx = &mock_image_ctx;
+ .WillOnce(Invoke([this, &mock_open_local_image_request, mock_image_ctx, r]() {
+ *mock_open_local_image_request.image_ctx = mock_image_ctx;
m_threads->work_queue->queue(mock_open_local_image_request.on_finish,
r);
}));
@@ -393,6 +372,25 @@ public:
Return(r)));
}
+ void expect_create_image(MockCreateImageRequest &mock_create_image_request,
+ const std::string &image_id, int r) {
+ EXPECT_CALL(mock_create_image_request, send())
+ .WillOnce(Invoke([this, &mock_create_image_request, image_id, r]() {
+ *mock_create_image_request.local_image_id = image_id;
+ m_threads->work_queue->queue(mock_create_image_request.on_finish, r);
+ }));
+ }
+
+ void expect_image_sync(MockImageSyncThrottler image_sync_throttler,
+ int r) {
+ EXPECT_CALL(*image_sync_throttler, start_sync(_, _, _, _,
+ StrEq("local mirror uuid"),
+ _, _, _, _, _))
+ .WillOnce(WithArg<8>(Invoke([this, r](Context *on_finish) {
+ m_threads->work_queue->queue(on_finish, r);
+ })));
+ }
+
bufferlist encode_tag_data(const librbd::journal::TagData &tag_data) {
bufferlist bl;
::encode(tag_data, bl);
@@ -524,7 +522,7 @@ TEST_F(TestMockImageReplayerBootstrapRequest, RemoteDemotePromote) {
mock_local_image_ctx.journal = &mock_journal;
MockOpenLocalImageRequest mock_open_local_image_request;
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
- mock_local_image_ctx.id, mock_local_image_ctx, 0);
+ mock_local_image_ctx.id, &mock_local_image_ctx, 0);
expect_is_resync_requested(mock_journal, false, 0);
// remote demotion / promotion event
@@ -599,7 +597,7 @@ TEST_F(TestMockImageReplayerBootstrapRequest, MultipleRemoteDemotePromotes) {
mock_local_image_ctx.journal = &mock_journal;
MockOpenLocalImageRequest mock_open_local_image_request;
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
- mock_local_image_ctx.id, mock_local_image_ctx, 0);
+ mock_local_image_ctx.id, &mock_local_image_ctx, 0);
expect_is_resync_requested(mock_journal, false, 0);
// remote demotion / promotion event
@@ -684,7 +682,7 @@ TEST_F(TestMockImageReplayerBootstrapRequest, LocalDemoteRemotePromote) {
mock_local_image_ctx.journal = &mock_journal;
MockOpenLocalImageRequest mock_open_local_image_request;
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
- mock_local_image_ctx.id, mock_local_image_ctx, 0);
+ mock_local_image_ctx.id, &mock_local_image_ctx, 0);
expect_is_resync_requested(mock_journal, false, 0);
// remote demotion / promotion event
@@ -757,7 +755,7 @@ TEST_F(TestMockImageReplayerBootstrapRequest, SplitBrainForcePromote) {
mock_local_image_ctx.journal = &mock_journal;
MockOpenLocalImageRequest mock_open_local_image_request;
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
- mock_local_image_ctx.id, mock_local_image_ctx, 0);
+ mock_local_image_ctx.id, &mock_local_image_ctx, 0);
expect_is_resync_requested(mock_journal, false, 0);
// remote demotion / promotion event
@@ -830,7 +828,7 @@ TEST_F(TestMockImageReplayerBootstrapRequest, ResyncRequested) {
mock_local_image_ctx.journal = &mock_journal;
MockOpenLocalImageRequest mock_open_local_image_request;
expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
- mock_local_image_ctx.id, mock_local_image_ctx, 0);
+ mock_local_image_ctx.id, &mock_local_image_ctx, 0);
// resync is requested
expect_is_resync_requested(mock_journal, true, 0);
@@ -852,6 +850,154 @@ TEST_F(TestMockImageReplayerBootstrapRequest, ResyncRequested) {
ASSERT_TRUE(m_do_resync);
}
+TEST_F(TestMockImageReplayerBootstrapRequest, PrimaryRemote) {
+ create_local_image();
+
+ InSequence seq;
+
+ // lookup remote image tag class
+ cls::journal::Client client;
+ librbd::journal::ClientData client_data{
+ librbd::journal::ImageClientMeta{123}};
+ ::encode(client_data, client.data);
+ ::journal::MockJournaler mock_journaler;
+ expect_journaler_get_client(mock_journaler,
+ librbd::Journal<>::IMAGE_CLIENT_ID,
+ client, 0);
+
+ // lookup local peer in remote journal
+ client = {};
+ expect_journaler_get_client(mock_journaler, "local mirror uuid",
+ client, -ENOENT);
+
+ // register missing client in remote journal
+ librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
+ client_data.client_meta = mirror_peer_client_meta;
+ expect_journaler_register_client(mock_journaler, client_data, 0);
+
+ // open the remote image
+ librbd::MockJournal mock_journal;
+ librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
+ MockOpenImageRequest mock_open_image_request;
+ expect_open_image(mock_open_image_request, m_remote_io_ctx,
+ mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
+ MockIsPrimaryRequest mock_is_primary_request;
+ expect_is_primary(mock_is_primary_request, true, 0);
+
+ // create the local image
+ librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
+ mock_local_image_ctx.journal = &mock_journal;
+
+ MockCreateImageRequest mock_create_image_request;
+ expect_create_image(mock_create_image_request, mock_local_image_ctx.id, 0);
+
+ // open the local image
+ MockOpenLocalImageRequest mock_open_local_image_request;
+ expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
+ mock_local_image_ctx.id, &mock_local_image_ctx, 0);
+ expect_is_resync_requested(mock_journal, false, 0);
+
+ // update client state back to syncing
+ mirror_peer_client_meta = {mock_local_image_ctx.id};
+ mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
+ client_data.client_meta = mirror_peer_client_meta;
+ client.data.clear();
+ ::encode(client_data, client.data);
+ expect_journaler_update_client(mock_journaler, client_data, 0);
+
+ // sync the remote image to the local image
+ MockImageSyncThrottler mock_image_sync_throttler(
+ new ImageSyncThrottler<librbd::MockTestImageCtx>());
+ expect_image_sync(mock_image_sync_throttler, 0);
+
+ MockCloseImageRequest mock_close_image_request;
+ expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
+
+ C_SaferCond ctx;
+ MockBootstrapRequest *request = create_request(
+ mock_image_sync_throttler, mock_journaler, "",
+ mock_remote_image_ctx.id, "global image id", "local mirror uuid",
+ "remote mirror uuid", &ctx);
+ request->send();
+ ASSERT_EQ(0, ctx.wait());
+}
+
+TEST_F(TestMockImageReplayerBootstrapRequest, PrimaryRemoteLocalDeleted) {
+ create_local_image();
+
+ InSequence seq;
+
+ // lookup remote image tag class
+ cls::journal::Client client;
+ librbd::journal::ClientData client_data{
+ librbd::journal::ImageClientMeta{123}};
+ ::encode(client_data, client.data);
+ ::journal::MockJournaler mock_journaler;
+ expect_journaler_get_client(mock_journaler,
+ librbd::Journal<>::IMAGE_CLIENT_ID,
+ client, 0);
+
+ // lookup local peer in remote journal
+ librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
+ "missing image id"};
+ mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+ client_data.client_meta = mirror_peer_client_meta;
+ client.data.clear();
+ ::encode(client_data, client.data);
+ expect_journaler_get_client(mock_journaler, "local mirror uuid",
+ client, 0);
+
+ // open the remote image
+ librbd::MockJournal mock_journal;
+ librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
+ MockOpenImageRequest mock_open_image_request;
+ expect_open_image(mock_open_image_request, m_remote_io_ctx,
+ mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
+ MockIsPrimaryRequest mock_is_primary_request;
+ expect_is_primary(mock_is_primary_request, true, 0);
+
+ // open the missing local image
+ MockOpenLocalImageRequest mock_open_local_image_request;
+ expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
+ "missing image id", nullptr, -ENOENT);
+
+ // create the missing local image
+ librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
+ mock_local_image_ctx.journal = &mock_journal;
+
+ MockCreateImageRequest mock_create_image_request;
+ expect_create_image(mock_create_image_request, mock_local_image_ctx.id, 0);
+
+ // open the local image
+ expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
+ mock_local_image_ctx.id, &mock_local_image_ctx, 0);
+ expect_is_resync_requested(mock_journal, false, 0);
+
+ // update client state back to syncing
+ mirror_peer_client_meta = {mock_local_image_ctx.id};
+ mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
+ client_data.client_meta = mirror_peer_client_meta;
+ client.data.clear();
+ ::encode(client_data, client.data);
+ expect_journaler_update_client(mock_journaler, client_data, 0);
+
+ // sync the remote image to the local image
+ MockImageSyncThrottler mock_image_sync_throttler(
+ new ImageSyncThrottler<librbd::MockTestImageCtx>());
+ expect_image_sync(mock_image_sync_throttler, 0);
+
+ MockCloseImageRequest mock_close_image_request;
+ expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
+
+ C_SaferCond ctx;
+ MockBootstrapRequest *request = create_request(
+ mock_image_sync_throttler, mock_journaler, "",
+ mock_remote_image_ctx.id, "global image id", "local mirror uuid",
+ "remote mirror uuid", &ctx);
+ request->send();
+ ASSERT_EQ(0, ctx.wait());
+}
+
} // namespace image_replayer
} // namespace mirror
} // namespace rbd