From: NitzanMordhai Date: Thu, 28 Jul 2022 12:27:51 +0000 (+0000) Subject: test/cls_refcount: Add unit-test for ec pools and refcount X-Git-Tag: v18.1.0~468^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=92d13f0a8f0f6e0263a0f05f04809d6becd9c736;p=ceph.git test/cls_refcount: Add unit-test for ec pools and refcount Create set of unit-test for erasure code pools Fixes: https://tracker.ceph.com/issues/56707 Signed-off-by: Nitzan Mordechai --- diff --git a/src/test/cls_refcount/test_cls_refcount.cc b/src/test/cls_refcount/test_cls_refcount.cc index b080c86ad782..2868b48b660b 100644 --- a/src/test/cls_refcount/test_cls_refcount.cc +++ b/src/test/cls_refcount/test_cls_refcount.cc @@ -396,3 +396,383 @@ TEST(cls_rgw, set) /* test refcount using implicit referencing of newly created ioctx.close(); ASSERT_EQ(0, destroy_one_pool_pp(pool_name, rados)); } + +TEST(cls_rgw, test_implicit_ec) /* test refcount using implicit referencing of newly created objects */ +{ + librados::Rados rados; + librados::IoCtx ioctx; + string pool_name = get_temp_pool_name(); + + /* create pool */ + ASSERT_EQ("", create_one_ec_pool_pp(pool_name, rados)); + ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx)); + + /* add chains */ + string oid = "obj"; + string oldtag = "oldtag"; + string newtag = "newtag"; + + + /* get on a missing object will fail */ + librados::ObjectWriteOperation *op = new_op(); + cls_refcount_get(*op, newtag, true); + ASSERT_EQ(-ENOENT, ioctx.operate(oid, op)); + delete op; + + /* create object */ + ASSERT_EQ(0, ioctx.create(oid, true)); + + /* read reference, should return a single wildcard entry */ + + list refs; + + ASSERT_EQ(0, cls_refcount_read(ioctx, oid, &refs, true)); + ASSERT_EQ(1, (int)refs.size()); + + string wildcard_tag; + string tag = refs.front(); + + ASSERT_EQ(wildcard_tag, tag); + + /* take another reference, verify */ + op = new_op(); + cls_refcount_get(*op, newtag, true); + ASSERT_EQ(0, ioctx.operate(oid, op)); + + ASSERT_EQ(0, cls_refcount_read(ioctx, oid, &refs, true)); + ASSERT_EQ(2, (int)refs.size()); + + map refs_map; + for (list::iterator iter = refs.begin(); iter != refs.end(); ++iter) { + refs_map[*iter] = true; + } + + ASSERT_EQ(1, (int)refs_map.count(wildcard_tag)); + ASSERT_EQ(1, (int)refs_map.count(newtag)); + + delete op; + + /* drop reference to oldtag */ + + op = new_op(); + cls_refcount_put(*op, oldtag, true); + ASSERT_EQ(0, ioctx.operate(oid, op)); + + ASSERT_EQ(0, cls_refcount_read(ioctx, oid, &refs, true)); + ASSERT_EQ(1, (int)refs.size()); + + tag = refs.front(); + ASSERT_EQ(newtag, tag); + + delete op; + + /* drop oldtag reference again, op should return success, wouldn't do anything */ + + op = new_op(); + cls_refcount_put(*op, oldtag, true); + ASSERT_EQ(0, ioctx.operate(oid, op)); + + ASSERT_EQ(0, cls_refcount_read(ioctx, oid, &refs, true)); + ASSERT_EQ(1, (int)refs.size()); + + tag = refs.front(); + ASSERT_EQ(newtag, tag); + + delete op; + + /* drop newtag reference, make sure object removed */ + op = new_op(); + cls_refcount_put(*op, newtag, true); + ASSERT_EQ(0, ioctx.operate(oid, op)); + + ASSERT_EQ(-ENOENT, ioctx.stat(oid, NULL, NULL)); + + delete op; + + /* remove pool */ + ioctx.close(); + ASSERT_EQ(0, destroy_one_ec_pool_pp(pool_name, rados)); +} + +/* + * similar to test_implicit, just changes the order of the tags removal + * see issue #20107 + */ +TEST(cls_rgw, test_implicit_idempotent_ec) /* test refcount using implicit referencing of newly created objects */ +{ + librados::Rados rados; + librados::IoCtx ioctx; + string pool_name = get_temp_pool_name(); + + /* create pool */ + ASSERT_EQ("", create_one_ec_pool_pp(pool_name, rados)); + ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx)); + + /* add chains */ + string oid = "obj"; + string oldtag = "oldtag"; + string newtag = "newtag"; + + + /* get on a missing object will fail */ + librados::ObjectWriteOperation *op = new_op(); + cls_refcount_get(*op, newtag, true); + ASSERT_EQ(-ENOENT, ioctx.operate(oid, op)); + delete op; + + /* create object */ + ASSERT_EQ(0, ioctx.create(oid, true)); + + /* read reference, should return a single wildcard entry */ + + list refs; + + ASSERT_EQ(0, cls_refcount_read(ioctx, oid, &refs, true)); + ASSERT_EQ(1, (int)refs.size()); + + string wildcard_tag; + string tag = refs.front(); + + ASSERT_EQ(wildcard_tag, tag); + + /* take another reference, verify */ + op = new_op(); + cls_refcount_get(*op, newtag, true); + ASSERT_EQ(0, ioctx.operate(oid, op)); + + ASSERT_EQ(0, cls_refcount_read(ioctx, oid, &refs, true)); + ASSERT_EQ(2, (int)refs.size()); + + map refs_map; + for (list::iterator iter = refs.begin(); iter != refs.end(); ++iter) { + refs_map[*iter] = true; + } + + ASSERT_EQ(1, (int)refs_map.count(wildcard_tag)); + ASSERT_EQ(1, (int)refs_map.count(newtag)); + + delete op; + + /* drop reference to newtag */ + + op = new_op(); + cls_refcount_put(*op, newtag, true); + ASSERT_EQ(0, ioctx.operate(oid, op)); + + ASSERT_EQ(0, cls_refcount_read(ioctx, oid, &refs, true)); + ASSERT_EQ(1, (int)refs.size()); + + tag = refs.front(); + ASSERT_EQ(string(), tag); + + delete op; + + /* drop newtag reference again, op should return success, wouldn't do anything */ + + op = new_op(); + cls_refcount_put(*op, newtag, true); + ASSERT_EQ(0, ioctx.operate(oid, op)); + + ASSERT_EQ(0, cls_refcount_read(ioctx, oid, &refs, true)); + ASSERT_EQ(1, (int)refs.size()); + + tag = refs.front(); + ASSERT_EQ(string(), tag); + + delete op; + + /* drop oldtag reference, make sure object removed */ + op = new_op(); + cls_refcount_put(*op, oldtag, true); + ASSERT_EQ(0, ioctx.operate(oid, op)); + + ASSERT_EQ(-ENOENT, ioctx.stat(oid, NULL, NULL)); + + delete op; + + /* remove pool */ + ioctx.close(); + ASSERT_EQ(0, destroy_one_ec_pool_pp(pool_name, rados)); +} + + +TEST(cls_rgw, test_put_snap_ec) { + librados::Rados rados; + librados::IoCtx ioctx; + string pool_name = get_temp_pool_name(); + + /* create pool */ + ASSERT_EQ("", create_one_ec_pool_pp(pool_name, rados)); + ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx)); + + bufferlist bl; + bl.append("hi there"); + ASSERT_EQ(0, ioctx.write("foo", bl, bl.length(), 0)); + ASSERT_EQ(0, ioctx.snap_create("snapfoo")); + ASSERT_EQ(0, ioctx.remove("foo")); + + sleep(2); + + ASSERT_EQ(0, ioctx.snap_create("snapbar")); + + librados::ObjectWriteOperation *op = new_op(); + cls_refcount_put(*op, "notag", true); + ASSERT_EQ(-ENOENT, ioctx.operate("foo", op)); + + EXPECT_EQ(0, ioctx.snap_remove("snapfoo")); + EXPECT_EQ(0, ioctx.snap_remove("snapbar")); + + delete op; + + /* remove pool */ + ioctx.close(); + ASSERT_EQ(0, destroy_one_ec_pool_pp(pool_name, rados)); +} + +TEST(cls_rgw, test_explicit_ec) /* test refcount using implicit referencing of newly created objects */ +{ + librados::Rados rados; + librados::IoCtx ioctx; + string pool_name = get_temp_pool_name(); + + /* create pool */ + ASSERT_EQ("", create_one_ec_pool_pp(pool_name, rados)); + ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx)); + + /* add chains */ + string oid = "obj"; + + + /* create object */ + + ASSERT_EQ(0, ioctx.create(oid, true)); + + /* read reference, should return a single wildcard entry */ + + list refs; + + ASSERT_EQ(0, cls_refcount_read(ioctx, oid, &refs)); + ASSERT_EQ(0, (int)refs.size()); + + + /* take first reference, verify */ + + string newtag = "newtag"; + + librados::ObjectWriteOperation *op = new_op(); + cls_refcount_get(*op, newtag); + ASSERT_EQ(0, ioctx.operate(oid, op)); + + ASSERT_EQ(0, cls_refcount_read(ioctx, oid, &refs)); + ASSERT_EQ(1, (int)refs.size()); + + map refs_map; + for (list::iterator iter = refs.begin(); iter != refs.end(); ++iter) { + refs_map[*iter] = true; + } + + ASSERT_EQ(1, (int)refs_map.count(newtag)); + + delete op; + + /* try to drop reference to unexisting tag */ + + string nosuchtag = "nosuchtag"; + + op = new_op(); + cls_refcount_put(*op, nosuchtag); + ASSERT_EQ(0, ioctx.operate(oid, op)); + + ASSERT_EQ(0, cls_refcount_read(ioctx, oid, &refs)); + ASSERT_EQ(1, (int)refs.size()); + + string tag = refs.front(); + ASSERT_EQ(newtag, tag); + + delete op; + + /* drop newtag reference, make sure object removed */ + op = new_op(); + cls_refcount_put(*op, newtag); + ASSERT_EQ(0, ioctx.operate(oid, op)); + + ASSERT_EQ(-ENOENT, ioctx.stat(oid, NULL, NULL)); + + delete op; + + /* remove pool */ + ioctx.close(); + ASSERT_EQ(0, destroy_one_ec_pool_pp(pool_name, rados)); +} + +TEST(cls_rgw, set_ec) /* test refcount using implicit referencing of newly created objects */ +{ + librados::Rados rados; + librados::IoCtx ioctx; + string pool_name = get_temp_pool_name(); + + /* create pool */ + ASSERT_EQ("", create_one_ec_pool_pp(pool_name, rados)); + ASSERT_EQ(0, rados.ioctx_create(pool_name.c_str(), ioctx)); + + /* add chains */ + string oid = "obj"; + + + /* create object */ + + ASSERT_EQ(0, ioctx.create(oid, true)); + + /* read reference, should return a single wildcard entry */ + + list tag_refs, refs; + +#define TAGS_NUM 5 + string tags[TAGS_NUM]; + + char buf[16]; + for (int i = 0; i < TAGS_NUM; i++) { + snprintf(buf, sizeof(buf), "tag%d", i); + tags[i] = buf; + tag_refs.push_back(tags[i]); + } + + ASSERT_EQ(0, cls_refcount_read(ioctx, oid, &refs)); + ASSERT_EQ(0, (int)refs.size()); + + /* set reference list, verify */ + + librados::ObjectWriteOperation *op = new_op(); + cls_refcount_set(*op, tag_refs); + ASSERT_EQ(0, ioctx.operate(oid, op)); + + refs.clear(); + ASSERT_EQ(0, cls_refcount_read(ioctx, oid, &refs)); + ASSERT_EQ(TAGS_NUM, (int)refs.size()); + + map refs_map; + for (list::iterator iter = refs.begin(); iter != refs.end(); ++iter) { + refs_map[*iter] = true; + } + + for (int i = 0; i < TAGS_NUM; i++) { + ASSERT_EQ(1, (int)refs_map.count(tags[i])); + } + + delete op; + + /* remove all refs */ + + for (int i = 0; i < TAGS_NUM; i++) { + op = new_op(); + cls_refcount_put(*op, tags[i]); + ASSERT_EQ(0, ioctx.operate(oid, op)); + delete op; + } + + ASSERT_EQ(-ENOENT, ioctx.stat(oid, NULL, NULL)); + + /* remove pool */ + ioctx.close(); + ASSERT_EQ(0, destroy_one_ec_pool_pp(pool_name, rados)); +}