From 972f0eb0acec9dfdc677cc1478cf86da7c51e6ab Mon Sep 17 00:00:00 2001 From: Loic Dachary Date: Thu, 28 Mar 2013 13:38:09 +0100 Subject: [PATCH] unit test LFNIndex::remove_object and LFNIndex::lfn_unlink When the object name is short, check that the corresponding file is ::unlink()ed. When the object name is long, there may be multiple files with the same name, modulo the anti-collision number showing just before the FILENAME_COOKIE. The following scenarii are tested: * there only is one file * there are multiple files and the last one is removed * there are multiple files and the last one is moved in place of the file that is to be removed lfn_unlink and remove_object are tested together because lfn_unlink is a private function and remove_object is a protected function that does very little beside calling lfn_unlink http://tracker.ceph.com/issues/4560 refs #4560 Signed-off-by: Loic Dachary --- src/test/os/TestLFNIndex.cc | 135 +++++++++++++++++++++++++++++++++++- 1 file changed, 134 insertions(+), 1 deletion(-) diff --git a/src/test/os/TestLFNIndex.cc b/src/test/os/TestLFNIndex.cc index e92baadf4a4d8..864c88c03b524 100644 --- a/src/test/os/TestLFNIndex.cc +++ b/src/test/os/TestLFNIndex.cc @@ -97,6 +97,139 @@ public: } }; +TEST_F(TestLFNIndex, remove_object) { + const vector path; + + // + // small object name removal + // + { + std::string mangled_name; + int exists = 666; + hobject_t hoid(sobject_t("ABC", CEPH_NOSNAP)); + + EXPECT_EQ(0, ::chmod("PATH", 0000)); + EXPECT_EQ(-EACCES, remove_object(path, hoid)); + EXPECT_EQ(0, ::chmod("PATH", 0700)); + EXPECT_EQ(-ENOENT, remove_object(path, hoid)); + EXPECT_EQ(0, get_mangled_name(path, hoid, &mangled_name, &exists)); + const std::string pathname("PATH/" + 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'); + hobject_t hoid(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/" + 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'); + hobject_t hoid(sobject_t(object_name, CEPH_NOSNAP)); + + // + // PATH/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/" + mangled_name); + EXPECT_EQ(0, ::close(::creat(pathname.c_str(), 0600))); + EXPECT_EQ(0, created(hoid, pathname.c_str())); + const string LFN_ATTR = "user.cephos.lfn"; + 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/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/" + 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/AAA..._0_long and removes PATH/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'); + hobject_t hoid(sobject_t(object_name, CEPH_NOSNAP)); + + // + // PATH/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/" + mangled_name); + EXPECT_EQ(0, ::close(::creat(pathname.c_str(), 0600))); + EXPECT_EQ(0, created(hoid, pathname.c_str())); + // + // PATH/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/" + mangled_name_1); + const std::string cmd("cp --preserve=xattr " + 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/AAA..._0_long + // with + // PATH/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; @@ -243,5 +376,5 @@ int main(int argc, char **argv) { } // Local Variables: -// compile-command: "cd ../.. ; make unittest_lfnindex ; ./unittest_lfnindex # --gtest_filter=LFNIndexTest.LFNIndex --log-to-stderr=true --debug-filestore=20" +// compile-command: "cd ../.. ; make unittest_lfnindex ; ./unittest_lfnindex # --gtest_filter=TestLFNIndex.* --log-to-stderr=true --debug-filestore=20" // End: -- 2.39.5