From 58b4209e051de96d865eca96d1abc398a9535a7b Mon Sep 17 00:00:00 2001 From: sdong Date: Thu, 16 Jul 2015 12:18:32 -0700 Subject: [PATCH] Trigger non-trivial compaction in fault_injection_test Summary: Now the major test cases of fault_injection_test only insert keys in sorted order so compactions will be trivial move. Add a new mode to insert in non-sequential order to trigger non-trivial compactions. Test Plan: Run the test Reviewers: kradhakrishnan, anthony, IslamAbdelRahman, yhchiang, igor Reviewed By: igor Subscribers: leveldb, dhruba Differential Revision: https://reviews.facebook.net/D42435 --- db/fault_injection_test.cc | 86 ++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 31 deletions(-) diff --git a/db/fault_injection_test.cc b/db/fault_injection_test.cc index 88366d055..9cddea8b8 100644 --- a/db/fault_injection_test.cc +++ b/db/fault_injection_test.cc @@ -424,7 +424,8 @@ Status TestWritableFile::Sync() { return Status::OK(); } -class FaultInjectionTest : public testing::Test { +class FaultInjectionTest : public testing::Test, + public testing::WithParamInterface { protected: enum OptionConfig { kDefault, @@ -441,6 +442,8 @@ class FaultInjectionTest : public testing::Test { // When need to make sure data is persistent, call DB::CompactRange() bool sync_use_compact_; + bool sequential_order_; + protected: public: enum ExpectedVerifResult { kValExpectFound, kValExpectNoError }; @@ -467,6 +470,11 @@ class FaultInjectionTest : public testing::Test { db_(NULL) { } + ~FaultInjectionTest() { + rocksdb::SyncPoint::GetInstance()->DisableProcessing(); + rocksdb::SyncPoint::GetInstance()->ClearAllCallBacks(); + } + bool ChangeOptions() { option_config_++; if (option_config_ >= kEnd) { @@ -547,7 +555,10 @@ class FaultInjectionTest : public testing::Test { return s; } - void SetUp() override { ASSERT_OK(NewDB()); } + void SetUp() override { + sequential_order_ = GetParam(); + ASSERT_OK(NewDB()); + } void TearDown() override { CloseDB(); @@ -562,34 +573,33 @@ class FaultInjectionTest : public testing::Test { ASSERT_OK(s); } - void Build(const WriteOptions& write_options, int start_idx, int num_vals, - bool sequential = true) { + void Build(const WriteOptions& write_options, int start_idx, int num_vals) { std::string key_space, value_space; WriteBatch batch; for (int i = start_idx; i < start_idx + num_vals; i++) { - Slice key = Key(sequential, i, &key_space); + Slice key = Key(i, &key_space); batch.Clear(); batch.Put(key, Value(i, &value_space)); ASSERT_OK(db_->Write(write_options, &batch)); } } - Status ReadValue(int i, std::string* val, bool sequential) const { + Status ReadValue(int i, std::string* val) const { std::string key_space, value_space; - Slice key = Key(sequential, i, &key_space); + Slice key = Key(i, &key_space); Value(i, &value_space); ReadOptions options; return db_->Get(options, key, val); } - Status Verify(int start_idx, int num_vals, ExpectedVerifResult expected, - bool sequential = true) const { + Status Verify(int start_idx, int num_vals, + ExpectedVerifResult expected) const { std::string val; std::string value_space; Status s; for (int i = start_idx; i < start_idx + num_vals && s.ok(); i++) { Value(i, &value_space); - s = ReadValue(i, &val, sequential); + s = ReadValue(i, &val); if (s.ok()) { EXPECT_EQ(value_space, val); } @@ -609,9 +619,9 @@ class FaultInjectionTest : public testing::Test { } // Return the ith key - Slice Key(bool sequential, int i, std::string* storage) const { + Slice Key(int i, std::string* storage) const { int num = i; - if (!sequential) { + if (!sequential_order_) { // random transfer const int m = 0x5bd1e995; num *= m; @@ -701,6 +711,10 @@ class FaultInjectionTest : public testing::Test { ASSERT_OK(Verify(0, num_pre_sync, FaultInjectionTest::kValExpectFound)); ASSERT_OK(Verify(num_pre_sync, num_post_sync, FaultInjectionTest::kValExpectNoError)); + WaitCompactionFinish(); + ASSERT_OK(Verify(0, num_pre_sync, FaultInjectionTest::kValExpectFound)); + ASSERT_OK(Verify(num_pre_sync, num_post_sync, + FaultInjectionTest::kValExpectNoError)); } void NoWriteTestPreFault() { @@ -711,9 +725,14 @@ class FaultInjectionTest : public testing::Test { ResetDBState(reset_method); ASSERT_OK(OpenDB()); } + + void WaitCompactionFinish() { + static_cast(db_)->TEST_WaitForCompact(); + ASSERT_OK(db_->Put(WriteOptions(), "", "")); + } }; -TEST_F(FaultInjectionTest, FaultTest) { +TEST_P(FaultInjectionTest, FaultTest) { do { Random rnd(301); @@ -787,7 +806,7 @@ class SleepingBackgroundTask { // Disable the test because it is not passing. // Previous log file is not fsynced if sync is forced after log rolling. // TODO(FB internal task#6730880) Fix the bug -TEST_F(FaultInjectionTest, DISABLED_WriteOptionSyncTest) { +TEST_P(FaultInjectionTest, DISABLED_WriteOptionSyncTest) { SleepingBackgroundTask sleeping_task_low; env_->SetBackgroundThreads(1, Env::HIGH); // Block the job queue to prevent flush job from running. @@ -798,14 +817,14 @@ TEST_F(FaultInjectionTest, DISABLED_WriteOptionSyncTest) { write_options.sync = false; std::string key_space, value_space; - ASSERT_OK(db_->Put(write_options, Key(true, 1, &key_space), - Value(1, &value_space))); + ASSERT_OK( + db_->Put(write_options, Key(1, &key_space), Value(1, &value_space))); FlushOptions flush_options; flush_options.wait = false; ASSERT_OK(db_->Flush(flush_options)); write_options.sync = true; - ASSERT_OK(db_->Put(write_options, Key(true, 2, &key_space), - Value(2, &value_space))); + ASSERT_OK( + db_->Put(write_options, Key(2, &key_space), Value(2, &value_space))); env_->SetFilesystemActive(false); NoWriteTestReopenWithFault(kResetDropAndDeleteUnsynced); @@ -814,15 +833,15 @@ TEST_F(FaultInjectionTest, DISABLED_WriteOptionSyncTest) { ASSERT_OK(OpenDB()); std::string val; Value(2, &value_space); - ASSERT_OK(ReadValue(2, &val, true)); + ASSERT_OK(ReadValue(2, &val)); ASSERT_EQ(value_space, val); Value(1, &value_space); - ASSERT_OK(ReadValue(1, &val, true)); + ASSERT_OK(ReadValue(1, &val)); ASSERT_EQ(value_space, val); } -TEST_F(FaultInjectionTest, UninstalledCompaction) { +TEST_P(FaultInjectionTest, UninstalledCompaction) { options_.target_file_size_base = 32 * 1024; options_.write_buffer_size = 100 << 10; // 100KB options_.level0_file_num_compaction_trigger = 6; @@ -831,16 +850,18 @@ TEST_F(FaultInjectionTest, UninstalledCompaction) { options_.max_background_compactions = 1; OpenDB(); - rocksdb::SyncPoint::GetInstance()->LoadDependency({ - {"FaultInjectionTest::FaultTest:0", "DBImpl::BGWorkCompaction"}, - {"CompactionJob::Run():End", "FaultInjectionTest::FaultTest:1"}, - {"FaultInjectionTest::FaultTest:2", - "DBImpl::BackgroundCompaction:NonTrivial:AfterRun"}, - }); + if (!sequential_order_) { + rocksdb::SyncPoint::GetInstance()->LoadDependency({ + {"FaultInjectionTest::FaultTest:0", "DBImpl::BGWorkCompaction"}, + {"CompactionJob::Run():End", "FaultInjectionTest::FaultTest:1"}, + {"FaultInjectionTest::FaultTest:2", + "DBImpl::BackgroundCompaction:NonTrivial:AfterRun"}, + }); + } rocksdb::SyncPoint::GetInstance()->EnableProcessing(); int kNumKeys = 1000; - Build(WriteOptions(), 0, kNumKeys, false); + Build(WriteOptions(), 0, kNumKeys); FlushOptions flush_options; flush_options.wait = true; db_->Flush(flush_options); @@ -861,12 +882,15 @@ TEST_F(FaultInjectionTest, UninstalledCompaction) { [&](void* arg) { ASSERT_TRUE(opened.load()); }); rocksdb::SyncPoint::GetInstance()->EnableProcessing(); ASSERT_OK(OpenDB()); - static_cast(db_)->TEST_WaitForCompact(); - ASSERT_OK(Verify(0, kNumKeys, FaultInjectionTest::kValExpectFound, false)); - ASSERT_OK(db_->Put(WriteOptions(), "", "")); + ASSERT_OK(Verify(0, kNumKeys, FaultInjectionTest::kValExpectFound)); + WaitCompactionFinish(); + ASSERT_OK(Verify(0, kNumKeys, FaultInjectionTest::kValExpectFound)); rocksdb::SyncPoint::GetInstance()->DisableProcessing(); + rocksdb::SyncPoint::GetInstance()->ClearAllCallBacks(); } +INSTANTIATE_TEST_CASE_P(FaultTest, FaultInjectionTest, ::testing::Bool()); + } // namespace rocksdb int main(int argc, char** argv) {