]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/journal/test_ObjectPlayer.cc
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / test / journal / test_ObjectPlayer.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 "journal/ObjectPlayer.h"
5 #include "journal/Entry.h"
6 #include "include/stringify.h"
7 #include "common/Mutex.h"
8 #include "common/Timer.h"
9 #include "gtest/gtest.h"
10 #include "test/librados/test.h"
11 #include "test/journal/RadosTestFixture.h"
12
13 template <typename T>
14 class TestObjectPlayer : public RadosTestFixture {
15 public:
16 static const uint32_t max_fetch_bytes = T::max_fetch_bytes;
17
18 journal::ObjectPlayerPtr create_object(const std::string &oid,
19 uint8_t order) {
20 journal::ObjectPlayerPtr object(new journal::ObjectPlayer(
21 m_ioctx, oid + ".", 0, *m_timer, m_timer_lock, order,
22 max_fetch_bytes));
23 return object;
24 }
25
26 int fetch(journal::ObjectPlayerPtr object_player) {
27 while (true) {
28 C_SaferCond ctx;
29 object_player->set_refetch_state(
30 journal::ObjectPlayer::REFETCH_STATE_NONE);
31 object_player->fetch(&ctx);
32 int r = ctx.wait();
33 if (r < 0 || !object_player->refetch_required()) {
34 return r;
35 }
36 }
37 return 0;
38 }
39
40 int watch_and_wait_for_entries(journal::ObjectPlayerPtr object_player,
41 journal::ObjectPlayer::Entries *entries,
42 size_t count) {
43 for (size_t i = 0; i < 50; ++i) {
44 object_player->get_entries(entries);
45 if (entries->size() == count) {
46 break;
47 }
48
49 C_SaferCond ctx;
50 object_player->watch(&ctx, 0.1);
51
52 int r = ctx.wait();
53 if (r < 0) {
54 return r;
55 }
56 }
57 return 0;
58 }
59
60 std::string get_object_name(const std::string &oid) {
61 return oid + ".0";
62 }
63 };
64
65 template <uint32_t _max_fetch_bytes>
66 struct TestObjectPlayerParams {
67 static const uint32_t max_fetch_bytes = _max_fetch_bytes;
68 };
69
70 typedef ::testing::Types<TestObjectPlayerParams<0>,
71 TestObjectPlayerParams<10> > TestObjectPlayerTypes;
72 TYPED_TEST_CASE(TestObjectPlayer, TestObjectPlayerTypes);
73
74 TYPED_TEST(TestObjectPlayer, Fetch) {
75 std::string oid = this->get_temp_oid();
76
77 journal::Entry entry1(234, 123, this->create_payload(std::string(24, '1')));
78 journal::Entry entry2(234, 124, this->create_payload(std::string(24, '1')));
79
80 bufferlist bl;
81 ::encode(entry1, bl);
82 ::encode(entry2, bl);
83 ASSERT_EQ(0, this->append(this->get_object_name(oid), bl));
84
85 journal::ObjectPlayerPtr object = this->create_object(oid, 14);
86 ASSERT_LE(0, this->fetch(object));
87
88 journal::ObjectPlayer::Entries entries;
89 object->get_entries(&entries);
90 ASSERT_EQ(2U, entries.size());
91
92 journal::ObjectPlayer::Entries expected_entries = {entry1, entry2};
93 ASSERT_EQ(expected_entries, entries);
94 }
95
96 TYPED_TEST(TestObjectPlayer, FetchLarge) {
97 std::string oid = this->get_temp_oid();
98
99 journal::Entry entry1(234, 123,
100 this->create_payload(std::string(8192 - 32, '1')));
101 journal::Entry entry2(234, 124, this->create_payload(""));
102
103 bufferlist bl;
104 ::encode(entry1, bl);
105 ::encode(entry2, bl);
106 ASSERT_EQ(0, this->append(this->get_object_name(oid), bl));
107
108 journal::ObjectPlayerPtr object = this->create_object(oid, 12);
109 ASSERT_LE(0, this->fetch(object));
110
111 journal::ObjectPlayer::Entries entries;
112 object->get_entries(&entries);
113 ASSERT_EQ(2U, entries.size());
114
115 journal::ObjectPlayer::Entries expected_entries = {entry1, entry2};
116 ASSERT_EQ(expected_entries, entries);
117 }
118
119 TYPED_TEST(TestObjectPlayer, FetchDeDup) {
120 std::string oid = this->get_temp_oid();
121
122 journal::Entry entry1(234, 123, this->create_payload(std::string(24, '1')));
123 journal::Entry entry2(234, 123, this->create_payload(std::string(24, '2')));
124
125 bufferlist bl;
126 ::encode(entry1, bl);
127 ::encode(entry2, bl);
128 ASSERT_EQ(0, this->append(this->get_object_name(oid), bl));
129
130 journal::ObjectPlayerPtr object = this->create_object(oid, 14);
131 ASSERT_LE(0, this->fetch(object));
132
133 journal::ObjectPlayer::Entries entries;
134 object->get_entries(&entries);
135 ASSERT_EQ(1U, entries.size());
136
137 journal::ObjectPlayer::Entries expected_entries = {entry2};
138 ASSERT_EQ(expected_entries, entries);
139 }
140
141 TYPED_TEST(TestObjectPlayer, FetchEmpty) {
142 std::string oid = this->get_temp_oid();
143
144 bufferlist bl;
145 ASSERT_EQ(0, this->append(this->get_object_name(oid), bl));
146
147 journal::ObjectPlayerPtr object = this->create_object(oid, 14);
148
149 ASSERT_EQ(0, this->fetch(object));
150 ASSERT_TRUE(object->empty());
151 }
152
153 TYPED_TEST(TestObjectPlayer, FetchCorrupt) {
154 std::string oid = this->get_temp_oid();
155
156 journal::Entry entry1(234, 123, this->create_payload(std::string(24, '1')));
157 journal::Entry entry2(234, 124, this->create_payload(std::string(24, '2')));
158
159 bufferlist bl;
160 ::encode(entry1, bl);
161 ::encode(this->create_payload("corruption"), bl);
162 ::encode(entry2, bl);
163 ASSERT_EQ(0, this->append(this->get_object_name(oid), bl));
164
165 journal::ObjectPlayerPtr object = this->create_object(oid, 14);
166 ASSERT_EQ(-EBADMSG, this->fetch(object));
167
168 journal::ObjectPlayer::Entries entries;
169 object->get_entries(&entries);
170 ASSERT_EQ(2U, entries.size());
171
172 journal::ObjectPlayer::Entries expected_entries = {entry1, entry2};
173 ASSERT_EQ(expected_entries, entries);
174 }
175
176 TYPED_TEST(TestObjectPlayer, FetchAppend) {
177 std::string oid = this->get_temp_oid();
178
179 journal::Entry entry1(234, 123, this->create_payload(std::string(24, '1')));
180 journal::Entry entry2(234, 124, this->create_payload(std::string(24, '2')));
181
182 bufferlist bl;
183 ::encode(entry1, bl);
184 ASSERT_EQ(0, this->append(this->get_object_name(oid), bl));
185
186 journal::ObjectPlayerPtr object = this->create_object(oid, 14);
187 ASSERT_LE(0, this->fetch(object));
188
189 journal::ObjectPlayer::Entries entries;
190 object->get_entries(&entries);
191 ASSERT_EQ(1U, entries.size());
192
193 journal::ObjectPlayer::Entries expected_entries = {entry1};
194 ASSERT_EQ(expected_entries, entries);
195
196 bl.clear();
197 ::encode(entry2, bl);
198 ASSERT_EQ(0, this->append(this->get_object_name(oid), bl));
199 ASSERT_LE(0, this->fetch(object));
200
201 object->get_entries(&entries);
202 ASSERT_EQ(2U, entries.size());
203
204 expected_entries = {entry1, entry2};
205 ASSERT_EQ(expected_entries, entries);
206 }
207
208 TYPED_TEST(TestObjectPlayer, PopEntry) {
209 std::string oid = this->get_temp_oid();
210
211 journal::Entry entry1(234, 123, this->create_payload(std::string(24, '1')));
212 journal::Entry entry2(234, 124, this->create_payload(std::string(24, '1')));
213
214 bufferlist bl;
215 ::encode(entry1, bl);
216 ::encode(entry2, bl);
217 ASSERT_EQ(0, this->append(this->get_object_name(oid), bl));
218
219 journal::ObjectPlayerPtr object = this->create_object(oid, 14);
220 ASSERT_LE(0, this->fetch(object));
221
222 journal::ObjectPlayer::Entries entries;
223 object->get_entries(&entries);
224 ASSERT_EQ(2U, entries.size());
225
226 journal::Entry entry;
227 object->front(&entry);
228 object->pop_front();
229 ASSERT_EQ(entry1, entry);
230 object->front(&entry);
231 object->pop_front();
232 ASSERT_EQ(entry2, entry);
233 ASSERT_TRUE(object->empty());
234 }
235
236 TYPED_TEST(TestObjectPlayer, Watch) {
237 std::string oid = this->get_temp_oid();
238 journal::ObjectPlayerPtr object = this->create_object(oid, 14);
239
240 C_SaferCond cond1;
241 object->watch(&cond1, 0.1);
242
243 journal::Entry entry1(234, 123, this->create_payload(std::string(24, '1')));
244 journal::Entry entry2(234, 124, this->create_payload(std::string(24, '1')));
245
246 bufferlist bl;
247 ::encode(entry1, bl);
248 ASSERT_EQ(0, this->append(this->get_object_name(oid), bl));
249 ASSERT_LE(0, cond1.wait());
250
251 journal::ObjectPlayer::Entries entries;
252 ASSERT_EQ(0, this->watch_and_wait_for_entries(object, &entries, 1U));
253 ASSERT_EQ(1U, entries.size());
254
255 journal::ObjectPlayer::Entries expected_entries;
256 expected_entries = {entry1};
257 ASSERT_EQ(expected_entries, entries);
258
259 C_SaferCond cond2;
260 object->watch(&cond2, 0.1);
261
262 bl.clear();
263 ::encode(entry2, bl);
264 ASSERT_EQ(0, this->append(this->get_object_name(oid), bl));
265 ASSERT_LE(0, cond2.wait());
266
267 ASSERT_EQ(0, this->watch_and_wait_for_entries(object, &entries, 2U));
268 ASSERT_EQ(2U, entries.size());
269
270 expected_entries = {entry1, entry2};
271 ASSERT_EQ(expected_entries, entries);
272 }
273
274 TYPED_TEST(TestObjectPlayer, Unwatch) {
275 std::string oid = this->get_temp_oid();
276 journal::ObjectPlayerPtr object = this->create_object(oid, 14);
277
278 C_SaferCond watch_ctx;
279 object->watch(&watch_ctx, 600);
280
281 usleep(200000);
282
283 object->unwatch();
284 ASSERT_EQ(-ECANCELED, watch_ctx.wait());
285 }