object_registry_test.cc 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860
  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. #include "rocksdb/utilities/object_registry.h"
  6. #include "rocksdb/convenience.h"
  7. #include "rocksdb/customizable.h"
  8. #include "test_util/testharness.h"
  9. namespace ROCKSDB_NAMESPACE {
  10. class ObjRegistryTest : public testing::Test {
  11. public:
  12. static int num_a, num_b;
  13. };
  14. int ObjRegistryTest::num_a = 0;
  15. int ObjRegistryTest::num_b = 0;
  16. static FactoryFunc<Env> test_reg_a = ObjectLibrary::Default()->AddFactory<Env>(
  17. ObjectLibrary::PatternEntry("a", false).AddSeparator("://"),
  18. [](const std::string& /*uri*/, std::unique_ptr<Env>* /*env_guard*/,
  19. std::string* /* errmsg */) {
  20. ++ObjRegistryTest::num_a;
  21. return Env::Default();
  22. });
  23. class WrappedEnv : public EnvWrapper {
  24. private:
  25. std::string id_;
  26. public:
  27. WrappedEnv(Env* t, const std::string& id) : EnvWrapper(t), id_(id) {}
  28. const char* Name() const override { return id_.c_str(); }
  29. std::string GetId() const override { return id_; }
  30. };
  31. static FactoryFunc<Env> test_reg_b = ObjectLibrary::Default()->AddFactory<Env>(
  32. ObjectLibrary::PatternEntry("b", false).AddSeparator("://"),
  33. [](const std::string& uri, std::unique_ptr<Env>* env_guard,
  34. std::string* /* errmsg */) {
  35. ++ObjRegistryTest::num_b;
  36. // Env::Default() is a singleton so we can't grant ownership directly to
  37. // the caller - we must wrap it first.
  38. env_guard->reset(new WrappedEnv(Env::Default(), uri));
  39. return env_guard->get();
  40. });
  41. TEST_F(ObjRegistryTest, Basics) {
  42. std::string msg;
  43. std::unique_ptr<Env> guard;
  44. Env* a_env = nullptr;
  45. auto registry = ObjectRegistry::NewInstance();
  46. ASSERT_NOK(registry->NewStaticObject<Env>("c://test", &a_env));
  47. ASSERT_NOK(registry->NewUniqueObject<Env>("c://test", &guard));
  48. ASSERT_EQ(a_env, nullptr);
  49. ASSERT_EQ(guard, nullptr);
  50. ASSERT_EQ(0, num_a);
  51. ASSERT_EQ(0, num_b);
  52. ASSERT_OK(registry->NewStaticObject<Env>("a://test", &a_env));
  53. ASSERT_NE(a_env, nullptr);
  54. ASSERT_EQ(1, num_a);
  55. ASSERT_EQ(0, num_b);
  56. ASSERT_OK(registry->NewUniqueObject<Env>("b://test", &guard));
  57. ASSERT_NE(guard, nullptr);
  58. ASSERT_EQ(1, num_a);
  59. ASSERT_EQ(1, num_b);
  60. Env* b_env = nullptr;
  61. ASSERT_NOK(registry->NewStaticObject<Env>("b://test", &b_env));
  62. ASSERT_EQ(b_env, nullptr);
  63. ASSERT_EQ(1, num_a);
  64. ASSERT_EQ(2, num_b); // Created but rejected as not static
  65. b_env = a_env;
  66. ASSERT_NOK(registry->NewStaticObject<Env>("b://test", &b_env));
  67. ASSERT_EQ(b_env, a_env);
  68. ASSERT_EQ(1, num_a);
  69. ASSERT_EQ(3, num_b);
  70. b_env = guard.get();
  71. ASSERT_NOK(registry->NewUniqueObject<Env>("a://test", &guard));
  72. ASSERT_EQ(guard.get(), b_env); // Unchanged
  73. ASSERT_EQ(2, num_a); // Created one but rejected it as not unique
  74. ASSERT_EQ(3, num_b);
  75. }
  76. TEST_F(ObjRegistryTest, LocalRegistry) {
  77. Env* env = nullptr;
  78. auto registry = ObjectRegistry::NewInstance();
  79. std::shared_ptr<ObjectLibrary> library =
  80. std::make_shared<ObjectLibrary>("local");
  81. registry->AddLibrary(library);
  82. library->AddFactory<Env>(
  83. "test-local",
  84. [](const std::string& /*uri*/, std::unique_ptr<Env>* /*guard */,
  85. std::string* /* errmsg */) { return Env::Default(); });
  86. ObjectLibrary::Default()->AddFactory<Env>(
  87. "test-global",
  88. [](const std::string& /*uri*/, std::unique_ptr<Env>* /*guard */,
  89. std::string* /* errmsg */) { return Env::Default(); });
  90. ASSERT_NOK(
  91. ObjectRegistry::NewInstance()->NewStaticObject<Env>("test-local", &env));
  92. ASSERT_EQ(env, nullptr);
  93. ASSERT_OK(
  94. ObjectRegistry::NewInstance()->NewStaticObject<Env>("test-global", &env));
  95. ASSERT_NE(env, nullptr);
  96. ASSERT_OK(registry->NewStaticObject<Env>("test-local", &env));
  97. ASSERT_NE(env, nullptr);
  98. ASSERT_OK(registry->NewStaticObject<Env>("test-global", &env));
  99. ASSERT_NE(env, nullptr);
  100. }
  101. static int RegisterTestUnguarded(ObjectLibrary& library,
  102. const std::string& /*arg*/) {
  103. library.AddFactory<Env>(
  104. "unguarded",
  105. [](const std::string& /*uri*/, std::unique_ptr<Env>* /*guard */,
  106. std::string* /* errmsg */) { return Env::Default(); });
  107. library.AddFactory<Env>(
  108. "guarded", [](const std::string& uri, std::unique_ptr<Env>* guard,
  109. std::string* /* errmsg */) {
  110. guard->reset(new WrappedEnv(Env::Default(), uri));
  111. return guard->get();
  112. });
  113. return 2;
  114. }
  115. TEST_F(ObjRegistryTest, CheckShared) {
  116. std::shared_ptr<Env> shared;
  117. std::shared_ptr<ObjectRegistry> registry = ObjectRegistry::NewInstance();
  118. registry->AddLibrary("shared", RegisterTestUnguarded, "");
  119. ASSERT_OK(registry->NewSharedObject<Env>("guarded", &shared));
  120. ASSERT_NE(shared, nullptr);
  121. shared.reset();
  122. ASSERT_NOK(registry->NewSharedObject<Env>("unguarded", &shared));
  123. ASSERT_EQ(shared, nullptr);
  124. }
  125. TEST_F(ObjRegistryTest, CheckStatic) {
  126. Env* env = nullptr;
  127. std::shared_ptr<ObjectRegistry> registry = ObjectRegistry::NewInstance();
  128. registry->AddLibrary("static", RegisterTestUnguarded, "");
  129. ASSERT_NOK(registry->NewStaticObject<Env>("guarded", &env));
  130. ASSERT_EQ(env, nullptr);
  131. env = nullptr;
  132. ASSERT_OK(registry->NewStaticObject<Env>("unguarded", &env));
  133. ASSERT_NE(env, nullptr);
  134. }
  135. TEST_F(ObjRegistryTest, CheckUnique) {
  136. std::unique_ptr<Env> unique;
  137. std::shared_ptr<ObjectRegistry> registry = ObjectRegistry::NewInstance();
  138. registry->AddLibrary("unique", RegisterTestUnguarded, "");
  139. ASSERT_OK(registry->NewUniqueObject<Env>("guarded", &unique));
  140. ASSERT_NE(unique, nullptr);
  141. unique.reset();
  142. ASSERT_NOK(registry->NewUniqueObject<Env>("unguarded", &unique));
  143. ASSERT_EQ(unique, nullptr);
  144. }
  145. TEST_F(ObjRegistryTest, FailingFactory) {
  146. std::shared_ptr<ObjectRegistry> registry = ObjectRegistry::NewInstance();
  147. std::shared_ptr<ObjectLibrary> library =
  148. std::make_shared<ObjectLibrary>("failing");
  149. registry->AddLibrary(library);
  150. library->AddFactory<Env>(
  151. "failing", [](const std::string& /*uri*/,
  152. std::unique_ptr<Env>* /*guard */, std::string* errmsg) {
  153. *errmsg = "Bad Factory";
  154. return nullptr;
  155. });
  156. std::unique_ptr<Env> unique;
  157. std::shared_ptr<Env> shared;
  158. Env* pointer = nullptr;
  159. Status s;
  160. s = registry->NewUniqueObject<Env>("failing", &unique);
  161. ASSERT_TRUE(s.IsInvalidArgument());
  162. s = registry->NewSharedObject<Env>("failing", &shared);
  163. ASSERT_TRUE(s.IsInvalidArgument());
  164. s = registry->NewStaticObject<Env>("failing", &pointer);
  165. ASSERT_TRUE(s.IsInvalidArgument());
  166. s = registry->NewUniqueObject<Env>("missing", &unique);
  167. ASSERT_TRUE(s.IsNotSupported());
  168. s = registry->NewSharedObject<Env>("missing", &shared);
  169. ASSERT_TRUE(s.IsNotSupported());
  170. s = registry->NewStaticObject<Env>("missing", &pointer);
  171. ASSERT_TRUE(s.IsNotSupported());
  172. }
  173. TEST_F(ObjRegistryTest, TestRegistryParents) {
  174. auto grand = ObjectRegistry::Default();
  175. auto parent = ObjectRegistry::NewInstance(); // parent with a grandparent
  176. auto uncle = ObjectRegistry::NewInstance(grand);
  177. auto child = ObjectRegistry::NewInstance(parent);
  178. auto cousin = ObjectRegistry::NewInstance(uncle);
  179. auto library = parent->AddLibrary("parent");
  180. library->AddFactory<Env>(
  181. "parent", [](const std::string& uri, std::unique_ptr<Env>* guard,
  182. std::string* /* errmsg */) {
  183. guard->reset(new WrappedEnv(Env::Default(), uri));
  184. return guard->get();
  185. });
  186. library = cousin->AddLibrary("cousin");
  187. library->AddFactory<Env>(
  188. "cousin", [](const std::string& uri, std::unique_ptr<Env>* guard,
  189. std::string* /* errmsg */) {
  190. guard->reset(new WrappedEnv(Env::Default(), uri));
  191. return guard->get();
  192. });
  193. Env* env = nullptr;
  194. std::unique_ptr<Env> guard;
  195. std::string msg;
  196. // a:://* is registered in Default, so they should all work
  197. ASSERT_OK(parent->NewStaticObject<Env>("a://test", &env));
  198. ASSERT_OK(child->NewStaticObject<Env>("a://test", &env));
  199. ASSERT_OK(uncle->NewStaticObject<Env>("a://test", &env));
  200. ASSERT_OK(cousin->NewStaticObject<Env>("a://test", &env));
  201. // The parent env is only registered for parent, not uncle,
  202. // So parent and child should return success and uncle and cousin should fail
  203. ASSERT_OK(parent->NewUniqueObject<Env>("parent", &guard));
  204. ASSERT_OK(child->NewUniqueObject<Env>("parent", &guard));
  205. ASSERT_NOK(uncle->NewUniqueObject<Env>("parent", &guard));
  206. ASSERT_NOK(cousin->NewUniqueObject<Env>("parent", &guard));
  207. // The cousin is only registered in the cousin, so all of the others should
  208. // fail
  209. ASSERT_OK(cousin->NewUniqueObject<Env>("cousin", &guard));
  210. ASSERT_NOK(parent->NewUniqueObject<Env>("cousin", &guard));
  211. ASSERT_NOK(child->NewUniqueObject<Env>("cousin", &guard));
  212. ASSERT_NOK(uncle->NewUniqueObject<Env>("cousin", &guard));
  213. }
  214. class MyCustomizable : public Customizable {
  215. public:
  216. static const char* Type() { return "MyCustomizable"; }
  217. MyCustomizable(const char* prefix, const std::string& id) : id_(id) {
  218. name_ = id_.substr(0, strlen(prefix) - 1);
  219. }
  220. const char* Name() const override { return name_.c_str(); }
  221. std::string GetId() const override { return id_; }
  222. private:
  223. std::string id_;
  224. std::string name_;
  225. };
  226. TEST_F(ObjRegistryTest, TestFactoryCount) {
  227. std::string msg;
  228. auto grand = ObjectRegistry::Default();
  229. auto local = ObjectRegistry::NewInstance();
  230. std::unordered_set<std::string> grand_types, local_types;
  231. std::vector<std::string> grand_names, local_names;
  232. // Check how many types we have on startup.
  233. // Grand should equal local
  234. grand->GetFactoryTypes(&grand_types);
  235. local->GetFactoryTypes(&local_types);
  236. ASSERT_EQ(grand_types, local_types);
  237. size_t grand_count = grand->GetFactoryCount(Env::Type());
  238. size_t local_count = local->GetFactoryCount(Env::Type());
  239. ASSERT_EQ(grand_count, local_count);
  240. grand->GetFactoryNames(Env::Type(), &grand_names);
  241. local->GetFactoryNames(Env::Type(), &local_names);
  242. ASSERT_EQ(grand_names.size(), grand_count);
  243. ASSERT_EQ(local_names.size(), local_count);
  244. ASSERT_EQ(grand_names, local_names);
  245. // Add an Env to the local registry.
  246. // This will add one factory.
  247. auto library = local->AddLibrary("local");
  248. library->AddFactory<Env>(
  249. "A", [](const std::string& /*uri*/, std::unique_ptr<Env>* /*guard */,
  250. std::string* /* errmsg */) { return nullptr; });
  251. ASSERT_EQ(local_count + 1, local->GetFactoryCount(Env::Type()));
  252. ASSERT_EQ(grand_count, grand->GetFactoryCount(Env::Type()));
  253. local->GetFactoryTypes(&local_types);
  254. local->GetFactoryNames(Env::Type(), &local_names);
  255. ASSERT_EQ(grand_names.size() + 1, local_names.size());
  256. ASSERT_EQ(local_names.size(), local->GetFactoryCount(Env::Type()));
  257. if (grand_count == 0) {
  258. // There were no Env when we started. Should have one more type
  259. // than previously
  260. ASSERT_NE(grand_types, local_types);
  261. ASSERT_EQ(grand_types.size() + 1, local_types.size());
  262. } else {
  263. // There was an Env type when we started. The types should match
  264. ASSERT_EQ(grand_types, local_types);
  265. }
  266. // Add a MyCustomizable to the registry. This should be a new type
  267. library->AddFactory<MyCustomizable>(
  268. "MY", [](const std::string& /*uri*/,
  269. std::unique_ptr<MyCustomizable>* /*guard */,
  270. std::string* /* errmsg */) { return nullptr; });
  271. ASSERT_EQ(local_count + 1, local->GetFactoryCount(Env::Type()));
  272. ASSERT_EQ(grand_count, grand->GetFactoryCount(Env::Type()));
  273. ASSERT_EQ(0U, grand->GetFactoryCount(MyCustomizable::Type()));
  274. ASSERT_EQ(1U, local->GetFactoryCount(MyCustomizable::Type()));
  275. local->GetFactoryNames(MyCustomizable::Type(), &local_names);
  276. ASSERT_EQ(1U, local_names.size());
  277. ASSERT_EQ(local_names[0], "MY");
  278. local->GetFactoryTypes(&local_types);
  279. ASSERT_EQ(grand_count == 0 ? 2 : grand_types.size() + 1, local_types.size());
  280. // Add the same name again. We should now have 2 factories.
  281. library->AddFactory<MyCustomizable>(
  282. "MY", [](const std::string& /*uri*/,
  283. std::unique_ptr<MyCustomizable>* /*guard */,
  284. std::string* /* errmsg */) { return nullptr; });
  285. local->GetFactoryNames(MyCustomizable::Type(), &local_names);
  286. ASSERT_EQ(2U, local_names.size());
  287. }
  288. TEST_F(ObjRegistryTest, TestManagedObjects) {
  289. auto registry = ObjectRegistry::NewInstance();
  290. auto m_a1 = std::make_shared<MyCustomizable>("", "A");
  291. auto m_a2 = std::make_shared<MyCustomizable>("", "A");
  292. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("A"), nullptr);
  293. ASSERT_OK(registry->SetManagedObject<MyCustomizable>(m_a1));
  294. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("A"), m_a1);
  295. ASSERT_NOK(registry->SetManagedObject<MyCustomizable>(m_a2));
  296. ASSERT_OK(registry->SetManagedObject<MyCustomizable>(m_a1));
  297. m_a1.reset();
  298. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("A"), nullptr);
  299. ASSERT_OK(registry->SetManagedObject<MyCustomizable>(m_a2));
  300. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("A"), m_a2);
  301. }
  302. TEST_F(ObjRegistryTest, TestTwoManagedObjects) {
  303. auto registry = ObjectRegistry::NewInstance();
  304. auto m_a = std::make_shared<MyCustomizable>("", "A");
  305. auto m_b = std::make_shared<MyCustomizable>("", "B");
  306. std::vector<std::shared_ptr<MyCustomizable>> objects;
  307. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("A"), nullptr);
  308. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("B"), nullptr);
  309. ASSERT_OK(registry->ListManagedObjects(&objects));
  310. ASSERT_EQ(objects.size(), 0U);
  311. ASSERT_OK(registry->SetManagedObject(m_a));
  312. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("B"), nullptr);
  313. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("A"), m_a);
  314. ASSERT_OK(registry->ListManagedObjects(&objects));
  315. ASSERT_EQ(objects.size(), 1U);
  316. ASSERT_EQ(objects.front(), m_a);
  317. ASSERT_OK(registry->SetManagedObject(m_b));
  318. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("A"), m_a);
  319. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("B"), m_b);
  320. ASSERT_OK(registry->ListManagedObjects(&objects));
  321. ASSERT_EQ(objects.size(), 2U);
  322. ASSERT_OK(registry->ListManagedObjects("A", &objects));
  323. ASSERT_EQ(objects.size(), 1U);
  324. ASSERT_EQ(objects.front(), m_a);
  325. ASSERT_OK(registry->ListManagedObjects("B", &objects));
  326. ASSERT_EQ(objects.size(), 1U);
  327. ASSERT_EQ(objects.front(), m_b);
  328. ASSERT_OK(registry->ListManagedObjects("C", &objects));
  329. ASSERT_EQ(objects.size(), 0U);
  330. m_a.reset();
  331. objects.clear();
  332. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("B"), m_b);
  333. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("A"), nullptr);
  334. ASSERT_OK(registry->ListManagedObjects(&objects));
  335. ASSERT_EQ(objects.size(), 1U);
  336. ASSERT_EQ(objects.front(), m_b);
  337. m_b.reset();
  338. objects.clear();
  339. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("A"), nullptr);
  340. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("B"), nullptr);
  341. }
  342. TEST_F(ObjRegistryTest, TestAlternateNames) {
  343. auto registry = ObjectRegistry::NewInstance();
  344. auto m_a = std::make_shared<MyCustomizable>("", "A");
  345. auto m_b = std::make_shared<MyCustomizable>("", "B");
  346. std::vector<std::shared_ptr<MyCustomizable>> objects;
  347. // Test no objects exist
  348. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("A"), nullptr);
  349. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("B"), nullptr);
  350. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("TheOne"), nullptr);
  351. ASSERT_OK(registry->ListManagedObjects(&objects));
  352. ASSERT_EQ(objects.size(), 0U);
  353. // Mark "TheOne" to be A
  354. ASSERT_OK(registry->SetManagedObject("TheOne", m_a));
  355. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("B"), nullptr);
  356. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("A"), nullptr);
  357. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("TheOne"), m_a);
  358. ASSERT_OK(registry->ListManagedObjects(&objects));
  359. ASSERT_EQ(objects.size(), 1U);
  360. ASSERT_EQ(objects.front(), m_a);
  361. // Try to mark "TheOne" again.
  362. ASSERT_NOK(registry->SetManagedObject("TheOne", m_b));
  363. ASSERT_OK(registry->SetManagedObject("TheOne", m_a));
  364. // Add "A" as a managed object. Registered 2x
  365. ASSERT_OK(registry->SetManagedObject(m_a));
  366. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("B"), nullptr);
  367. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("A"), m_a);
  368. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("TheOne"), m_a);
  369. ASSERT_OK(registry->ListManagedObjects(&objects));
  370. ASSERT_EQ(objects.size(), 2U);
  371. // Delete "A".
  372. m_a.reset();
  373. objects.clear();
  374. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("TheOne"), nullptr);
  375. ASSERT_OK(registry->SetManagedObject("TheOne", m_b));
  376. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("TheOne"), m_b);
  377. ASSERT_OK(registry->ListManagedObjects(&objects));
  378. ASSERT_EQ(objects.size(), 1U);
  379. ASSERT_EQ(objects.front(), m_b);
  380. m_b.reset();
  381. objects.clear();
  382. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("A"), nullptr);
  383. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("A"), nullptr);
  384. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("TheOne"), nullptr);
  385. ASSERT_OK(registry->ListManagedObjects(&objects));
  386. ASSERT_EQ(objects.size(), 0U);
  387. }
  388. TEST_F(ObjRegistryTest, TestTwoManagedClasses) {
  389. class MyCustomizable2 : public MyCustomizable {
  390. public:
  391. static const char* Type() { return "MyCustomizable2"; }
  392. MyCustomizable2(const char* prefix, const std::string& id)
  393. : MyCustomizable(prefix, id) {}
  394. };
  395. auto registry = ObjectRegistry::NewInstance();
  396. auto m_a1 = std::make_shared<MyCustomizable>("", "A");
  397. auto m_a2 = std::make_shared<MyCustomizable2>("", "A");
  398. std::vector<std::shared_ptr<MyCustomizable>> obj1s;
  399. std::vector<std::shared_ptr<MyCustomizable2>> obj2s;
  400. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("A"), nullptr);
  401. ASSERT_EQ(registry->GetManagedObject<MyCustomizable2>("A"), nullptr);
  402. ASSERT_OK(registry->SetManagedObject(m_a1));
  403. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("A"), m_a1);
  404. ASSERT_EQ(registry->GetManagedObject<MyCustomizable2>("A"), nullptr);
  405. ASSERT_OK(registry->SetManagedObject(m_a2));
  406. ASSERT_EQ(registry->GetManagedObject<MyCustomizable2>("A"), m_a2);
  407. ASSERT_OK(registry->ListManagedObjects(&obj1s));
  408. ASSERT_OK(registry->ListManagedObjects(&obj2s));
  409. ASSERT_EQ(obj1s.size(), 1U);
  410. ASSERT_EQ(obj2s.size(), 1U);
  411. ASSERT_EQ(obj1s.front(), m_a1);
  412. ASSERT_EQ(obj2s.front(), m_a2);
  413. m_a1.reset();
  414. obj1s.clear();
  415. obj2s.clear();
  416. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("A"), nullptr);
  417. ASSERT_EQ(registry->GetManagedObject<MyCustomizable2>("A"), m_a2);
  418. m_a2.reset();
  419. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("A"), nullptr);
  420. ASSERT_EQ(registry->GetManagedObject<MyCustomizable2>("A"), nullptr);
  421. }
  422. TEST_F(ObjRegistryTest, TestManagedObjectsWithParent) {
  423. auto base = ObjectRegistry::NewInstance();
  424. auto registry = ObjectRegistry::NewInstance(base);
  425. auto m_a = std::make_shared<MyCustomizable>("", "A");
  426. auto m_b = std::make_shared<MyCustomizable>("", "A");
  427. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("A"), nullptr);
  428. ASSERT_OK(base->SetManagedObject(m_a));
  429. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("A"), m_a);
  430. ASSERT_NOK(registry->SetManagedObject(m_b));
  431. ASSERT_OK(registry->SetManagedObject(m_a));
  432. m_a.reset();
  433. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("A"), nullptr);
  434. ASSERT_OK(registry->SetManagedObject(m_b));
  435. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("A"), m_b);
  436. }
  437. TEST_F(ObjRegistryTest, TestGetOrCreateManagedObject) {
  438. auto registry = ObjectRegistry::NewInstance();
  439. registry->AddLibrary("test")->AddFactory<MyCustomizable>(
  440. ObjectLibrary::PatternEntry::AsIndividualId("MC"),
  441. [](const std::string& uri, std::unique_ptr<MyCustomizable>* guard,
  442. std::string* /* errmsg */) {
  443. guard->reset(new MyCustomizable("MC", uri));
  444. return guard->get();
  445. });
  446. std::shared_ptr<MyCustomizable> m_a, m_b, obj;
  447. std::vector<std::shared_ptr<MyCustomizable>> objs;
  448. std::unordered_map<std::string, std::string> opt_map;
  449. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("MC@A#1"), nullptr);
  450. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("MC@B#1"), nullptr);
  451. ASSERT_OK(registry->GetOrCreateManagedObject("MC@A#1", &m_a));
  452. ASSERT_OK(registry->GetOrCreateManagedObject("MC@B#1", &m_b));
  453. ASSERT_EQ(registry->GetManagedObject<MyCustomizable>("MC@A#1"), m_a);
  454. ASSERT_OK(registry->GetOrCreateManagedObject("MC@A#1", &obj));
  455. ASSERT_EQ(obj, m_a);
  456. ASSERT_OK(registry->GetOrCreateManagedObject("MC@B#1", &obj));
  457. ASSERT_EQ(obj, m_b);
  458. ASSERT_OK(registry->ListManagedObjects(&objs));
  459. ASSERT_EQ(objs.size(), 2U);
  460. objs.clear();
  461. m_a.reset();
  462. obj.reset();
  463. ASSERT_OK(registry->GetOrCreateManagedObject("MC@A#1", &m_a));
  464. ASSERT_EQ(1, m_a.use_count());
  465. ASSERT_OK(registry->GetOrCreateManagedObject("MC@B#1", &obj));
  466. ASSERT_EQ(2, obj.use_count());
  467. }
  468. TEST_F(ObjRegistryTest, RegisterPlugin) {
  469. std::shared_ptr<ObjectRegistry> registry = ObjectRegistry::NewInstance();
  470. std::unique_ptr<Env> guard;
  471. Env* env = nullptr;
  472. ASSERT_NOK(registry->NewObject<Env>("unguarded", &env, &guard));
  473. ASSERT_EQ(registry->RegisterPlugin("Missing", nullptr), -1);
  474. ASSERT_EQ(registry->RegisterPlugin("", RegisterTestUnguarded), -1);
  475. ASSERT_GT(registry->RegisterPlugin("Valid", RegisterTestUnguarded), 0);
  476. ASSERT_OK(registry->NewObject<Env>("unguarded", &env, &guard));
  477. ASSERT_NE(env, nullptr);
  478. }
  479. class PatternEntryTest : public testing::Test {};
  480. TEST_F(PatternEntryTest, TestSimpleEntry) {
  481. ObjectLibrary::PatternEntry entry("ABC", true);
  482. ASSERT_TRUE(entry.Matches("ABC"));
  483. ASSERT_FALSE(entry.Matches("AABC"));
  484. ASSERT_FALSE(entry.Matches("ABCA"));
  485. ASSERT_FALSE(entry.Matches("AABCA"));
  486. ASSERT_FALSE(entry.Matches("AB"));
  487. ASSERT_FALSE(entry.Matches("BC"));
  488. ASSERT_FALSE(entry.Matches("ABD"));
  489. ASSERT_FALSE(entry.Matches("BCA"));
  490. }
  491. TEST_F(PatternEntryTest, TestPatternEntry) {
  492. // Matches A:+
  493. ObjectLibrary::PatternEntry entry("A", false);
  494. entry.AddSeparator(":");
  495. ASSERT_FALSE(entry.Matches("A"));
  496. ASSERT_FALSE(entry.Matches("AA"));
  497. ASSERT_FALSE(entry.Matches("AB"));
  498. ASSERT_FALSE(entry.Matches("B"));
  499. ASSERT_FALSE(entry.Matches("A:"));
  500. ASSERT_FALSE(entry.Matches("AA:"));
  501. ASSERT_FALSE(entry.Matches("AA:B"));
  502. ASSERT_FALSE(entry.Matches("AA:BB"));
  503. ASSERT_TRUE(entry.Matches("A:B"));
  504. ASSERT_TRUE(entry.Matches("A:BB"));
  505. entry.SetOptional(true); // Now matches "A" or "A:+"
  506. ASSERT_TRUE(entry.Matches("A"));
  507. ASSERT_FALSE(entry.Matches("AA"));
  508. ASSERT_FALSE(entry.Matches("AB"));
  509. ASSERT_FALSE(entry.Matches("B"));
  510. ASSERT_FALSE(entry.Matches("A:"));
  511. ASSERT_FALSE(entry.Matches("AA:"));
  512. ASSERT_FALSE(entry.Matches("AA:B"));
  513. ASSERT_FALSE(entry.Matches("AA:BB"));
  514. ASSERT_TRUE(entry.Matches("A:B"));
  515. ASSERT_TRUE(entry.Matches("A:BB"));
  516. }
  517. TEST_F(PatternEntryTest, MatchZeroOrMore) {
  518. // Matches A:*
  519. ObjectLibrary::PatternEntry entry("A", false);
  520. entry.AddSeparator(":", false);
  521. ASSERT_FALSE(entry.Matches("A"));
  522. ASSERT_FALSE(entry.Matches("AA"));
  523. ASSERT_FALSE(entry.Matches("AB"));
  524. ASSERT_FALSE(entry.Matches("B"));
  525. ASSERT_TRUE(entry.Matches("A:"));
  526. ASSERT_FALSE(entry.Matches("B:"));
  527. ASSERT_FALSE(entry.Matches("B:A"));
  528. ASSERT_FALSE(entry.Matches("AA:"));
  529. ASSERT_FALSE(entry.Matches("AA:B"));
  530. ASSERT_FALSE(entry.Matches("AA:BB"));
  531. ASSERT_TRUE(entry.Matches("A:B"));
  532. ASSERT_TRUE(entry.Matches("A:BB"));
  533. entry.SetOptional(true); // Now matches "A" or "A:*"
  534. ASSERT_TRUE(entry.Matches("A"));
  535. ASSERT_FALSE(entry.Matches("AA"));
  536. ASSERT_FALSE(entry.Matches("AB"));
  537. ASSERT_FALSE(entry.Matches("B"));
  538. ASSERT_TRUE(entry.Matches("A:"));
  539. ASSERT_FALSE(entry.Matches("B:"));
  540. ASSERT_FALSE(entry.Matches("B:A"));
  541. ASSERT_FALSE(entry.Matches("AA:"));
  542. ASSERT_FALSE(entry.Matches("AA:B"));
  543. ASSERT_FALSE(entry.Matches("AA:BB"));
  544. ASSERT_TRUE(entry.Matches("A:B"));
  545. ASSERT_TRUE(entry.Matches("A:BB"));
  546. }
  547. TEST_F(PatternEntryTest, TestSuffixEntry) {
  548. ObjectLibrary::PatternEntry entry("AA", true);
  549. entry.AddSuffix("BB");
  550. ASSERT_TRUE(entry.Matches("AA"));
  551. ASSERT_TRUE(entry.Matches("AABB"));
  552. ASSERT_FALSE(entry.Matches("A"));
  553. ASSERT_FALSE(entry.Matches("AB"));
  554. ASSERT_FALSE(entry.Matches("B"));
  555. ASSERT_FALSE(entry.Matches("BB"));
  556. ASSERT_FALSE(entry.Matches("ABA"));
  557. ASSERT_FALSE(entry.Matches("BBAA"));
  558. ASSERT_FALSE(entry.Matches("AABBA"));
  559. ASSERT_FALSE(entry.Matches("AABBB"));
  560. }
  561. TEST_F(PatternEntryTest, TestNumericEntry) {
  562. ObjectLibrary::PatternEntry entry("A", false);
  563. entry.AddNumber(":");
  564. ASSERT_FALSE(entry.Matches("A"));
  565. ASSERT_FALSE(entry.Matches("AA"));
  566. ASSERT_FALSE(entry.Matches("A:"));
  567. ASSERT_FALSE(entry.Matches("AA:"));
  568. ASSERT_TRUE(entry.Matches("A:1"));
  569. ASSERT_TRUE(entry.Matches("A:11"));
  570. ASSERT_FALSE(entry.Matches("AA:1"));
  571. ASSERT_FALSE(entry.Matches("AA:11"));
  572. ASSERT_FALSE(entry.Matches("A:B"));
  573. ASSERT_FALSE(entry.Matches("A:1B"));
  574. ASSERT_FALSE(entry.Matches("A:B1"));
  575. entry.AddSeparator(":", false);
  576. ASSERT_FALSE(entry.Matches("A"));
  577. ASSERT_FALSE(entry.Matches("AA"));
  578. ASSERT_FALSE(entry.Matches("A:"));
  579. ASSERT_FALSE(entry.Matches("AA:"));
  580. ASSERT_TRUE(entry.Matches("A:1:"));
  581. ASSERT_TRUE(entry.Matches("A:11:"));
  582. ASSERT_FALSE(entry.Matches("A:1"));
  583. ASSERT_FALSE(entry.Matches("A:B1:"));
  584. ASSERT_FALSE(entry.Matches("A:1B:"));
  585. ASSERT_FALSE(entry.Matches("A::"));
  586. }
  587. TEST_F(PatternEntryTest, TestDoubleEntry) {
  588. ObjectLibrary::PatternEntry entry("A", false);
  589. entry.AddNumber(":", false);
  590. ASSERT_FALSE(entry.Matches("A"));
  591. ASSERT_FALSE(entry.Matches("AA"));
  592. ASSERT_FALSE(entry.Matches("A:"));
  593. ASSERT_FALSE(entry.Matches("AA:"));
  594. ASSERT_FALSE(entry.Matches("AA:1"));
  595. ASSERT_FALSE(entry.Matches("AA:11"));
  596. ASSERT_FALSE(entry.Matches("A:B"));
  597. ASSERT_FALSE(entry.Matches("A:1B"));
  598. ASSERT_FALSE(entry.Matches("A:B1"));
  599. ASSERT_TRUE(entry.Matches("A:1"));
  600. ASSERT_TRUE(entry.Matches("A:11"));
  601. ASSERT_TRUE(entry.Matches("A:1.1"));
  602. ASSERT_TRUE(entry.Matches("A:11.11"));
  603. ASSERT_TRUE(entry.Matches("A:1."));
  604. ASSERT_TRUE(entry.Matches("A:.1"));
  605. ASSERT_TRUE(entry.Matches("A:0.1"));
  606. ASSERT_TRUE(entry.Matches("A:1.0"));
  607. ASSERT_TRUE(entry.Matches("A:1.0"));
  608. ASSERT_FALSE(entry.Matches("A:1.0."));
  609. ASSERT_FALSE(entry.Matches("A:1.0.2"));
  610. ASSERT_FALSE(entry.Matches("A:.1.0"));
  611. ASSERT_FALSE(entry.Matches("A:..10"));
  612. ASSERT_FALSE(entry.Matches("A:10.."));
  613. ASSERT_FALSE(entry.Matches("A:."));
  614. entry.AddSeparator(":", false);
  615. ASSERT_FALSE(entry.Matches("A:1"));
  616. ASSERT_FALSE(entry.Matches("A:1.0"));
  617. ASSERT_TRUE(entry.Matches("A:11:"));
  618. ASSERT_TRUE(entry.Matches("A:1.1:"));
  619. ASSERT_TRUE(entry.Matches("A:11.11:"));
  620. ASSERT_TRUE(entry.Matches("A:1.:"));
  621. ASSERT_TRUE(entry.Matches("A:.1:"));
  622. ASSERT_TRUE(entry.Matches("A:0.1:"));
  623. ASSERT_TRUE(entry.Matches("A:1.0:"));
  624. ASSERT_TRUE(entry.Matches("A:1.0:"));
  625. ASSERT_FALSE(entry.Matches("A:1.0.:"));
  626. ASSERT_FALSE(entry.Matches("A:1.0.2:"));
  627. ASSERT_FALSE(entry.Matches("A:.1.0:"));
  628. ASSERT_FALSE(entry.Matches("A:..10:"));
  629. ASSERT_FALSE(entry.Matches("A:10..:"));
  630. ASSERT_FALSE(entry.Matches("A:.:"));
  631. ASSERT_FALSE(entry.Matches("A::"));
  632. }
  633. TEST_F(PatternEntryTest, TestIndividualIdEntry) {
  634. auto entry = ObjectLibrary::PatternEntry::AsIndividualId("AA");
  635. ASSERT_TRUE(entry.Matches("AA"));
  636. ASSERT_TRUE(entry.Matches("AA@123#456"));
  637. ASSERT_TRUE(entry.Matches("AA@deadbeef#id"));
  638. ASSERT_FALSE(entry.Matches("A"));
  639. ASSERT_FALSE(entry.Matches("AAA"));
  640. ASSERT_FALSE(entry.Matches("AA@123"));
  641. ASSERT_FALSE(entry.Matches("AA@123#"));
  642. ASSERT_FALSE(entry.Matches("AA@#123"));
  643. }
  644. TEST_F(PatternEntryTest, TestTwoNameEntry) {
  645. ObjectLibrary::PatternEntry entry("A");
  646. entry.AnotherName("B");
  647. ASSERT_TRUE(entry.Matches("A"));
  648. ASSERT_TRUE(entry.Matches("B"));
  649. ASSERT_FALSE(entry.Matches("AA"));
  650. ASSERT_FALSE(entry.Matches("BB"));
  651. ASSERT_FALSE(entry.Matches("AA"));
  652. ASSERT_FALSE(entry.Matches("BA"));
  653. ASSERT_FALSE(entry.Matches("AB"));
  654. }
  655. TEST_F(PatternEntryTest, TestTwoPatternEntry) {
  656. ObjectLibrary::PatternEntry entry("AA", false);
  657. entry.AddSeparator(":");
  658. entry.AddSeparator(":");
  659. ASSERT_FALSE(entry.Matches("AA"));
  660. ASSERT_FALSE(entry.Matches("AA:"));
  661. ASSERT_FALSE(entry.Matches("AA::"));
  662. ASSERT_FALSE(entry.Matches("AA::12"));
  663. ASSERT_TRUE(entry.Matches("AA:1:2"));
  664. ASSERT_TRUE(entry.Matches("AA:1:2:"));
  665. ObjectLibrary::PatternEntry entry2("AA", false);
  666. entry2.AddSeparator("::");
  667. entry2.AddSeparator("##");
  668. ASSERT_FALSE(entry2.Matches("AA"));
  669. ASSERT_FALSE(entry2.Matches("AA:"));
  670. ASSERT_FALSE(entry2.Matches("AA::"));
  671. ASSERT_FALSE(entry2.Matches("AA::#"));
  672. ASSERT_FALSE(entry2.Matches("AA::##"));
  673. ASSERT_FALSE(entry2.Matches("AA##1::2"));
  674. ASSERT_FALSE(entry2.Matches("AA::123##"));
  675. ASSERT_TRUE(entry2.Matches("AA::1##2"));
  676. ASSERT_TRUE(entry2.Matches("AA::12##34:"));
  677. ASSERT_TRUE(entry2.Matches("AA::12::34##56"));
  678. ASSERT_TRUE(entry2.Matches("AA::12##34::56"));
  679. }
  680. TEST_F(PatternEntryTest, TestTwoNumbersEntry) {
  681. ObjectLibrary::PatternEntry entry("AA", false);
  682. entry.AddNumber(":");
  683. entry.AddNumber(":");
  684. ASSERT_FALSE(entry.Matches("AA"));
  685. ASSERT_FALSE(entry.Matches("AA:"));
  686. ASSERT_FALSE(entry.Matches("AA::"));
  687. ASSERT_FALSE(entry.Matches("AA::12"));
  688. ASSERT_FALSE(entry.Matches("AA:1:2:"));
  689. ASSERT_TRUE(entry.Matches("AA:1:2"));
  690. ASSERT_TRUE(entry.Matches("AA:12:23456"));
  691. ObjectLibrary::PatternEntry entry2("AA", false);
  692. entry2.AddNumber(":");
  693. entry2.AddNumber("#");
  694. ASSERT_FALSE(entry2.Matches("AA"));
  695. ASSERT_FALSE(entry2.Matches("AA:"));
  696. ASSERT_FALSE(entry2.Matches("AA:#"));
  697. ASSERT_FALSE(entry2.Matches("AA#:"));
  698. ASSERT_FALSE(entry2.Matches("AA:123#"));
  699. ASSERT_FALSE(entry2.Matches("AA:123#B"));
  700. ASSERT_FALSE(entry2.Matches("AA:B#123"));
  701. ASSERT_TRUE(entry2.Matches("AA:1#2"));
  702. ASSERT_FALSE(entry2.Matches("AA:123#23:"));
  703. ASSERT_FALSE(entry2.Matches("AA::12#234"));
  704. }
  705. TEST_F(PatternEntryTest, TestPatternAndSuffix) {
  706. ObjectLibrary::PatternEntry entry("AA", false);
  707. entry.AddSeparator("::");
  708. entry.AddSuffix("##");
  709. ASSERT_FALSE(entry.Matches("AA"));
  710. ASSERT_FALSE(entry.Matches("AA::"));
  711. ASSERT_FALSE(entry.Matches("AA::##"));
  712. ASSERT_FALSE(entry.Matches("AB::1##"));
  713. ASSERT_FALSE(entry.Matches("AB::1##2"));
  714. ASSERT_FALSE(entry.Matches("AA##1::"));
  715. ASSERT_TRUE(entry.Matches("AA::1##"));
  716. ASSERT_FALSE(entry.Matches("AA::1###"));
  717. ObjectLibrary::PatternEntry entry2("AA", false);
  718. entry2.AddSuffix("::");
  719. entry2.AddSeparator("##");
  720. ASSERT_FALSE(entry2.Matches("AA"));
  721. ASSERT_FALSE(entry2.Matches("AA::"));
  722. ASSERT_FALSE(entry2.Matches("AA::##"));
  723. ASSERT_FALSE(entry2.Matches("AB::1##"));
  724. ASSERT_FALSE(entry2.Matches("AB::1##2"));
  725. ASSERT_TRUE(entry2.Matches("AA::##12"));
  726. }
  727. TEST_F(PatternEntryTest, TestTwoNamesAndPattern) {
  728. ObjectLibrary::PatternEntry entry("AA", true);
  729. entry.AddSeparator("::");
  730. entry.AnotherName("BBB");
  731. ASSERT_TRUE(entry.Matches("AA"));
  732. ASSERT_TRUE(entry.Matches("AA::1"));
  733. ASSERT_TRUE(entry.Matches("BBB"));
  734. ASSERT_TRUE(entry.Matches("BBB::2"));
  735. ASSERT_FALSE(entry.Matches("AA::"));
  736. ASSERT_FALSE(entry.Matches("AAA::"));
  737. ASSERT_FALSE(entry.Matches("BBB::"));
  738. entry.SetOptional(false);
  739. ASSERT_FALSE(entry.Matches("AA"));
  740. ASSERT_FALSE(entry.Matches("BBB"));
  741. ASSERT_FALSE(entry.Matches("AA::"));
  742. ASSERT_FALSE(entry.Matches("AAA::"));
  743. ASSERT_FALSE(entry.Matches("BBB::"));
  744. ASSERT_TRUE(entry.Matches("AA::1"));
  745. ASSERT_TRUE(entry.Matches("BBB::2"));
  746. }
  747. } // namespace ROCKSDB_NAMESPACE
  748. int main(int argc, char** argv) {
  749. ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
  750. ::testing::InitGoogleTest(&argc, argv);
  751. return RUN_ALL_TESTS();
  752. }