// Copyright (c) 2016-present, Facebook, Inc. All rights reserved. // This source code is licensed under both the GPLv2 (found in the // COPYING file in the root directory) and Apache 2.0 License // (found in the LICENSE.Apache file in the root directory). #ifndef ROCKSDB_LITE #include "rocksdb/utilities/object_registry.h" #include "test_util/testharness.h" namespace ROCKSDB_NAMESPACE { class EnvRegistryTest : public testing::Test { public: static int num_a, num_b; }; int EnvRegistryTest::num_a = 0; int EnvRegistryTest::num_b = 0; static FactoryFunc test_reg_a = ObjectLibrary::Default()->Register( "a://.*", [](const std::string& /*uri*/, std::unique_ptr* /*env_guard*/, std::string* /* errmsg */) { ++EnvRegistryTest::num_a; return Env::Default(); }); static FactoryFunc test_reg_b = ObjectLibrary::Default()->Register( "b://.*", [](const std::string& /*uri*/, std::unique_ptr* env_guard, std::string* /* errmsg */) { ++EnvRegistryTest::num_b; // Env::Default() is a singleton so we can't grant ownership directly to // the caller - we must wrap it first. env_guard->reset(new EnvWrapper(Env::Default())); return env_guard->get(); }); TEST_F(EnvRegistryTest, Basics) { std::string msg; std::unique_ptr env_guard; auto registry = ObjectRegistry::NewInstance(); auto res = registry->NewObject("a://test", &env_guard, &msg); ASSERT_NE(res, nullptr); ASSERT_EQ(env_guard, nullptr); ASSERT_EQ(1, num_a); ASSERT_EQ(0, num_b); res = registry->NewObject("b://test", &env_guard, &msg); ASSERT_NE(res, nullptr); ASSERT_NE(env_guard, nullptr); ASSERT_EQ(1, num_a); ASSERT_EQ(1, num_b); res = registry->NewObject("c://test", &env_guard, &msg); ASSERT_EQ(res, nullptr); ASSERT_EQ(env_guard, nullptr); ASSERT_EQ(1, num_a); ASSERT_EQ(1, num_b); } TEST_F(EnvRegistryTest, LocalRegistry) { std::string msg; std::unique_ptr guard; auto registry = ObjectRegistry::NewInstance(); std::shared_ptr library = std::make_shared(); registry->AddLibrary(library); library->Register( "test-local", [](const std::string& /*uri*/, std::unique_ptr* /*guard */, std::string* /* errmsg */) { return Env::Default(); }); ObjectLibrary::Default()->Register( "test-global", [](const std::string& /*uri*/, std::unique_ptr* /*guard */, std::string* /* errmsg */) { return Env::Default(); }); ASSERT_EQ( ObjectRegistry::NewInstance()->NewObject("test-local", &guard, &msg), nullptr); ASSERT_NE( ObjectRegistry::NewInstance()->NewObject("test-global", &guard, &msg), nullptr); ASSERT_NE(registry->NewObject("test-local", &guard, &msg), nullptr); ASSERT_NE(registry->NewObject("test-global", &guard, &msg), nullptr); } TEST_F(EnvRegistryTest, CheckShared) { std::shared_ptr shared; std::shared_ptr registry = ObjectRegistry::NewInstance(); std::shared_ptr library = std::make_shared(); registry->AddLibrary(library); library->Register( "unguarded", [](const std::string& /*uri*/, std::unique_ptr* /*guard */, std::string* /* errmsg */) { return Env::Default(); }); library->Register( "guarded", [](const std::string& /*uri*/, std::unique_ptr* guard, std::string* /* errmsg */) { guard->reset(new EnvWrapper(Env::Default())); return guard->get(); }); ASSERT_OK(registry->NewSharedObject("guarded", &shared)); ASSERT_NE(shared, nullptr); shared.reset(); ASSERT_NOK(registry->NewSharedObject("unguarded", &shared)); ASSERT_EQ(shared, nullptr); } TEST_F(EnvRegistryTest, CheckStatic) { Env* env = nullptr; std::shared_ptr registry = ObjectRegistry::NewInstance(); std::shared_ptr library = std::make_shared(); registry->AddLibrary(library); library->Register( "unguarded", [](const std::string& /*uri*/, std::unique_ptr* /*guard */, std::string* /* errmsg */) { return Env::Default(); }); library->Register( "guarded", [](const std::string& /*uri*/, std::unique_ptr* guard, std::string* /* errmsg */) { guard->reset(new EnvWrapper(Env::Default())); return guard->get(); }); ASSERT_NOK(registry->NewStaticObject("guarded", &env)); ASSERT_EQ(env, nullptr); env = nullptr; ASSERT_OK(registry->NewStaticObject("unguarded", &env)); ASSERT_NE(env, nullptr); } TEST_F(EnvRegistryTest, CheckUnique) { std::unique_ptr unique; std::shared_ptr registry = ObjectRegistry::NewInstance(); std::shared_ptr library = std::make_shared(); registry->AddLibrary(library); library->Register( "unguarded", [](const std::string& /*uri*/, std::unique_ptr* /*guard */, std::string* /* errmsg */) { return Env::Default(); }); library->Register( "guarded", [](const std::string& /*uri*/, std::unique_ptr* guard, std::string* /* errmsg */) { guard->reset(new EnvWrapper(Env::Default())); return guard->get(); }); ASSERT_OK(registry->NewUniqueObject("guarded", &unique)); ASSERT_NE(unique, nullptr); unique.reset(); ASSERT_NOK(registry->NewUniqueObject("unguarded", &unique)); ASSERT_EQ(unique, nullptr); } } // namespace ROCKSDB_NAMESPACE int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } #else // ROCKSDB_LITE #include int main(int /*argc*/, char** /*argv*/) { fprintf(stderr, "SKIPPED as EnvRegistry is not supported in ROCKSDB_LITE\n"); return 0; } #endif // ROCKSDB_LITE