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  }