github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/c-deps/libroach/file_registry_test.cc (about) 1 // Copyright 2018 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 #include <vector> 12 #include "file_registry.h" 13 #include "fmt.h" 14 #include "testutils.h" 15 16 using namespace cockroach; 17 18 TEST(FileRegistry, TransformPath) { 19 struct TestCase { 20 std::string db_dir; 21 std::string input; 22 std::string output; 23 }; 24 25 // The db_dir as sanitized does not have a trailing slash. 26 std::vector<TestCase> test_cases = { 27 {"/", "/foo", "foo"}, 28 {"/rocksdir", "/rocksdirfoo", "/rocksdirfoo"}, 29 {"/rocksdir", "/rocksdir/foo", "foo"}, 30 // We get the occasional double-slash. 31 {"/rocksdir", "/rocksdir//foo", "foo"}, 32 {"/mydir", "/mydir", ""}, 33 {"/mydir", "/mydir/", ""}, 34 {"/mydir", "/mydir//", ""}, 35 {"/mnt/otherdevice/", "/mnt/otherdevice/myfile", "myfile"}, 36 {"/mnt/otherdevice/myfile", "/mnt/otherdevice/myfile", ""}, 37 }; 38 39 std::unique_ptr<rocksdb::Env> env(rocksdb::NewMemEnv(rocksdb::Env::Default())); 40 int test_num = 0; 41 for (auto t : test_cases) { 42 SCOPED_TRACE(fmt::StringPrintf("Testing #%d", test_num++)); 43 44 FileRegistry reg(env.get(), t.db_dir, false /* read-only */); 45 auto out = reg.TransformPath(t.input); 46 EXPECT_EQ(t.output, out); 47 } 48 } 49 50 TEST(FileRegistry, RelativePaths) { 51 std::unique_ptr<rocksdb::Env> env(rocksdb::NewMemEnv(rocksdb::Env::Default())); 52 53 FileRegistry reg(env.get(), "/base", false); 54 ASSERT_OK(reg.Load()); 55 56 // Create a few file entries. 57 std::vector<std::string> files = { 58 "/base/foo", 59 "/base/dir1/bar", 60 "/base/dir1/dir2/baz", 61 }; 62 for (auto f : files) { 63 auto entry = std::unique_ptr<enginepb::FileEntry>(new enginepb::FileEntry()); 64 EXPECT_OK(reg.SetFileEntry(f, std::move(entry))); 65 EXPECT_NE(nullptr, reg.GetFileEntry(f)); 66 } 67 68 struct TestCase { 69 std::string path; 70 bool relative; 71 bool found; 72 }; 73 74 std::vector<TestCase> test_cases = { 75 // Full paths. 76 {"/base/foo", false, true}, 77 {"/base/dir1/bar", false, true}, 78 {"/base/dir1/dir2/baz", false, true}, 79 // Relative paths with separator. 80 {"/foo", true, true}, 81 {"/dir1/bar", true, true}, 82 {"/dir1/dir2/baz", true, true}, 83 // Relative paths without separator. 84 {"foo", true, true}, 85 {"dir1/bar", true, true}, 86 {"dir1/dir2/baz", true, true}, 87 // We don't sanitize paths, so a few things break: 88 {"../base/foo", true, false}, // .. 89 {"/dir1//bar", true, false}, // multiple separators 90 }; 91 92 int test_num = 0; 93 for (auto t : test_cases) { 94 SCOPED_TRACE(fmt::StringPrintf("Testing #%d", test_num++)); 95 bool found = (reg.GetFileEntry(t.path, t.relative) != nullptr); 96 EXPECT_EQ(t.found, found); 97 } 98 } 99 100 TEST(FileRegistry, FileOps) { 101 std::unique_ptr<rocksdb::Env> env(rocksdb::NewMemEnv(rocksdb::Env::Default())); 102 103 FileRegistry rw_reg(env.get(), "/", false /* read-only */); 104 ASSERT_OK(rw_reg.CheckNoRegistryFile()); 105 ASSERT_OK(rw_reg.Load()); 106 107 EXPECT_EQ(nullptr, rw_reg.GetFileEntry("/foo")); 108 auto entry = std::unique_ptr<enginepb::FileEntry>(new enginepb::FileEntry()); 109 EXPECT_OK(rw_reg.SetFileEntry("/foo", std::move(entry))); 110 EXPECT_NE(nullptr, rw_reg.GetFileEntry("/foo")); 111 112 EXPECT_OK(rw_reg.MaybeLinkEntry("/foo", "/bar")); 113 EXPECT_NE(nullptr, rw_reg.GetFileEntry("/foo")); 114 EXPECT_NE(nullptr, rw_reg.GetFileEntry("/bar")); 115 116 EXPECT_OK(rw_reg.MaybeRenameEntry("/bar", "/baz")); 117 EXPECT_NE(nullptr, rw_reg.GetFileEntry("/foo")); 118 EXPECT_EQ(nullptr, rw_reg.GetFileEntry("/bar")); 119 EXPECT_NE(nullptr, rw_reg.GetFileEntry("/baz")); 120 121 EXPECT_OK(rw_reg.MaybeDeleteEntry("/baz")); 122 EXPECT_NE(nullptr, rw_reg.GetFileEntry("/foo")); 123 EXPECT_EQ(nullptr, rw_reg.GetFileEntry("/bar")); 124 EXPECT_EQ(nullptr, rw_reg.GetFileEntry("/baz")); 125 126 // Now try with a read-only registry. 127 FileRegistry ro_reg(env.get(), "/", true /* read-only */); 128 // We have a registry file. 129 EXPECT_ERR(ro_reg.CheckNoRegistryFile(), "registry file .* exists"); 130 ASSERT_OK(ro_reg.Load()); 131 132 EXPECT_NE(nullptr, ro_reg.GetFileEntry("/foo")); 133 EXPECT_EQ(nullptr, ro_reg.GetFileEntry("/bar")); 134 EXPECT_EQ(nullptr, ro_reg.GetFileEntry("/baz")); 135 136 // All mutable operations fail. 137 EXPECT_ERR(ro_reg.MaybeLinkEntry("/foo", "/bar"), "file registry is read-only .*"); 138 EXPECT_ERR(ro_reg.MaybeRenameEntry("/foo", "/baz"), "file registry is read-only .*"); 139 EXPECT_ERR(ro_reg.MaybeDeleteEntry("/foo"), "file registry is read-only .*"); 140 }