testutil.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  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 "test_util/testutil.h"
  10. #include <array>
  11. #include <cctype>
  12. #include <fstream>
  13. #include <sstream>
  14. #include "db/memtable_list.h"
  15. #include "env/composite_env_wrapper.h"
  16. #include "file/random_access_file_reader.h"
  17. #include "file/sequence_file_reader.h"
  18. #include "file/writable_file_writer.h"
  19. #include "port/port.h"
  20. namespace ROCKSDB_NAMESPACE {
  21. namespace test {
  22. const uint32_t kDefaultFormatVersion = BlockBasedTableOptions().format_version;
  23. const uint32_t kLatestFormatVersion = 5u;
  24. Slice RandomString(Random* rnd, int len, std::string* dst) {
  25. dst->resize(len);
  26. for (int i = 0; i < len; i++) {
  27. (*dst)[i] = static_cast<char>(' ' + rnd->Uniform(95)); // ' ' .. '~'
  28. }
  29. return Slice(*dst);
  30. }
  31. extern std::string RandomHumanReadableString(Random* rnd, int len) {
  32. std::string ret;
  33. ret.resize(len);
  34. for (int i = 0; i < len; ++i) {
  35. ret[i] = static_cast<char>('a' + rnd->Uniform(26));
  36. }
  37. return ret;
  38. }
  39. std::string RandomKey(Random* rnd, int len, RandomKeyType type) {
  40. // Make sure to generate a wide variety of characters so we
  41. // test the boundary conditions for short-key optimizations.
  42. static const char kTestChars[] = {'\0', '\1', 'a', 'b', 'c',
  43. 'd', 'e', '\xfd', '\xfe', '\xff'};
  44. std::string result;
  45. for (int i = 0; i < len; i++) {
  46. std::size_t indx = 0;
  47. switch (type) {
  48. case RandomKeyType::RANDOM:
  49. indx = rnd->Uniform(sizeof(kTestChars));
  50. break;
  51. case RandomKeyType::LARGEST:
  52. indx = sizeof(kTestChars) - 1;
  53. break;
  54. case RandomKeyType::MIDDLE:
  55. indx = sizeof(kTestChars) / 2;
  56. break;
  57. case RandomKeyType::SMALLEST:
  58. indx = 0;
  59. break;
  60. }
  61. result += kTestChars[indx];
  62. }
  63. return result;
  64. }
  65. extern Slice CompressibleString(Random* rnd, double compressed_fraction,
  66. int len, std::string* dst) {
  67. int raw = static_cast<int>(len * compressed_fraction);
  68. if (raw < 1) raw = 1;
  69. std::string raw_data;
  70. RandomString(rnd, raw, &raw_data);
  71. // Duplicate the random data until we have filled "len" bytes
  72. dst->clear();
  73. while (dst->size() < (unsigned int)len) {
  74. dst->append(raw_data);
  75. }
  76. dst->resize(len);
  77. return Slice(*dst);
  78. }
  79. namespace {
  80. class Uint64ComparatorImpl : public Comparator {
  81. public:
  82. Uint64ComparatorImpl() {}
  83. const char* Name() const override { return "rocksdb.Uint64Comparator"; }
  84. int Compare(const Slice& a, const Slice& b) const override {
  85. assert(a.size() == sizeof(uint64_t) && b.size() == sizeof(uint64_t));
  86. const uint64_t* left = reinterpret_cast<const uint64_t*>(a.data());
  87. const uint64_t* right = reinterpret_cast<const uint64_t*>(b.data());
  88. uint64_t leftValue;
  89. uint64_t rightValue;
  90. GetUnaligned(left, &leftValue);
  91. GetUnaligned(right, &rightValue);
  92. if (leftValue == rightValue) {
  93. return 0;
  94. } else if (leftValue < rightValue) {
  95. return -1;
  96. } else {
  97. return 1;
  98. }
  99. }
  100. void FindShortestSeparator(std::string* /*start*/,
  101. const Slice& /*limit*/) const override {
  102. return;
  103. }
  104. void FindShortSuccessor(std::string* /*key*/) const override { return; }
  105. };
  106. } // namespace
  107. const Comparator* Uint64Comparator() {
  108. static Uint64ComparatorImpl uint64comp;
  109. return &uint64comp;
  110. }
  111. WritableFileWriter* GetWritableFileWriter(WritableFile* wf,
  112. const std::string& fname) {
  113. std::unique_ptr<WritableFile> file(wf);
  114. return new WritableFileWriter(NewLegacyWritableFileWrapper(std::move(file)),
  115. fname, EnvOptions());
  116. }
  117. RandomAccessFileReader* GetRandomAccessFileReader(RandomAccessFile* raf) {
  118. std::unique_ptr<RandomAccessFile> file(raf);
  119. return new RandomAccessFileReader(NewLegacyRandomAccessFileWrapper(file),
  120. "[test RandomAccessFileReader]");
  121. }
  122. SequentialFileReader* GetSequentialFileReader(SequentialFile* se,
  123. const std::string& fname) {
  124. std::unique_ptr<SequentialFile> file(se);
  125. return new SequentialFileReader(NewLegacySequentialFileWrapper(file), fname);
  126. }
  127. void CorruptKeyType(InternalKey* ikey) {
  128. std::string keystr = ikey->Encode().ToString();
  129. keystr[keystr.size() - 8] = kTypeLogData;
  130. ikey->DecodeFrom(Slice(keystr.data(), keystr.size()));
  131. }
  132. std::string KeyStr(const std::string& user_key, const SequenceNumber& seq,
  133. const ValueType& t, bool corrupt) {
  134. InternalKey k(user_key, seq, t);
  135. if (corrupt) {
  136. CorruptKeyType(&k);
  137. }
  138. return k.Encode().ToString();
  139. }
  140. std::string RandomName(Random* rnd, const size_t len) {
  141. std::stringstream ss;
  142. for (size_t i = 0; i < len; ++i) {
  143. ss << static_cast<char>(rnd->Uniform(26) + 'a');
  144. }
  145. return ss.str();
  146. }
  147. CompressionType RandomCompressionType(Random* rnd) {
  148. auto ret = static_cast<CompressionType>(rnd->Uniform(6));
  149. while (!CompressionTypeSupported(ret)) {
  150. ret = static_cast<CompressionType>((static_cast<int>(ret) + 1) % 6);
  151. }
  152. return ret;
  153. }
  154. void RandomCompressionTypeVector(const size_t count,
  155. std::vector<CompressionType>* types,
  156. Random* rnd) {
  157. types->clear();
  158. for (size_t i = 0; i < count; ++i) {
  159. types->emplace_back(RandomCompressionType(rnd));
  160. }
  161. }
  162. const SliceTransform* RandomSliceTransform(Random* rnd, int pre_defined) {
  163. int random_num = pre_defined >= 0 ? pre_defined : rnd->Uniform(4);
  164. switch (random_num) {
  165. case 0:
  166. return NewFixedPrefixTransform(rnd->Uniform(20) + 1);
  167. case 1:
  168. return NewCappedPrefixTransform(rnd->Uniform(20) + 1);
  169. case 2:
  170. return NewNoopTransform();
  171. default:
  172. return nullptr;
  173. }
  174. }
  175. BlockBasedTableOptions RandomBlockBasedTableOptions(Random* rnd) {
  176. BlockBasedTableOptions opt;
  177. opt.cache_index_and_filter_blocks = rnd->Uniform(2);
  178. opt.pin_l0_filter_and_index_blocks_in_cache = rnd->Uniform(2);
  179. opt.pin_top_level_index_and_filter = rnd->Uniform(2);
  180. using IndexType = BlockBasedTableOptions::IndexType;
  181. const std::array<IndexType, 4> index_types = {
  182. {IndexType::kBinarySearch, IndexType::kHashSearch,
  183. IndexType::kTwoLevelIndexSearch, IndexType::kBinarySearchWithFirstKey}};
  184. opt.index_type =
  185. index_types[rnd->Uniform(static_cast<int>(index_types.size()))];
  186. opt.hash_index_allow_collision = rnd->Uniform(2);
  187. opt.checksum = static_cast<ChecksumType>(rnd->Uniform(3));
  188. opt.block_size = rnd->Uniform(10000000);
  189. opt.block_size_deviation = rnd->Uniform(100);
  190. opt.block_restart_interval = rnd->Uniform(100);
  191. opt.index_block_restart_interval = rnd->Uniform(100);
  192. opt.whole_key_filtering = rnd->Uniform(2);
  193. return opt;
  194. }
  195. TableFactory* RandomTableFactory(Random* rnd, int pre_defined) {
  196. #ifndef ROCKSDB_LITE
  197. int random_num = pre_defined >= 0 ? pre_defined : rnd->Uniform(4);
  198. switch (random_num) {
  199. case 0:
  200. return NewPlainTableFactory();
  201. case 1:
  202. return NewCuckooTableFactory();
  203. default:
  204. return NewBlockBasedTableFactory();
  205. }
  206. #else
  207. (void)rnd;
  208. (void)pre_defined;
  209. return NewBlockBasedTableFactory();
  210. #endif // !ROCKSDB_LITE
  211. }
  212. MergeOperator* RandomMergeOperator(Random* rnd) {
  213. return new ChanglingMergeOperator(RandomName(rnd, 10));
  214. }
  215. CompactionFilter* RandomCompactionFilter(Random* rnd) {
  216. return new ChanglingCompactionFilter(RandomName(rnd, 10));
  217. }
  218. CompactionFilterFactory* RandomCompactionFilterFactory(Random* rnd) {
  219. return new ChanglingCompactionFilterFactory(RandomName(rnd, 10));
  220. }
  221. void RandomInitDBOptions(DBOptions* db_opt, Random* rnd) {
  222. // boolean options
  223. db_opt->advise_random_on_open = rnd->Uniform(2);
  224. db_opt->allow_mmap_reads = rnd->Uniform(2);
  225. db_opt->allow_mmap_writes = rnd->Uniform(2);
  226. db_opt->use_direct_reads = rnd->Uniform(2);
  227. db_opt->use_direct_io_for_flush_and_compaction = rnd->Uniform(2);
  228. db_opt->create_if_missing = rnd->Uniform(2);
  229. db_opt->create_missing_column_families = rnd->Uniform(2);
  230. db_opt->enable_thread_tracking = rnd->Uniform(2);
  231. db_opt->error_if_exists = rnd->Uniform(2);
  232. db_opt->is_fd_close_on_exec = rnd->Uniform(2);
  233. db_opt->paranoid_checks = rnd->Uniform(2);
  234. db_opt->skip_log_error_on_recovery = rnd->Uniform(2);
  235. db_opt->skip_stats_update_on_db_open = rnd->Uniform(2);
  236. db_opt->skip_checking_sst_file_sizes_on_db_open = rnd->Uniform(2);
  237. db_opt->use_adaptive_mutex = rnd->Uniform(2);
  238. db_opt->use_fsync = rnd->Uniform(2);
  239. db_opt->recycle_log_file_num = rnd->Uniform(2);
  240. db_opt->avoid_flush_during_recovery = rnd->Uniform(2);
  241. db_opt->avoid_flush_during_shutdown = rnd->Uniform(2);
  242. // int options
  243. db_opt->max_background_compactions = rnd->Uniform(100);
  244. db_opt->max_background_flushes = rnd->Uniform(100);
  245. db_opt->max_file_opening_threads = rnd->Uniform(100);
  246. db_opt->max_open_files = rnd->Uniform(100);
  247. db_opt->table_cache_numshardbits = rnd->Uniform(100);
  248. // size_t options
  249. db_opt->db_write_buffer_size = rnd->Uniform(10000);
  250. db_opt->keep_log_file_num = rnd->Uniform(10000);
  251. db_opt->log_file_time_to_roll = rnd->Uniform(10000);
  252. db_opt->manifest_preallocation_size = rnd->Uniform(10000);
  253. db_opt->max_log_file_size = rnd->Uniform(10000);
  254. // std::string options
  255. db_opt->db_log_dir = "path/to/db_log_dir";
  256. db_opt->wal_dir = "path/to/wal_dir";
  257. // uint32_t options
  258. db_opt->max_subcompactions = rnd->Uniform(100000);
  259. // uint64_t options
  260. static const uint64_t uint_max = static_cast<uint64_t>(UINT_MAX);
  261. db_opt->WAL_size_limit_MB = uint_max + rnd->Uniform(100000);
  262. db_opt->WAL_ttl_seconds = uint_max + rnd->Uniform(100000);
  263. db_opt->bytes_per_sync = uint_max + rnd->Uniform(100000);
  264. db_opt->delayed_write_rate = uint_max + rnd->Uniform(100000);
  265. db_opt->delete_obsolete_files_period_micros = uint_max + rnd->Uniform(100000);
  266. db_opt->max_manifest_file_size = uint_max + rnd->Uniform(100000);
  267. db_opt->max_total_wal_size = uint_max + rnd->Uniform(100000);
  268. db_opt->wal_bytes_per_sync = uint_max + rnd->Uniform(100000);
  269. // unsigned int options
  270. db_opt->stats_dump_period_sec = rnd->Uniform(100000);
  271. }
  272. void RandomInitCFOptions(ColumnFamilyOptions* cf_opt, DBOptions& db_options,
  273. Random* rnd) {
  274. cf_opt->compaction_style = (CompactionStyle)(rnd->Uniform(4));
  275. // boolean options
  276. cf_opt->report_bg_io_stats = rnd->Uniform(2);
  277. cf_opt->disable_auto_compactions = rnd->Uniform(2);
  278. cf_opt->inplace_update_support = rnd->Uniform(2);
  279. cf_opt->level_compaction_dynamic_level_bytes = rnd->Uniform(2);
  280. cf_opt->optimize_filters_for_hits = rnd->Uniform(2);
  281. cf_opt->paranoid_file_checks = rnd->Uniform(2);
  282. cf_opt->purge_redundant_kvs_while_flush = rnd->Uniform(2);
  283. cf_opt->force_consistency_checks = rnd->Uniform(2);
  284. cf_opt->compaction_options_fifo.allow_compaction = rnd->Uniform(2);
  285. cf_opt->memtable_whole_key_filtering = rnd->Uniform(2);
  286. // double options
  287. cf_opt->hard_rate_limit = static_cast<double>(rnd->Uniform(10000)) / 13;
  288. cf_opt->soft_rate_limit = static_cast<double>(rnd->Uniform(10000)) / 13;
  289. cf_opt->memtable_prefix_bloom_size_ratio =
  290. static_cast<double>(rnd->Uniform(10000)) / 20000.0;
  291. // int options
  292. cf_opt->level0_file_num_compaction_trigger = rnd->Uniform(100);
  293. cf_opt->level0_slowdown_writes_trigger = rnd->Uniform(100);
  294. cf_opt->level0_stop_writes_trigger = rnd->Uniform(100);
  295. cf_opt->max_bytes_for_level_multiplier = rnd->Uniform(100);
  296. cf_opt->max_mem_compaction_level = rnd->Uniform(100);
  297. cf_opt->max_write_buffer_number = rnd->Uniform(100);
  298. cf_opt->max_write_buffer_number_to_maintain = rnd->Uniform(100);
  299. cf_opt->max_write_buffer_size_to_maintain = rnd->Uniform(10000);
  300. cf_opt->min_write_buffer_number_to_merge = rnd->Uniform(100);
  301. cf_opt->num_levels = rnd->Uniform(100);
  302. cf_opt->target_file_size_multiplier = rnd->Uniform(100);
  303. // vector int options
  304. cf_opt->max_bytes_for_level_multiplier_additional.resize(cf_opt->num_levels);
  305. for (int i = 0; i < cf_opt->num_levels; i++) {
  306. cf_opt->max_bytes_for_level_multiplier_additional[i] = rnd->Uniform(100);
  307. }
  308. // size_t options
  309. cf_opt->arena_block_size = rnd->Uniform(10000);
  310. cf_opt->inplace_update_num_locks = rnd->Uniform(10000);
  311. cf_opt->max_successive_merges = rnd->Uniform(10000);
  312. cf_opt->memtable_huge_page_size = rnd->Uniform(10000);
  313. cf_opt->write_buffer_size = rnd->Uniform(10000);
  314. // uint32_t options
  315. cf_opt->bloom_locality = rnd->Uniform(10000);
  316. cf_opt->max_bytes_for_level_base = rnd->Uniform(10000);
  317. // uint64_t options
  318. static const uint64_t uint_max = static_cast<uint64_t>(UINT_MAX);
  319. cf_opt->ttl =
  320. db_options.max_open_files == -1 ? uint_max + rnd->Uniform(10000) : 0;
  321. cf_opt->periodic_compaction_seconds =
  322. db_options.max_open_files == -1 ? uint_max + rnd->Uniform(10000) : 0;
  323. cf_opt->max_sequential_skip_in_iterations = uint_max + rnd->Uniform(10000);
  324. cf_opt->target_file_size_base = uint_max + rnd->Uniform(10000);
  325. cf_opt->max_compaction_bytes =
  326. cf_opt->target_file_size_base * rnd->Uniform(100);
  327. cf_opt->compaction_options_fifo.max_table_files_size =
  328. uint_max + rnd->Uniform(10000);
  329. // unsigned int options
  330. cf_opt->rate_limit_delay_max_milliseconds = rnd->Uniform(10000);
  331. // pointer typed options
  332. cf_opt->prefix_extractor.reset(RandomSliceTransform(rnd));
  333. cf_opt->table_factory.reset(RandomTableFactory(rnd));
  334. cf_opt->merge_operator.reset(RandomMergeOperator(rnd));
  335. if (cf_opt->compaction_filter) {
  336. delete cf_opt->compaction_filter;
  337. }
  338. cf_opt->compaction_filter = RandomCompactionFilter(rnd);
  339. cf_opt->compaction_filter_factory.reset(RandomCompactionFilterFactory(rnd));
  340. // custom typed options
  341. cf_opt->compression = RandomCompressionType(rnd);
  342. RandomCompressionTypeVector(cf_opt->num_levels,
  343. &cf_opt->compression_per_level, rnd);
  344. }
  345. Status DestroyDir(Env* env, const std::string& dir) {
  346. Status s;
  347. if (env->FileExists(dir).IsNotFound()) {
  348. return s;
  349. }
  350. std::vector<std::string> files_in_dir;
  351. s = env->GetChildren(dir, &files_in_dir);
  352. if (s.ok()) {
  353. for (auto& file_in_dir : files_in_dir) {
  354. if (file_in_dir == "." || file_in_dir == "..") {
  355. continue;
  356. }
  357. s = env->DeleteFile(dir + "/" + file_in_dir);
  358. if (!s.ok()) {
  359. break;
  360. }
  361. }
  362. }
  363. if (s.ok()) {
  364. s = env->DeleteDir(dir);
  365. }
  366. return s;
  367. }
  368. bool IsDirectIOSupported(Env* env, const std::string& dir) {
  369. EnvOptions env_options;
  370. env_options.use_mmap_writes = false;
  371. env_options.use_direct_writes = true;
  372. std::string tmp = TempFileName(dir, 999);
  373. Status s;
  374. {
  375. std::unique_ptr<WritableFile> file;
  376. s = env->NewWritableFile(tmp, &file, env_options);
  377. }
  378. if (s.ok()) {
  379. s = env->DeleteFile(tmp);
  380. }
  381. return s.ok();
  382. }
  383. size_t GetLinesCount(const std::string& fname, const std::string& pattern) {
  384. std::stringstream ssbuf;
  385. std::string line;
  386. size_t count = 0;
  387. std::ifstream inFile(fname.c_str());
  388. ssbuf << inFile.rdbuf();
  389. while (getline(ssbuf, line)) {
  390. if (line.find(pattern) != std::string::npos) {
  391. count++;
  392. }
  393. }
  394. return count;
  395. }
  396. } // namespace test
  397. } // namespace ROCKSDB_NAMESPACE