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"
11 inline ImageCtx
*get_image_ctx(MockImageCtx
*image_ctx
) {
12 return image_ctx
->image_ctx
;
18 #include "librbd/crypto/luks/FormatRequest.cc"
25 using ::testing::Invoke
;
26 using ::testing::Return
;
28 struct TestMockCryptoLuksFormatRequest
: public TestMockFixture
{
29 typedef FormatRequest
<librbd::MockImageCtx
> MockFormatRequest
;
31 const size_t OBJECT_SIZE
= 4 * 1024 * 1024;
32 const size_t IMAGE_SIZE
= 1024 * 1024 * 1024;
33 const char* passphrase_cstr
= "password";
34 std::string passphrase
= passphrase_cstr
;
36 MockImageCtx
* mock_image_ctx
;
37 C_SaferCond finished_cond
;
38 Context
*on_finish
= &finished_cond
;
39 io::AioCompletion
* aio_comp
;
40 ceph::bufferlist header_bl
;
41 std::unique_ptr
<CryptoInterface
> crypto
;
43 void SetUp() override
{
44 TestMockFixture::SetUp();
46 librbd::ImageCtx
*ictx
;
47 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
48 mock_image_ctx
= new MockImageCtx(*ictx
);
51 void TearDown() override
{
52 delete mock_image_ctx
;
53 TestMockFixture::TearDown();
56 void expect_get_stripe_period() {
57 EXPECT_CALL(*mock_image_ctx
, get_stripe_period()).WillOnce(Return(
61 void expect_get_image_size(uint64_t image_size
) {
62 EXPECT_CALL(*mock_image_ctx
, get_image_size(CEPH_NOSNAP
)).WillOnce(Return(
66 void expect_image_write() {
67 EXPECT_CALL(*mock_image_ctx
->io_image_dispatcher
, send(_
))
68 .WillOnce(Invoke([this](io::ImageDispatchSpec
* spec
) {
69 auto* write
= boost::get
<io::ImageDispatchSpec::Write
>(
71 ASSERT_TRUE(write
!= nullptr);
73 ASSERT_EQ(1, spec
->image_extents
.size());
74 ASSERT_EQ(0, spec
->image_extents
[0].first
);
75 ASSERT_GT(spec
->image_extents
[0].second
, 0);
77 spec
->dispatch_result
= io::DISPATCH_RESULT_COMPLETE
;
78 aio_comp
= spec
->aio_comp
;
79 header_bl
= write
->bl
;
83 void complete_aio(int r
) {
87 aio_comp
->set_request_count(1);
88 aio_comp
->add_request();
89 aio_comp
->complete_request(r
);
93 void verify_header(const char* expected_format
, size_t expected_key_length
,
94 uint64_t expected_sector_size
, bool magic_switched
) {
95 Header
header(mock_image_ctx
->cct
);
97 ASSERT_EQ(0, header
.init());
100 Header
non_switched_header(mock_image_ctx
->cct
);
101 ASSERT_EQ(0, non_switched_header
.init());
102 ASSERT_EQ(0, non_switched_header
.write(header_bl
));
103 ASSERT_EQ(-EINVAL
, non_switched_header
.load(expected_format
));
104 ASSERT_EQ(0, Magic::replace_magic(mock_image_ctx
->cct
, header_bl
));
106 ASSERT_EQ(0, header
.write(header_bl
));
107 ASSERT_EQ(0, header
.load(expected_format
));
109 ASSERT_EQ(expected_sector_size
, header
.get_sector_size());
110 ASSERT_EQ(0, header
.get_data_offset() % OBJECT_SIZE
);
113 size_t volume_key_size
= sizeof(volume_key
);
114 ASSERT_EQ(0, header
.read_volume_key(
115 passphrase_cstr
, strlen(passphrase_cstr
),
116 reinterpret_cast<char*>(volume_key
), &volume_key_size
));
118 ASSERT_EQ(expected_key_length
, crypto
->get_key_length());
119 ASSERT_EQ(0, std::memcmp(
120 volume_key
, crypto
->get_key(), expected_key_length
));
121 ASSERT_EQ(expected_sector_size
, crypto
->get_block_size());
122 ASSERT_EQ(header
.get_data_offset(), crypto
->get_data_offset());
126 TEST_F(TestMockCryptoLuksFormatRequest
, LUKS1
) {
127 auto mock_format_request
= MockFormatRequest::create(
128 mock_image_ctx
, RBD_ENCRYPTION_FORMAT_LUKS1
,
129 RBD_ENCRYPTION_ALGORITHM_AES128
, std::move(passphrase
), &crypto
,
131 expect_get_stripe_period();
132 expect_get_image_size(IMAGE_SIZE
);
133 expect_image_write();
134 mock_format_request
->send();
135 ASSERT_EQ(ETIMEDOUT
, finished_cond
.wait_for(0));
137 ASSERT_EQ(0, finished_cond
.wait());
138 ASSERT_NO_FATAL_FAILURE(verify_header(CRYPT_LUKS1
, 32, 512, false));
141 TEST_F(TestMockCryptoLuksFormatRequest
, AES128
) {
142 auto mock_format_request
= MockFormatRequest::create(
143 mock_image_ctx
, RBD_ENCRYPTION_FORMAT_LUKS2
,
144 RBD_ENCRYPTION_ALGORITHM_AES128
, std::move(passphrase
), &crypto
,
146 expect_get_stripe_period();
147 expect_get_image_size(IMAGE_SIZE
);
148 expect_image_write();
149 mock_format_request
->send();
150 ASSERT_EQ(ETIMEDOUT
, finished_cond
.wait_for(0));
152 ASSERT_EQ(0, finished_cond
.wait());
153 ASSERT_NO_FATAL_FAILURE(verify_header(CRYPT_LUKS2
, 32, 4096, false));
156 TEST_F(TestMockCryptoLuksFormatRequest
, AES256
) {
157 auto mock_format_request
= MockFormatRequest::create(
158 mock_image_ctx
, RBD_ENCRYPTION_FORMAT_LUKS2
,
159 RBD_ENCRYPTION_ALGORITHM_AES256
, std::move(passphrase
), &crypto
,
161 expect_get_stripe_period();
162 expect_get_image_size(IMAGE_SIZE
);
163 expect_image_write();
164 mock_format_request
->send();
165 ASSERT_EQ(ETIMEDOUT
, finished_cond
.wait_for(0));
167 ASSERT_EQ(0, finished_cond
.wait());
168 ASSERT_NO_FATAL_FAILURE(verify_header(CRYPT_LUKS2
, 64, 4096, false));
171 TEST_F(TestMockCryptoLuksFormatRequest
, LUKS1OnCloned
) {
172 mock_image_ctx
->parent
= mock_image_ctx
;
173 auto mock_format_request
= MockFormatRequest::create(
174 mock_image_ctx
, RBD_ENCRYPTION_FORMAT_LUKS1
,
175 RBD_ENCRYPTION_ALGORITHM_AES256
, std::move(passphrase
), &crypto
,
177 expect_get_stripe_period();
178 expect_get_image_size(IMAGE_SIZE
);
179 expect_image_write();
180 mock_format_request
->send();
181 ASSERT_EQ(ETIMEDOUT
, finished_cond
.wait_for(0));
183 ASSERT_EQ(0, finished_cond
.wait());
184 ASSERT_NO_FATAL_FAILURE(verify_header(CRYPT_LUKS1
, 64, 512, true));
187 TEST_F(TestMockCryptoLuksFormatRequest
, LUKS2OnCloned
) {
188 mock_image_ctx
->parent
= mock_image_ctx
;
189 auto mock_format_request
= MockFormatRequest::create(
190 mock_image_ctx
, RBD_ENCRYPTION_FORMAT_LUKS2
,
191 RBD_ENCRYPTION_ALGORITHM_AES256
, std::move(passphrase
), &crypto
,
193 expect_get_stripe_period();
194 expect_get_image_size(IMAGE_SIZE
);
195 expect_image_write();
196 mock_format_request
->send();
197 ASSERT_EQ(ETIMEDOUT
, finished_cond
.wait_for(0));
199 ASSERT_EQ(0, finished_cond
.wait());
200 ASSERT_NO_FATAL_FAILURE(verify_header(CRYPT_LUKS2
, 64, 4096, true));
203 TEST_F(TestMockCryptoLuksFormatRequest
, ImageTooSmall
) {
204 auto mock_format_request
= MockFormatRequest::create(
205 mock_image_ctx
, RBD_ENCRYPTION_FORMAT_LUKS2
,
206 RBD_ENCRYPTION_ALGORITHM_AES256
, std::move(passphrase
), &crypto
,
208 expect_get_stripe_period();
209 expect_get_image_size(1024*1024);
210 mock_format_request
->send();
211 ASSERT_EQ(-ENOSPC
, finished_cond
.wait());
214 TEST_F(TestMockCryptoLuksFormatRequest
, WriteFail
) {
215 auto mock_format_request
= MockFormatRequest::create(
216 mock_image_ctx
, RBD_ENCRYPTION_FORMAT_LUKS2
,
217 RBD_ENCRYPTION_ALGORITHM_AES256
, std::move(passphrase
), &crypto
,
219 expect_get_stripe_period();
220 expect_get_image_size(IMAGE_SIZE
);
221 expect_image_write();
222 mock_format_request
->send();
223 ASSERT_EQ(ETIMEDOUT
, finished_cond
.wait_for(0));
225 ASSERT_EQ(-123, finished_cond
.wait());
229 } // namespace crypto
230 } // namespace librbd