* 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 <sys/wait.h>
#include <sys/time.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>
#include <sys/stat.h>
#include <string>
#include <fstream>
#include <iostream>
#include <sstream>
#include "utils/utils.h"
#include "collection_entry.h"
#include "collect_engine.h"
#include "ai_drv_dev_api.h"
#include "ai_drv_prof_api.h"
#include "app/application.h"
#include "prof_timer.h"
#include "uploader_mgr.h"
#include "param_validation.h"
#include "config_manager.h"
#include "prof_channel_manager.h"
using namespace analysis::dvvp::common::error;
using namespace analysis::dvvp::driver;
using namespace analysis::dvvp::message;
using namespace Analysis::Dvvp::JobWrapper;
class DEVICE_COLLECTION_ENGINE_TEST: public testing::Test {
protected:
virtual void SetUp() {
HDC_SESSION session = (HDC_SESSION)0x12345678;
_transport = std::shared_ptr<analysis::dvvp::transport::HDCTransport>(
new analysis::dvvp::transport::HDCTransport(session));
}
virtual void TearDown() {
_transport.reset();
}
public:
std::shared_ptr<analysis::dvvp::transport::HDCTransport> _transport;
};
TEST_F(DEVICE_COLLECTION_ENGINE_TEST, CollectEngine_destructor) {
GlobalMockObject::verify();
std::shared_ptr<analysis::dvvp::device::CollectEngine> engine(
new analysis::dvvp::device::CollectEngine());
EXPECT_EQ(PROFILING_SUCCESS, engine->Init());
EXPECT_EQ(PROFILING_SUCCESS, engine->Uinit());
engine.reset();
}
TEST_F(DEVICE_COLLECTION_ENGINE_TEST, Init) {
GlobalMockObject::verify();
std::shared_ptr<analysis::dvvp::device::CollectEngine> engine(
new analysis::dvvp::device::CollectEngine());
EXPECT_EQ(PROFILING_SUCCESS, engine->Init());
}
TEST_F(DEVICE_COLLECTION_ENGINE_TEST, SetDevIdOnHost) {
GlobalMockObject::verify();
std::shared_ptr<analysis::dvvp::device::CollectEngine> engine(
new analysis::dvvp::device::CollectEngine());
EXPECT_EQ(PROFILING_SUCCESS, engine->Init());
engine->collectionJobCommCfg_ =
std::shared_ptr<Analysis::Dvvp::JobWrapper::CollectionJobCommonParams>(
new Analysis::Dvvp::JobWrapper::CollectionJobCommonParams());
engine->SetDevIdOnHost(0);
EXPECT_EQ(PROFILING_SUCCESS, engine->Uinit());
}
TEST_F(DEVICE_COLLECTION_ENGINE_TEST, Uinit) {
GlobalMockObject::verify();
std::shared_ptr<analysis::dvvp::device::CollectEngine> engine(
new analysis::dvvp::device::CollectEngine());
MOCKER_CPP(&analysis::dvvp::device::CollectEngine::CollectStop)
.stubs()
.will(returnValue(PROFILING_FAILED))
.then(returnValue(PROFILING_SUCCESS));
engine->isInited_ = true;
engine->_is_started = true;
EXPECT_EQ(PROFILING_FAILED, engine->Uinit());
EXPECT_EQ(PROFILING_SUCCESS, engine->Uinit());
}
static int _drv_get_dev_ids(int num_devices, std::vector<int> & dev_ids) {
static int phase = 0;
if (phase == 0) {
phase++;
return PROFILING_FAILED;
}
if (phase >= 1) {
dev_ids.push_back(0);
return PROFILING_SUCCESS;
}
}
TEST_F(DEVICE_COLLECTION_ENGINE_TEST, CollectStart) {
GlobalMockObject::verify();
std::shared_ptr<analysis::dvvp::device::CollectEngine> engine(
new analysis::dvvp::device::CollectEngine());
std::string sampleConfig;
analysis::dvvp::message::StatusInfo status;
engine->Init(0);
engine->isInited_ = true;
engine->tmpResultDir_ = "./tmp/to/project_dir";
engine->collectionJobCommCfg_->params = std::shared_ptr<analysis::dvvp::message::ProfileParams>(
new analysis::dvvp::message::ProfileParams());
MOCKER_CPP(&analysis::dvvp::device::CollectEngine::InitBeforeCollectStart)
.stubs()
.will(returnValue(PROFILING_SUCCESS));
EXPECT_EQ(PROFILING_SUCCESS, engine->CollectStart(sampleConfig, status));
}
TEST_F(DEVICE_COLLECTION_ENGINE_TEST, CollectStop) {
GlobalMockObject::verify();
std::shared_ptr<analysis::dvvp::device::CollectEngine> engine(
new analysis::dvvp::device::CollectEngine());
analysis::dvvp::message::StatusInfo status;
EXPECT_EQ(PROFILING_FAILED, engine->CollectStop(status));
engine->Init(0);
engine->_is_started = true;
engine->tmpResultDir_ = "./tmp/to/project_dir";
engine->collectionJobCommCfg_->params = std::shared_ptr<analysis::dvvp::message::ProfileParams>(
new analysis::dvvp::message::ProfileParams());
MOCKER_CPP(&analysis::dvvp::device::CollectEngine::CollectStopReplay)
.stubs()
.will(returnValue(PROFILING_FAILED))
.then(returnValue(PROFILING_SUCCESS));
MOCKER(analysis::dvvp::common::utils::Utils::RemoveDir)
.stubs()
.will(returnValue(PROFILING_SUCCESS));
MOCKER_CPP(&analysis::dvvp::device::CollectionEntry::FinishCollection)
.stubs()
.will(returnValue(PROFILING_FAILED))
.then(returnValue(PROFILING_SUCCESS));
EXPECT_EQ(PROFILING_FAILED, engine->CollectStop(status));
engine->_is_started = true;
engine->tmpResultDir_ = "./tmp/to/project_dir";
EXPECT_EQ(PROFILING_SUCCESS, engine->CollectStop(status));
}
TEST_F(DEVICE_COLLECTION_ENGINE_TEST, CollectStartReplay) {
GlobalMockObject::verify();
std::shared_ptr<analysis::dvvp::device::CollectEngine> engine(
new analysis::dvvp::device::CollectEngine());
engine->Init(1);
auto ctrl_cpu_event = std::make_shared<std::vector<std::string>>();
auto ts_cpu_event = std::make_shared<std::vector<std::string>>();
auto ai_core_event = std::make_shared<std::vector<std::string>>();
auto ai_core_event_cores = std::make_shared<std::vector<int>>();
auto aiv_event = std::make_shared<std::vector<std::string>>();
auto aiv_event_cores = std::make_shared<std::vector<int>>();
analysis::dvvp::message::StatusInfo status;
auto llc_event = std::make_shared<std::vector<std::string>>();
auto ddr_event = std::make_shared<std::vector<std::string>>();
ctrl_cpu_event->push_back("0x11");
ts_cpu_event->push_back("0x11");
ai_core_event->push_back("0x11");
ai_core_event_cores->push_back(1);
aiv_event->push_back("0x11");
aiv_event_cores->push_back(1);
llc_event->push_back("e1,e2");
ddr_event->push_back("read");
ddr_event->push_back("write");
ddr_event->push_back("master_id");
std::shared_ptr<analysis::dvvp::message::ProfileParams> params(
new analysis::dvvp::message::ProfileParams);
params->ai_core_profiling = "on";
params->ai_core_profiling_mode = "sample-based";
engine->collectionJobCommCfg_->params = params;
engine->collectionJobCommCfg_->params->dvpp_profiling = "on";
engine->collectionJobCommCfg_->params->nicProfiling = "on";
engine->collectionJobCommCfg_->params->llc_interval = 100;
engine->collectionJobCommCfg_->params->ddr_interval = 100;
engine->collectionJobCommCfg_->params->hbmProfiling = "on";
engine->collectionJobCommCfg_->params->hbm_profiling_events = "read,write";
MOCKER(analysis::dvvp::common::utils::Utils::ExecCmd)
.stubs()
.will(returnValue(PROFILING_SUCCESS));
MOCKER(mmCreateTaskWithThreadAttr)
.stubs()
.will(returnValue(EN_OK));
engine->_is_started = false;
EXPECT_EQ(PROFILING_FAILED, engine->CollectStartReplay(
ctrl_cpu_event,
status,
llc_event));
engine->_is_started = true;
EXPECT_EQ(PROFILING_FAILED, engine->CollectStartReplay(
ctrl_cpu_event,
status,
llc_event));
}
TEST_F(DEVICE_COLLECTION_ENGINE_TEST, CollectStopReplay) {
GlobalMockObject::verify();
std::shared_ptr<analysis::dvvp::device::CollectEngine> engine(
new analysis::dvvp::device::CollectEngine());
auto ctrl_cpu_event = std::make_shared<std::vector<std::string>>();
auto ts_cpu_event = std::make_shared<std::vector<std::string>>();
auto ai_cpu_event = std::make_shared<std::vector<std::string>>();
auto ai_core_event = std::make_shared<std::vector<std::string>>();
auto ai_core_event_cores = std::make_shared<std::vector<int>>();
analysis::dvvp::message::StatusInfo status;
ctrl_cpu_event->push_back("0x11");
ts_cpu_event->push_back("0x11");
ai_cpu_event->push_back("0x11");
ai_core_event->push_back("0x11");
ai_core_event_cores->push_back(1);
engine->collectionJobCommCfg_ =
std::shared_ptr<Analysis::Dvvp::JobWrapper::CollectionJobCommonParams>(
new Analysis::Dvvp::JobWrapper::CollectionJobCommonParams());
engine->collectionJobCommCfg_->devId = 0;
engine->CreateCollectionJobArray();
std::shared_ptr<analysis::dvvp::message::ProfileParams> params(
new analysis::dvvp::message::ProfileParams);
engine->collectionJobCommCfg_->params = params;
engine->collectionJobCommCfg_->params->dvpp_profiling = "on";
engine->collectionJobCommCfg_->params->nicProfiling = "on";
MOCKER(analysis::dvvp::common::utils::Utils::ExecCmd)
.stubs()
.will(returnValue(PROFILING_SUCCESS));
engine->_is_started = false;
EXPECT_EQ(PROFILING_FAILED, engine->CollectStopReplay(status));
engine->_is_started = true;
EXPECT_EQ(PROFILING_SUCCESS, engine->CollectStopReplay(status));
EXPECT_EQ(analysis::dvvp::message::SUCCESS, status.status);
EXPECT_EQ(PROFILING_SUCCESS, engine->CollectStopReplay(status));
EXPECT_EQ(analysis::dvvp::message::SUCCESS, status.status);
engine->_is_started = true;
engine->tmpResultDir_ = "./tmp_result_dir";
MOCKER(mmJoinTask)
.stubs()
.will(returnValue(EN_OK));
EXPECT_EQ(PROFILING_SUCCESS, engine->CollectStopReplay(status));
EXPECT_EQ(analysis::dvvp::message::SUCCESS, status.status);
engine->_is_started = true;
engine->tmpResultDir_ = "./tmp_result_dir";
analysis::dvvp::common::utils::Utils::CreateDir(engine->tmpResultDir_ + "/data");
EXPECT_EQ(PROFILING_SUCCESS, engine->CollectStopReplay(status));
EXPECT_EQ(analysis::dvvp::message::SUCCESS, status.status);
analysis::dvvp::common::utils::Utils::RemoveDir(engine->tmpResultDir_);
}
void fake_get_files(const std::string & dir, bool is_recur, std::vector<std::string>& files) {
std::string ctrl_cpu_data_path = "./path/to/ctrl_cpu_data_path";
files.push_back(ctrl_cpu_data_path + ".1");
files.push_back(ctrl_cpu_data_path + ".2");
files.push_back("./not_data");
}
int DrvGetDevIds(int num_devices, std::vector<int> & dev_ids) {
dev_ids.push_back(0);
return PROFILING_SUCCESS;
}
TEST_F(DEVICE_COLLECTION_ENGINE_TEST, CreateTmpDir) {
GlobalMockObject::verify();
std::shared_ptr<analysis::dvvp::device::CollectEngine> engine(
new analysis::dvvp::device::CollectEngine());
engine->collectionJobCommCfg_ =
std::shared_ptr<Analysis::Dvvp::JobWrapper::CollectionJobCommonParams>(
new Analysis::Dvvp::JobWrapper::CollectionJobCommonParams());
auto app_dirs = std::make_shared<std::vector<std::string>>();
app_dirs->push_back("./tmp/path/to/app");
app_dirs->push_back("./tmp/path/to/app/conf");
app_dirs->push_back("./tmp/path/to/app/bin");
app_dirs->push_back("./tmp/path/to/app/conf/1.conf");
std::shared_ptr<analysis::dvvp::message::ProfileParams> params(
new analysis::dvvp::message::ProfileParams);
engine->collectionJobCommCfg_->params = params;
engine->collectionJobCommCfg_->params->job_id = "123";
std::string tmp;
MOCKER(&analysis::dvvp::common::utils::Utils::CreateDir)
.stubs()
.will(returnValue(PROFILING_FAILED))
.then(returnValue(PROFILING_FAILED))
.then(returnValue(PROFILING_SUCCESS));
const std::string path = "/tmp/PROFILER_UT/";
EXPECT_EQ(PROFILING_FAILED, engine->CreateTmpDir(tmp));
EXPECT_EQ(PROFILING_FAILED, engine->CreateTmpDir(tmp));
EXPECT_EQ(PROFILING_SUCCESS, engine->CreateTmpDir(tmp));
}
TEST_F(DEVICE_COLLECTION_ENGINE_TEST, CleanupResults) {
GlobalMockObject::verify();
std::shared_ptr<analysis::dvvp::device::CollectEngine> engine(
new analysis::dvvp::device::CollectEngine());
engine->collectionJobCommCfg_ =
std::shared_ptr<Analysis::Dvvp::JobWrapper::CollectionJobCommonParams>(
new Analysis::Dvvp::JobWrapper::CollectionJobCommonParams());
std::shared_ptr<analysis::dvvp::message::ProfileParams> params(
new analysis::dvvp::message::ProfileParams);
engine->collectionJobCommCfg_->params = params;
engine->collectionJobCommCfg_->params->job_id = "123";
EXPECT_EQ(PROFILING_SUCCESS, engine->CleanupResults());
engine->tmpResultDir_ = "./tmp/folder";
EXPECT_EQ(PROFILING_SUCCESS, engine->CleanupResults());
auto app_dirs = std::make_shared<std::vector<std::string>>();
app_dirs->push_back("./tmp/path/to/app");
app_dirs->push_back("./tmp/path/to/app/conf");
app_dirs->push_back("./tmp/path/to/app/bin");
app_dirs->push_back("./tmp/path/to/app/conf/1.conf");
MOCKER(&analysis::dvvp::common::utils::Utils::RemoveDir)
.stubs()
.will(returnValue(PROFILING_SUCCESS));
engine->tmpResultDir_ = "./tmp/folder";
EXPECT_EQ(PROFILING_SUCCESS, engine->CleanupResults());
}
TEST_F(DEVICE_COLLECTION_ENGINE_TEST, BindFileWithChannel) {
GlobalMockObject::verify();
std::shared_ptr<analysis::dvvp::device::CollectEngine> engine(
new analysis::dvvp::device::CollectEngine());
std::string org_file = "1.data";
EXPECT_STREQ("1.data.1", engine->BindFileWithChannel(org_file, 1).c_str());
}
TEST_F(DEVICE_COLLECTION_ENGINE_TEST, CreateCollectionJobArray) {
GlobalMockObject::verify();
std::shared_ptr<analysis::dvvp::device::CollectEngine> engine(
new analysis::dvvp::device::CollectEngine());
EXPECT_NE(nullptr, engine);
engine->CreateCollectionJobArray();
}
TEST_F(DEVICE_COLLECTION_ENGINE_TEST, CheckPmuEventIsValid) {
GlobalMockObject::verify();
std::shared_ptr<analysis::dvvp::device::CollectEngine> engine(
new analysis::dvvp::device::CollectEngine());
EXPECT_NE(nullptr, engine);
auto ctrl_cpu_event = std::make_shared<std::vector<std::string>>();
auto llc_event = std::make_shared<std::vector<std::string>>();
ctrl_cpu_event->push_back("0x11");
llc_event->push_back("e1,e2");
MOCKER_CPP(&analysis::dvvp::common::validation::ParamValidation::CheckCtrlCpuEventIsValid)
.stubs()
.will(returnValue(false))
.then(returnValue(true));
MOCKER_CPP(&analysis::dvvp::common::validation::ParamValidation::CheckLlcEventsIsValid)
.stubs()
.will(returnValue(false))
.then(returnValue(true));
EXPECT_EQ(PROFILING_FAILED, engine->CheckPmuEventIsValid(ctrl_cpu_event, llc_event));
EXPECT_EQ(PROFILING_FAILED, engine->CheckPmuEventIsValid(ctrl_cpu_event, llc_event));
EXPECT_EQ(PROFILING_SUCCESS, engine->CheckPmuEventIsValid(ctrl_cpu_event, llc_event));
}