22#include <gtest/gtest.h>
32using ::resdb::testing::EqualsProto;
34using ::testing::AtLeast;
35using ::testing::Invoke;
36using ::testing::Pointee;
37using ::testing::Return;
47class MockConsensusManager :
public ConsensusManager {
49 MockConsensusManager(
const ResDBConfig& config) : ConsensusManager(config) {}
51 MOCK_METHOD(std::unique_ptr<ReplicaCommunicator>, GetReplicaClient,
52 (
const std::vector<ReplicaInfo>&,
bool), (
override));
53 MOCK_METHOD(
int, ConsensusCommit,
54 (std::unique_ptr<Context>, std::unique_ptr<Request>), (
override));
55 MOCK_METHOD(std::vector<ReplicaInfo>, GetReplicas, (), (
override));
56 MOCK_METHOD(std::vector<ReplicaInfo>, GetClientReplicas, (), (
override));
59 void BroadCast(
const Request& request) {
62 void UpdateBroadCastClient() {
66 ReplicaCommunicator* GetBroadCastClient() {
71 int Dispatch(std::unique_ptr<Context> context,
72 std::unique_ptr<Request> request) {
77class ConsensusManagerTest :
public Test {
79 ConsensusManagerTest()
83 config_(replicas_, self_info_, KeyInfo(), CertificateInfo()) {
85 auto region =
data.add_region();
86 region->set_region_id(1);
87 for (ReplicaInfo info :
config_.GetReplicaInfos()) {
88 *region->add_replica_info() = info;
94 impl_ = std::make_unique<MockConsensusManager>(config_);
96 ON_CALL(*impl_, GetReplicas).WillByDefault(Return(replicas_));
99 ~ConsensusManagerTest() { impl_->Stop(); }
105 std::unique_ptr<MockConsensusManager> impl_;
108TEST_F(ConsensusManagerTest, SendHB) {
109 std::promise<bool> hb;
110 std::future<bool> hb_done = hb.get_future();
111 EXPECT_CALL(*impl_, GetReplicaClient)
114 Invoke([&](
const std::vector<ReplicaInfo>& replicas,
bool) {
115 auto client = std::make_unique<MockReplicaCommunicator>(replicas);
116 EXPECT_CALL(*client, SendHeartBeat)
117 .WillRepeatedly(Invoke([&](
const Request& hb_info) {
127TEST_F(ConsensusManagerTest, SendHBToClient) {
128 std::promise<bool> hb;
129 std::future<bool> hb_done = hb.get_future();
131 EXPECT_CALL(*impl_, GetClientReplicas)
133 .WillRepeatedly(Invoke([&]() {
134 ReplicaInfo client_info;
135 client_info.set_ip(
"127.0.0.1");
136 client_info.set_port(54321);
137 return std::vector<ReplicaInfo>({client_info});
140 EXPECT_CALL(*impl_, GetReplicaClient)
143 Invoke([&](
const std::vector<ReplicaInfo>& replicas,
bool) {
144 EXPECT_EQ(replicas.size(), 3);
146 for (
auto& info : replicas) {
147 if (info.ip() ==
"127.0.0.1" && info.port() == 54321) {
152 auto client = std::make_unique<MockReplicaCommunicator>(replicas);
153 EXPECT_CALL(*client, SendHeartBeat)
154 .WillRepeatedly(Invoke([&](
const Request& hb_info) {
164TEST_F(ConsensusManagerTest, SendHBToClientWithTworegion) {
166 auto region =
data.add_region();
167 region->set_region_id(1);
171 region =
data.add_region();
172 region->set_region_id(2);
176 impl_ = std::make_unique<MockConsensusManager>(
config_);
178 std::promise<bool> hb;
179 std::future<bool> hb_done = hb.get_future();
181 EXPECT_CALL(*impl_, GetClientReplicas)
183 .WillRepeatedly(Invoke([&]() {
184 ReplicaInfo client_info;
185 client_info.set_ip(
"127.0.0.1");
186 client_info.set_port(54321);
187 return std::vector<ReplicaInfo>({client_info});
190 EXPECT_CALL(*impl_, GetReplicaClient)
193 Invoke([&](
const std::vector<ReplicaInfo>& replicas,
bool) {
194 EXPECT_EQ(replicas.size(), 5);
196 for (
auto& info : replicas) {
197 if (info.ip() ==
"127.0.0.1" && info.port() == 54321) {
202 auto client = std::make_unique<MockReplicaCommunicator>(replicas);
203 EXPECT_CALL(*client, SendHeartBeat)
204 .WillRepeatedly(Invoke([&](
const Request& hb_info) {
214TEST_F(ConsensusManagerTest, BroadCast) {
215 std::promise<bool> bc;
216 std::future<bool> bc_done = bc.get_future();
217 EXPECT_CALL(*impl_, GetReplicaClient)
219 Invoke([&](
const std::vector<ReplicaInfo>& replicas,
bool long_conn) {
220 EXPECT_EQ(replicas.size(),
replicas_.size());
221 auto client = std::make_unique<MockReplicaCommunicator>(replicas);
222 EXPECT_CALL(*client, SendMessage(_))
224 Invoke([&](
const google::protobuf::Message& request) {
235 impl_->UpdateBroadCastClient();
236 impl_->BroadCast(Request());
240TEST_F(ConsensusManagerTest, DiscoverNewClient) {
241 config_.SetSignatureVerifierEnabled(
false);
242 impl_ = std::make_unique<MockConsensusManager>(
config_);
245 EXPECT_CALL(*impl_, GetReplicaClient)
247 Invoke([&](
const std::vector<ReplicaInfo>& replicas,
bool long_conn) {
248 EXPECT_EQ(replicas.size(),
replicas_.size());
249 auto client = std::make_unique<MockReplicaCommunicator>(replicas);
254 auto* public_key = hb.add_public_keys();
256 public_key->mutable_public_key_info()->set_ip(
"127.0.0.1");
257 public_key->mutable_public_key_info()->set_port(12345);
258 public_key->mutable_public_key_info()->set_node_id(5);
259 public_key->mutable_public_key_info()->set_type(CertificateKeyInfo::CLIENT);
261 auto request = std::make_unique<Request>();
262 request->set_type(Request::TYPE_HEART_BEAT);
263 hb.SerializeToString(request->mutable_data());
265 EXPECT_EQ(impl_->Dispatch(std::make_unique<Context>(), std::move(request)),
268 ReplicaCommunicator* bc_client = impl_->GetBroadCastClient();
269 EXPECT_NE(bc_client,
nullptr);
271 std::vector<ReplicaInfo> client_infos = bc_client->GetClientReplicas();
272 EXPECT_EQ(client_infos.size(), 1);
275TEST_F(ConsensusManagerTest, DispatchOK) {
276 Request expected_request;
277 expected_request.set_type(Request::TYPE_CLIENT_REQUEST);
279 ConsensusCommit(_, Pointee(EqualsProto(expected_request))))
284 auto request = std::make_unique<Request>();
285 request->set_type(Request::TYPE_HEART_BEAT);
287 replica_info.SerializeToString(request->mutable_data());
289 EXPECT_EQ(impl_->Dispatch(std::make_unique<Context>(), std::move(request)),
294 auto request = std::make_unique<Request>();
295 request->set_type(Request::TYPE_CLIENT_REQUEST);
296 EXPECT_EQ(impl_->Dispatch(std::make_unique<Context>(), std::move(request)),
virtual void BroadCast(const Request &request)
void UpdateBroadCastClient()
ReplicaCommunicator * GetBroadCastClient()
virtual int Dispatch(std::unique_ptr< Context > context, std::unique_ptr< Request > request)
static Stats * GetGlobalStats(int sleep_seconds=5)
ReplicaInfo GenerateReplicaInfo(int id, const std::string &ip, int port)
TEST_F(ResDBTest, TestPBFTService)
std::vector< ReplicaInfo > replicas_
std::unique_ptr< ResDBConfig > config_