mirror of
https://github.com/ceph/ceph
synced 2025-01-31 23:44:10 +00:00
test/librbd: add DiffIterateTest.DiffIterateDeterministic{,PP}
scribble()-based DiffIterate tests are too weak: at least two regressions that should been caught by DiffIterate.DiffIterate or DiffIterate.DiffIterateStress were missed [1][2]. Aside from the randomness which can be both a good and a bad thing, asserts there ensure only that the returned diff covers all changes that were made. If the returned diff is too excessive or otherwise bogus, this isn't detected [3]. Add a deterministic test to systematically cover the most common cases that don't involve discards. A similar test for discards will be added with the fix for [4]. Comment out debug log in vector_iterate_cb() like it's done in iterate_cb(). [1] https://tracker.ceph.com/issues/50787 [2] https://tracker.ceph.com/issues/63654 [3] https://tracker.ceph.com/issues/63719 [4] https://tracker.ceph.com/issues/53897 Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
This commit is contained in:
parent
0a1f633e02
commit
f5e3f26372
@ -7501,12 +7501,273 @@ ostream& operator<<(ostream & o, const diff_extent& e) {
|
||||
|
||||
int vector_iterate_cb(uint64_t off, size_t len, int exists, void *arg)
|
||||
{
|
||||
cout << "iterate_cb " << off << "~" << len << std::endl;
|
||||
//cout << "iterate_cb " << off << "~" << len << std::endl;
|
||||
vector<diff_extent> *diff = static_cast<vector<diff_extent> *>(arg);
|
||||
diff->push_back(diff_extent(off, len, exists, 0));
|
||||
return 0;
|
||||
}
|
||||
|
||||
TYPED_TEST(DiffIterateTest, DiffIterateDeterministic)
|
||||
{
|
||||
REQUIRE(!is_feature_enabled(RBD_FEATURE_STRIPINGV2));
|
||||
|
||||
rados_ioctx_t ioctx;
|
||||
ASSERT_EQ(0, rados_ioctx_create(this->_cluster, this->m_pool_name.c_str(),
|
||||
&ioctx));
|
||||
|
||||
rbd_image_t image;
|
||||
int order = 22;
|
||||
std::string name = this->get_temp_image_name();
|
||||
uint64_t size = 20 << 20;
|
||||
|
||||
ASSERT_EQ(0, create_image(ioctx, name.c_str(), size, &order));
|
||||
ASSERT_EQ(0, rbd_open(ioctx, name.c_str(), &image, NULL));
|
||||
|
||||
uint64_t object_size = 0;
|
||||
if (this->whole_object) {
|
||||
object_size = 1 << order;
|
||||
}
|
||||
|
||||
std::vector<diff_extent> extents;
|
||||
ASSERT_EQ(0, rbd_diff_iterate2(image, NULL, 0, size, true, this->whole_object,
|
||||
vector_iterate_cb, &extents));
|
||||
ASSERT_EQ(0u, extents.size());
|
||||
|
||||
ASSERT_EQ(0, rbd_snap_create(image, "snap1"));
|
||||
|
||||
std::string buf(256, '1');
|
||||
ASSERT_EQ(256, rbd_write(image, 0, 256, buf.data()));
|
||||
ASSERT_EQ(0, rbd_diff_iterate2(image, NULL, 0, size, true, this->whole_object,
|
||||
vector_iterate_cb, &extents));
|
||||
ASSERT_EQ(1u, extents.size());
|
||||
ASSERT_EQ(diff_extent(0, 256, true, object_size), extents[0]);
|
||||
extents.clear();
|
||||
|
||||
ASSERT_EQ(0, rbd_snap_create(image, "snap2"));
|
||||
|
||||
ASSERT_EQ(256, rbd_write(image, 1 << order, 256, buf.data()));
|
||||
ASSERT_EQ(0, rbd_diff_iterate2(image, NULL, 0, size, true, this->whole_object,
|
||||
vector_iterate_cb, &extents));
|
||||
ASSERT_EQ(2u, extents.size());
|
||||
ASSERT_EQ(diff_extent(0, 256, true, object_size), extents[0]);
|
||||
ASSERT_EQ(diff_extent(1 << order, 256, true, object_size), extents[1]);
|
||||
extents.clear();
|
||||
|
||||
ASSERT_EQ(0, rbd_snap_create(image, "snap3"));
|
||||
|
||||
// 1. beginning of time -> HEAD
|
||||
ASSERT_EQ(0, rbd_diff_iterate2(image, NULL, 0, size, true, this->whole_object,
|
||||
vector_iterate_cb, &extents));
|
||||
ASSERT_EQ(2u, extents.size());
|
||||
ASSERT_EQ(diff_extent(0, 256, true, object_size), extents[0]);
|
||||
ASSERT_EQ(diff_extent(1 << order, 256, true, object_size), extents[1]);
|
||||
extents.clear();
|
||||
|
||||
// 2. snap1 -> HEAD
|
||||
ASSERT_EQ(0, rbd_diff_iterate2(image, "snap1", 0, size, true, this->whole_object,
|
||||
vector_iterate_cb, &extents));
|
||||
ASSERT_EQ(2u, extents.size());
|
||||
ASSERT_EQ(diff_extent(0, 256, true, object_size), extents[0]);
|
||||
ASSERT_EQ(diff_extent(1 << order, 256, true, object_size), extents[1]);
|
||||
extents.clear();
|
||||
|
||||
// 3. snap2 -> HEAD
|
||||
ASSERT_EQ(0, rbd_diff_iterate2(image, "snap2", 0, size, true, this->whole_object,
|
||||
vector_iterate_cb, &extents));
|
||||
ASSERT_EQ(1u, extents.size());
|
||||
ASSERT_EQ(diff_extent(1 << order, 256, true, object_size), extents[0]);
|
||||
extents.clear();
|
||||
|
||||
// 4. snap3 -> HEAD
|
||||
ASSERT_EQ(0, rbd_diff_iterate2(image, "snap3", 0, size, true, this->whole_object,
|
||||
vector_iterate_cb, &extents));
|
||||
ASSERT_EQ(0u, extents.size());
|
||||
|
||||
ASSERT_PASSED(this->validate_object_map, image);
|
||||
ASSERT_EQ(0, rbd_snap_set(image, "snap3"));
|
||||
|
||||
// 5. beginning of time -> snap3
|
||||
ASSERT_EQ(0, rbd_diff_iterate2(image, NULL, 0, size, true, this->whole_object,
|
||||
vector_iterate_cb, &extents));
|
||||
ASSERT_EQ(2u, extents.size());
|
||||
ASSERT_EQ(diff_extent(0, 256, true, object_size), extents[0]);
|
||||
ASSERT_EQ(diff_extent(1 << order, 256, true, object_size), extents[1]);
|
||||
extents.clear();
|
||||
|
||||
// 6. snap1 -> snap3
|
||||
ASSERT_EQ(0, rbd_diff_iterate2(image, "snap1", 0, size, true, this->whole_object,
|
||||
vector_iterate_cb, &extents));
|
||||
ASSERT_EQ(2u, extents.size());
|
||||
ASSERT_EQ(diff_extent(0, 256, true, object_size), extents[0]);
|
||||
ASSERT_EQ(diff_extent(1 << order, 256, true, object_size), extents[1]);
|
||||
extents.clear();
|
||||
|
||||
// 7. snap2 -> snap3
|
||||
ASSERT_EQ(0, rbd_diff_iterate2(image, "snap2", 0, size, true, this->whole_object,
|
||||
vector_iterate_cb, &extents));
|
||||
ASSERT_EQ(1u, extents.size());
|
||||
ASSERT_EQ(diff_extent(1 << order, 256, true, object_size), extents[0]);
|
||||
extents.clear();
|
||||
|
||||
ASSERT_PASSED(this->validate_object_map, image);
|
||||
ASSERT_EQ(0, rbd_snap_set(image, "snap2"));
|
||||
|
||||
// 8. beginning of time -> snap2
|
||||
ASSERT_EQ(0, rbd_diff_iterate2(image, NULL, 0, size, true, this->whole_object,
|
||||
vector_iterate_cb, &extents));
|
||||
ASSERT_EQ(1u, extents.size());
|
||||
ASSERT_EQ(diff_extent(0, 256, true, object_size), extents[0]);
|
||||
extents.clear();
|
||||
|
||||
// 9. snap1 -> snap2
|
||||
ASSERT_EQ(0, rbd_diff_iterate2(image, "snap1", 0, size, true, this->whole_object,
|
||||
vector_iterate_cb, &extents));
|
||||
ASSERT_EQ(1u, extents.size());
|
||||
ASSERT_EQ(diff_extent(0, 256, true, object_size), extents[0]);
|
||||
extents.clear();
|
||||
|
||||
ASSERT_PASSED(this->validate_object_map, image);
|
||||
ASSERT_EQ(0, rbd_snap_set(image, "snap1"));
|
||||
|
||||
// 10. beginning of time -> snap1
|
||||
ASSERT_EQ(0, rbd_diff_iterate2(image, NULL, 0, size, true, this->whole_object,
|
||||
vector_iterate_cb, &extents));
|
||||
ASSERT_EQ(0u, extents.size());
|
||||
|
||||
ASSERT_PASSED(this->validate_object_map, image);
|
||||
}
|
||||
|
||||
TYPED_TEST(DiffIterateTest, DiffIterateDeterministicPP)
|
||||
{
|
||||
REQUIRE(!is_feature_enabled(RBD_FEATURE_STRIPINGV2));
|
||||
|
||||
librados::IoCtx ioctx;
|
||||
ASSERT_EQ(0, this->_rados.ioctx_create(this->m_pool_name.c_str(), ioctx));
|
||||
|
||||
librbd::RBD rbd;
|
||||
librbd::Image image;
|
||||
int order = 22;
|
||||
std::string name = this->get_temp_image_name();
|
||||
uint64_t size = 20 << 20;
|
||||
|
||||
ASSERT_EQ(0, create_image_pp(rbd, ioctx, name.c_str(), size, &order));
|
||||
ASSERT_EQ(0, rbd.open(ioctx, image, name.c_str(), NULL));
|
||||
|
||||
uint64_t object_size = 0;
|
||||
if (this->whole_object) {
|
||||
object_size = 1 << order;
|
||||
}
|
||||
|
||||
std::vector<diff_extent> extents;
|
||||
ASSERT_EQ(0, image.diff_iterate2(NULL, 0, size, true, this->whole_object,
|
||||
vector_iterate_cb, &extents));
|
||||
ASSERT_EQ(0u, extents.size());
|
||||
|
||||
ASSERT_EQ(0, image.snap_create("snap1"));
|
||||
|
||||
ceph::bufferlist bl;
|
||||
bl.append(std::string(256, '1'));
|
||||
ASSERT_EQ(256, image.write(0, 256, bl));
|
||||
ASSERT_EQ(0, image.diff_iterate2(NULL, 0, size, true, this->whole_object,
|
||||
vector_iterate_cb, &extents));
|
||||
ASSERT_EQ(1u, extents.size());
|
||||
ASSERT_EQ(diff_extent(0, 256, true, object_size), extents[0]);
|
||||
extents.clear();
|
||||
|
||||
ASSERT_EQ(0, image.snap_create("snap2"));
|
||||
|
||||
ASSERT_EQ(256, image.write(1 << order, 256, bl));
|
||||
ASSERT_EQ(0, image.diff_iterate2(NULL, 0, size, true, this->whole_object,
|
||||
vector_iterate_cb, &extents));
|
||||
ASSERT_EQ(2u, extents.size());
|
||||
ASSERT_EQ(diff_extent(0, 256, true, object_size), extents[0]);
|
||||
ASSERT_EQ(diff_extent(1 << order, 256, true, object_size), extents[1]);
|
||||
extents.clear();
|
||||
|
||||
ASSERT_EQ(0, image.snap_create("snap3"));
|
||||
|
||||
// 1. beginning of time -> HEAD
|
||||
ASSERT_EQ(0, image.diff_iterate2(NULL, 0, size, true, this->whole_object,
|
||||
vector_iterate_cb, &extents));
|
||||
ASSERT_EQ(2u, extents.size());
|
||||
ASSERT_EQ(diff_extent(0, 256, true, object_size), extents[0]);
|
||||
ASSERT_EQ(diff_extent(1 << order, 256, true, object_size), extents[1]);
|
||||
extents.clear();
|
||||
|
||||
// 2. snap1 -> HEAD
|
||||
ASSERT_EQ(0, image.diff_iterate2("snap1", 0, size, true, this->whole_object,
|
||||
vector_iterate_cb, &extents));
|
||||
ASSERT_EQ(2u, extents.size());
|
||||
ASSERT_EQ(diff_extent(0, 256, true, object_size), extents[0]);
|
||||
ASSERT_EQ(diff_extent(1 << order, 256, true, object_size), extents[1]);
|
||||
extents.clear();
|
||||
|
||||
// 3. snap2 -> HEAD
|
||||
ASSERT_EQ(0, image.diff_iterate2("snap2", 0, size, true, this->whole_object,
|
||||
vector_iterate_cb, &extents));
|
||||
ASSERT_EQ(1u, extents.size());
|
||||
ASSERT_EQ(diff_extent(1 << order, 256, true, object_size), extents[0]);
|
||||
extents.clear();
|
||||
|
||||
// 4. snap3 -> HEAD
|
||||
ASSERT_EQ(0, image.diff_iterate2("snap3", 0, size, true, this->whole_object,
|
||||
vector_iterate_cb, &extents));
|
||||
ASSERT_EQ(0u, extents.size());
|
||||
|
||||
ASSERT_PASSED(this->validate_object_map, image);
|
||||
ASSERT_EQ(0, image.snap_set("snap3"));
|
||||
|
||||
// 5. beginning of time -> snap3
|
||||
ASSERT_EQ(0, image.diff_iterate2(NULL, 0, size, true, this->whole_object,
|
||||
vector_iterate_cb, &extents));
|
||||
ASSERT_EQ(2u, extents.size());
|
||||
ASSERT_EQ(diff_extent(0, 256, true, object_size), extents[0]);
|
||||
ASSERT_EQ(diff_extent(1 << order, 256, true, object_size), extents[1]);
|
||||
extents.clear();
|
||||
|
||||
// 6. snap1 -> snap3
|
||||
ASSERT_EQ(0, image.diff_iterate2("snap1", 0, size, true, this->whole_object,
|
||||
vector_iterate_cb, &extents));
|
||||
ASSERT_EQ(2u, extents.size());
|
||||
ASSERT_EQ(diff_extent(0, 256, true, object_size), extents[0]);
|
||||
ASSERT_EQ(diff_extent(1 << order, 256, true, object_size), extents[1]);
|
||||
extents.clear();
|
||||
|
||||
// 7. snap2 -> snap3
|
||||
ASSERT_EQ(0, image.diff_iterate2("snap2", 0, size, true, this->whole_object,
|
||||
vector_iterate_cb, &extents));
|
||||
ASSERT_EQ(1u, extents.size());
|
||||
ASSERT_EQ(diff_extent(1 << order, 256, true, object_size), extents[0]);
|
||||
extents.clear();
|
||||
|
||||
ASSERT_PASSED(this->validate_object_map, image);
|
||||
ASSERT_EQ(0, image.snap_set("snap2"));
|
||||
|
||||
// 8. beginning of time -> snap2
|
||||
ASSERT_EQ(0, image.diff_iterate2(NULL, 0, size, true, this->whole_object,
|
||||
vector_iterate_cb, &extents));
|
||||
ASSERT_EQ(1u, extents.size());
|
||||
ASSERT_EQ(diff_extent(0, 256, true, object_size), extents[0]);
|
||||
extents.clear();
|
||||
|
||||
// 9. snap1 -> snap2
|
||||
ASSERT_EQ(0, image.diff_iterate2("snap1", 0, size, true, this->whole_object,
|
||||
vector_iterate_cb, &extents));
|
||||
ASSERT_EQ(1u, extents.size());
|
||||
ASSERT_EQ(diff_extent(0, 256, true, object_size), extents[0]);
|
||||
extents.clear();
|
||||
|
||||
ASSERT_PASSED(this->validate_object_map, image);
|
||||
ASSERT_EQ(0, image.snap_set("snap1"));
|
||||
|
||||
// 10. beginning of time -> snap1
|
||||
ASSERT_EQ(0, image.diff_iterate2(NULL, 0, size, true, this->whole_object,
|
||||
vector_iterate_cb, &extents));
|
||||
ASSERT_EQ(0u, extents.size());
|
||||
|
||||
ASSERT_PASSED(this->validate_object_map, image);
|
||||
}
|
||||
|
||||
TYPED_TEST(DiffIterateTest, DiffIterateDiscard)
|
||||
{
|
||||
librados::IoCtx ioctx;
|
||||
|
Loading…
Reference in New Issue
Block a user