* This file is part of the MindStudio project.
* Copyright (c) 2025 Huawei Technologies Co.,Ltd.
*
* MindStudio is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* 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 FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* ------------------------------------------------------------------------- */
#include <sstream>
#include <dlfcn.h>
#include <gtest/gtest.h>
#define private public
#include "core/BinaryInstrumentation.h"
#undef private
#include "utils/PipeCall.h"
#include "mockcpp/mockcpp.hpp"
#include "utils/FileSystem.h"
using namespace std;
TEST(BBCountDBI, covert_kernel_expect_success)
{
MOCKER(PipeCall).stubs().will(returnValue(true));
MOCKER(chmod).stubs().will(returnValue(0));
BBCountDBI bbcount;
bool ret = bbcount.Convert("", "");
bool needExtraSpace = bbcount.NeedExtraSpace();
bool exArgs = bbcount.ExpandArgs("");
EXPECT_TRUE(ret);
EXPECT_TRUE(needExtraSpace);
EXPECT_TRUE(exArgs);
GlobalMockObject::verify();
}
TEST(BBCountDBI, covert_kernel_expect_false)
{
MOCKER(PipeCall).stubs().will(returnValue(false));
BBCountDBI bbcount;
bool ret = bbcount.Convert("", "", "1");
bool needExtraSpace = bbcount.NeedExtraSpace();
bool exArgs = bbcount.ExpandArgs("");
EXPECT_FALSE(ret);
GlobalMockObject::verify();
}
TEST(PGODBI, covert_kernel_expect_success)
{
MOCKER(PipeCall).stubs().will(returnValue(true));
MOCKER(chmod).stubs().will(returnValue(0));
PGODBI pgo;
bool ret = pgo.Convert("", "");
bool needExtraSpace = pgo.NeedExtraSpace();
bool exArgs = pgo.ExpandArgs("");
EXPECT_TRUE(ret);
EXPECT_FALSE(needExtraSpace);
EXPECT_TRUE(exArgs);
GlobalMockObject::verify();
}
TEST(PGODBI, covert_kernel_expect_false)
{
MOCKER(PipeCall).stubs().will(returnValue(false));
PGODBI pgo;
bool ret = pgo.Convert("", "", "1");
bool needExtraSpace = pgo.NeedExtraSpace();
bool exArgs = pgo.ExpandArgs("");
EXPECT_FALSE(ret);
GlobalMockObject::verify();
}
TEST(CustomDBI, input_invalid_lib_path_then_set_plugin_path_convert_expect_fail)
{
MOCKER(PipeCall).stubs().will(returnValue(true));
CustomDBI dbi;
BinaryInstrumentation::Config config{};
bool ret = dbi.SetConfig(config);
EXPECT_FALSE(ret);
GlobalMockObject::verify();
}
TEST(CustomDBI, input_invalid_lib_path_then_set_plugin_path_convert_expect_True)
{
MOCKER(PipeCall).stubs().will(returnValue(false));
CustomDBI dbi;
BinaryInstrumentation::Config config{};
bool ret = dbi.SetConfig(config);
EXPECT_FALSE(ret);
GlobalMockObject::verify();
}
void BitMockFunc(const char *output, uint16_t length)
{
return;
}
void StubInitFunc(const char *, uint16_t, const char *) {}
TEST(CustomDBI, input_valid_lib_path_then_set_plugin_path_expect_success)
{
{
MOCKER(PipeCall).stubs().will(returnValue(true));
string handle = "handle";
void *res = &handle;
MOCKER(&dlopen).stubs().will(returnValue(res));
MOCKER(&dlclose).stubs().will(returnValue(int(0)));
MOCKER(&dlsym).stubs().will(returnValue(res));
CustomDBI dbi;
BinaryInstrumentation::Config config{"./libmem_trace.so", "dav-c220"};
bool ret = dbi.SetConfig(config);
EXPECT_TRUE(ret);
remove(config.pluginPath.c_str());
}
GlobalMockObject::verify();
}
TEST(CustomDBI, input_valid_lib_path_then_convert_expect_success)
{
{
MOCKER(PipeCall).stubs().will(returnValue(true));
MOCKER(chmod).stubs().will(returnValue(0));
string handle = "handle";
void *res = &handle;
MOCKER(&dlopen).stubs().will(returnValue(res));
MOCKER(&dlsym).stubs().will(returnValue((void *)BitMockFunc));
MOCKER(&dlclose).stubs().will(returnValue(int(0)));
MOCKER(&CustomDBI::GenerateOrderingFile).stubs().will(returnValue(true));
CustomDBI dbi;
BinaryInstrumentation::Config config{"./libmem_trace.so", ".ascend910B"};
bool ret = dbi.SetConfig(config);
ret = dbi.Convert("new_kernel.o", "old_kernel.o");
EXPECT_TRUE(ret);
remove(config.pluginPath.c_str());
}
GlobalMockObject::verify();
}
TEST(CustomDBI, input_valid_lib_path_then_convert_expect_fail)
{
{
MOCKER(PipeCall).stubs().will(returnValue(true));
MOCKER(chmod).stubs().will(returnValue(0));
string handle = "handle";
void *res = &handle;
MOCKER(&dlopen).stubs().will(returnValue(res));
MOCKER(&dlsym).stubs().will(returnValue((void *)BitMockFunc));
MOCKER(&dlclose).stubs().will(returnValue(int(0)));
MOCKER(&CustomDBI::GenerateOrderingFile).stubs().will(returnValue(true));
CustomDBI dbi;
BinaryInstrumentation::Config config{"./libmem_trace.so", ".ascend910B"};
bool ret = dbi.SetConfig(config);
ret = dbi.Convert("new_kernel.o", "old_kernel.o", "1");
EXPECT_TRUE(ret);
remove(config.pluginPath.c_str());
}
GlobalMockObject::verify();
}
TEST(CustomDBI, kernel_binary_objdump_failed_expect_generate_ordering_file_return_false)
{
MOCKER(PipeCall).stubs().will(returnValue(false));
CustomDBI dbi;
bool ret = dbi.GenerateOrderingFile("kernel.o", "probe.o", "ordering.txt");
EXPECT_FALSE(ret);
GlobalMockObject::verify();
}
bool PipeCallStubForInvalidKernelObjdump(std::vector<std::string> const &cmd, std::string &output)
{
output = "0000000000000000\tg\tF\t.unknown\t0000000000000000\tkernel";
return true;
}
TEST(CustomDBI, kernel_parse_first_symbol_failed_expect_generate_ordering_file_return_false)
{
MOCKER(PipeCall).stubs().will(invoke(PipeCallStubForInvalidKernelObjdump));
CustomDBI dbi;
bool ret = dbi.GenerateOrderingFile("kernel.o", "probe.o", "ordering.txt");
EXPECT_FALSE(ret);
GlobalMockObject::verify();
}
bool PipeCallStubForProbeObjdumpFailed(std::vector<std::string> const &cmd, std::string &output)
{
constexpr size_t fileNameIdx = 2;
if (cmd[fileNameIdx] == "kernel.o") {
output = "0000000000000000\tg\tF\t.text\t0000000000000000\tkernel";
return true;
}
return false;
}
TEST(CustomDBI, probe_binary_objdump_failed_expect_generate_ordering_file_return_false)
{
MOCKER(PipeCall).stubs().will(invoke(PipeCallStubForProbeObjdumpFailed));
CustomDBI dbi;
bool ret = dbi.GenerateOrderingFile("kernel.o", "probe.o", "ordering.txt");
EXPECT_FALSE(ret);
GlobalMockObject::verify();
}
bool PipeCallStubForInvalidProbeObjdump(std::vector<std::string> const &cmd, std::string &output)
{
constexpr size_t fileNameIdx = 2;
if (cmd[fileNameIdx] == "kernel.o") {
output = "0000000000000000\tg\tF\t.text\t0000000000000000\tkernel";
} else {
output = "0000000000000000\tw\tF\t.unknown\t0000000000000000\tprobe";
}
return true;
}
TEST(CustomDBI, probe_parse_first_symbol_failed_expect_generate_ordering_file_return_false)
{
MOCKER(PipeCall).stubs().will(invoke(PipeCallStubForInvalidProbeObjdump));
CustomDBI dbi;
bool ret = dbi.GenerateOrderingFile("kernel.o", "probe.o", "ordering.txt");
EXPECT_FALSE(ret);
GlobalMockObject::verify();
}
bool PipeCallStubForGetValidObjdumpResult(std::vector<std::string> const &cmd, std::string &output)
{
constexpr size_t fileNameIdx = 2;
if (cmd[fileNameIdx] == "kernel.o") {
output = "0000000000000000\tg\tF\t.text\t0000000000000000\tkernel";
} else {
output = "0000000000000000\tw\tF\t.text\t0000000000000000\tprobe";
}
return true;
}
TEST(CustomDBI, kernel_and_probe_parse_symbol_success_expect_generate_ordering_file_return_true)
{
MOCKER(PipeCall).stubs().will(invoke(PipeCallStubForGetValidObjdumpResult));
CustomDBI dbi;
bool ret = dbi.GenerateOrderingFile("kernel.o", "probe.o", "ordering.txt");
EXPECT_TRUE(ret);
GlobalMockObject::verify();
}
TEST(CustomDBI, GenerateKernelWithProbe_expect_return_false)
{
MOCKER(PipeCall).stubs().will(returnValue(false));
CustomDBI dbi;
EXPECT_FALSE(dbi.GenerateKernelWithProbe("", "", "", ""));
GlobalMockObject::verify();
}
TEST(CustomDBI, GenerateTempProbe_expect_return_false)
{
MOCKER(PipeCall).stubs().will(returnValue(false));
CustomDBI dbi;
EXPECT_FALSE(dbi.GenerateTempProbe("/probe"));
GlobalMockObject::verify();
}
TEST(CustomDBI, write_order_file_failed_return_false)
{
MOCKER(PipeCall).stubs().will(invoke(PipeCallStubForGetValidObjdumpResult));
CustomDBI dbi;
bool ret = dbi.GenerateOrderingFile("kernel.o", "probe.o", "1!@#$/\\{}/");
EXPECT_FALSE(ret);
GlobalMockObject::verify();
}
TEST(CustomDBI, dl_interface_failed_set_config_return_false)
{
MOCKER(dlopen).stubs().will(returnValue((void*)nullptr)).then(returnValue((void*)0x1));
MOCKER(dlsym).stubs().will(returnValue((void*)nullptr));
MOCKER(dlclose).stubs().will(returnValue(0));
{
CustomDBI dbi;
BinaryInstrumentation::Config config{"plugin", "arch", "tmp_dir"};
EXPECT_FALSE(dbi.SetConfig(config));
EXPECT_FALSE(dbi.SetConfig(config));
}
GlobalMockObject::verify();
}
TEST(CustomDBI, convert_call_llvm_objcopy_failed_return_false)
{
MOCKER(PipeCall)
.stubs()
.will(returnValue(false));
CustomDBI dbi;
dbi.initFunc_ = (CustomDBI::PluginInitFunc)0x1;
BinaryInstrumentation::Config config;
config.archName = "arch";
dbi.SetConfig(config);
EXPECT_FALSE(dbi.Convert("newKernelFile", "oldKernelFile", "tilingKey"));
GlobalMockObject::verify();
}
TEST(CustomDBI, convert_generate_ordering_file_failed_return_false)
{
MOCKER(PipeCall)
.stubs()
.will(returnValue(true));
MOCKER(&CustomDBI::GenerateOrderingFile)
.stubs()
.will(returnValue(false));
CustomDBI dbi;
dbi.initFunc_ = (CustomDBI::PluginInitFunc)0x1;
BinaryInstrumentation::Config config;
config.archName = "arch";
dbi.SetConfig(config);
EXPECT_FALSE(dbi.Convert("newKernelFile", "oldKernelFile", "tilingKey"));
GlobalMockObject::verify();
}
TEST(CustomDBI, convert_ld_failed_return_false)
{
MOCKER(PipeCall)
.stubs()
.will(returnValue(true))
.then(returnValue(false));
MOCKER(&CustomDBI::GenerateOrderingFile)
.stubs()
.will(returnValue(false));
CustomDBI dbi;
dbi.initFunc_ = (CustomDBI::PluginInitFunc)0x1;
BinaryInstrumentation::Config config;
config.archName = "arch";
dbi.SetConfig(config);
EXPECT_FALSE(dbi.Convert("newKernelFile", "oldKernelFile", "tilingKey"));
GlobalMockObject::verify();
}
TEST(CustomDBI, convert_bisheng_tune_failed_return_false)
{
MOCKER(PipeCall)
.stubs()
.will(returnValue(true))
.then(returnValue(true))
.then(returnValue(false));
MOCKER(&CustomDBI::GenerateOrderingFile)
.stubs()
.will(returnValue(false));
CustomDBI dbi;
dbi.initFunc_ = (CustomDBI::PluginInitFunc)0x1;
BinaryInstrumentation::Config config;
config.archName = "arch";
dbi.SetConfig(config);
EXPECT_FALSE(dbi.Convert("newKernelFile", "oldKernelFile", "tilingKey"));
GlobalMockObject::verify();
}
TEST(DBIFactory, create_not_nullptr)
{
EXPECT_NE(DBIFactory::Instance().Create(BIType::CUSTOMIZE), nullptr);
EXPECT_NE(DBIFactory::Instance().Create(BIType::BB_COUNT), nullptr);
EXPECT_NE(DBIFactory::Instance().Create(BIType::PGO), nullptr);
}
TEST(DBIFactory, create_nullptr)
{
EXPECT_EQ(DBIFactory::Instance().Create(BIType::MAX), nullptr);
}
/* | 用例集 | BinaryInstrumentationTest
/* |测试函数| CustomDBI::Convert()
/* | 用例名 | convert_with_tune_log_path_write_log_on_failure
/* |用例描述| 执行测试函数,PipeCall失败时写入tune日志
*/
TEST(CustomDBI, convert_with_tune_log_path_write_log_on_failure)
{
MOCKER(&CustomDBI::GenerateOrderingFile).stubs().will(returnValue(true));
MOCKER(&CustomDBI::GenerateTempProbe).stubs().will(returnValue(true));
MOCKER(&CustomDBI::GenerateKernelWithProbe).stubs().will(returnValue(true));
MOCKER(chmod).stubs().will(returnValue(0));
MOCKER(PipeCall).stubs().will(returnValue(false));
MOCKER(&WriteStringToFile).expects(exactly(1)).will(returnValue(true));
CustomDBI dbi;
dbi.initFunc_ = StubInitFunc;
BinaryInstrumentation::Config config;
config.archName = "arch";
config.tuneLogPath = "./tune.log";
dbi.SetConfig(config);
EXPECT_FALSE(dbi.Convert("newKernelFile", "oldKernelFile", "tilingKey"));
GlobalMockObject::verify();
}
/* | 用例集 | BinaryInstrumentationTest
/* |测试函数| CustomDBI::Convert()
/* | 用例名 | convert_with_tune_log_path_write_log_on_success
/* |用例描述| 执行测试函数,转换成功时写入tune日志
*/
TEST(CustomDBI, convert_with_tune_log_path_write_log_on_success)
{
MOCKER(PipeCall).stubs().will(returnValue(true));
MOCKER(chmod).stubs().will(returnValue(0));
MOCKER(&WriteStringToFile).expects(exactly(1)).will(returnValue(true));
MOCKER(&CustomDBI::GenerateOrderingFile).stubs().will(returnValue(true));
MOCKER(&CustomDBI::GenerateTempProbe).stubs().will(returnValue(true));
MOCKER(&CustomDBI::GenerateKernelWithProbe).stubs().will(returnValue(true));
CustomDBI dbi;
dbi.initFunc_ = StubInitFunc;
BinaryInstrumentation::Config config;
config.archName = "arch";
config.tuneLogPath = "./tune.log";
dbi.SetConfig(config);
EXPECT_TRUE(dbi.Convert("newKernelFile", "oldKernelFile", "tilingKey"));
GlobalMockObject::verify();
}
/* | 用例集 | BinaryInstrumentationTest
/* |测试函数| CustomDBI::Convert()
/* | 用例名 | convert_without_tune_log_path_no_write
/* |用例描述| 执行测试函数,无tune日志路径时不写入日志
*/
TEST(CustomDBI, convert_without_tune_log_path_no_write)
{
MOCKER(&CustomDBI::GenerateOrderingFile).stubs().will(returnValue(true));
MOCKER(&CustomDBI::GenerateTempProbe).stubs().will(returnValue(true));
MOCKER(&CustomDBI::GenerateKernelWithProbe).stubs().will(returnValue(true));
MOCKER(chmod).stubs().will(returnValue(0));
MOCKER(PipeCall).stubs().will(returnValue(false));
MOCKER(&WriteStringToFile).expects(exactly(0));
CustomDBI dbi;
dbi.initFunc_ = StubInitFunc;
BinaryInstrumentation::Config config;
config.archName = "arch";
config.tuneLogPath = "";
dbi.SetConfig(config);
EXPECT_FALSE(dbi.Convert("newKernelFile", "oldKernelFile", "tilingKey"));
GlobalMockObject::verify();
}