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