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 ceph::ref_t
<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_object_size() {
57 EXPECT_CALL(*mock_image_ctx
, get_object_size()).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
) {
95 Header
header(mock_image_ctx
->cct
);
97 ASSERT_EQ(0, header
.init());
98 ASSERT_EQ(0, header
.write(header_bl
));
99 ASSERT_EQ(0, header
.load(expected_format
));
101 ASSERT_EQ(expected_sector_size
, header
.get_sector_size());
102 ASSERT_EQ(0, header
.get_data_offset() % OBJECT_SIZE
);
105 size_t volume_key_size
= sizeof(volume_key
);
106 ASSERT_EQ(0, header
.read_volume_key(
107 passphrase_cstr
, strlen(passphrase_cstr
),
108 reinterpret_cast<char*>(volume_key
), &volume_key_size
));
110 ASSERT_EQ(expected_key_length
, crypto
->get_key_length());
111 ASSERT_EQ(0, std::memcmp(
112 volume_key
, crypto
->get_key(), expected_key_length
));
113 ASSERT_EQ(expected_sector_size
, crypto
->get_block_size());
114 ASSERT_EQ(header
.get_data_offset(), crypto
->get_data_offset());
118 TEST_F(TestMockCryptoLuksFormatRequest
, LUKS1
) {
119 auto mock_format_request
= MockFormatRequest::create(
120 mock_image_ctx
, RBD_ENCRYPTION_FORMAT_LUKS1
,
121 RBD_ENCRYPTION_ALGORITHM_AES128
, std::move(passphrase
), &crypto
,
123 expect_get_object_size();
124 expect_get_image_size(IMAGE_SIZE
);
125 expect_image_write();
126 mock_format_request
->send();
127 ASSERT_EQ(ETIMEDOUT
, finished_cond
.wait_for(0));
129 ASSERT_EQ(0, finished_cond
.wait());
130 ASSERT_NO_FATAL_FAILURE(verify_header(CRYPT_LUKS1
, 32, 512));
133 TEST_F(TestMockCryptoLuksFormatRequest
, AES128
) {
134 auto mock_format_request
= MockFormatRequest::create(
135 mock_image_ctx
, RBD_ENCRYPTION_FORMAT_LUKS2
,
136 RBD_ENCRYPTION_ALGORITHM_AES128
, std::move(passphrase
), &crypto
,
138 expect_get_object_size();
139 expect_get_image_size(IMAGE_SIZE
);
140 expect_image_write();
141 mock_format_request
->send();
142 ASSERT_EQ(ETIMEDOUT
, finished_cond
.wait_for(0));
144 ASSERT_EQ(0, finished_cond
.wait());
145 ASSERT_NO_FATAL_FAILURE(verify_header(CRYPT_LUKS2
, 32, 4096));
148 TEST_F(TestMockCryptoLuksFormatRequest
, AES256
) {
149 auto mock_format_request
= MockFormatRequest::create(
150 mock_image_ctx
, RBD_ENCRYPTION_FORMAT_LUKS2
,
151 RBD_ENCRYPTION_ALGORITHM_AES256
, std::move(passphrase
), &crypto
,
153 expect_get_object_size();
154 expect_get_image_size(IMAGE_SIZE
);
155 expect_image_write();
156 mock_format_request
->send();
157 ASSERT_EQ(ETIMEDOUT
, finished_cond
.wait_for(0));
159 ASSERT_EQ(0, finished_cond
.wait());
160 ASSERT_NO_FATAL_FAILURE(verify_header(CRYPT_LUKS2
, 64, 4096));
163 TEST_F(TestMockCryptoLuksFormatRequest
, ImageTooSmall
) {
164 auto mock_format_request
= MockFormatRequest::create(
165 mock_image_ctx
, RBD_ENCRYPTION_FORMAT_LUKS2
,
166 RBD_ENCRYPTION_ALGORITHM_AES256
, std::move(passphrase
), &crypto
,
168 expect_get_object_size();
169 expect_get_image_size(1024*1024);
170 mock_format_request
->send();
171 ASSERT_EQ(-ENOSPC
, finished_cond
.wait());
174 TEST_F(TestMockCryptoLuksFormatRequest
, WriteFail
) {
175 auto mock_format_request
= MockFormatRequest::create(
176 mock_image_ctx
, RBD_ENCRYPTION_FORMAT_LUKS2
,
177 RBD_ENCRYPTION_ALGORITHM_AES256
, std::move(passphrase
), &crypto
,
179 expect_get_object_size();
180 expect_get_image_size(IMAGE_SIZE
);
181 expect_image_write();
182 mock_format_request
->send();
183 ASSERT_EQ(ETIMEDOUT
, finished_cond
.wait_for(0));
185 ASSERT_EQ(-123, finished_cond
.wait());
189 } // namespace crypto
190 } // namespace librbd