db_sanity_test.cc 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  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. #include <cstdio>
  6. #include <cstdlib>
  7. #include <vector>
  8. #include <memory>
  9. #include "rocksdb/db.h"
  10. #include "rocksdb/options.h"
  11. #include "rocksdb/env.h"
  12. #include "rocksdb/slice.h"
  13. #include "rocksdb/status.h"
  14. #include "rocksdb/comparator.h"
  15. #include "rocksdb/table.h"
  16. #include "rocksdb/slice_transform.h"
  17. #include "rocksdb/filter_policy.h"
  18. #include "port/port.h"
  19. #include "util/string_util.h"
  20. namespace ROCKSDB_NAMESPACE {
  21. class SanityTest {
  22. public:
  23. explicit SanityTest(const std::string& path)
  24. : env_(Env::Default()), path_(path) {
  25. env_->CreateDirIfMissing(path);
  26. }
  27. virtual ~SanityTest() {}
  28. virtual std::string Name() const = 0;
  29. virtual Options GetOptions() const = 0;
  30. Status Create() {
  31. Options options = GetOptions();
  32. options.create_if_missing = true;
  33. std::string dbname = path_ + Name();
  34. DestroyDB(dbname, options);
  35. DB* db = nullptr;
  36. Status s = DB::Open(options, dbname, &db);
  37. std::unique_ptr<DB> db_guard(db);
  38. if (!s.ok()) {
  39. return s;
  40. }
  41. for (int i = 0; i < 1000000; ++i) {
  42. std::string k = "key" + ToString(i);
  43. std::string v = "value" + ToString(i);
  44. s = db->Put(WriteOptions(), Slice(k), Slice(v));
  45. if (!s.ok()) {
  46. return s;
  47. }
  48. }
  49. return db->Flush(FlushOptions());
  50. }
  51. Status Verify() {
  52. DB* db = nullptr;
  53. std::string dbname = path_ + Name();
  54. Status s = DB::Open(GetOptions(), dbname, &db);
  55. std::unique_ptr<DB> db_guard(db);
  56. if (!s.ok()) {
  57. return s;
  58. }
  59. for (int i = 0; i < 1000000; ++i) {
  60. std::string k = "key" + ToString(i);
  61. std::string v = "value" + ToString(i);
  62. std::string result;
  63. s = db->Get(ReadOptions(), Slice(k), &result);
  64. if (!s.ok()) {
  65. return s;
  66. }
  67. if (result != v) {
  68. return Status::Corruption("Unexpected value for key " + k);
  69. }
  70. }
  71. return Status::OK();
  72. }
  73. private:
  74. Env* env_;
  75. std::string const path_;
  76. };
  77. class SanityTestBasic : public SanityTest {
  78. public:
  79. explicit SanityTestBasic(const std::string& path) : SanityTest(path) {}
  80. virtual Options GetOptions() const override {
  81. Options options;
  82. options.create_if_missing = true;
  83. return options;
  84. }
  85. virtual std::string Name() const override { return "Basic"; }
  86. };
  87. class SanityTestSpecialComparator : public SanityTest {
  88. public:
  89. explicit SanityTestSpecialComparator(const std::string& path)
  90. : SanityTest(path) {
  91. options_.comparator = new NewComparator();
  92. }
  93. ~SanityTestSpecialComparator() { delete options_.comparator; }
  94. virtual Options GetOptions() const override { return options_; }
  95. virtual std::string Name() const override { return "SpecialComparator"; }
  96. private:
  97. class NewComparator : public Comparator {
  98. public:
  99. virtual const char* Name() const override {
  100. return "rocksdb.NewComparator";
  101. }
  102. virtual int Compare(const Slice& a, const Slice& b) const override {
  103. return BytewiseComparator()->Compare(a, b);
  104. }
  105. virtual void FindShortestSeparator(std::string* s,
  106. const Slice& l) const override {
  107. BytewiseComparator()->FindShortestSeparator(s, l);
  108. }
  109. virtual void FindShortSuccessor(std::string* key) const override {
  110. BytewiseComparator()->FindShortSuccessor(key);
  111. }
  112. };
  113. Options options_;
  114. };
  115. class SanityTestZlibCompression : public SanityTest {
  116. public:
  117. explicit SanityTestZlibCompression(const std::string& path)
  118. : SanityTest(path) {
  119. options_.compression = kZlibCompression;
  120. }
  121. virtual Options GetOptions() const override { return options_; }
  122. virtual std::string Name() const override { return "ZlibCompression"; }
  123. private:
  124. Options options_;
  125. };
  126. class SanityTestZlibCompressionVersion2 : public SanityTest {
  127. public:
  128. explicit SanityTestZlibCompressionVersion2(const std::string& path)
  129. : SanityTest(path) {
  130. options_.compression = kZlibCompression;
  131. BlockBasedTableOptions table_options;
  132. #if ROCKSDB_MAJOR > 3 || (ROCKSDB_MAJOR == 3 && ROCKSDB_MINOR >= 10)
  133. table_options.format_version = 2;
  134. #endif
  135. options_.table_factory.reset(NewBlockBasedTableFactory(table_options));
  136. }
  137. virtual Options GetOptions() const override { return options_; }
  138. virtual std::string Name() const override {
  139. return "ZlibCompressionVersion2";
  140. }
  141. private:
  142. Options options_;
  143. };
  144. class SanityTestLZ4Compression : public SanityTest {
  145. public:
  146. explicit SanityTestLZ4Compression(const std::string& path)
  147. : SanityTest(path) {
  148. options_.compression = kLZ4Compression;
  149. }
  150. virtual Options GetOptions() const override { return options_; }
  151. virtual std::string Name() const override { return "LZ4Compression"; }
  152. private:
  153. Options options_;
  154. };
  155. class SanityTestLZ4HCCompression : public SanityTest {
  156. public:
  157. explicit SanityTestLZ4HCCompression(const std::string& path)
  158. : SanityTest(path) {
  159. options_.compression = kLZ4HCCompression;
  160. }
  161. virtual Options GetOptions() const override { return options_; }
  162. virtual std::string Name() const override { return "LZ4HCCompression"; }
  163. private:
  164. Options options_;
  165. };
  166. class SanityTestZSTDCompression : public SanityTest {
  167. public:
  168. explicit SanityTestZSTDCompression(const std::string& path)
  169. : SanityTest(path) {
  170. options_.compression = kZSTD;
  171. }
  172. virtual Options GetOptions() const override { return options_; }
  173. virtual std::string Name() const override { return "ZSTDCompression"; }
  174. private:
  175. Options options_;
  176. };
  177. #ifndef ROCKSDB_LITE
  178. class SanityTestPlainTableFactory : public SanityTest {
  179. public:
  180. explicit SanityTestPlainTableFactory(const std::string& path)
  181. : SanityTest(path) {
  182. options_.table_factory.reset(NewPlainTableFactory());
  183. options_.prefix_extractor.reset(NewFixedPrefixTransform(2));
  184. options_.allow_mmap_reads = true;
  185. }
  186. ~SanityTestPlainTableFactory() {}
  187. virtual Options GetOptions() const override { return options_; }
  188. virtual std::string Name() const override { return "PlainTable"; }
  189. private:
  190. Options options_;
  191. };
  192. #endif // ROCKSDB_LITE
  193. class SanityTestBloomFilter : public SanityTest {
  194. public:
  195. explicit SanityTestBloomFilter(const std::string& path) : SanityTest(path) {
  196. BlockBasedTableOptions table_options;
  197. table_options.filter_policy.reset(NewBloomFilterPolicy(10));
  198. options_.table_factory.reset(NewBlockBasedTableFactory(table_options));
  199. }
  200. ~SanityTestBloomFilter() {}
  201. virtual Options GetOptions() const override { return options_; }
  202. virtual std::string Name() const override { return "BloomFilter"; }
  203. private:
  204. Options options_;
  205. };
  206. namespace {
  207. bool RunSanityTests(const std::string& command, const std::string& path) {
  208. bool result = true;
  209. // Suppress false positive clang static anaylzer warnings.
  210. #ifndef __clang_analyzer__
  211. std::vector<SanityTest*> sanity_tests = {
  212. new SanityTestBasic(path),
  213. new SanityTestSpecialComparator(path),
  214. new SanityTestZlibCompression(path),
  215. new SanityTestZlibCompressionVersion2(path),
  216. new SanityTestLZ4Compression(path),
  217. new SanityTestLZ4HCCompression(path),
  218. new SanityTestZSTDCompression(path),
  219. #ifndef ROCKSDB_LITE
  220. new SanityTestPlainTableFactory(path),
  221. #endif // ROCKSDB_LITE
  222. new SanityTestBloomFilter(path)};
  223. if (command == "create") {
  224. fprintf(stderr, "Creating...\n");
  225. } else {
  226. fprintf(stderr, "Verifying...\n");
  227. }
  228. for (auto sanity_test : sanity_tests) {
  229. Status s;
  230. fprintf(stderr, "%s -- ", sanity_test->Name().c_str());
  231. if (command == "create") {
  232. s = sanity_test->Create();
  233. } else {
  234. assert(command == "verify");
  235. s = sanity_test->Verify();
  236. }
  237. fprintf(stderr, "%s\n", s.ToString().c_str());
  238. if (!s.ok()) {
  239. fprintf(stderr, "FAIL\n");
  240. result = false;
  241. }
  242. delete sanity_test;
  243. }
  244. #endif // __clang_analyzer__
  245. return result;
  246. }
  247. } // namespace
  248. } // namespace ROCKSDB_NAMESPACE
  249. int main(int argc, char** argv) {
  250. std::string path, command;
  251. bool ok = (argc == 3);
  252. if (ok) {
  253. path = std::string(argv[1]);
  254. command = std::string(argv[2]);
  255. ok = (command == "create" || command == "verify");
  256. }
  257. if (!ok) {
  258. fprintf(stderr, "Usage: %s <path> [create|verify] \n", argv[0]);
  259. exit(1);
  260. }
  261. if (path.back() != '/') {
  262. path += "/";
  263. }
  264. bool sanity_ok = ROCKSDB_NAMESPACE::RunSanityTests(command, path);
  265. return sanity_ok ? 0 : 1;
  266. }