]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/ObjectMap/test_object_map.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / test / ObjectMap / test_object_map.cc
CommitLineData
7c673cae 1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
f67539c2 2#include <iterator>
7c673cae
FG
3#include <map>
4#include <set>
5#include <boost/scoped_ptr.hpp>
6
7#include "include/buffer.h"
8#include "test/ObjectMap/KeyValueDBMemory.h"
9#include "kv/KeyValueDB.h"
10#include "os/filestore/DBObjectMap.h"
11#include "os/filestore/HashIndex.h"
12#include <sys/types.h>
13#include "global/global_init.h"
14#include "common/ceph_argparse.h"
15#include <dirent.h>
16
17#include "gtest/gtest.h"
18#include "stdlib.h"
19
20using namespace std;
21
22template <typename T>
23typename T::iterator rand_choose(T &cont) {
f67539c2
TL
24 if (std::empty(cont)) {
25 return std::end(cont);
7c673cae 26 }
f67539c2 27 return std::next(std::begin(cont), rand() % cont.size());
7c673cae
FG
28}
29
30string num_str(unsigned i) {
31 char buf[100];
32 snprintf(buf, sizeof(buf), "%.10u", i);
33 return string(buf);
34}
35
36class ObjectMapTester {
37public:
38 ObjectMap *db;
39 set<string> key_space;
40 set<string> object_name_space;
41 map<string, map<string, string> > omap;
42 map<string, string > hmap;
43 map<string, map<string, string> > xattrs;
44 unsigned seq;
45
46 ObjectMapTester() : db(0), seq(0) {}
47
48 string val_from_key(const string &object, const string &key) {
49 return object + "_" + key + "_" + num_str(seq++);
50 }
51
52 void set_key(const string &objname, const string &key, const string &value) {
53 set_key(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))),
54 key, value);
55 }
56
57 void set_xattr(const string &objname, const string &key, const string &value) {
58 set_xattr(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))),
59 key, value);
60 }
61
62 void set_key(ghobject_t hoid,
63 string key, string value) {
64 map<string, bufferlist> to_write;
65 bufferptr bp(value.c_str(), value.size());
66 bufferlist bl;
67 bl.append(bp);
68 to_write.insert(make_pair(key, bl));
69 db->set_keys(hoid, to_write);
70 }
71
72 void set_keys(ghobject_t hoid, const map<string, string> &to_set) {
73 map<string, bufferlist> to_write;
74 for (auto &&i: to_set) {
75 bufferptr bp(i.second.data(), i.second.size());
76 bufferlist bl;
77 bl.append(bp);
78 to_write.insert(make_pair(i.first, bl));
79 }
80 db->set_keys(hoid, to_write);
81 }
82
83 void set_xattr(ghobject_t hoid,
84 string key, string value) {
85 map<string, bufferlist> to_write;
86 bufferptr bp(value.c_str(), value.size());
87 bufferlist bl;
88 bl.append(bp);
89 to_write.insert(make_pair(key, bl));
90 db->set_xattrs(hoid, to_write);
91 }
92
93 void set_header(const string &objname, const string &value) {
94 set_header(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))),
95 value);
96 }
97
98 void set_header(ghobject_t hoid,
99 const string &value) {
100 bufferlist header;
101 header.append(bufferptr(value.c_str(), value.size() + 1));
102 db->set_header(hoid, header);
103 }
104
105 int get_header(const string &objname, string *value) {
106 return get_header(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))),
107 value);
108 }
109
110 int get_header(ghobject_t hoid,
111 string *value) {
112 bufferlist header;
113 int r = db->get_header(hoid, &header);
114 if (r < 0)
115 return r;
116 if (header.length())
117 *value = string(header.c_str());
118 else
119 *value = string("");
120 return 0;
121 }
122
123 int get_xattr(const string &objname, const string &key, string *value) {
124 return get_xattr(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))),
125 key, value);
126 }
127
128 int get_xattr(ghobject_t hoid,
129 string key, string *value) {
130 set<string> to_get;
131 to_get.insert(key);
132 map<string, bufferlist> got;
133 db->get_xattrs(hoid, to_get, &got);
134 if (!got.empty()) {
135 *value = string(got.begin()->second.c_str(),
136 got.begin()->second.length());
137 return 1;
138 } else {
139 return 0;
140 }
141 }
142
143 int get_key(const string &objname, const string &key, string *value) {
144 return get_key(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))),
145 key, value);
146 }
147
148 int get_key(ghobject_t hoid,
149 string key, string *value) {
150 set<string> to_get;
151 to_get.insert(key);
152 map<string, bufferlist> got;
153 db->get_values(hoid, to_get, &got);
154 if (!got.empty()) {
155 if (value) {
156 *value = string(got.begin()->second.c_str(),
157 got.begin()->second.length());
158 }
159 return 1;
160 } else {
161 return 0;
162 }
163 }
164
165 void remove_key(const string &objname, const string &key) {
166 remove_key(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))),
167 key);
168 }
169
170 void remove_keys(const string &objname, const set<string> &to_remove) {
171 remove_keys(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))),
172 to_remove);
173 }
174
175 void remove_key(ghobject_t hoid,
176 string key) {
177 set<string> to_remove;
178 to_remove.insert(key);
179 db->rm_keys(hoid, to_remove);
180 }
181
182 void remove_keys(ghobject_t hoid,
183 const set<string> &to_remove) {
184 db->rm_keys(hoid, to_remove);
185 }
186
187 void remove_xattr(const string &objname, const string &key) {
188 remove_xattr(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))),
189 key);
190 }
191
192 void remove_xattr(ghobject_t hoid,
193 string key) {
194 set<string> to_remove;
195 to_remove.insert(key);
196 db->remove_xattrs(hoid, to_remove);
197 }
198
199 void clone(const string &objname, const string &target) {
200 clone(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))),
201 ghobject_t(hobject_t(sobject_t(target, CEPH_NOSNAP))));
202 }
203
204 void clone(ghobject_t hoid,
205 ghobject_t hoid2) {
206 db->clone(hoid, hoid2);
207 }
208
209 void rename(const string &objname, const string &target) {
210 rename(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))),
211 ghobject_t(hobject_t(sobject_t(target, CEPH_NOSNAP))));
212 }
213
214 void rename(ghobject_t hoid,
215 ghobject_t hoid2) {
216 db->rename(hoid, hoid2);
217 }
218
219 void clear(const string &objname) {
220 clear(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))));
221 }
222
223 void legacy_clone(const string &objname, const string &target) {
224 legacy_clone(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))),
225 ghobject_t(hobject_t(sobject_t(target, CEPH_NOSNAP))));
226 }
227
228 void legacy_clone(ghobject_t hoid,
229 ghobject_t hoid2) {
230 db->legacy_clone(hoid, hoid2);
231 }
232
233 void clear(ghobject_t hoid) {
234 db->clear(hoid);
235 }
236
237 void clear_omap(const string &objname) {
238 clear_omap(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))));
239 }
240
241 void clear_omap(const ghobject_t &objname) {
242 db->clear_keys_header(objname);
243 }
244
245 void def_init() {
246 for (unsigned i = 0; i < 10000; ++i) {
247 key_space.insert("key_" + num_str(i));
248 }
249 for (unsigned i = 0; i < 100; ++i) {
250 object_name_space.insert("name_" + num_str(i));
251 }
252 }
253
254 void init_key_set(const set<string> &keys) {
255 key_space = keys;
256 }
257
258 void init_object_name_space(const set<string> &onamespace) {
259 object_name_space = onamespace;
260 }
261
262 void auto_set_xattr(ostream &out) {
263 set<string>::iterator key = rand_choose(key_space);
264 set<string>::iterator object = rand_choose(object_name_space);
265
266 string value = val_from_key(*object, *key);
267
268 xattrs[*object][*key] = value;
269 set_xattr(*object, *key, value);
270
271 out << "auto_set_xattr " << *object << ": " << *key << " -> "
272 << value << std::endl;
273 }
274
275 void test_set_key(const string &obj, const string &key, const string &val) {
276 omap[obj][key] = val;
277 set_key(obj, key, val);
278 }
279
280 void test_set_keys(const string &obj, const map<string, string> &to_set) {
281 for (auto &&i: to_set) {
282 omap[obj][i.first] = i.second;
283 }
284 set_keys(
285 ghobject_t(hobject_t(sobject_t(obj, CEPH_NOSNAP))),
286 to_set);
287 }
288
289 void auto_set_keys(ostream &out) {
290 set<string>::iterator object = rand_choose(object_name_space);
291
292 map<string, string> to_set;
293 unsigned amount = (rand() % 10) + 1;
294 for (unsigned i = 0; i < amount; ++i) {
295 set<string>::iterator key = rand_choose(key_space);
296 string value = val_from_key(*object, *key);
297 out << "auto_set_key " << *object << ": " << *key << " -> "
298 << value << std::endl;
299 to_set.insert(make_pair(*key, value));
300 }
301
302
303 test_set_keys(*object, to_set);
304 }
305
306 void xattrs_on_object(const string &object, set<string> *out) {
307 if (!xattrs.count(object))
308 return;
309 const map<string, string> &xmap = xattrs.find(object)->second;
310 for (map<string, string>::const_iterator i = xmap.begin();
311 i != xmap.end();
312 ++i) {
313 out->insert(i->first);
314 }
315 }
316
317 void keys_on_object(const string &object, set<string> *out) {
318 if (!omap.count(object))
319 return;
320 const map<string, string> &kmap = omap.find(object)->second;
321 for (map<string, string>::const_iterator i = kmap.begin();
322 i != kmap.end();
323 ++i) {
324 out->insert(i->first);
325 }
326 }
327
328 void xattrs_off_object(const string &object, set<string> *out) {
329 *out = key_space;
330 set<string> xspace;
331 xattrs_on_object(object, &xspace);
332 for (set<string>::iterator i = xspace.begin();
333 i != xspace.end();
334 ++i) {
335 out->erase(*i);
336 }
337 }
338
339 void keys_off_object(const string &object, set<string> *out) {
340 *out = key_space;
341 set<string> kspace;
342 keys_on_object(object, &kspace);
343 for (set<string>::iterator i = kspace.begin();
344 i != kspace.end();
345 ++i) {
346 out->erase(*i);
347 }
348 }
349
350 int auto_check_present_xattr(ostream &out) {
351 set<string>::iterator object = rand_choose(object_name_space);
352 set<string> xspace;
353 xattrs_on_object(*object, &xspace);
354 set<string>::iterator key = rand_choose(xspace);
355 if (key == xspace.end()) {
356 return 1;
357 }
358
359 string result;
360 int r = get_xattr(*object, *key, &result);
361 if (!r) {
362 out << "auto_check_present_key: failed to find key "
363 << *key << " on object " << *object << std::endl;
364 return 0;
365 }
366
367 if (result != xattrs[*object][*key]) {
368 out << "auto_check_present_key: for key "
369 << *key << " on object " << *object
370 << " found value " << result << " where we should have found "
371 << xattrs[*object][*key] << std::endl;
372 return 0;
373 }
374
375 out << "auto_check_present_key: for key "
376 << *key << " on object " << *object
377 << " found value " << result << " where we should have found "
378 << xattrs[*object][*key] << std::endl;
379 return 1;
380 }
381
382
383 int auto_check_present_key(ostream &out) {
384 set<string>::iterator object = rand_choose(object_name_space);
385 set<string> kspace;
386 keys_on_object(*object, &kspace);
387 set<string>::iterator key = rand_choose(kspace);
388 if (key == kspace.end()) {
389 return 1;
390 }
391
392 string result;
393 int r = get_key(*object, *key, &result);
394 if (!r) {
395 out << "auto_check_present_key: failed to find key "
396 << *key << " on object " << *object << std::endl;
397 return 0;
398 }
399
400 if (result != omap[*object][*key]) {
401 out << "auto_check_present_key: for key "
402 << *key << " on object " << *object
403 << " found value " << result << " where we should have found "
404 << omap[*object][*key] << std::endl;
405 return 0;
406 }
407
408 out << "auto_check_present_key: for key "
409 << *key << " on object " << *object
410 << " found value " << result << " where we should have found "
411 << omap[*object][*key] << std::endl;
412 return 1;
413 }
414
415 int auto_check_absent_xattr(ostream &out) {
416 set<string>::iterator object = rand_choose(object_name_space);
417 set<string> xspace;
418 xattrs_off_object(*object, &xspace);
419 set<string>::iterator key = rand_choose(xspace);
420 if (key == xspace.end()) {
421 return 1;
422 }
423
424 string result;
425 int r = get_xattr(*object, *key, &result);
426 if (!r) {
427 out << "auto_check_absent_key: did not find key "
428 << *key << " on object " << *object << std::endl;
429 return 1;
430 }
431
432 out << "auto_check_basent_key: for key "
433 << *key << " on object " << *object
434 << " found value " << result << " where we should have found nothing"
435 << std::endl;
436 return 0;
437 }
438
439 int auto_check_absent_key(ostream &out) {
440 set<string>::iterator object = rand_choose(object_name_space);
441 set<string> kspace;
442 keys_off_object(*object, &kspace);
443 set<string>::iterator key = rand_choose(kspace);
444 if (key == kspace.end()) {
445 return 1;
446 }
447
448 string result;
449 int r = get_key(*object, *key, &result);
450 if (!r) {
451 out << "auto_check_absent_key: did not find key "
452 << *key << " on object " << *object << std::endl;
453 return 1;
454 }
455
456 out << "auto_check_basent_key: for key "
457 << *key << " on object " << *object
458 << " found value " << result << " where we should have found nothing"
459 << std::endl;
460 return 0;
461 }
462
463 void test_clone(const string &object, const string &target, ostream &out) {
464 clone(object, target);
465 if (!omap.count(object)) {
466 out << " source missing.";
467 omap.erase(target);
468 } else {
469 out << " source present.";
470 omap[target] = omap[object];
471 }
472 if (!hmap.count(object)) {
473 out << " hmap source missing." << std::endl;
474 hmap.erase(target);
475 } else {
476 out << " hmap source present." << std::endl;
477 hmap[target] = hmap[object];
478 }
479 if (!xattrs.count(object)) {
480 out << " hmap source missing." << std::endl;
481 xattrs.erase(target);
482 } else {
483 out << " hmap source present." << std::endl;
484 xattrs[target] = xattrs[object];
485 }
486 }
487
488 void auto_clone_key(ostream &out) {
489 set<string>::iterator object = rand_choose(object_name_space);
490 set<string>::iterator target = rand_choose(object_name_space);
491 while (target == object) {
492 target = rand_choose(object_name_space);
493 }
494 out << "clone " << *object << " to " << *target;
495 test_clone(*object, *target, out);
496 }
497
498 void test_remove_keys(const string &obj, const set<string> &to_remove) {
499 for (auto &&k: to_remove)
500 omap[obj].erase(k);
501 remove_keys(obj, to_remove);
502 }
503
504 void test_remove_key(const string &obj, const string &key) {
505 omap[obj].erase(key);
506 remove_key(obj, key);
507 }
508
509 void auto_remove_keys(ostream &out) {
510 set<string>::iterator object = rand_choose(object_name_space);
511 set<string> kspace;
512 keys_on_object(*object, &kspace);
513 set<string> to_remove;
514 for (unsigned i = 0; i < 3; ++i) {
515 set<string>::iterator key = rand_choose(kspace);
516 if (key == kspace.end())
517 continue;
518 out << "removing " << *key << " from " << *object << std::endl;
519 to_remove.insert(*key);
520 }
521 test_remove_keys(*object, to_remove);
522 }
523
524 void auto_remove_xattr(ostream &out) {
525 set<string>::iterator object = rand_choose(object_name_space);
526 set<string> kspace;
527 xattrs_on_object(*object, &kspace);
528 set<string>::iterator key = rand_choose(kspace);
529 if (key == kspace.end()) {
530 return;
531 }
532 out << "removing xattr " << *key << " from " << *object << std::endl;
533 xattrs[*object].erase(*key);
534 remove_xattr(*object, *key);
535 }
536
537 void auto_delete_object(ostream &out) {
538 set<string>::iterator object = rand_choose(object_name_space);
539 out << "auto_delete_object " << *object << std::endl;
540 clear(*object);
541 omap.erase(*object);
542 hmap.erase(*object);
543 xattrs.erase(*object);
544 }
545
546 void test_clear(const string &obj) {
547 clear_omap(obj);
548 omap.erase(obj);
549 hmap.erase(obj);
550 }
551
552 void auto_clear_omap(ostream &out) {
553 set<string>::iterator object = rand_choose(object_name_space);
554 out << "auto_clear_object " << *object << std::endl;
555 test_clear(*object);
556 }
557
558 void auto_write_header(ostream &out) {
559 set<string>::iterator object = rand_choose(object_name_space);
560 string header = val_from_key(*object, "HEADER");
561 out << "auto_write_header: " << *object << " -> " << header << std::endl;
562 set_header(*object, header);
563 hmap[*object] = header;
564 }
565
566 int auto_verify_header(ostream &out) {
567 set<string>::iterator object = rand_choose(object_name_space);
568 out << "verify_header: " << *object << " ";
569 string header;
570 int r = get_header(*object, &header);
571 if (r < 0) {
572 ceph_abort();
573 }
574 if (header.size() == 0) {
575 if (hmap.count(*object)) {
576 out << " failed to find header " << hmap[*object] << std::endl;
577 return 0;
578 } else {
579 out << " found no header" << std::endl;
580 return 1;
581 }
582 }
583
584 if (!hmap.count(*object)) {
585 out << " found header " << header << " should have been empty"
586 << std::endl;
587 return 0;
588 } else if (header == hmap[*object]) {
589 out << " found correct header " << header << std::endl;
590 return 1;
591 } else {
592 out << " found incorrect header " << header
593 << " where we should have found " << hmap[*object] << std::endl;
594 return 0;
595 }
596 }
597
598 void verify_keys(const std::string &obj, ostream &out) {
599 set<string> in_db;
600 ObjectMap::ObjectMapIterator iter = db->get_iterator(
601 ghobject_t(hobject_t(sobject_t(obj, CEPH_NOSNAP))));
602 for (iter->seek_to_first(); iter->valid(); iter->next()) {
603 in_db.insert(iter->key());
604 }
605 bool err = false;
606 for (auto &&i: omap[obj]) {
607 if (!in_db.count(i.first)) {
608 out << __func__ << ": obj " << obj << " missing key "
609 << i.first << std::endl;
610 err = true;
611 } else {
612 in_db.erase(i.first);
613 }
614 }
615 if (!in_db.empty()) {
616 out << __func__ << ": obj " << obj << " found extra keys "
617 << in_db << std::endl;
618 err = true;
619 }
620 ASSERT_FALSE(err);
621 }
622
623 void auto_verify_objects(ostream &out) {
624 for (auto &&i: omap) {
625 verify_keys(i.first, out);
626 }
627 }
628};
629
630class ObjectMapTest : public ::testing::Test {
631public:
632 boost::scoped_ptr< ObjectMap > db;
633 ObjectMapTester tester;
634 void SetUp() override {
635 char *path = getenv("OBJECT_MAP_PATH");
636 if (!path) {
637 db.reset(new DBObjectMap(g_ceph_context, new KeyValueDBMemory()));
638 tester.db = db.get();
639 return;
640 }
641
642 string strpath(path);
643
644 cerr << "using path " << strpath << std::endl;
645 KeyValueDB *store = KeyValueDB::create(g_ceph_context, "leveldb", strpath);
11fdf7f2 646 ceph_assert(!store->create_and_open(cerr));
7c673cae
FG
647
648 db.reset(new DBObjectMap(g_ceph_context, store));
649 tester.db = db.get();
650 }
651
652 void TearDown() override {
653 std::cerr << "Checking..." << std::endl;
654 ASSERT_EQ(0, db->check(std::cerr));
655 }
656};
657
658
659int main(int argc, char **argv) {
660 vector<const char*> args;
661 argv_to_vec(argc, (const char **)argv, args);
662
663 auto cct = global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT,
11fdf7f2
TL
664 CODE_ENVIRONMENT_UTILITY,
665 CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
7c673cae
FG
666 common_init_finish(g_ceph_context);
667 ::testing::InitGoogleTest(&argc, argv);
668 return RUN_ALL_TESTS();
669}
670
671TEST_F(ObjectMapTest, CreateOneObject) {
672 ghobject_t hoid(hobject_t(sobject_t("foo", CEPH_NOSNAP)), 100, shard_id_t(0));
673 map<string, bufferlist> to_set;
674 string key("test");
675 string val("test_val");
676 bufferptr bp(val.c_str(), val.size());
677 bufferlist bl;
678 bl.append(bp);
679 to_set.insert(make_pair(key, bl));
31f18b77 680 ASSERT_EQ(db->set_keys(hoid, to_set), 0);
7c673cae
FG
681
682 map<string, bufferlist> got;
683 set<string> to_get;
684 to_get.insert(key);
685 to_get.insert("not there");
686 db->get_values(hoid, to_get, &got);
687 ASSERT_EQ(got.size(), (unsigned)1);
688 ASSERT_EQ(string(got[key].c_str(), got[key].length()), val);
689
690 bufferlist header;
691 got.clear();
692 db->get(hoid, &header, &got);
693 ASSERT_EQ(got.size(), (unsigned)1);
694 ASSERT_EQ(string(got[key].c_str(), got[key].length()), val);
695 ASSERT_EQ(header.length(), (unsigned)0);
696
697 db->rm_keys(hoid, to_get);
698 got.clear();
699 db->get(hoid, &header, &got);
700 ASSERT_EQ(got.size(), (unsigned)0);
701
702 map<string, bufferlist> attrs;
703 attrs["attr1"] = bl;
704 db->set_xattrs(hoid, attrs);
705
706 db->set_header(hoid, bl);
707
708 db->clear_keys_header(hoid);
709 set<string> attrs_got;
710 db->get_all_xattrs(hoid, &attrs_got);
711 ASSERT_EQ(attrs_got.size(), 1U);
712 ASSERT_EQ(*(attrs_got.begin()), "attr1");
713 db->get(hoid, &header, &got);
714 ASSERT_EQ(got.size(), (unsigned)0);
715 ASSERT_EQ(header.length(), 0U);
716 got.clear();
717
718 db->clear(hoid);
719 db->get(hoid, &header, &got);
720 ASSERT_EQ(got.size(), (unsigned)0);
721 attrs_got.clear();
722 db->get_all_xattrs(hoid, &attrs_got);
723 ASSERT_EQ(attrs_got.size(), 0U);
724}
725
726TEST_F(ObjectMapTest, CloneOneObject) {
727 ghobject_t hoid(hobject_t(sobject_t("foo", CEPH_NOSNAP)), 200, shard_id_t(0));
728 ghobject_t hoid2(hobject_t(sobject_t("foo2", CEPH_NOSNAP)), 201, shard_id_t(1));
729
730 tester.set_key(hoid, "foo", "bar");
731 tester.set_key(hoid, "foo2", "bar2");
732 string result;
733 int r = tester.get_key(hoid, "foo", &result);
734 ASSERT_EQ(r, 1);
735 ASSERT_EQ(result, "bar");
736
737 db->clone(hoid, hoid2);
738 r = tester.get_key(hoid, "foo", &result);
739 ASSERT_EQ(r, 1);
740 ASSERT_EQ(result, "bar");
741 r = tester.get_key(hoid2, "foo", &result);
742 ASSERT_EQ(r, 1);
743 ASSERT_EQ(result, "bar");
744
745 tester.remove_key(hoid, "foo");
746 r = tester.get_key(hoid2, "foo", &result);
747 ASSERT_EQ(r, 1);
748 ASSERT_EQ(result, "bar");
749 r = tester.get_key(hoid, "foo", &result);
750 ASSERT_EQ(r, 0);
751 r = tester.get_key(hoid, "foo2", &result);
752 ASSERT_EQ(r, 1);
753 ASSERT_EQ(result, "bar2");
754
755 tester.set_key(hoid, "foo", "baz");
756 tester.remove_key(hoid, "foo");
757 r = tester.get_key(hoid, "foo", &result);
758 ASSERT_EQ(r, 0);
759
760 tester.set_key(hoid, "foo2", "baz");
761 tester.remove_key(hoid, "foo2");
762 r = tester.get_key(hoid, "foo2", &result);
763 ASSERT_EQ(r, 0);
764
765 map<string, bufferlist> got;
766 bufferlist header;
767
768 got.clear();
769 db->clear(hoid);
770 db->get(hoid, &header, &got);
771 ASSERT_EQ(got.size(), (unsigned)0);
772
773 got.clear();
774 r = db->clear(hoid2);
775 ASSERT_EQ(0, r);
776 db->get(hoid2, &header, &got);
777 ASSERT_EQ(got.size(), (unsigned)0);
778
779 tester.set_key(hoid, "baz", "bar");
780 got.clear();
781 db->get(hoid, &header, &got);
782 ASSERT_EQ(got.size(), (unsigned)1);
783 db->clear(hoid);
784 db->clear(hoid2);
785}
786
787TEST_F(ObjectMapTest, OddEvenClone) {
788 ghobject_t hoid(hobject_t(sobject_t("foo", CEPH_NOSNAP)));
789 ghobject_t hoid2(hobject_t(sobject_t("foo2", CEPH_NOSNAP)));
790
791 for (unsigned i = 0; i < 1000; ++i) {
792 tester.set_key(hoid, "foo" + num_str(i), "bar" + num_str(i));
793 }
794
795 db->clone(hoid, hoid2);
796
797 int r = 0;
798 for (unsigned i = 0; i < 1000; ++i) {
799 string result;
800 r = tester.get_key(hoid, "foo" + num_str(i), &result);
801 ASSERT_EQ(1, r);
802 ASSERT_EQ("bar" + num_str(i), result);
803 r = tester.get_key(hoid2, "foo" + num_str(i), &result);
804 ASSERT_EQ(1, r);
805 ASSERT_EQ("bar" + num_str(i), result);
806
807 if (i % 2) {
808 tester.remove_key(hoid, "foo" + num_str(i));
809 } else {
810 tester.remove_key(hoid2, "foo" + num_str(i));
811 }
812 }
813
814 for (unsigned i = 0; i < 1000; ++i) {
815 string result;
816 string result2;
817 r = tester.get_key(hoid, "foo" + num_str(i), &result);
818 int r2 = tester.get_key(hoid2, "foo" + num_str(i), &result2);
819 if (i % 2) {
820 ASSERT_EQ(0, r);
821 ASSERT_EQ(1, r2);
822 ASSERT_EQ("bar" + num_str(i), result2);
823 } else {
824 ASSERT_EQ(0, r2);
825 ASSERT_EQ(1, r);
826 ASSERT_EQ("bar" + num_str(i), result);
827 }
828 }
829
830 {
831 ObjectMap::ObjectMapIterator iter = db->get_iterator(hoid);
832 iter->seek_to_first();
833 for (unsigned i = 0; i < 1000; ++i) {
834 if (!(i % 2)) {
835 ASSERT_TRUE(iter->valid());
836 ASSERT_EQ("foo" + num_str(i), iter->key());
837 iter->next();
838 }
839 }
840 }
841
842 {
843 ObjectMap::ObjectMapIterator iter2 = db->get_iterator(hoid2);
844 iter2->seek_to_first();
845 for (unsigned i = 0; i < 1000; ++i) {
846 if (i % 2) {
847 ASSERT_TRUE(iter2->valid());
848 ASSERT_EQ("foo" + num_str(i), iter2->key());
849 iter2->next();
850 }
851 }
852 }
853
854 db->clear(hoid);
855 db->clear(hoid2);
856}
857
858TEST_F(ObjectMapTest, Rename) {
859 ghobject_t hoid(hobject_t(sobject_t("foo", CEPH_NOSNAP)));
860 ghobject_t hoid2(hobject_t(sobject_t("foo2", CEPH_NOSNAP)));
861
862 for (unsigned i = 0; i < 1000; ++i) {
863 tester.set_key(hoid, "foo" + num_str(i), "bar" + num_str(i));
864 }
865
866 db->rename(hoid, hoid2);
867 // Verify rename where target exists
868 db->clone(hoid2, hoid);
869 db->rename(hoid, hoid2);
870
871 int r = 0;
872 for (unsigned i = 0; i < 1000; ++i) {
873 string result;
874 r = tester.get_key(hoid2, "foo" + num_str(i), &result);
875 ASSERT_EQ(1, r);
876 ASSERT_EQ("bar" + num_str(i), result);
877
878 if (i % 2) {
879 tester.remove_key(hoid2, "foo" + num_str(i));
880 }
881 }
882
883 for (unsigned i = 0; i < 1000; ++i) {
884 string result;
885 r = tester.get_key(hoid2, "foo" + num_str(i), &result);
886 if (i % 2) {
887 ASSERT_EQ(0, r);
888 } else {
889 ASSERT_EQ(1, r);
890 ASSERT_EQ("bar" + num_str(i), result);
891 }
892 }
893
894 {
895 ObjectMap::ObjectMapIterator iter = db->get_iterator(hoid2);
896 iter->seek_to_first();
897 for (unsigned i = 0; i < 1000; ++i) {
898 if (!(i % 2)) {
899 ASSERT_TRUE(iter->valid());
900 ASSERT_EQ("foo" + num_str(i), iter->key());
901 iter->next();
902 }
903 }
904 }
905
906 db->clear(hoid2);
907}
908
909TEST_F(ObjectMapTest, OddEvenOldClone) {
910 ghobject_t hoid(hobject_t(sobject_t("foo", CEPH_NOSNAP)));
911 ghobject_t hoid2(hobject_t(sobject_t("foo2", CEPH_NOSNAP)));
912
913 for (unsigned i = 0; i < 1000; ++i) {
914 tester.set_key(hoid, "foo" + num_str(i), "bar" + num_str(i));
915 }
916
917 db->legacy_clone(hoid, hoid2);
918
919 int r = 0;
920 for (unsigned i = 0; i < 1000; ++i) {
921 string result;
922 r = tester.get_key(hoid, "foo" + num_str(i), &result);
923 ASSERT_EQ(1, r);
924 ASSERT_EQ("bar" + num_str(i), result);
925 r = tester.get_key(hoid2, "foo" + num_str(i), &result);
926 ASSERT_EQ(1, r);
927 ASSERT_EQ("bar" + num_str(i), result);
928
929 if (i % 2) {
930 tester.remove_key(hoid, "foo" + num_str(i));
931 } else {
932 tester.remove_key(hoid2, "foo" + num_str(i));
933 }
934 }
935
936 for (unsigned i = 0; i < 1000; ++i) {
937 string result;
938 string result2;
939 r = tester.get_key(hoid, "foo" + num_str(i), &result);
940 int r2 = tester.get_key(hoid2, "foo" + num_str(i), &result2);
941 if (i % 2) {
942 ASSERT_EQ(0, r);
943 ASSERT_EQ(1, r2);
944 ASSERT_EQ("bar" + num_str(i), result2);
945 } else {
946 ASSERT_EQ(0, r2);
947 ASSERT_EQ(1, r);
948 ASSERT_EQ("bar" + num_str(i), result);
949 }
950 }
951
952 {
953 ObjectMap::ObjectMapIterator iter = db->get_iterator(hoid);
954 iter->seek_to_first();
955 for (unsigned i = 0; i < 1000; ++i) {
956 if (!(i % 2)) {
957 ASSERT_TRUE(iter->valid());
958 ASSERT_EQ("foo" + num_str(i), iter->key());
959 iter->next();
960 }
961 }
962 }
963
964 {
965 ObjectMap::ObjectMapIterator iter2 = db->get_iterator(hoid2);
966 iter2->seek_to_first();
967 for (unsigned i = 0; i < 1000; ++i) {
968 if (i % 2) {
969 ASSERT_TRUE(iter2->valid());
970 ASSERT_EQ("foo" + num_str(i), iter2->key());
971 iter2->next();
972 }
973 }
974 }
975
976 db->clear(hoid);
977 db->clear(hoid2);
978}
979
980TEST_F(ObjectMapTest, RandomTest) {
981 tester.def_init();
982 for (unsigned i = 0; i < 5000; ++i) {
983 unsigned val = rand();
984 val <<= 8;
985 val %= 100;
986 if (!(i%100))
987 std::cout << "on op " << i
988 << " val is " << val << std::endl;
989
990 if (val < 7) {
991 tester.auto_write_header(std::cerr);
992 } else if (val < 14) {
993 ASSERT_TRUE(tester.auto_verify_header(std::cerr));
994 } else if (val < 30) {
995 tester.auto_set_keys(std::cerr);
996 } else if (val < 42) {
997 tester.auto_set_xattr(std::cerr);
998 } else if (val < 55) {
999 ASSERT_TRUE(tester.auto_check_present_key(std::cerr));
1000 } else if (val < 62) {
1001 ASSERT_TRUE(tester.auto_check_present_xattr(std::cerr));
1002 } else if (val < 70) {
1003 ASSERT_TRUE(tester.auto_check_absent_key(std::cerr));
1004 } else if (val < 72) {
1005 ASSERT_TRUE(tester.auto_check_absent_xattr(std::cerr));
1006 } else if (val < 73) {
1007 tester.auto_clear_omap(std::cerr);
1008 } else if (val < 76) {
1009 tester.auto_delete_object(std::cerr);
1010 } else if (val < 85) {
1011 tester.auto_clone_key(std::cerr);
1012 } else if (val < 92) {
1013 tester.auto_remove_xattr(std::cerr);
1014 } else {
1015 tester.auto_remove_keys(std::cerr);
1016 }
1017
1018 if (i % 500) {
1019 tester.auto_verify_objects(std::cerr);
1020 }
1021 }
1022}
1023
1024TEST_F(ObjectMapTest, RandomTestNoDeletesXattrs) {
1025 tester.def_init();
1026 for (unsigned i = 0; i < 5000; ++i) {
1027 unsigned val = rand();
1028 val <<= 8;
1029 val %= 100;
1030 if (!(i%100))
1031 std::cout << "on op " << i
1032 << " val is " << val << std::endl;
1033
1034 if (val < 45) {
1035 tester.auto_set_keys(std::cerr);
1036 } else if (val < 90) {
1037 tester.auto_remove_keys(std::cerr);
1038 } else {
1039 tester.auto_clone_key(std::cerr);
1040 }
1041
1042 if (i % 500) {
1043 tester.auto_verify_objects(std::cerr);
1044 }
1045 }
1046}
1047
1048string num_to_key(unsigned i) {
1049 char buf[100];
1050 int ret = snprintf(buf, sizeof(buf), "%010u", i);
11fdf7f2 1051 ceph_assert(ret > 0);
7c673cae
FG
1052 return string(buf, ret);
1053}
1054
1055TEST_F(ObjectMapTest, TestMergeNewCompleteContainBug) {
1056 /* This test exploits a bug in kraken and earlier where merge_new_complete
1057 * could miss complete entries fully contained by a new entry. To get this
1058 * to actually result in an incorrect return value, you need to remove at
1059 * least two values, one before a complete region, and one which occurs in
1060 * the parent after the complete region (but within 20 not yet completed
1061 * parent points of the first value).
1062 */
1063 for (unsigned i = 10; i < 160; i+=2) {
1064 tester.test_set_key("foo", num_to_key(i), "asdf");
1065 }
1066 tester.test_clone("foo", "foo2", std::cout);
1067 tester.test_clear("foo");
1068
1069 tester.test_set_key("foo2", num_to_key(15), "asdf");
1070 tester.test_set_key("foo2", num_to_key(13), "asdf");
1071 tester.test_set_key("foo2", num_to_key(57), "asdf");
1072
1073 tester.test_remove_key("foo2", num_to_key(15));
1074
1075 set<string> to_remove;
1076 to_remove.insert(num_to_key(13));
1077 to_remove.insert(num_to_key(58));
1078 to_remove.insert(num_to_key(60));
1079 to_remove.insert(num_to_key(62));
1080 tester.test_remove_keys("foo2", to_remove);
1081
1082 tester.verify_keys("foo2", std::cout);
1083 ASSERT_EQ(tester.get_key("foo2", num_to_key(10), nullptr), 1);
1084 ASSERT_EQ(tester.get_key("foo2", num_to_key(1), nullptr), 0);
1085 ASSERT_EQ(tester.get_key("foo2", num_to_key(56), nullptr), 1);
1086 // this one triggers the bug
1087 ASSERT_EQ(tester.get_key("foo2", num_to_key(58), nullptr), 0);
1088}
1089
1090TEST_F(ObjectMapTest, TestIterateBug18533) {
1091 /* This test starts with the one immediately above to create a pair of
1092 * complete regions where one contains the other. Then, it deletes the
1093 * key at the start of the contained region. The logic in next_parent()
1094 * skips ahead to the end of the contained region, and we start copying
1095 * values down again from the parent into the child -- including some
1096 * that had actually been deleted. I think this works for any removal
1097 * within the outer complete region after the start of the contained
1098 * region.
1099 */
1100 for (unsigned i = 10; i < 160; i+=2) {
1101 tester.test_set_key("foo", num_to_key(i), "asdf");
1102 }
1103 tester.test_clone("foo", "foo2", std::cout);
1104 tester.test_clear("foo");
1105
1106 tester.test_set_key("foo2", num_to_key(15), "asdf");
1107 tester.test_set_key("foo2", num_to_key(13), "asdf");
1108 tester.test_set_key("foo2", num_to_key(57), "asdf");
1109 tester.test_set_key("foo2", num_to_key(91), "asdf");
1110
1111 tester.test_remove_key("foo2", num_to_key(15));
1112
1113 set<string> to_remove;
1114 to_remove.insert(num_to_key(13));
1115 to_remove.insert(num_to_key(58));
1116 to_remove.insert(num_to_key(60));
1117 to_remove.insert(num_to_key(62));
1118 to_remove.insert(num_to_key(82));
1119 to_remove.insert(num_to_key(84));
1120 tester.test_remove_keys("foo2", to_remove);
1121
1122 //tester.test_remove_key("foo2", num_to_key(15)); also does the trick
1123 tester.test_remove_key("foo2", num_to_key(80));
1124
1125 // the iterator in verify_keys will return an extra value
1126 tester.verify_keys("foo2", std::cout);
1127}
1128