curve/test/tools/copyset_check_test.cpp

437 lines
15 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2020 NetEase Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Project: curve
* File Created: 2019-11-1
* Author: charisu
*/
#include <gtest/gtest.h>
#include "src/tools/copyset_check.h"
#include "src/tools/copyset_check_core.h"
#include "test/tools/mock/mock_copyset_check_core.h"
using ::testing::_;
using ::testing::Return;
using ::testing::ReturnRef;
using ::testing::DoAll;
using ::testing::SetArgPointee;
DECLARE_bool(detail);
DECLARE_uint32(logicalPoolId);
DECLARE_uint32(copysetId);
DECLARE_uint32(chunkserverId);
DECLARE_string(chunkserverAddr);
DECLARE_uint32(serverId);
DECLARE_string(serverIp);
DECLARE_uint64(leaderOpInterval);
DECLARE_uint64(opIntervalExceptLeader);
DECLARE_string(opName);
namespace curve {
namespace tool {
class CopysetCheckTest : public ::testing::Test {
protected:
CopysetCheckTest() {
statistics1 = CopysetStatistics(2, 0);
statistics2 = CopysetStatistics(6, 5);
}
void SetUp() {
core_ = std::make_shared<MockCopysetCheckCore>();
FLAGS_detail = true;
}
void TearDown() {
core_ = nullptr;
}
void GetIoBufForTest(butil::IOBuf* buf, const std::string& gId,
bool isLeader = false,
bool noLeader = false,
bool installingSnapshot = false,
bool peersLess = false,
bool gapBig = false,
bool parseErr = false,
bool peerOffline = false) {
butil::IOBufBuilder os;
os << "[" << gId << "]\r\n";
if (peersLess) {
os << "peers: \r\n";
} else if (peerOffline) {
os << "peers: 127.0.0.1:9191:0 127.0.0.1:9192:0 127.0.0.1:9194:0\r\n"; // NOLINT
} else {
os << "peers: 127.0.0.1:9191:0 127.0.0.1:9192:0 127.0.0.1:9193:0\r\n"; // NOLINT
}
os << "storage: [2581, 2580]\n";
if (parseErr) {
os << "\n";
} else {
os << "last_log_id: (index=2580,term=4)\n";
}
os << "state_machine: Idle\r\n";
if (isLeader) {
os << "state: " << "LEADER" << "\r\n";
os << "replicator_123: next_index=";
if (gapBig) {
os << "1000";
} else {
os << "2581";
}
os << " flying_append_entries_size=0 ";
if (installingSnapshot) {
os << "installing snapshot {1234, 3} ";
} else {
os << "idle ";
}
os << "hc=4211759 ac=1089 ic=0\r\n";
} else {
os << "state: " << "FOLLOWER" << "\r\n";
if (noLeader) {
os << "leader: " << "0.0.0.0:0:0\r\n";
} else {
os << "leader: " << "127.0.0.1:9192:0\r\n";
}
}
os.move_to(*buf);
}
std::map<std::string, std::set<std::string>> res1 =
{{"total", {"4294967396", "4294967397"}}};
std::map<std::string, std::set<std::string>> res2 =
{{"total", {"4294967396", "4294967397", "4294967398",
"4294967399", "4294967400", "4294967401"}},
{"installing snapshot", {"4294967397"}},
{"no leader", {"4294967398"}},
{"index gap too big", {"4294967399"}},
{"peers not sufficient", {"4294967400"}},
{"peer not online", {"4294967401"}}};
std::set<std::string> serviceExcepCs = {"127.0.0.1:9092"};
std::set<std::string> copysetExcepCs = {"127.0.0.1:9093"};
std::set<std::string> emptySet;
CopysetStatistics statistics1;
CopysetStatistics statistics2;
std::shared_ptr<MockCopysetCheckCore> core_;
};
TEST_F(CopysetCheckTest, SupportCommand) {
CopysetCheck copysetCheck(core_);
ASSERT_TRUE(copysetCheck.SupportCommand("check-copyset"));
ASSERT_TRUE(copysetCheck.SupportCommand("check-chunkserver"));
ASSERT_TRUE(copysetCheck.SupportCommand("check-server"));
ASSERT_TRUE(copysetCheck.SupportCommand("copysets-status"));
ASSERT_TRUE(copysetCheck.SupportCommand("check-operator"));
ASSERT_FALSE(copysetCheck.SupportCommand("check-nothing"));
}
TEST_F(CopysetCheckTest, CheckOneCopyset) {
CopysetCheck copysetCheck(core_);
copysetCheck.PrintHelp("check-copyset");
butil::IOBuf iobuf;
GetIoBufForTest(&iobuf, "4294967396", true);
std::vector<std::string> peersInCopyset =
{"127.0.0.1:9091", "127.0.0.1:9092", "127.0.0.1:9093"};
std::string copysetDetail = iobuf.to_string();
// Init失败的情况
EXPECT_CALL(*core_, Init(_))
.Times(1)
.WillOnce(Return(-1));
ASSERT_EQ(-1, copysetCheck.RunCommand("check-copyset"));
EXPECT_CALL(*core_, Init(_))
.Times(1)
.WillOnce(Return(0));
// 不支持的命令
ASSERT_EQ(-1, copysetCheck.RunCommand("check-nothings"));
copysetCheck.PrintHelp("check-nothins");
// 没有指定逻辑池和copyset的话返回失败
ASSERT_EQ(-1, copysetCheck.RunCommand("check-copyset"));
FLAGS_logicalPoolId = 1;
FLAGS_copysetId = 100;
copysetCheck.PrintHelp("check-copyset");
// 健康的情况
EXPECT_CALL(*core_, CheckOneCopyset(_, _))
.Times(1)
.WillOnce(Return(CheckResult::kHealthy));
EXPECT_CALL(*core_, GetCopysetDetail())
.Times(1)
.WillOnce(ReturnRef(copysetDetail));
EXPECT_CALL(*core_, GetServiceExceptionChunkServer())
.Times(1)
.WillOnce(ReturnRef(emptySet));
EXPECT_CALL(*core_, GetCopysetLoadExceptionChunkServer())
.Times(1)
.WillOnce(ReturnRef(emptySet));
ASSERT_EQ(0, copysetCheck.RunCommand("check-copyset"));
// copyset不健康的情况
EXPECT_CALL(*core_, CheckOneCopyset(_, _))
.Times(1)
.WillOnce(Return(CheckResult::kLogIndexGapTooBig));
EXPECT_CALL(*core_, GetCopysetDetail())
.Times(1)
.WillOnce(ReturnRef(copysetDetail));
EXPECT_CALL(*core_, GetServiceExceptionChunkServer())
.Times(1)
.WillOnce(ReturnRef(serviceExcepCs));
EXPECT_CALL(*core_, GetCopysetLoadExceptionChunkServer())
.Times(1)
.WillOnce(ReturnRef(copysetExcepCs));
ASSERT_EQ(-1, copysetCheck.RunCommand("check-copyset"));
}
TEST_F(CopysetCheckTest, testCheckChunkServer) {
CopysetCheck copysetCheck(core_);
copysetCheck.PrintHelp("check-chunkserver");
EXPECT_CALL(*core_, Init(_))
.Times(1)
.WillOnce(Return(0));
// 没有指定chunkserver的话报错
ASSERT_EQ(-1, copysetCheck.RunCommand("check-chunkserver"));
copysetCheck.PrintHelp("check-chunkserver");
// 健康的情况
// 通过id查询
FLAGS_chunkserverId = 1;
EXPECT_CALL(*core_, CheckCopysetsOnChunkServer(FLAGS_chunkserverId))
.Times(1)
.WillOnce(Return(0));
EXPECT_CALL(*core_, GetCopysetsRes())
.Times(1)
.WillRepeatedly(ReturnRef(res1));
EXPECT_CALL(*core_, GetCopysetStatistics())
.Times(1)
.WillRepeatedly(Return(statistics1));
EXPECT_CALL(*core_, GetServiceExceptionChunkServer())
.Times(1)
.WillOnce(ReturnRef(emptySet));
EXPECT_CALL(*core_, GetCopysetLoadExceptionChunkServer())
.Times(1)
.WillOnce(ReturnRef(emptySet));
ASSERT_EQ(0, copysetCheck.RunCommand("check-chunkserver"));
// id和地址同时指定报错
FLAGS_chunkserverAddr = "127.0.0.1:8200";
ASSERT_EQ(-1, copysetCheck.RunCommand("check-chunkserver"));
FLAGS_chunkserverId = 0;
// 通过地址查询
EXPECT_CALL(*core_, CheckCopysetsOnChunkServer(FLAGS_chunkserverAddr))
.Times(1)
.WillOnce(Return(0));
EXPECT_CALL(*core_, GetCopysetsRes())
.Times(1)
.WillRepeatedly(ReturnRef(res1));
EXPECT_CALL(*core_, GetCopysetStatistics())
.Times(1)
.WillRepeatedly(Return(statistics1));
EXPECT_CALL(*core_, GetServiceExceptionChunkServer())
.Times(1)
.WillOnce(ReturnRef(emptySet));
EXPECT_CALL(*core_, GetCopysetLoadExceptionChunkServer())
.Times(1)
.WillOnce(ReturnRef(emptySet));
ASSERT_EQ(0, copysetCheck.RunCommand("check-chunkserver"));
// 不健康的情况
EXPECT_CALL(*core_, CheckCopysetsOnChunkServer(FLAGS_chunkserverAddr))
.Times(1)
.WillOnce(Return(-1));
EXPECT_CALL(*core_, GetCopysetsRes())
.Times(1)
.WillRepeatedly(ReturnRef(res2));
EXPECT_CALL(*core_, GetCopysetStatistics())
.Times(1)
.WillRepeatedly(Return(statistics2));
EXPECT_CALL(*core_, GetServiceExceptionChunkServer())
.Times(1)
.WillOnce(ReturnRef(serviceExcepCs));
EXPECT_CALL(*core_, GetCopysetLoadExceptionChunkServer())
.Times(1)
.WillOnce(ReturnRef(copysetExcepCs));
ASSERT_EQ(-1, copysetCheck.RunCommand("check-chunkserver"));
}
TEST_F(CopysetCheckTest, testCheckServer) {
CopysetCheck copysetCheck(core_);
copysetCheck.PrintHelp("check-server");
std::vector<std::string> chunkservers =
{"127.0.0.1:9091", "127.0.0.1:9092", "127.0.0.1:9093"};
EXPECT_CALL(*core_, Init(_))
.Times(1)
.WillOnce(Return(0));
// 没有指定server的话报错
ASSERT_EQ(-1, copysetCheck.RunCommand("check-server"));
copysetCheck.PrintHelp("check-server");
// 健康的情况
// 通过id查询
FLAGS_serverId = 1;
EXPECT_CALL(*core_, CheckCopysetsOnServer(FLAGS_serverId, _))
.Times(1)
.WillOnce(DoAll(SetArgPointee<1>(chunkservers),
Return(0)));
EXPECT_CALL(*core_, GetCopysetsRes())
.Times(1)
.WillRepeatedly(ReturnRef(res1));
EXPECT_CALL(*core_, GetCopysetStatistics())
.Times(1)
.WillRepeatedly(Return(statistics1));
EXPECT_CALL(*core_, GetServiceExceptionChunkServer())
.Times(1)
.WillOnce(ReturnRef(emptySet));
EXPECT_CALL(*core_, GetCopysetLoadExceptionChunkServer())
.Times(1)
.WillOnce(ReturnRef(emptySet));
ASSERT_EQ(0, copysetCheck.RunCommand("check-server"));
// id和ip同时指定报错
FLAGS_serverIp = "127.0.0.1";
ASSERT_EQ(-1, copysetCheck.RunCommand("check-server"));
FLAGS_serverId = 0;
// 通过ip查询
EXPECT_CALL(*core_, CheckCopysetsOnServer(FLAGS_serverIp, _))
.Times(1)
.WillOnce(DoAll(SetArgPointee<1>(chunkservers),
Return(0)));
EXPECT_CALL(*core_, GetCopysetsRes())
.Times(1)
.WillRepeatedly(ReturnRef(res1));
EXPECT_CALL(*core_, GetCopysetStatistics())
.Times(1)
.WillRepeatedly(Return(statistics1));
EXPECT_CALL(*core_, GetServiceExceptionChunkServer())
.Times(1)
.WillOnce(ReturnRef(emptySet));
EXPECT_CALL(*core_, GetCopysetLoadExceptionChunkServer())
.Times(1)
.WillOnce(ReturnRef(emptySet));
ASSERT_EQ(0, copysetCheck.RunCommand("check-server"));
// 不健康的情况
EXPECT_CALL(*core_, CheckCopysetsOnServer(FLAGS_serverIp, _))
.Times(1)
.WillOnce(Return(-1));
EXPECT_CALL(*core_, GetCopysetsRes())
.Times(1)
.WillRepeatedly(ReturnRef(res2));
EXPECT_CALL(*core_, GetCopysetStatistics())
.Times(1)
.WillRepeatedly(Return(statistics2));
EXPECT_CALL(*core_, GetServiceExceptionChunkServer())
.Times(1)
.WillOnce(ReturnRef(serviceExcepCs));
EXPECT_CALL(*core_, GetCopysetLoadExceptionChunkServer())
.Times(1)
.WillOnce(ReturnRef(copysetExcepCs));
ASSERT_EQ(-1, copysetCheck.RunCommand("check-server"));
}
TEST_F(CopysetCheckTest, testCheckCluster) {
CopysetCheck copysetCheck(core_);
copysetCheck.PrintHelp("copysets-status");
EXPECT_CALL(*core_, Init(_))
.Times(1)
.WillOnce(Return(0));
// 健康的情况
EXPECT_CALL(*core_, CheckCopysetsInCluster())
.Times(1)
.WillOnce(Return(0));
EXPECT_CALL(*core_, GetCopysetsRes())
.Times(1)
.WillRepeatedly(ReturnRef(res1));
EXPECT_CALL(*core_, GetCopysetStatistics())
.Times(1)
.WillRepeatedly(Return(statistics1));
EXPECT_CALL(*core_, GetServiceExceptionChunkServer())
.Times(1)
.WillOnce(ReturnRef(emptySet));
EXPECT_CALL(*core_, GetCopysetLoadExceptionChunkServer())
.Times(1)
.WillOnce(ReturnRef(emptySet));
ASSERT_EQ(0, copysetCheck.RunCommand(kCopysetsStatusCmd));
// 不健康的情况
EXPECT_CALL(*core_, CheckCopysetsInCluster())
.Times(1)
.WillOnce(Return(-1));
EXPECT_CALL(*core_, GetCopysetsRes())
.Times(1)
.WillRepeatedly(ReturnRef(res2));
EXPECT_CALL(*core_, GetCopysetStatistics())
.Times(1)
.WillRepeatedly(Return(statistics2));
EXPECT_CALL(*core_, GetServiceExceptionChunkServer())
.Times(1)
.WillOnce(ReturnRef(serviceExcepCs));
EXPECT_CALL(*core_, GetCopysetLoadExceptionChunkServer())
.Times(1)
.WillOnce(ReturnRef(copysetExcepCs));
ASSERT_EQ(-1, copysetCheck.RunCommand(kCopysetsStatusCmd));
}
TEST_F(CopysetCheckTest, testCheckOperator) {
CopysetCheck copysetCheck(core_);
copysetCheck.PrintHelp("check-operator");
EXPECT_CALL(*core_, Init(_))
.Times(1)
.WillOnce(Return(0));
// 1、不支持的operator
FLAGS_opName = "no_operator";
ASSERT_EQ(-1, copysetCheck.RunCommand(kCheckOperatorCmd));
// 2、transfer leader的operator和total的
EXPECT_CALL(*core_, CheckOperator(_, FLAGS_leaderOpInterval))
.Times(2)
.WillOnce(Return(0))
.WillOnce(Return(-1));
FLAGS_opName = kTransferOpName;
ASSERT_EQ(0, copysetCheck.RunCommand(kCheckOperatorCmd));
FLAGS_opName = kTotalOpName;
ASSERT_EQ(-1, copysetCheck.RunCommand(kCheckOperatorCmd));
// 2、其他operator
EXPECT_CALL(*core_, CheckOperator(_, FLAGS_opIntervalExceptLeader))
.Times(3)
.WillOnce(Return(10))
.WillRepeatedly(Return(0));
FLAGS_opName = kChangeOpName;
ASSERT_EQ(0, copysetCheck.RunCommand(kCheckOperatorCmd));
FLAGS_opName = kAddOpName;
ASSERT_EQ(0, copysetCheck.RunCommand(kCheckOperatorCmd));
FLAGS_opName = kRemoveOpName;
ASSERT_EQ(0, copysetCheck.RunCommand(kCheckOperatorCmd));
}
TEST_F(CopysetCheckTest, PrintMayBrokenVolumes) {
CopysetCheck copysetCheck(core_);
copysetCheck.PrintHelp(kListMayBrokenVolumes);
EXPECT_CALL(*core_, Init(_))
.Times(1)
.WillOnce(Return(0));
// fail
EXPECT_CALL(*core_, ListMayBrokenVolumes(_))
.WillOnce(Return(-1));
ASSERT_EQ(-1, copysetCheck.RunCommand(kListMayBrokenVolumes));
EXPECT_CALL(*core_, ListMayBrokenVolumes(_))
.WillOnce(Return(0));
ASSERT_EQ(0, copysetCheck.RunCommand(kListMayBrokenVolumes));
}
} // namespace tool
} // namespace curve