]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/librbd/crypto/test_mock_FormatRequest.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / test / librbd / crypto / test_mock_FormatRequest.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include "test/librbd/test_mock_fixture.h"
5 #include "test/librbd/test_support.h"
6 #include "test/librbd/mock/MockImageCtx.h"
7 #include "test/librbd/mock/crypto/MockCryptoInterface.h"
8 #include "test/librbd/mock/crypto/MockEncryptionFormat.h"
9 #include "librbd/crypto/Utils.h"
10
11 namespace librbd {
12 namespace util {
13
14 inline ImageCtx *get_image_ctx(MockImageCtx *image_ctx) {
15 return image_ctx->image_ctx;
16 }
17
18 } // namespace util
19 } // namespace librbd
20
21 #include "librbd/crypto/FormatRequest.cc"
22
23 namespace librbd {
24 namespace crypto {
25
26 namespace util {
27
28 template <> void set_crypto(
29 MockImageCtx *image_ctx, ceph::ref_t<CryptoInterface> crypto) {
30 image_ctx->crypto = crypto.get();
31 }
32
33 } // namespace util
34
35 using ::testing::_;
36 using ::testing::Invoke;
37 using ::testing::Return;
38 using ::testing::WithArg;
39
40 template <>
41 struct ShutDownCryptoRequest<MockImageCtx> {
42 Context *on_finish = nullptr;
43 static ShutDownCryptoRequest *s_instance;
44 static ShutDownCryptoRequest *create(
45 MockImageCtx* image_ctx, Context *on_finish) {
46 ceph_assert(s_instance != nullptr);
47 s_instance->on_finish = on_finish;
48 return s_instance;
49 }
50
51 MOCK_METHOD0(send, void());
52
53 ShutDownCryptoRequest() {
54 s_instance = this;
55 }
56 };
57
58 ShutDownCryptoRequest<MockImageCtx> *ShutDownCryptoRequest<
59 MockImageCtx>::s_instance = nullptr;
60
61 struct TestMockCryptoFormatRequest : public TestMockFixture {
62 typedef FormatRequest<librbd::MockImageCtx> MockFormatRequest;
63 typedef ShutDownCryptoRequest<MockImageCtx> MockShutDownCryptoRequest;
64
65 MockImageCtx* mock_image_ctx;
66 C_SaferCond finished_cond;
67 Context *on_finish = &finished_cond;
68 MockEncryptionFormat* mock_encryption_format;
69 Context* format_context;
70 MockCryptoInterface* crypto;
71 MockCryptoInterface* old_crypto;
72 MockFormatRequest* mock_format_request;
73 std::string key = std::string(64, '0');
74
75 void SetUp() override {
76 TestMockFixture::SetUp();
77
78 librbd::ImageCtx *ictx;
79 ASSERT_EQ(0, open_image(m_image_name, &ictx));
80 mock_image_ctx = new MockImageCtx(*ictx);
81 mock_encryption_format = new MockEncryptionFormat();
82 crypto = new MockCryptoInterface();
83 old_crypto = new MockCryptoInterface();
84 mock_image_ctx->crypto = old_crypto;
85 mock_format_request = MockFormatRequest::create(
86 mock_image_ctx,
87 std::unique_ptr<MockEncryptionFormat>(mock_encryption_format),
88 on_finish);
89 }
90
91 void TearDown() override {
92 crypto->put();
93 old_crypto->put();
94 delete mock_image_ctx;
95 TestMockFixture::TearDown();
96 }
97
98 void expect_test_journal_feature(bool has_journal=false) {
99 EXPECT_CALL(*mock_image_ctx, test_features(
100 RBD_FEATURE_JOURNALING)).WillOnce(Return(has_journal));
101 }
102
103 void expect_encryption_format() {
104 EXPECT_CALL(*mock_encryption_format, format(
105 mock_image_ctx, _)).WillOnce(
106 WithArg<1>(Invoke([this](Context* ctx) {
107 format_context = ctx;
108 })));
109 }
110
111 void expect_image_flush(int r) {
112 EXPECT_CALL(*mock_image_ctx->io_image_dispatcher, send(_)).WillOnce(
113 Invoke([r](io::ImageDispatchSpec* spec) {
114 ASSERT_TRUE(boost::get<io::ImageDispatchSpec::Flush>(
115 &spec->request) != nullptr);
116 spec->dispatch_result = io::DISPATCH_RESULT_COMPLETE;
117 spec->aio_comp->set_request_count(1);
118 spec->aio_comp->add_request();
119 spec->aio_comp->complete_request(r);
120 }));
121 }
122 };
123
124 TEST_F(TestMockCryptoFormatRequest, JournalEnabled) {
125 expect_test_journal_feature(true);
126 mock_format_request->send();
127 ASSERT_EQ(-ENOTSUP, finished_cond.wait());
128 ASSERT_EQ(old_crypto, mock_image_ctx->crypto);
129 }
130
131 TEST_F(TestMockCryptoFormatRequest, FailShutDownCrypto) {
132 expect_test_journal_feature(false);
133 MockShutDownCryptoRequest mock_shutdown_crypto_request;
134 EXPECT_CALL(mock_shutdown_crypto_request, send());
135 mock_format_request->send();
136 ASSERT_EQ(ETIMEDOUT, finished_cond.wait_for(0));
137 mock_shutdown_crypto_request.on_finish->complete(-EIO);
138 ASSERT_EQ(-EIO, finished_cond.wait());
139 ASSERT_EQ(old_crypto, mock_image_ctx->crypto);
140 }
141
142 TEST_F(TestMockCryptoFormatRequest, FormatFail) {
143 mock_image_ctx->crypto = nullptr;
144 expect_test_journal_feature(false);
145 expect_encryption_format();
146 mock_format_request->send();
147 ASSERT_EQ(ETIMEDOUT, finished_cond.wait_for(0));
148 format_context->complete(-EIO);
149 ASSERT_EQ(-EIO, finished_cond.wait());
150 ASSERT_EQ(nullptr, mock_image_ctx->crypto);
151 }
152
153 TEST_F(TestMockCryptoFormatRequest, Success) {
154 mock_image_ctx->crypto = nullptr;
155 expect_test_journal_feature(false);
156 expect_encryption_format();
157 mock_format_request->send();
158 ASSERT_EQ(ETIMEDOUT, finished_cond.wait_for(0));
159 expect_image_flush(0);
160 EXPECT_CALL(*mock_encryption_format, get_crypto()).WillOnce(Return(crypto));
161 format_context->complete(0);
162 ASSERT_EQ(0, finished_cond.wait());
163 ASSERT_EQ(crypto, mock_image_ctx->crypto);
164 }
165
166 TEST_F(TestMockCryptoFormatRequest, FailFlush) {
167 mock_image_ctx->crypto = nullptr;
168 expect_test_journal_feature(false);
169 expect_encryption_format();
170 mock_format_request->send();
171 ASSERT_EQ(ETIMEDOUT, finished_cond.wait_for(0));
172 expect_image_flush(-EIO);
173 format_context->complete(0);
174 ASSERT_EQ(-EIO, finished_cond.wait());
175 ASSERT_EQ(nullptr, mock_image_ctx->crypto);
176 }
177
178 TEST_F(TestMockCryptoFormatRequest, CryptoAlreadyLoaded) {
179 expect_test_journal_feature(false);
180 MockShutDownCryptoRequest mock_shutdown_crypto_request;
181 EXPECT_CALL(mock_shutdown_crypto_request, send());
182 mock_format_request->send();
183 ASSERT_EQ(ETIMEDOUT, finished_cond.wait_for(0));
184 expect_encryption_format();
185 mock_shutdown_crypto_request.on_finish->complete(0);
186 ASSERT_EQ(ETIMEDOUT, finished_cond.wait_for(0));
187 expect_image_flush(0);
188 EXPECT_CALL(*mock_encryption_format, get_crypto()).WillOnce(Return(crypto));
189 format_context->complete(0);
190 ASSERT_EQ(0, finished_cond.wait());
191 ASSERT_EQ(crypto, mock_image_ctx->crypto);
192 }
193
194 } // namespace crypto
195 } // namespace librbd