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());