/************************************************************************ * * 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 #include #include #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 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 rlog, rlog1; rlog1= rlog= std::make_shared("paxosLogTestDir1", true, 4 * 1024 * 1024); Paxos *paxos1= new Paxos(timeout, rlog); paxos1->init(strConfig, 1); rlog= std::make_shared("paxosLogTestDir2", true, 4 * 1024 * 1024); Paxos *paxos2= new Paxos(timeout, rlog); paxos2->init(strConfig, 2); rlog= std::make_shared("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("paxosLogTestDir5", true, 4 * 1024 * 1024); Paxos *learner2= new Paxos(timeout, rlog); learner2->initAsLearner(strTmp2); rlog= std::make_shared("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(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 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(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("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("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"); }