]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/cls_log/test_cls_log.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / test / cls_log / test_cls_log.cc
CommitLineData
1e59de90 1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
7c673cae
FG
2// vim: ts=8 sw=2 smarttab
3
4#include "include/types.h"
5#include "cls/log/cls_log_types.h"
6#include "cls/log/cls_log_client.h"
7
8#include "include/utime.h"
9#include "common/Clock.h"
10#include "global/global_context.h"
11
12#include "gtest/gtest.h"
11fdf7f2 13#include "test/librados/test_cxx.h"
7c673cae
FG
14
15#include <errno.h>
16#include <string>
17#include <vector>
18
20effc67
TL
19using namespace std;
20
9f95a23c
TL
21/// creates a temporary pool and initializes an IoCtx for each test
22class cls_log : public ::testing::Test {
23 librados::Rados rados;
24 std::string pool_name;
25 protected:
26 librados::IoCtx ioctx;
7c673cae 27
9f95a23c
TL
28 void SetUp() {
29 pool_name = get_temp_pool_name();
30 /* create pool */
31 ASSERT_EQ("", create_one_pool_pp(pool_name, rados));
32 ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx));
33 }
34 void TearDown() {
35 /* remove pool */
36 ioctx.close();
37 ASSERT_EQ(0, destroy_one_pool_pp(pool_name, rados));
38 }
39};
7c673cae
FG
40
41static int read_bl(bufferlist& bl, int *i)
42{
11fdf7f2 43 auto iter = bl.cbegin();
7c673cae
FG
44
45 try {
11fdf7f2 46 decode(*i, iter);
7c673cae
FG
47 } catch (buffer::error& err) {
48 std::cout << "failed to decode buffer" << std::endl;
49 return -EIO;
50 }
51
52 return 0;
53}
54
55void add_log(librados::ObjectWriteOperation *op, utime_t& timestamp, string& section, string&name, int i)
56{
57 bufferlist bl;
11fdf7f2 58 encode(i, bl);
7c673cae
FG
59
60 cls_log_add(*op, timestamp, section, name, bl);
61}
62
63
64string get_name(int i)
65{
66 string name_prefix = "data-source";
67
68 char buf[16];
69 snprintf(buf, sizeof(buf), "%d", i);
70 return name_prefix + buf;
71}
72
73void generate_log(librados::IoCtx& ioctx, string& oid, int max, utime_t& start_time, bool modify_time)
74{
75 string section = "global";
76
9f95a23c 77 librados::ObjectWriteOperation op;
7c673cae
FG
78
79 int i;
80
81 for (i = 0; i < max; i++) {
82 uint32_t secs = start_time.sec();
83 if (modify_time)
84 secs += i;
85
86 utime_t ts(secs, start_time.nsec());
87 string name = get_name(i);
88
9f95a23c 89 add_log(&op, ts, section, name, i);
7c673cae
FG
90 }
91
9f95a23c 92 ASSERT_EQ(0, ioctx.operate(oid, &op));
7c673cae
FG
93}
94
95utime_t get_time(utime_t& start_time, int i, bool modify_time)
96{
97 uint32_t secs = start_time.sec();
98 if (modify_time)
99 secs += i;
100 return utime_t(secs, start_time.nsec());
101}
102
103void check_entry(cls_log_entry& entry, utime_t& start_time, int i, bool modified_time)
104{
105 string section = "global";
106 string name = get_name(i);
107 utime_t ts = get_time(start_time, i, modified_time);
108
109 ASSERT_EQ(section, entry.section);
110 ASSERT_EQ(name, entry.name);
111 ASSERT_EQ(ts, entry.timestamp);
112}
113
9f95a23c
TL
114static int log_list(librados::IoCtx& ioctx, const std::string& oid,
115 utime_t& from, utime_t& to,
116 const string& in_marker, int max_entries,
117 list<cls_log_entry>& entries,
118 string *out_marker, bool *truncated)
119{
120 librados::ObjectReadOperation rop;
121 cls_log_list(rop, from, to, in_marker, max_entries,
122 entries, out_marker, truncated);
123 bufferlist obl;
124 return ioctx.operate(oid, &rop, &obl);
125}
7c673cae 126
9f95a23c
TL
127static int log_list(librados::IoCtx& ioctx, const std::string& oid,
128 utime_t& from, utime_t& to, int max_entries,
129 list<cls_log_entry>& entries, bool *truncated)
7c673cae 130{
9f95a23c
TL
131 std::string marker;
132 return log_list(ioctx, oid, from, to, marker, max_entries,
133 entries, &marker, truncated);
134}
7c673cae 135
9f95a23c
TL
136static int log_list(librados::IoCtx& ioctx, const std::string& oid,
137 list<cls_log_entry>& entries)
138{
139 utime_t from, to;
140 bool truncated{false};
141 return log_list(ioctx, oid, from, to, 0, entries, &truncated);
142}
7c673cae 143
9f95a23c
TL
144TEST_F(cls_log, test_log_add_same_time)
145{
7c673cae
FG
146 /* add chains */
147 string oid = "obj";
148
149 /* create object */
150 ASSERT_EQ(0, ioctx.create(oid, true));
151
152 /* generate log */
153 utime_t start_time = ceph_clock_now();
9f95a23c 154 utime_t to_time = get_time(start_time, 1, true);
7c673cae
FG
155 generate_log(ioctx, oid, 10, start_time, false);
156
7c673cae
FG
157 list<cls_log_entry> entries;
158 bool truncated;
159
160 /* check list */
9f95a23c
TL
161 {
162 ASSERT_EQ(0, log_list(ioctx, oid, start_time, to_time, 0,
163 entries, &truncated));
164 ASSERT_EQ(10, (int)entries.size());
165 ASSERT_EQ(0, (int)truncated);
166 }
7c673cae
FG
167 list<cls_log_entry>::iterator iter;
168
169 /* need to sort returned entries, all were using the same time as key */
170 map<int, cls_log_entry> check_ents;
171
172 for (iter = entries.begin(); iter != entries.end(); ++iter) {
173 cls_log_entry& entry = *iter;
174
175 int num;
176 ASSERT_EQ(0, read_bl(entry.data, &num));
177
178 check_ents[num] = entry;
179 }
180
181 ASSERT_EQ(10, (int)check_ents.size());
182
183 map<int, cls_log_entry>::iterator ei;
184
185 /* verify entries are as expected */
186
187 int i;
188
189 for (i = 0, ei = check_ents.begin(); i < 10; i++, ++ei) {
190 cls_log_entry& entry = ei->second;
191
192 ASSERT_EQ(i, ei->first);
193 check_entry(entry, start_time, i, false);
194 }
195
7c673cae 196 /* check list again, now want to be truncated*/
9f95a23c
TL
197 {
198 ASSERT_EQ(0, log_list(ioctx, oid, start_time, to_time, 1,
199 entries, &truncated));
200 ASSERT_EQ(1, (int)entries.size());
201 ASSERT_EQ(1, (int)truncated);
202 }
7c673cae
FG
203}
204
9f95a23c 205TEST_F(cls_log, test_log_add_different_time)
7c673cae 206{
7c673cae
FG
207 /* add chains */
208 string oid = "obj";
209
210 /* create object */
211 ASSERT_EQ(0, ioctx.create(oid, true));
212
213 /* generate log */
214 utime_t start_time = ceph_clock_now();
215 generate_log(ioctx, oid, 10, start_time, true);
216
7c673cae
FG
217 list<cls_log_entry> entries;
218 bool truncated;
219
220 utime_t to_time = utime_t(start_time.sec() + 10, start_time.nsec());
221
9f95a23c
TL
222 {
223 /* check list */
224 ASSERT_EQ(0, log_list(ioctx, oid, start_time, to_time, 0,
225 entries, &truncated));
226 ASSERT_EQ(10, (int)entries.size());
227 ASSERT_EQ(0, (int)truncated);
228 }
7c673cae
FG
229
230 list<cls_log_entry>::iterator iter;
231
232 /* returned entries should be sorted by time */
233 map<int, cls_log_entry> check_ents;
234
235 int i;
236
237 for (i = 0, iter = entries.begin(); iter != entries.end(); ++iter, ++i) {
238 cls_log_entry& entry = *iter;
239
240 int num;
241
242 ASSERT_EQ(0, read_bl(entry.data, &num));
243
244 ASSERT_EQ(i, num);
245
246 check_entry(entry, start_time, i, true);
247 }
248
7c673cae 249 /* check list again with shifted time */
9f95a23c
TL
250 {
251 utime_t next_time = get_time(start_time, 1, true);
252 ASSERT_EQ(0, log_list(ioctx, oid, next_time, to_time, 0,
253 entries, &truncated));
254 ASSERT_EQ(9u, entries.size());
255 ASSERT_FALSE(truncated);
256 }
7c673cae 257
9f95a23c 258 string marker;
7c673cae
FG
259 i = 0;
260 do {
9f95a23c
TL
261 string old_marker = std::move(marker);
262 ASSERT_EQ(0, log_list(ioctx, oid, start_time, to_time, old_marker, 1,
263 entries, &marker, &truncated));
7c673cae
FG
264 ASSERT_NE(old_marker, marker);
265 ASSERT_EQ(1, (int)entries.size());
266
267 ++i;
268 ASSERT_GE(10, i);
269 } while (truncated);
270
271 ASSERT_EQ(10, i);
7c673cae
FG
272}
273
9f95a23c
TL
274int do_log_trim(librados::IoCtx& ioctx, const std::string& oid,
275 const std::string& from_marker, const std::string& to_marker)
7c673cae 276{
9f95a23c
TL
277 librados::ObjectWriteOperation op;
278 cls_log_trim(op, {}, {}, from_marker, to_marker);
279 return ioctx.operate(oid, &op);
280}
7c673cae 281
9f95a23c
TL
282int do_log_trim(librados::IoCtx& ioctx, const std::string& oid,
283 const utime_t& from_time, const utime_t& to_time)
284{
285 librados::ObjectWriteOperation op;
286 cls_log_trim(op, from_time, to_time, "", "");
287 return ioctx.operate(oid, &op);
288}
7c673cae 289
9f95a23c
TL
290TEST_F(cls_log, trim_by_time)
291{
7c673cae
FG
292 /* add chains */
293 string oid = "obj";
294
295 /* create object */
296 ASSERT_EQ(0, ioctx.create(oid, true));
297
298 /* generate log */
299 utime_t start_time = ceph_clock_now();
300 generate_log(ioctx, oid, 10, start_time, true);
301
7c673cae
FG
302 list<cls_log_entry> entries;
303 bool truncated;
304
305 /* check list */
306
307 /* trim */
308 utime_t to_time = get_time(start_time, 10, true);
309
310 for (int i = 0; i < 10; i++) {
311 utime_t trim_time = get_time(start_time, i, true);
312
313 utime_t zero_time;
7c673cae 314
9f95a23c
TL
315 ASSERT_EQ(0, do_log_trim(ioctx, oid, zero_time, trim_time));
316 ASSERT_EQ(-ENODATA, do_log_trim(ioctx, oid, zero_time, trim_time));
7c673cae 317
9f95a23c
TL
318 ASSERT_EQ(0, log_list(ioctx, oid, start_time, to_time, 0,
319 entries, &truncated));
320 ASSERT_EQ(9u - i, entries.size());
321 ASSERT_FALSE(truncated);
322 }
323}
7c673cae 324
9f95a23c
TL
325TEST_F(cls_log, trim_by_marker)
326{
327 string oid = "obj";
328 ASSERT_EQ(0, ioctx.create(oid, true));
7c673cae 329
9f95a23c
TL
330 utime_t start_time = ceph_clock_now();
331 generate_log(ioctx, oid, 10, start_time, true);
7c673cae 332
9f95a23c
TL
333 utime_t zero_time;
334 std::vector<cls_log_entry> log1;
335 {
336 list<cls_log_entry> entries;
337 ASSERT_EQ(0, log_list(ioctx, oid, entries));
338 ASSERT_EQ(10u, entries.size());
7c673cae 339
9f95a23c
TL
340 log1.assign(std::make_move_iterator(entries.begin()),
341 std::make_move_iterator(entries.end()));
342 }
343 // trim front of log
344 {
345 const std::string from = "";
346 const std::string to = log1[0].id;
347 ASSERT_EQ(0, do_log_trim(ioctx, oid, from, to));
348 list<cls_log_entry> entries;
349 ASSERT_EQ(0, log_list(ioctx, oid, entries));
350 ASSERT_EQ(9u, entries.size());
351 EXPECT_EQ(log1[1].id, entries.begin()->id);
352 ASSERT_EQ(-ENODATA, do_log_trim(ioctx, oid, from, to));
353 }
354 // trim back of log
355 {
356 const std::string from = log1[8].id;
357 const std::string to = "9";
358 ASSERT_EQ(0, do_log_trim(ioctx, oid, from, to));
359 list<cls_log_entry> entries;
360 ASSERT_EQ(0, log_list(ioctx, oid, entries));
361 ASSERT_EQ(8u, entries.size());
362 EXPECT_EQ(log1[8].id, entries.rbegin()->id);
363 ASSERT_EQ(-ENODATA, do_log_trim(ioctx, oid, from, to));
364 }
365 // trim a key from the middle
366 {
367 const std::string from = log1[3].id;
368 const std::string to = log1[4].id;
369 ASSERT_EQ(0, do_log_trim(ioctx, oid, from, to));
370 list<cls_log_entry> entries;
371 ASSERT_EQ(0, log_list(ioctx, oid, entries));
372 ASSERT_EQ(7u, entries.size());
373 ASSERT_EQ(-ENODATA, do_log_trim(ioctx, oid, from, to));
374 }
375 // trim full log
376 {
377 const std::string from = "";
378 const std::string to = "9";
379 ASSERT_EQ(0, do_log_trim(ioctx, oid, from, to));
380 list<cls_log_entry> entries;
381 ASSERT_EQ(0, log_list(ioctx, oid, entries));
382 ASSERT_EQ(0u, entries.size());
383 ASSERT_EQ(-ENODATA, do_log_trim(ioctx, oid, from, to));
384 }
7c673cae 385}