]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
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/librados_test_stub/MockTestMemIoCtxImpl.h" | |
8 | #include "gmock/gmock.h" | |
9 | #include "gtest/gtest.h" | |
10 | ||
11 | namespace librbd { | |
12 | namespace { | |
13 | ||
14 | struct MockTestImageCtx : public MockImageCtx { | |
15 | MockTestImageCtx(ImageCtx &image_ctx) : MockImageCtx(image_ctx) { | |
16 | } | |
17 | }; | |
18 | ||
19 | } // anonymous namespace | |
20 | } // namespace librbd | |
21 | ||
22 | // template definitions | |
23 | #include "librbd/image/ValidatePoolRequest.cc" | |
24 | ||
25 | namespace librbd { | |
26 | namespace image { | |
27 | ||
28 | using ::testing::_; | |
29 | using ::testing::DoDefault; | |
30 | using ::testing::InSequence; | |
31 | using ::testing::Invoke; | |
32 | using ::testing::Return; | |
33 | using ::testing::StrEq; | |
34 | using ::testing::WithArg; | |
35 | ||
36 | class TestMockImageValidatePoolRequest : public TestMockFixture { | |
37 | public: | |
38 | typedef ValidatePoolRequest<MockTestImageCtx> MockValidatePoolRequest; | |
39 | ||
40 | void SetUp() override { | |
41 | TestMockFixture::SetUp(); | |
f67539c2 | 42 | m_ioctx.remove(RBD_INFO); |
11fdf7f2 TL |
43 | ASSERT_EQ(0, open_image(m_image_name, &image_ctx)); |
44 | } | |
45 | ||
46 | void expect_clone(librados::MockTestMemIoCtxImpl &mock_io_ctx) { | |
47 | EXPECT_CALL(mock_io_ctx, clone()) | |
48 | .WillOnce(Invoke([&mock_io_ctx]() { | |
49 | mock_io_ctx.get(); | |
50 | return &mock_io_ctx; | |
51 | })); | |
52 | } | |
53 | ||
54 | void expect_read_rbd_info(librados::MockTestMemIoCtxImpl &mock_io_ctx, | |
55 | const std::string& data, int r) { | |
f67539c2 TL |
56 | auto& expect = EXPECT_CALL( |
57 | mock_io_ctx, read(StrEq(RBD_INFO), 0, 0, _, _, _)); | |
11fdf7f2 TL |
58 | if (r < 0) { |
59 | expect.WillOnce(Return(r)); | |
60 | } else { | |
61 | expect.WillOnce(WithArg<3>(Invoke([data](bufferlist* bl) { | |
62 | bl->append(data); | |
63 | return 0; | |
64 | }))); | |
65 | } | |
66 | } | |
67 | ||
68 | void expect_write_rbd_info(librados::MockTestMemIoCtxImpl &mock_io_ctx, | |
69 | const std::string& data, int r) { | |
70 | bufferlist bl; | |
71 | bl.append(data); | |
72 | ||
73 | EXPECT_CALL(mock_io_ctx, write(StrEq(RBD_INFO), ContentsEqual(bl), | |
74 | data.length(), 0, _)) | |
75 | .WillOnce(Return(r)); | |
76 | } | |
77 | ||
78 | void expect_allocate_snap_id(librados::MockTestMemIoCtxImpl &mock_io_ctx, | |
79 | int r) { | |
80 | auto &expect = EXPECT_CALL(mock_io_ctx, selfmanaged_snap_create(_)); | |
81 | if (r < 0) { | |
82 | expect.WillOnce(Return(r)); | |
83 | } else { | |
84 | expect.WillOnce(DoDefault()); | |
85 | } | |
86 | } | |
87 | ||
88 | void expect_release_snap_id(librados::MockTestMemIoCtxImpl &mock_io_ctx, | |
89 | int r) { | |
90 | auto &expect = EXPECT_CALL(mock_io_ctx, selfmanaged_snap_remove(_)); | |
91 | if (r < 0) { | |
92 | expect.WillOnce(Return(r)); | |
93 | } else { | |
94 | expect.WillOnce(DoDefault()); | |
95 | } | |
96 | } | |
97 | ||
98 | librbd::ImageCtx *image_ctx; | |
99 | }; | |
100 | ||
101 | TEST_F(TestMockImageValidatePoolRequest, Success) { | |
102 | librados::MockTestMemIoCtxImpl &mock_io_ctx(get_mock_io_ctx(m_ioctx)); | |
103 | ||
104 | InSequence seq; | |
105 | expect_clone(mock_io_ctx); | |
106 | expect_read_rbd_info(mock_io_ctx, "", -ENOENT); | |
107 | expect_allocate_snap_id(mock_io_ctx, 0); | |
108 | expect_write_rbd_info(mock_io_ctx, "validate", 0); | |
109 | expect_release_snap_id(mock_io_ctx, 0); | |
110 | expect_write_rbd_info(mock_io_ctx, "overwrite validated", 0); | |
111 | ||
112 | C_SaferCond ctx; | |
113 | auto req = new MockValidatePoolRequest(m_ioctx, image_ctx->op_work_queue, | |
114 | &ctx); | |
115 | req->send(); | |
116 | ASSERT_EQ(0, ctx.wait()); | |
117 | } | |
118 | ||
119 | TEST_F(TestMockImageValidatePoolRequest, AlreadyValidated) { | |
120 | librados::MockTestMemIoCtxImpl &mock_io_ctx(get_mock_io_ctx(m_ioctx)); | |
121 | ||
122 | InSequence seq; | |
123 | expect_clone(mock_io_ctx); | |
124 | expect_read_rbd_info(mock_io_ctx, "overwrite validated", 0); | |
125 | ||
126 | C_SaferCond ctx; | |
127 | auto req = new MockValidatePoolRequest(m_ioctx, image_ctx->op_work_queue, | |
128 | &ctx); | |
129 | req->send(); | |
130 | ASSERT_EQ(0, ctx.wait()); | |
131 | } | |
132 | ||
133 | TEST_F(TestMockImageValidatePoolRequest, SnapshotsValidated) { | |
134 | librados::MockTestMemIoCtxImpl &mock_io_ctx(get_mock_io_ctx(m_ioctx)); | |
135 | ||
136 | InSequence seq; | |
137 | expect_clone(mock_io_ctx); | |
138 | expect_read_rbd_info(mock_io_ctx, "validate", 0); | |
139 | expect_write_rbd_info(mock_io_ctx, "overwrite validated", 0); | |
140 | ||
141 | C_SaferCond ctx; | |
142 | auto req = new MockValidatePoolRequest(m_ioctx, image_ctx->op_work_queue, | |
143 | &ctx); | |
144 | req->send(); | |
145 | ASSERT_EQ(0, ctx.wait()); | |
146 | } | |
147 | ||
148 | TEST_F(TestMockImageValidatePoolRequest, ReadError) { | |
149 | librados::MockTestMemIoCtxImpl &mock_io_ctx(get_mock_io_ctx(m_ioctx)); | |
150 | ||
151 | InSequence seq; | |
152 | expect_clone(mock_io_ctx); | |
153 | expect_read_rbd_info(mock_io_ctx, "", -EPERM); | |
154 | ||
155 | C_SaferCond ctx; | |
156 | auto req = new MockValidatePoolRequest(m_ioctx, image_ctx->op_work_queue, | |
157 | &ctx); | |
158 | req->send(); | |
159 | ASSERT_EQ(-EPERM, ctx.wait()); | |
160 | } | |
161 | ||
162 | TEST_F(TestMockImageValidatePoolRequest, CreateSnapshotError) { | |
163 | librados::MockTestMemIoCtxImpl &mock_io_ctx(get_mock_io_ctx(m_ioctx)); | |
164 | ||
165 | InSequence seq; | |
166 | expect_clone(mock_io_ctx); | |
167 | expect_read_rbd_info(mock_io_ctx, "", 0); | |
168 | expect_allocate_snap_id(mock_io_ctx, -EPERM); | |
169 | ||
170 | C_SaferCond ctx; | |
171 | auto req = new MockValidatePoolRequest(m_ioctx, image_ctx->op_work_queue, | |
172 | &ctx); | |
173 | req->send(); | |
174 | ASSERT_EQ(-EPERM, ctx.wait()); | |
175 | } | |
176 | ||
177 | TEST_F(TestMockImageValidatePoolRequest, WriteError) { | |
178 | librados::MockTestMemIoCtxImpl &mock_io_ctx(get_mock_io_ctx(m_ioctx)); | |
179 | ||
180 | InSequence seq; | |
181 | expect_clone(mock_io_ctx); | |
182 | expect_read_rbd_info(mock_io_ctx, "", -ENOENT); | |
183 | expect_allocate_snap_id(mock_io_ctx, 0); | |
184 | expect_write_rbd_info(mock_io_ctx, "validate", -EPERM); | |
185 | expect_release_snap_id(mock_io_ctx, -EINVAL); | |
186 | ||
187 | C_SaferCond ctx; | |
188 | auto req = new MockValidatePoolRequest(m_ioctx, image_ctx->op_work_queue, | |
189 | &ctx); | |
190 | req->send(); | |
191 | ASSERT_EQ(-EPERM, ctx.wait()); | |
192 | } | |
193 | ||
194 | TEST_F(TestMockImageValidatePoolRequest, RemoveSnapshotError) { | |
195 | librados::MockTestMemIoCtxImpl &mock_io_ctx(get_mock_io_ctx(m_ioctx)); | |
196 | ||
197 | InSequence seq; | |
198 | expect_clone(mock_io_ctx); | |
199 | expect_read_rbd_info(mock_io_ctx, "", -ENOENT); | |
200 | expect_allocate_snap_id(mock_io_ctx, 0); | |
201 | expect_write_rbd_info(mock_io_ctx, "validate", 0); | |
202 | expect_release_snap_id(mock_io_ctx, -EPERM); | |
203 | expect_write_rbd_info(mock_io_ctx, "overwrite validated", 0); | |
204 | ||
205 | C_SaferCond ctx; | |
206 | auto req = new MockValidatePoolRequest(m_ioctx, image_ctx->op_work_queue, | |
207 | &ctx); | |
208 | req->send(); | |
209 | ASSERT_EQ(0, ctx.wait()); | |
210 | } | |
211 | ||
212 | TEST_F(TestMockImageValidatePoolRequest, OverwriteError) { | |
213 | librados::MockTestMemIoCtxImpl &mock_io_ctx(get_mock_io_ctx(m_ioctx)); | |
214 | ||
215 | InSequence seq; | |
216 | expect_clone(mock_io_ctx); | |
217 | expect_read_rbd_info(mock_io_ctx, "", -ENOENT); | |
218 | expect_allocate_snap_id(mock_io_ctx, 0); | |
219 | expect_write_rbd_info(mock_io_ctx, "validate", 0); | |
220 | expect_release_snap_id(mock_io_ctx, 0); | |
221 | expect_write_rbd_info(mock_io_ctx, "overwrite validated", -EOPNOTSUPP); | |
222 | ||
223 | C_SaferCond ctx; | |
224 | auto req = new MockValidatePoolRequest(m_ioctx, image_ctx->op_work_queue, | |
225 | &ctx); | |
226 | req->send(); | |
227 | ASSERT_EQ(-EINVAL, ctx.wait()); | |
228 | } | |
229 | ||
230 | } // namespace image | |
231 | } // namespace librbd |