/** * @file func.cpp * @author slguan (slguan@taosdata.com) * @brief MNODE module func tests * @version 1.0 * @date 2022-01-24 * * @copyright Copyright (c) 2022 * */ #include "sut.h" class MndTestFunc : public ::testing::Test { protected: static void SetUpTestSuite() { test.Init("/tmp/mnode_test_func", 9038); } static void TearDownTestSuite() { test.Cleanup(); } static Testbase test; public: void SetUp() override {} void TearDown() override {} }; Testbase MndTestFunc::test; TEST_F(MndTestFunc, 01_Show_Func) { test.SendShowMetaReq(TSDB_MGMT_TABLE_FUNC, ""); CHECK_META("show functions", 7); CHECK_SCHEMA(0, TSDB_DATA_TYPE_BINARY, TSDB_FUNC_NAME_LEN + VARSTR_HEADER_SIZE, "name"); CHECK_SCHEMA(1, TSDB_DATA_TYPE_BINARY, PATH_MAX + VARSTR_HEADER_SIZE, "comment"); CHECK_SCHEMA(2, TSDB_DATA_TYPE_INT, 4, "aggregate"); CHECK_SCHEMA(3, TSDB_DATA_TYPE_BINARY, TSDB_TYPE_STR_MAX_LEN + VARSTR_HEADER_SIZE, "outputtype"); CHECK_SCHEMA(4, TSDB_DATA_TYPE_TIMESTAMP, 8, "create_time"); CHECK_SCHEMA(5, TSDB_DATA_TYPE_INT, 4, "code_len"); CHECK_SCHEMA(6, TSDB_DATA_TYPE_INT, 4, "bufsize"); test.SendShowRetrieveReq(); EXPECT_EQ(test.GetShowRows(), 0); } TEST_F(MndTestFunc, 02_Create_Func) { { int32_t contLen = sizeof(SCreateFuncReq); SCreateFuncReq* pReq = (SCreateFuncReq*)rpcMallocCont(contLen); strcpy(pReq->name, ""); SRpcMsg* pRsp = test.SendReq(TDMT_MND_CREATE_FUNC, pReq, contLen); ASSERT_NE(pRsp, nullptr); ASSERT_EQ(pRsp->code, TSDB_CODE_MND_INVALID_FUNC_NAME); } { int32_t contLen = sizeof(SCreateFuncReq); SCreateFuncReq* pReq = (SCreateFuncReq*)rpcMallocCont(contLen); strcpy(pReq->name, "f1"); SRpcMsg* pRsp = test.SendReq(TDMT_MND_CREATE_FUNC, pReq, contLen); ASSERT_NE(pRsp, nullptr); ASSERT_EQ(pRsp->code, TSDB_CODE_MND_INVALID_FUNC_COMMENT); } { int32_t contLen = sizeof(SCreateFuncReq); SCreateFuncReq* pReq = (SCreateFuncReq*)rpcMallocCont(contLen); strcpy(pReq->name, "f1"); pReq->commentSize = htonl(TSDB_FUNC_COMMENT_LEN + 1); SRpcMsg* pRsp = test.SendReq(TDMT_MND_CREATE_FUNC, pReq, contLen); ASSERT_NE(pRsp, nullptr); ASSERT_EQ(pRsp->code, TSDB_CODE_MND_INVALID_FUNC_COMMENT); } { int32_t contLen = sizeof(SCreateFuncReq); SCreateFuncReq* pReq = (SCreateFuncReq*)rpcMallocCont(contLen); strcpy(pReq->name, "f1"); pReq->commentSize = htonl(TSDB_FUNC_COMMENT_LEN); SRpcMsg* pRsp = test.SendReq(TDMT_MND_CREATE_FUNC, pReq, contLen); ASSERT_NE(pRsp, nullptr); ASSERT_EQ(pRsp->code, TSDB_CODE_MND_INVALID_FUNC_CODE); } { int32_t contLen = sizeof(SCreateFuncReq); SCreateFuncReq* pReq = (SCreateFuncReq*)rpcMallocCont(contLen); strcpy(pReq->name, "f1"); pReq->commentSize = htonl(TSDB_FUNC_COMMENT_LEN); pReq->codeSize = htonl(TSDB_FUNC_CODE_LEN - 1); SRpcMsg* pRsp = test.SendReq(TDMT_MND_CREATE_FUNC, pReq, contLen); ASSERT_NE(pRsp, nullptr); ASSERT_EQ(pRsp->code, TSDB_CODE_MND_INVALID_FUNC_CODE); } { int32_t contLen = sizeof(SCreateFuncReq) + 24; SCreateFuncReq* pReq = (SCreateFuncReq*)rpcMallocCont(contLen); strcpy(pReq->name, "f1"); pReq->commentSize = htonl(TSDB_FUNC_COMMENT_LEN); pReq->codeSize = htonl(TSDB_FUNC_CODE_LEN); pReq->pCont[0] = 0; SRpcMsg* pRsp = test.SendReq(TDMT_MND_CREATE_FUNC, pReq, contLen); ASSERT_NE(pRsp, nullptr); ASSERT_EQ(pRsp->code, TSDB_CODE_MND_INVALID_FUNC_CODE); } { int32_t contLen = sizeof(SCreateFuncReq) + 24; SCreateFuncReq* pReq = (SCreateFuncReq*)rpcMallocCont(contLen); strcpy(pReq->name, "f1"); pReq->commentSize = htonl(TSDB_FUNC_COMMENT_LEN); pReq->codeSize = htonl(TSDB_FUNC_CODE_LEN); pReq->pCont[0] = 'a'; SRpcMsg* pRsp = test.SendReq(TDMT_MND_CREATE_FUNC, pReq, contLen); ASSERT_NE(pRsp, nullptr); ASSERT_EQ(pRsp->code, TSDB_CODE_MND_INVALID_FUNC_BUFSIZE); } { int32_t contLen = sizeof(SCreateFuncReq) + 24; SCreateFuncReq* pReq = (SCreateFuncReq*)rpcMallocCont(contLen); strcpy(pReq->name, "f1"); pReq->commentSize = htonl(TSDB_FUNC_COMMENT_LEN); pReq->codeSize = htonl(TSDB_FUNC_CODE_LEN); pReq->pCont[0] = 'a'; pReq->bufSize = htonl(TSDB_FUNC_BUF_SIZE + 1); SRpcMsg* pRsp = test.SendReq(TDMT_MND_CREATE_FUNC, pReq, contLen); ASSERT_NE(pRsp, nullptr); ASSERT_EQ(pRsp->code, TSDB_CODE_MND_INVALID_FUNC_BUFSIZE); } for (int32_t i = 0; i < 3; ++i) { int32_t contLen = sizeof(SCreateFuncReq); int32_t commentSize = TSDB_FUNC_COMMENT_LEN; int32_t codeSize = TSDB_FUNC_CODE_LEN; contLen = (contLen + codeSize + commentSize); SCreateFuncReq* pReq = (SCreateFuncReq*)rpcMallocCont(contLen); strcpy(pReq->name, "f1"); pReq->igExists = 0; if (i == 2) pReq->igExists = 1; pReq->funcType = 1; pReq->scriptType = 2; pReq->outputType = TSDB_DATA_TYPE_SMALLINT; pReq->outputLen = htonl(12); pReq->bufSize = htonl(4); pReq->signature = htobe64(5); pReq->commentSize = htonl(commentSize); pReq->codeSize = htonl(codeSize); for (int32_t i = 0; i < commentSize - 1; ++i) { pReq->pCont[i] = 'm'; } for (int32_t i = commentSize; i < commentSize + codeSize - 1; ++i) { pReq->pCont[i] = 'd'; } SRpcMsg* pRsp = test.SendReq(TDMT_MND_CREATE_FUNC, pReq, contLen); ASSERT_NE(pRsp, nullptr); if (i == 0 || i == 2) { ASSERT_EQ(pRsp->code, 0); } else { ASSERT_EQ(pRsp->code, TSDB_CODE_MND_FUNC_ALREADY_EXIST); } } test.SendShowMetaReq(TSDB_MGMT_TABLE_FUNC, ""); CHECK_META("show functions", 7); test.SendShowRetrieveReq(); EXPECT_EQ(test.GetShowRows(), 1); CheckBinary("f1", TSDB_FUNC_NAME_LEN); CheckBinaryByte('m', TSDB_FUNC_COMMENT_LEN); CheckInt32(0); CheckBinary("SMALLINT", TSDB_TYPE_STR_MAX_LEN); CheckTimestamp(); CheckInt32(TSDB_FUNC_CODE_LEN); CheckInt32(4); } TEST_F(MndTestFunc, 03_Retrieve_Func) { { int32_t contLen = sizeof(SRetrieveFuncReq); int32_t numOfFuncs = 1; contLen = (contLen + numOfFuncs * TSDB_FUNC_NAME_LEN); SRetrieveFuncReq* pReq = (SRetrieveFuncReq*)rpcMallocCont(contLen); pReq->numOfFuncs = htonl(1); strcpy(pReq->pFuncNames, "f1"); SRpcMsg* pRsp = test.SendReq(TDMT_MND_RETRIEVE_FUNC, pReq, contLen); ASSERT_NE(pRsp, nullptr); ASSERT_EQ(pRsp->code, 0); SRetrieveFuncRsp* pRetrieveRsp = (SRetrieveFuncRsp*)pRsp->pCont; pRetrieveRsp->numOfFuncs = htonl(pRetrieveRsp->numOfFuncs); SFuncInfo* pFuncInfo = (SFuncInfo*)(pRetrieveRsp->pFuncInfos); pFuncInfo->outputLen = htonl(pFuncInfo->outputLen); pFuncInfo->bufSize = htonl(pFuncInfo->bufSize); pFuncInfo->signature = htobe64(pFuncInfo->signature); pFuncInfo->commentSize = htonl(pFuncInfo->commentSize); pFuncInfo->codeSize = htonl(pFuncInfo->codeSize); EXPECT_STREQ(pFuncInfo->name, "f1"); EXPECT_EQ(pFuncInfo->funcType, 1); EXPECT_EQ(pFuncInfo->scriptType, 2); EXPECT_EQ(pFuncInfo->outputType, TSDB_DATA_TYPE_SMALLINT); EXPECT_EQ(pFuncInfo->outputLen, 12); EXPECT_EQ(pFuncInfo->bufSize, 4); EXPECT_EQ(pFuncInfo->signature, 5); EXPECT_EQ(pFuncInfo->commentSize, TSDB_FUNC_COMMENT_LEN); EXPECT_EQ(pFuncInfo->codeSize, TSDB_FUNC_CODE_LEN); char* pComment = pFuncInfo->pCont; char* pCode = pFuncInfo->pCont + pFuncInfo->commentSize; char comments[TSDB_FUNC_COMMENT_LEN] = {0}; for (int32_t i = 0; i < TSDB_FUNC_COMMENT_LEN - 1; ++i) { comments[i] = 'm'; } char codes[TSDB_FUNC_CODE_LEN] = {0}; for (int32_t i = 0; i < TSDB_FUNC_CODE_LEN - 1; ++i) { codes[i] = 'd'; } EXPECT_STREQ(pComment, comments); EXPECT_STREQ(pCode, codes); } { int32_t contLen = sizeof(SRetrieveFuncReq); int32_t numOfFuncs = 0; contLen = (contLen + numOfFuncs * TSDB_FUNC_NAME_LEN); SRetrieveFuncReq* pReq = (SRetrieveFuncReq*)rpcMallocCont(contLen); pReq->numOfFuncs = htonl(numOfFuncs); SRpcMsg* pRsp = test.SendReq(TDMT_MND_RETRIEVE_FUNC, pReq, contLen); ASSERT_NE(pRsp, nullptr); ASSERT_EQ(pRsp->code, TSDB_CODE_MND_INVALID_FUNC_RETRIEVE); } { int32_t contLen = sizeof(SRetrieveFuncReq); int32_t numOfFuncs = TSDB_FUNC_MAX_RETRIEVE + 1; contLen = (contLen + numOfFuncs * TSDB_FUNC_NAME_LEN); SRetrieveFuncReq* pReq = (SRetrieveFuncReq*)rpcMallocCont(contLen); pReq->numOfFuncs = htonl(numOfFuncs); SRpcMsg* pRsp = test.SendReq(TDMT_MND_RETRIEVE_FUNC, pReq, contLen); ASSERT_NE(pRsp, nullptr); ASSERT_EQ(pRsp->code, TSDB_CODE_MND_INVALID_FUNC_RETRIEVE); } { int32_t contLen = sizeof(SRetrieveFuncReq); int32_t numOfFuncs = 1; contLen = (contLen + numOfFuncs * TSDB_FUNC_NAME_LEN); SRetrieveFuncReq* pReq = (SRetrieveFuncReq*)rpcMallocCont(contLen); pReq->numOfFuncs = htonl(numOfFuncs); strcpy(pReq->pFuncNames, "f2"); SRpcMsg* pRsp = test.SendReq(TDMT_MND_RETRIEVE_FUNC, pReq, contLen); ASSERT_NE(pRsp, nullptr); ASSERT_EQ(pRsp->code, TSDB_CODE_MND_INVALID_FUNC); } { int32_t contLen = sizeof(SCreateFuncReq); int32_t commentSize = 1024; int32_t codeSize = 9527; contLen = (contLen + codeSize + commentSize); SCreateFuncReq* pReq = (SCreateFuncReq*)rpcMallocCont(contLen); strcpy(pReq->name, "f2"); pReq->igExists = 1; pReq->funcType = 2; pReq->scriptType = 3; pReq->outputType = TSDB_DATA_TYPE_BINARY; pReq->outputLen = htonl(24); pReq->bufSize = htonl(6); pReq->signature = htobe64(18); pReq->commentSize = htonl(commentSize); pReq->codeSize = htonl(codeSize); for (int32_t i = 0; i < commentSize - 1; ++i) { pReq->pCont[i] = 'p'; } for (int32_t i = commentSize; i < commentSize + codeSize - 1; ++i) { pReq->pCont[i] = 'q'; } SRpcMsg* pRsp = test.SendReq(TDMT_MND_CREATE_FUNC, pReq, contLen); ASSERT_NE(pRsp, nullptr); ASSERT_EQ(pRsp->code, 0); test.SendShowMetaReq(TSDB_MGMT_TABLE_FUNC, ""); CHECK_META("show functions", 7); test.SendShowRetrieveReq(); EXPECT_EQ(test.GetShowRows(), 2); } { int32_t contLen = sizeof(SRetrieveFuncReq); int32_t numOfFuncs = 1; contLen = (contLen + numOfFuncs * TSDB_FUNC_NAME_LEN); SRetrieveFuncReq* pReq = (SRetrieveFuncReq*)rpcMallocCont(contLen); pReq->numOfFuncs = htonl(1); strcpy(pReq->pFuncNames, "f2"); SRpcMsg* pRsp = test.SendReq(TDMT_MND_RETRIEVE_FUNC, pReq, contLen); ASSERT_NE(pRsp, nullptr); ASSERT_EQ(pRsp->code, 0); SRetrieveFuncRsp* pRetrieveRsp = (SRetrieveFuncRsp*)pRsp->pCont; pRetrieveRsp->numOfFuncs = htonl(pRetrieveRsp->numOfFuncs); SFuncInfo* pFuncInfo = (SFuncInfo*)(pRetrieveRsp->pFuncInfos); pFuncInfo->outputLen = htonl(pFuncInfo->outputLen); pFuncInfo->bufSize = htonl(pFuncInfo->bufSize); pFuncInfo->signature = htobe64(pFuncInfo->signature); pFuncInfo->commentSize = htonl(pFuncInfo->commentSize); pFuncInfo->codeSize = htonl(pFuncInfo->codeSize); EXPECT_STREQ(pFuncInfo->name, "f2"); EXPECT_EQ(pFuncInfo->funcType, 2); EXPECT_EQ(pFuncInfo->scriptType, 3); EXPECT_EQ(pFuncInfo->outputType, TSDB_DATA_TYPE_BINARY); EXPECT_EQ(pFuncInfo->outputLen, 24); EXPECT_EQ(pFuncInfo->bufSize, 6); EXPECT_EQ(pFuncInfo->signature, 18); EXPECT_EQ(pFuncInfo->commentSize, 1024); EXPECT_EQ(pFuncInfo->codeSize, 9527); char* pComment = pFuncInfo->pCont; char* pCode = pFuncInfo->pCont + pFuncInfo->commentSize; char* comments = (char*)calloc(1, 1024); for (int32_t i = 0; i < 1024 - 1; ++i) { comments[i] = 'p'; } char* codes = (char*)calloc(1, 9527); for (int32_t i = 0; i < 9527 - 1; ++i) { codes[i] = 'q'; } EXPECT_STREQ(pComment, comments); EXPECT_STREQ(pCode, codes); free(comments); free(codes); } { int32_t contLen = sizeof(SRetrieveFuncReq); int32_t numOfFuncs = 2; contLen = (contLen + numOfFuncs * TSDB_FUNC_NAME_LEN); SRetrieveFuncReq* pReq = (SRetrieveFuncReq*)rpcMallocCont(contLen); pReq->numOfFuncs = htonl(numOfFuncs); strcpy(pReq->pFuncNames, "f2"); strcpy((char*)pReq->pFuncNames + TSDB_FUNC_NAME_LEN, "f1"); SRpcMsg* pRsp = test.SendReq(TDMT_MND_RETRIEVE_FUNC, pReq, contLen); ASSERT_NE(pRsp, nullptr); ASSERT_EQ(pRsp->code, 0); SRetrieveFuncRsp* pRetrieveRsp = (SRetrieveFuncRsp*)pRsp->pCont; pRetrieveRsp->numOfFuncs = htonl(pRetrieveRsp->numOfFuncs); { SFuncInfo* pFuncInfo = (SFuncInfo*)(pRetrieveRsp->pFuncInfos); pFuncInfo->outputLen = htonl(pFuncInfo->outputLen); pFuncInfo->bufSize = htonl(pFuncInfo->bufSize); pFuncInfo->signature = htobe64(pFuncInfo->signature); pFuncInfo->commentSize = htonl(pFuncInfo->commentSize); pFuncInfo->codeSize = htonl(pFuncInfo->codeSize); EXPECT_STREQ(pFuncInfo->name, "f2"); EXPECT_EQ(pFuncInfo->funcType, 2); EXPECT_EQ(pFuncInfo->scriptType, 3); EXPECT_EQ(pFuncInfo->outputType, TSDB_DATA_TYPE_BINARY); EXPECT_EQ(pFuncInfo->outputLen, 24); EXPECT_EQ(pFuncInfo->bufSize, 6); EXPECT_EQ(pFuncInfo->signature, 18); EXPECT_EQ(pFuncInfo->commentSize, 1024); EXPECT_EQ(pFuncInfo->codeSize, 9527); char* pComment = pFuncInfo->pCont; char* pCode = pFuncInfo->pCont + pFuncInfo->commentSize; char* comments = (char*)calloc(1, 1024); for (int32_t i = 0; i < 1024 - 1; ++i) { comments[i] = 'p'; } char* codes = (char*)calloc(1, 9527); for (int32_t i = 0; i < 9527 - 1; ++i) { codes[i] = 'q'; } EXPECT_STREQ(pComment, comments); EXPECT_STREQ(pCode, codes); free(comments); free(codes); } { SFuncInfo* pFuncInfo = (SFuncInfo*)(pRetrieveRsp->pFuncInfos + sizeof(SFuncInfo) + 1024 + 9527); pFuncInfo->outputLen = htonl(pFuncInfo->outputLen); pFuncInfo->bufSize = htonl(pFuncInfo->bufSize); pFuncInfo->signature = htobe64(pFuncInfo->signature); pFuncInfo->commentSize = htonl(pFuncInfo->commentSize); pFuncInfo->codeSize = htonl(pFuncInfo->codeSize); EXPECT_STREQ(pFuncInfo->name, "f1"); EXPECT_EQ(pFuncInfo->funcType, 1); EXPECT_EQ(pFuncInfo->scriptType, 2); EXPECT_EQ(pFuncInfo->outputType, TSDB_DATA_TYPE_SMALLINT); EXPECT_EQ(pFuncInfo->outputLen, 12); EXPECT_EQ(pFuncInfo->bufSize, 4); EXPECT_EQ(pFuncInfo->signature, 5); EXPECT_EQ(pFuncInfo->commentSize, TSDB_FUNC_COMMENT_LEN); EXPECT_EQ(pFuncInfo->codeSize, TSDB_FUNC_CODE_LEN); char* pComment = pFuncInfo->pCont; char* pCode = pFuncInfo->pCont + pFuncInfo->commentSize; char comments[TSDB_FUNC_COMMENT_LEN] = {0}; for (int32_t i = 0; i < TSDB_FUNC_COMMENT_LEN - 1; ++i) { comments[i] = 'm'; } char codes[TSDB_FUNC_CODE_LEN] = {0}; for (int32_t i = 0; i < TSDB_FUNC_CODE_LEN - 1; ++i) { codes[i] = 'd'; } EXPECT_STREQ(pComment, comments); EXPECT_STREQ(pCode, codes); } } { int32_t contLen = sizeof(SRetrieveFuncReq); int32_t numOfFuncs = 2; contLen = (contLen + numOfFuncs * TSDB_FUNC_NAME_LEN); SRetrieveFuncReq* pReq = (SRetrieveFuncReq*)rpcMallocCont(contLen); pReq->numOfFuncs = htonl(numOfFuncs); strcpy(pReq->pFuncNames, "f2"); strcpy((char*)pReq->pFuncNames + TSDB_FUNC_NAME_LEN, "f3"); SRpcMsg* pRsp = test.SendReq(TDMT_MND_RETRIEVE_FUNC, pReq, contLen); ASSERT_NE(pRsp, nullptr); ASSERT_EQ(pRsp->code, TSDB_CODE_MND_INVALID_FUNC); } } TEST_F(MndTestFunc, 04_Drop_Func) { { int32_t contLen = sizeof(SDropFuncReq); SDropFuncReq* pReq = (SDropFuncReq*)rpcMallocCont(contLen); strcpy(pReq->name, ""); SRpcMsg* pRsp = test.SendReq(TDMT_MND_DROP_FUNC, pReq, contLen); ASSERT_NE(pRsp, nullptr); ASSERT_EQ(pRsp->code, TSDB_CODE_MND_INVALID_FUNC_NAME); } { int32_t contLen = sizeof(SDropFuncReq); SDropFuncReq* pReq = (SDropFuncReq*)rpcMallocCont(contLen); strcpy(pReq->name, "f3"); SRpcMsg* pRsp = test.SendReq(TDMT_MND_DROP_FUNC, pReq, contLen); ASSERT_NE(pRsp, nullptr); ASSERT_EQ(pRsp->code, TSDB_CODE_MND_FUNC_NOT_EXIST); } { int32_t contLen = sizeof(SDropFuncReq); SDropFuncReq* pReq = (SDropFuncReq*)rpcMallocCont(contLen); strcpy(pReq->name, "f3"); pReq->igNotExists = 1; SRpcMsg* pRsp = test.SendReq(TDMT_MND_DROP_FUNC, pReq, contLen); ASSERT_NE(pRsp, nullptr); ASSERT_EQ(pRsp->code, 0); } { int32_t contLen = sizeof(SDropFuncReq); SDropFuncReq* pReq = (SDropFuncReq*)rpcMallocCont(contLen); strcpy(pReq->name, "f1"); SRpcMsg* pRsp = test.SendReq(TDMT_MND_DROP_FUNC, pReq, contLen); ASSERT_NE(pRsp, nullptr); ASSERT_EQ(pRsp->code, 0); } test.SendShowMetaReq(TSDB_MGMT_TABLE_FUNC, ""); CHECK_META("show functions", 7); test.SendShowRetrieveReq(); EXPECT_EQ(test.GetShowRows(), 1); // restart test.Restart(); test.SendShowMetaReq(TSDB_MGMT_TABLE_FUNC, ""); CHECK_META("show functions", 7); test.SendShowRetrieveReq(); EXPECT_EQ(test.GetShowRows(), 1); CheckBinary("f2", TSDB_FUNC_NAME_LEN); }