]> git.proxmox.com Git - ceph.git/blame - ceph/src/rocksdb/tools/ldb_cmd_test.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / rocksdb / tools / ldb_cmd_test.cc
CommitLineData
7c673cae 1// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
11fdf7f2
TL
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).
7c673cae
FG
5//
6#ifndef ROCKSDB_LITE
7
8#include "rocksdb/utilities/ldb_cmd.h"
20effc67 9
f67539c2
TL
10#include "db/version_edit.h"
11#include "db/version_set.h"
12#include "env/composite_env_wrapper.h"
13#include "file/filename.h"
14#include "port/stack_trace.h"
15#include "rocksdb/file_checksum.h"
16#include "test_util/sync_point.h"
17#include "test_util/testharness.h"
18#include "test_util/testutil.h"
19#include "util/file_checksum_helper.h"
20effc67 20#include "util/random.h"
7c673cae
FG
21
22using std::string;
23using std::vector;
24using std::map;
25
f67539c2 26namespace ROCKSDB_NAMESPACE {
494da23a 27
f67539c2
TL
28class LdbCmdTest : public testing::Test {
29 public:
30 LdbCmdTest() : testing::Test() {}
31
32 Env* TryLoadCustomOrDefaultEnv() {
33 const char* test_env_uri = getenv("TEST_ENV_URI");
34 if (!test_env_uri) {
35 return Env::Default();
36 }
37 Env* env = Env::Default();
38 Env::LoadEnv(test_env_uri, &env, &env_guard_);
39 return env;
40 }
41
42 private:
43 std::shared_ptr<Env> env_guard_;
44};
7c673cae 45
20effc67
TL
46TEST_F(LdbCmdTest, HelpAndVersion) {
47 Options o;
48 o.env = TryLoadCustomOrDefaultEnv();
49 LDBOptions lo;
50 static const char* help[] = {"./ldb", "--help"};
51 ASSERT_EQ(0, LDBCommandRunner::RunCommand(2, help, o, lo, nullptr));
52 static const char* version[] = {"./ldb", "--version"};
53 ASSERT_EQ(0, LDBCommandRunner::RunCommand(2, version, o, lo, nullptr));
54 static const char* bad[] = {"./ldb", "--not_an_option"};
55 ASSERT_NE(0, LDBCommandRunner::RunCommand(2, bad, o, lo, nullptr));
56}
57
7c673cae
FG
58TEST_F(LdbCmdTest, HexToString) {
59 // map input to expected outputs.
60 // odd number of "hex" half bytes doesn't make sense
61 map<string, vector<int>> inputMap = {
62 {"0x07", {7}}, {"0x5050", {80, 80}}, {"0xFF", {-1}},
63 {"0x1234", {18, 52}}, {"0xaaAbAC", {-86, -85, -84}}, {"0x1203", {18, 3}},
64 };
65
66 for (const auto& inPair : inputMap) {
f67539c2 67 auto actual = ROCKSDB_NAMESPACE::LDBCommand::HexToString(inPair.first);
7c673cae
FG
68 auto expected = inPair.second;
69 for (unsigned int i = 0; i < actual.length(); i++) {
70 EXPECT_EQ(expected[i], static_cast<int>((signed char) actual[i]));
71 }
f67539c2 72 auto reverse = ROCKSDB_NAMESPACE::LDBCommand::StringToHex(actual);
7c673cae
FG
73 EXPECT_STRCASEEQ(inPair.first.c_str(), reverse.c_str());
74 }
75}
76
77TEST_F(LdbCmdTest, HexToStringBadInputs) {
78 const vector<string> badInputs = {
79 "0xZZ", "123", "0xx5", "0x111G", "0x123", "Ox12", "0xT", "0x1Q1",
80 };
20effc67 81 for (const auto& badInput : badInputs) {
7c673cae 82 try {
f67539c2 83 ROCKSDB_NAMESPACE::LDBCommand::HexToString(badInput);
7c673cae
FG
84 std::cerr << "Should fail on bad hex value: " << badInput << "\n";
85 FAIL();
86 } catch (...) {
87 }
88 }
89}
90
494da23a 91TEST_F(LdbCmdTest, MemEnv) {
f67539c2
TL
92 Env* base_env = TryLoadCustomOrDefaultEnv();
93 std::unique_ptr<Env> env(NewMemEnv(base_env));
494da23a
TL
94 Options opts;
95 opts.env = env.get();
96 opts.create_if_missing = true;
97
98 DB* db = nullptr;
20effc67 99 std::string dbname = test::PerThreadDBPath(env.get(), "ldb_cmd_test");
494da23a
TL
100 ASSERT_OK(DB::Open(opts, dbname, &db));
101
102 WriteOptions wopts;
103 for (int i = 0; i < 100; i++) {
104 char buf[16];
105 snprintf(buf, sizeof(buf), "%08d", i);
106 ASSERT_OK(db->Put(wopts, buf, buf));
107 }
108 FlushOptions fopts;
109 fopts.wait = true;
110 ASSERT_OK(db->Flush(fopts));
111
112 delete db;
113
114 char arg1[] = "./ldb";
115 char arg2[1024];
116 snprintf(arg2, sizeof(arg2), "--db=%s", dbname.c_str());
117 char arg3[] = "dump_live_files";
118 char* argv[] = {arg1, arg2, arg3};
119
f67539c2
TL
120 ASSERT_EQ(0,
121 LDBCommandRunner::RunCommand(3, argv, opts, LDBOptions(), nullptr));
122}
123
124class FileChecksumTestHelper {
125 private:
126 Options options_;
127 DB* db_;
128 std::string dbname_;
129
130 Status VerifyChecksum(LiveFileMetaData& file_meta) {
131 std::string cur_checksum;
132 std::string checksum_func_name;
133
134 Status s;
135 EnvOptions soptions;
136 std::unique_ptr<SequentialFile> file_reader;
137 std::string file_path = dbname_ + "/" + file_meta.name;
138 s = options_.env->NewSequentialFile(file_path, &file_reader, soptions);
139 if (!s.ok()) {
140 return s;
141 }
142 std::unique_ptr<char[]> scratch(new char[2048]);
f67539c2 143 Slice result;
20effc67
TL
144 FileChecksumGenFactory* file_checksum_gen_factory =
145 options_.file_checksum_gen_factory.get();
146 if (file_checksum_gen_factory == nullptr) {
f67539c2
TL
147 cur_checksum = kUnknownFileChecksum;
148 checksum_func_name = kUnknownFileChecksumFuncName;
149 } else {
20effc67
TL
150 FileChecksumGenContext gen_context;
151 gen_context.file_name = file_meta.name;
152 std::unique_ptr<FileChecksumGenerator> file_checksum_gen =
153 file_checksum_gen_factory->CreateFileChecksumGenerator(gen_context);
154 checksum_func_name = file_checksum_gen->Name();
f67539c2
TL
155 s = file_reader->Read(2048, &result, scratch.get());
156 if (!s.ok()) {
157 return s;
158 }
159 while (result.size() != 0) {
20effc67 160 file_checksum_gen->Update(scratch.get(), result.size());
f67539c2
TL
161 s = file_reader->Read(2048, &result, scratch.get());
162 if (!s.ok()) {
163 return s;
164 }
165 }
20effc67
TL
166 file_checksum_gen->Finalize();
167 cur_checksum = file_checksum_gen->GetChecksum();
f67539c2
TL
168 }
169
170 std::string stored_checksum = file_meta.file_checksum;
171 std::string stored_checksum_func_name = file_meta.file_checksum_func_name;
172 if ((cur_checksum != stored_checksum) ||
173 (checksum_func_name != stored_checksum_func_name)) {
174 return Status::Corruption(
175 "Checksum does not match! The file: " + file_meta.name +
176 ", checksum name: " + stored_checksum_func_name + " and checksum " +
177 stored_checksum + ". However, expected checksum name: " +
178 checksum_func_name + " and checksum " + cur_checksum);
179 }
180 return Status::OK();
181 }
182
183 public:
184 FileChecksumTestHelper(Options& options, DB* db, std::string db_name)
185 : options_(options), db_(db), dbname_(db_name) {}
186 ~FileChecksumTestHelper() {}
187
188 // Verify the checksum information in Manifest.
189 Status VerifyChecksumInManifest(
190 const std::vector<LiveFileMetaData>& live_files) {
191 // Step 1: verify if the dbname_ is correct
192 if (dbname_[dbname_.length() - 1] != '/') {
193 dbname_.append("/");
194 }
195
196 // Step 2, get the the checksum information by recovering the VersionSet
197 // from Manifest.
198 std::unique_ptr<FileChecksumList> checksum_list(NewFileChecksumList());
199 EnvOptions sopt;
200 std::shared_ptr<Cache> tc(NewLRUCache(options_.max_open_files - 10,
201 options_.table_cache_numshardbits));
202 options_.db_paths.emplace_back(dbname_, 0);
203 options_.num_levels = 64;
204 WriteController wc(options_.delayed_write_rate);
205 WriteBufferManager wb(options_.db_write_buffer_size);
206 ImmutableDBOptions immutable_db_options(options_);
207 VersionSet versions(dbname_, &immutable_db_options, sopt, tc.get(), &wb,
20effc67 208 &wc, nullptr, nullptr);
f67539c2
TL
209 std::vector<std::string> cf_name_list;
210 Status s;
211 s = versions.ListColumnFamilies(&cf_name_list, dbname_,
20effc67 212 immutable_db_options.fs.get());
f67539c2
TL
213 if (s.ok()) {
214 std::vector<ColumnFamilyDescriptor> cf_list;
215 for (const auto& name : cf_name_list) {
216 fprintf(stdout, "cf_name: %s", name.c_str());
217 cf_list.emplace_back(name, ColumnFamilyOptions(options_));
218 }
219 s = versions.Recover(cf_list, true);
220 }
221 if (s.ok()) {
222 s = versions.GetLiveFilesChecksumInfo(checksum_list.get());
223 }
224 if (!s.ok()) {
225 return s;
226 }
227
228 // Step 3 verify the checksum
229 if (live_files.size() != checksum_list->size()) {
230 return Status::Corruption("The number of files does not match!");
231 }
232 for (size_t i = 0; i < live_files.size(); i++) {
233 std::string stored_checksum = "";
234 std::string stored_func_name = "";
235 s = checksum_list->SearchOneFileChecksum(
236 live_files[i].file_number, &stored_checksum, &stored_func_name);
237 if (s.IsNotFound()) {
238 return s;
239 }
240 if (live_files[i].file_checksum != stored_checksum ||
241 live_files[i].file_checksum_func_name != stored_func_name) {
242 return Status::Corruption(
243 "Checksum does not match! The file: " +
244 ToString(live_files[i].file_number) +
245 ". In Manifest, checksum name: " + stored_func_name +
246 " and checksum " + stored_checksum +
247 ". However, expected checksum name: " +
248 live_files[i].file_checksum_func_name + " and checksum " +
249 live_files[i].file_checksum);
250 }
251 }
252 return Status::OK();
253 }
254
255 // Verify the checksum of each file by recalculting the checksum and
256 // comparing it with the one being generated when a SST file is created.
257 Status VerifyEachFileChecksum() {
258 assert(db_ != nullptr);
259 std::vector<LiveFileMetaData> live_files;
260 db_->GetLiveFilesMetaData(&live_files);
261 for (auto a_file : live_files) {
262 Status cs = VerifyChecksum(a_file);
263 if (!cs.ok()) {
264 return cs;
265 }
266 }
267 return Status::OK();
268 }
269};
270
271TEST_F(LdbCmdTest, DumpFileChecksumNoChecksum) {
272 Env* base_env = TryLoadCustomOrDefaultEnv();
273 std::unique_ptr<Env> env(NewMemEnv(base_env));
274 Options opts;
275 opts.env = env.get();
276 opts.create_if_missing = true;
f67539c2
TL
277
278 DB* db = nullptr;
20effc67 279 std::string dbname = test::PerThreadDBPath(env.get(), "ldb_cmd_test");
f67539c2
TL
280 ASSERT_OK(DB::Open(opts, dbname, &db));
281
282 WriteOptions wopts;
283 FlushOptions fopts;
284 fopts.wait = true;
285 Random rnd(test::RandomSeed());
286 for (int i = 0; i < 200; i++) {
287 char buf[16];
288 snprintf(buf, sizeof(buf), "%08d", i);
20effc67 289 std::string v = rnd.RandomString(100);
f67539c2
TL
290 ASSERT_OK(db->Put(wopts, buf, v));
291 }
292 ASSERT_OK(db->Flush(fopts));
293 for (int i = 100; i < 300; i++) {
294 char buf[16];
295 snprintf(buf, sizeof(buf), "%08d", i);
20effc67 296 std::string v = rnd.RandomString(100);
f67539c2
TL
297 ASSERT_OK(db->Put(wopts, buf, v));
298 }
299 ASSERT_OK(db->Flush(fopts));
300 for (int i = 200; i < 400; i++) {
301 char buf[16];
302 snprintf(buf, sizeof(buf), "%08d", i);
20effc67 303 std::string v = rnd.RandomString(100);
f67539c2
TL
304 ASSERT_OK(db->Put(wopts, buf, v));
305 }
306 ASSERT_OK(db->Flush(fopts));
307 for (int i = 300; i < 400; i++) {
308 char buf[16];
309 snprintf(buf, sizeof(buf), "%08d", i);
20effc67 310 std::string v = rnd.RandomString(100);
f67539c2
TL
311 ASSERT_OK(db->Put(wopts, buf, v));
312 }
313 ASSERT_OK(db->Flush(fopts));
314
315 char arg1[] = "./ldb";
316 char arg2[1024];
317 snprintf(arg2, sizeof(arg2), "--db=%s", dbname.c_str());
318 char arg3[] = "file_checksum_dump";
319 char* argv[] = {arg1, arg2, arg3};
320
321 ASSERT_EQ(0,
322 LDBCommandRunner::RunCommand(3, argv, opts, LDBOptions(), nullptr));
323
324 // Verify each sst file checksum value and checksum name
325 FileChecksumTestHelper fct_helper(opts, db, dbname);
326 ASSERT_OK(fct_helper.VerifyEachFileChecksum());
327
328 // Manually trigger compaction
329 char b_buf[16];
330 snprintf(b_buf, sizeof(b_buf), "%08d", 0);
331 char e_buf[16];
332 snprintf(e_buf, sizeof(e_buf), "%08d", 399);
333 Slice begin(b_buf);
334 Slice end(e_buf);
335 CompactRangeOptions options;
336 ASSERT_OK(db->CompactRange(options, &begin, &end));
337 // Verify each sst file checksum after compaction
338 FileChecksumTestHelper fct_helper_ac(opts, db, dbname);
339 ASSERT_OK(fct_helper_ac.VerifyEachFileChecksum());
340
341 ASSERT_EQ(0,
342 LDBCommandRunner::RunCommand(3, argv, opts, LDBOptions(), nullptr));
343
344 // Verify the checksum information in memory is the same as that in Manifest;
345 std::vector<LiveFileMetaData> live_files;
346 db->GetLiveFilesMetaData(&live_files);
347 delete db;
348 ASSERT_OK(fct_helper_ac.VerifyChecksumInManifest(live_files));
349}
350
351TEST_F(LdbCmdTest, DumpFileChecksumCRC32) {
352 Env* base_env = TryLoadCustomOrDefaultEnv();
353 std::unique_ptr<Env> env(NewMemEnv(base_env));
354 Options opts;
355 opts.env = env.get();
356 opts.create_if_missing = true;
20effc67 357 opts.file_checksum_gen_factory = GetFileChecksumGenCrc32cFactory();
f67539c2
TL
358
359 DB* db = nullptr;
20effc67 360 std::string dbname = test::PerThreadDBPath(env.get(), "ldb_cmd_test");
f67539c2
TL
361 ASSERT_OK(DB::Open(opts, dbname, &db));
362
363 WriteOptions wopts;
364 FlushOptions fopts;
365 fopts.wait = true;
366 Random rnd(test::RandomSeed());
367 for (int i = 0; i < 100; i++) {
368 char buf[16];
369 snprintf(buf, sizeof(buf), "%08d", i);
20effc67 370 std::string v = rnd.RandomString(100);
f67539c2
TL
371 ASSERT_OK(db->Put(wopts, buf, v));
372 }
373 ASSERT_OK(db->Flush(fopts));
374 for (int i = 50; i < 150; i++) {
375 char buf[16];
376 snprintf(buf, sizeof(buf), "%08d", i);
20effc67 377 std::string v = rnd.RandomString(100);
f67539c2
TL
378 ASSERT_OK(db->Put(wopts, buf, v));
379 }
380 ASSERT_OK(db->Flush(fopts));
381 for (int i = 100; i < 200; i++) {
382 char buf[16];
383 snprintf(buf, sizeof(buf), "%08d", i);
20effc67 384 std::string v = rnd.RandomString(100);
f67539c2
TL
385 ASSERT_OK(db->Put(wopts, buf, v));
386 }
387 ASSERT_OK(db->Flush(fopts));
388 for (int i = 150; i < 250; i++) {
389 char buf[16];
390 snprintf(buf, sizeof(buf), "%08d", i);
20effc67 391 std::string v = rnd.RandomString(100);
f67539c2
TL
392 ASSERT_OK(db->Put(wopts, buf, v));
393 }
394 ASSERT_OK(db->Flush(fopts));
395
396 char arg1[] = "./ldb";
397 char arg2[1024];
398 snprintf(arg2, sizeof(arg2), "--db=%s", dbname.c_str());
399 char arg3[] = "file_checksum_dump";
400 char* argv[] = {arg1, arg2, arg3};
401
402 ASSERT_EQ(0,
403 LDBCommandRunner::RunCommand(3, argv, opts, LDBOptions(), nullptr));
404
405 // Verify each sst file checksum value and checksum name
406 FileChecksumTestHelper fct_helper(opts, db, dbname);
407 ASSERT_OK(fct_helper.VerifyEachFileChecksum());
408
409 // Manually trigger compaction
410 char b_buf[16];
411 snprintf(b_buf, sizeof(b_buf), "%08d", 0);
412 char e_buf[16];
413 snprintf(e_buf, sizeof(e_buf), "%08d", 249);
414 Slice begin(b_buf);
415 Slice end(e_buf);
416 CompactRangeOptions options;
417 ASSERT_OK(db->CompactRange(options, &begin, &end));
418 // Verify each sst file checksum after compaction
419 FileChecksumTestHelper fct_helper_ac(opts, db, dbname);
420 ASSERT_OK(fct_helper_ac.VerifyEachFileChecksum());
421
422 ASSERT_EQ(0,
423 LDBCommandRunner::RunCommand(3, argv, opts, LDBOptions(), nullptr));
424
425 // Verify the checksum information in memory is the same as that in Manifest;
426 std::vector<LiveFileMetaData> live_files;
427 db->GetLiveFilesMetaData(&live_files);
428 delete db;
429 ASSERT_OK(fct_helper_ac.VerifyChecksumInManifest(live_files));
494da23a
TL
430}
431
432TEST_F(LdbCmdTest, OptionParsing) {
433 // test parsing flags
f67539c2
TL
434 Options opts;
435 opts.env = TryLoadCustomOrDefaultEnv();
494da23a
TL
436 {
437 std::vector<std::string> args;
438 args.push_back("scan");
439 args.push_back("--ttl");
440 args.push_back("--timestamp");
f67539c2
TL
441 LDBCommand* command = ROCKSDB_NAMESPACE::LDBCommand::InitFromCmdLineArgs(
442 args, opts, LDBOptions(), nullptr);
494da23a
TL
443 const std::vector<std::string> flags = command->TEST_GetFlags();
444 EXPECT_EQ(flags.size(), 2);
445 EXPECT_EQ(flags[0], "ttl");
446 EXPECT_EQ(flags[1], "timestamp");
447 delete command;
448 }
449 // test parsing options which contains equal sign in the option value
450 {
451 std::vector<std::string> args;
452 args.push_back("scan");
453 args.push_back("--db=/dev/shm/ldbtest/");
454 args.push_back(
455 "--from='abcd/efg/hijk/lmn/"
456 "opq:__rst.uvw.xyz?a=3+4+bcd+efghi&jk=lm_no&pq=rst-0&uv=wx-8&yz=a&bcd_"
457 "ef=gh.ijk'");
f67539c2
TL
458 LDBCommand* command = ROCKSDB_NAMESPACE::LDBCommand::InitFromCmdLineArgs(
459 args, opts, LDBOptions(), nullptr);
494da23a
TL
460 const std::map<std::string, std::string> option_map =
461 command->TEST_GetOptionMap();
462 EXPECT_EQ(option_map.at("db"), "/dev/shm/ldbtest/");
463 EXPECT_EQ(option_map.at("from"),
464 "'abcd/efg/hijk/lmn/"
465 "opq:__rst.uvw.xyz?a=3+4+bcd+efghi&jk=lm_no&pq=rst-0&uv=wx-8&yz="
466 "a&bcd_ef=gh.ijk'");
467 delete command;
468 }
469}
470
f67539c2
TL
471TEST_F(LdbCmdTest, ListFileTombstone) {
472 Env* base_env = TryLoadCustomOrDefaultEnv();
473 std::unique_ptr<Env> env(NewMemEnv(base_env));
474 Options opts;
475 opts.env = env.get();
476 opts.create_if_missing = true;
477
478 DB* db = nullptr;
20effc67 479 std::string dbname = test::PerThreadDBPath(env.get(), "ldb_cmd_test");
f67539c2
TL
480 ASSERT_OK(DB::Open(opts, dbname, &db));
481
482 WriteOptions wopts;
483 ASSERT_OK(db->Put(wopts, "foo", "1"));
484 ASSERT_OK(db->Put(wopts, "bar", "2"));
485
486 FlushOptions fopts;
487 fopts.wait = true;
488 ASSERT_OK(db->Flush(fopts));
489
490 ASSERT_OK(db->DeleteRange(wopts, db->DefaultColumnFamily(), "foo", "foo2"));
491 ASSERT_OK(db->DeleteRange(wopts, db->DefaultColumnFamily(), "bar", "foo2"));
492 ASSERT_OK(db->Flush(fopts));
493
494 delete db;
495
496 {
497 char arg1[] = "./ldb";
498 char arg2[1024];
499 snprintf(arg2, sizeof(arg2), "--db=%s", dbname.c_str());
500 char arg3[] = "list_file_range_deletes";
501 char* argv[] = {arg1, arg2, arg3};
502
503 ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
504 "ListFileRangeDeletesCommand::DoCommand:BeforePrint", [&](void* arg) {
505 std::string* out_str = reinterpret_cast<std::string*>(arg);
506
507 // Count number of tombstones printed
508 int num_tb = 0;
509 const std::string kFingerprintStr = "start: ";
510 auto offset = out_str->find(kFingerprintStr);
511 while (offset != std::string::npos) {
512 num_tb++;
513 offset =
514 out_str->find(kFingerprintStr, offset + kFingerprintStr.size());
515 }
516 EXPECT_EQ(2, num_tb);
517 });
518 ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
519
520 ASSERT_EQ(
521 0, LDBCommandRunner::RunCommand(3, argv, opts, LDBOptions(), nullptr));
522
523 ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearAllCallBacks();
524 ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
525 }
526
527 // Test the case of limiting tombstones
528 {
529 char arg1[] = "./ldb";
530 char arg2[1024];
531 snprintf(arg2, sizeof(arg2), "--db=%s", dbname.c_str());
532 char arg3[] = "list_file_range_deletes";
533 char arg4[] = "--max_keys=1";
534 char* argv[] = {arg1, arg2, arg3, arg4};
535
536 ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
537 "ListFileRangeDeletesCommand::DoCommand:BeforePrint", [&](void* arg) {
538 std::string* out_str = reinterpret_cast<std::string*>(arg);
539
540 // Count number of tombstones printed
541 int num_tb = 0;
542 const std::string kFingerprintStr = "start: ";
543 auto offset = out_str->find(kFingerprintStr);
544 while (offset != std::string::npos) {
545 num_tb++;
546 offset =
547 out_str->find(kFingerprintStr, offset + kFingerprintStr.size());
548 }
549 EXPECT_EQ(1, num_tb);
550 });
551 ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
552
553 ASSERT_EQ(
554 0, LDBCommandRunner::RunCommand(4, argv, opts, LDBOptions(), nullptr));
555
556 ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearAllCallBacks();
557 ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
558 }
559}
20effc67
TL
560
561TEST_F(LdbCmdTest, DisableConsistencyChecks) {
562 Env* base_env = TryLoadCustomOrDefaultEnv();
563 std::unique_ptr<Env> env(NewMemEnv(base_env));
564 Options opts;
565 opts.env = env.get();
566 opts.create_if_missing = true;
567
568 std::string dbname = test::PerThreadDBPath(env.get(), "ldb_cmd_test");
569
570 {
571 DB* db = nullptr;
572 ASSERT_OK(DB::Open(opts, dbname, &db));
573
574 WriteOptions wopts;
575 FlushOptions fopts;
576 fopts.wait = true;
577
578 ASSERT_OK(db->Put(wopts, "foo1", "1"));
579 ASSERT_OK(db->Put(wopts, "bar1", "2"));
580 ASSERT_OK(db->Flush(fopts));
581
582 ASSERT_OK(db->Put(wopts, "foo2", "3"));
583 ASSERT_OK(db->Put(wopts, "bar2", "4"));
584 ASSERT_OK(db->Flush(fopts));
585
586 delete db;
587 }
588
589 {
590 char arg1[] = "./ldb";
591 char arg2[1024];
592 snprintf(arg2, sizeof(arg2), "--db=%s", dbname.c_str());
593 char arg3[] = "checkconsistency";
594 char* argv[] = {arg1, arg2, arg3};
595
596 SyncPoint::GetInstance()->SetCallBack(
597 "Version::PrepareApply:forced_check", [&](void* arg) {
598 bool* forced = reinterpret_cast<bool*>(arg);
599 ASSERT_TRUE(*forced);
600 });
601 SyncPoint::GetInstance()->EnableProcessing();
602
603 ASSERT_EQ(
604 0, LDBCommandRunner::RunCommand(3, argv, opts, LDBOptions(), nullptr));
605
606 SyncPoint::GetInstance()->ClearAllCallBacks();
607 SyncPoint::GetInstance()->DisableProcessing();
608 }
609 {
610 char arg1[] = "./ldb";
611 char arg2[1024];
612 snprintf(arg2, sizeof(arg2), "--db=%s", dbname.c_str());
613 char arg3[] = "scan";
614 char* argv[] = {arg1, arg2, arg3};
615
616 SyncPoint::GetInstance()->SetCallBack(
617 "Version::PrepareApply:forced_check", [&](void* arg) {
618 bool* forced = reinterpret_cast<bool*>(arg);
619 ASSERT_TRUE(*forced);
620 });
621 SyncPoint::GetInstance()->EnableProcessing();
622
623 ASSERT_EQ(
624 0, LDBCommandRunner::RunCommand(3, argv, opts, LDBOptions(), nullptr));
625
626 SyncPoint::GetInstance()->ClearAllCallBacks();
627 SyncPoint::GetInstance()->DisableProcessing();
628 }
629 {
630 char arg1[] = "./ldb";
631 char arg2[1024];
632 snprintf(arg2, sizeof(arg2), "--db=%s", dbname.c_str());
633 char arg3[] = "scan";
634 char arg4[] = "--disable_consistency_checks";
635 char* argv[] = {arg1, arg2, arg3, arg4};
636
637 SyncPoint::GetInstance()->SetCallBack(
638 "ColumnFamilyData::ColumnFamilyData", [&](void* arg) {
639 ColumnFamilyOptions* cfo =
640 reinterpret_cast<ColumnFamilyOptions*>(arg);
641 ASSERT_FALSE(cfo->force_consistency_checks);
642 });
643 SyncPoint::GetInstance()->EnableProcessing();
644
645 ASSERT_EQ(
646 0, LDBCommandRunner::RunCommand(4, argv, opts, LDBOptions(), nullptr));
647
648 SyncPoint::GetInstance()->ClearAllCallBacks();
649 SyncPoint::GetInstance()->DisableProcessing();
650 }
651}
652
653TEST_F(LdbCmdTest, TestBadDbPath) {
654 Env* base_env = TryLoadCustomOrDefaultEnv();
655 std::unique_ptr<Env> env(NewMemEnv(base_env));
656 Options opts;
657 opts.env = env.get();
658 opts.create_if_missing = true;
659
660 std::string dbname = test::PerThreadDBPath(env.get(), "ldb_cmd_test");
661 char arg1[] = "./ldb";
662 char arg2[1024];
663 snprintf(arg2, sizeof(arg2), "--db=%s/.no_such_dir", dbname.c_str());
664 char arg3[1024];
665 snprintf(arg3, sizeof(arg3), "create_column_family");
666 char arg4[] = "bad cf";
667 char* argv[] = {arg1, arg2, arg3, arg4};
668
669 ASSERT_EQ(1,
670 LDBCommandRunner::RunCommand(4, argv, opts, LDBOptions(), nullptr));
671 snprintf(arg3, sizeof(arg3), "drop_column_family");
672 ASSERT_EQ(1,
673 LDBCommandRunner::RunCommand(4, argv, opts, LDBOptions(), nullptr));
674}
f67539c2
TL
675} // namespace ROCKSDB_NAMESPACE
676
677#ifdef ROCKSDB_UNITTESTS_WITH_CUSTOM_OBJECTS_FROM_STATIC_LIBS
678extern "C" {
679void RegisterCustomObjects(int argc, char** argv);
680}
681#else
682void RegisterCustomObjects(int /*argc*/, char** /*argv*/) {}
683#endif // !ROCKSDB_UNITTESTS_WITH_CUSTOM_OBJECTS_FROM_STATIC_LIBS
494da23a 684
7c673cae 685int main(int argc, char** argv) {
f67539c2 686 ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
7c673cae 687 ::testing::InitGoogleTest(&argc, argv);
f67539c2 688 RegisterCustomObjects(argc, argv);
7c673cae
FG
689 return RUN_ALL_TESTS();
690}
691#else
692#include <stdio.h>
693
11fdf7f2 694int main(int /*argc*/, char** /*argv*/) {
7c673cae
FG
695 fprintf(stderr, "SKIPPED as LDBCommand is not supported in ROCKSDB_LITE\n");
696 return 0;
697}
698
699#endif // ROCKSDB_LITE