Loading...
Searching...
No Matches
commitment_test.cpp
Go to the documentation of this file.
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
21
22#include <glog/logging.h>
23#include <gmock/gmock.h>
24#include <gtest/gtest.h>
25
26#include <future>
27
35
36namespace resdb {
37namespace {
38
39using ::resdb::testing::EqualsProto;
40using ::testing::Invoke;
41using ::testing::Return;
42using ::testing::Test;
43
44ResDBConfig GenerateConfig() {
45 ResConfigData data;
46 data.set_duplicate_check_frequency_useconds(100000);
47 return ResDBConfig({GenerateReplicaInfo(1, "127.0.0.1", 1234),
48 GenerateReplicaInfo(2, "127.0.0.1", 1235),
49 GenerateReplicaInfo(3, "127.0.0.1", 1236),
50 GenerateReplicaInfo(4, "127.0.0.1", 1237)},
51 GenerateReplicaInfo(1, "127.0.0.1", 1234), data);
52}
53
54class CommitmentTest : public Test {
55 public:
56 CommitmentTest()
57 : // just set the monitor time to 1 second to return early.
58 global_stats_(Stats::GetGlobalStats(1)),
59 config_(GenerateConfig()),
62 message_manager_(std::make_unique<MessageManager>(
65 std::make_unique<Commitment>(config_, message_manager_.get(),
67
68 std::unique_ptr<Context> GetContext() {
69 auto context = std::make_unique<Context>();
70 context->signature.set_signature("signature");
71 return context;
72 }
73
74 int AddProposeMsg(int sender_id, bool need_resp = false, int proxy_id = 1) {
75 auto context = std::make_unique<Context>();
76 context->signature.set_signature("signature");
77
78 Request request;
79 request.set_current_view(1);
80 request.set_seq(1);
81 request.set_type(Request::TYPE_PRE_PREPARE);
82 request.set_sender_id(sender_id);
83 request.set_need_response(need_resp);
84 request.set_proxy_id(proxy_id);
85 request.set_data(data_);
86
87 return commitment_->ProcessProposeMsg(std::move(context),
88 std::make_unique<Request>(request));
89 }
90
91 int AddPrepareMsg(int sender_id) {
92 auto context = std::make_unique<Context>();
93 context->signature.set_signature("signature");
94
95 Request request;
96 request.set_current_view(1);
97 request.set_seq(1);
98 request.set_type(Request::TYPE_PREPARE);
99 request.set_sender_id(sender_id);
100 return commitment_->ProcessPrepareMsg(std::move(context),
101 std::make_unique<Request>(request));
102 }
103
104 int AddCommitMsg(int sender_id) {
105 auto context = std::make_unique<Context>();
106 context->signature.set_signature("signature");
107
108 Request request;
109 request.set_current_view(1);
110 request.set_seq(1);
111 request.set_type(Request::TYPE_COMMIT);
112 request.set_sender_id(sender_id);
113 return commitment_->ProcessCommitMsg(std::move(context),
114 std::make_unique<Request>(request));
115 }
116
117 protected:
119 ResDBConfig config_;
120 SystemInfo system_info_;
121 CheckPointManager checkpoint_manager_;
122 MockReplicaCommunicator replica_communicator_;
123 MockSignatureVerifier verifier_;
124 std::unique_ptr<MessageManager> message_manager_;
125 std::unique_ptr<Commitment> commitment_;
126 std::string data_;
127};
128
129TEST_F(CommitmentTest, NotContesxt) {
130 EXPECT_EQ(
131 commitment_->ProcessProposeMsg(nullptr, std::make_unique<Request>()), -2);
132 EXPECT_EQ(
133 commitment_->ProcessPrepareMsg(nullptr, std::make_unique<Request>()), -2);
134 EXPECT_EQ(commitment_->ProcessCommitMsg(nullptr, std::make_unique<Request>()),
135 -2);
136}
137
138TEST_F(CommitmentTest, NoSignature) {
139 EXPECT_EQ(commitment_->ProcessProposeMsg(std::make_unique<Context>(),
140 std::make_unique<Request>()),
141 -2);
142 EXPECT_EQ(commitment_->ProcessPrepareMsg(std::make_unique<Context>(),
143 std::make_unique<Request>()),
144 -2);
145 EXPECT_EQ(commitment_->ProcessCommitMsg(std::make_unique<Context>(),
146 std::make_unique<Request>()),
147 -2);
148}
149
150TEST_F(CommitmentTest, NoPrimary) {
152 EXPECT_EQ(AddProposeMsg(Request::TYPE_PRE_PREPARE, 1), -2);
153}
154
155TEST_F(CommitmentTest, NewRequest) {
156 auto context = std::make_unique<Context>();
157 context->signature.set_signature("signature");
158 Request request;
159 request.set_data("data");
160
161 std::promise<bool> propose_done;
162 std::future<bool> propose_done_future = propose_done.get_future();
163 EXPECT_CALL(replica_communicator_, BroadCast).WillOnce(Invoke([&]() {
164 propose_done.set_value(true);
165 }));
166
167 EXPECT_CALL(verifier_,
168 VerifyMessage(::testing::_, EqualsProto(SignatureInfo())))
169 .WillOnce(Return(true));
170
171 EXPECT_EQ(commitment_->ProcessNewRequest(std::move(context),
172 std::make_unique<Request>(request)),
173 0);
174 propose_done_future.get();
175}
176
177TEST_F(CommitmentTest, SeqConsumeAll) {
178 config_.SetMaxProcessTxn(2);
179 commitment_ = nullptr;
180 message_manager_ = std::make_unique<MessageManager>(
182 commitment_ = std::make_unique<Commitment>(
184 std::promise<bool> done;
185 std::future<bool> done_future = done.get_future();
186 EXPECT_CALL(verifier_,
187 VerifyMessage(::testing::_, EqualsProto(SignatureInfo())))
188 .WillRepeatedly(Return(true));
189 for (int i = 0; i < 3; ++i) {
190 std::unique_ptr<MockNetChannel> channel =
191 std::make_unique<MockNetChannel>("127.0.0.1", 0);
192 auto context = std::make_unique<Context>();
193 context->signature.set_signature("signature");
194 Request request;
195 request.set_data("sig" + std::to_string(i));
196 request.set_hash("hash" + std::to_string(i));
197 if (i < 2) {
198 EXPECT_EQ(commitment_->ProcessNewRequest(
199 std::move(context), std::make_unique<Request>(request)),
200 0);
201 } else {
202 EXPECT_EQ(commitment_->ProcessNewRequest(
203 std::move(context), std::make_unique<Request>(request)),
204 -2);
205 }
206 }
207}
208
209TEST_F(CommitmentTest, ProposeMsgWithoutSignature) {
211 EXPECT_CALL(replica_communicator_, BroadCast).Times(0);
212 EXPECT_CALL(verifier_,
213 VerifyMessage(::testing::_, EqualsProto(SignatureInfo())))
214 .WillOnce(Return(false));
215 EXPECT_EQ(AddProposeMsg(Request::TYPE_PRE_PREPARE, 1), -2);
216}
217
218TEST_F(CommitmentTest, ProposeMsg) {
220 BatchUserRequest request;
221 request.SerializeToString(&data_);
222 EXPECT_CALL(replica_communicator_, BroadCast).Times(1);
223 EXPECT_CALL(verifier_, VerifyMessage(data_, EqualsProto(SignatureInfo())))
224 .WillOnce(Return(true));
225
226 EXPECT_EQ(AddProposeMsg(Request::TYPE_PRE_PREPARE, 1), 0);
227}
228
229TEST_F(CommitmentTest, ProposeMsgOnlyBCOnce) {
231 BatchUserRequest request;
232 request.SerializeToString(&data_);
233 EXPECT_CALL(replica_communicator_, BroadCast).Times(1);
234 EXPECT_CALL(verifier_, VerifyMessage(data_, EqualsProto(SignatureInfo())))
235 .WillRepeatedly(Return(true));
236
237 EXPECT_EQ(AddProposeMsg(Request::TYPE_PRE_PREPARE, 1), 0);
238 EXPECT_EQ(AddProposeMsg(Request::TYPE_PRE_PREPARE, 2), -2);
239}
240
241TEST_F(CommitmentTest, ProcessPrepareMsg) {
242 EXPECT_CALL(replica_communicator_, BroadCast).Times(2);
243
244 EXPECT_EQ(AddProposeMsg(1), 0);
245
246 EXPECT_EQ(AddPrepareMsg(1), 0);
247 EXPECT_EQ(AddPrepareMsg(2), 0);
248 EXPECT_EQ(AddPrepareMsg(3), 0);
249}
250
251TEST_F(CommitmentTest, ProcessPrepareMsgNotEnough) {
252 EXPECT_CALL(replica_communicator_, BroadCast).Times(1);
253
254 EXPECT_EQ(AddProposeMsg(1), 0);
255
256 EXPECT_EQ(AddPrepareMsg(1), 0);
257}
258
259TEST_F(CommitmentTest, ProcessPrepareMsgNoProposeMsg) {
260 EXPECT_CALL(replica_communicator_, BroadCast).Times(0);
261
262 EXPECT_EQ(AddPrepareMsg(1), 0);
263 EXPECT_EQ(AddPrepareMsg(2), 0);
264 EXPECT_EQ(AddPrepareMsg(3), 0);
265}
266
267TEST_F(CommitmentTest, ProcessPrepareMsgProposeMsgDelay) {
268 EXPECT_CALL(replica_communicator_, BroadCast).Times(2);
269 EXPECT_EQ(AddPrepareMsg(2), 0);
270 EXPECT_EQ(AddPrepareMsg(3), 0);
271
272 EXPECT_EQ(AddProposeMsg(1), 0);
273
274 EXPECT_EQ(AddPrepareMsg(1), 0);
275}
276
277TEST_F(CommitmentTest, ProcessCommitMsg) {
278 EXPECT_CALL(replica_communicator_, BroadCast)
279 .Times(2); // 1 propose + 1 prepare
280
281 EXPECT_EQ(AddProposeMsg(1), 0);
282
283 EXPECT_EQ(AddPrepareMsg(1), 0);
284 EXPECT_EQ(AddPrepareMsg(2), 0);
285 EXPECT_EQ(AddPrepareMsg(3), 0);
286
287 EXPECT_EQ(AddCommitMsg(1), 0);
288 EXPECT_EQ(AddCommitMsg(2), 0);
289 EXPECT_EQ(AddCommitMsg(3), 0);
290}
291
292TEST_F(CommitmentTest, ProcessCommitMsgProposeDelay) {
293 EXPECT_CALL(replica_communicator_, BroadCast)
294 .Times(2); // 1 propose + 1 prepare
295
296 EXPECT_EQ(AddPrepareMsg(2), 0);
297 EXPECT_EQ(AddPrepareMsg(3), 0);
298
299 EXPECT_EQ(AddCommitMsg(2), 0);
300 EXPECT_EQ(AddCommitMsg(3), 0);
301
302 EXPECT_EQ(AddProposeMsg(1), 0);
303 EXPECT_EQ(AddPrepareMsg(1), 0);
304
305 EXPECT_EQ(AddCommitMsg(1), 0);
306}
307
308TEST_F(CommitmentTest, ProcessCommitMsgWithDuplicated) {
309 EXPECT_CALL(replica_communicator_, BroadCast)
310 .Times(2); // 1 propose + 1 prepare
311
312 EXPECT_EQ(AddProposeMsg(1), 0);
313 EXPECT_EQ(AddProposeMsg(1), -2);
314
315 EXPECT_EQ(AddPrepareMsg(1), 0);
316 EXPECT_EQ(AddPrepareMsg(2), 0);
317 EXPECT_EQ(AddPrepareMsg(2), 0);
318 EXPECT_EQ(AddPrepareMsg(3), 0);
319
320 EXPECT_EQ(AddCommitMsg(1), 0);
321 EXPECT_EQ(AddCommitMsg(2), 0);
322 EXPECT_EQ(AddCommitMsg(3), 0);
323 EXPECT_EQ(AddCommitMsg(3), -2);
324}
325
326TEST_F(CommitmentTest, ProcessCommitMsgWithResponse) {
327 EXPECT_CALL(replica_communicator_, BroadCast).Times(2);
328
329 std::promise<bool> done;
330 std::future<bool> done_future = done.get_future();
331
332 BatchUserResponse batch_resp;
333
334 batch_resp.set_primary_id(1);
335 batch_resp.set_proxy_id(1);
336 batch_resp.set_seq(1);
337 batch_resp.set_current_view(1);
338
339 // Response Msg
340 Request resp_request;
341 resp_request.set_type(Request::TYPE_RESPONSE);
342 resp_request.set_sender_id(1);
343 resp_request.set_current_view(1);
344 resp_request.set_seq(1);
345 resp_request.set_proxy_id(1);
346 resp_request.set_primary_id(1);
347 batch_resp.SerializeToString(resp_request.mutable_data());
348
349 EXPECT_CALL(replica_communicator_, SendMessage(EqualsProto(resp_request), 1))
350 .WillOnce(Invoke(
351 [&](const google::protobuf::Message& request, int64_t node_id) {
352 done.set_value(true);
353 return 0;
354 }));
355
356 EXPECT_EQ(AddProposeMsg(1, true), 0);
357
358 EXPECT_EQ(AddPrepareMsg(1), 0);
359 EXPECT_EQ(AddPrepareMsg(2), 0);
360 EXPECT_EQ(AddPrepareMsg(3), 0);
361
362 EXPECT_EQ(AddCommitMsg(1), 0);
363 EXPECT_EQ(AddCommitMsg(2), 0);
364 EXPECT_EQ(AddCommitMsg(3), 0);
365 done_future.get();
366}
367
368} // namespace
369
370} // namespace resdb
std::string data
MockReplicaCommunicator replica_communicator_
void SetPrimary(uint32_t id)
std::unique_ptr< Commitment > commitment_
CheckPointManager checkpoint_manager_
Stats * global_stats_
SystemInfo system_info_
std::unique_ptr< MessageManager > message_manager_
MockSignatureVerifier verifier_
std::string data_
T ParseFromText(const std::string &json_str)
Definition test_macros.h:41
std::unique_ptr< Request > NewRequest(Request::Type type, const Request &request, int sender_id)
ReplicaInfo GenerateReplicaInfo(int id, const std::string &ip, int port)
TEST_F(ResDBTest, TestPBFTService)
std::unique_ptr< ResDBConfig > config_