1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
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"
14 inline ImageCtx
*get_image_ctx(MockImageCtx
*image_ctx
) {
15 return image_ctx
->image_ctx
;
21 #include "librbd/crypto/FormatRequest.cc"
28 template <> void set_crypto(
29 MockImageCtx
*image_ctx
, ceph::ref_t
<CryptoInterface
> crypto
) {
30 image_ctx
->crypto
= crypto
.get();
36 using ::testing::Invoke
;
37 using ::testing::Return
;
38 using ::testing::WithArg
;
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
;
51 MOCK_METHOD0(send
, void());
53 ShutDownCryptoRequest() {
58 ShutDownCryptoRequest
<MockImageCtx
> *ShutDownCryptoRequest
<
59 MockImageCtx
>::s_instance
= nullptr;
61 struct TestMockCryptoFormatRequest
: public TestMockFixture
{
62 typedef FormatRequest
<librbd::MockImageCtx
> MockFormatRequest
;
63 typedef ShutDownCryptoRequest
<MockImageCtx
> MockShutDownCryptoRequest
;
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');
75 void SetUp() override
{
76 TestMockFixture::SetUp();
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(
87 std::unique_ptr
<MockEncryptionFormat
>(mock_encryption_format
),
91 void TearDown() override
{
94 delete mock_image_ctx
;
95 TestMockFixture::TearDown();
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
));
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
;
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
);
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
);
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
);
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
);
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
);
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
);
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
);
194 } // namespace crypto
195 } // namespace librbd