customizable_test.cc 80 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146
  1. // Copyright (c) 2011-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. // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
  7. // Use of this source code is governed by a BSD-style license that can be
  8. // found in the LICENSE file. See the AUTHORS file for names of contributors.
  9. #include "rocksdb/customizable.h"
  10. #include <cctype>
  11. #include <cinttypes>
  12. #include <cstring>
  13. #include <unordered_map>
  14. #include <unordered_set>
  15. #include "db/db_test_util.h"
  16. #include "memory/jemalloc_nodump_allocator.h"
  17. #include "memory/memkind_kmem_allocator.h"
  18. #include "options/options_helper.h"
  19. #include "options/options_parser.h"
  20. #include "port/stack_trace.h"
  21. #include "rocksdb/convenience.h"
  22. #include "rocksdb/env_encryption.h"
  23. #include "rocksdb/file_checksum.h"
  24. #include "rocksdb/filter_policy.h"
  25. #include "rocksdb/flush_block_policy.h"
  26. #include "rocksdb/memory_allocator.h"
  27. #include "rocksdb/secondary_cache.h"
  28. #include "rocksdb/slice_transform.h"
  29. #include "rocksdb/sst_partitioner.h"
  30. #include "rocksdb/statistics.h"
  31. #include "rocksdb/utilities/customizable_util.h"
  32. #include "rocksdb/utilities/object_registry.h"
  33. #include "rocksdb/utilities/options_type.h"
  34. #include "table/block_based/filter_policy_internal.h"
  35. #include "table/block_based/flush_block_policy_impl.h"
  36. #include "table/mock_table.h"
  37. #include "test_util/mock_time_env.h"
  38. #include "test_util/testharness.h"
  39. #include "test_util/testutil.h"
  40. #include "util/file_checksum_helper.h"
  41. #include "util/string_util.h"
  42. #include "utilities/compaction_filters/remove_emptyvalue_compactionfilter.h"
  43. #include "utilities/memory_allocators.h"
  44. #include "utilities/merge_operators/bytesxor.h"
  45. #include "utilities/merge_operators/sortlist.h"
  46. #include "utilities/merge_operators/string_append/stringappend.h"
  47. #include "utilities/merge_operators/string_append/stringappend2.h"
  48. #ifndef GFLAGS
  49. bool FLAGS_enable_print = false;
  50. #else
  51. #include "util/gflags_compat.h"
  52. using GFLAGS_NAMESPACE::ParseCommandLineFlags;
  53. DEFINE_bool(enable_print, false, "Print options generated to console.");
  54. #endif // GFLAGS
  55. namespace ROCKSDB_NAMESPACE {
  56. namespace {
  57. class StringLogger : public Logger {
  58. public:
  59. using Logger::Logv;
  60. void Logv(const char* format, va_list ap) override {
  61. char buffer[1000];
  62. vsnprintf(buffer, sizeof(buffer), format, ap);
  63. string_.append(buffer);
  64. }
  65. const std::string& str() const { return string_; }
  66. void clear() { string_.clear(); }
  67. private:
  68. std::string string_;
  69. };
  70. class TestCustomizable : public Customizable {
  71. public:
  72. TestCustomizable(const std::string& name) : name_(name) {}
  73. // Method to allow CheckedCast to work for this class
  74. static const char* kClassName() { return "TestCustomizable"; }
  75. const char* Name() const override { return name_.c_str(); }
  76. static const char* Type() { return "test.custom"; }
  77. static Status CreateFromString(const ConfigOptions& opts,
  78. const std::string& value,
  79. std::unique_ptr<TestCustomizable>* result);
  80. static Status CreateFromString(const ConfigOptions& opts,
  81. const std::string& value,
  82. std::shared_ptr<TestCustomizable>* result);
  83. static Status CreateFromString(const ConfigOptions& opts,
  84. const std::string& value,
  85. TestCustomizable** result);
  86. bool IsInstanceOf(const std::string& name) const override {
  87. if (name == kClassName()) {
  88. return true;
  89. } else {
  90. return Customizable::IsInstanceOf(name);
  91. }
  92. }
  93. protected:
  94. const std::string name_;
  95. };
  96. struct AOptions {
  97. static const char* kName() { return "A"; }
  98. int i = 0;
  99. bool b = false;
  100. };
  101. static std::unordered_map<std::string, OptionTypeInfo> a_option_info = {
  102. {"int",
  103. {offsetof(struct AOptions, i), OptionType::kInt,
  104. OptionVerificationType::kNormal, OptionTypeFlags::kMutable}},
  105. {"bool",
  106. {offsetof(struct AOptions, b), OptionType::kBoolean,
  107. OptionVerificationType::kNormal, OptionTypeFlags::kNone}},
  108. };
  109. class ACustomizable : public TestCustomizable {
  110. public:
  111. explicit ACustomizable(const std::string& id)
  112. : TestCustomizable("A"), id_(id) {
  113. RegisterOptions(&opts_, &a_option_info);
  114. }
  115. std::string GetId() const override { return id_; }
  116. static const char* kClassName() { return "A"; }
  117. private:
  118. AOptions opts_;
  119. const std::string id_;
  120. };
  121. struct BOptions {
  122. std::string s;
  123. bool b = false;
  124. };
  125. static std::unordered_map<std::string, OptionTypeInfo> b_option_info = {
  126. {"string",
  127. {offsetof(struct BOptions, s), OptionType::kString,
  128. OptionVerificationType::kNormal, OptionTypeFlags::kNone}},
  129. {"bool",
  130. {offsetof(struct BOptions, b), OptionType::kBoolean,
  131. OptionVerificationType::kNormal, OptionTypeFlags::kNone}},
  132. };
  133. class BCustomizable : public TestCustomizable {
  134. private:
  135. public:
  136. explicit BCustomizable(const std::string& name) : TestCustomizable(name) {
  137. RegisterOptions(name, &opts_, &b_option_info);
  138. }
  139. static const char* kClassName() { return "B"; }
  140. private:
  141. BOptions opts_;
  142. };
  143. static int A_count = 0;
  144. static int RegisterCustomTestObjects(ObjectLibrary& library,
  145. const std::string& /*arg*/) {
  146. library.AddFactory<TestCustomizable>(
  147. ObjectLibrary::PatternEntry("A", true).AddSeparator("_"),
  148. [](const std::string& name, std::unique_ptr<TestCustomizable>* guard,
  149. std::string* /* msg */) {
  150. guard->reset(new ACustomizable(name));
  151. A_count++;
  152. return guard->get();
  153. });
  154. library.AddFactory<TestCustomizable>(
  155. "B", [](const std::string& name, std::unique_ptr<TestCustomizable>* guard,
  156. std::string* /* msg */) {
  157. guard->reset(new BCustomizable(name));
  158. return guard->get();
  159. });
  160. library.AddFactory<TestCustomizable>(
  161. "S", [](const std::string& name,
  162. std::unique_ptr<TestCustomizable>* /* guard */,
  163. std::string* /* msg */) { return new BCustomizable(name); });
  164. size_t num_types;
  165. return static_cast<int>(library.GetFactoryCount(&num_types));
  166. }
  167. struct SimpleOptions {
  168. static const char* kName() { return "simple"; }
  169. bool b = true;
  170. std::unique_ptr<TestCustomizable> cu;
  171. std::shared_ptr<TestCustomizable> cs;
  172. TestCustomizable* cp = nullptr;
  173. };
  174. static std::unordered_map<std::string, OptionTypeInfo> simple_option_info = {
  175. {"bool",
  176. {offsetof(struct SimpleOptions, b), OptionType::kBoolean,
  177. OptionVerificationType::kNormal, OptionTypeFlags::kNone}},
  178. {"unique",
  179. OptionTypeInfo::AsCustomUniquePtr<TestCustomizable>(
  180. offsetof(struct SimpleOptions, cu), OptionVerificationType::kNormal,
  181. OptionTypeFlags::kAllowNull)},
  182. {"shared",
  183. OptionTypeInfo::AsCustomSharedPtr<TestCustomizable>(
  184. offsetof(struct SimpleOptions, cs), OptionVerificationType::kNormal,
  185. OptionTypeFlags::kAllowNull)},
  186. {"pointer",
  187. OptionTypeInfo::AsCustomRawPtr<TestCustomizable>(
  188. offsetof(struct SimpleOptions, cp), OptionVerificationType::kNormal,
  189. OptionTypeFlags::kAllowNull)},
  190. };
  191. class SimpleConfigurable : public Configurable {
  192. private:
  193. SimpleOptions simple_;
  194. public:
  195. SimpleConfigurable() { RegisterOptions(&simple_, &simple_option_info); }
  196. explicit SimpleConfigurable(
  197. const std::unordered_map<std::string, OptionTypeInfo>* map) {
  198. RegisterOptions(&simple_, map);
  199. }
  200. };
  201. static void GetMapFromProperties(
  202. const std::string& props,
  203. std::unordered_map<std::string, std::string>* map) {
  204. std::istringstream iss(props);
  205. std::unordered_map<std::string, std::string> copy_map;
  206. std::string line;
  207. map->clear();
  208. for (int line_num = 0; std::getline(iss, line); line_num++) {
  209. std::string name;
  210. std::string value;
  211. ASSERT_OK(
  212. RocksDBOptionsParser::ParseStatement(&name, &value, line, line_num));
  213. (*map)[name] = value;
  214. }
  215. }
  216. } // namespace
  217. Status TestCustomizable::CreateFromString(
  218. const ConfigOptions& config_options, const std::string& value,
  219. std::shared_ptr<TestCustomizable>* result) {
  220. return LoadSharedObject<TestCustomizable>(config_options, value, result);
  221. }
  222. Status TestCustomizable::CreateFromString(
  223. const ConfigOptions& config_options, const std::string& value,
  224. std::unique_ptr<TestCustomizable>* result) {
  225. return LoadUniqueObject<TestCustomizable>(config_options, value, result);
  226. }
  227. Status TestCustomizable::CreateFromString(const ConfigOptions& config_options,
  228. const std::string& value,
  229. TestCustomizable** result) {
  230. return LoadStaticObject<TestCustomizable>(config_options, value, result);
  231. }
  232. class CustomizableTest : public testing::Test {
  233. public:
  234. CustomizableTest() {
  235. config_options_.invoke_prepare_options = false;
  236. config_options_.registry->AddLibrary("CustomizableTest",
  237. RegisterCustomTestObjects, "");
  238. }
  239. ConfigOptions config_options_;
  240. };
  241. // Tests that a Customizable can be created by:
  242. // - a simple name
  243. // - a XXX.id option
  244. // - a property with a name
  245. TEST_F(CustomizableTest, CreateByNameTest) {
  246. ObjectLibrary::Default()->AddFactory<TestCustomizable>(
  247. ObjectLibrary::PatternEntry("TEST", false).AddSeparator("_"),
  248. [](const std::string& name, std::unique_ptr<TestCustomizable>* guard,
  249. std::string* /* msg */) {
  250. guard->reset(new TestCustomizable(name));
  251. return guard->get();
  252. });
  253. std::unique_ptr<Configurable> configurable(new SimpleConfigurable());
  254. SimpleOptions* simple = configurable->GetOptions<SimpleOptions>();
  255. ASSERT_NE(simple, nullptr);
  256. ASSERT_OK(
  257. configurable->ConfigureFromString(config_options_, "unique={id=TEST_1}"));
  258. ASSERT_NE(simple->cu, nullptr);
  259. ASSERT_EQ(simple->cu->GetId(), "TEST_1");
  260. ASSERT_OK(
  261. configurable->ConfigureFromString(config_options_, "unique.id=TEST_2"));
  262. ASSERT_NE(simple->cu, nullptr);
  263. ASSERT_EQ(simple->cu->GetId(), "TEST_2");
  264. ASSERT_OK(
  265. configurable->ConfigureFromString(config_options_, "unique=TEST_3"));
  266. ASSERT_NE(simple->cu, nullptr);
  267. ASSERT_EQ(simple->cu->GetId(), "TEST_3");
  268. }
  269. TEST_F(CustomizableTest, ToStringTest) {
  270. std::unique_ptr<TestCustomizable> custom(new TestCustomizable("test"));
  271. ASSERT_EQ(custom->ToString(config_options_), "test");
  272. }
  273. TEST_F(CustomizableTest, SimpleConfigureTest) {
  274. std::unordered_map<std::string, std::string> opt_map = {
  275. {"unique", "id=A;int=1;bool=true"},
  276. {"shared", "id=B;string=s"},
  277. };
  278. std::unique_ptr<Configurable> configurable(new SimpleConfigurable());
  279. ASSERT_OK(configurable->ConfigureFromMap(config_options_, opt_map));
  280. SimpleOptions* simple = configurable->GetOptions<SimpleOptions>();
  281. ASSERT_NE(simple, nullptr);
  282. ASSERT_NE(simple->cu, nullptr);
  283. ASSERT_EQ(simple->cu->GetId(), "A");
  284. std::string opt_str;
  285. std::string mismatch;
  286. ASSERT_OK(configurable->GetOptionString(config_options_, &opt_str));
  287. std::unique_ptr<Configurable> copy(new SimpleConfigurable());
  288. ASSERT_OK(copy->ConfigureFromString(config_options_, opt_str));
  289. ASSERT_TRUE(
  290. configurable->AreEquivalent(config_options_, copy.get(), &mismatch));
  291. }
  292. TEST_F(CustomizableTest, ConfigureFromPropsTest) {
  293. std::unordered_map<std::string, std::string> opt_map = {
  294. {"unique.id", "A"}, {"unique.A.int", "1"}, {"unique.A.bool", "true"},
  295. {"shared.id", "B"}, {"shared.B.string", "s"},
  296. };
  297. std::unique_ptr<Configurable> configurable(new SimpleConfigurable());
  298. ASSERT_OK(configurable->ConfigureFromMap(config_options_, opt_map));
  299. SimpleOptions* simple = configurable->GetOptions<SimpleOptions>();
  300. ASSERT_NE(simple, nullptr);
  301. ASSERT_NE(simple->cu, nullptr);
  302. ASSERT_EQ(simple->cu->GetId(), "A");
  303. std::string opt_str;
  304. std::string mismatch;
  305. config_options_.delimiter = "\n";
  306. std::unordered_map<std::string, std::string> props;
  307. ASSERT_OK(configurable->GetOptionString(config_options_, &opt_str));
  308. GetMapFromProperties(opt_str, &props);
  309. std::unique_ptr<Configurable> copy(new SimpleConfigurable());
  310. ASSERT_OK(copy->ConfigureFromMap(config_options_, props));
  311. ASSERT_TRUE(
  312. configurable->AreEquivalent(config_options_, copy.get(), &mismatch));
  313. }
  314. TEST_F(CustomizableTest, ConfigureFromShortTest) {
  315. std::unordered_map<std::string, std::string> opt_map = {
  316. {"unique.id", "A"}, {"unique.A.int", "1"}, {"unique.A.bool", "true"},
  317. {"shared.id", "B"}, {"shared.B.string", "s"},
  318. };
  319. std::unique_ptr<Configurable> configurable(new SimpleConfigurable());
  320. ASSERT_OK(configurable->ConfigureFromMap(config_options_, opt_map));
  321. SimpleOptions* simple = configurable->GetOptions<SimpleOptions>();
  322. ASSERT_NE(simple, nullptr);
  323. ASSERT_NE(simple->cu, nullptr);
  324. ASSERT_EQ(simple->cu->GetId(), "A");
  325. }
  326. TEST_F(CustomizableTest, AreEquivalentOptionsTest) {
  327. std::unordered_map<std::string, std::string> opt_map = {
  328. {"unique", "id=A;int=1;bool=true"},
  329. {"shared", "id=A;int=1;bool=true"},
  330. };
  331. std::string mismatch;
  332. ConfigOptions config_options = config_options_;
  333. std::unique_ptr<Configurable> c1(new SimpleConfigurable());
  334. std::unique_ptr<Configurable> c2(new SimpleConfigurable());
  335. ASSERT_OK(c1->ConfigureFromMap(config_options, opt_map));
  336. ASSERT_OK(c2->ConfigureFromMap(config_options, opt_map));
  337. ASSERT_TRUE(c1->AreEquivalent(config_options, c2.get(), &mismatch));
  338. SimpleOptions* simple = c1->GetOptions<SimpleOptions>();
  339. ASSERT_TRUE(
  340. simple->cu->AreEquivalent(config_options, simple->cs.get(), &mismatch));
  341. ASSERT_OK(simple->cu->ConfigureOption(config_options, "int", "2"));
  342. ASSERT_FALSE(
  343. simple->cu->AreEquivalent(config_options, simple->cs.get(), &mismatch));
  344. ASSERT_FALSE(c1->AreEquivalent(config_options, c2.get(), &mismatch));
  345. ConfigOptions loosely = config_options;
  346. loosely.sanity_level = ConfigOptions::kSanityLevelLooselyCompatible;
  347. ASSERT_TRUE(c1->AreEquivalent(loosely, c2.get(), &mismatch));
  348. ASSERT_TRUE(simple->cu->AreEquivalent(loosely, simple->cs.get(), &mismatch));
  349. ASSERT_OK(c1->ConfigureOption(config_options, "shared", "id=B;string=3"));
  350. ASSERT_TRUE(c1->AreEquivalent(loosely, c2.get(), &mismatch));
  351. ASSERT_FALSE(c1->AreEquivalent(config_options, c2.get(), &mismatch));
  352. ASSERT_FALSE(simple->cs->AreEquivalent(loosely, simple->cu.get(), &mismatch));
  353. simple->cs.reset();
  354. ASSERT_TRUE(c1->AreEquivalent(loosely, c2.get(), &mismatch));
  355. ASSERT_FALSE(c1->AreEquivalent(config_options, c2.get(), &mismatch));
  356. }
  357. // Tests that we can initialize a customizable from its options
  358. TEST_F(CustomizableTest, ConfigureStandaloneCustomTest) {
  359. std::unique_ptr<TestCustomizable> base, copy;
  360. const auto& registry = config_options_.registry;
  361. ASSERT_OK(registry->NewUniqueObject<TestCustomizable>("A", &base));
  362. ASSERT_OK(registry->NewUniqueObject<TestCustomizable>("A", &copy));
  363. ASSERT_OK(base->ConfigureFromString(config_options_, "int=33;bool=true"));
  364. std::string opt_str;
  365. std::string mismatch;
  366. ASSERT_OK(base->GetOptionString(config_options_, &opt_str));
  367. ASSERT_OK(copy->ConfigureFromString(config_options_, opt_str));
  368. ASSERT_TRUE(base->AreEquivalent(config_options_, copy.get(), &mismatch));
  369. }
  370. // Tests that we fail appropriately if the pattern is not registered
  371. TEST_F(CustomizableTest, BadNameTest) {
  372. config_options_.ignore_unsupported_options = false;
  373. std::unique_ptr<Configurable> c1(new SimpleConfigurable());
  374. ASSERT_NOK(
  375. c1->ConfigureFromString(config_options_, "unique.shared.id=bad name"));
  376. config_options_.ignore_unsupported_options = true;
  377. ASSERT_OK(
  378. c1->ConfigureFromString(config_options_, "unique.shared.id=bad name"));
  379. }
  380. // Tests that we fail appropriately if a bad option is passed to the underlying
  381. // configurable
  382. TEST_F(CustomizableTest, BadOptionTest) {
  383. std::unique_ptr<Configurable> c1(new SimpleConfigurable());
  384. ConfigOptions ignore = config_options_;
  385. ignore.ignore_unknown_options = true;
  386. ASSERT_NOK(c1->ConfigureFromString(config_options_, "A.int=11"));
  387. ASSERT_NOK(c1->ConfigureFromString(config_options_, "shared={id=B;int=1}"));
  388. ASSERT_OK(c1->ConfigureFromString(ignore, "shared={id=A;string=s}"));
  389. ASSERT_NOK(c1->ConfigureFromString(config_options_, "B.int=11"));
  390. ASSERT_OK(c1->ConfigureFromString(ignore, "B.int=11"));
  391. ASSERT_NOK(c1->ConfigureFromString(config_options_, "A.string=s"));
  392. ASSERT_OK(c1->ConfigureFromString(ignore, "A.string=s"));
  393. // Test as detached
  394. ASSERT_NOK(
  395. c1->ConfigureFromString(config_options_, "shared.id=A;A.string=b}"));
  396. ASSERT_OK(c1->ConfigureFromString(ignore, "shared.id=A;A.string=s}"));
  397. }
  398. TEST_F(CustomizableTest, FailingFactoryTest) {
  399. std::shared_ptr<ObjectRegistry> registry = ObjectRegistry::NewInstance();
  400. std::unique_ptr<Configurable> c1(new SimpleConfigurable());
  401. ConfigOptions ignore = config_options_;
  402. Status s;
  403. ignore.registry->AddLibrary("failing")->AddFactory<TestCustomizable>(
  404. "failing",
  405. [](const std::string& /*uri*/,
  406. std::unique_ptr<TestCustomizable>* /*guard */, std::string* errmsg) {
  407. *errmsg = "Bad Factory";
  408. return nullptr;
  409. });
  410. // If we are ignoring unknown and unsupported options, will see
  411. // different errors for failing versus missing
  412. ignore.ignore_unknown_options = false;
  413. ignore.ignore_unsupported_options = false;
  414. s = c1->ConfigureFromString(ignore, "shared.id=failing");
  415. ASSERT_TRUE(s.IsInvalidArgument());
  416. s = c1->ConfigureFromString(ignore, "unique.id=failing");
  417. ASSERT_TRUE(s.IsInvalidArgument());
  418. s = c1->ConfigureFromString(ignore, "shared.id=missing");
  419. ASSERT_TRUE(s.IsNotSupported());
  420. s = c1->ConfigureFromString(ignore, "unique.id=missing");
  421. ASSERT_TRUE(s.IsNotSupported());
  422. // If we are ignoring unsupported options, will see
  423. // errors for failing but not missing
  424. ignore.ignore_unknown_options = false;
  425. ignore.ignore_unsupported_options = true;
  426. s = c1->ConfigureFromString(ignore, "shared.id=failing");
  427. ASSERT_TRUE(s.IsInvalidArgument());
  428. s = c1->ConfigureFromString(ignore, "unique.id=failing");
  429. ASSERT_TRUE(s.IsInvalidArgument());
  430. ASSERT_OK(c1->ConfigureFromString(ignore, "shared.id=missing"));
  431. ASSERT_OK(c1->ConfigureFromString(ignore, "unique.id=missing"));
  432. // If we are ignoring unknown options, will see no errors
  433. // for failing or missing
  434. ignore.ignore_unknown_options = true;
  435. ignore.ignore_unsupported_options = false;
  436. ASSERT_OK(c1->ConfigureFromString(ignore, "shared.id=failing"));
  437. ASSERT_OK(c1->ConfigureFromString(ignore, "unique.id=failing"));
  438. ASSERT_OK(c1->ConfigureFromString(ignore, "shared.id=missing"));
  439. ASSERT_OK(c1->ConfigureFromString(ignore, "unique.id=missing"));
  440. }
  441. // Tests that different IDs lead to different objects
  442. TEST_F(CustomizableTest, UniqueIdTest) {
  443. std::unique_ptr<Configurable> base(new SimpleConfigurable());
  444. ASSERT_OK(base->ConfigureFromString(config_options_,
  445. "unique={id=A_1;int=1;bool=true}"));
  446. SimpleOptions* simple = base->GetOptions<SimpleOptions>();
  447. ASSERT_NE(simple, nullptr);
  448. ASSERT_NE(simple->cu, nullptr);
  449. ASSERT_EQ(simple->cu->GetId(), std::string("A_1"));
  450. std::string opt_str;
  451. std::string mismatch;
  452. ASSERT_OK(base->GetOptionString(config_options_, &opt_str));
  453. std::unique_ptr<Configurable> copy(new SimpleConfigurable());
  454. ASSERT_OK(copy->ConfigureFromString(config_options_, opt_str));
  455. ASSERT_TRUE(base->AreEquivalent(config_options_, copy.get(), &mismatch));
  456. ASSERT_OK(base->ConfigureFromString(config_options_,
  457. "unique={id=A_2;int=1;bool=true}"));
  458. ASSERT_FALSE(base->AreEquivalent(config_options_, copy.get(), &mismatch));
  459. ASSERT_EQ(simple->cu->GetId(), std::string("A_2"));
  460. }
  461. TEST_F(CustomizableTest, IsInstanceOfTest) {
  462. std::shared_ptr<TestCustomizable> tc = std::make_shared<ACustomizable>("A_1");
  463. ASSERT_EQ(tc->GetId(), std::string("A_1"));
  464. ASSERT_TRUE(tc->IsInstanceOf("A"));
  465. ASSERT_TRUE(tc->IsInstanceOf("TestCustomizable"));
  466. ASSERT_FALSE(tc->IsInstanceOf("B"));
  467. ASSERT_FALSE(tc->IsInstanceOf("A_1"));
  468. ASSERT_EQ(tc->CheckedCast<ACustomizable>(), tc.get());
  469. ASSERT_EQ(tc->CheckedCast<TestCustomizable>(), tc.get());
  470. ASSERT_EQ(tc->CheckedCast<BCustomizable>(), nullptr);
  471. tc.reset(new BCustomizable("B"));
  472. ASSERT_TRUE(tc->IsInstanceOf("B"));
  473. ASSERT_TRUE(tc->IsInstanceOf("TestCustomizable"));
  474. ASSERT_FALSE(tc->IsInstanceOf("A"));
  475. ASSERT_EQ(tc->CheckedCast<BCustomizable>(), tc.get());
  476. ASSERT_EQ(tc->CheckedCast<TestCustomizable>(), tc.get());
  477. ASSERT_EQ(tc->CheckedCast<ACustomizable>(), nullptr);
  478. }
  479. TEST_F(CustomizableTest, PrepareOptionsTest) {
  480. static std::unordered_map<std::string, OptionTypeInfo> p_option_info = {
  481. {"can_prepare",
  482. {0, OptionType::kBoolean, OptionVerificationType::kNormal,
  483. OptionTypeFlags::kNone}},
  484. };
  485. class PrepareCustomizable : public TestCustomizable {
  486. public:
  487. bool can_prepare_ = true;
  488. PrepareCustomizable() : TestCustomizable("P") {
  489. RegisterOptions("Prepare", &can_prepare_, &p_option_info);
  490. }
  491. Status PrepareOptions(const ConfigOptions& opts) override {
  492. if (!can_prepare_) {
  493. return Status::InvalidArgument("Cannot Prepare");
  494. } else {
  495. return TestCustomizable::PrepareOptions(opts);
  496. }
  497. }
  498. };
  499. ObjectLibrary::Default()->AddFactory<TestCustomizable>(
  500. "P",
  501. [](const std::string& /*name*/, std::unique_ptr<TestCustomizable>* guard,
  502. std::string* /* msg */) {
  503. guard->reset(new PrepareCustomizable());
  504. return guard->get();
  505. });
  506. std::unique_ptr<Configurable> base(new SimpleConfigurable());
  507. ConfigOptions prepared(config_options_);
  508. prepared.invoke_prepare_options = true;
  509. ASSERT_OK(base->ConfigureFromString(
  510. prepared, "unique=A_1; shared={id=B;string=s}; pointer.id=S"));
  511. SimpleOptions* simple = base->GetOptions<SimpleOptions>();
  512. ASSERT_NE(simple, nullptr);
  513. ASSERT_NE(simple->cu, nullptr);
  514. ASSERT_NE(simple->cs, nullptr);
  515. ASSERT_NE(simple->cp, nullptr);
  516. delete simple->cp;
  517. base.reset(new SimpleConfigurable());
  518. ASSERT_OK(base->ConfigureFromString(
  519. config_options_, "unique=A_1; shared={id=B;string=s}; pointer.id=S"));
  520. simple = base->GetOptions<SimpleOptions>();
  521. ASSERT_NE(simple, nullptr);
  522. ASSERT_NE(simple->cu, nullptr);
  523. ASSERT_NE(simple->cs, nullptr);
  524. ASSERT_NE(simple->cp, nullptr);
  525. ASSERT_OK(base->PrepareOptions(config_options_));
  526. delete simple->cp;
  527. base.reset(new SimpleConfigurable());
  528. simple = base->GetOptions<SimpleOptions>();
  529. ASSERT_NE(simple, nullptr);
  530. ASSERT_NOK(
  531. base->ConfigureFromString(prepared, "unique={id=P; can_prepare=false}"));
  532. ASSERT_EQ(simple->cu, nullptr);
  533. ASSERT_OK(
  534. base->ConfigureFromString(prepared, "unique={id=P; can_prepare=true}"));
  535. ASSERT_NE(simple->cu, nullptr);
  536. ASSERT_OK(base->ConfigureFromString(config_options_,
  537. "unique={id=P; can_prepare=true}"));
  538. ASSERT_NE(simple->cu, nullptr);
  539. ASSERT_OK(simple->cu->PrepareOptions(prepared));
  540. ASSERT_OK(base->ConfigureFromString(config_options_,
  541. "unique={id=P; can_prepare=false}"));
  542. ASSERT_NE(simple->cu, nullptr);
  543. ASSERT_NOK(simple->cu->PrepareOptions(prepared));
  544. }
  545. namespace {
  546. static std::unordered_map<std::string, OptionTypeInfo> inner_option_info = {
  547. {"inner", OptionTypeInfo::AsCustomSharedPtr<TestCustomizable>(
  548. 0, OptionVerificationType::kNormal,
  549. OptionTypeFlags::kStringNameOnly)}};
  550. struct InnerOptions {
  551. static const char* kName() { return "InnerOptions"; }
  552. std::shared_ptr<Customizable> inner;
  553. };
  554. class InnerCustomizable : public Customizable {
  555. public:
  556. explicit InnerCustomizable(const std::shared_ptr<Customizable>& w) {
  557. iopts_.inner = w;
  558. RegisterOptions(&iopts_, &inner_option_info);
  559. }
  560. static const char* kClassName() { return "Inner"; }
  561. const char* Name() const override { return kClassName(); }
  562. bool IsInstanceOf(const std::string& name) const override {
  563. if (name == kClassName()) {
  564. return true;
  565. } else {
  566. return Customizable::IsInstanceOf(name);
  567. }
  568. }
  569. protected:
  570. const Customizable* Inner() const override { return iopts_.inner.get(); }
  571. private:
  572. InnerOptions iopts_;
  573. };
  574. struct WrappedOptions1 {
  575. static const char* kName() { return "WrappedOptions1"; }
  576. int i = 42;
  577. };
  578. class WrappedCustomizable1 : public InnerCustomizable {
  579. public:
  580. explicit WrappedCustomizable1(const std::shared_ptr<Customizable>& w)
  581. : InnerCustomizable(w) {
  582. RegisterOptions(&wopts_, nullptr);
  583. }
  584. const char* Name() const override { return kClassName(); }
  585. static const char* kClassName() { return "Wrapped1"; }
  586. private:
  587. WrappedOptions1 wopts_;
  588. };
  589. struct WrappedOptions2 {
  590. static const char* kName() { return "WrappedOptions2"; }
  591. std::string s = "42";
  592. };
  593. class WrappedCustomizable2 : public InnerCustomizable {
  594. public:
  595. explicit WrappedCustomizable2(const std::shared_ptr<Customizable>& w)
  596. : InnerCustomizable(w) {}
  597. const void* GetOptionsPtr(const std::string& name) const override {
  598. if (name == WrappedOptions2::kName()) {
  599. return &wopts_;
  600. } else {
  601. return InnerCustomizable::GetOptionsPtr(name);
  602. }
  603. }
  604. const char* Name() const override { return kClassName(); }
  605. static const char* kClassName() { return "Wrapped2"; }
  606. private:
  607. WrappedOptions2 wopts_;
  608. };
  609. } // namespace
  610. TEST_F(CustomizableTest, WrappedInnerTest) {
  611. std::shared_ptr<TestCustomizable> ac =
  612. std::make_shared<TestCustomizable>("A");
  613. ASSERT_TRUE(ac->IsInstanceOf("A"));
  614. ASSERT_TRUE(ac->IsInstanceOf("TestCustomizable"));
  615. ASSERT_EQ(ac->CheckedCast<TestCustomizable>(), ac.get());
  616. ASSERT_EQ(ac->CheckedCast<InnerCustomizable>(), nullptr);
  617. ASSERT_EQ(ac->CheckedCast<WrappedCustomizable1>(), nullptr);
  618. ASSERT_EQ(ac->CheckedCast<WrappedCustomizable2>(), nullptr);
  619. std::shared_ptr<Customizable> wc1 =
  620. std::make_shared<WrappedCustomizable1>(ac);
  621. ASSERT_TRUE(wc1->IsInstanceOf(WrappedCustomizable1::kClassName()));
  622. ASSERT_EQ(wc1->CheckedCast<WrappedCustomizable1>(), wc1.get());
  623. ASSERT_EQ(wc1->CheckedCast<WrappedCustomizable2>(), nullptr);
  624. ASSERT_EQ(wc1->CheckedCast<InnerCustomizable>(), wc1.get());
  625. ASSERT_EQ(wc1->CheckedCast<TestCustomizable>(), ac.get());
  626. std::shared_ptr<Customizable> wc2 =
  627. std::make_shared<WrappedCustomizable2>(wc1);
  628. ASSERT_TRUE(wc2->IsInstanceOf(WrappedCustomizable2::kClassName()));
  629. ASSERT_EQ(wc2->CheckedCast<WrappedCustomizable2>(), wc2.get());
  630. ASSERT_EQ(wc2->CheckedCast<WrappedCustomizable1>(), wc1.get());
  631. ASSERT_EQ(wc2->CheckedCast<InnerCustomizable>(), wc2.get());
  632. ASSERT_EQ(wc2->CheckedCast<TestCustomizable>(), ac.get());
  633. }
  634. TEST_F(CustomizableTest, CustomizableInnerTest) {
  635. std::shared_ptr<Customizable> c =
  636. std::make_shared<InnerCustomizable>(std::make_shared<ACustomizable>("a"));
  637. std::shared_ptr<Customizable> wc1 = std::make_shared<WrappedCustomizable1>(c);
  638. std::shared_ptr<Customizable> wc2 = std::make_shared<WrappedCustomizable2>(c);
  639. auto inner = c->GetOptions<InnerOptions>();
  640. ASSERT_NE(inner, nullptr);
  641. auto aopts = c->GetOptions<AOptions>();
  642. ASSERT_NE(aopts, nullptr);
  643. ASSERT_EQ(aopts, wc1->GetOptions<AOptions>());
  644. ASSERT_EQ(aopts, wc2->GetOptions<AOptions>());
  645. auto w1opts = wc1->GetOptions<WrappedOptions1>();
  646. ASSERT_NE(w1opts, nullptr);
  647. ASSERT_EQ(c->GetOptions<WrappedOptions1>(), nullptr);
  648. ASSERT_EQ(wc2->GetOptions<WrappedOptions1>(), nullptr);
  649. auto w2opts = wc2->GetOptions<WrappedOptions2>();
  650. ASSERT_NE(w2opts, nullptr);
  651. ASSERT_EQ(c->GetOptions<WrappedOptions2>(), nullptr);
  652. ASSERT_EQ(wc1->GetOptions<WrappedOptions2>(), nullptr);
  653. }
  654. TEST_F(CustomizableTest, CopyObjectTest) {
  655. class CopyCustomizable : public Customizable {
  656. public:
  657. CopyCustomizable() : prepared_(0), validated_(0) {}
  658. const char* Name() const override { return "CopyCustomizable"; }
  659. Status PrepareOptions(const ConfigOptions& options) override {
  660. prepared_++;
  661. return Customizable::PrepareOptions(options);
  662. }
  663. Status ValidateOptions(const DBOptions& db_opts,
  664. const ColumnFamilyOptions& cf_opts) const override {
  665. validated_++;
  666. return Customizable::ValidateOptions(db_opts, cf_opts);
  667. }
  668. int prepared_;
  669. mutable int validated_;
  670. };
  671. CopyCustomizable c1;
  672. ConfigOptions config_options;
  673. Options options;
  674. ASSERT_OK(c1.PrepareOptions(config_options));
  675. ASSERT_OK(c1.ValidateOptions(options, options));
  676. ASSERT_EQ(c1.prepared_, 1);
  677. ASSERT_EQ(c1.validated_, 1);
  678. CopyCustomizable c2 = c1;
  679. ASSERT_OK(c1.PrepareOptions(config_options));
  680. ASSERT_OK(c1.ValidateOptions(options, options));
  681. ASSERT_EQ(c2.prepared_, 1);
  682. ASSERT_EQ(c2.validated_, 1);
  683. ASSERT_EQ(c1.prepared_, 2);
  684. ASSERT_EQ(c1.validated_, 2);
  685. }
  686. TEST_F(CustomizableTest, TestStringDepth) {
  687. ConfigOptions shallow = config_options_;
  688. std::unique_ptr<Configurable> c(
  689. new InnerCustomizable(std::make_shared<ACustomizable>("a")));
  690. std::string opt_str;
  691. shallow.depth = ConfigOptions::Depth::kDepthShallow;
  692. ASSERT_OK(c->GetOptionString(shallow, &opt_str));
  693. ASSERT_EQ(opt_str, "inner=a;");
  694. shallow.depth = ConfigOptions::Depth::kDepthDetailed;
  695. ASSERT_OK(c->GetOptionString(shallow, &opt_str));
  696. ASSERT_NE(opt_str, "inner=a;");
  697. }
  698. // Tests that we only get a new customizable when it changes
  699. TEST_F(CustomizableTest, NewUniqueCustomizableTest) {
  700. std::unique_ptr<Configurable> base(new SimpleConfigurable());
  701. A_count = 0;
  702. ASSERT_OK(base->ConfigureFromString(config_options_,
  703. "unique={id=A_1;int=1;bool=true}"));
  704. SimpleOptions* simple = base->GetOptions<SimpleOptions>();
  705. ASSERT_NE(simple, nullptr);
  706. ASSERT_NE(simple->cu, nullptr);
  707. ASSERT_EQ(A_count, 1); // Created one A
  708. ASSERT_OK(base->ConfigureFromString(config_options_,
  709. "unique={id=A_1;int=1;bool=false}"));
  710. ASSERT_EQ(A_count, 2); // Create another A_1
  711. ASSERT_OK(base->ConfigureFromString(config_options_, "unique={id=}"));
  712. ASSERT_EQ(simple->cu, nullptr);
  713. ASSERT_EQ(A_count, 2);
  714. ASSERT_OK(base->ConfigureFromString(config_options_,
  715. "unique={id=A_2;int=1;bool=false}"));
  716. ASSERT_EQ(A_count, 3); // Created another A
  717. ASSERT_OK(base->ConfigureFromString(config_options_, "unique.id="));
  718. ASSERT_EQ(simple->cu, nullptr);
  719. ASSERT_OK(base->ConfigureFromString(config_options_, "unique=nullptr"));
  720. ASSERT_EQ(simple->cu, nullptr);
  721. ASSERT_OK(base->ConfigureFromString(config_options_, "unique.id=nullptr"));
  722. ASSERT_EQ(simple->cu, nullptr);
  723. ASSERT_EQ(A_count, 3);
  724. }
  725. TEST_F(CustomizableTest, NewEmptyUniqueTest) {
  726. std::unique_ptr<Configurable> base(new SimpleConfigurable());
  727. SimpleOptions* simple = base->GetOptions<SimpleOptions>();
  728. ASSERT_EQ(simple->cu, nullptr);
  729. simple->cu.reset(new BCustomizable("B"));
  730. ASSERT_OK(base->ConfigureFromString(config_options_, "unique={id=}"));
  731. ASSERT_EQ(simple->cu, nullptr);
  732. simple->cu.reset(new BCustomizable("B"));
  733. ASSERT_OK(base->ConfigureFromString(config_options_, "unique={id=nullptr}"));
  734. ASSERT_EQ(simple->cu, nullptr);
  735. simple->cu.reset(new BCustomizable("B"));
  736. ASSERT_OK(base->ConfigureFromString(config_options_, "unique.id="));
  737. ASSERT_EQ(simple->cu, nullptr);
  738. simple->cu.reset(new BCustomizable("B"));
  739. ASSERT_OK(base->ConfigureFromString(config_options_, "unique=nullptr"));
  740. ASSERT_EQ(simple->cu, nullptr);
  741. simple->cu.reset(new BCustomizable("B"));
  742. ASSERT_OK(base->ConfigureFromString(config_options_, "unique.id=nullptr"));
  743. ASSERT_EQ(simple->cu, nullptr);
  744. }
  745. TEST_F(CustomizableTest, NewEmptySharedTest) {
  746. std::unique_ptr<Configurable> base(new SimpleConfigurable());
  747. SimpleOptions* simple = base->GetOptions<SimpleOptions>();
  748. ASSERT_NE(simple, nullptr);
  749. ASSERT_EQ(simple->cs, nullptr);
  750. simple->cs.reset(new BCustomizable("B"));
  751. ASSERT_OK(base->ConfigureFromString(config_options_, "shared={id=}"));
  752. ASSERT_NE(simple, nullptr);
  753. ASSERT_EQ(simple->cs, nullptr);
  754. simple->cs.reset(new BCustomizable("B"));
  755. ASSERT_OK(base->ConfigureFromString(config_options_, "shared={id=nullptr}"));
  756. ASSERT_EQ(simple->cs, nullptr);
  757. simple->cs.reset(new BCustomizable("B"));
  758. ASSERT_OK(base->ConfigureFromString(config_options_, "shared.id="));
  759. ASSERT_EQ(simple->cs, nullptr);
  760. simple->cs.reset(new BCustomizable("B"));
  761. ASSERT_OK(base->ConfigureFromString(config_options_, "shared.id=nullptr"));
  762. ASSERT_EQ(simple->cs, nullptr);
  763. simple->cs.reset(new BCustomizable("B"));
  764. ASSERT_OK(base->ConfigureFromString(config_options_, "shared=nullptr"));
  765. ASSERT_EQ(simple->cs, nullptr);
  766. }
  767. TEST_F(CustomizableTest, NewEmptyStaticTest) {
  768. std::unique_ptr<Configurable> base(new SimpleConfigurable());
  769. ASSERT_OK(base->ConfigureFromString(config_options_, "pointer={id=}"));
  770. SimpleOptions* simple = base->GetOptions<SimpleOptions>();
  771. ASSERT_NE(simple, nullptr);
  772. ASSERT_EQ(simple->cp, nullptr);
  773. ASSERT_OK(base->ConfigureFromString(config_options_, "pointer={id=nullptr}"));
  774. ASSERT_EQ(simple->cp, nullptr);
  775. ASSERT_OK(base->ConfigureFromString(config_options_, "pointer="));
  776. ASSERT_EQ(simple->cp, nullptr);
  777. ASSERT_OK(base->ConfigureFromString(config_options_, "pointer=nullptr"));
  778. ASSERT_EQ(simple->cp, nullptr);
  779. ASSERT_OK(base->ConfigureFromString(config_options_, "pointer.id="));
  780. ASSERT_EQ(simple->cp, nullptr);
  781. ASSERT_OK(base->ConfigureFromString(config_options_, "pointer.id=nullptr"));
  782. ASSERT_EQ(simple->cp, nullptr);
  783. }
  784. namespace {
  785. static std::unordered_map<std::string, OptionTypeInfo> vector_option_info = {
  786. {"vector",
  787. OptionTypeInfo::Vector<std::shared_ptr<TestCustomizable>>(
  788. 0, OptionVerificationType::kNormal,
  789. OptionTypeFlags::kNone,
  790. OptionTypeInfo::AsCustomSharedPtr<TestCustomizable>(
  791. 0, OptionVerificationType::kNormal, OptionTypeFlags::kNone))},
  792. };
  793. class VectorConfigurable : public SimpleConfigurable {
  794. public:
  795. VectorConfigurable() { RegisterOptions("vector", &cv, &vector_option_info); }
  796. std::vector<std::shared_ptr<TestCustomizable>> cv;
  797. };
  798. } // namespace
  799. TEST_F(CustomizableTest, VectorConfigTest) {
  800. VectorConfigurable orig, copy;
  801. std::shared_ptr<TestCustomizable> c1, c2;
  802. ASSERT_OK(TestCustomizable::CreateFromString(config_options_, "A", &c1));
  803. ASSERT_OK(TestCustomizable::CreateFromString(config_options_, "B", &c2));
  804. orig.cv.push_back(c1);
  805. orig.cv.push_back(c2);
  806. ASSERT_OK(orig.ConfigureFromString(config_options_, "unique=A2"));
  807. std::string opt_str, mismatch;
  808. ASSERT_OK(orig.GetOptionString(config_options_, &opt_str));
  809. ASSERT_OK(copy.ConfigureFromString(config_options_, opt_str));
  810. ASSERT_TRUE(orig.AreEquivalent(config_options_, &copy, &mismatch));
  811. }
  812. TEST_F(CustomizableTest, NoNameTest) {
  813. // If Customizables are created without names, they are not
  814. // part of the serialization (since they cannot be recreated)
  815. VectorConfigurable orig, copy;
  816. auto sopts = orig.GetOptions<SimpleOptions>();
  817. auto copts = copy.GetOptions<SimpleOptions>();
  818. sopts->cu.reset(new ACustomizable(""));
  819. orig.cv.push_back(std::make_shared<ACustomizable>(""));
  820. orig.cv.push_back(std::make_shared<ACustomizable>("A_1"));
  821. std::string opt_str, mismatch;
  822. ASSERT_OK(orig.GetOptionString(config_options_, &opt_str));
  823. ASSERT_OK(copy.ConfigureFromString(config_options_, opt_str));
  824. ASSERT_EQ(copy.cv.size(), 1U);
  825. ASSERT_EQ(copy.cv[0]->GetId(), "A_1");
  826. ASSERT_EQ(copts->cu, nullptr);
  827. }
  828. TEST_F(CustomizableTest, IgnoreUnknownObjects) {
  829. ConfigOptions ignore = config_options_;
  830. std::shared_ptr<TestCustomizable> shared;
  831. std::unique_ptr<TestCustomizable> unique;
  832. TestCustomizable* pointer = nullptr;
  833. ignore.ignore_unsupported_options = false;
  834. ASSERT_NOK(LoadSharedObject<TestCustomizable>(ignore, "Unknown", &shared));
  835. ASSERT_NOK(LoadUniqueObject<TestCustomizable>(ignore, "Unknown", &unique));
  836. ASSERT_NOK(LoadStaticObject<TestCustomizable>(ignore, "Unknown", &pointer));
  837. ASSERT_EQ(shared.get(), nullptr);
  838. ASSERT_EQ(unique.get(), nullptr);
  839. ASSERT_EQ(pointer, nullptr);
  840. ignore.ignore_unsupported_options = true;
  841. ASSERT_OK(LoadSharedObject<TestCustomizable>(ignore, "Unknown", &shared));
  842. ASSERT_OK(LoadUniqueObject<TestCustomizable>(ignore, "Unknown", &unique));
  843. ASSERT_OK(LoadStaticObject<TestCustomizable>(ignore, "Unknown", &pointer));
  844. ASSERT_EQ(shared.get(), nullptr);
  845. ASSERT_EQ(unique.get(), nullptr);
  846. ASSERT_EQ(pointer, nullptr);
  847. ASSERT_OK(LoadSharedObject<TestCustomizable>(ignore, "id=Unknown", &shared));
  848. ASSERT_OK(LoadUniqueObject<TestCustomizable>(ignore, "id=Unknown", &unique));
  849. ASSERT_OK(LoadStaticObject<TestCustomizable>(ignore, "id=Unknown", &pointer));
  850. ASSERT_EQ(shared.get(), nullptr);
  851. ASSERT_EQ(unique.get(), nullptr);
  852. ASSERT_EQ(pointer, nullptr);
  853. ASSERT_OK(LoadSharedObject<TestCustomizable>(ignore, "id=Unknown;option=bad",
  854. &shared));
  855. ASSERT_OK(LoadUniqueObject<TestCustomizable>(ignore, "id=Unknown;option=bad",
  856. &unique));
  857. ASSERT_OK(LoadStaticObject<TestCustomizable>(ignore, "id=Unknown;option=bad",
  858. &pointer));
  859. ASSERT_EQ(shared.get(), nullptr);
  860. ASSERT_EQ(unique.get(), nullptr);
  861. ASSERT_EQ(pointer, nullptr);
  862. }
  863. TEST_F(CustomizableTest, URLFactoryTest) {
  864. std::unique_ptr<TestCustomizable> unique;
  865. config_options_.registry->AddLibrary("URL")->AddFactory<TestCustomizable>(
  866. ObjectLibrary::PatternEntry("Z", false).AddSeparator(""),
  867. [](const std::string& name, std::unique_ptr<TestCustomizable>* guard,
  868. std::string* /* msg */) {
  869. guard->reset(new TestCustomizable(name));
  870. return guard->get();
  871. });
  872. ConfigOptions ignore = config_options_;
  873. ignore.ignore_unsupported_options = false;
  874. ignore.ignore_unsupported_options = false;
  875. ASSERT_OK(TestCustomizable::CreateFromString(ignore, "Z=1;x=y", &unique));
  876. ASSERT_NE(unique, nullptr);
  877. ASSERT_EQ(unique->GetId(), "Z=1;x=y");
  878. ASSERT_OK(TestCustomizable::CreateFromString(ignore, "Z;x=y", &unique));
  879. ASSERT_NE(unique, nullptr);
  880. ASSERT_EQ(unique->GetId(), "Z;x=y");
  881. unique.reset();
  882. ASSERT_OK(TestCustomizable::CreateFromString(ignore, "Z=1?x=y", &unique));
  883. ASSERT_NE(unique, nullptr);
  884. ASSERT_EQ(unique->GetId(), "Z=1?x=y");
  885. }
  886. TEST_F(CustomizableTest, MutableOptionsTest) {
  887. static std::unordered_map<std::string, OptionTypeInfo> mutable_option_info = {
  888. {"mutable",
  889. OptionTypeInfo::AsCustomSharedPtr<TestCustomizable>(
  890. 0, OptionVerificationType::kNormal, OptionTypeFlags::kMutable)}};
  891. static std::unordered_map<std::string, OptionTypeInfo> immutable_option_info =
  892. {{"immutable",
  893. OptionTypeInfo::AsCustomSharedPtr<TestCustomizable>(
  894. 0, OptionVerificationType::kNormal, OptionTypeFlags::kAllowNull)}};
  895. class MutableCustomizable : public Customizable {
  896. private:
  897. std::shared_ptr<TestCustomizable> mutable_;
  898. std::shared_ptr<TestCustomizable> immutable_;
  899. public:
  900. MutableCustomizable() {
  901. RegisterOptions("mutable", &mutable_, &mutable_option_info);
  902. RegisterOptions("immutable", &immutable_, &immutable_option_info);
  903. }
  904. const char* Name() const override { return "MutableCustomizable"; }
  905. };
  906. MutableCustomizable mc, mc2;
  907. std::string mismatch;
  908. std::string opt_str;
  909. ConfigOptions options = config_options_;
  910. ASSERT_OK(mc.ConfigureOption(options, "mutable", "{id=B;}"));
  911. options.mutable_options_only = true;
  912. ASSERT_OK(mc.GetOptionString(options, &opt_str));
  913. ASSERT_OK(mc2.ConfigureFromString(options, opt_str));
  914. ASSERT_TRUE(mc.AreEquivalent(options, &mc2, &mismatch));
  915. options.mutable_options_only = false;
  916. ASSERT_OK(mc.ConfigureOption(options, "immutable", "{id=A; int=10}"));
  917. auto* mm = mc.GetOptions<std::shared_ptr<TestCustomizable>>("mutable");
  918. auto* im = mc.GetOptions<std::shared_ptr<TestCustomizable>>("immutable");
  919. ASSERT_NE(mm, nullptr);
  920. ASSERT_NE(mm->get(), nullptr);
  921. ASSERT_NE(im, nullptr);
  922. ASSERT_NE(im->get(), nullptr);
  923. // Now only deal with mutable options
  924. options.mutable_options_only = true;
  925. // Setting nested immutable customizable options fails
  926. ASSERT_NOK(mc.ConfigureOption(options, "immutable", "{id=B;}"));
  927. ASSERT_NOK(mc.ConfigureOption(options, "immutable.id", "B"));
  928. ASSERT_NOK(mc.ConfigureOption(options, "immutable.bool", "true"));
  929. ASSERT_NOK(mc.ConfigureOption(options, "immutable", "bool=true"));
  930. ASSERT_NOK(mc.ConfigureOption(options, "immutable", "{int=11;bool=true}"));
  931. auto* im_a = im->get()->GetOptions<AOptions>("A");
  932. ASSERT_NE(im_a, nullptr);
  933. ASSERT_EQ(im_a->i, 10);
  934. ASSERT_EQ(im_a->b, false);
  935. // Setting nested mutable customizable options succeeds but the object did not
  936. // change
  937. ASSERT_OK(mc.ConfigureOption(options, "immutable.int", "11"));
  938. ASSERT_EQ(im_a->i, 11);
  939. ASSERT_EQ(im_a, im->get()->GetOptions<AOptions>("A"));
  940. // The mutable configurable itself can be changed
  941. ASSERT_OK(mc.ConfigureOption(options, "mutable.id", "A"));
  942. ASSERT_OK(mc.ConfigureOption(options, "mutable", "A"));
  943. ASSERT_OK(mc.ConfigureOption(options, "mutable", "{id=A}"));
  944. ASSERT_OK(mc.ConfigureOption(options, "mutable", "{bool=true}"));
  945. // The Nested options in the mutable object can be changed
  946. ASSERT_OK(mc.ConfigureOption(options, "mutable", "{bool=true}"));
  947. auto* mm_a = mm->get()->GetOptions<AOptions>("A");
  948. ASSERT_EQ(mm_a->b, true);
  949. ASSERT_OK(mc.ConfigureOption(options, "mutable", "{int=22;bool=false}"));
  950. mm_a = mm->get()->GetOptions<AOptions>("A");
  951. ASSERT_EQ(mm_a->i, 22);
  952. ASSERT_EQ(mm_a->b, false);
  953. // Only the mutable options should get serialized
  954. options.mutable_options_only = false;
  955. ASSERT_OK(mc.GetOptionString(options, &opt_str));
  956. ASSERT_OK(mc.ConfigureOption(options, "immutable", "{id=B;}"));
  957. options.mutable_options_only = true;
  958. ASSERT_OK(mc.GetOptionString(options, &opt_str));
  959. ASSERT_OK(mc2.ConfigureFromString(options, opt_str));
  960. ASSERT_TRUE(mc.AreEquivalent(options, &mc2, &mismatch));
  961. options.mutable_options_only = false;
  962. ASSERT_FALSE(mc.AreEquivalent(options, &mc2, &mismatch));
  963. ASSERT_EQ(mismatch, "immutable");
  964. }
  965. TEST_F(CustomizableTest, CustomManagedObjects) {
  966. std::shared_ptr<TestCustomizable> object1, object2;
  967. ASSERT_OK(LoadManagedObject<TestCustomizable>(
  968. config_options_, "id=A_1;int=1;bool=true", &object1));
  969. ASSERT_NE(object1, nullptr);
  970. ASSERT_OK(
  971. LoadManagedObject<TestCustomizable>(config_options_, "A_1", &object2));
  972. ASSERT_EQ(object1, object2);
  973. auto* opts = object2->GetOptions<AOptions>("A");
  974. ASSERT_NE(opts, nullptr);
  975. ASSERT_EQ(opts->i, 1);
  976. ASSERT_EQ(opts->b, true);
  977. ASSERT_OK(
  978. LoadManagedObject<TestCustomizable>(config_options_, "A_2", &object2));
  979. ASSERT_NE(object1, object2);
  980. object1.reset();
  981. ASSERT_OK(LoadManagedObject<TestCustomizable>(
  982. config_options_, "id=A_1;int=2;bool=false", &object1));
  983. opts = object1->GetOptions<AOptions>("A");
  984. ASSERT_NE(opts, nullptr);
  985. ASSERT_EQ(opts->i, 2);
  986. ASSERT_EQ(opts->b, false);
  987. }
  988. TEST_F(CustomizableTest, CreateManagedObjects) {
  989. class ManagedCustomizable : public Customizable {
  990. public:
  991. static const char* Type() { return "ManagedCustomizable"; }
  992. static const char* kClassName() { return "Managed"; }
  993. const char* Name() const override { return kClassName(); }
  994. std::string GetId() const override { return id_; }
  995. ManagedCustomizable() { id_ = GenerateIndividualId(); }
  996. static Status CreateFromString(
  997. const ConfigOptions& opts, const std::string& value,
  998. std::shared_ptr<ManagedCustomizable>* result) {
  999. return LoadManagedObject<ManagedCustomizable>(opts, value, result);
  1000. }
  1001. private:
  1002. std::string id_;
  1003. };
  1004. config_options_.registry->AddLibrary("Managed")
  1005. ->AddFactory<ManagedCustomizable>(
  1006. ObjectLibrary::PatternEntry::AsIndividualId(
  1007. ManagedCustomizable::kClassName()),
  1008. [](const std::string& /*name*/,
  1009. std::unique_ptr<ManagedCustomizable>* guard,
  1010. std::string* /* msg */) {
  1011. guard->reset(new ManagedCustomizable());
  1012. return guard->get();
  1013. });
  1014. std::shared_ptr<ManagedCustomizable> mc1, mc2, mc3, obj;
  1015. // Create a "deadbeef" customizable
  1016. std::string deadbeef =
  1017. std::string(ManagedCustomizable::kClassName()) + "@0xdeadbeef#0001";
  1018. ASSERT_OK(
  1019. ManagedCustomizable::CreateFromString(config_options_, deadbeef, &mc1));
  1020. // Create an object with the base/class name
  1021. ASSERT_OK(ManagedCustomizable::CreateFromString(
  1022. config_options_, ManagedCustomizable::kClassName(), &mc2));
  1023. // Creating another with the base name returns a different object
  1024. ASSERT_OK(ManagedCustomizable::CreateFromString(
  1025. config_options_, ManagedCustomizable::kClassName(), &mc3));
  1026. // At this point, there should be 4 managed objects (deadbeef, mc1, 2, and 3)
  1027. std::vector<std::shared_ptr<ManagedCustomizable>> objects;
  1028. ASSERT_OK(config_options_.registry->ListManagedObjects(&objects));
  1029. ASSERT_EQ(objects.size(), 4U);
  1030. objects.clear();
  1031. // Three separate object, none of them equal
  1032. ASSERT_NE(mc1, mc2);
  1033. ASSERT_NE(mc1, mc3);
  1034. ASSERT_NE(mc2, mc3);
  1035. // Creating another object with "deadbeef" object
  1036. ASSERT_OK(
  1037. ManagedCustomizable::CreateFromString(config_options_, deadbeef, &obj));
  1038. ASSERT_EQ(mc1, obj);
  1039. // Create another with the IDs of the instances
  1040. ASSERT_OK(ManagedCustomizable::CreateFromString(config_options_, mc1->GetId(),
  1041. &obj));
  1042. ASSERT_EQ(mc1, obj);
  1043. ASSERT_OK(ManagedCustomizable::CreateFromString(config_options_, mc2->GetId(),
  1044. &obj));
  1045. ASSERT_EQ(mc2, obj);
  1046. ASSERT_OK(ManagedCustomizable::CreateFromString(config_options_, mc3->GetId(),
  1047. &obj));
  1048. ASSERT_EQ(mc3, obj);
  1049. // Now get rid of deadbeef. 2 Objects left (m2+m3)
  1050. mc1.reset();
  1051. ASSERT_EQ(
  1052. config_options_.registry->GetManagedObject<ManagedCustomizable>(deadbeef),
  1053. nullptr);
  1054. ASSERT_OK(config_options_.registry->ListManagedObjects(&objects));
  1055. ASSERT_EQ(objects.size(), 2U);
  1056. objects.clear();
  1057. // Associate deadbeef with #2
  1058. ASSERT_OK(config_options_.registry->SetManagedObject(deadbeef, mc2));
  1059. ASSERT_OK(
  1060. ManagedCustomizable::CreateFromString(config_options_, deadbeef, &obj));
  1061. ASSERT_EQ(mc2, obj);
  1062. obj.reset();
  1063. // Get the ID of mc2 and then reset it. 1 Object left
  1064. std::string mc2id = mc2->GetId();
  1065. mc2.reset();
  1066. ASSERT_EQ(
  1067. config_options_.registry->GetManagedObject<ManagedCustomizable>(mc2id),
  1068. nullptr);
  1069. ASSERT_OK(config_options_.registry->ListManagedObjects(&objects));
  1070. ASSERT_EQ(objects.size(), 1U);
  1071. objects.clear();
  1072. // Create another object with the old mc2id.
  1073. ASSERT_OK(
  1074. ManagedCustomizable::CreateFromString(config_options_, mc2id, &mc2));
  1075. ASSERT_OK(
  1076. ManagedCustomizable::CreateFromString(config_options_, mc2id, &obj));
  1077. ASSERT_EQ(mc2, obj);
  1078. // For good measure, create another deadbeef object
  1079. ASSERT_OK(
  1080. ManagedCustomizable::CreateFromString(config_options_, deadbeef, &mc1));
  1081. ASSERT_OK(
  1082. ManagedCustomizable::CreateFromString(config_options_, deadbeef, &obj));
  1083. ASSERT_EQ(mc1, obj);
  1084. }
  1085. namespace {
  1086. class TestSecondaryCache : public SecondaryCache {
  1087. public:
  1088. static const char* kClassName() { return "Test"; }
  1089. const char* Name() const override { return kClassName(); }
  1090. Status Insert(const Slice& /*key*/, Cache::ObjectPtr /*value*/,
  1091. const Cache::CacheItemHelper* /*helper*/,
  1092. bool /*force_insert*/) override {
  1093. return Status::NotSupported();
  1094. }
  1095. Status InsertSaved(const Slice& /*key*/, const Slice& /*saved*/,
  1096. CompressionType /*type*/, CacheTier /*source*/) override {
  1097. return Status::OK();
  1098. }
  1099. std::unique_ptr<SecondaryCacheResultHandle> Lookup(
  1100. const Slice& /*key*/, const Cache::CacheItemHelper* /*helper*/,
  1101. Cache::CreateContext* /*create_context*/, bool /*wait*/,
  1102. bool /*advise_erase*/, Statistics* /*stats*/,
  1103. bool& kept_in_sec_cache) override {
  1104. kept_in_sec_cache = true;
  1105. return nullptr;
  1106. }
  1107. bool SupportForceErase() const override { return false; }
  1108. void Erase(const Slice& /*key*/) override {}
  1109. // Wait for a collection of handles to become ready
  1110. void WaitAll(std::vector<SecondaryCacheResultHandle*> /*handles*/) override {}
  1111. std::string GetPrintableOptions() const override { return ""; }
  1112. };
  1113. class TestStatistics : public StatisticsImpl {
  1114. public:
  1115. TestStatistics() : StatisticsImpl(nullptr) {}
  1116. const char* Name() const override { return kClassName(); }
  1117. static const char* kClassName() { return "Test"; }
  1118. };
  1119. class TestFlushBlockPolicyFactory : public FlushBlockPolicyFactory {
  1120. public:
  1121. TestFlushBlockPolicyFactory() = default;
  1122. static const char* kClassName() { return "TestFlushBlockPolicyFactory"; }
  1123. const char* Name() const override { return kClassName(); }
  1124. FlushBlockPolicy* NewFlushBlockPolicy(
  1125. const BlockBasedTableOptions& /*table_options*/,
  1126. const BlockBuilder& /*data_block_builder*/) const override {
  1127. return nullptr;
  1128. }
  1129. };
  1130. class MockSliceTransform : public SliceTransform {
  1131. public:
  1132. const char* Name() const override { return kClassName(); }
  1133. static const char* kClassName() { return "Mock"; }
  1134. Slice Transform(const Slice& /*key*/) const override { return Slice(); }
  1135. bool InDomain(const Slice& /*key*/) const override { return false; }
  1136. bool InRange(const Slice& /*key*/) const override { return false; }
  1137. };
  1138. class MockMemoryAllocator : public BaseMemoryAllocator {
  1139. public:
  1140. static const char* kClassName() { return "MockMemoryAllocator"; }
  1141. const char* Name() const override { return kClassName(); }
  1142. };
  1143. class MockEncryptionProvider : public EncryptionProvider {
  1144. public:
  1145. explicit MockEncryptionProvider(const std::string& id) : id_(id) {}
  1146. static const char* kClassName() { return "Mock"; }
  1147. const char* Name() const override { return kClassName(); }
  1148. size_t GetPrefixLength() const override { return 0; }
  1149. Status CreateNewPrefix(const std::string& /*fname*/, char* /*prefix*/,
  1150. size_t /*prefixLength*/) const override {
  1151. return Status::NotSupported();
  1152. }
  1153. Status AddCipher(const std::string& /*descriptor*/, const char* /*cipher*/,
  1154. size_t /*len*/, bool /*for_write*/) override {
  1155. return Status::NotSupported();
  1156. }
  1157. Status CreateCipherStream(
  1158. const std::string& /*fname*/, const EnvOptions& /*options*/,
  1159. Slice& /*prefix*/,
  1160. std::unique_ptr<BlockAccessCipherStream>* /*result*/) override {
  1161. return Status::NotSupported();
  1162. }
  1163. Status ValidateOptions(const DBOptions& db_opts,
  1164. const ColumnFamilyOptions& cf_opts) const override {
  1165. if (EndsWith(id_, "://test")) {
  1166. return EncryptionProvider::ValidateOptions(db_opts, cf_opts);
  1167. } else {
  1168. return Status::InvalidArgument("MockProvider not initialized");
  1169. }
  1170. }
  1171. private:
  1172. std::string id_;
  1173. };
  1174. class MockCipher : public BlockCipher {
  1175. public:
  1176. const char* Name() const override { return "Mock"; }
  1177. size_t BlockSize() override { return 0; }
  1178. Status Encrypt(char* /*data*/) override { return Status::NotSupported(); }
  1179. Status Decrypt(char* data) override { return Encrypt(data); }
  1180. };
  1181. class DummyFileSystem : public FileSystemWrapper {
  1182. public:
  1183. explicit DummyFileSystem(const std::shared_ptr<FileSystem>& t)
  1184. : FileSystemWrapper(t) {}
  1185. static const char* kClassName() { return "DummyFileSystem"; }
  1186. const char* Name() const override { return kClassName(); }
  1187. };
  1188. class MockTablePropertiesCollectorFactory
  1189. : public TablePropertiesCollectorFactory {
  1190. private:
  1191. public:
  1192. TablePropertiesCollector* CreateTablePropertiesCollector(
  1193. TablePropertiesCollectorFactory::Context /*context*/) override {
  1194. return nullptr;
  1195. }
  1196. static const char* kClassName() { return "Mock"; }
  1197. const char* Name() const override { return kClassName(); }
  1198. };
  1199. class MockSstPartitionerFactory : public SstPartitionerFactory {
  1200. public:
  1201. static const char* kClassName() { return "Mock"; }
  1202. const char* Name() const override { return kClassName(); }
  1203. std::unique_ptr<SstPartitioner> CreatePartitioner(
  1204. const SstPartitioner::Context& /* context */) const override {
  1205. return nullptr;
  1206. }
  1207. };
  1208. class MockFileChecksumGenFactory : public FileChecksumGenFactory {
  1209. public:
  1210. static const char* kClassName() { return "Mock"; }
  1211. const char* Name() const override { return kClassName(); }
  1212. std::unique_ptr<FileChecksumGenerator> CreateFileChecksumGenerator(
  1213. const FileChecksumGenContext& /*context*/) override {
  1214. return nullptr;
  1215. }
  1216. };
  1217. class MockFilterPolicy : public FilterPolicy {
  1218. public:
  1219. static const char* kClassName() { return "MockFilterPolicy"; }
  1220. const char* Name() const override { return kClassName(); }
  1221. const char* CompatibilityName() const override { return Name(); }
  1222. FilterBitsBuilder* GetBuilderWithContext(
  1223. const FilterBuildingContext&) const override {
  1224. return nullptr;
  1225. }
  1226. FilterBitsReader* GetFilterBitsReader(
  1227. const Slice& /*contents*/) const override {
  1228. return nullptr;
  1229. }
  1230. };
  1231. class MockCache : public CacheWrapper {
  1232. public:
  1233. static const char* kClassName() { return "MockCache"; }
  1234. const char* Name() const override { return kClassName(); }
  1235. MockCache()
  1236. : CacheWrapper(NewLRUCache(LRUCacheOptions(100, 0, false, 0.0))) {}
  1237. bool IsInstanceOf(const std::string& name) const override {
  1238. return name.find(Name()) == 0;
  1239. }
  1240. };
  1241. static int RegisterLocalObjects(ObjectLibrary& library,
  1242. const std::string& /*arg*/) {
  1243. size_t num_types;
  1244. library.AddFactory<TableFactory>(
  1245. mock::MockTableFactory::kClassName(),
  1246. [](const std::string& /*uri*/, std::unique_ptr<TableFactory>* guard,
  1247. std::string* /* errmsg */) {
  1248. guard->reset(new mock::MockTableFactory());
  1249. return guard->get();
  1250. });
  1251. library.AddFactory<EventListener>(
  1252. OnFileDeletionListener::kClassName(),
  1253. [](const std::string& /*uri*/, std::unique_ptr<EventListener>* guard,
  1254. std::string* /* errmsg */) {
  1255. guard->reset(new OnFileDeletionListener());
  1256. return guard->get();
  1257. });
  1258. library.AddFactory<EventListener>(
  1259. FlushCounterListener::kClassName(),
  1260. [](const std::string& /*uri*/, std::unique_ptr<EventListener>* guard,
  1261. std::string* /* errmsg */) {
  1262. guard->reset(new FlushCounterListener());
  1263. return guard->get();
  1264. });
  1265. // Load any locally defined objects here
  1266. library.AddFactory<const SliceTransform>(
  1267. MockSliceTransform::kClassName(),
  1268. [](const std::string& /*uri*/,
  1269. std::unique_ptr<const SliceTransform>* guard,
  1270. std::string* /* errmsg */) {
  1271. guard->reset(new MockSliceTransform());
  1272. return guard->get();
  1273. });
  1274. library.AddFactory<Statistics>(
  1275. TestStatistics::kClassName(),
  1276. [](const std::string& /*uri*/, std::unique_ptr<Statistics>* guard,
  1277. std::string* /* errmsg */) {
  1278. guard->reset(new TestStatistics());
  1279. return guard->get();
  1280. });
  1281. library.AddFactory<EncryptionProvider>(
  1282. ObjectLibrary::PatternEntry(MockEncryptionProvider::kClassName(), true)
  1283. .AddSuffix("://test"),
  1284. [](const std::string& uri, std::unique_ptr<EncryptionProvider>* guard,
  1285. std::string* /* errmsg */) {
  1286. guard->reset(new MockEncryptionProvider(uri));
  1287. return guard->get();
  1288. });
  1289. library.AddFactory<BlockCipher>(
  1290. "Mock",
  1291. [](const std::string& /*uri*/, std::unique_ptr<BlockCipher>* guard,
  1292. std::string* /* errmsg */) {
  1293. guard->reset(new MockCipher());
  1294. return guard->get();
  1295. });
  1296. library.AddFactory<MemoryAllocator>(
  1297. MockMemoryAllocator::kClassName(),
  1298. [](const std::string& /*uri*/, std::unique_ptr<MemoryAllocator>* guard,
  1299. std::string* /* errmsg */) {
  1300. guard->reset(new MockMemoryAllocator());
  1301. return guard->get();
  1302. });
  1303. library.AddFactory<FlushBlockPolicyFactory>(
  1304. TestFlushBlockPolicyFactory::kClassName(),
  1305. [](const std::string& /*uri*/,
  1306. std::unique_ptr<FlushBlockPolicyFactory>* guard,
  1307. std::string* /* errmsg */) {
  1308. guard->reset(new TestFlushBlockPolicyFactory());
  1309. return guard->get();
  1310. });
  1311. library.AddFactory<SecondaryCache>(
  1312. TestSecondaryCache::kClassName(),
  1313. [](const std::string& /*uri*/, std::unique_ptr<SecondaryCache>* guard,
  1314. std::string* /* errmsg */) {
  1315. guard->reset(new TestSecondaryCache());
  1316. return guard->get();
  1317. });
  1318. library.AddFactory<FileSystem>(
  1319. DummyFileSystem::kClassName(),
  1320. [](const std::string& /*uri*/, std::unique_ptr<FileSystem>* guard,
  1321. std::string* /* errmsg */) {
  1322. guard->reset(new DummyFileSystem(nullptr));
  1323. return guard->get();
  1324. });
  1325. library.AddFactory<SstPartitionerFactory>(
  1326. MockSstPartitionerFactory::kClassName(),
  1327. [](const std::string& /*uri*/,
  1328. std::unique_ptr<SstPartitionerFactory>* guard,
  1329. std::string* /* errmsg */) {
  1330. guard->reset(new MockSstPartitionerFactory());
  1331. return guard->get();
  1332. });
  1333. library.AddFactory<FileChecksumGenFactory>(
  1334. MockFileChecksumGenFactory::kClassName(),
  1335. [](const std::string& /*uri*/,
  1336. std::unique_ptr<FileChecksumGenFactory>* guard,
  1337. std::string* /* errmsg */) {
  1338. guard->reset(new MockFileChecksumGenFactory());
  1339. return guard->get();
  1340. });
  1341. library.AddFactory<TablePropertiesCollectorFactory>(
  1342. MockTablePropertiesCollectorFactory::kClassName(),
  1343. [](const std::string& /*uri*/,
  1344. std::unique_ptr<TablePropertiesCollectorFactory>* guard,
  1345. std::string* /* errmsg */) {
  1346. guard->reset(new MockTablePropertiesCollectorFactory());
  1347. return guard->get();
  1348. });
  1349. library.AddFactory<const FilterPolicy>(
  1350. MockFilterPolicy::kClassName(),
  1351. [](const std::string& /*uri*/, std::unique_ptr<const FilterPolicy>* guard,
  1352. std::string* /* errmsg */) {
  1353. guard->reset(new MockFilterPolicy());
  1354. return guard->get();
  1355. });
  1356. library.AddFactory<Cache>(
  1357. ObjectLibrary::PatternEntry(MockCache::kClassName())
  1358. .AddSeparator("://", /*at_least_one=*/false),
  1359. [](const std::string& /*uri*/, std::unique_ptr<Cache>* guard,
  1360. std::string* /* errmsg */) {
  1361. guard->reset(new MockCache());
  1362. return guard->get();
  1363. });
  1364. return static_cast<int>(library.GetFactoryCount(&num_types));
  1365. }
  1366. } // namespace
  1367. class LoadCustomizableTest : public testing::Test {
  1368. public:
  1369. LoadCustomizableTest() {
  1370. config_options_.ignore_unsupported_options = false;
  1371. config_options_.invoke_prepare_options = false;
  1372. }
  1373. bool RegisterTests(const std::string& arg) {
  1374. config_options_.registry->AddLibrary("custom-tests",
  1375. test::RegisterTestObjects, arg);
  1376. config_options_.registry->AddLibrary("local-tests", RegisterLocalObjects,
  1377. arg);
  1378. return true;
  1379. }
  1380. template <typename T, typename U>
  1381. Status TestCreateStatic(const std::string& name, U** result,
  1382. bool delete_result = false) {
  1383. Status s = T::CreateFromString(config_options_, name, result);
  1384. if (s.ok()) {
  1385. EXPECT_NE(*result, nullptr);
  1386. EXPECT_TRUE(*result != nullptr && (*result)->IsInstanceOf(name));
  1387. }
  1388. if (delete_result) {
  1389. delete *result;
  1390. *result = nullptr;
  1391. }
  1392. return s;
  1393. }
  1394. template <typename T, typename U>
  1395. std::shared_ptr<U> ExpectCreateShared(const std::string& name,
  1396. std::shared_ptr<U>* object) {
  1397. EXPECT_OK(T::CreateFromString(config_options_, name, object));
  1398. EXPECT_NE(object->get(), nullptr);
  1399. EXPECT_TRUE(object->get()->IsInstanceOf(name));
  1400. return *object;
  1401. }
  1402. template <typename T>
  1403. std::shared_ptr<T> ExpectCreateShared(const std::string& name) {
  1404. std::shared_ptr<T> result;
  1405. return ExpectCreateShared<T>(name, &result);
  1406. }
  1407. template <typename T, typename U>
  1408. Status TestExpectedBuiltins(
  1409. const std::string& mock, const std::unordered_set<std::string>& expected,
  1410. std::shared_ptr<U>* object, std::vector<std::string>* failed,
  1411. const std::function<std::vector<std::string>(const std::string&)>& alt =
  1412. nullptr) {
  1413. std::unordered_set<std::string> factories = expected;
  1414. Status s = T::CreateFromString(config_options_, mock, object);
  1415. EXPECT_NOK(s);
  1416. std::vector<std::string> builtins;
  1417. ObjectLibrary::Default()->GetFactoryNames(T::Type(), &builtins);
  1418. factories.insert(builtins.begin(), builtins.end());
  1419. Status result;
  1420. int created = 0;
  1421. for (const auto& name : factories) {
  1422. created++;
  1423. s = T::CreateFromString(config_options_, name, object);
  1424. if (!s.ok() && alt != nullptr) {
  1425. for (const auto& alt_name : alt(name)) {
  1426. s = T::CreateFromString(config_options_, alt_name, object);
  1427. if (s.ok()) {
  1428. break;
  1429. }
  1430. }
  1431. }
  1432. if (!s.ok()) {
  1433. result = s;
  1434. failed->push_back(name);
  1435. } else {
  1436. EXPECT_NE(object->get(), nullptr);
  1437. EXPECT_TRUE(object->get()->IsInstanceOf(name));
  1438. }
  1439. }
  1440. std::vector<std::string> plugins;
  1441. ObjectRegistry::Default()->GetFactoryNames(T::Type(), &plugins);
  1442. if (plugins.size() > builtins.size()) {
  1443. for (const auto& name : plugins) {
  1444. if (factories.find(name) == factories.end()) {
  1445. created++;
  1446. s = T::CreateFromString(config_options_, name, object);
  1447. if (!s.ok() && alt != nullptr) {
  1448. for (const auto& alt_name : alt(name)) {
  1449. s = T::CreateFromString(config_options_, alt_name, object);
  1450. if (s.ok()) {
  1451. break;
  1452. }
  1453. }
  1454. }
  1455. if (!s.ok()) {
  1456. failed->push_back(name);
  1457. if (result.ok()) {
  1458. result = s;
  1459. }
  1460. printf("%s: Failed creating plugin[%s]: %s\n", T::Type(),
  1461. name.c_str(), s.ToString().c_str());
  1462. } else if (object->get() == nullptr ||
  1463. !object->get()->IsInstanceOf(name)) {
  1464. failed->push_back(name);
  1465. printf("%s: Invalid plugin[%s]\n", T::Type(), name.c_str());
  1466. }
  1467. }
  1468. }
  1469. }
  1470. printf("%s: Created %d (expected+builtins+plugins %d+%d+%d) %d Failed\n",
  1471. T::Type(), created, (int)expected.size(),
  1472. (int)(factories.size() - expected.size()),
  1473. (int)(plugins.size() - builtins.size()), (int)failed->size());
  1474. return result;
  1475. }
  1476. template <typename T>
  1477. Status TestSharedBuiltins(const std::string& mock,
  1478. const std::string& expected,
  1479. std::vector<std::string>* failed = nullptr) {
  1480. std::unordered_set<std::string> values;
  1481. if (!expected.empty()) {
  1482. values.insert(expected);
  1483. }
  1484. std::shared_ptr<T> object;
  1485. if (failed != nullptr) {
  1486. return TestExpectedBuiltins<T>(mock, values, &object, failed);
  1487. } else {
  1488. std::vector<std::string> failures;
  1489. Status s = TestExpectedBuiltins<T>(mock, values, &object, &failures);
  1490. EXPECT_EQ(0U, failures.size());
  1491. return s;
  1492. }
  1493. }
  1494. template <typename T, typename U>
  1495. Status TestStaticBuiltins(const std::string& mock, U** object,
  1496. const std::unordered_set<std::string>& expected,
  1497. std::vector<std::string>* failed,
  1498. bool delete_objects = false) {
  1499. std::unordered_set<std::string> factories = expected;
  1500. Status s = TestCreateStatic<T>(mock, object, delete_objects);
  1501. EXPECT_NOK(s);
  1502. std::vector<std::string> builtins;
  1503. ObjectLibrary::Default()->GetFactoryNames(T::Type(), &builtins);
  1504. factories.insert(builtins.begin(), builtins.end());
  1505. int created = 0;
  1506. Status result;
  1507. for (const auto& name : factories) {
  1508. created++;
  1509. s = TestCreateStatic<T>(name, object, delete_objects);
  1510. if (!s.ok()) {
  1511. result = s;
  1512. failed->push_back(name);
  1513. }
  1514. }
  1515. std::vector<std::string> plugins;
  1516. ObjectRegistry::Default()->GetFactoryNames(T::Type(), &plugins);
  1517. if (plugins.size() > builtins.size()) {
  1518. for (const auto& name : plugins) {
  1519. if (factories.find(name) == factories.end()) {
  1520. created++;
  1521. s = T::CreateFromString(config_options_, name, object);
  1522. if (!s.ok() || *object == nullptr ||
  1523. !((*object)->IsInstanceOf(name))) {
  1524. failed->push_back(name);
  1525. if (result.ok() && !s.ok()) {
  1526. result = s;
  1527. }
  1528. printf("%s: Failed creating plugin[%s]: %s\n", T::Type(),
  1529. name.c_str(), s.ToString().c_str());
  1530. }
  1531. if (delete_objects) {
  1532. delete *object;
  1533. *object = nullptr;
  1534. }
  1535. }
  1536. }
  1537. }
  1538. printf("%s: Created %d (expected+builtins+plugins %d+%d+%d) %d Failed\n",
  1539. T::Type(), created, (int)expected.size(),
  1540. (int)(factories.size() - expected.size()),
  1541. (int)(plugins.size() - builtins.size()), (int)failed->size());
  1542. return result;
  1543. }
  1544. protected:
  1545. DBOptions db_opts_;
  1546. ColumnFamilyOptions cf_opts_;
  1547. ConfigOptions config_options_;
  1548. };
  1549. TEST_F(LoadCustomizableTest, LoadTableFactoryTest) {
  1550. ASSERT_OK(
  1551. TestSharedBuiltins<TableFactory>(mock::MockTableFactory::kClassName(),
  1552. TableFactory::kBlockBasedTableName()));
  1553. std::string opts_str = "table_factory=";
  1554. ASSERT_OK(GetColumnFamilyOptionsFromString(
  1555. config_options_, cf_opts_,
  1556. opts_str + TableFactory::kBlockBasedTableName(), &cf_opts_));
  1557. ASSERT_NE(cf_opts_.table_factory.get(), nullptr);
  1558. ASSERT_STREQ(cf_opts_.table_factory->Name(),
  1559. TableFactory::kBlockBasedTableName());
  1560. if (RegisterTests("Test")) {
  1561. ExpectCreateShared<TableFactory>(mock::MockTableFactory::kClassName());
  1562. ASSERT_OK(GetColumnFamilyOptionsFromString(
  1563. config_options_, cf_opts_,
  1564. opts_str + mock::MockTableFactory::kClassName(), &cf_opts_));
  1565. ASSERT_NE(cf_opts_.table_factory.get(), nullptr);
  1566. ASSERT_STREQ(cf_opts_.table_factory->Name(),
  1567. mock::MockTableFactory::kClassName());
  1568. }
  1569. }
  1570. TEST_F(LoadCustomizableTest, LoadFileSystemTest) {
  1571. ASSERT_OK(TestSharedBuiltins<FileSystem>(DummyFileSystem::kClassName(),
  1572. FileSystem::kDefaultName()));
  1573. if (RegisterTests("Test")) {
  1574. auto fs = ExpectCreateShared<FileSystem>(DummyFileSystem::kClassName());
  1575. ASSERT_FALSE(fs->IsInstanceOf(FileSystem::kDefaultName()));
  1576. }
  1577. }
  1578. TEST_F(LoadCustomizableTest, LoadSecondaryCacheTest) {
  1579. ASSERT_OK(
  1580. TestSharedBuiltins<SecondaryCache>(TestSecondaryCache::kClassName(), ""));
  1581. if (RegisterTests("Test")) {
  1582. ExpectCreateShared<SecondaryCache>(TestSecondaryCache::kClassName());
  1583. }
  1584. }
  1585. TEST_F(LoadCustomizableTest, LoadSstPartitionerFactoryTest) {
  1586. ASSERT_OK(TestSharedBuiltins<SstPartitionerFactory>(
  1587. "Mock", SstPartitionerFixedPrefixFactory::kClassName()));
  1588. if (RegisterTests("Test")) {
  1589. ExpectCreateShared<SstPartitionerFactory>("Mock");
  1590. }
  1591. }
  1592. TEST_F(LoadCustomizableTest, LoadChecksumGenFactoryTest) {
  1593. ASSERT_OK(TestSharedBuiltins<FileChecksumGenFactory>("Mock", ""));
  1594. if (RegisterTests("Test")) {
  1595. ExpectCreateShared<FileChecksumGenFactory>("Mock");
  1596. }
  1597. }
  1598. TEST_F(LoadCustomizableTest, LoadTablePropertiesCollectorFactoryTest) {
  1599. ASSERT_OK(TestSharedBuiltins<TablePropertiesCollectorFactory>(
  1600. MockTablePropertiesCollectorFactory::kClassName(), ""));
  1601. if (RegisterTests("Test")) {
  1602. ExpectCreateShared<TablePropertiesCollectorFactory>(
  1603. MockTablePropertiesCollectorFactory::kClassName());
  1604. }
  1605. }
  1606. TEST_F(LoadCustomizableTest, LoadComparatorTest) {
  1607. const Comparator* bytewise = BytewiseComparator();
  1608. const Comparator* reverse = ReverseBytewiseComparator();
  1609. const Comparator* result = nullptr;
  1610. std::unordered_set<std::string> expected = {bytewise->Name(),
  1611. reverse->Name()};
  1612. std::vector<std::string> failures;
  1613. ASSERT_OK(TestStaticBuiltins<Comparator>(
  1614. test::SimpleSuffixReverseComparator::kClassName(), &result, expected,
  1615. &failures));
  1616. if (RegisterTests("Test")) {
  1617. ASSERT_OK(TestCreateStatic<Comparator>(
  1618. test::SimpleSuffixReverseComparator::kClassName(), &result));
  1619. }
  1620. }
  1621. TEST_F(LoadCustomizableTest, LoadSliceTransformFactoryTest) {
  1622. std::shared_ptr<const SliceTransform> result;
  1623. std::vector<std::string> failures;
  1624. std::unordered_set<std::string> expected = {"rocksdb.Noop", "fixed",
  1625. "rocksdb.FixedPrefix", "capped",
  1626. "rocksdb.CappedPrefix"};
  1627. ASSERT_OK(TestExpectedBuiltins<SliceTransform>(
  1628. "Mock", expected, &result, &failures, [](const std::string& name) {
  1629. std::vector<std::string> names = {name + ":22", name + ".22"};
  1630. return names;
  1631. }));
  1632. ASSERT_OK(SliceTransform::CreateFromString(
  1633. config_options_, "rocksdb.FixedPrefix.22", &result));
  1634. ASSERT_NE(result.get(), nullptr);
  1635. ASSERT_TRUE(result->IsInstanceOf("fixed"));
  1636. ASSERT_OK(SliceTransform::CreateFromString(
  1637. config_options_, "rocksdb.CappedPrefix.22", &result));
  1638. ASSERT_NE(result.get(), nullptr);
  1639. ASSERT_TRUE(result->IsInstanceOf("capped"));
  1640. if (RegisterTests("Test")) {
  1641. ExpectCreateShared<SliceTransform>("Mock", &result);
  1642. }
  1643. }
  1644. TEST_F(LoadCustomizableTest, LoadStatisticsTest) {
  1645. ASSERT_OK(TestSharedBuiltins<Statistics>(TestStatistics::kClassName(),
  1646. "BasicStatistics"));
  1647. // Empty will create a default BasicStatistics
  1648. ASSERT_OK(
  1649. Statistics::CreateFromString(config_options_, "", &db_opts_.statistics));
  1650. ASSERT_NE(db_opts_.statistics, nullptr);
  1651. ASSERT_STREQ(db_opts_.statistics->Name(), "BasicStatistics");
  1652. ASSERT_NOK(GetDBOptionsFromString(config_options_, db_opts_,
  1653. "statistics=Test", &db_opts_));
  1654. ASSERT_OK(GetDBOptionsFromString(config_options_, db_opts_,
  1655. "statistics=BasicStatistics", &db_opts_));
  1656. ASSERT_NE(db_opts_.statistics, nullptr);
  1657. ASSERT_STREQ(db_opts_.statistics->Name(), "BasicStatistics");
  1658. if (RegisterTests("test")) {
  1659. auto stats = ExpectCreateShared<Statistics>(TestStatistics::kClassName());
  1660. ASSERT_OK(GetDBOptionsFromString(config_options_, db_opts_,
  1661. "statistics=Test", &db_opts_));
  1662. ASSERT_NE(db_opts_.statistics, nullptr);
  1663. ASSERT_STREQ(db_opts_.statistics->Name(), TestStatistics::kClassName());
  1664. ASSERT_OK(GetDBOptionsFromString(
  1665. config_options_, db_opts_, "statistics={id=Test;inner=BasicStatistics}",
  1666. &db_opts_));
  1667. ASSERT_NE(db_opts_.statistics, nullptr);
  1668. ASSERT_STREQ(db_opts_.statistics->Name(), TestStatistics::kClassName());
  1669. auto* inner = db_opts_.statistics->GetOptions<std::shared_ptr<Statistics>>(
  1670. "StatisticsOptions");
  1671. ASSERT_NE(inner, nullptr);
  1672. ASSERT_NE(inner->get(), nullptr);
  1673. ASSERT_STREQ(inner->get()->Name(), "BasicStatistics");
  1674. ASSERT_OK(Statistics::CreateFromString(
  1675. config_options_, "id=BasicStatistics;inner=Test", &stats));
  1676. ASSERT_NE(stats, nullptr);
  1677. ASSERT_STREQ(stats->Name(), "BasicStatistics");
  1678. inner = stats->GetOptions<std::shared_ptr<Statistics>>("StatisticsOptions");
  1679. ASSERT_NE(inner, nullptr);
  1680. ASSERT_NE(inner->get(), nullptr);
  1681. ASSERT_STREQ(inner->get()->Name(), TestStatistics::kClassName());
  1682. }
  1683. }
  1684. TEST_F(LoadCustomizableTest, LoadMemTableRepFactoryTest) {
  1685. std::unordered_set<std::string> expected = {
  1686. SkipListFactory::kClassName(),
  1687. SkipListFactory::kNickName(),
  1688. };
  1689. std::vector<std::string> failures;
  1690. std::shared_ptr<MemTableRepFactory> factory;
  1691. Status s = TestExpectedBuiltins<MemTableRepFactory>(
  1692. "SpecialSkipListFactory", expected, &factory, &failures);
  1693. // There is a "cuckoo" factory registered that we expect to fail. Ignore the
  1694. // error if this is the one
  1695. if (s.ok() || failures.size() > 1 || failures[0] != "cuckoo") {
  1696. ASSERT_OK(s);
  1697. }
  1698. if (RegisterTests("Test")) {
  1699. ExpectCreateShared<MemTableRepFactory>("SpecialSkipListFactory");
  1700. }
  1701. }
  1702. TEST_F(LoadCustomizableTest, LoadMergeOperatorTest) {
  1703. std::shared_ptr<MergeOperator> result;
  1704. std::vector<std::string> failed;
  1705. std::unordered_set<std::string> expected = {
  1706. "put", "put_v1", "PutOperator", "uint64add", "UInt64AddOperator",
  1707. "max", "MaxOperator",
  1708. };
  1709. expected.insert({
  1710. StringAppendOperator::kClassName(),
  1711. StringAppendOperator::kNickName(),
  1712. StringAppendTESTOperator::kClassName(),
  1713. StringAppendTESTOperator::kNickName(),
  1714. SortList::kClassName(),
  1715. SortList::kNickName(),
  1716. BytesXOROperator::kClassName(),
  1717. BytesXOROperator::kNickName(),
  1718. });
  1719. ASSERT_OK(TestExpectedBuiltins<MergeOperator>("Changling", expected, &result,
  1720. &failed));
  1721. if (RegisterTests("Test")) {
  1722. ExpectCreateShared<MergeOperator>("Changling");
  1723. }
  1724. }
  1725. TEST_F(LoadCustomizableTest, LoadCompactionFilterFactoryTest) {
  1726. ASSERT_OK(TestSharedBuiltins<CompactionFilterFactory>("Changling", ""));
  1727. if (RegisterTests("Test")) {
  1728. ExpectCreateShared<CompactionFilterFactory>("Changling");
  1729. }
  1730. }
  1731. TEST_F(LoadCustomizableTest, LoadCompactionFilterTest) {
  1732. const CompactionFilter* result = nullptr;
  1733. std::vector<std::string> failures;
  1734. ASSERT_OK(TestStaticBuiltins<CompactionFilter>("Changling", &result, {},
  1735. &failures, true));
  1736. if (RegisterTests("Test")) {
  1737. ASSERT_OK(TestCreateStatic<CompactionFilter>("Changling", &result, true));
  1738. }
  1739. }
  1740. TEST_F(LoadCustomizableTest, LoadEventListenerTest) {
  1741. ASSERT_OK(TestSharedBuiltins<EventListener>(
  1742. OnFileDeletionListener::kClassName(), ""));
  1743. if (RegisterTests("Test")) {
  1744. ExpectCreateShared<EventListener>(OnFileDeletionListener::kClassName());
  1745. ExpectCreateShared<EventListener>(FlushCounterListener::kClassName());
  1746. }
  1747. }
  1748. TEST_F(LoadCustomizableTest, LoadEncryptionProviderTest) {
  1749. std::vector<std::string> failures;
  1750. std::shared_ptr<EncryptionProvider> result;
  1751. ASSERT_OK(
  1752. TestExpectedBuiltins<EncryptionProvider>("Mock", {}, &result, &failures));
  1753. if (!failures.empty()) {
  1754. ASSERT_EQ(failures[0], "1://test");
  1755. ASSERT_EQ(failures.size(), 1U);
  1756. }
  1757. result = ExpectCreateShared<EncryptionProvider>("CTR");
  1758. ASSERT_NOK(result->ValidateOptions(db_opts_, cf_opts_));
  1759. ASSERT_OK(EncryptionProvider::CreateFromString(config_options_, "CTR://test",
  1760. &result));
  1761. ASSERT_NE(result, nullptr);
  1762. ASSERT_STREQ(result->Name(), "CTR");
  1763. ASSERT_OK(result->ValidateOptions(db_opts_, cf_opts_));
  1764. if (RegisterTests("Test")) {
  1765. ExpectCreateShared<EncryptionProvider>("Mock");
  1766. ASSERT_OK(EncryptionProvider::CreateFromString(config_options_,
  1767. "Mock://test", &result));
  1768. ASSERT_NE(result, nullptr);
  1769. ASSERT_STREQ(result->Name(), "Mock");
  1770. ASSERT_OK(result->ValidateOptions(db_opts_, cf_opts_));
  1771. }
  1772. }
  1773. TEST_F(LoadCustomizableTest, LoadEncryptionCipherTest) {
  1774. ASSERT_OK(TestSharedBuiltins<BlockCipher>("Mock", "ROT13"));
  1775. if (RegisterTests("Test")) {
  1776. ExpectCreateShared<BlockCipher>("Mock");
  1777. }
  1778. }
  1779. TEST_F(LoadCustomizableTest, LoadSystemClockTest) {
  1780. ASSERT_OK(TestSharedBuiltins<SystemClock>(MockSystemClock::kClassName(),
  1781. SystemClock::kDefaultName()));
  1782. if (RegisterTests("Test")) {
  1783. auto result =
  1784. ExpectCreateShared<SystemClock>(MockSystemClock::kClassName());
  1785. ASSERT_FALSE(result->IsInstanceOf(SystemClock::kDefaultName()));
  1786. }
  1787. }
  1788. TEST_F(LoadCustomizableTest, LoadMemoryAllocatorTest) {
  1789. std::vector<std::string> failures;
  1790. Status s = TestSharedBuiltins<MemoryAllocator>(
  1791. MockMemoryAllocator::kClassName(), DefaultMemoryAllocator::kClassName(),
  1792. &failures);
  1793. if (failures.empty()) {
  1794. ASSERT_OK(s);
  1795. } else {
  1796. ASSERT_NOK(s);
  1797. for (const auto& failure : failures) {
  1798. if (failure == JemallocNodumpAllocator::kClassName()) {
  1799. ASSERT_FALSE(JemallocNodumpAllocator::IsSupported());
  1800. } else if (failure == MemkindKmemAllocator::kClassName()) {
  1801. ASSERT_FALSE(MemkindKmemAllocator::IsSupported());
  1802. } else {
  1803. printf("BYPASSED: %s -- %s\n", failure.c_str(), s.ToString().c_str());
  1804. }
  1805. }
  1806. }
  1807. if (RegisterTests("Test")) {
  1808. ExpectCreateShared<MemoryAllocator>(MockMemoryAllocator::kClassName());
  1809. }
  1810. }
  1811. TEST_F(LoadCustomizableTest, LoadFilterPolicyTest) {
  1812. const std::string kAutoBloom = BloomFilterPolicy::kClassName();
  1813. const std::string kAutoRibbon = RibbonFilterPolicy::kClassName();
  1814. std::shared_ptr<const FilterPolicy> result;
  1815. std::vector<std::string> failures;
  1816. std::unordered_set<std::string> expected = {
  1817. ReadOnlyBuiltinFilterPolicy::kClassName(),
  1818. };
  1819. expected.insert({
  1820. kAutoBloom,
  1821. BloomFilterPolicy::kNickName(),
  1822. kAutoRibbon,
  1823. RibbonFilterPolicy::kNickName(),
  1824. });
  1825. ASSERT_OK(TestExpectedBuiltins<const FilterPolicy>(
  1826. "Mock", expected, &result, &failures, [](const std::string& name) {
  1827. std::vector<std::string> names = {name + ":1.234"};
  1828. return names;
  1829. }));
  1830. ASSERT_OK(FilterPolicy::CreateFromString(
  1831. config_options_, kAutoBloom + ":1.234:false", &result));
  1832. ASSERT_NE(result.get(), nullptr);
  1833. ASSERT_TRUE(result->IsInstanceOf(kAutoBloom));
  1834. ASSERT_OK(FilterPolicy::CreateFromString(
  1835. config_options_, kAutoBloom + ":1.234:false", &result));
  1836. ASSERT_NE(result.get(), nullptr);
  1837. ASSERT_TRUE(result->IsInstanceOf(kAutoBloom));
  1838. ASSERT_OK(FilterPolicy::CreateFromString(config_options_,
  1839. kAutoRibbon + ":1.234:-1", &result));
  1840. ASSERT_NE(result.get(), nullptr);
  1841. ASSERT_TRUE(result->IsInstanceOf(kAutoRibbon));
  1842. ASSERT_OK(FilterPolicy::CreateFromString(config_options_,
  1843. kAutoRibbon + ":1.234:56", &result));
  1844. ASSERT_NE(result.get(), nullptr);
  1845. ASSERT_TRUE(result->IsInstanceOf(kAutoRibbon));
  1846. if (RegisterTests("Test")) {
  1847. ExpectCreateShared<FilterPolicy>(MockFilterPolicy::kClassName(), &result);
  1848. }
  1849. std::shared_ptr<TableFactory> table;
  1850. std::string table_opts = "id=BlockBasedTable; filter_policy=";
  1851. ASSERT_OK(TableFactory::CreateFromString(config_options_,
  1852. table_opts + "nullptr", &table));
  1853. ASSERT_NE(table.get(), nullptr);
  1854. auto bbto = table->GetOptions<BlockBasedTableOptions>();
  1855. ASSERT_NE(bbto, nullptr);
  1856. ASSERT_EQ(bbto->filter_policy.get(), nullptr);
  1857. ASSERT_OK(TableFactory::CreateFromString(
  1858. config_options_, table_opts + ReadOnlyBuiltinFilterPolicy::kClassName(),
  1859. &table));
  1860. bbto = table->GetOptions<BlockBasedTableOptions>();
  1861. ASSERT_NE(bbto, nullptr);
  1862. ASSERT_NE(bbto->filter_policy.get(), nullptr);
  1863. ASSERT_STREQ(bbto->filter_policy->Name(),
  1864. ReadOnlyBuiltinFilterPolicy::kClassName());
  1865. ASSERT_OK(TableFactory::CreateFromString(
  1866. config_options_, table_opts + MockFilterPolicy::kClassName(), &table));
  1867. bbto = table->GetOptions<BlockBasedTableOptions>();
  1868. ASSERT_NE(bbto, nullptr);
  1869. ASSERT_NE(bbto->filter_policy.get(), nullptr);
  1870. ASSERT_TRUE(
  1871. bbto->filter_policy->IsInstanceOf(MockFilterPolicy::kClassName()));
  1872. }
  1873. TEST_F(LoadCustomizableTest, LoadFlushBlockPolicyFactoryTest) {
  1874. std::shared_ptr<FlushBlockPolicyFactory> result;
  1875. std::shared_ptr<TableFactory> table;
  1876. std::vector<std::string> failed;
  1877. std::unordered_set<std::string> expected = {
  1878. FlushBlockBySizePolicyFactory::kClassName(),
  1879. FlushBlockEveryKeyPolicyFactory::kClassName(),
  1880. };
  1881. ASSERT_OK(TestExpectedBuiltins<FlushBlockPolicyFactory>(
  1882. TestFlushBlockPolicyFactory::kClassName(), expected, &result, &failed));
  1883. // An empty policy name creates a BySize policy
  1884. ASSERT_OK(
  1885. FlushBlockPolicyFactory::CreateFromString(config_options_, "", &result));
  1886. ASSERT_NE(result, nullptr);
  1887. ASSERT_STREQ(result->Name(), FlushBlockBySizePolicyFactory::kClassName());
  1888. std::string table_opts = "id=BlockBasedTable; flush_block_policy_factory=";
  1889. ASSERT_OK(TableFactory::CreateFromString(
  1890. config_options_,
  1891. table_opts + FlushBlockEveryKeyPolicyFactory::kClassName(), &table));
  1892. auto bbto = table->GetOptions<BlockBasedTableOptions>();
  1893. ASSERT_NE(bbto, nullptr);
  1894. ASSERT_NE(bbto->flush_block_policy_factory.get(), nullptr);
  1895. ASSERT_STREQ(bbto->flush_block_policy_factory->Name(),
  1896. FlushBlockEveryKeyPolicyFactory::kClassName());
  1897. if (RegisterTests("Test")) {
  1898. ExpectCreateShared<FlushBlockPolicyFactory>(
  1899. TestFlushBlockPolicyFactory::kClassName());
  1900. ASSERT_OK(TableFactory::CreateFromString(
  1901. config_options_, table_opts + TestFlushBlockPolicyFactory::kClassName(),
  1902. &table));
  1903. bbto = table->GetOptions<BlockBasedTableOptions>();
  1904. ASSERT_NE(bbto, nullptr);
  1905. ASSERT_NE(bbto->flush_block_policy_factory.get(), nullptr);
  1906. ASSERT_STREQ(bbto->flush_block_policy_factory->Name(),
  1907. TestFlushBlockPolicyFactory::kClassName());
  1908. }
  1909. }
  1910. TEST_F(LoadCustomizableTest, LoadCacheTest) {
  1911. if (RegisterTests("Test")) {
  1912. std::string uri(MockCache::kClassName());
  1913. uri.append("://");
  1914. auto cache = ExpectCreateShared<Cache>(uri);
  1915. ASSERT_TRUE(cache->IsInstanceOf(MockCache::kClassName()));
  1916. }
  1917. }
  1918. } // namespace ROCKSDB_NAMESPACE
  1919. int main(int argc, char** argv) {
  1920. ::testing::InitGoogleTest(&argc, argv);
  1921. ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
  1922. #ifdef GFLAGS
  1923. ParseCommandLineFlags(&argc, &argv, true);
  1924. #endif // GFLAGS
  1925. return RUN_ALL_TESTS();
  1926. }