polardbxengine/extra/IS/consensus/unittest/consensus-leader-transfer-t.cc

198 lines
5.4 KiB
C++

/************************************************************************
*
* Copyright (c) 2019 Alibaba.com, Inc. All Rights Reserved
* $Id: consensus-leader-transfer-t.cc,v 1.0 07/31/2019 16:23:00 PM aili.xp(aili.xp@alibaba-inc.com) $
*
************************************************************************/
/**
* @file consensus-leader-transfer-t.cc
* @author aili.xp(aili.xp@alibaba-inc.com)
* @date 07/31/2019 16:23:00 PM
* @version 1.0
* @brief unit test for leader transfer
*
**/
#include <vector>
#include <string>
#include <memory>
#include <gtest/gtest.h>
#include "paxos.h"
#include "file_paxos_log.h"
#include "files.h"
using namespace alisql;
TEST(LeaderTransfer, UnnecessaryLog)
{
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= 10000;
std::string dir1 = std::string("paxosLogTestDir71");
std::shared_ptr<PaxosLog> rlog1= std::make_shared<FilePaxosLog>(dir1, FilePaxosLog::LogType::LTMem);
Paxos *paxos1= new Paxos(timeout, rlog1);
paxos1->init(strConfig, 1);
std::string dir2 = std::string("paxosLogTestDir72");
std::shared_ptr<PaxosLog> rlog2= std::make_shared<FilePaxosLog>(dir2, FilePaxosLog::LogType::LTMem);
Paxos *paxos2= new Paxos(timeout, rlog2);
paxos2->init(strConfig, 2);
std::string dir3 = std::string("paxosLogTestDir73");
std::shared_ptr<PaxosLog> rlog3= std::make_shared<FilePaxosLog>(dir3, FilePaxosLog::LogType::LTMem);
Paxos *paxos3= new Paxos(timeout, rlog3);
paxos3->init(strConfig, 3);
sleep(1);
paxos1->requestVote();
sleep(1);
EXPECT_EQ(paxos1->getState(), Paxos::LEADER);
uint64_t term = paxos1->getTerm();
sleep(1);
EXPECT_EQ(paxos1->getLastLogIndex(), 1);
EXPECT_EQ(paxos1->getCommitIndex(), 1);
paxos1->setMaxPacketSize(10);
for (int i = 0; i < 20; ++i) {
LogEntry le;
le.set_index(0);
le.set_term(paxos1->getTerm());
le.set_info(0);
le.set_optype(0);
paxos1->getLog()->append(le);
}
paxos1->leaderTransfer(2);
// wait for leader transfer taking effect
sleep(12);
EXPECT_EQ(paxos2->getState(), Paxos::LEADER);
EXPECT_EQ(paxos2->getTerm(), term + 1); // only one election should happen
EXPECT_EQ(paxos2->getCommitIndex(), 22);
EXPECT_EQ(paxos2->getLastLogIndex(), 22);
delete paxos1;
delete paxos2;
delete paxos3;
deleteDir("paxosLogTestDir71");
deleteDir("paxosLogTestDir72");
deleteDir("paxosLogTestDir73");
}
class PaxosLogTmp : public FilePaxosLog
{
public:
PaxosLogTmp(const std::string &dataDir, FilePaxosLog::LogTypeT type):FilePaxosLog(dataDir, type) {}
virtual ~PaxosLogTmp() { }
virtual bool isStateMachineHealthy() {
return healthy;
}
bool healthy = true;
};
TEST(LeaderTransfer, AutoLeaderTransfer)
{
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= 1000;
std::string dir1 = std::string("paxosLogTestDir71");
std::shared_ptr<PaxosLog> rlog1= std::make_shared<PaxosLogTmp>(dir1, FilePaxosLog::LogType::LTMem);
Paxos *paxos1= new Paxos(timeout, rlog1);
paxos1->init(strConfig, 1);
std::string dir2 = std::string("paxosLogTestDir72");
std::shared_ptr<PaxosLog> rlog2= std::make_shared<PaxosLogTmp>(dir2, FilePaxosLog::LogType::LTMem);
Paxos *paxos2= new Paxos(timeout, rlog2);
paxos2->init(strConfig, 2);
std::string dir3 = std::string("paxosLogTestDir73");
std::shared_ptr<PaxosLog> rlog3= std::make_shared<PaxosLogTmp>(dir3, FilePaxosLog::LogType::LTMem);
Paxos *paxos3= new Paxos(timeout, rlog3);
paxos3->init(strConfig, 3);
sleep(1);
paxos1->requestVote();
sleep(1);
EXPECT_EQ(paxos1->getState(), Paxos::LEADER);
paxos1->setEnableAutoLeaderTransfer(true);
paxos1->setAutoLeaderTransferCheckSeconds(5);
paxos2->setEnableAutoLeaderTransfer(true);
paxos2->setAutoLeaderTransferCheckSeconds(5);
paxos3->setEnableAutoLeaderTransfer(true);
paxos3->setAutoLeaderTransferCheckSeconds(5);
uint64_t term = paxos1->getTerm();
// case 1: log type node
paxos1->setAsLogType(true);
sleep(2);
ASSERT_EQ(paxos1->getTerm(), term + 1);
paxos1->setAsLogType(false);
// case 2: state machine not healthy
((PaxosLogTmp*)rlog1.get())->healthy = false;
paxos2->leaderTransfer(1);
paxos3->leaderTransfer(1);
sleep(2);
ASSERT_EQ(paxos1->getState(), Paxos::LEADER);
ASSERT_EQ(paxos1->getTerm(), term + 2);
sleep(5);
ASSERT_NE(paxos1->getState(), Paxos::LEADER);
ASSERT_EQ(paxos1->getTerm(), term + 3);
// case 3: test whether target will be random
((PaxosLogTmp*)rlog1.get())->healthy = false;
((PaxosLogTmp*)rlog2.get())->healthy = false;
((PaxosLogTmp*)rlog3.get())->healthy = false;
paxos1->leaderTransfer(2);
int l1 = 0, l2 = 0, l3 = 0;
for (int i = 0; i < 10; ++i) {
sleep(6);
if (paxos1->getState() == Paxos::LEADER)
l1++;
if (paxos2->getState() == Paxos::LEADER)
l2++;
if (paxos3->getState() == Paxos::LEADER)
l3++;
}
ASSERT_NE(l1, 0);
ASSERT_NE(l2, 0);
ASSERT_NE(l3, 0);
std::cout << "l1: " << l1 << std::endl;
std::cout << "l2: " << l2 << std::endl;
std::cout << "l3: " << l3 << std::endl;
delete paxos1;
delete paxos2;
delete paxos3;
deleteDir("paxosLogTestDir71");
deleteDir("paxosLogTestDir72");
deleteDir("paxosLogTestDir73");
}