1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 #include "include/memory.h"
5 #include <boost/scoped_ptr.hpp>
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"
17 #include "gtest/gtest.h"
23 typename T::iterator rand_choose(T &cont) {
24 if (cont.size() == 0) {
27 int index = rand() % cont.size();
28 typename T::iterator retval = cont.begin();
30 for (; index > 0; --index) ++retval;
34 string num_str(unsigned i) {
36 snprintf(buf, sizeof(buf), "%.10u", i);
40 class ObjectMapTester {
43 set<string> key_space;
44 set<string> object_name_space;
45 map<string, map<string, string> > omap;
46 map<string, string > hmap;
47 map<string, map<string, string> > xattrs;
50 ObjectMapTester() : db(0), seq(0) {}
52 string val_from_key(const string &object, const string &key) {
53 return object + "_" + key + "_" + num_str(seq++);
56 void set_key(const string &objname, const string &key, const string &value) {
57 set_key(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))),
61 void set_xattr(const string &objname, const string &key, const string &value) {
62 set_xattr(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))),
66 void set_key(ghobject_t hoid,
67 string key, string value) {
68 map<string, bufferlist> to_write;
69 bufferptr bp(value.c_str(), value.size());
72 to_write.insert(make_pair(key, bl));
73 db->set_keys(hoid, to_write);
76 void set_keys(ghobject_t hoid, const map<string, string> &to_set) {
77 map<string, bufferlist> to_write;
78 for (auto &&i: to_set) {
79 bufferptr bp(i.second.data(), i.second.size());
82 to_write.insert(make_pair(i.first, bl));
84 db->set_keys(hoid, to_write);
87 void set_xattr(ghobject_t hoid,
88 string key, string value) {
89 map<string, bufferlist> to_write;
90 bufferptr bp(value.c_str(), value.size());
93 to_write.insert(make_pair(key, bl));
94 db->set_xattrs(hoid, to_write);
97 void set_header(const string &objname, const string &value) {
98 set_header(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))),
102 void set_header(ghobject_t hoid,
103 const string &value) {
105 header.append(bufferptr(value.c_str(), value.size() + 1));
106 db->set_header(hoid, header);
109 int get_header(const string &objname, string *value) {
110 return get_header(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))),
114 int get_header(ghobject_t hoid,
117 int r = db->get_header(hoid, &header);
121 *value = string(header.c_str());
127 int get_xattr(const string &objname, const string &key, string *value) {
128 return get_xattr(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))),
132 int get_xattr(ghobject_t hoid,
133 string key, string *value) {
136 map<string, bufferlist> got;
137 db->get_xattrs(hoid, to_get, &got);
139 *value = string(got.begin()->second.c_str(),
140 got.begin()->second.length());
147 int get_key(const string &objname, const string &key, string *value) {
148 return get_key(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))),
152 int get_key(ghobject_t hoid,
153 string key, string *value) {
156 map<string, bufferlist> got;
157 db->get_values(hoid, to_get, &got);
160 *value = string(got.begin()->second.c_str(),
161 got.begin()->second.length());
169 void remove_key(const string &objname, const string &key) {
170 remove_key(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))),
174 void remove_keys(const string &objname, const set<string> &to_remove) {
175 remove_keys(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))),
179 void remove_key(ghobject_t hoid,
181 set<string> to_remove;
182 to_remove.insert(key);
183 db->rm_keys(hoid, to_remove);
186 void remove_keys(ghobject_t hoid,
187 const set<string> &to_remove) {
188 db->rm_keys(hoid, to_remove);
191 void remove_xattr(const string &objname, const string &key) {
192 remove_xattr(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))),
196 void remove_xattr(ghobject_t hoid,
198 set<string> to_remove;
199 to_remove.insert(key);
200 db->remove_xattrs(hoid, to_remove);
203 void clone(const string &objname, const string &target) {
204 clone(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))),
205 ghobject_t(hobject_t(sobject_t(target, CEPH_NOSNAP))));
208 void clone(ghobject_t hoid,
210 db->clone(hoid, hoid2);
213 void rename(const string &objname, const string &target) {
214 rename(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))),
215 ghobject_t(hobject_t(sobject_t(target, CEPH_NOSNAP))));
218 void rename(ghobject_t hoid,
220 db->rename(hoid, hoid2);
223 void clear(const string &objname) {
224 clear(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))));
227 void legacy_clone(const string &objname, const string &target) {
228 legacy_clone(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))),
229 ghobject_t(hobject_t(sobject_t(target, CEPH_NOSNAP))));
232 void legacy_clone(ghobject_t hoid,
234 db->legacy_clone(hoid, hoid2);
237 void clear(ghobject_t hoid) {
241 void clear_omap(const string &objname) {
242 clear_omap(ghobject_t(hobject_t(sobject_t(objname, CEPH_NOSNAP))));
245 void clear_omap(const ghobject_t &objname) {
246 db->clear_keys_header(objname);
250 for (unsigned i = 0; i < 10000; ++i) {
251 key_space.insert("key_" + num_str(i));
253 for (unsigned i = 0; i < 100; ++i) {
254 object_name_space.insert("name_" + num_str(i));
258 void init_key_set(const set<string> &keys) {
262 void init_object_name_space(const set<string> &onamespace) {
263 object_name_space = onamespace;
266 void auto_set_xattr(ostream &out) {
267 set<string>::iterator key = rand_choose(key_space);
268 set<string>::iterator object = rand_choose(object_name_space);
270 string value = val_from_key(*object, *key);
272 xattrs[*object][*key] = value;
273 set_xattr(*object, *key, value);
275 out << "auto_set_xattr " << *object << ": " << *key << " -> "
276 << value << std::endl;
279 void test_set_key(const string &obj, const string &key, const string &val) {
280 omap[obj][key] = val;
281 set_key(obj, key, val);
284 void test_set_keys(const string &obj, const map<string, string> &to_set) {
285 for (auto &&i: to_set) {
286 omap[obj][i.first] = i.second;
289 ghobject_t(hobject_t(sobject_t(obj, CEPH_NOSNAP))),
293 void auto_set_keys(ostream &out) {
294 set<string>::iterator object = rand_choose(object_name_space);
296 map<string, string> to_set;
297 unsigned amount = (rand() % 10) + 1;
298 for (unsigned i = 0; i < amount; ++i) {
299 set<string>::iterator key = rand_choose(key_space);
300 string value = val_from_key(*object, *key);
301 out << "auto_set_key " << *object << ": " << *key << " -> "
302 << value << std::endl;
303 to_set.insert(make_pair(*key, value));
307 test_set_keys(*object, to_set);
310 void xattrs_on_object(const string &object, set<string> *out) {
311 if (!xattrs.count(object))
313 const map<string, string> &xmap = xattrs.find(object)->second;
314 for (map<string, string>::const_iterator i = xmap.begin();
317 out->insert(i->first);
321 void keys_on_object(const string &object, set<string> *out) {
322 if (!omap.count(object))
324 const map<string, string> &kmap = omap.find(object)->second;
325 for (map<string, string>::const_iterator i = kmap.begin();
328 out->insert(i->first);
332 void xattrs_off_object(const string &object, set<string> *out) {
335 xattrs_on_object(object, &xspace);
336 for (set<string>::iterator i = xspace.begin();
343 void keys_off_object(const string &object, set<string> *out) {
346 keys_on_object(object, &kspace);
347 for (set<string>::iterator i = kspace.begin();
354 int auto_check_present_xattr(ostream &out) {
355 set<string>::iterator object = rand_choose(object_name_space);
357 xattrs_on_object(*object, &xspace);
358 set<string>::iterator key = rand_choose(xspace);
359 if (key == xspace.end()) {
364 int r = get_xattr(*object, *key, &result);
366 out << "auto_check_present_key: failed to find key "
367 << *key << " on object " << *object << std::endl;
371 if (result != xattrs[*object][*key]) {
372 out << "auto_check_present_key: for key "
373 << *key << " on object " << *object
374 << " found value " << result << " where we should have found "
375 << xattrs[*object][*key] << std::endl;
379 out << "auto_check_present_key: for key "
380 << *key << " on object " << *object
381 << " found value " << result << " where we should have found "
382 << xattrs[*object][*key] << std::endl;
387 int auto_check_present_key(ostream &out) {
388 set<string>::iterator object = rand_choose(object_name_space);
390 keys_on_object(*object, &kspace);
391 set<string>::iterator key = rand_choose(kspace);
392 if (key == kspace.end()) {
397 int r = get_key(*object, *key, &result);
399 out << "auto_check_present_key: failed to find key "
400 << *key << " on object " << *object << std::endl;
404 if (result != omap[*object][*key]) {
405 out << "auto_check_present_key: for key "
406 << *key << " on object " << *object
407 << " found value " << result << " where we should have found "
408 << omap[*object][*key] << std::endl;
412 out << "auto_check_present_key: for key "
413 << *key << " on object " << *object
414 << " found value " << result << " where we should have found "
415 << omap[*object][*key] << std::endl;
419 int auto_check_absent_xattr(ostream &out) {
420 set<string>::iterator object = rand_choose(object_name_space);
422 xattrs_off_object(*object, &xspace);
423 set<string>::iterator key = rand_choose(xspace);
424 if (key == xspace.end()) {
429 int r = get_xattr(*object, *key, &result);
431 out << "auto_check_absent_key: did not find key "
432 << *key << " on object " << *object << std::endl;
436 out << "auto_check_basent_key: for key "
437 << *key << " on object " << *object
438 << " found value " << result << " where we should have found nothing"
443 int auto_check_absent_key(ostream &out) {
444 set<string>::iterator object = rand_choose(object_name_space);
446 keys_off_object(*object, &kspace);
447 set<string>::iterator key = rand_choose(kspace);
448 if (key == kspace.end()) {
453 int r = get_key(*object, *key, &result);
455 out << "auto_check_absent_key: did not find key "
456 << *key << " on object " << *object << std::endl;
460 out << "auto_check_basent_key: for key "
461 << *key << " on object " << *object
462 << " found value " << result << " where we should have found nothing"
467 void test_clone(const string &object, const string &target, ostream &out) {
468 clone(object, target);
469 if (!omap.count(object)) {
470 out << " source missing.";
473 out << " source present.";
474 omap[target] = omap[object];
476 if (!hmap.count(object)) {
477 out << " hmap source missing." << std::endl;
480 out << " hmap source present." << std::endl;
481 hmap[target] = hmap[object];
483 if (!xattrs.count(object)) {
484 out << " hmap source missing." << std::endl;
485 xattrs.erase(target);
487 out << " hmap source present." << std::endl;
488 xattrs[target] = xattrs[object];
492 void auto_clone_key(ostream &out) {
493 set<string>::iterator object = rand_choose(object_name_space);
494 set<string>::iterator target = rand_choose(object_name_space);
495 while (target == object) {
496 target = rand_choose(object_name_space);
498 out << "clone " << *object << " to " << *target;
499 test_clone(*object, *target, out);
502 void test_remove_keys(const string &obj, const set<string> &to_remove) {
503 for (auto &&k: to_remove)
505 remove_keys(obj, to_remove);
508 void test_remove_key(const string &obj, const string &key) {
509 omap[obj].erase(key);
510 remove_key(obj, key);
513 void auto_remove_keys(ostream &out) {
514 set<string>::iterator object = rand_choose(object_name_space);
516 keys_on_object(*object, &kspace);
517 set<string> to_remove;
518 for (unsigned i = 0; i < 3; ++i) {
519 set<string>::iterator key = rand_choose(kspace);
520 if (key == kspace.end())
522 out << "removing " << *key << " from " << *object << std::endl;
523 to_remove.insert(*key);
525 test_remove_keys(*object, to_remove);
528 void auto_remove_xattr(ostream &out) {
529 set<string>::iterator object = rand_choose(object_name_space);
531 xattrs_on_object(*object, &kspace);
532 set<string>::iterator key = rand_choose(kspace);
533 if (key == kspace.end()) {
536 out << "removing xattr " << *key << " from " << *object << std::endl;
537 xattrs[*object].erase(*key);
538 remove_xattr(*object, *key);
541 void auto_delete_object(ostream &out) {
542 set<string>::iterator object = rand_choose(object_name_space);
543 out << "auto_delete_object " << *object << std::endl;
547 xattrs.erase(*object);
550 void test_clear(const string &obj) {
556 void auto_clear_omap(ostream &out) {
557 set<string>::iterator object = rand_choose(object_name_space);
558 out << "auto_clear_object " << *object << std::endl;
562 void auto_write_header(ostream &out) {
563 set<string>::iterator object = rand_choose(object_name_space);
564 string header = val_from_key(*object, "HEADER");
565 out << "auto_write_header: " << *object << " -> " << header << std::endl;
566 set_header(*object, header);
567 hmap[*object] = header;
570 int auto_verify_header(ostream &out) {
571 set<string>::iterator object = rand_choose(object_name_space);
572 out << "verify_header: " << *object << " ";
574 int r = get_header(*object, &header);
578 if (header.size() == 0) {
579 if (hmap.count(*object)) {
580 out << " failed to find header " << hmap[*object] << std::endl;
583 out << " found no header" << std::endl;
588 if (!hmap.count(*object)) {
589 out << " found header " << header << " should have been empty"
592 } else if (header == hmap[*object]) {
593 out << " found correct header " << header << std::endl;
596 out << " found incorrect header " << header
597 << " where we should have found " << hmap[*object] << std::endl;
602 void verify_keys(const std::string &obj, ostream &out) {
604 ObjectMap::ObjectMapIterator iter = db->get_iterator(
605 ghobject_t(hobject_t(sobject_t(obj, CEPH_NOSNAP))));
606 for (iter->seek_to_first(); iter->valid(); iter->next()) {
607 in_db.insert(iter->key());
610 for (auto &&i: omap[obj]) {
611 if (!in_db.count(i.first)) {
612 out << __func__ << ": obj " << obj << " missing key "
613 << i.first << std::endl;
616 in_db.erase(i.first);
619 if (!in_db.empty()) {
620 out << __func__ << ": obj " << obj << " found extra keys "
621 << in_db << std::endl;
627 void auto_verify_objects(ostream &out) {
628 for (auto &&i: omap) {
629 verify_keys(i.first, out);
634 class ObjectMapTest : public ::testing::Test {
636 boost::scoped_ptr< ObjectMap > db;
637 ObjectMapTester tester;
638 void SetUp() override {
639 char *path = getenv("OBJECT_MAP_PATH");
641 db.reset(new DBObjectMap(g_ceph_context, new KeyValueDBMemory()));
642 tester.db = db.get();
646 string strpath(path);
648 cerr << "using path " << strpath << std::endl;
649 KeyValueDB *store = KeyValueDB::create(g_ceph_context, "leveldb", strpath);
650 assert(!store->create_and_open(cerr));
652 db.reset(new DBObjectMap(g_ceph_context, store));
653 tester.db = db.get();
656 void TearDown() override {
657 std::cerr << "Checking..." << std::endl;
658 ASSERT_EQ(0, db->check(std::cerr));
663 int main(int argc, char **argv) {
664 vector<const char*> args;
665 argv_to_vec(argc, (const char **)argv, args);
667 auto cct = global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT,
668 CODE_ENVIRONMENT_UTILITY, 0);
669 common_init_finish(g_ceph_context);
670 ::testing::InitGoogleTest(&argc, argv);
671 return RUN_ALL_TESTS();
674 TEST_F(ObjectMapTest, CreateOneObject) {
675 ghobject_t hoid(hobject_t(sobject_t("foo", CEPH_NOSNAP)), 100, shard_id_t(0));
676 map<string, bufferlist> to_set;
678 string val("test_val");
679 bufferptr bp(val.c_str(), val.size());
682 to_set.insert(make_pair(key, bl));
683 ASSERT_EQ(db->set_keys(hoid, to_set), 0);
685 map<string, bufferlist> got;
688 to_get.insert("not there");
689 db->get_values(hoid, to_get, &got);
690 ASSERT_EQ(got.size(), (unsigned)1);
691 ASSERT_EQ(string(got[key].c_str(), got[key].length()), val);
695 db->get(hoid, &header, &got);
696 ASSERT_EQ(got.size(), (unsigned)1);
697 ASSERT_EQ(string(got[key].c_str(), got[key].length()), val);
698 ASSERT_EQ(header.length(), (unsigned)0);
700 db->rm_keys(hoid, to_get);
702 db->get(hoid, &header, &got);
703 ASSERT_EQ(got.size(), (unsigned)0);
705 map<string, bufferlist> attrs;
707 db->set_xattrs(hoid, attrs);
709 db->set_header(hoid, bl);
711 db->clear_keys_header(hoid);
712 set<string> attrs_got;
713 db->get_all_xattrs(hoid, &attrs_got);
714 ASSERT_EQ(attrs_got.size(), 1U);
715 ASSERT_EQ(*(attrs_got.begin()), "attr1");
716 db->get(hoid, &header, &got);
717 ASSERT_EQ(got.size(), (unsigned)0);
718 ASSERT_EQ(header.length(), 0U);
722 db->get(hoid, &header, &got);
723 ASSERT_EQ(got.size(), (unsigned)0);
725 db->get_all_xattrs(hoid, &attrs_got);
726 ASSERT_EQ(attrs_got.size(), 0U);
729 TEST_F(ObjectMapTest, CloneOneObject) {
730 ghobject_t hoid(hobject_t(sobject_t("foo", CEPH_NOSNAP)), 200, shard_id_t(0));
731 ghobject_t hoid2(hobject_t(sobject_t("foo2", CEPH_NOSNAP)), 201, shard_id_t(1));
733 tester.set_key(hoid, "foo", "bar");
734 tester.set_key(hoid, "foo2", "bar2");
736 int r = tester.get_key(hoid, "foo", &result);
738 ASSERT_EQ(result, "bar");
740 db->clone(hoid, hoid2);
741 r = tester.get_key(hoid, "foo", &result);
743 ASSERT_EQ(result, "bar");
744 r = tester.get_key(hoid2, "foo", &result);
746 ASSERT_EQ(result, "bar");
748 tester.remove_key(hoid, "foo");
749 r = tester.get_key(hoid2, "foo", &result);
751 ASSERT_EQ(result, "bar");
752 r = tester.get_key(hoid, "foo", &result);
754 r = tester.get_key(hoid, "foo2", &result);
756 ASSERT_EQ(result, "bar2");
758 tester.set_key(hoid, "foo", "baz");
759 tester.remove_key(hoid, "foo");
760 r = tester.get_key(hoid, "foo", &result);
763 tester.set_key(hoid, "foo2", "baz");
764 tester.remove_key(hoid, "foo2");
765 r = tester.get_key(hoid, "foo2", &result);
768 map<string, bufferlist> got;
773 db->get(hoid, &header, &got);
774 ASSERT_EQ(got.size(), (unsigned)0);
777 r = db->clear(hoid2);
779 db->get(hoid2, &header, &got);
780 ASSERT_EQ(got.size(), (unsigned)0);
782 tester.set_key(hoid, "baz", "bar");
784 db->get(hoid, &header, &got);
785 ASSERT_EQ(got.size(), (unsigned)1);
790 TEST_F(ObjectMapTest, OddEvenClone) {
791 ghobject_t hoid(hobject_t(sobject_t("foo", CEPH_NOSNAP)));
792 ghobject_t hoid2(hobject_t(sobject_t("foo2", CEPH_NOSNAP)));
794 for (unsigned i = 0; i < 1000; ++i) {
795 tester.set_key(hoid, "foo" + num_str(i), "bar" + num_str(i));
798 db->clone(hoid, hoid2);
801 for (unsigned i = 0; i < 1000; ++i) {
803 r = tester.get_key(hoid, "foo" + num_str(i), &result);
805 ASSERT_EQ("bar" + num_str(i), result);
806 r = tester.get_key(hoid2, "foo" + num_str(i), &result);
808 ASSERT_EQ("bar" + num_str(i), result);
811 tester.remove_key(hoid, "foo" + num_str(i));
813 tester.remove_key(hoid2, "foo" + num_str(i));
817 for (unsigned i = 0; i < 1000; ++i) {
820 r = tester.get_key(hoid, "foo" + num_str(i), &result);
821 int r2 = tester.get_key(hoid2, "foo" + num_str(i), &result2);
825 ASSERT_EQ("bar" + num_str(i), result2);
829 ASSERT_EQ("bar" + num_str(i), result);
834 ObjectMap::ObjectMapIterator iter = db->get_iterator(hoid);
835 iter->seek_to_first();
836 for (unsigned i = 0; i < 1000; ++i) {
838 ASSERT_TRUE(iter->valid());
839 ASSERT_EQ("foo" + num_str(i), iter->key());
846 ObjectMap::ObjectMapIterator iter2 = db->get_iterator(hoid2);
847 iter2->seek_to_first();
848 for (unsigned i = 0; i < 1000; ++i) {
850 ASSERT_TRUE(iter2->valid());
851 ASSERT_EQ("foo" + num_str(i), iter2->key());
861 TEST_F(ObjectMapTest, Rename) {
862 ghobject_t hoid(hobject_t(sobject_t("foo", CEPH_NOSNAP)));
863 ghobject_t hoid2(hobject_t(sobject_t("foo2", CEPH_NOSNAP)));
865 for (unsigned i = 0; i < 1000; ++i) {
866 tester.set_key(hoid, "foo" + num_str(i), "bar" + num_str(i));
869 db->rename(hoid, hoid2);
870 // Verify rename where target exists
871 db->clone(hoid2, hoid);
872 db->rename(hoid, hoid2);
875 for (unsigned i = 0; i < 1000; ++i) {
877 r = tester.get_key(hoid2, "foo" + num_str(i), &result);
879 ASSERT_EQ("bar" + num_str(i), result);
882 tester.remove_key(hoid2, "foo" + num_str(i));
886 for (unsigned i = 0; i < 1000; ++i) {
888 r = tester.get_key(hoid2, "foo" + num_str(i), &result);
893 ASSERT_EQ("bar" + num_str(i), result);
898 ObjectMap::ObjectMapIterator iter = db->get_iterator(hoid2);
899 iter->seek_to_first();
900 for (unsigned i = 0; i < 1000; ++i) {
902 ASSERT_TRUE(iter->valid());
903 ASSERT_EQ("foo" + num_str(i), iter->key());
912 TEST_F(ObjectMapTest, OddEvenOldClone) {
913 ghobject_t hoid(hobject_t(sobject_t("foo", CEPH_NOSNAP)));
914 ghobject_t hoid2(hobject_t(sobject_t("foo2", CEPH_NOSNAP)));
916 for (unsigned i = 0; i < 1000; ++i) {
917 tester.set_key(hoid, "foo" + num_str(i), "bar" + num_str(i));
920 db->legacy_clone(hoid, hoid2);
923 for (unsigned i = 0; i < 1000; ++i) {
925 r = tester.get_key(hoid, "foo" + num_str(i), &result);
927 ASSERT_EQ("bar" + num_str(i), result);
928 r = tester.get_key(hoid2, "foo" + num_str(i), &result);
930 ASSERT_EQ("bar" + num_str(i), result);
933 tester.remove_key(hoid, "foo" + num_str(i));
935 tester.remove_key(hoid2, "foo" + num_str(i));
939 for (unsigned i = 0; i < 1000; ++i) {
942 r = tester.get_key(hoid, "foo" + num_str(i), &result);
943 int r2 = tester.get_key(hoid2, "foo" + num_str(i), &result2);
947 ASSERT_EQ("bar" + num_str(i), result2);
951 ASSERT_EQ("bar" + num_str(i), result);
956 ObjectMap::ObjectMapIterator iter = db->get_iterator(hoid);
957 iter->seek_to_first();
958 for (unsigned i = 0; i < 1000; ++i) {
960 ASSERT_TRUE(iter->valid());
961 ASSERT_EQ("foo" + num_str(i), iter->key());
968 ObjectMap::ObjectMapIterator iter2 = db->get_iterator(hoid2);
969 iter2->seek_to_first();
970 for (unsigned i = 0; i < 1000; ++i) {
972 ASSERT_TRUE(iter2->valid());
973 ASSERT_EQ("foo" + num_str(i), iter2->key());
983 TEST_F(ObjectMapTest, RandomTest) {
985 for (unsigned i = 0; i < 5000; ++i) {
986 unsigned val = rand();
990 std::cout << "on op " << i
991 << " val is " << val << std::endl;
994 tester.auto_write_header(std::cerr);
995 } else if (val < 14) {
996 ASSERT_TRUE(tester.auto_verify_header(std::cerr));
997 } else if (val < 30) {
998 tester.auto_set_keys(std::cerr);
999 } else if (val < 42) {
1000 tester.auto_set_xattr(std::cerr);
1001 } else if (val < 55) {
1002 ASSERT_TRUE(tester.auto_check_present_key(std::cerr));
1003 } else if (val < 62) {
1004 ASSERT_TRUE(tester.auto_check_present_xattr(std::cerr));
1005 } else if (val < 70) {
1006 ASSERT_TRUE(tester.auto_check_absent_key(std::cerr));
1007 } else if (val < 72) {
1008 ASSERT_TRUE(tester.auto_check_absent_xattr(std::cerr));
1009 } else if (val < 73) {
1010 tester.auto_clear_omap(std::cerr);
1011 } else if (val < 76) {
1012 tester.auto_delete_object(std::cerr);
1013 } else if (val < 85) {
1014 tester.auto_clone_key(std::cerr);
1015 } else if (val < 92) {
1016 tester.auto_remove_xattr(std::cerr);
1018 tester.auto_remove_keys(std::cerr);
1022 tester.auto_verify_objects(std::cerr);
1027 TEST_F(ObjectMapTest, RandomTestNoDeletesXattrs) {
1029 for (unsigned i = 0; i < 5000; ++i) {
1030 unsigned val = rand();
1034 std::cout << "on op " << i
1035 << " val is " << val << std::endl;
1038 tester.auto_set_keys(std::cerr);
1039 } else if (val < 90) {
1040 tester.auto_remove_keys(std::cerr);
1042 tester.auto_clone_key(std::cerr);
1046 tester.auto_verify_objects(std::cerr);
1051 string num_to_key(unsigned i) {
1053 int ret = snprintf(buf, sizeof(buf), "%010u", i);
1055 return string(buf, ret);
1058 TEST_F(ObjectMapTest, TestMergeNewCompleteContainBug) {
1059 /* This test exploits a bug in kraken and earlier where merge_new_complete
1060 * could miss complete entries fully contained by a new entry. To get this
1061 * to actually result in an incorrect return value, you need to remove at
1062 * least two values, one before a complete region, and one which occurs in
1063 * the parent after the complete region (but within 20 not yet completed
1064 * parent points of the first value).
1066 for (unsigned i = 10; i < 160; i+=2) {
1067 tester.test_set_key("foo", num_to_key(i), "asdf");
1069 tester.test_clone("foo", "foo2", std::cout);
1070 tester.test_clear("foo");
1072 tester.test_set_key("foo2", num_to_key(15), "asdf");
1073 tester.test_set_key("foo2", num_to_key(13), "asdf");
1074 tester.test_set_key("foo2", num_to_key(57), "asdf");
1076 tester.test_remove_key("foo2", num_to_key(15));
1078 set<string> to_remove;
1079 to_remove.insert(num_to_key(13));
1080 to_remove.insert(num_to_key(58));
1081 to_remove.insert(num_to_key(60));
1082 to_remove.insert(num_to_key(62));
1083 tester.test_remove_keys("foo2", to_remove);
1085 tester.verify_keys("foo2", std::cout);
1086 ASSERT_EQ(tester.get_key("foo2", num_to_key(10), nullptr), 1);
1087 ASSERT_EQ(tester.get_key("foo2", num_to_key(1), nullptr), 0);
1088 ASSERT_EQ(tester.get_key("foo2", num_to_key(56), nullptr), 1);
1089 // this one triggers the bug
1090 ASSERT_EQ(tester.get_key("foo2", num_to_key(58), nullptr), 0);
1093 TEST_F(ObjectMapTest, TestIterateBug18533) {
1094 /* This test starts with the one immediately above to create a pair of
1095 * complete regions where one contains the other. Then, it deletes the
1096 * key at the start of the contained region. The logic in next_parent()
1097 * skips ahead to the end of the contained region, and we start copying
1098 * values down again from the parent into the child -- including some
1099 * that had actually been deleted. I think this works for any removal
1100 * within the outer complete region after the start of the contained
1103 for (unsigned i = 10; i < 160; i+=2) {
1104 tester.test_set_key("foo", num_to_key(i), "asdf");
1106 tester.test_clone("foo", "foo2", std::cout);
1107 tester.test_clear("foo");
1109 tester.test_set_key("foo2", num_to_key(15), "asdf");
1110 tester.test_set_key("foo2", num_to_key(13), "asdf");
1111 tester.test_set_key("foo2", num_to_key(57), "asdf");
1112 tester.test_set_key("foo2", num_to_key(91), "asdf");
1114 tester.test_remove_key("foo2", num_to_key(15));
1116 set<string> to_remove;
1117 to_remove.insert(num_to_key(13));
1118 to_remove.insert(num_to_key(58));
1119 to_remove.insert(num_to_key(60));
1120 to_remove.insert(num_to_key(62));
1121 to_remove.insert(num_to_key(82));
1122 to_remove.insert(num_to_key(84));
1123 tester.test_remove_keys("foo2", to_remove);
1125 //tester.test_remove_key("foo2", num_to_key(15)); also does the trick
1126 tester.test_remove_key("foo2", num_to_key(80));
1128 // the iterator in verify_keys will return an extra value
1129 tester.verify_keys("foo2", std::cout);