/* * Copyright (c) 2019 TAOS Data, Inc. * * This program is free software: you can use, redistribute, and/or modify * it under the terms of the GNU Affero General Public License, version 3 * or later ("AGPL"), as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ // #include #include #include // #include "nodes.h" // #include "planner.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wwrite-strings" #pragma GCC diagnostic ignored "-Wunused-function" #pragma GCC diagnostic ignored "-Wunused-variable" #pragma GCC diagnostic ignored "-Wsign-compare" // #include #include "../../inc/mndArbGroup.h" namespace { void generateArbToken(int32_t nodeId, int32_t vgId, char* buf) { memset(buf, 0, TSDB_ARB_TOKEN_SIZE); int32_t randVal = taosSafeRand() % 1000; int64_t currentMs = taosGetTimestampMs(); snprintf(buf, TSDB_ARB_TOKEN_SIZE, "d%d#g%d#%" PRId64 "#%d", nodeId, vgId, currentMs, randVal); } } // namespace class ArbgroupTest : public testing::Test { protected: static void SetUpTestSuite() { std::cout << "setup env for arbgroupTest suite" << std::endl; } static void TearDownTestSuite() { std::cout << "tearDown env for arbgroupTest suite" << std::endl; } virtual void SetUp() override {} virtual void TearDown() override {} }; int main(int argc, char** argv) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } TEST_F(ArbgroupTest, 01_encode_decode_sdb) { SArbGroup group = {0}; group.vgId = 5; group.dbUid = 1234; group.members[0].info.dnodeId = 1; generateArbToken(1, 5, group.members[0].state.token); group.members[1].info.dnodeId = 2; generateArbToken(2, 5, group.members[1].state.token); group.isSync = 1; group.assignedLeader.dnodeId = 1; generateArbToken(1, 5, group.assignedLeader.token); group.version = 2234; // -------------------------------------------------------------------------------- SSdbRaw* pRaw = mndArbGroupActionEncode(&group); ASSERT_NE(pRaw, nullptr); SSdbRow* pRow = mndArbGroupActionDecode(pRaw); ASSERT_NE(pRow, nullptr); SArbGroup* pNewGroup = (SArbGroup*)sdbGetRowObj(pRow); EXPECT_EQ(group.vgId, pNewGroup->vgId); EXPECT_EQ(group.dbUid, pNewGroup->dbUid); EXPECT_EQ(group.members[0].info.dnodeId, pNewGroup->members[0].info.dnodeId); EXPECT_EQ(group.members[1].info.dnodeId, pNewGroup->members[1].info.dnodeId); EXPECT_EQ(group.isSync, pNewGroup->isSync); EXPECT_EQ(group.assignedLeader.dnodeId, pNewGroup->assignedLeader.dnodeId); EXPECT_EQ(std::string(group.members[0].state.token), std::string(pNewGroup->members[0].state.token)); EXPECT_EQ(std::string(group.members[1].state.token), std::string(pNewGroup->members[1].state.token)); EXPECT_EQ(std::string(group.assignedLeader.token), std::string(pNewGroup->assignedLeader.token)); EXPECT_EQ(group.version, pNewGroup->version); taosMemoryFree(pRow); taosMemoryFree(pRaw); } TEST_F(ArbgroupTest, 02_process_heart_beat_rsp) { const int32_t dnodeId = 1; const int32_t vgId = 5; SArbGroup group = {0}; group.vgId = vgId; group.dbUid = 1234; group.members[0].info.dnodeId = dnodeId; generateArbToken(dnodeId, vgId, group.members[0].state.token); group.members[0].state.lastHbMs = 1000; group.members[0].state.responsedHbSeq = 100; group.members[0].state.nextHbSeq = 102; group.members[1].info.dnodeId = 2; generateArbToken(2, vgId, group.members[1].state.token); group.isSync = 1; group.assignedLeader.dnodeId = dnodeId; strncpy(group.assignedLeader.token, group.members[0].state.token, TSDB_ARB_TOKEN_SIZE); taosThreadMutexInit(&group.mutex, NULL); // -------------------------------------------------------------------------------- { // expired hb => skip SVArbHbRspMember rspMember = {0}; rspMember.vgId = vgId; rspMember.hbSeq = group.members[0].state.responsedHbSeq - 1; strncpy(rspMember.memberToken, group.members[0].state.token, TSDB_ARB_TOKEN_SIZE); int32_t nowMs = group.members[0].state.lastHbMs + 10; SArbGroup newGroup = {0}; bool updateToken = mndUpdateArbGroupByHeartBeat(&group, &rspMember, nowMs, dnodeId, &newGroup); EXPECT_FALSE(updateToken); EXPECT_NE(group.members[0].state.responsedHbSeq, rspMember.hbSeq); EXPECT_NE(group.members[0].state.lastHbMs, nowMs); } { // old token SVArbHbRspMember rspMember = {0}; rspMember.vgId = vgId; rspMember.hbSeq = group.members[0].state.responsedHbSeq + 1; strncpy(rspMember.memberToken, group.members[0].state.token, TSDB_ARB_TOKEN_SIZE); int32_t nowMs = group.members[0].state.lastHbMs + 10; SArbGroup newGroup = {0}; bool updateToken = mndUpdateArbGroupByHeartBeat(&group, &rspMember, nowMs, dnodeId, &newGroup); EXPECT_FALSE(updateToken); EXPECT_EQ(group.members[0].state.responsedHbSeq, rspMember.hbSeq); EXPECT_EQ(group.members[0].state.lastHbMs, nowMs); } { // new token SVArbHbRspMember rspMember = {0}; rspMember.vgId = vgId; rspMember.hbSeq = group.members[0].state.responsedHbSeq + 1; generateArbToken(dnodeId, vgId, rspMember.memberToken); int32_t nowMs = group.members[0].state.lastHbMs + 10; SArbGroup newGroup = {0}; bool updateToken = mndUpdateArbGroupByHeartBeat(&group, &rspMember, nowMs, dnodeId, &newGroup); EXPECT_TRUE(updateToken); EXPECT_EQ(group.members[0].state.responsedHbSeq, rspMember.hbSeq); EXPECT_EQ(group.members[0].state.lastHbMs, nowMs); EXPECT_EQ(std::string(newGroup.members[0].state.token), std::string(rspMember.memberToken)); EXPECT_FALSE(newGroup.isSync); EXPECT_EQ(newGroup.assignedLeader.dnodeId, 0); EXPECT_EQ(std::string(newGroup.assignedLeader.token).size(), 0); } taosThreadMutexDestroy(&group.mutex); } TEST_F(ArbgroupTest, 03_process_check_sync_rsp) { const int32_t dnodeId = 1; const int32_t vgId = 5; SArbGroup group = {0}; group.vgId = vgId; group.dbUid = 1234; group.members[0].info.dnodeId = dnodeId; generateArbToken(dnodeId, vgId, group.members[0].state.token); group.members[0].state.lastHbMs = 1000; group.members[0].state.responsedHbSeq = 100; group.members[0].state.nextHbSeq = 102; group.members[1].info.dnodeId = 2; generateArbToken(2, vgId, group.members[1].state.token); group.isSync = 0; taosThreadMutexInit(&group.mutex, NULL); // -------------------------------------------------------------------------------- { // token mismatch => skip char member0Token[TSDB_ARB_TOKEN_SIZE] = {0}; strncpy(member0Token, group.members[0].state.token, TSDB_ARB_TOKEN_SIZE); char member1Token[TSDB_ARB_TOKEN_SIZE] = {0}; generateArbToken(2, 5, member1Token); bool newIsSync = false; SArbGroup newGroup = {0}; bool updateIsSync = mndUpdateArbGroupByCheckSync(&group, vgId, member0Token, member1Token, newIsSync, &newGroup); EXPECT_FALSE(updateIsSync); } { // newIsSync char member0Token[TSDB_ARB_TOKEN_SIZE] = {0}; strncpy(member0Token, group.members[0].state.token, TSDB_ARB_TOKEN_SIZE); char member1Token[TSDB_ARB_TOKEN_SIZE] = {0}; strncpy(member1Token, group.members[1].state.token, TSDB_ARB_TOKEN_SIZE); bool newIsSync = true; SArbGroup newGroup = {0}; bool updateIsSync = mndUpdateArbGroupByCheckSync(&group, vgId, member0Token, member1Token, newIsSync, &newGroup); EXPECT_TRUE(updateIsSync); EXPECT_TRUE(newGroup.isSync); } taosThreadMutexDestroy(&group.mutex); } TEST_F(ArbgroupTest, 04_process_set_assigned_leader){ const int32_t dnodeId = 1; const int32_t vgId = 5; SArbGroup group = {0}; group.vgId = vgId; group.dbUid = 1234; group.members[0].info.dnodeId = dnodeId; generateArbToken(dnodeId, vgId, group.members[0].state.token); group.members[0].state.lastHbMs = 1000; group.members[0].state.responsedHbSeq = 100; group.members[0].state.nextHbSeq = 102; group.members[1].info.dnodeId = 2; generateArbToken(2, vgId, group.members[1].state.token); group.isSync = 1; group.assignedLeader.dnodeId = dnodeId; strncpy(group.assignedLeader.token, group.members[0].state.token, TSDB_ARB_TOKEN_SIZE); taosThreadMutexInit(&group.mutex, NULL); // -------------------------------------------------------------------------------- { // token mismatch => skip char memberToken[TSDB_ARB_TOKEN_SIZE] = {0}; generateArbToken(dnodeId, vgId, memberToken); int32_t errcode = TSDB_CODE_SUCCESS; SArbGroup newGroup = {0}; bool updateAssigned = mndUpdateArbGroupBySetAssignedLeader(&group, vgId, memberToken, errcode, &newGroup); EXPECT_FALSE(updateAssigned); } { // errcode != TSDB_CODE_SUCCESS char memberToken[TSDB_ARB_TOKEN_SIZE] = {0}; strncpy(memberToken, group.assignedLeader.token, TSDB_ARB_TOKEN_SIZE); int32_t errcode = TSDB_CODE_MND_ARB_TOKEN_MISMATCH; SArbGroup newGroup = {0}; bool updateAssigned = mndUpdateArbGroupBySetAssignedLeader(&group, vgId, memberToken, errcode, &newGroup); EXPECT_FALSE(updateAssigned); } { // errcode == TSDB_CODE_SUCCESS char memberToken[TSDB_ARB_TOKEN_SIZE] = {0}; strncpy(memberToken, group.assignedLeader.token, TSDB_ARB_TOKEN_SIZE); int32_t errcode = TSDB_CODE_SUCCESS; SArbGroup newGroup = {0}; bool updateAssigned = mndUpdateArbGroupBySetAssignedLeader(&group, vgId, memberToken, errcode, &newGroup); EXPECT_TRUE(updateAssigned); EXPECT_FALSE(newGroup.isSync); } taosThreadMutexDestroy(&group.mutex); } #pragma GCC diagnostic pop