polardbxengine/extra/IS/consensus/unittest/consensus-del-t.cc

279 lines
8.6 KiB
C++

/************************************************************************
*
* Copyright (c) 2016 Alibaba.com, Inc. All Rights Reserved
* $Id: consensus-t.cc,v 1.0 07/30/2016 02:41:21 PM yingqiang.zyq(yingqiang.zyq@alibaba-inc.com) $
*
************************************************************************/
/**
* @file consensus-t.cc
* @author yingqiang.zyq(yingqiang.zyq@alibaba-inc.com)
* @date 07/30/2016 02:41:21 PM
* @version 1.0
* @brief unit test for alisql::Consensus
*
**/
#include <atomic>
#include <thread>
#include <gtest/gtest.h>
#include "easyNet.h"
#include "service.h"
#include "paxos.h"
#include "paxos_log.h"
#include "paxos_server.h"
#include "paxos_configuration.h"
#include "paxos.pb.h"
#include "files.h"
#include "rd_paxos_log.h"
#include "file_paxos_log.h"
using namespace alisql;
TEST(consensus, Paxos_delete_node)
{
std::vector<std::string> strConfig;
strConfig.emplace_back("127.0.0.1:11001");
strConfig.emplace_back("127.0.0.1:11002");
strConfig.emplace_back("127.0.0.1:11003");
const uint64_t timeout= 2000;
std::shared_ptr<PaxosLog> rlog, rlog1;
rlog1= rlog= std::make_shared<RDPaxosLog>("paxosLogTestDir1", true, 4 * 1024 * 1024);
Paxos *paxos1= new Paxos(timeout, rlog);
paxos1->init(strConfig, 1);
rlog= std::make_shared<RDPaxosLog>("paxosLogTestDir2", true, 4 * 1024 * 1024);
Paxos *paxos2= new Paxos(timeout, rlog);
paxos2->init(strConfig, 2);
rlog= std::make_shared<RDPaxosLog>("paxosLogTestDir3", true, 4 * 1024 * 1024);
Paxos *paxos3= new Paxos(timeout, rlog);
paxos3->init(strConfig, 3);
sleep(3);
paxos2->requestVote();
sleep(1);
EXPECT_EQ(paxos2->getState(), Paxos::LEADER);
LogEntry le;
le.set_index(0);
le.set_optype(0);
le.set_ikey("bbb");
le.set_value("ccc");
paxos2->replicateLog(le);
// add member
// // create 2 learners
std::string strTmp2("127.0.0.1:11005");
std::string strTmp3("127.0.0.1:11006");
//there is no 127.0.0.1:11007 instance actually !
std::string strTmp4("127.0.0.1:11007");
rlog= std::make_shared<RDPaxosLog>("paxosLogTestDir5", true, 4 * 1024 * 1024);
Paxos *learner2= new Paxos(timeout, rlog);
learner2->initAsLearner(strTmp2);
rlog= std::make_shared<RDPaxosLog>("paxosLogTestDir6", true, 4 * 1024 * 1024);
Paxos *learner3= new Paxos(timeout, rlog);
learner3->initAsLearner(strTmp3);
sleep(1);
// // add 2 learners
strConfig.clear();
strConfig.push_back(strTmp2);
strConfig.push_back(strTmp3);
paxos2->changeLearners(Paxos::CCAddNode, strConfig);
sleep(1);
auto config= std::dynamic_pointer_cast<StableConfiguration>(paxos2->getConfig());
auto& servers= config->getServers();
auto& learners= config->getLearners();
EXPECT_EQ(config->getServerNum(), 3);
EXPECT_EQ(config->getLearnerNum(), 2);
EXPECT_EQ(learner2->getLastLogIndex(), paxos2->getLastLogIndex());
EXPECT_EQ(learner3->getLastLogIndex(), paxos2->getLastLogIndex());
// // add another learner
strConfig.clear();
strConfig.push_back(strTmp4);
paxos2->changeLearners(Paxos::CCAddNode, strConfig);
sleep(1);
EXPECT_EQ(config->getServerNum(), 3);
EXPECT_EQ(config->getLearnerNum(), 3);
EXPECT_EQ(learner2->getLastLogIndex(), paxos2->getLastLogIndex());
EXPECT_EQ(learner3->getLastLogIndex(), paxos2->getLastLogIndex());
std::vector<Paxos::ClusterInfoType> cis;
paxos2->getClusterInfo(cis);
Paxos::printClusterInfo(cis);
/*
for (auto& ci : cis)
{
std::cout<< "serverId:"<< ci.serverId<< " ipPort:"<< ci.ipPort<< " matchIndex:"<< ci.matchIndex<< " nextIndex:"<< ci.nextIndex<< " role:"<< ci.role<< " hasVoted:"<< ci.hasVoted << " forceSync:" << ci.forceSync << " electionWeight: " << ci.electionWeight << std::endl<< std::flush;
}
*/
sleep(1);
std::string tmpStr;
tmpStr.clear();
rlog1->getMetaData(std::string(Paxos::keyLearnerConfigure), tmpStr);
EXPECT_EQ(tmpStr, std::string("127.0.0.1:11005$00;127.0.0.1:11006$00;127.0.0.1:11007$00"));
// // change learners to followers one by one 1
paxos2->changeMember(Paxos::CCAddNode, strTmp2);
sleep(1);
le.clear_term();
paxos2->replicateLog(le);
sleep(1);
EXPECT_EQ(learner2->getState(), Paxos::FOLLOWER);
EXPECT_EQ(config->getServerNum(), 4);
EXPECT_EQ(config->getLearnerNum(), 2);
// restart paxos1
sleep(1);
EXPECT_EQ(paxos1->getCommitIndex(), paxos2->getCommitIndex());
tmpStr.clear();
rlog1->getMetaData(std::string(Paxos::keyMemberConfigure), tmpStr);
EXPECT_EQ(tmpStr, std::string("127.0.0.1:11001#5N;127.0.0.1:11002#5N;127.0.0.1:11003#5N;127.0.0.1:11005#5N@1"));
tmpStr.clear();
rlog1->getMetaData(std::string(Paxos::keyLearnerConfigure), tmpStr);
EXPECT_EQ(tmpStr, std::string("0;127.0.0.1:11006$00;127.0.0.1:11007$00"));
delete paxos1;
paxos1= new Paxos(timeout, rlog1);
strConfig.clear();
paxos1->init(strConfig, 1);
sleep(1);
auto config1= std::dynamic_pointer_cast<StableConfiguration>(paxos1->getConfig());
EXPECT_EQ(config1->membersToString(("127.0.0.1:11001")), std::string("127.0.0.1:11001#5N;127.0.0.1:11002#5N;127.0.0.1:11003#5N;127.0.0.1:11005#5N@1"));
// // change learners to followers one by one 2
paxos2->changeMember(Paxos::CCAddNode, strTmp3);
sleep(1);
le.clear_term();
paxos2->replicateLog(le);
sleep(1);
EXPECT_EQ(learner3->getState(), Paxos::FOLLOWER);
EXPECT_EQ(config->getServerNum(), 5);
EXPECT_EQ(config->getLearnerNum(), 1);
// // check 2 new followers
EXPECT_EQ(learner2->getLastLogIndex(), paxos2->getLastLogIndex());
EXPECT_EQ(learner3->getLastLogIndex(), paxos2->getLastLogIndex());
cis.clear();
paxos2->getClusterInfo(cis);
Paxos::printClusterInfo(cis);
EXPECT_EQ(cis[3].ipPort, strTmp2);
EXPECT_EQ(cis[4].ipPort, strTmp3);
// // delete one follower
paxos2->changeMember(Paxos::CCDelNode, strTmp2);
sleep(1);
le.clear_term();
paxos2->replicateLog(le);
sleep(1);
//EXPECT_EQ(config->getServerNum(), 4);
//EXPECT_EQ(config->getLearnerNum(), 0);
EXPECT_LT(learner2->getLastLogIndex(), paxos2->getLastLogIndex());
EXPECT_EQ(learner3->getLastLogIndex(), paxos2->getLastLogIndex());
paxos2->getClusterInfo(cis);
Paxos::printClusterInfo(cis);
EXPECT_EQ(cis[3].ipPort, strTmp3);
//add learner with mock log
auto rlog7= std::make_shared<RDPaxosLog>("paxosLogTestDir7", true, 4 * 1024 * 1024);
le.set_term(1);
le.set_index(0);
le.set_optype(kMock);
le.set_ikey("bbb");
le.set_value("ccc");
rlog7->debugSetLastLogIndex(2);
rlog7->append(le);
EXPECT_EQ(rlog7->getLastLogIndex(), 3);
LogEntry le1;
rlog7->getEntry(3, le1, false);
EXPECT_EQ(le1.index(), 3);
EXPECT_EQ(le1.term(), 1);
std::cout<< "add learner 127.0.0.1:11008"<< std::endl;
Paxos *learner4= new Paxos(timeout, rlog7);
std::string strTmp5("127.0.0.1:11008");
learner4->initAsLearner(strTmp5);
strConfig.clear();
strConfig.push_back(strTmp5);
paxos2->changeLearners(Paxos::CCAddNode, strConfig);
sleep(1);
EXPECT_EQ(learner4->getLastLogIndex(), paxos2->getLastLogIndex());
//add learner with error log(without mock)
auto rlog8= std::make_shared<RDPaxosLog>("paxosLogTestDir8", true, 4 * 1024 * 1024);
le.set_term(1);
le.set_index(0);
le.set_optype(0);
le.set_ikey("bbb");
le.set_value("ccc");
rlog8->debugSetLastLogIndex(2);
rlog8->append(le);
EXPECT_EQ(rlog8->getLastLogIndex(), 3);
rlog8->getEntry(3, le1, false);
EXPECT_EQ(le1.index(), 3);
EXPECT_EQ(le1.term(), 1);
std::cout<< "add learner 127.0.0.1:11009"<< std::endl;
Paxos *learner5= new Paxos(timeout, rlog8);
std::string strTmp6("127.0.0.1:11009");
learner5->initAsLearner(strTmp6);
strConfig.clear();
strConfig.push_back(strTmp6);
paxos2->changeLearners(Paxos::CCAddNode, strConfig);
sleep(1);
le.clear_term();
paxos2->replicateLog(le);
sleep(1);
cis.clear();
paxos2->getClusterInfo(cis);
Paxos::printClusterInfo(cis);
EXPECT_EQ(learner5->getLastLogIndex(), 3);
// test appliedIndex
paxos1->updateAppliedIndex(5);
sleep(1);
paxos2->getClusterInfo(cis);
Paxos::printClusterInfo(cis);
EXPECT_EQ(cis[0].appliedIndex, 5);
EXPECT_EQ(learner4->getLastLogIndex(), paxos2->getLastLogIndex());
//delete server 1
strTmp2= "127.0.0.1:11001";
paxos2->changeMember(Paxos::CCDelNode, strTmp2);
sleep(1);
le.clear_term();
paxos2->replicateLog(le);
sleep(1);
paxos2->getClusterInfo(cis);
Paxos::printClusterInfo(cis);
EXPECT_EQ(paxos2->getCurrentLeader(), paxos2->getLocalServer()->serverId);
delete paxos1;
delete learner2;
delete learner3;
delete learner4;
delete learner5;
config.reset();
delete paxos2;
delete paxos3;
deleteDir("paxosLogTestDir1");
deleteDir("paxosLogTestDir2");
deleteDir("paxosLogTestDir3");
deleteDir("paxosLogTestDir5");
deleteDir("paxosLogTestDir6");
deleteDir("paxosLogTestDir7");
deleteDir("paxosLogTestDir8");
}