From d266e3ee53f9d9310bb9cbba91481754dc38c522 Mon Sep 17 00:00:00 2001 From: yangjundong <1047934838@qq.com> Date: Fri, 12 Jul 2024 18:29:55 +0000 Subject: [PATCH] [test][store] Add pessimistic lock unit test --- src/server/store_service.cc | 2 +- .../txn/test_txn_pessimistic_lock.cc | 1138 ++++++++++------- 2 files changed, 675 insertions(+), 465 deletions(-) diff --git a/src/server/store_service.cc b/src/server/store_service.cc index abb3e5b6f..ebe47d02c 100644 --- a/src/server/store_service.cc +++ b/src/server/store_service.cc @@ -1983,7 +1983,7 @@ void DoTxnPessimisticLock(StoragePtr storage, google::protobuf::RpcController* c } std::vector kvs; - // yjddebug todo + status = storage->TxnPessimisticLock(ctx, mutations, request->primary_lock(), request->start_ts(), request->lock_ttl(), request->for_update_ts(), true, kvs); if (!status.ok()) { diff --git a/test/unit_test/txn/test_txn_pessimistic_lock.cc b/test/unit_test/txn/test_txn_pessimistic_lock.cc index aa4fbfcad..bfd2da24d 100644 --- a/test/unit_test/txn/test_txn_pessimistic_lock.cc +++ b/test/unit_test/txn/test_txn_pessimistic_lock.cc @@ -28,16 +28,25 @@ #include #include #include +#include #include #include "butil/status.h" #include "common/constant.h" +#include "common/context.h" #include "common/helper.h" +#include "common/role.h" #include "config/config.h" +#include "config/config_manager.h" #include "config/yaml_config.h" #include "coordinator/tso_control.h" +#include "engine/bdb_raw_engine.h" +#include "engine/mono_store_engine.h" #include "engine/rocks_raw_engine.h" #include "engine/txn_engine_helper.h" +#include "event/store_state_machine_event.h" +#include "gflags/gflags.h" +#include "meta/store_meta_manager.h" #include "mvcc/codec.h" #include "proto/common.pb.h" #include "proto/error.pb.h" @@ -50,11 +59,12 @@ #include "serial/schema/string_schema.h" namespace dingodb { +// DECLARE_string(role); static const std::string kDefaultCf = "default"; static const std::vector kAllCFs = {Constant::kTxnWriteCF, Constant::kTxnDataCF, Constant::kTxnLockCF, - kDefaultCf}; + kDefaultCf, Constant::kStoreMetaCF}; const char kAlphabet[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'o', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; @@ -112,10 +122,38 @@ class TxnPessimisticLockTest : public testing::Test { std::shared_ptr config = std::make_shared(); ASSERT_EQ(0, config->Load(kYamlConfigContent)); + SetRole("store"); + ConfigManager::GetInstance().Register(GetRoleName(), config); engine = std::make_shared(); ASSERT_TRUE(engine != nullptr); ASSERT_TRUE(engine->Init(config, kAllCFs)); + + auto raw_bdb_engine = std::make_shared(); + ASSERT_TRUE(raw_bdb_engine != nullptr); + auto listener_factory = std::make_shared(); + ASSERT_TRUE(listener_factory != nullptr); + + auto ts_provider = mvcc::TsProvider::New(nullptr); + + ASSERT_TRUE(ts_provider->Init()); + + mono_engine = std::make_shared(engine, raw_bdb_engine, listener_factory->Build(), ts_provider); + ASSERT_TRUE(mono_engine != nullptr); + ASSERT_TRUE(mono_engine->Init(config)); + + auto meta_reader = std::make_shared(engine); + auto meta_writer = std::make_shared(engine); + auto store_meta_manager = std::make_shared(meta_reader, meta_writer); + ASSERT_TRUE(store_meta_manager->Init()); + + auto store_metrics_manager = std::make_shared(meta_reader, meta_writer); + ASSERT_TRUE(store_metrics_manager->Init()); + + mono_engine->SetStoreMetaManager(store_meta_manager); + mono_engine->SetStoreMetricsManager(store_metrics_manager); + + InitRecord(); } static void TearDownTestSuite() { @@ -129,89 +167,159 @@ class TxnPessimisticLockTest : public testing::Test { void TearDown() override {} static void DeleteRange(); + static void InitRecord(); + static void PrepareData(); + static void SetKvFunction(bool short_value, pb::store::Op write_op, bool include_lock, bool is_pissimistic_lock, + pb::common::KeyValue &key_value); + static void PrepareDataAndLock(bool short_value, pb::store::Op write_op, bool include_lock, bool is_pissimistic_lock, + std::unordered_map &kvs, + std::unordered_map &lock_keys); static inline std::shared_ptr engine; - static inline pb::common::CoprocessorV2 pb_coprocessor; + static inline std::shared_ptr mono_engine; static inline int64_t start_ts = 0; static inline int64_t end_ts = 0; - static inline std::vector keys; + static inline int64_t physical = 1702966356362 /*Helper::TimestampMs()*/; + static inline int64_t logical = 0; + static inline int64_t lock_ttl = 2036211681000; // 2034-07-11 14:21:21 + // static inline std::unordered_map kvs; + static inline std::shared_ptr record_encoder; }; static int64_t Tso2Timestamp(pb::meta::TsoTimestamp tso) { return (tso.physical() << ::dingodb::kLogicalBits) + tso.logical(); } -void TxnPessimisticLockTest::DeleteRange() { - const std::string &cf_name = kDefaultCf; - auto writer = engine->Writer(); +void TxnPessimisticLockTest::SetKvFunction(bool short_value, pb::store::Op write_op, bool include_lock, + bool is_pissimistic_lock, pb::common::KeyValue &key_value) { + pb::common::KeyValue kv_write; + pb::meta::TsoTimestamp tso; + tso.set_physical(physical); + tso.set_logical(logical); + int64_t target_start_ts = Tso2Timestamp(tso); + tso.set_logical(++logical); + int64_t commit_ts = Tso2Timestamp(tso); + + if (0 == start_ts) { + start_ts = target_start_ts; + } - pb::common::Range range; + end_ts = commit_ts; - // std::sort(keys.begin(), keys.end()); + std::string write_key = mvcc::Codec::EncodeKey(std::string(key_value.key()), commit_ts); - // std::string my_min_key(keys.front()); - // std::string my_max_key(Helper::PrefixNext(keys.back())); + pb::store::WriteInfo write_info; + write_info.set_start_ts(start_ts); + write_info.set_op(write_op); + if (short_value) { + write_info.set_short_value(key_value.value()); + } - std::string my_min_key(Helper::GenMinStartKey()); - std::string my_max_key(Helper::GenMaxStartKey()); + kv_write.set_key(write_key); + kv_write.set_value(write_info.SerializeAsString()); - std::string my_min_key_s = StrToHex(my_min_key, " "); - LOG(INFO) << "my_min_key_s : " << my_min_key_s; + engine->Writer()->KvPut(Constant::kTxnWriteCF, kv_write); - std::string my_max_key_s = StrToHex(my_max_key, " "); - LOG(INFO) << "my_max_key_s : " << my_max_key_s; + if (!short_value) { + pb::common::KeyValue kv_data; + std::string data_key = mvcc::Codec::EncodeKey(std::string(key_value.key()), start_ts); + kv_data.set_key(data_key); + kv_data.set_value(key_value.value()); - range.set_start_key(my_min_key); - range.set_end_key(Helper::PrefixNext(my_max_key)); + butil::Status ok = engine->Writer()->KvPut(Constant::kTxnDataCF, kv_data); - // ok + EXPECT_EQ(ok.error_code(), pb::error::OK); + } + + if (include_lock) { + pb::common::KeyValue lock_data; + lock_data.set_key(mvcc::Codec::EncodeKey(key_value.key(), Constant::kLockVer)); + pb::store::LockInfo lock_info; + lock_info.set_primary_lock(key_value.key()); + lock_info.set_lock_ts(start_ts); + if (is_pissimistic_lock) { + lock_info.set_for_update_ts(start_ts); + } + + lock_info.set_key(key_value.key()); + lock_info.set_lock_ttl(lock_ttl); + lock_info.set_lock_type(pb::store::Op::Lock); + lock_data.set_value(lock_info.SerializeAsString()); + + butil::Status ok = engine->Writer()->KvPut(Constant::kTxnLockCF, lock_data); + EXPECT_EQ(ok.error_code(), pb::error::OK); + } +} + +void TxnPessimisticLockTest::PrepareDataAndLock(bool short_value, pb::store::Op write_op, bool include_lock, + bool is_pissimistic_lock, + std::unordered_map &kvs, + std::unordered_map &lock_keys) { + // 1 { - butil::Status ok = writer->KvDeleteRange(Constant::kTxnWriteCF, range); + pb::common::KeyValue key_value; + std::vector record; + record.reserve(6); + std::any any_bool = std::optional(false); + record.emplace_back(std::move(any_bool)); - EXPECT_EQ(ok.error_code(), dingodb::pb::error::Errno::OK); + std::any any_int = std::optional(22); + record.emplace_back(std::move(any_int)); - const std::string &start_key = my_min_key; - std::string end_key = Helper::PrefixNext(my_max_key); - std::vector kvs; + std::any any_float = std::optional(22.23); + record.emplace_back(std::move(any_float)); - auto reader = engine->Reader(); + std::any any_long = std::optional(2200); + record.emplace_back(std::move(any_long)); - ok = reader->KvScan(cf_name, start_key, end_key, kvs); - EXPECT_EQ(ok.error_code(), dingodb::pb::error::Errno::OK); + std::any any_double = std::optional(22.4545); + record.emplace_back(std::move(any_double)); - LOG(INFO) << "start_key : " << StrToHex(start_key, " ") << "\n" - << "end_key : " << StrToHex(end_key, " "); - for (const auto &kv : kvs) { - LOG(INFO) << kv.key() << ":" << kv.value(); - } + std::any any_string = std::optional>(std::make_shared("string_222222")); + record.emplace_back(std::move(any_string)); + + int ret = record_encoder->Encode('r', record, *key_value.mutable_key(), *key_value.mutable_value()); + + EXPECT_EQ(ret, 0); + + SetKvFunction(short_value, write_op, include_lock, is_pissimistic_lock, key_value); + kvs[key_value.key()] = key_value.value(); + lock_keys[key_value.key()] = true; } - // ok + // 2 { - butil::Status ok = writer->KvDeleteRange(Constant::kTxnDataCF, range); + pb::common::KeyValue key_value; + std::vector record; + record.reserve(6); + std::any any_bool = std::optional(true); + record.emplace_back(std::move(any_bool)); - EXPECT_EQ(ok.error_code(), dingodb::pb::error::Errno::OK); + std::any any_int = std::optional(33); + record.emplace_back(std::move(any_int)); - const std::string &start_key = my_min_key; - std::string end_key = Helper::PrefixNext(my_max_key); - std::vector kvs; + std::any any_float = std::optional(33.23); + record.emplace_back(std::move(any_float)); - auto reader = engine->Reader(); + std::any any_long = std::optional(3300); + record.emplace_back(std::move(any_long)); - ok = reader->KvScan(cf_name, start_key, end_key, kvs); - EXPECT_EQ(ok.error_code(), dingodb::pb::error::Errno::OK); + std::any any_double = std::optional(33.4545); + record.emplace_back(std::move(any_double)); - LOG(INFO) << "start_key : " << StrToHex(start_key, " ") << "\n" - << "end_key : " << StrToHex(end_key, " "); - for (const auto &kv : kvs) { - LOG(INFO) << kv.key() << ":" << kv.value(); - } - } -} + std::any any_string = std::optional>(std::make_shared("string_333333")); + record.emplace_back(std::move(any_string)); -TEST_F(TxnPessimisticLockTest, KvDeleteRangeBefore) { DeleteRange(); } + int ret = record_encoder->Encode('r', record, *key_value.mutable_key(), *key_value.mutable_value()); -TEST_F(TxnPessimisticLockTest, Prepare) { + EXPECT_EQ(ret, 0); + + SetKvFunction(short_value, write_op, include_lock, is_pissimistic_lock, key_value); + kvs[key_value.key()] = key_value.value(); + lock_keys[key_value.key()] = true; + } +} +void TxnPessimisticLockTest::InitRecord() { int schema_version = 1; std::shared_ptr>> schemas; long common_id = 1; // NOLINT @@ -261,520 +369,622 @@ TEST_F(TxnPessimisticLockTest, Prepare) { string_schema->SetAllowNull(true); string_schema->SetIndex(5); schemas->emplace_back(std::move(string_schema)); + record_encoder = std::make_shared(schema_version, schemas, common_id); +} - RecordEncoder record_encoder(schema_version, schemas, common_id); - - int64_t physical = 1702966356362 /*Helper::TimestampMs()*/; - int64_t logical = 0; - - auto lambda_txn_set_kv_function = [&](const pb::common::KeyValue &key_value) { - pb::common::KeyValue kv_write; - pb::meta::TsoTimestamp tso; - tso.set_physical(physical); - tso.set_logical(logical); - int64_t start_ts = Tso2Timestamp(tso); - tso.set_logical(++logical); - int64_t commit_ts = Tso2Timestamp(tso); - - if (0 == this->start_ts) { - this->start_ts = start_ts; - } - - end_ts = commit_ts; - - std::string write_key = mvcc::Codec::EncodeKey(std::string(key_value.key()), commit_ts); +void TxnPessimisticLockTest::DeleteRange() { + const std::string &cf_name = kDefaultCf; + auto writer = engine->Writer(); - pb::store::WriteInfo write_info; - write_info.set_start_ts(start_ts); - write_info.set_op(::dingodb::pb::store::Op::Put); - // write_info.set_short_value(key_value.value()); + pb::common::Range range; - kv_write.set_key(write_key); - kv_write.set_value(write_info.SerializeAsString()); + std::string my_min_key(Helper::GenMinStartKey()); + std::string my_max_key(Helper::GenMaxStartKey()); - engine->Writer()->KvPut(Constant::kTxnWriteCF, kv_write); + std::string my_min_key_s = StrToHex(my_min_key, " "); + LOG(INFO) << "my_min_key_s : " << my_min_key_s; - pb::common::KeyValue kv_data; - std::string data_key = mvcc::Codec::EncodeKey(std::string(key_value.key()), start_ts); - kv_data.set_key(data_key); - kv_data.set_value(key_value.value()); + std::string my_max_key_s = StrToHex(my_max_key, " "); + LOG(INFO) << "my_max_key_s : " << my_max_key_s; - butil::Status ok = engine->Writer()->KvPut(Constant::kTxnDataCF, kv_data); - EXPECT_EQ(ok.error_code(), pb::error::OK); - }; + range.set_start_key(my_min_key); + range.set_end_key(Helper::PrefixNext(my_max_key)); - // 1 + // ok { - pb::common::KeyValue key_value; - std::vector record; - record.reserve(6); - std::any any_bool = std::optional(std::nullopt); - record.emplace_back(std::move(any_bool)); - - std::any any_int = std::optional(std::nullopt); - record.emplace_back(std::move(any_int)); - - std::any any_float = std::optional(std::nullopt); - record.emplace_back(std::move(any_float)); - - std::any any_long = std::optional(std::nullopt); - record.emplace_back(std::move(any_long)); - - std::any any_double = std::optional(std::nullopt); - record.emplace_back(std::move(any_double)); - - std::any any_string = std::optional>(std::nullopt); - record.emplace_back(std::move(any_string)); + butil::Status ok = writer->KvDeleteRange(Constant::kTxnWriteCF, range); - int ret = record_encoder.Encode('r', record, *key_value.mutable_key(), *key_value.mutable_value()); + EXPECT_EQ(ok.error_code(), dingodb::pb::error::Errno::OK); - EXPECT_EQ(ret, 0); + const std::string &start_key = my_min_key; + std::string end_key = Helper::PrefixNext(my_max_key); + std::vector delete_kvs; - lambda_txn_set_kv_function(key_value); - std::string key = key_value.key(); - std::string value = key_value.value(); + auto reader = engine->Reader(); - keys.push_back(key); + ok = reader->KvScan(cf_name, start_key, end_key, delete_kvs); + EXPECT_EQ(ok.error_code(), dingodb::pb::error::Errno::OK); - std::string s = StrToHex(key, " "); - LOG(INFO) << "s : " << s; + LOG(INFO) << "start_key : " << StrToHex(start_key, " ") << "\n" + << "end_key : " << StrToHex(end_key, " "); + for (const auto &kv : delete_kvs) { + LOG(INFO) << kv.key() << ":" << kv.value(); + } } - // 2 + // ok { - pb::common::KeyValue key_value; - std::vector record; - record.reserve(6); - std::any any_bool = std::optional(false); - record.emplace_back(std::move(any_bool)); - - std::any any_int = std::optional(2); - record.emplace_back(std::move(any_int)); - - std::any any_float = std::optional(2.23); - record.emplace_back(std::move(any_float)); - - std::any any_long = std::optional(200); - record.emplace_back(std::move(any_long)); - - std::any any_double = std::optional(2.4545); - record.emplace_back(std::move(any_double)); + butil::Status ok = writer->KvDeleteRange(Constant::kTxnDataCF, range); - std::any any_string = std::optional>(std::make_shared("string_22222")); - record.emplace_back(std::move(any_string)); + EXPECT_EQ(ok.error_code(), dingodb::pb::error::Errno::OK); - int ret = record_encoder.Encode('r', record, *key_value.mutable_key(), *key_value.mutable_value()); + const std::string &start_key = my_min_key; + std::string end_key = Helper::PrefixNext(my_max_key); + std::vector delete_kvs; - EXPECT_EQ(ret, 0); - lambda_txn_set_kv_function(key_value); + auto reader = engine->Reader(); - std::string key = key_value.key(); - std::string value = key_value.value(); - keys.push_back(key); + ok = reader->KvScan(cf_name, start_key, end_key, delete_kvs); + EXPECT_EQ(ok.error_code(), dingodb::pb::error::Errno::OK); - std::string s = StrToHex(key, " "); - LOG(INFO) << "s : " << s; + LOG(INFO) << "start_key : " << StrToHex(start_key, " ") << "\n" + << "end_key : " << StrToHex(end_key, " "); + for (const auto &kv : delete_kvs) { + LOG(INFO) << kv.key() << ":" << kv.value(); + } } - // 3 + // ok { - pb::common::KeyValue key_value; - std::vector record; - record.reserve(6); - std::any any_bool = std::optional(true); - record.emplace_back(std::move(any_bool)); - - std::any any_int = std::optional(3); - record.emplace_back(std::move(any_int)); - - std::any any_float = std::optional(3.23); - record.emplace_back(std::move(any_float)); - - std::any any_long = std::optional(300); - record.emplace_back(std::move(any_long)); - - std::any any_double = std::optional(3.4545); - record.emplace_back(std::move(any_double)); - - std::any any_string = std::optional>(std::make_shared("string_33333")); - record.emplace_back(std::move(any_string)); + butil::Status ok = writer->KvDeleteRange(Constant::kTxnLockCF, range); - int ret = record_encoder.Encode('r', record, *key_value.mutable_key(), *key_value.mutable_value()); + EXPECT_EQ(ok.error_code(), dingodb::pb::error::Errno::OK); - EXPECT_EQ(ret, 0); + const std::string &start_key = my_min_key; + std::string end_key = Helper::PrefixNext(my_max_key); + std::vector delete_kvs; - lambda_txn_set_kv_function(key_value); + auto reader = engine->Reader(); - std::string key = key_value.key(); - std::string value = key_value.value(); - keys.push_back(key); + ok = reader->KvScan(cf_name, start_key, end_key, delete_kvs); + EXPECT_EQ(ok.error_code(), dingodb::pb::error::Errno::OK); - std::string s = StrToHex(key, " "); - LOG(INFO) << "s : " << s; + LOG(INFO) << "start_key : " << StrToHex(start_key, " ") << "\n" + << "end_key : " << StrToHex(end_key, " "); + for (const auto &kv : delete_kvs) { + LOG(INFO) << kv.key() << ":" << kv.value(); + } } +} - // 4 - { - pb::common::KeyValue key_value; - std::vector record; - record.reserve(6); - std::any any_bool = std::optional(4); - record.emplace_back(std::move(any_bool)); +TEST_F(TxnPessimisticLockTest, KvDeleteRangeBefore) { DeleteRange(); } - std::any any_int = std::optional(std::nullopt); - record.emplace_back(std::move(any_int)); +// todo(yangjundong) +TEST_F(TxnPessimisticLockTest, PessimisticLock) { + GTEST_SKIP() << "not impl PessimisticLock "; + // create region for test + auto region_id = 373; + auto region = store::Region::New(region_id); + region->SetState(pb::common::StoreRegionState::NORMAL); + auto store_region_meta = mono_engine->GetStoreMetaManager()->GetStoreRegionMeta(); + store_region_meta->AddRegion(region); + auto region_metrics = StoreRegionMetrics::NewMetrics(region->Id()); + mono_engine->GetStoreMetricsManager()->GetStoreRegionMetrics()->AddMetrics(region_metrics); - std::any any_float = std::optional(4.23); - record.emplace_back(std::move(any_float)); + // Normal - std::any any_long = std::optional(400); - record.emplace_back(std::move(any_long)); + // Op not correct - std::any any_double = std::optional(4.4545); - record.emplace_back(std::move(any_double)); + // Lock confilict - std::any any_string = std::optional>(std::make_shared("string_44444")); - record.emplace_back(std::move(any_string)); + // Write confilct - int ret = record_encoder.Encode('r', record, *key_value.mutable_key(), *key_value.mutable_value()); + // Rollback - EXPECT_EQ(ret, 0); + // Duplicated - lambda_txn_set_kv_function(key_value); + // Rollback - std::string key = key_value.key(); - std::string value = key_value.value(); - keys.push_back(key); + // LockTypeNotMatch - std::string s = StrToHex(key, " "); - LOG(INFO) << "s : " << s; - } + // Acquire lock on a prewritten key should fail - // 5 - { - pb::common::KeyValue key_value; - std::vector record; - record.reserve(6); - std::any any_bool = std::optional(true); - record.emplace_back(std::move(any_bool)); + // Acquire lock on a committed key should fail. - std::any any_int = std::optional(5); - record.emplace_back(std::move(any_int)); + // Pessimistic prewrite on a committed key should fail. - std::any any_float = std::optional(5.23); - record.emplace_back(std::move(any_float)); + // Acquire lock when there is lock with different for_update_ts. - std::any any_long = std::optional(std::nullopt); - record.emplace_back(std::move(any_long)); + // lock key is Deleted. - std::any any_double = std::optional(std::nullopt); - record.emplace_back(std::move(any_double)); + // Over write lock info(update lock info) - std::any any_string = std::optional>(std::make_shared("string_55555")); - record.emplace_back(std::move(any_string)); - - int ret = record_encoder.Encode('r', record, *key_value.mutable_key(), *key_value.mutable_value()); + // Duplicated command +} - EXPECT_EQ(ret, 0); +TEST_F(TxnPessimisticLockTest, PessimisticLockReturnValue) { + // create region for test + auto region_id = 373; + auto region = store::Region::New(region_id); + region->SetState(pb::common::StoreRegionState::NORMAL); + auto store_region_meta = mono_engine->GetStoreMetaManager()->GetStoreRegionMeta(); + store_region_meta->AddRegion(region); + auto region_metrics = StoreRegionMetrics::NewMetrics(region->Id()); + mono_engine->GetStoreMetricsManager()->GetStoreRegionMetrics()->AddMetrics(region_metrics); + + // normal + { + bool short_value = false; + bool include_lock = false; + bool is_pissimistic_lock = false; + std::unordered_map kvs; + std::unordered_map lock_keys; + PrepareDataAndLock(short_value, ::dingodb::pb::store::Op::Put, include_lock, is_pissimistic_lock, kvs, lock_keys); + + butil::Status ok; + pb::store::TxnPessimisticLockResponse response; + auto ctx = std::make_shared(); + ctx->SetRegionId(region_id); + ctx->SetCfName(Constant::kStoreDataCF); + ctx->SetResponse(&response); + std::vector mutations; + std::vector expected_kvs; + std::string primary_lock = kvs.begin()->first; + int64_t target_start_ts = end_ts + 1; + int64_t target_for_update_ts = end_ts + 1; + int64_t target_lock_ttl = lock_ttl; // 2034-07-11 14:21:21 + bool return_values = true; + + for (auto const &kv : kvs) { + pb::store::Mutation mutation; + mutation.set_op(::dingodb::pb::store::Op::Lock); + mutation.set_key(kv.first); + mutations.emplace_back(mutation); + } - lambda_txn_set_kv_function(key_value); + auto status = TxnEngineHelper::PessimisticLock(engine, mono_engine, ctx, mutations, primary_lock, target_start_ts, + target_lock_ttl, target_for_update_ts, return_values, expected_kvs); - std::string key = key_value.key(); - std::string value = key_value.value(); - keys.push_back(key); + EXPECT_EQ(status.ok(), true); + EXPECT_EQ(mutations.size(), expected_kvs.size()); - std::string s = StrToHex(key, " "); - LOG(INFO) << "s : " << s; + for (auto const &kv : expected_kvs) { + auto found = kvs.find(kv.key()); + EXPECT_NE(found, kvs.end()); + if (found != kvs.end()) { + EXPECT_EQ(kv.value(), found->second); + } + } + DeleteRange(); } - // 6 + // short value { - pb::common::KeyValue key_value; - std::vector record; - record.reserve(6); - std::any any_bool = std::optional(6); - record.emplace_back(std::move(any_bool)); - - std::any any_int = std::optional(std::nullopt); - record.emplace_back(std::move(any_int)); - - std::any any_float = std::optional(6.23); - record.emplace_back(std::move(any_float)); - - std::any any_long = std::optional(600); - record.emplace_back(std::move(any_long)); - - std::any any_double = std::optional(6.4545); - record.emplace_back(std::move(any_double)); - - std::any any_string = std::optional>(std::nullopt); - record.emplace_back(std::move(any_string)); - - int ret = record_encoder.Encode('r', record, *key_value.mutable_key(), *key_value.mutable_value()); - - EXPECT_EQ(ret, 0); - - lambda_txn_set_kv_function(key_value); - - std::string key = key_value.key(); - std::string value = key_value.value(); - keys.push_back(key); + bool short_value = true; + bool include_lock = false; + bool is_pissimistic_lock = false; + std::unordered_map kvs; + std::unordered_map lock_keys; + PrepareDataAndLock(short_value, ::dingodb::pb::store::Op::Put, include_lock, is_pissimistic_lock, kvs, lock_keys); + + butil::Status ok; + pb::store::TxnPessimisticLockResponse response; + auto ctx = std::make_shared(); + ctx->SetRegionId(region_id); + ctx->SetCfName(Constant::kStoreDataCF); + ctx->SetResponse(&response); + std::vector mutations; + std::vector expected_kvs; + std::string primary_lock = kvs.begin()->first; + int64_t target_start_ts = end_ts + 1; + int64_t target_for_update_ts = end_ts + 1; + int64_t target_lock_ttl = lock_ttl; // 2034-07-11 14:21:21 + bool return_values = true; + + for (auto const &kv : kvs) { + pb::store::Mutation mutation; + mutation.set_op(::dingodb::pb::store::Op::Lock); + mutation.set_key(kv.first); + mutations.emplace_back(mutation); + } - std::string s = StrToHex(key, " "); - LOG(INFO) << "s : " << s; + auto status = TxnEngineHelper::PessimisticLock(engine, mono_engine, ctx, mutations, primary_lock, target_start_ts, + target_lock_ttl, target_for_update_ts, return_values, expected_kvs); + EXPECT_EQ(status.ok(), true); + EXPECT_EQ(mutations.size(), expected_kvs.size()); + for (auto const &kv : expected_kvs) { + auto found = kvs.find(kv.key()); + EXPECT_NE(found, kvs.end()); + if (found != kvs.end()) { + EXPECT_EQ(kv.value(), found->second); + } + } + DeleteRange(); } - // 7 + // Lock not exist key, return value is empty. { - pb::common::KeyValue key_value; - std::vector record; - record.reserve(6); - std::any any_bool = std::optional(false); - record.emplace_back(std::move(any_bool)); - - std::any any_int = std::optional(7); - record.emplace_back(std::move(any_int)); - - std::any any_float = std::optional(7.23); - record.emplace_back(std::move(any_float)); - - std::any any_long = std::optional(700); - record.emplace_back(std::move(any_long)); - - std::any any_double = std::optional(7.4545); - record.emplace_back(std::move(any_double)); - - std::any any_string = std::optional>(std::make_shared("string_77777")); - record.emplace_back(std::move(any_string)); - - int ret = record_encoder.Encode('r', record, *key_value.mutable_key(), *key_value.mutable_value()); + butil::Status ok; + pb::store::TxnPessimisticLockResponse response; + auto ctx = std::make_shared(); + ctx->SetRegionId(region_id); + ctx->SetCfName(Constant::kStoreDataCF); + ctx->SetResponse(&response); + std::vector mutations; + std::vector expected_kvs; + + std::string primary_lock = "not_exist"; + int64_t target_start_ts = end_ts + 1; + int64_t target_for_update_ts = end_ts + 1; + int64_t target_lock_ttl = lock_ttl; // 2034-07-11 14:21:21 + bool return_values = true; + + pb::store::Mutation mutation; + mutation.set_op(::dingodb::pb::store::Op::Lock); + mutation.set_key("not_exist"); + mutations.emplace_back(mutation); + + auto status = TxnEngineHelper::PessimisticLock(engine, mono_engine, ctx, mutations, primary_lock, target_start_ts, + target_lock_ttl, target_for_update_ts, return_values, expected_kvs); + + EXPECT_EQ(status.ok(), true); + + EXPECT_EQ(mutations.size(), expected_kvs.size()); + EXPECT_EQ(expected_kvs[0].key(), mutations[0].key()); + EXPECT_EQ(expected_kvs[0].value(), ""); + DeleteRange(); + } - EXPECT_EQ(ret, 0); + // WriteConflict + { + bool short_value = false; + bool include_lock = false; + bool is_pissimistic_lock = false; + std::unordered_map kvs; + std::unordered_map lock_keys; + PrepareDataAndLock(short_value, ::dingodb::pb::store::Op::Put, include_lock, is_pissimistic_lock, kvs, lock_keys); + + butil::Status ok; + pb::store::TxnPessimisticLockResponse response; + auto ctx = std::make_shared(); + ctx->SetRegionId(region_id); + ctx->SetCfName(Constant::kStoreDataCF); + ctx->SetResponse(&response); + std::vector mutations; + std::vector expected_kvs; + EXPECT_NE(kvs.begin(), kvs.end()); + std::string primary_lock = kvs.begin()->first; + int64_t target_start_ts = start_ts; + int64_t target_for_update_ts = start_ts; + int64_t target_lock_ttl = lock_ttl; + bool return_values = true; + + for (auto const &kv : kvs) { + pb::store::Mutation mutation; + mutation.set_op(::dingodb::pb::store::Op::Lock); + mutation.set_key(kv.first); + mutations.emplace_back(mutation); + } - lambda_txn_set_kv_function(key_value); + auto status = TxnEngineHelper::PessimisticLock(engine, mono_engine, ctx, mutations, primary_lock, target_start_ts, + target_lock_ttl, target_for_update_ts, return_values, expected_kvs); - std::string key = key_value.key(); - std::string value = key_value.value(); - keys.push_back(key); + EXPECT_EQ(status.ok(), true); + EXPECT_EQ(expected_kvs.size(), 0); + EXPECT_GT(response.txn_result_size(), 0); - std::string s = StrToHex(key, " "); - LOG(INFO) << "s : " << s; + for (auto const &txn_result : response.txn_result()) { + EXPECT_EQ(txn_result.write_conflict().reason(), + ::dingodb::pb::store::WriteConflict_Reason::WriteConflict_Reason_PessimisticRetry); + } + DeleteRange(); } - // 8 + // KeyIsLocked { - pb::common::KeyValue key_value; - std::vector record; - record.reserve(6); - std::any any_bool = std::optional(true); - record.emplace_back(std::move(any_bool)); - - std::any any_int = std::optional(8); - record.emplace_back(std::move(any_int)); - - std::any any_float = std::optional(8.23); - record.emplace_back(std::move(any_float)); - - std::any any_long = std::optional(800); - record.emplace_back(std::move(any_long)); + bool short_value = false; + bool include_lock = true; + bool is_pissimistic_lock = true; + std::unordered_map kvs; + std::unordered_map lock_keys; + PrepareDataAndLock(short_value, ::dingodb::pb::store::Op::Put, include_lock, is_pissimistic_lock, kvs, lock_keys); + + butil::Status ok; + pb::store::TxnPessimisticLockResponse response; + auto ctx = std::make_shared(); + ctx->SetRegionId(region_id); + ctx->SetCfName(Constant::kStoreDataCF); + ctx->SetResponse(&response); + std::vector mutations; + std::vector expected_kvs; + EXPECT_NE(kvs.begin(), kvs.end()); + std::string primary_lock = kvs.begin()->first; + int64_t target_start_ts = end_ts + 1; + int64_t target_for_update_ts = end_ts + 1; + int64_t target_lock_ttl = lock_ttl; + bool return_values = true; + + for (auto const &kv : kvs) { + pb::store::Mutation mutation; + mutation.set_op(::dingodb::pb::store::Op::Lock); + mutation.set_key(kv.first); + mutations.emplace_back(mutation); + } - std::any any_double = std::optional(8.4545); - record.emplace_back(std::move(any_double)); + auto status = TxnEngineHelper::PessimisticLock(engine, mono_engine, ctx, mutations, primary_lock, target_start_ts, + target_lock_ttl, target_for_update_ts, return_values, expected_kvs); - std::any any_string = std::optional>(std::nullopt); - record.emplace_back(std::move(any_string)); + EXPECT_EQ(status.ok(), true); + EXPECT_EQ(expected_kvs.size(), 0); + EXPECT_GT(response.txn_result_size(), 0); - int ret = record_encoder.Encode('r', record, *key_value.mutable_key(), *key_value.mutable_value()); + for (auto const &txn_result : response.txn_result()) { + auto found = lock_keys.find(txn_result.locked().key()); + EXPECT_NE(found, lock_keys.end()); + } + DeleteRange(); + } - EXPECT_EQ(ret, 0); + // Lock type not match + { + bool short_value = false; + bool include_lock = true; + bool is_pissimistic_lock = false; + std::unordered_map kvs; + std::unordered_map lock_keys; + PrepareDataAndLock(short_value, ::dingodb::pb::store::Op::Put, include_lock, is_pissimistic_lock, kvs, lock_keys); + + butil::Status ok; + pb::store::TxnPessimisticLockResponse response; + auto ctx = std::make_shared(); + ctx->SetRegionId(region_id); + ctx->SetCfName(Constant::kStoreDataCF); + ctx->SetResponse(&response); + std::vector mutations; + std::vector expected_kvs; + EXPECT_NE(kvs.begin(), kvs.end()); + std::string primary_lock = kvs.begin()->first; + int64_t target_start_ts = end_ts + 1; + int64_t target_for_update_ts = end_ts + 1; + int64_t target_lock_ttl = lock_ttl; + bool return_values = true; + + for (auto const &kv : kvs) { + pb::store::Mutation mutation; + mutation.set_op(::dingodb::pb::store::Op::Lock); + mutation.set_key(kv.first); + mutations.emplace_back(mutation); + } - lambda_txn_set_kv_function(key_value); + auto status = TxnEngineHelper::PessimisticLock(engine, mono_engine, ctx, mutations, primary_lock, target_start_ts, + target_lock_ttl, target_for_update_ts, return_values, expected_kvs); - std::string key = key_value.key(); - std::string value = key_value.value(); - keys.push_back(key); + EXPECT_EQ(status.ok(), true); + EXPECT_EQ(expected_kvs.size(), 0); + EXPECT_GT(response.txn_result_size(), 0); - std::string s = StrToHex(key, " "); - LOG(INFO) << "s : " << s; + for (auto const &txn_result : response.txn_result()) { + auto found = lock_keys.find(txn_result.locked().key()); + EXPECT_NE(found, lock_keys.end()); + } + DeleteRange(); } -} -TEST_F(TxnPessimisticLockTest, Open) { - butil::Status ok; - - // + // lock key is Deleted, return value is empty. { - pb_coprocessor.set_schema_version(1); + bool short_value = false; + bool include_lock = false; + bool is_pissimistic_lock = false; + std::unordered_map kvs; + std::unordered_map lock_keys; + PrepareDataAndLock(short_value, ::dingodb::pb::store::Op::Delete, include_lock, is_pissimistic_lock, kvs, + lock_keys); + + butil::Status ok; + pb::store::TxnPessimisticLockResponse response; + auto ctx = std::make_shared(); + ctx->SetRegionId(region_id); + ctx->SetCfName(Constant::kStoreDataCF); + ctx->SetResponse(&response); + std::vector mutations; + std::vector expected_kvs; + std::string primary_lock = kvs.begin()->first; + int64_t target_start_ts = end_ts + 1; + int64_t target_for_update_ts = end_ts + 1; + int64_t target_lock_ttl = lock_ttl; // 2034-07-11 14:21:21 + bool return_values = true; + + for (auto const &kv : kvs) { + pb::store::Mutation mutation; + mutation.set_op(::dingodb::pb::store::Op::Lock); + mutation.set_key(kv.first); + mutations.emplace_back(mutation); + } - auto *original_schema = pb_coprocessor.mutable_original_schema(); - original_schema->set_common_id(1); + auto status = TxnEngineHelper::PessimisticLock(engine, mono_engine, ctx, mutations, primary_lock, target_start_ts, + target_lock_ttl, target_for_update_ts, return_values, expected_kvs); - auto *schema1 = original_schema->add_schema(); - { - schema1->set_type(::dingodb::pb::common::Schema_Type::Schema_Type_BOOL); - schema1->set_is_key(true); - schema1->set_is_nullable(true); - schema1->set_index(0); - schema1->set_name("name_bool"); + EXPECT_EQ(status.ok(), true); + EXPECT_EQ(mutations.size(), expected_kvs.size()); + for (auto const &kv : expected_kvs) { + auto found = kvs.find(kv.key()); + EXPECT_NE(found, kvs.end()); + if (found != kvs.end()) { + EXPECT_EQ(kv.value(), ""); + } } + DeleteRange(); + } - auto *schema2 = original_schema->add_schema(); + // Over write lock info(update lock info) + { + // prepare data + bool short_value = false; + bool include_lock = false; + bool is_pissimistic_lock = false; + std::unordered_map kvs; + std::unordered_map lock_keys; + PrepareDataAndLock(short_value, ::dingodb::pb::store::Op::Put, include_lock, is_pissimistic_lock, kvs, lock_keys); { - schema2->set_type(::dingodb::pb::common::Schema_Type::Schema_Type_INTEGER); - schema2->set_is_key(false); - schema2->set_is_nullable(true); - schema2->set_index(1); - schema2->set_name("name_int"); - } + butil::Status ok; + pb::store::TxnPessimisticLockResponse response; + auto ctx = std::make_shared(); + ctx->SetRegionId(region_id); + ctx->SetCfName(Constant::kStoreDataCF); + ctx->SetResponse(&response); + std::vector mutations; + std::vector expected_kvs; + std::string primary_lock = kvs.begin()->first; + int64_t target_start_ts = end_ts + 1; + int64_t target_for_update_ts = end_ts + 10; + int64_t target_lock_ttl = lock_ttl; // 2034-07-11 14:21:21 + bool return_values = true; + + for (auto const &kv : kvs) { + pb::store::Mutation mutation; + mutation.set_op(::dingodb::pb::store::Op::Lock); + mutation.set_key(kv.first); + mutations.emplace_back(mutation); + } - auto *schema3 = original_schema->add_schema(); - { - schema3->set_type(::dingodb::pb::common::Schema_Type::Schema_Type_FLOAT); - schema3->set_is_key(false); - schema3->set_is_nullable(true); - schema3->set_index(2); - schema3->set_name("name_float"); + auto status = + TxnEngineHelper::PessimisticLock(engine, mono_engine, ctx, mutations, primary_lock, target_start_ts, + target_lock_ttl, target_for_update_ts, return_values, expected_kvs); + + EXPECT_EQ(status.ok(), true); + EXPECT_EQ(mutations.size(), expected_kvs.size()); + for (auto const &kv : expected_kvs) { + auto found = kvs.find(kv.key()); + EXPECT_NE(found, kvs.end()); + if (found != kvs.end()) { + EXPECT_EQ(kv.value(), found->second); + } + } } - auto *schema4 = original_schema->add_schema(); - { - schema4->set_type(::dingodb::pb::common::Schema_Type::Schema_Type_LONG); - schema4->set_is_key(false); - schema4->set_is_nullable(true); - schema4->set_index(3); - schema4->set_name("name_int64"); + butil::Status ok; + pb::store::TxnPessimisticLockResponse response; + auto ctx = std::make_shared(); + ctx->SetRegionId(region_id); + ctx->SetCfName(Constant::kStoreDataCF); + ctx->SetResponse(&response); + std::vector mutations; + std::vector expected_kvs; + std::string primary_lock = kvs.begin()->first; + int64_t target_start_ts = end_ts + 1; + int64_t target_for_update_ts = end_ts + 20; + int64_t target_lock_ttl = lock_ttl; // 2034-07-11 14:21:21 + bool return_values = true; + + for (auto const &kv : kvs) { + pb::store::Mutation mutation; + mutation.set_op(::dingodb::pb::store::Op::Lock); + mutation.set_key(kv.first); + mutations.emplace_back(mutation); } - auto *schema5 = original_schema->add_schema(); - { - schema5->set_type(::dingodb::pb::common::Schema_Type::Schema_Type_DOUBLE); - schema5->set_is_key(true); - schema5->set_is_nullable(true); - schema5->set_index(4); - schema5->set_name("name_double"); - } + auto status = TxnEngineHelper::PessimisticLock(engine, mono_engine, ctx, mutations, primary_lock, target_start_ts, + target_lock_ttl, target_for_update_ts, return_values, expected_kvs); - auto *schema6 = original_schema->add_schema(); - { - schema6->set_type(::dingodb::pb::common::Schema_Type::Schema_Type_STRING); - schema6->set_is_key(true); - schema6->set_is_nullable(true); - schema6->set_index(5); - schema6->set_name("name_string"); + EXPECT_EQ(status.ok(), true); + EXPECT_EQ(mutations.size(), expected_kvs.size()); + for (auto const &kv : expected_kvs) { + auto found = kvs.find(kv.key()); + EXPECT_NE(found, kvs.end()); + if (found != kvs.end()) { + EXPECT_EQ(kv.value(), found->second); + } } - auto *selection_columns = pb_coprocessor.mutable_selection_columns(); - selection_columns->Add(0); - selection_columns->Add(1); - selection_columns->Add(2); - selection_columns->Add(3); - selection_columns->Add(4); - selection_columns->Add(5); - - pb_coprocessor.set_rel_expr(Helper::StringToHex(std::string_view("7134021442480000930400"))); + DeleteRange(); + } - auto *result_schema = pb_coprocessor.mutable_result_schema(); - result_schema->set_common_id(1); + // Duplicated command + { + // prepare data + bool short_value = false; + bool include_lock = false; + bool is_pissimistic_lock = false; + std::unordered_map kvs; + std::unordered_map lock_keys; + PrepareDataAndLock(short_value, ::dingodb::pb::store::Op::Put, include_lock, is_pissimistic_lock, kvs, lock_keys); { - auto *schema1 = result_schema->add_schema(); - { - schema1->set_type(::dingodb::pb::common::Schema_Type::Schema_Type_BOOL); - schema1->set_is_key(true); - schema1->set_is_nullable(true); - schema1->set_index(0); - schema1->set_name("name_bool"); + butil::Status ok; + pb::store::TxnPessimisticLockResponse response; + auto ctx = std::make_shared(); + ctx->SetRegionId(region_id); + ctx->SetCfName(Constant::kStoreDataCF); + ctx->SetResponse(&response); + std::vector mutations; + std::vector expected_kvs; + std::string primary_lock = kvs.begin()->first; + int64_t target_start_ts = end_ts + 1; + int64_t target_for_update_ts = end_ts + 10; + int64_t target_lock_ttl = lock_ttl; // 2034-07-11 14:21:21 + bool return_values = true; + + for (auto const &kv : kvs) { + pb::store::Mutation mutation; + mutation.set_op(::dingodb::pb::store::Op::Lock); + mutation.set_key(kv.first); + mutations.emplace_back(mutation); } - auto *schema2 = result_schema->add_schema(); - { - schema2->set_type(::dingodb::pb::common::Schema_Type::Schema_Type_INTEGER); - schema2->set_is_key(false); - schema2->set_is_nullable(true); - schema2->set_index(1); - schema2->set_name("name_int"); - } - - auto *schema3 = result_schema->add_schema(); - { - schema3->set_type(::dingodb::pb::common::Schema_Type::Schema_Type_FLOAT); - schema3->set_is_key(false); - schema3->set_is_nullable(true); - schema3->set_index(2); - schema3->set_name("name_float"); - } - - auto *schema4 = result_schema->add_schema(); - { - schema4->set_type(::dingodb::pb::common::Schema_Type::Schema_Type_LONG); - schema4->set_is_key(false); - schema4->set_is_nullable(true); - schema4->set_index(3); - schema4->set_name("name_int64"); + auto status = + TxnEngineHelper::PessimisticLock(engine, mono_engine, ctx, mutations, primary_lock, target_start_ts, + target_lock_ttl, target_for_update_ts, return_values, expected_kvs); + + EXPECT_EQ(status.ok(), true); + EXPECT_EQ(mutations.size(), expected_kvs.size()); + for (auto const &kv : expected_kvs) { + auto found = kvs.find(kv.key()); + EXPECT_NE(found, kvs.end()); + if (found != kvs.end()) { + EXPECT_EQ(kv.value(), found->second); + } } + } - auto *schema5 = result_schema->add_schema(); - { - schema5->set_type(::dingodb::pb::common::Schema_Type::Schema_Type_DOUBLE); - schema5->set_is_key(true); - schema5->set_is_nullable(true); - schema5->set_index(4); - schema5->set_name("name_double"); + { + butil::Status ok; + pb::store::TxnPessimisticLockResponse response; + auto ctx = std::make_shared(); + ctx->SetRegionId(region_id); + ctx->SetCfName(Constant::kStoreDataCF); + ctx->SetResponse(&response); + std::vector mutations; + std::vector expected_kvs; + std::string primary_lock = kvs.begin()->first; + int64_t target_start_ts = end_ts + 1; + int64_t target_for_update_ts = end_ts + 10; + int64_t target_lock_ttl = lock_ttl; // 2034-07-11 14:21:21 + bool return_values = true; + + for (auto const &kv : kvs) { + pb::store::Mutation mutation; + mutation.set_op(::dingodb::pb::store::Op::Lock); + mutation.set_key(kv.first); + mutations.emplace_back(mutation); } - auto *schema6 = result_schema->add_schema(); - { - schema6->set_type(::dingodb::pb::common::Schema_Type::Schema_Type_STRING); - schema6->set_is_key(true); - schema6->set_is_nullable(true); - schema6->set_index(5); - schema6->set_name("name_string"); + auto status = + TxnEngineHelper::PessimisticLock(engine, mono_engine, ctx, mutations, primary_lock, target_start_ts, + target_lock_ttl, target_for_update_ts, return_values, expected_kvs); + + EXPECT_EQ(status.ok(), true); + EXPECT_EQ(mutations.size(), expected_kvs.size()); + for (auto const &kv : expected_kvs) { + auto found = kvs.find(kv.key()); + EXPECT_NE(found, kvs.end()); + if (found != kvs.end()) { + EXPECT_EQ(kv.value(), found->second); + } } } - } -} - -TEST_F(TxnPessimisticLockTest, Scan) { -#if !defined(TEST_COPROCESSOR_V2_MOCK) - GTEST_SKIP() << "TEST_COPROCESSOR_V2_MOCK not defined"; -#endif - butil::Status ok; - - std::sort(keys.begin(), keys.end()); - std::string my_min_key(keys.front()); - std::string my_max_key(Helper::PrefixNext(keys.back())); - - std::string my_min_key_s = StrToHex(my_min_key, " "); - LOG(INFO) << "my_min_key_s : " << my_min_key_s; - - std::string my_max_key_s = StrToHex(my_max_key, " "); - LOG(INFO) << "my_max_key_s : " << my_max_key_s; - - pb::common::Range range; - // range.set_start_key(my_min_key); - range.set_start_key(my_min_key); - range.set_end_key(my_max_key); - - bool key_only = false; - size_t limit = 10; - std::vector kvs; - bool is_reverse = false; - pb::store::TxnResultInfo txn_result_info; - std::string end_key; - bool has_more = false; - std::set resolved_locks = {}; - size_t cnt = 0; - - ok = - TxnEngineHelper::Scan(engine, pb::store::IsolationLevel::SnapshotIsolation, ++end_ts, range, limit, key_only, - is_reverse, resolved_locks, false, pb_coprocessor, txn_result_info, kvs, has_more, end_key); - - cnt = kvs.size(); - - LOG(INFO) << "ExecuteTxn key_values cnt : " << cnt; - EXPECT_EQ(cnt, keys.size()); - EXPECT_FALSE(has_more); + DeleteRange(); + } } TEST_F(TxnPessimisticLockTest, KvDeleteRange) { DeleteRange(); }