/** * @file trans.cpp * @author slguan (slguan@taosdata.com) * @brief MNODE module trans tests * @version 1.0 * @date 2022-05-02 * * @copyright Copyright (c) 2022 * */ #include #include "mndTrans.h" #include "mndUser.h" #include "tcache.h" void reportStartup(SMgmtWrapper *pWrapper, const char *name, const char *desc) {} class MndTestTrans2 : public ::testing::Test { protected: static void InitLog() { dDebugFlag = 143; vDebugFlag = 0; mDebugFlag = 207; cDebugFlag = 0; jniDebugFlag = 0; tmrDebugFlag = 135; uDebugFlag = 135; rpcDebugFlag = 143; qDebugFlag = 0; wDebugFlag = 0; sDebugFlag = 0; tsdbDebugFlag = 0; tsLogEmbedded = 1; tsAsyncLog = 0; const char *logpath = "/tmp/td"; taosRemoveDir(logpath); taosMkDir(logpath); tstrncpy(tsLogDir, logpath, PATH_MAX); if (taosInitLog("taosdlog", 1) != 0) { printf("failed to init log file\n"); } } static void InitMnode() { static SMsgCb msgCb = {0}; msgCb.reportStartupFp = reportStartup; msgCb.pWrapper = (SMgmtWrapper *)(&msgCb); // hack tmsgSetDefaultMsgCb(&msgCb); SMnodeOpt opt = {0}; opt.deploy = 1; opt.replica = 1; opt.replicas[0].id = 1; opt.replicas[0].port = 9040; strcpy(opt.replicas[0].fqdn, "localhost"); opt.msgCb = msgCb; tsTransPullupMs = 1000; const char *mnodepath = "/tmp/mnode_test_trans"; taosRemoveDir(mnodepath); pMnode = mndOpen(mnodepath, &opt); mndStart(pMnode); } static void SetUpTestSuite() { InitLog(); walInit(); InitMnode(); } static void TearDownTestSuite() { mndStop(pMnode); mndClose(pMnode); walCleanUp(); taosCloseLog(); taosStopCacheRefreshWorker(); } static SMnode *pMnode; public: void SetUp() override {} void TearDown() override {} int32_t CreateUserLog(const char *acct, const char *user) { SUserObj userObj = {0}; taosEncryptPass_c((uint8_t *)"taosdata", strlen("taosdata"), userObj.pass); tstrncpy(userObj.user, user, TSDB_USER_LEN); tstrncpy(userObj.acct, acct, TSDB_USER_LEN); userObj.createdTime = taosGetTimestampMs(); userObj.updateTime = userObj.createdTime; userObj.superUser = 1; SRpcMsg rpcMsg = {0}; STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_TYPE_CREATE_USER, &rpcMsg); SSdbRaw *pRedoRaw = mndUserActionEncode(&userObj); mndTransAppendRedolog(pTrans, pRedoRaw); sdbSetRawStatus(pRedoRaw, SDB_STATUS_READY); SSdbRaw *pUndoRaw = mndUserActionEncode(&userObj); mndTransAppendUndolog(pTrans, pUndoRaw); sdbSetRawStatus(pUndoRaw, SDB_STATUS_DROPPED); char *param = strdup("====> test log <====="); mndTransSetCb(pTrans, TEST_TRANS_START_FUNC, TEST_TRANS_STOP_FUNC, param, strlen(param) + 1); int32_t code = mndTransPrepare(pMnode, pTrans); mndTransDrop(pTrans); return code; } int32_t CreateUserAction(const char *acct, const char *user, bool hasUndoAction) { SUserObj userObj = {0}; taosEncryptPass_c((uint8_t *)"taosdata", strlen("taosdata"), userObj.pass); tstrncpy(userObj.user, user, TSDB_USER_LEN); tstrncpy(userObj.acct, acct, TSDB_USER_LEN); userObj.createdTime = taosGetTimestampMs(); userObj.updateTime = userObj.createdTime; userObj.superUser = 1; SRpcMsg rpcMsg = {0}; STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_TYPE_CREATE_USER, &rpcMsg); SSdbRaw *pRedoRaw = mndUserActionEncode(&userObj); mndTransAppendRedolog(pTrans, pRedoRaw); sdbSetRawStatus(pRedoRaw, SDB_STATUS_READY); SSdbRaw *pUndoRaw = mndUserActionEncode(&userObj); mndTransAppendUndolog(pTrans, pUndoRaw); sdbSetRawStatus(pUndoRaw, SDB_STATUS_DROPPED); char *param = strdup("====> test action <====="); mndTransSetCb(pTrans, TEST_TRANS_START_FUNC, TEST_TRANS_STOP_FUNC, param, strlen(param) + 1); { STransAction action = {0}; action.epSet.inUse = 0; action.epSet.numOfEps = 1; action.epSet.eps[0].port = 9040; strcpy(action.epSet.eps[0].fqdn, "localhost"); int32_t contLen = 1024; void *pReq = taosMemoryCalloc(1, contLen); strcpy((char *)pReq, "hello world redo"); action.pCont = pReq; action.contLen = contLen; action.msgType = TDMT_DND_CREATE_MNODE; action.acceptableCode = TSDB_CODE_NODE_ALREADY_DEPLOYED; mndTransAppendRedoAction(pTrans, &action); } if (hasUndoAction) { STransAction action = {0}; action.epSet.inUse = 0; action.epSet.numOfEps = 1; action.epSet.eps[0].port = 9040; strcpy(action.epSet.eps[0].fqdn, "localhost"); int32_t contLen = 1024; void *pReq = taosMemoryCalloc(1, contLen); strcpy((char *)pReq, "hello world undo"); action.pCont = pReq; action.contLen = contLen; action.msgType = TDMT_DND_CREATE_MNODE; action.acceptableCode = TSDB_CODE_NODE_ALREADY_DEPLOYED; mndTransAppendUndoAction(pTrans, &action); } int32_t code = mndTransPrepare(pMnode, pTrans); mndTransDrop(pTrans); return code; } }; SMnode *MndTestTrans2::pMnode; TEST_F(MndTestTrans2, 01_Log) { const char *acct = "root"; const char *acct_invalid = "root1"; const char *user1 = "log1"; const char *user2 = "log2"; SUserObj *pUser1 = NULL; SUserObj *pUser2 = NULL; ASSERT_NE(pMnode, nullptr); EXPECT_EQ(CreateUserLog(acct, user1), 0); pUser1 = mndAcquireUser(pMnode, user1); ASSERT_NE(pUser1, nullptr); // failed to create user and rollback EXPECT_EQ(CreateUserLog(acct_invalid, user2), 0); pUser2 = mndAcquireUser(pMnode, user2); ASSERT_EQ(pUser2, nullptr); mndTransPullup(pMnode); } TEST_F(MndTestTrans2, 02_Action) { const char *acct = "root"; const char *acct_invalid = "root1"; const char *user1 = "action1"; const char *user2 = "action2"; SUserObj *pUser1 = NULL; SUserObj *pUser2 = NULL; STrans *pTrans = NULL; int32_t transId = 4; int32_t action = 0; ASSERT_NE(pMnode, nullptr); // failed to create user and rollback EXPECT_EQ(CreateUserAction(acct, user1, false), 0); pUser1 = mndAcquireUser(pMnode, user1); ASSERT_EQ(pUser1, nullptr); mndReleaseUser(pMnode, pUser1); // create user, and fake a response EXPECT_EQ(CreateUserAction(acct, user1, true), 0); pUser1 = mndAcquireUser(pMnode, user1); ASSERT_NE(pUser1, nullptr); mndReleaseUser(pMnode, pUser1); pTrans = mndAcquireTrans(pMnode, transId); EXPECT_EQ(pTrans->code, TSDB_CODE_INVALID_PTR); EXPECT_EQ(pTrans->stage, TRN_STAGE_UNDO_ACTION); EXPECT_EQ(pTrans->failedTimes, 1); STransAction *pAction = (STransAction *)taosArrayGet(pTrans->undoActions, action); pAction->msgSent = 1; SNodeMsg rspMsg = {0}; rspMsg.pNode = pMnode; int64_t signature = transId; signature = (signature << 32); signature += action; rspMsg.rpcMsg.ahandle = (void *)signature; mndTransProcessRsp(&rspMsg); mndReleaseTrans(pMnode, pTrans); pUser1 = mndAcquireUser(pMnode, user1); ASSERT_EQ(pUser1, nullptr); mndReleaseUser(pMnode, pUser1); }