* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
#include <gtest/gtest.h>
#include "mockcpp/mockcpp.hpp"
#include <fcntl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <vector>
#include "ide_daemon_hdc_stest.h"
#include "mmpa_stub.h"
#include "ide_platform_stub.h"
#include "ide_daemon_hdc.h"
#include "ide_common_util.h"
#include "adx_dsmi.h"
#include "ide_daemon_stub.h"
#include <map>
using std::make_pair;
using std::vector;
using namespace Adx;
using namespace Analysis::Dvvp::Adx;
using DevInfoT = struct IdeDevInfo;
extern struct IdeGlobalCtrlInfo g_ideGlobalInfo;
extern struct IdeComponentsFuncs g_ideComponentsFuncs;
extern int IdeDaemonHdcProcessEventOne(struct IdeSock &clientFd);
extern int IdeDaemonReadReq(const struct IdeTransChannel &handle, IdeTlvReqAddr req);
extern int IdeDaemonHdcProcessEventOne(const struct DevSession &devSession);
extern void IdeDaemonCreateHdcServer(DevInfoT *devInfo);
extern int IdeCreateHdcHandleThread(HDC_SESSION session, const DevInfoT &devInfo);
extern int IdeHdcDistroyDevice(const DevInfoT &devInfo);
extern IdeThreadArg IdeDaemonHdcHandleEvent(IdeThreadArg args);
extern int IdeHdcCheckRunEnv(HDC_SESSION session);
class IDE_HANDLE_STEST: public testing::Test {
protected:
HDC_SESSION session = (HDC_SESSION)0x12345678;
virtual void SetUp() {
g_ideGlobalInfo.mapDevInfo.clear();
}
virtual void TearDown() {
GlobalMockObject::verify();
}
};
TEST_F(IDE_HANDLE_STEST, IdeDaemonReadReq_recv_len_failed)
{
int buf_len = UINT32_MAX;
void *sock_desc = (void *)0x12345678;
struct tlv_req *req = NULL;
MOCKER(IdeRead)
.stubs()
.with(any(), any(), outBoundP(&buf_len, sizeof(int)), any())
.will(returnValue(IDE_DAEMON_ERROR))
.then(returnValue(IDE_DAEMON_OK));
struct IdeTransChannel handle = {IdeChannel::IDE_CHANNEL_SOCK, sock_desc};
EXPECT_EQ(IDE_DAEMON_ERROR, IdeDaemonReadReq(handle, &req));
EXPECT_TRUE(req == NULL);
EXPECT_EQ(IDE_DAEMON_ERROR, IdeDaemonReadReq(handle, &req));
EXPECT_TRUE(req == NULL);
}
TEST_F(IDE_HANDLE_STEST, IdeDaemonReadReq_IdeXmalloc_failed)
{
int buf_len = 4;
char *buf = (char *)IdeXmalloc(buf_len);
void *sock_desc = (void *)0x12345678;
struct tlv_req *req = NULL;
MOCKER(IdeXmalloc)
.stubs()
.will(returnValue((void *)NULL));
MOCKER(IdeRead)
.stubs()
.with(any(), outBoundP((void **)&buf, sizeof(void *)), outBoundP(&buf_len, sizeof(int)), any())
.will(returnValue(IDE_DAEMON_OK));
struct IdeTransChannel handle = {IdeChannel::IDE_CHANNEL_SOCK, sock_desc};
EXPECT_EQ(IDE_DAEMON_ERROR, IdeDaemonReadReq(handle, &req));
EXPECT_TRUE(req == NULL);
}
TEST_F(IDE_HANDLE_STEST, IdeDaemonReadReq_memcpy_s_failed)
{
int buf_len = 4;
char *buf = (char *)IdeXmalloc(buf_len);
void *sock_desc = (void *)0x12345678;
struct tlv_req *req = NULL;
MOCKER(memcpy_s)
.stubs()
.will(returnValue(-1));
MOCKER(IdeRead)
.stubs()
.with(any(), outBoundP((void **)&buf, sizeof(void *)), outBoundP(&buf_len, sizeof(int)), any())
.will(returnValue(IDE_DAEMON_OK));
struct IdeTransChannel handle = {IdeChannel::IDE_CHANNEL_SOCK, sock_desc};
EXPECT_EQ(IDE_DAEMON_ERROR, IdeDaemonReadReq(handle, &req));
}
TEST_F(IDE_HANDLE_STEST, IdeDaemonReadReqLenFailed)
{
int buf_len = 24;
char *buf = (char *)IdeXmalloc(buf_len);
struct tlv_req * ceq = (struct tlv_req *)buf;
ceq->len = buf_len - sizeof(struct tlv_req) - 1;
void *sock_desc = (void *)0x12345678;
struct tlv_req *req = NULL;
MOCKER(IdeRead)
.stubs()
.with(any(), outBoundP((void **)&buf, sizeof(void *)), outBoundP(&buf_len, sizeof(int)), any())
.will(returnValue(IDE_DAEMON_OK));
struct IdeTransChannel handle = {IdeChannel::IDE_CHANNEL_SOCK, sock_desc};
EXPECT_EQ(IDE_DAEMON_ERROR, IdeDaemonReadReq(handle, &req));
}
TEST_F(IDE_HANDLE_STEST, IdeDaemonReadReqSucc)
{
int buf_len = 24;
char *buf = (char *)IdeXmalloc(buf_len);
struct tlv_req * ceq = (struct tlv_req *)buf;
ceq->len = buf_len - sizeof(struct tlv_req);
void *sock_desc = (void *)0x12345678;
struct tlv_req *req = NULL;
MOCKER(IdeRead)
.stubs()
.with(any(), outBoundP((void **)&buf, sizeof(void *)), outBoundP(&buf_len, sizeof(int)), any())
.will(returnValue(IDE_DAEMON_OK));
struct IdeTransChannel handle = {IdeChannel::IDE_CHANNEL_SOCK, sock_desc};
EXPECT_EQ(IDE_DAEMON_OK, IdeDaemonReadReq(handle, &req));
IdeXfree(req);
}
TEST_F(IDE_HANDLE_STEST, IdeDaemonHdcProcessEventOneTest)
{
HDC_SESSION session = (HDC_SESSION)0x12345678;
struct DevSession *devSession = (struct DevSession *)IdeXmalloc(sizeof(struct DevSession));
TlvReqT *req = (TlvReqT *)IdeXmalloc(sizeof(TlvReqT));
devSession->session = session;
req->type = IDE_INVALID_REQ;
req->dev_id = 0;
g_ideComponentsFuncs.hdcProcess[IDE_COMPONENT_CMD] = ide_daemon_cmd_process_stub;
MOCKER(IdeDaemonReadReq)
.stubs()
.with(any(), outBoundP(&req, sizeof(struct tlv_req *)), any())
.will(returnValue(IDE_DAEMON_ERROR))
.then(returnValue(IDE_DAEMON_OK));
MOCKER(IdeGetComponentType)
.stubs()
.will(returnValue(IDE_COMPONENT_CMD))
.then(returnValue(NR_IDE_COMPONENTS));
MOCKER(ide_daemon_cmd_process_stub)
.stubs()
.will(returnValue(IDE_DAEMON_ERROR))
.then(returnValue(IDE_DAEMON_OK));
MOCKER(IdeReqFree)
.stubs();
EXPECT_EQ(IDE_DAEMON_ERROR, IdeDaemonHdcProcessEventOne(*devSession));
EXPECT_EQ(IDE_DAEMON_ERROR, IdeDaemonHdcProcessEventOne(*devSession));
EXPECT_EQ(nullptr, IdeDaemonHdcProcessEvent(devSession));
IdeXfree(req);
}
int32_t g_drvHdcServ = 0;
hdcError_t drvHdcServerCreateStub(int devid, int serviceType, HDC_SERVER *pServer)
{
*pServer = (HDC_SERVER)0x12345678;
g_drvHdcServ++;
if (g_drvHdcServ == 1) {
return DRV_ERROR_DEVICE_NOT_READY;
}
if (g_drvHdcServ == 2) {
return (hdcError_t)(DRV_ERROR_NONE + 1);
}
return DRV_ERROR_NONE;
}
TEST_F(IDE_HANDLE_STEST, IdeDaemonCreateHdcServerTest)
{
struct IdeDevInfo devInfo;
devInfo.phyDevId = 1;
devInfo.serviceType = (drvHdcServiceType)0x1;
g_ideGlobalInfo.hdcHandleEventFlag = true;
MOCKER(IdeGetLogIdByPhyId)
.stubs()
.will(returnValue(IDE_DAEMON_ERROR))
.then(returnValue(IDE_DAEMON_OK));
MOCKER(drvHdcServerCreate)
.stubs()
.will(invoke(drvHdcServerCreateStub));
IdeDaemonCreateHdcServer(&devInfo);
EXPECT_EQ(devInfo.server, (HDC_SERVER)0x12345678);
}
TEST_F(IDE_HANDLE_STEST, IdeCreateHdcHandleThread)
{
HDC_SESSION session = (HDC_SESSION)0x12345678;
struct DevSession devSession;
struct IdeDevInfo devInfo;
uintptr_t server_id = 0x12345678;
HDC_SERVER server = (HDC_SERVER)server_id;
devInfo.phyDevId = 1;
devInfo.server = server;
devInfo.serviceType = (drvHdcServiceType)0x1;
g_ideGlobalInfo.hdcHandleEventFlag = true;
MOCKER(IdeXmalloc)
.stubs()
.will(returnValue((void*)NULL))
.then(returnValue((void*)&devSession));
MOCKER(mmCreateTaskWithThreadAttr)
.stubs()
.will(returnValue(EN_ERROR))
.then(returnValue(EN_OK));
MOCKER(IdeXfree)
.stubs();
EXPECT_EQ(IDE_DAEMON_ERROR, IdeCreateHdcHandleThread(session, devInfo));
EXPECT_EQ(IDE_DAEMON_ERROR, IdeCreateHdcHandleThread(session, devInfo));
EXPECT_EQ(IDE_DAEMON_OK, IdeCreateHdcHandleThread(session, devInfo));
}
TEST_F(IDE_HANDLE_STEST, IdeHdcDistroyDeviceTest)
{
DevInfoT devInfo = {0};
uint32_t phyDevId = 1;
uint32_t devCount = 0;
g_ideGlobalInfo.hdcClient = (HDC_CLIENT)1;
devInfo.phyDevId = phyDevId;
devInfo.server = nullptr;
devInfo.createHdc = false;
devInfo.devDisable = true;
devInfo.serviceType = HDC_SERVICE_TYPE_IDE2;
g_ideGlobalInfo.mapDevInfo.insert(std::pair<int, DevInfoT>(phyDevId, devInfo));
phyDevId += 1;
devInfo.phyDevId = phyDevId;
g_ideGlobalInfo.mapDevInfo.insert(std::pair<int, DevInfoT>(phyDevId, devInfo));
EXPECT_EQ(IDE_DAEMON_ERROR, IdeHdcDistroyDevice(devInfo));
devInfo.devDisable = false;
EXPECT_EQ(IDE_DAEMON_OK, IdeHdcDistroyDevice(devInfo));
}
TEST_F(IDE_HANDLE_STEST, IdeDaemonHdcHandleEventTest)
{
HDC_SESSION session = (HDC_SESSION)0x12345;
DevInfoT devInfo = {0};
uint32_t phyDevId = 1;
uint32_t devCount = 0;
uintptr_t server_id = 0x12345678;
g_ideGlobalInfo.hdcClient = (HDC_CLIENT)1;
devInfo.phyDevId = phyDevId;
devInfo.server = (HDC_SERVER)server_id;
devInfo.createHdc = false;
devInfo.devDisable = true;
devInfo.serviceType = HDC_SERVICE_TYPE_IDE2;
MOCKER(IdeDaemonCreateHdcServer)
.stubs();
MOCKER(drvHdcSessionAccept)
.stubs()
.with(any(), outBoundP(&session))
.will(returnValue(DRV_ERROR_DEVICE_NOT_READY))
.then(returnValue(DRV_ERROR_DEVICE_NOT_READY))
.then(returnValue(DRV_ERROR_NONE));
MOCKER(mmGetErrorCode)
.stubs()
.will(returnValue(EINTR))
.then(returnValue(EINTR+1));
MOCKER(drvHdcServerDestroy)
.stubs()
.will(returnValue(DRV_ERROR_DEVICE_NOT_READY))
.then(returnValue(DRV_ERROR_NONE));
MOCKER(IdeHdcDistroyDevice)
.stubs()
.will(returnValue(IDE_DAEMON_ERROR))
.then(returnValue(IDE_DAEMON_OK));
MOCKER(drvHdcSetSessionReference)
.stubs()
.will(returnValue(DRV_ERROR_DEVICE_NOT_READY))
.then(returnValue(DRV_ERROR_NONE));
MOCKER(IdeHdcCheckRunEnv)
.stubs()
.will(returnValue(IDE_DAEMON_OK));
MOCKER(IdeCreateHdcHandleThread)
.stubs()
.will(returnValue(IDE_DAEMON_ERROR))
.then(returnValue(IDE_DAEMON_OK));
MOCKER(HdcSessionClose)
.stubs()
.will(returnValue(IDE_DAEMON_OK));
EXPECT_EQ(nullptr, IdeDaemonHdcHandleEvent(IdeThreadArg(&devInfo)));
EXPECT_EQ(nullptr, IdeDaemonHdcHandleEvent(IdeThreadArg(&devInfo)));
}