1 // Copyright (c) 2016-present, Facebook, Inc.  All rights reserved.
2 //  This source code is licensed under both the GPLv2 (found in the
3 //  COPYING file in the root directory) and Apache 2.0 License
4 //  (found in the LICENSE.Apache file in the root directory).
5 
6 #ifndef ROCKSDB_LITE
7 
8 #include "rocksdb/utilities/object_registry.h"
9 #include "test_util/testharness.h"
10 
11 namespace rocksdb {
12 
13 class EnvRegistryTest : public testing::Test {
14  public:
15   static int num_a, num_b;
16 };
17 
18 int EnvRegistryTest::num_a = 0;
19 int EnvRegistryTest::num_b = 0;
20 static FactoryFunc<Env> test_reg_a = ObjectLibrary::Default()->Register<Env>(
21     "a://.*",
22     [](const std::string& /*uri*/, std::unique_ptr<Env>* /*env_guard*/,
__anon7ba270970102(const std::string& , std::unique_ptr<Env>* , std::string* ) 23        std::string* /* errmsg */) {
24       ++EnvRegistryTest::num_a;
25       return Env::Default();
26     });
27 
28 static FactoryFunc<Env> test_reg_b = ObjectLibrary::Default()->Register<Env>(
29     "b://.*", [](const std::string& /*uri*/, std::unique_ptr<Env>* env_guard,
__anon7ba270970202(const std::string& , std::unique_ptr<Env>* env_guard, std::string* ) 30                  std::string* /* errmsg */) {
31       ++EnvRegistryTest::num_b;
32       // Env::Default() is a singleton so we can't grant ownership directly to
33       // the caller - we must wrap it first.
34       env_guard->reset(new EnvWrapper(Env::Default()));
35       return env_guard->get();
36     });
37 
TEST_F(EnvRegistryTest,Basics)38 TEST_F(EnvRegistryTest, Basics) {
39   std::string msg;
40   std::unique_ptr<Env> env_guard;
41   auto registry = ObjectRegistry::NewInstance();
42   auto res = registry->NewObject<Env>("a://test", &env_guard, &msg);
43   ASSERT_NE(res, nullptr);
44   ASSERT_EQ(env_guard, nullptr);
45   ASSERT_EQ(1, num_a);
46   ASSERT_EQ(0, num_b);
47 
48   res = registry->NewObject<Env>("b://test", &env_guard, &msg);
49   ASSERT_NE(res, nullptr);
50   ASSERT_NE(env_guard, nullptr);
51   ASSERT_EQ(1, num_a);
52   ASSERT_EQ(1, num_b);
53 
54   res = registry->NewObject<Env>("c://test", &env_guard, &msg);
55   ASSERT_EQ(res, nullptr);
56   ASSERT_EQ(env_guard, nullptr);
57   ASSERT_EQ(1, num_a);
58   ASSERT_EQ(1, num_b);
59 }
60 
TEST_F(EnvRegistryTest,LocalRegistry)61 TEST_F(EnvRegistryTest, LocalRegistry) {
62   std::string msg;
63   std::unique_ptr<Env> guard;
64   auto registry = ObjectRegistry::NewInstance();
65   std::shared_ptr<ObjectLibrary> library = std::make_shared<ObjectLibrary>();
66   registry->AddLibrary(library);
67   library->Register<Env>(
68       "test-local",
69       [](const std::string& /*uri*/, std::unique_ptr<Env>* /*guard */,
70          std::string* /* errmsg */) { return Env::Default(); });
71 
72   ObjectLibrary::Default()->Register<Env>(
73       "test-global",
74       [](const std::string& /*uri*/, std::unique_ptr<Env>* /*guard */,
75          std::string* /* errmsg */) { return Env::Default(); });
76 
77   ASSERT_EQ(
78       ObjectRegistry::NewInstance()->NewObject<Env>("test-local", &guard, &msg),
79       nullptr);
80   ASSERT_NE(
81       ObjectRegistry::NewInstance()->NewObject("test-global", &guard, &msg),
82       nullptr);
83   ASSERT_NE(registry->NewObject<Env>("test-local", &guard, &msg), nullptr);
84   ASSERT_NE(registry->NewObject<Env>("test-global", &guard, &msg), nullptr);
85 }
86 
TEST_F(EnvRegistryTest,CheckShared)87 TEST_F(EnvRegistryTest, CheckShared) {
88   std::shared_ptr<Env> shared;
89   std::shared_ptr<ObjectRegistry> registry = ObjectRegistry::NewInstance();
90   std::shared_ptr<ObjectLibrary> library = std::make_shared<ObjectLibrary>();
91   registry->AddLibrary(library);
92   library->Register<Env>(
93       "unguarded",
94       [](const std::string& /*uri*/, std::unique_ptr<Env>* /*guard */,
95          std::string* /* errmsg */) { return Env::Default(); });
96 
97   library->Register<Env>(
98       "guarded", [](const std::string& /*uri*/, std::unique_ptr<Env>* guard,
99                     std::string* /* errmsg */) {
100         guard->reset(new EnvWrapper(Env::Default()));
101         return guard->get();
102       });
103 
104   ASSERT_OK(registry->NewSharedObject<Env>("guarded", &shared));
105   ASSERT_NE(shared, nullptr);
106   shared.reset();
107   ASSERT_NOK(registry->NewSharedObject<Env>("unguarded", &shared));
108   ASSERT_EQ(shared, nullptr);
109 }
110 
TEST_F(EnvRegistryTest,CheckStatic)111 TEST_F(EnvRegistryTest, CheckStatic) {
112   Env* env = nullptr;
113   std::shared_ptr<ObjectRegistry> registry = ObjectRegistry::NewInstance();
114   std::shared_ptr<ObjectLibrary> library = std::make_shared<ObjectLibrary>();
115   registry->AddLibrary(library);
116   library->Register<Env>(
117       "unguarded",
118       [](const std::string& /*uri*/, std::unique_ptr<Env>* /*guard */,
119          std::string* /* errmsg */) { return Env::Default(); });
120 
121   library->Register<Env>(
122       "guarded", [](const std::string& /*uri*/, std::unique_ptr<Env>* guard,
123                     std::string* /* errmsg */) {
124         guard->reset(new EnvWrapper(Env::Default()));
125         return guard->get();
126       });
127 
128   ASSERT_NOK(registry->NewStaticObject<Env>("guarded", &env));
129   ASSERT_EQ(env, nullptr);
130   env = nullptr;
131   ASSERT_OK(registry->NewStaticObject<Env>("unguarded", &env));
132   ASSERT_NE(env, nullptr);
133 }
134 
TEST_F(EnvRegistryTest,CheckUnique)135 TEST_F(EnvRegistryTest, CheckUnique) {
136   std::unique_ptr<Env> unique;
137   std::shared_ptr<ObjectRegistry> registry = ObjectRegistry::NewInstance();
138   std::shared_ptr<ObjectLibrary> library = std::make_shared<ObjectLibrary>();
139   registry->AddLibrary(library);
140   library->Register<Env>(
141       "unguarded",
142       [](const std::string& /*uri*/, std::unique_ptr<Env>* /*guard */,
143          std::string* /* errmsg */) { return Env::Default(); });
144 
145   library->Register<Env>(
146       "guarded", [](const std::string& /*uri*/, std::unique_ptr<Env>* guard,
147                     std::string* /* errmsg */) {
148         guard->reset(new EnvWrapper(Env::Default()));
149         return guard->get();
150       });
151 
152   ASSERT_OK(registry->NewUniqueObject<Env>("guarded", &unique));
153   ASSERT_NE(unique, nullptr);
154   unique.reset();
155   ASSERT_NOK(registry->NewUniqueObject<Env>("unguarded", &unique));
156   ASSERT_EQ(unique, nullptr);
157 }
158 
159 }  // namespace rocksdb
160 
main(int argc,char ** argv)161 int main(int argc, char** argv) {
162   ::testing::InitGoogleTest(&argc, argv);
163   return RUN_ALL_TESTS();
164 }
165 
166 #else  // ROCKSDB_LITE
167 #include <stdio.h>
168 
main(int,char **)169 int main(int /*argc*/, char** /*argv*/) {
170   fprintf(stderr, "SKIPPED as EnvRegistry is not supported in ROCKSDB_LITE\n");
171   return 0;
172 }
173 
174 #endif  // ROCKSDB_LITE
175