Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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 }