X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Ftest%2Fos%2FTestLFNIndex.cc;fp=src%2Fceph%2Fsrc%2Ftest%2Fos%2FTestLFNIndex.cc;h=0000000000000000000000000000000000000000;hb=7da45d65be36d36b880cc55c5036e96c24b53f00;hp=77919999117f49e7c3a7d165ff9c3f36f0bb0572;hpb=691462d09d0987b47e112d6ee8740375df3c51b2;p=stor4nfv.git diff --git a/src/ceph/src/test/os/TestLFNIndex.cc b/src/ceph/src/test/os/TestLFNIndex.cc deleted file mode 100644 index 7791999..0000000 --- a/src/ceph/src/test/os/TestLFNIndex.cc +++ /dev/null @@ -1,484 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab -/* - * Ceph - scalable distributed file system - * - * Copyright (C) 2013 Cloudwatt - * - * Author: Loic Dachary - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library Public License for more details. - * - */ - -#include -#include -#include "os/filestore/LFNIndex.h" -#include "os/filestore/chain_xattr.h" -#include "common/ceph_argparse.h" -#include "global/global_init.h" -#include - -class TestWrapLFNIndex : public LFNIndex { -public: - TestWrapLFNIndex(CephContext* cct, - coll_t collection, - const char *base_path, - uint32_t index_version) - : LFNIndex(cct, collection, base_path, index_version) {} - - uint32_t collection_version() override { - return index_version; - } - - int cleanup() override { return 0; } - - int _split( - uint32_t match, - uint32_t bits, - CollectionIndex* dest - ) override { return 0; } - - void test_generate_and_parse(const ghobject_t &hoid, const std::string &mangled_expected) { - const std::string mangled_name = lfn_generate_object_name(hoid); - EXPECT_EQ(mangled_expected, mangled_name); - ghobject_t hoid_parsed; - EXPECT_EQ(0, lfn_parse_object_name(mangled_name, &hoid_parsed)); - EXPECT_EQ(hoid, hoid_parsed); - } - -protected: - int _init() override { return 0; } - - int _created( - const vector &path, - const ghobject_t &hoid, - const string &mangled_name - ) override { return 0; } - - int _remove( - const vector &path, - const ghobject_t &hoid, - const string &mangled_name - ) override { return 0; } - - int _lookup( - const ghobject_t &hoid, - vector *path, - string *mangled_name, - int *exists - ) override { return 0; } - - int _collection_list_partial( - const ghobject_t &start, - const ghobject_t &end, - int max_count, - vector *ls, - ghobject_t *next - ) override { return 0; } - int _pre_hash_collection( - uint32_t pg_num, - uint64_t expected_num_objs - ) override { return 0; } - -}; - -class TestHASH_INDEX_TAG : public TestWrapLFNIndex, public ::testing::Test { -public: - TestHASH_INDEX_TAG() - : TestWrapLFNIndex(g_ceph_context, coll_t(), "PATH_1", - CollectionIndex::HASH_INDEX_TAG) { - } -}; - -TEST_F(TestHASH_INDEX_TAG, generate_and_parse_name) { - const vector path; - const std::string key; - uint64_t hash = 0xABABABAB; - uint64_t pool = -1; - - test_generate_and_parse(ghobject_t(hobject_t(object_t(".A/B_\\C.D"), key, CEPH_NOSNAP, hash, pool, "")), - "\\.A\\sB_\\\\C.D_head_ABABABAB"); - test_generate_and_parse(ghobject_t(hobject_t(object_t("DIR_A"), key, CEPH_NOSNAP, hash, pool, "")), - "\\dA_head_ABABABAB"); -} - -class TestHASH_INDEX_TAG_2 : public TestWrapLFNIndex, public ::testing::Test { -public: - TestHASH_INDEX_TAG_2() - : TestWrapLFNIndex(g_ceph_context, - coll_t(), "PATH_1", CollectionIndex::HASH_INDEX_TAG_2) { - } -}; - -TEST_F(TestHASH_INDEX_TAG_2, generate_and_parse_name) { - const vector path; - const std::string key("KEY"); - uint64_t hash = 0xABABABAB; - uint64_t pool = -1; - - { - std::string name(".XA/B_\\C.D"); - name[1] = '\0'; - ghobject_t hoid(hobject_t(object_t(name), key, CEPH_NOSNAP, hash, pool, "")); - - test_generate_and_parse(hoid, "\\.\\nA\\sB\\u\\\\C.D_KEY_head_ABABABAB"); - } - test_generate_and_parse(ghobject_t(hobject_t(object_t("DIR_A"), key, CEPH_NOSNAP, hash, pool, "")), - "\\dA_KEY_head_ABABABAB"); -} - -class TestHOBJECT_WITH_POOL : public TestWrapLFNIndex, public ::testing::Test { -public: - TestHOBJECT_WITH_POOL() - : TestWrapLFNIndex(g_ceph_context, coll_t(), - "PATH_1", CollectionIndex::HOBJECT_WITH_POOL) { - } -}; - -TEST_F(TestHOBJECT_WITH_POOL, generate_and_parse_name) { - const vector path; - const std::string key("KEY"); - uint64_t hash = 0xABABABAB; - uint64_t pool = 0xCDCDCDCD; - int64_t gen = 0xefefefefef; - shard_id_t shard_id(0xb); - - { - std::string name(".XA/B_\\C.D"); - name[1] = '\0'; - ghobject_t hoid(hobject_t(object_t(name), key, CEPH_NOSNAP, hash, pool, "")); - hoid.hobj.nspace = "NSPACE"; - - test_generate_and_parse(hoid, "\\.\\nA\\sB\\u\\\\C.D_KEY_head_ABABABAB_NSPACE_cdcdcdcd"); - } - { - ghobject_t hoid(hobject_t(object_t("DIR_A"), key, CEPH_NOSNAP, hash, pool, "")); - hoid.hobj.nspace = "NSPACE"; - - test_generate_and_parse(hoid, "\\dA_KEY_head_ABABABAB_NSPACE_cdcdcdcd"); - } - { - std::string name(".XA/B_\\C.D"); - name[1] = '\0'; - ghobject_t hoid(hobject_t(object_t(name), key, CEPH_NOSNAP, hash, pool, ""), gen, shard_id); - hoid.hobj.nspace = "NSPACE"; - - test_generate_and_parse(hoid, "\\.\\nA\\sB\\u\\\\C.D_KEY_head_ABABABAB_NSPACE_cdcdcdcd_efefefefef_b"); - } - { - ghobject_t hoid(hobject_t(object_t("DIR_A"), key, CEPH_NOSNAP, hash, pool, ""), gen, shard_id); - hoid.hobj.nspace = "NSPACE"; - - test_generate_and_parse(hoid, "\\dA_KEY_head_ABABABAB_NSPACE_cdcdcdcd_efefefefef_b"); - } -} - -class TestLFNIndex : public TestWrapLFNIndex, public ::testing::Test { -public: - TestLFNIndex() - : TestWrapLFNIndex(g_ceph_context, coll_t(), "PATH_1", - CollectionIndex::HOBJECT_WITH_POOL) { - } - - void SetUp() override { - ::chmod("PATH_1", 0700); - ASSERT_EQ(0, ::system("rm -fr PATH_1")); - ASSERT_EQ(0, ::mkdir("PATH_1", 0700)); - } - - void TearDown() override { - ASSERT_EQ(0, ::system("rm -fr PATH_1")); - } -}; - -TEST_F(TestLFNIndex, remove_object) { - const vector path; - - // - // small object name removal - // - { - std::string mangled_name; - int exists = 666; - ghobject_t hoid(hobject_t(sobject_t("ABC", CEPH_NOSNAP))); - - EXPECT_EQ(0, ::chmod("PATH_1", 0000)); - if (getuid() != 0) { - EXPECT_EQ(-EACCES, remove_object(path, hoid)); - } - EXPECT_EQ(0, ::chmod("PATH_1", 0700)); - EXPECT_EQ(-ENOENT, remove_object(path, hoid)); - EXPECT_EQ(0, get_mangled_name(path, hoid, &mangled_name, &exists)); - const std::string pathname("PATH_1/" + mangled_name); - EXPECT_EQ(0, ::close(::creat(pathname.c_str(), 0600))); - EXPECT_EQ(0, remove_object(path, hoid)); - EXPECT_EQ(-1, ::access(pathname.c_str(), 0)); - EXPECT_EQ(ENOENT, errno); - } - // - // long object name removal of a single file - // - { - std::string mangled_name; - int exists; - const std::string object_name(1024, 'A'); - ghobject_t hoid(hobject_t(sobject_t(object_name, CEPH_NOSNAP))); - - EXPECT_EQ(0, get_mangled_name(path, hoid, &mangled_name, &exists)); - EXPECT_EQ(0, exists); - EXPECT_NE(std::string::npos, mangled_name.find("0_long")); - std::string pathname("PATH_1/" + mangled_name); - EXPECT_EQ(0, ::close(::creat(pathname.c_str(), 0600))); - EXPECT_EQ(0, created(hoid, pathname.c_str())); - - EXPECT_EQ(0, remove_object(path, hoid)); - EXPECT_EQ(-1, ::access(pathname.c_str(), 0)); - EXPECT_EQ(ENOENT, errno); - } - - // - // long object name removal of the last file - // - { - std::string mangled_name; - int exists; - const std::string object_name(1024, 'A'); - ghobject_t hoid(hobject_t(sobject_t(object_name, CEPH_NOSNAP))); - - // - // PATH_1/AAA..._0_long => does not match long object name - // - EXPECT_EQ(0, get_mangled_name(path, hoid, &mangled_name, &exists)); - EXPECT_EQ(0, exists); - EXPECT_NE(std::string::npos, mangled_name.find("0_long")); - std::string pathname("PATH_1/" + mangled_name); - EXPECT_EQ(0, ::close(::creat(pathname.c_str(), 0600))); - EXPECT_EQ(0, created(hoid, pathname.c_str())); - string LFN_ATTR = "user.cephos.lfn"; - if (index_version != HASH_INDEX_TAG) { - char buf[100]; - snprintf(buf, sizeof(buf), "%d", index_version); - LFN_ATTR += string(buf); - } - const std::string object_name_1 = object_name + "SUFFIX"; - EXPECT_EQ(object_name_1.size(), (unsigned)chain_setxattr(pathname.c_str(), LFN_ATTR.c_str(), object_name_1.c_str(), object_name_1.size())); - - // - // PATH_1/AAA..._1_long => matches long object name - // - std::string mangled_name_1; - exists = 666; - EXPECT_EQ(0, get_mangled_name(path, hoid, &mangled_name_1, &exists)); - EXPECT_NE(std::string::npos, mangled_name_1.find("1_long")); - EXPECT_EQ(0, exists); - std::string pathname_1("PATH_1/" + mangled_name_1); - EXPECT_EQ(0, ::close(::creat(pathname_1.c_str(), 0600))); - EXPECT_EQ(0, created(hoid, pathname_1.c_str())); - - // - // remove_object skips PATH_1/AAA..._0_long and removes PATH_1/AAA..._1_long - // - EXPECT_EQ(0, remove_object(path, hoid)); - EXPECT_EQ(0, ::access(pathname.c_str(), 0)); - EXPECT_EQ(-1, ::access(pathname_1.c_str(), 0)); - EXPECT_EQ(ENOENT, errno); - EXPECT_EQ(0, ::unlink(pathname.c_str())); - } - - // - // long object name removal of a file in the middle of the list - // - { - std::string mangled_name; - int exists; - const std::string object_name(1024, 'A'); - ghobject_t hoid(hobject_t(sobject_t(object_name, CEPH_NOSNAP))); - - // - // PATH_1/AAA..._0_long => matches long object name - // - EXPECT_EQ(0, get_mangled_name(path, hoid, &mangled_name, &exists)); - EXPECT_EQ(0, exists); - EXPECT_NE(std::string::npos, mangled_name.find("0_long")); - std::string pathname("PATH_1/" + mangled_name); - EXPECT_EQ(0, ::close(::creat(pathname.c_str(), 0600))); - EXPECT_EQ(0, created(hoid, pathname.c_str())); - // - // PATH_1/AAA..._1_long => matches long object name - // - std::string mangled_name_1 = mangled_name; - mangled_name_1.replace(mangled_name_1.find("0_long"), 6, "1_long"); - const std::string pathname_1("PATH_1/" + mangled_name_1); - const std::string cmd("cp -a " + pathname + " " + pathname_1); - EXPECT_EQ(0, ::system(cmd.c_str())); - const string ATTR = "user.MARK"; - EXPECT_EQ((unsigned)1, (unsigned)chain_setxattr(pathname_1.c_str(), ATTR.c_str(), "Y", 1)); - - // - // remove_object replaces the file to be removed with the last from the - // collision list. In this case it replaces - // PATH_1/AAA..._0_long - // with - // PATH_1/AAA..._1_long - // - EXPECT_EQ(0, remove_object(path, hoid)); - EXPECT_EQ(0, ::access(pathname.c_str(), 0)); - char buffer[1] = { 0, }; - EXPECT_EQ((unsigned)1, (unsigned)chain_getxattr(pathname.c_str(), ATTR.c_str(), buffer, 1)); - EXPECT_EQ('Y', buffer[0]); - EXPECT_EQ(-1, ::access(pathname_1.c_str(), 0)); - EXPECT_EQ(ENOENT, errno); - } -} - -TEST_F(TestLFNIndex, get_mangled_name) { - const vector path; - - // - // small object name - // - { - std::string mangled_name; - int exists = 666; - ghobject_t hoid(hobject_t(sobject_t("ABC", CEPH_NOSNAP))); - - EXPECT_EQ(0, get_mangled_name(path, hoid, &mangled_name, &exists)); - EXPECT_NE(std::string::npos, mangled_name.find("ABC__head")); - EXPECT_EQ(std::string::npos, mangled_name.find("0_long")); - EXPECT_EQ(0, exists); - const std::string pathname("PATH_1/" + mangled_name); - EXPECT_EQ(0, ::close(::creat(pathname.c_str(), 0600))); - EXPECT_EQ(0, get_mangled_name(path, hoid, &mangled_name, &exists)); - EXPECT_NE(std::string::npos, mangled_name.find("ABC__head")); - EXPECT_EQ(1, exists); - EXPECT_EQ(0, ::unlink(pathname.c_str())); - } - // - // long object name - // - { - std::string mangled_name; - int exists; - const std::string object_name(1024, 'A'); - ghobject_t hoid(hobject_t(sobject_t(object_name, CEPH_NOSNAP))); - - // - // long version of the mangled name and no matching - // file exists - // - mangled_name.clear(); - exists = 666; - EXPECT_EQ(0, get_mangled_name(path, hoid, &mangled_name, &exists)); - EXPECT_NE(std::string::npos, mangled_name.find("0_long")); - EXPECT_EQ(0, exists); - - const std::string pathname("PATH_1/" + mangled_name); - - // - // if a file by the same name exists but does not have the - // expected extended attribute, it is silently removed - // - mangled_name.clear(); - exists = 666; - EXPECT_EQ(0, ::close(::creat(pathname.c_str(), 0600))); - EXPECT_EQ(0, get_mangled_name(path, hoid, &mangled_name, &exists)); - EXPECT_NE(std::string::npos, mangled_name.find("0_long")); - EXPECT_EQ(0, exists); - EXPECT_EQ(-1, ::access(pathname.c_str(), 0)); - EXPECT_EQ(ENOENT, errno); - - // - // if a file by the same name exists but does not have the - // expected extended attribute, and cannot be removed, - // return on error - // - mangled_name.clear(); - exists = 666; - EXPECT_EQ(0, ::close(::creat(pathname.c_str(), 0600))); - EXPECT_EQ(0, ::chmod("PATH_1", 0500)); - if (getuid() != 0) { - EXPECT_EQ(-EACCES, get_mangled_name(path, hoid, &mangled_name, &exists)); - } - EXPECT_EQ("", mangled_name); - EXPECT_EQ(666, exists); - EXPECT_EQ(0, ::chmod("PATH_1", 0700)); - EXPECT_EQ(0, ::unlink(pathname.c_str())); - - // - // long version of the mangled name and a file - // exists by that name and contains the long object name - // - mangled_name.clear(); - exists = 666; - EXPECT_EQ(0, ::close(::creat(pathname.c_str(), 0600))); - EXPECT_EQ(0, created(hoid, pathname.c_str())); - EXPECT_EQ(0, get_mangled_name(path, hoid, &mangled_name, &exists)); - EXPECT_NE(std::string::npos, mangled_name.find("0_long")); - EXPECT_EQ(1, exists); - EXPECT_EQ(0, ::access(pathname.c_str(), 0)); - - // - // long version of the mangled name and a file exists by that name - // and contains a long object name with the same prefix but they - // are not identical and it so happens that their SHA1 is - // identical : a collision number is used to differentiate them - // - string LFN_ATTR = "user.cephos.lfn"; - if (index_version != HASH_INDEX_TAG) { - char buf[100]; - snprintf(buf, sizeof(buf), "%d", index_version); - LFN_ATTR += string(buf); - } - const std::string object_name_same_prefix = object_name + "SUFFIX"; - EXPECT_EQ(object_name_same_prefix.size(), (unsigned)chain_setxattr(pathname.c_str(), LFN_ATTR.c_str(), object_name_same_prefix.c_str(), object_name_same_prefix.size())); - std::string mangled_name_same_prefix; - exists = 666; - EXPECT_EQ(0, get_mangled_name(path, hoid, &mangled_name_same_prefix, &exists)); - EXPECT_NE(std::string::npos, mangled_name_same_prefix.find("1_long")); - EXPECT_EQ(0, exists); - - EXPECT_EQ(0, ::unlink(pathname.c_str())); - } -} - -int main(int argc, char **argv) { - int fd = ::creat("detect", 0600); - if (fd < 0){ - cerr << "failed to create file detect" << std::endl; - return EXIT_FAILURE; - } - int ret = chain_fsetxattr(fd, "user.test", "A", 1); - ::close(fd); - ::unlink("detect"); - if (ret < 0) { - cerr << "SKIP LFNIndex because unable to test for xattr" << std::endl; - } else { - vector args; - argv_to_vec(argc, (const char **)argv, args); - - auto cct = global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, - CODE_ENVIRONMENT_UTILITY, 0); - common_init_finish(g_ceph_context); - - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); - } -} - -/* - * Local Variables: - * compile-command: "cd ../.. ; - * make unittest_lfnindex && - * valgrind --tool=memcheck ./unittest_lfnindex \ - * # --gtest_filter=TestLFNIndex.* --log-to-stderr=true --debug-filestore=20" - * End: - */