提交 4d33cb8f 编写于 作者: H Haojun Liao

Merge remote-tracking branch 'origin/3.0' into feature/3.0_liaohj

......@@ -306,6 +306,7 @@ static void dndProcessQnodeQueue(SDnode *pDnode, SRpcMsg *pMsg) {
}
dndReleaseQnode(pDnode, pQnode);
if (pMsg->msgType & 1u) {
if (pRsp != NULL) {
pRsp->ahandle = pMsg->ahandle;
rpcSendResponse(pRsp);
......@@ -315,6 +316,7 @@ static void dndProcessQnodeQueue(SDnode *pDnode, SRpcMsg *pMsg) {
SRpcMsg rpcRsp = {.handle = pMsg->handle, .ahandle = pMsg->ahandle, .code = code};
rpcSendResponse(&rpcRsp);
}
}
rpcFreeCont(pMsg->pCont);
taosFreeQitem(pMsg);
......
......@@ -300,6 +300,7 @@ static void dndProcessSnodeQueue(SDnode *pDnode, SRpcMsg *pMsg) {
}
dndReleaseSnode(pDnode, pSnode);
if (pMsg->msgType & 1u) {
if (pRsp != NULL) {
pRsp->ahandle = pMsg->ahandle;
rpcSendResponse(pRsp);
......@@ -309,6 +310,7 @@ static void dndProcessSnodeQueue(SDnode *pDnode, SRpcMsg *pMsg) {
SRpcMsg rpcRsp = {.handle = pMsg->handle, .ahandle = pMsg->ahandle, .code = code};
rpcSendResponse(&rpcRsp);
}
}
rpcFreeCont(pMsg->pCont);
taosFreeQitem(pMsg);
......
enable_testing()
add_subdirectory(qnode)
add_subdirectory(bnode)
add_subdirectory(snode)
# add_subdirectory(auth)
# add_subdirectory(balance)
......
aux_source_directory(. BQTEST_SRC)
add_executable(dnode_test_bnode ${BQTEST_SRC})
target_link_libraries(
dnode_test_bnode
PUBLIC sut
)
add_test(
NAME dnode_test_bnode
COMMAND dnode_test_bnode
)
/**
* @file dnode.cpp
* @author slguan (slguan@taosdata.com)
* @brief DNODE module dnode-msg tests
* @version 0.1
* @date 2021-12-15
*
* @copyright Copyright (c) 2021
*
*/
#include "sut.h"
class DndTestBnode : public ::testing::Test {
public:
void SetUp() override {}
void TearDown() override {}
public:
static void SetUpTestSuite() {
test.Init("/tmp/dnode_test_bnode1", 9068);
const char* fqdn = "localhost";
const char* firstEp = "localhost:9068";
server2.Start("/tmp/dnode_test_bnode2", fqdn, 9069, firstEp);
taosMsleep(300);
}
static void TearDownTestSuite() {
server2.Stop();
test.Cleanup();
}
static Testbase test;
static TestServer server2;
};
Testbase DndTestBnode::test;
TestServer DndTestBnode::server2;
TEST_F(DndTestBnode, 01_ShowBnode) {
test.SendShowMetaMsg(TSDB_MGMT_TABLE_BNODE, "");
CHECK_META("show bnodes", 3);
CHECK_SCHEMA(0, TSDB_DATA_TYPE_SMALLINT, 2, "id");
CHECK_SCHEMA(1, TSDB_DATA_TYPE_BINARY, TSDB_EP_LEN + VARSTR_HEADER_SIZE, "endpoint");
CHECK_SCHEMA(2, TSDB_DATA_TYPE_TIMESTAMP, 8, "create_time");
test.SendShowRetrieveMsg();
EXPECT_EQ(test.GetShowRows(), 0);
}
TEST_F(DndTestBnode, 02_Create_Bnode_Invalid_Id) {
{
int32_t contLen = sizeof(SMCreateBnodeReq);
SMCreateBnodeReq* pReq = (SMCreateBnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(1);
SRpcMsg* pMsg = test.SendMsg(TDMT_MND_CREATE_BNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, 0);
test.SendShowMetaMsg(TSDB_MGMT_TABLE_BNODE, "");
CHECK_META("show bnodes", 3);
CHECK_SCHEMA(0, TSDB_DATA_TYPE_SMALLINT, 2, "id");
CHECK_SCHEMA(1, TSDB_DATA_TYPE_BINARY, TSDB_EP_LEN + VARSTR_HEADER_SIZE, "endpoint");
CHECK_SCHEMA(2, TSDB_DATA_TYPE_TIMESTAMP, 8, "create_time");
test.SendShowRetrieveMsg();
EXPECT_EQ(test.GetShowRows(), 1);
CheckInt16(1);
CheckBinary("localhost:9068", TSDB_EP_LEN);
CheckTimestamp();
}
}
TEST_F(DndTestBnode, 03_Create_Bnode_Invalid_Id) {
{
int32_t contLen = sizeof(SMCreateBnodeReq);
SMCreateBnodeReq* pReq = (SMCreateBnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(2);
SRpcMsg* pMsg = test.SendMsg(TDMT_MND_CREATE_BNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, TSDB_CODE_MND_DNODE_NOT_EXIST);
}
}
TEST_F(DndTestBnode, 04_Create_Bnode) {
{
// create dnode
int32_t contLen = sizeof(SCreateDnodeMsg);
SCreateDnodeMsg* pReq = (SCreateDnodeMsg*)rpcMallocCont(contLen);
strcpy(pReq->fqdn, "localhost");
pReq->port = htonl(9069);
SRpcMsg* pMsg = test.SendMsg(TDMT_MND_CREATE_DNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, 0);
taosMsleep(1300);
test.SendShowMetaMsg(TSDB_MGMT_TABLE_DNODE, "");
test.SendShowRetrieveMsg();
EXPECT_EQ(test.GetShowRows(), 2);
}
{
// create bnode
int32_t contLen = sizeof(SMCreateBnodeReq);
SMCreateBnodeReq* pReq = (SMCreateBnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(2);
SRpcMsg* pMsg = test.SendMsg(TDMT_MND_CREATE_BNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, 0);
test.SendShowMetaMsg(TSDB_MGMT_TABLE_BNODE, "");
test.SendShowRetrieveMsg();
EXPECT_EQ(test.GetShowRows(), 2);
CheckInt16(1);
CheckInt16(2);
CheckBinary("localhost:9068", TSDB_EP_LEN);
CheckBinary("localhost:9069", TSDB_EP_LEN);
CheckTimestamp();
CheckTimestamp();
}
{
// drop bnode
int32_t contLen = sizeof(SMDropBnodeReq);
SMDropBnodeReq* pReq = (SMDropBnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(2);
SRpcMsg* pMsg = test.SendMsg(TDMT_MND_DROP_BNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, 0);
test.SendShowMetaMsg(TSDB_MGMT_TABLE_BNODE, "");
test.SendShowRetrieveMsg();
EXPECT_EQ(test.GetShowRows(), 1);
CheckInt16(1);
CheckBinary("localhost:9068", TSDB_EP_LEN);
CheckTimestamp();
}
}
\ No newline at end of file
/**
* @file dbnode.cpp
* @author slguan (slguan@taosdata.com)
* @brief DNODE module bnode tests
* @version 1.0
* @date 2022-01-05
*
* @copyright Copyright (c) 2022
*
*/
#include "sut.h"
class DndTestBnode : public ::testing::Test {
protected:
static void SetUpTestSuite() { test.Init("/tmp/dnode_test_snode", 9112); }
static void TearDownTestSuite() { test.Cleanup(); }
static Testbase test;
public:
void SetUp() override {}
void TearDown() override {}
};
Testbase DndTestBnode::test;
TEST_F(DndTestBnode, 01_Create_Bnode) {
{
int32_t contLen = sizeof(SDCreateBnodeReq);
SDCreateBnodeReq* pReq = (SDCreateBnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(2);
SRpcMsg* pMsg = test.SendMsg(TDMT_DND_CREATE_BNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, TSDB_CODE_DND_BNODE_ID_INVALID);
}
{
int32_t contLen = sizeof(SDCreateBnodeReq);
SDCreateBnodeReq* pReq = (SDCreateBnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(1);
SRpcMsg* pMsg = test.SendMsg(TDMT_DND_CREATE_BNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, 0);
}
{
int32_t contLen = sizeof(SDCreateBnodeReq);
SDCreateBnodeReq* pReq = (SDCreateBnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(1);
SRpcMsg* pMsg = test.SendMsg(TDMT_DND_CREATE_BNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, TSDB_CODE_DND_BNODE_ALREADY_DEPLOYED);
}
test.Restart();
{
int32_t contLen = sizeof(SDCreateBnodeReq);
SDCreateBnodeReq* pReq = (SDCreateBnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(1);
SRpcMsg* pMsg = test.SendMsg(TDMT_DND_CREATE_BNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, TSDB_CODE_DND_BNODE_ALREADY_DEPLOYED);
}
}
TEST_F(DndTestBnode, 01_Drop_Bnode) {
{
int32_t contLen = sizeof(SDDropBnodeReq);
SDDropBnodeReq* pReq = (SDDropBnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(2);
SRpcMsg* pMsg = test.SendMsg(TDMT_DND_DROP_BNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, TSDB_CODE_DND_BNODE_ID_INVALID);
}
{
int32_t contLen = sizeof(SDDropBnodeReq);
SDDropBnodeReq* pReq = (SDDropBnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(1);
SRpcMsg* pMsg = test.SendMsg(TDMT_DND_DROP_BNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, 0);
}
{
int32_t contLen = sizeof(SDDropBnodeReq);
SDDropBnodeReq* pReq = (SDDropBnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(1);
SRpcMsg* pMsg = test.SendMsg(TDMT_DND_DROP_BNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, TSDB_CODE_DND_BNODE_NOT_DEPLOYED);
}
test.Restart();
{
int32_t contLen = sizeof(SDDropBnodeReq);
SDDropBnodeReq* pReq = (SDDropBnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(1);
SRpcMsg* pMsg = test.SendMsg(TDMT_DND_DROP_BNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, TSDB_CODE_DND_BNODE_NOT_DEPLOYED);
}
{
int32_t contLen = sizeof(SDCreateBnodeReq);
SDCreateBnodeReq* pReq = (SDCreateBnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(1);
SRpcMsg* pMsg = test.SendMsg(TDMT_DND_CREATE_BNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, 0);
}
}
\ No newline at end of file
......@@ -25,7 +25,7 @@ class DndTestQnode : public ::testing::Test {
Testbase DndTestQnode::test;
TEST_F(DndTestQnode, 01_Create_Qnode_Invalid) {
TEST_F(DndTestQnode, 01_Create_Qnode) {
{
int32_t contLen = sizeof(SDCreateQnodeReq);
......@@ -72,3 +72,62 @@ TEST_F(DndTestQnode, 01_Create_Qnode_Invalid) {
ASSERT_EQ(pMsg->code, TSDB_CODE_DND_QNODE_ALREADY_DEPLOYED);
}
}
TEST_F(DndTestQnode, 01_Drop_Qnode) {
{
int32_t contLen = sizeof(SDDropQnodeReq);
SDDropQnodeReq* pReq = (SDDropQnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(2);
SRpcMsg* pMsg = test.SendMsg(TDMT_DND_DROP_QNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, TSDB_CODE_DND_QNODE_ID_INVALID);
}
{
int32_t contLen = sizeof(SDDropQnodeReq);
SDDropQnodeReq* pReq = (SDDropQnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(1);
SRpcMsg* pMsg = test.SendMsg(TDMT_DND_DROP_QNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, 0);
}
{
int32_t contLen = sizeof(SDDropQnodeReq);
SDDropQnodeReq* pReq = (SDDropQnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(1);
SRpcMsg* pMsg = test.SendMsg(TDMT_DND_DROP_QNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, TSDB_CODE_DND_QNODE_NOT_DEPLOYED);
}
test.Restart();
{
int32_t contLen = sizeof(SDDropQnodeReq);
SDDropQnodeReq* pReq = (SDDropQnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(1);
SRpcMsg* pMsg = test.SendMsg(TDMT_DND_DROP_QNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, TSDB_CODE_DND_QNODE_NOT_DEPLOYED);
}
{
int32_t contLen = sizeof(SDCreateQnodeReq);
SDCreateQnodeReq* pReq = (SDCreateQnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(1);
SRpcMsg* pMsg = test.SendMsg(TDMT_DND_CREATE_QNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, 0);
}
}
\ No newline at end of file
aux_source_directory(. SQTEST_SRC)
add_executable(dnode_test_snode ${SQTEST_SRC})
target_link_libraries(
dnode_test_snode
PUBLIC sut
)
add_test(
NAME dnode_test_snode
COMMAND dnode_test_snode
)
/**
* @file dsnode.cpp
* @author slguan (slguan@taosdata.com)
* @brief DNODE module snode tests
* @version 1.0
* @date 2022-01-05
*
* @copyright Copyright (c) 2022
*
*/
#include "sut.h"
class DndTestSnode : public ::testing::Test {
protected:
static void SetUpTestSuite() { test.Init("/tmp/dnode_test_snode", 9112); }
static void TearDownTestSuite() { test.Cleanup(); }
static Testbase test;
public:
void SetUp() override {}
void TearDown() override {}
};
Testbase DndTestSnode::test;
TEST_F(DndTestSnode, 01_Create_Snode) {
{
int32_t contLen = sizeof(SDCreateSnodeReq);
SDCreateSnodeReq* pReq = (SDCreateSnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(2);
SRpcMsg* pMsg = test.SendMsg(TDMT_DND_CREATE_SNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, TSDB_CODE_DND_SNODE_ID_INVALID);
}
{
int32_t contLen = sizeof(SDCreateSnodeReq);
SDCreateSnodeReq* pReq = (SDCreateSnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(1);
SRpcMsg* pMsg = test.SendMsg(TDMT_DND_CREATE_SNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, 0);
}
{
int32_t contLen = sizeof(SDCreateSnodeReq);
SDCreateSnodeReq* pReq = (SDCreateSnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(1);
SRpcMsg* pMsg = test.SendMsg(TDMT_DND_CREATE_SNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, TSDB_CODE_DND_SNODE_ALREADY_DEPLOYED);
}
test.Restart();
{
int32_t contLen = sizeof(SDCreateSnodeReq);
SDCreateSnodeReq* pReq = (SDCreateSnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(1);
SRpcMsg* pMsg = test.SendMsg(TDMT_DND_CREATE_SNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, TSDB_CODE_DND_SNODE_ALREADY_DEPLOYED);
}
}
TEST_F(DndTestSnode, 01_Drop_Snode) {
{
int32_t contLen = sizeof(SDDropSnodeReq);
SDDropSnodeReq* pReq = (SDDropSnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(2);
SRpcMsg* pMsg = test.SendMsg(TDMT_DND_DROP_SNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, TSDB_CODE_DND_SNODE_ID_INVALID);
}
{
int32_t contLen = sizeof(SDDropSnodeReq);
SDDropSnodeReq* pReq = (SDDropSnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(1);
SRpcMsg* pMsg = test.SendMsg(TDMT_DND_DROP_SNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, 0);
}
{
int32_t contLen = sizeof(SDDropSnodeReq);
SDDropSnodeReq* pReq = (SDDropSnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(1);
SRpcMsg* pMsg = test.SendMsg(TDMT_DND_DROP_SNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, TSDB_CODE_DND_SNODE_NOT_DEPLOYED);
}
test.Restart();
{
int32_t contLen = sizeof(SDDropSnodeReq);
SDDropSnodeReq* pReq = (SDDropSnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(1);
SRpcMsg* pMsg = test.SendMsg(TDMT_DND_DROP_SNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, TSDB_CODE_DND_SNODE_NOT_DEPLOYED);
}
{
int32_t contLen = sizeof(SDCreateSnodeReq);
SDCreateSnodeReq* pReq = (SDCreateSnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(1);
SRpcMsg* pMsg = test.SendMsg(TDMT_DND_CREATE_SNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, 0);
}
}
\ No newline at end of file
......@@ -366,6 +366,7 @@ SMnodeMsg *mndInitMsg(SMnode *pMnode, SRpcMsg *pRpcMsg) {
return NULL;
}
if (pRpcMsg->msgType != TDMT_MND_TRANS) {
SRpcConnInfo connInfo = {0};
if ((pRpcMsg->msgType & 1U) && rpcGetConnInfo(pRpcMsg->handle, &connInfo) != 0) {
taosFreeQitem(pMsg);
......@@ -374,6 +375,7 @@ SMnodeMsg *mndInitMsg(SMnode *pMnode, SRpcMsg *pRpcMsg) {
return NULL;
}
memcpy(pMsg->user, connInfo.user, TSDB_USER_LEN);
}
pMsg->pMnode = pMnode;
pMsg->rpcMsg = *pRpcMsg;
......
......@@ -50,7 +50,18 @@ TEST_F(MndTestQnode, 01_Show_Qnode) {
EXPECT_EQ(test.GetShowRows(), 0);
}
TEST_F(MndTestQnode, 02_Create_Qnode_Invalid_Id) {
TEST_F(MndTestQnode, 02_Create_Qnode) {
{
int32_t contLen = sizeof(SMCreateQnodeReq);
SMCreateQnodeReq* pReq = (SMCreateQnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(2);
SRpcMsg* pMsg = test.SendMsg(TDMT_MND_CREATE_QNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
ASSERT_EQ(pMsg->code, TSDB_CODE_MND_DNODE_NOT_EXIST);
}
{
int32_t contLen = sizeof(SMCreateQnodeReq);
......@@ -63,11 +74,6 @@ TEST_F(MndTestQnode, 02_Create_Qnode_Invalid_Id) {
test.SendShowMetaMsg(TSDB_MGMT_TABLE_QNODE, "");
CHECK_META("show qnodes", 3);
CHECK_SCHEMA(0, TSDB_DATA_TYPE_SMALLINT, 2, "id");
CHECK_SCHEMA(1, TSDB_DATA_TYPE_BINARY, TSDB_EP_LEN + VARSTR_HEADER_SIZE, "endpoint");
CHECK_SCHEMA(2, TSDB_DATA_TYPE_TIMESTAMP, 8, "create_time");
test.SendShowRetrieveMsg();
EXPECT_EQ(test.GetShowRows(), 1);
......@@ -75,14 +81,12 @@ TEST_F(MndTestQnode, 02_Create_Qnode_Invalid_Id) {
CheckBinary("localhost:9014", TSDB_EP_LEN);
CheckTimestamp();
}
}
TEST_F(MndTestQnode, 03_Create_Qnode_Invalid_Id) {
{
int32_t contLen = sizeof(SMCreateQnodeReq);
SMCreateQnodeReq* pReq = (SMCreateQnodeReq*)rpcMallocCont(contLen);
pReq->dnodeId = htonl(2);
pReq->dnodeId = htonl(1);
SRpcMsg* pMsg = test.SendMsg(TDMT_MND_CREATE_QNODE, pReq, contLen);
ASSERT_NE(pMsg, nullptr);
......
......@@ -423,6 +423,8 @@ void rpcSendRequest(void *shandle, const SEpSet *pEpSet, SRpcMsg *pMsg, int64_t
}
void rpcSendResponse(const SRpcMsg *pRsp) {
if (pRsp->handle == NULL) return;
int msgLen = 0;
SRpcConn *pConn = (SRpcConn *)pRsp->handle;
SRpcMsg rpcMsg = *pRsp;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册