1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
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"
14 class TestObjectPlayer : public RadosTestFixture {
16 static const uint32_t max_fetch_bytes = T::max_fetch_bytes;
18 journal::ObjectPlayerPtr create_object(const std::string &oid,
20 journal::ObjectPlayerPtr object(new journal::ObjectPlayer(
21 m_ioctx, oid + ".", 0, *m_timer, m_timer_lock, order,
26 int fetch(journal::ObjectPlayerPtr object_player) {
29 object_player->set_refetch_state(
30 journal::ObjectPlayer::REFETCH_STATE_NONE);
31 object_player->fetch(&ctx);
33 if (r < 0 || !object_player->refetch_required()) {
40 int watch_and_wait_for_entries(journal::ObjectPlayerPtr object_player,
41 journal::ObjectPlayer::Entries *entries,
43 for (size_t i = 0; i < 50; ++i) {
44 object_player->get_entries(entries);
45 if (entries->size() == count) {
50 object_player->watch(&ctx, 0.1);
60 std::string get_object_name(const std::string &oid) {
65 template <uint32_t _max_fetch_bytes>
66 struct TestObjectPlayerParams {
67 static const uint32_t max_fetch_bytes = _max_fetch_bytes;
70 typedef ::testing::Types<TestObjectPlayerParams<0>,
71 TestObjectPlayerParams<10> > TestObjectPlayerTypes;
72 TYPED_TEST_CASE(TestObjectPlayer, TestObjectPlayerTypes);
74 TYPED_TEST(TestObjectPlayer, Fetch) {
75 std::string oid = this->get_temp_oid();
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')));
83 ASSERT_EQ(0, this->append(this->get_object_name(oid), bl));
85 journal::ObjectPlayerPtr object = this->create_object(oid, 14);
86 ASSERT_LE(0, this->fetch(object));
88 journal::ObjectPlayer::Entries entries;
89 object->get_entries(&entries);
90 ASSERT_EQ(2U, entries.size());
92 journal::ObjectPlayer::Entries expected_entries = {entry1, entry2};
93 ASSERT_EQ(expected_entries, entries);
96 TYPED_TEST(TestObjectPlayer, FetchLarge) {
97 std::string oid = this->get_temp_oid();
99 journal::Entry entry1(234, 123,
100 this->create_payload(std::string(8192 - 32, '1')));
101 journal::Entry entry2(234, 124, this->create_payload(""));
104 ::encode(entry1, bl);
105 ::encode(entry2, bl);
106 ASSERT_EQ(0, this->append(this->get_object_name(oid), bl));
108 journal::ObjectPlayerPtr object = this->create_object(oid, 12);
109 ASSERT_LE(0, this->fetch(object));
111 journal::ObjectPlayer::Entries entries;
112 object->get_entries(&entries);
113 ASSERT_EQ(2U, entries.size());
115 journal::ObjectPlayer::Entries expected_entries = {entry1, entry2};
116 ASSERT_EQ(expected_entries, entries);
119 TYPED_TEST(TestObjectPlayer, FetchDeDup) {
120 std::string oid = this->get_temp_oid();
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')));
126 ::encode(entry1, bl);
127 ::encode(entry2, bl);
128 ASSERT_EQ(0, this->append(this->get_object_name(oid), bl));
130 journal::ObjectPlayerPtr object = this->create_object(oid, 14);
131 ASSERT_LE(0, this->fetch(object));
133 journal::ObjectPlayer::Entries entries;
134 object->get_entries(&entries);
135 ASSERT_EQ(1U, entries.size());
137 journal::ObjectPlayer::Entries expected_entries = {entry2};
138 ASSERT_EQ(expected_entries, entries);
141 TYPED_TEST(TestObjectPlayer, FetchEmpty) {
142 std::string oid = this->get_temp_oid();
145 ASSERT_EQ(0, this->append(this->get_object_name(oid), bl));
147 journal::ObjectPlayerPtr object = this->create_object(oid, 14);
149 ASSERT_EQ(0, this->fetch(object));
150 ASSERT_TRUE(object->empty());
153 TYPED_TEST(TestObjectPlayer, FetchCorrupt) {
154 std::string oid = this->get_temp_oid();
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')));
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));
165 journal::ObjectPlayerPtr object = this->create_object(oid, 14);
166 ASSERT_EQ(-EBADMSG, this->fetch(object));
168 journal::ObjectPlayer::Entries entries;
169 object->get_entries(&entries);
170 ASSERT_EQ(2U, entries.size());
172 journal::ObjectPlayer::Entries expected_entries = {entry1, entry2};
173 ASSERT_EQ(expected_entries, entries);
176 TYPED_TEST(TestObjectPlayer, FetchAppend) {
177 std::string oid = this->get_temp_oid();
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')));
183 ::encode(entry1, bl);
184 ASSERT_EQ(0, this->append(this->get_object_name(oid), bl));
186 journal::ObjectPlayerPtr object = this->create_object(oid, 14);
187 ASSERT_LE(0, this->fetch(object));
189 journal::ObjectPlayer::Entries entries;
190 object->get_entries(&entries);
191 ASSERT_EQ(1U, entries.size());
193 journal::ObjectPlayer::Entries expected_entries = {entry1};
194 ASSERT_EQ(expected_entries, entries);
197 ::encode(entry2, bl);
198 ASSERT_EQ(0, this->append(this->get_object_name(oid), bl));
199 ASSERT_LE(0, this->fetch(object));
201 object->get_entries(&entries);
202 ASSERT_EQ(2U, entries.size());
204 expected_entries = {entry1, entry2};
205 ASSERT_EQ(expected_entries, entries);
208 TYPED_TEST(TestObjectPlayer, PopEntry) {
209 std::string oid = this->get_temp_oid();
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')));
215 ::encode(entry1, bl);
216 ::encode(entry2, bl);
217 ASSERT_EQ(0, this->append(this->get_object_name(oid), bl));
219 journal::ObjectPlayerPtr object = this->create_object(oid, 14);
220 ASSERT_LE(0, this->fetch(object));
222 journal::ObjectPlayer::Entries entries;
223 object->get_entries(&entries);
224 ASSERT_EQ(2U, entries.size());
226 journal::Entry entry;
227 object->front(&entry);
229 ASSERT_EQ(entry1, entry);
230 object->front(&entry);
232 ASSERT_EQ(entry2, entry);
233 ASSERT_TRUE(object->empty());
236 TYPED_TEST(TestObjectPlayer, Watch) {
237 std::string oid = this->get_temp_oid();
238 journal::ObjectPlayerPtr object = this->create_object(oid, 14);
241 object->watch(&cond1, 0.1);
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')));
247 ::encode(entry1, bl);
248 ASSERT_EQ(0, this->append(this->get_object_name(oid), bl));
249 ASSERT_LE(0, cond1.wait());
251 journal::ObjectPlayer::Entries entries;
252 ASSERT_EQ(0, this->watch_and_wait_for_entries(object, &entries, 1U));
253 ASSERT_EQ(1U, entries.size());
255 journal::ObjectPlayer::Entries expected_entries;
256 expected_entries = {entry1};
257 ASSERT_EQ(expected_entries, entries);
260 object->watch(&cond2, 0.1);
263 ::encode(entry2, bl);
264 ASSERT_EQ(0, this->append(this->get_object_name(oid), bl));
265 ASSERT_LE(0, cond2.wait());
267 ASSERT_EQ(0, this->watch_and_wait_for_entries(object, &entries, 2U));
268 ASSERT_EQ(2U, entries.size());
270 expected_entries = {entry1, entry2};
271 ASSERT_EQ(expected_entries, entries);
274 TYPED_TEST(TestObjectPlayer, Unwatch) {
275 std::string oid = this->get_temp_oid();
276 journal::ObjectPlayerPtr object = this->create_object(oid, 14);
278 C_SaferCond watch_ctx;
279 object->watch(&watch_ctx, 600);
284 ASSERT_EQ(-ECANCELED, watch_ctx.wait());