* Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved.
* ubs-engine 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 "test_ubse_node_controller_collector.h"
#include <src/framework/config/ubse_conf_module.h>
#include <src/framework/misc/ubse_net_util.h>
#include <filesystem>
#include "ubse_lcne_module.h"
#include "ubse_mti_interface_default.h"
#include "adapter_plugins/mti/ubse_mti_def.h"
#include "adapter_plugins/mti/ubse_topology_interface.h"
#include "ubse_node_controller_collector.cpp"
namespace ubse::node_controller::ut {
using namespace ubse::adapter_plugins::mti;
void TestNodeControllerCollector::SetUp()
{
Test::SetUp();
std::string certDir = std::filesystem::current_path().string();
try {
if (!std::filesystem::exists(certDir)) {
std::filesystem::create_directories(certDir);
chmod(certDir.c_str(), 0700);
}
} catch (const std::filesystem::filesystem_error& e) {
std::cerr << "Failed to create directory: " << e.what() << std::endl;
}
}
void TestNodeControllerCollector::TearDown()
{
Test::TearDown();
GlobalMockObject::verify();
}
TEST_F(TestNodeControllerCollector, CollectNodeBaseInfo)
{
MOCKER(GetCurNodeInfo).stubs().will(ignoreReturnValue());
MOCKER(gethostname).stubs().will(returnValue(1)).then(returnValue(0));
UbseNodeInfo ubseNodeInfo{};
EXPECT_EQ(CollectNodeBaseInfo(ubseNodeInfo), 1);
}
TEST_F(TestNodeControllerCollector, CollectNodeBaseInfoWhenConfModuleIsNull)
{
UbseNodeInfo info{.nodeId = "0", .slotId = 0};
MOCKER_CPP(GetCurNodeInfo).stubs().with(outBound(info));
MOCKER(gethostname).stubs().will(returnValue(EOK));
std::shared_ptr<UbseConfModule> nullModule;
MOCKER_CPP(&UbseContext::GetModule<UbseConfModule>).stubs().will(returnValue(nullModule));
EXPECT_EQ(CollectNodeBaseInfo(info), UBSE_ERROR_MODULE_LOAD_FAILED);
}
TEST_F(TestNodeControllerCollector, CollectCpuInfo)
{
adapter_plugins::mti::UbseMtiCpuTopoInfoMap cpuTopoInfos;
adapter_plugins::mti::UbseDevName devName("1", "2");
adapter_plugins::mti::UbseMtiCpuTopoInfo cpuTopoInfo;
cpuTopoInfo.nodeId = 1;
cpuTopoInfo.chipId = "2";
cpuTopoInfo.primaryEid = "primaryEid";
cpuTopoInfo.cardId = "cardId";
cpuTopoInfo.busNodeCna = 100;
cpuTopoInfo.eid = "eid";
cpuTopoInfo.guid = "guid";
cpuTopoInfos[devName] = cpuTopoInfo;
adapter_plugins::mti::UbseMtiInterfaceDefault mtiDefault;
MOCKER_CPP_VIRTUAL(&mtiDefault, &adapter_plugins::mti::UbseMtiInterfaceDefault::GetClusterCpuTopo)
.stubs()
.with(outBound(cpuTopoInfos))
.will(returnValue(UBSE_OK));
ubse::nodeController::UbseNodeInfo ubseNodeInfo{};
auto ret = CollectCpuInfo(ubseNodeInfo, "1");
EXPECT_EQ(ret, UBSE_OK);
EXPECT_EQ(ubseNodeInfo.cpuInfos.size(), 1);
}
TEST_F(TestNodeControllerCollector, CollectNodeTopology)
{
UbseNodeInfo ubseNodeInfo{};
MOCKER(CollectIpList).stubs().will(returnValue(UBSE_ERROR)).then(returnValue(UBSE_OK));
MOCKER(CollectNumaInfo).stubs().will(returnValue(UBSE_ERROR)).then(returnValue(UBSE_OK));
MOCKER(CollectCpuInfo).stubs().will(returnValue(UBSE_ERROR)).then(returnValue(UBSE_OK));
EXPECT_EQ(CollectNodeTopology(ubseNodeInfo), UBSE_ERROR);
EXPECT_EQ(CollectNodeTopology(ubseNodeInfo), UBSE_ERROR);
EXPECT_EQ(CollectNodeTopology(ubseNodeInfo), UBSE_ERROR);
EXPECT_EQ(CollectNodeTopology(ubseNodeInfo), UBSE_OK);
}
TEST_F(TestNodeControllerCollector, ParseIP)
{
UbseIpV4Addr ipv4{};
EXPECT_EQ(ParseIP("a.1.1.1", ipv4), UBSE_ERROR_INVAL);
EXPECT_EQ(ParseIP("2147483648.1.1.1", ipv4), UBSE_ERROR_INVAL);
EXPECT_EQ(ParseIP("256.1.1.1", ipv4), UBSE_ERROR_INVAL);
EXPECT_EQ(ParseIP("127.0.0.0.1", ipv4), UBSE_ERROR_INVAL);
EXPECT_EQ(ParseIP("127.0.0.1", ipv4), UBSE_OK);
EXPECT_EQ(ipv4.addr[0], 127);
EXPECT_EQ(ipv4.addr[1], 0);
EXPECT_EQ(ipv4.addr[2], 0);
EXPECT_EQ(ipv4.addr[3], 1);
}
TEST_F(TestNodeControllerCollector, IsSpecialIP)
{
EXPECT_EQ(UbseNetUtil::IsSpecialIP("127.0.0.1"), true);
EXPECT_EQ(UbseNetUtil::IsSpecialIP("6.123.2.27"), false);
}
std::string FibTrieStr()
{
return "Main:\n"
" +-- 0.0.0.0/0 3 0 5\n"
" +-- 0.0.0.0/5 2 0 2\n"
" |-- 0.0.0.0\n"
" /0 universe UNICAST\n"
" +-- 7.218.100.0/23 2 0 1\n"
" |-- 7.218.100.0\n"
" /23 link UNICAST\n"
" |-- 7.218.101.27\n"
" /32 host LOCAL\n"
" |-- 7.218.101.255\n"
" /32 link BROADCAST\n"
" +-- 127.0.0.0/8 2 0 2\n"
" +-- 127.0.0.0/31 1 0 0\n"
" |-- 127.0.0.0\n"
" /8 host LOCAL\n"
" |-- 127.0.0.1\n"
" /32 host LOCAL\n"
" |-- 127.255.255.255\n"
" /32 link BROADCAST\n"
" |-- 169.254.169.254\n"
" /32 universe UNICAST\n"
"Local:\n"
" +-- 0.0.0.0/0 3 0 5\n"
" +-- 0.0.0.0/5 2 0 2\n"
" |-- 0.0.0.0\n"
" /0 universe UNICAST\n"
" +-- 7.218.100.0/23 2 0 1\n"
" |-- 7.218.100.0\n"
" /23 link UNICAST\n"
" |-- 7.218.101.27\n"
" /32 host LOCAL\n"
" |-- 7.218.101.255\n"
" /32 link BROADCAST\n"
" +-- 127.0.0.0/8 2 0 2\n"
" +-- 127.0.0.0/31 1 0 0\n"
" |-- 127.0.0.0\n"
" /8 host LOCAL\n"
" |-- 127.0.0.1\n"
" /32 host LOCAL\n"
" |-- 127.255.255.255\n"
" /32 link BROADCAST\n"
" |-- 169.254.169.254\n"
" /32 universe UNICAST";
}
int CreateFibTrieFile()
{
std::string certDir = std::filesystem::current_path().string();
FIB_TRIE_PATH = certDir + "fib_trie";
std::ofstream fibTrie(FIB_TRIE_PATH, std::ios::binary);
if (!fibTrie) {
std::cerr << "Failed to create node files" << std::endl;
return 1;
}
fibTrie << FibTrieStr();
fibTrie.close();
}
uint32_t MockUbseNodeTelemetryGetIpInfo(std::vector<std::string>& ipInfos)
{
ipInfos = {"7.218.101.255"};
return UBSE_OK;
}
TEST_F(TestNodeControllerCollector, ProcessListLine)
{
std::vector<uint16_t> cpuList{};
EXPECT_EQ(ProcessListLine("a", cpuList), UBSE_ERROR);
cpuList.clear();
EXPECT_EQ(ProcessListLine("1", cpuList), UBSE_OK);
EXPECT_EQ(cpuList.size(), 1);
EXPECT_EQ(cpuList[0], 1);
cpuList.clear();
EXPECT_EQ(ProcessListLine("0-1", cpuList), UBSE_OK);
EXPECT_EQ(cpuList.size(), 2);
EXPECT_EQ(cpuList[0], 0);
EXPECT_EQ(cpuList[1], 1);
}
int CreateCpuListFile(const std::string& content)
{
std::string certDir = std::filesystem::current_path().string();
CPU_LIST_PREFIX_PATH = certDir + "node";
try {
if (!std::filesystem::exists(CPU_LIST_PREFIX_PATH + "0")) {
std::filesystem::create_directories(CPU_LIST_PREFIX_PATH + "0");
chmod(certDir.c_str(), 0700);
}
} catch (const std::filesystem::filesystem_error& e) {
std::cerr << "Failed to create directory: " << e.what() << std::endl;
}
std::string path = CPU_LIST_PREFIX_PATH + "0" + CPU_LIST_SUFFIX_PATH;
std::ofstream cpuList(path, std::ios::binary);
if (!cpuList) {
std::cerr << "Failed to create cpu list files" << std::endl;
return 1;
}
cpuList << content;
cpuList.close();
}
void RemoveCpuDir()
{
CPU_LIST_PREFIX_PATH = std::filesystem::current_path().string() + "node";
std::string cpuPath = CPU_LIST_PREFIX_PATH + "0";
try {
if (std::filesystem::exists(cpuPath)) {
std::filesystem::remove_all(cpuPath);
}
} catch (const std::filesystem::filesystem_error& e) {
std::cerr << "remove cpu dir failed." << e.what() << std::endl;
}
}
TEST_F(TestNodeControllerCollector, CollectCpuList_FAIL)
{
std::vector<uint16_t> cpuList{};
CPU_LIST_PREFIX_PATH = "";
EXPECT_EQ(CollectCpuList(0, cpuList), UBSE_ERROR);
CPU_LIST_PREFIX_PATH = std::filesystem::current_path().string() + "node";
CreateCpuListFile("a");
EXPECT_EQ(CollectCpuList(0, cpuList), UBSE_ERROR);
RemoveCpuDir();
}
TEST_F(TestNodeControllerCollector, CollectCpuList)
{
std::vector<uint16_t> cpuList{};
CPU_LIST_PREFIX_PATH = std::filesystem::current_path().string() + "node";
CreateCpuListFile("0-1");
EXPECT_EQ(CollectCpuList(0, cpuList), UBSE_OK);
EXPECT_EQ(cpuList.size(), 2);
EXPECT_EQ(cpuList[0], 0);
EXPECT_EQ(cpuList[1], 1);
RemoveCpuDir();
}
int CreateSocketIdFile(const std::string& content)
{
std::string certDir = std::filesystem::current_path().string();
SOCKET_ID_PREFIX_PATH = certDir + "socket";
try {
if (!std::filesystem::exists(SOCKET_ID_PREFIX_PATH + "0" + "/topology")) {
std::filesystem::create_directories(SOCKET_ID_PREFIX_PATH + "0" + "/topology");
chmod(certDir.c_str(), 0700);
}
} catch (const std::filesystem::filesystem_error& e) {
std::cerr << "Failed to create directory: " << e.what() << std::endl;
}
std::string path = SOCKET_ID_PREFIX_PATH + "0" + SOCKET_ID_SUFFIX_PATH;
std::ofstream cpuList(path, std::ios::binary);
if (!cpuList) {
std::cerr << "Failed to create socket id files" << std::endl;
return 1;
}
cpuList << content;
cpuList.close();
}
void RemoveSocketDir()
{
SOCKET_ID_PREFIX_PATH = std::filesystem::current_path().string() + "socket";
std::string socketPath = SOCKET_ID_PREFIX_PATH + "0";
try {
if (std::filesystem::exists(socketPath)) {
std::filesystem::remove_all(socketPath);
}
} catch (const std::filesystem::filesystem_error& e) {
std::cerr << "remove socket dir failed." << e.what() << std::endl;
}
}
TEST_F(TestNodeControllerCollector, GetSocketId)
{
uint32_t socketId;
SOCKET_ID_PREFIX_PATH = "";
EXPECT_EQ(GetSocketId(socketId, 0), UBSE_ERROR);
CreateSocketIdFile("36");
EXPECT_EQ(GetSocketId(socketId, 0), UBSE_OK);
EXPECT_EQ(socketId, 36);
RemoveSocketDir();
}
int CreateMemFile(const std::string& content)
{
std::string certDir = std::filesystem::current_path().string();
MEM_PREFIX_PATH = certDir + "mem";
try {
if (!std::filesystem::exists(MEM_PREFIX_PATH + "0")) {
std::filesystem::create_directories(MEM_PREFIX_PATH + "0");
chmod(certDir.c_str(), 0700);
}
} catch (const std::filesystem::filesystem_error& e) {
std::cerr << "Failed to create directory: " << e.what() << std::endl;
}
std::string path = MEM_PREFIX_PATH + "0" + MEM_SUFFIX_PATH;
std::ofstream cpuList(path, std::ios::binary);
if (!cpuList) {
std::cerr << "Failed to create mem files" << std::endl;
return 1;
}
cpuList << content;
cpuList.close();
}
void RemoveMemDir()
{
MEM_PREFIX_PATH = std::filesystem::current_path().string() + "mem";
std::string memPath = MEM_PREFIX_PATH + "0";
try {
if (std::filesystem::exists(memPath)) {
std::filesystem::remove_all(memPath);
}
} catch (const std::filesystem::filesystem_error& e) {
std::cerr << "remove mem dir failed." << e.what() << std::endl;
}
}
TEST_F(TestNodeControllerCollector, CollectMemSize)
{
uint64_t memSize;
uint64_t memFree;
MEM_PREFIX_PATH = "";
EXPECT_EQ(CollectMemSize(0, memSize, memFree), UBSE_ERROR);
std::string content = "Node 0 MemTotal: 65812844 kB\n"
"Node 0 MemFree: 60791520 kB\n"
"Node 0 ";
CreateMemFile(content);
EXPECT_EQ(CollectMemSize(0, memSize, memFree), UBSE_OK);
EXPECT_EQ(memSize, 65812844);
EXPECT_EQ(memFree, 60791520);
RemoveMemDir();
}
int CreateNrPageFile(const std::string& content)
{
std::string certDir = std::filesystem::current_path().string();
NR_PAGE_PREFIX_PATH = certDir + "nr";
try {
if (!std::filesystem::exists(NR_PAGE_PREFIX_PATH + "0" + "/hugepages/hugepages-2048kB")) {
std::filesystem::create_directories(NR_PAGE_PREFIX_PATH + "0" + "/hugepages/hugepages-2048kB");
chmod(certDir.c_str(), 0700);
}
} catch (const std::filesystem::filesystem_error& e) {
std::cerr << "Failed to create directory: " << e.what() << std::endl;
}
std::string path = NR_PAGE_PREFIX_PATH + "0" + NR_PAGE_SUFFIX_PATH_1 + "2048" + NR_PAGE_SUFFIX_PATH_2;
std::ofstream cpuList(path, std::ios::binary);
if (!cpuList) {
std::cerr << "Failed to create nr page files" << std::endl;
return 1;
}
cpuList << content;
cpuList.close();
}
void RemoveNrPageDir()
{
NR_PAGE_PREFIX_PATH = std::filesystem::current_path().string() + "nr";
std::string nrPagePath = NR_PAGE_PREFIX_PATH + "0";
try {
if (std::filesystem::exists(nrPagePath)) {
std::filesystem::remove_all(nrPagePath);
}
} catch (const std::filesystem::filesystem_error& e) {
std::cerr << "remove nr page dir failed." << e.what() << std::endl;
}
}
TEST_F(TestNodeControllerCollector, CollectNrHugePages2048)
{
uint32_t nrHugePages2048;
NR_PAGE_PREFIX_PATH = "";
EXPECT_EQ(CollectNrHugePages(0, nrHugePages2048, 2048), UBSE_ERROR);
CreateNrPageFile("1024");
EXPECT_EQ(CollectNrHugePages(0, nrHugePages2048, 2048), UBSE_OK);
EXPECT_EQ(nrHugePages2048, 1024);
RemoveNrPageDir();
}
int CreateFreePageFile(const std::string& content)
{
std::string certDir = std::filesystem::current_path().string();
FREE_PAGE_PREFIX_PATH = certDir + "free";
try {
if (!std::filesystem::exists(FREE_PAGE_PREFIX_PATH + "0" + "/hugepages/hugepages-2048kB")) {
std::filesystem::create_directories(FREE_PAGE_PREFIX_PATH + "0" + "/hugepages/hugepages-2048kB");
chmod(certDir.c_str(), 0700);
}
} catch (const std::filesystem::filesystem_error& e) {
std::cerr << "Failed to create directory: " << e.what() << std::endl;
}
std::string path = FREE_PAGE_PREFIX_PATH + "0" + FREE_PAGE_SUFFIX_PATH_1 + "2048" + FREE_PAGE_SUFFIX_PATH_2;
std::ofstream cpuList(path, std::ios::binary);
if (!cpuList) {
std::cerr << "Failed to create free page files" << std::endl;
return 1;
}
cpuList << content;
cpuList.close();
}
void RemoveFreePageDir()
{
FREE_PAGE_PREFIX_PATH = std::filesystem::current_path().string() + "free";
std::string nrPagePath = FREE_PAGE_PREFIX_PATH + "0";
try {
if (std::filesystem::exists(nrPagePath)) {
std::filesystem::remove_all(nrPagePath);
}
} catch (const std::filesystem::filesystem_error& e) {
std::cerr << "remove nr page dir failed." << e.what() << std::endl;
}
}
TEST_F(TestNodeControllerCollector, CollectFreeHugePages2048)
{
uint32_t freeHugePages2048;
FREE_PAGE_PREFIX_PATH = "";
EXPECT_EQ(CollectFreeHugePages(0, freeHugePages2048, 2048), UBSE_ERROR);
CreateFreePageFile("1024");
EXPECT_EQ(CollectFreeHugePages(0, freeHugePages2048, 2048), UBSE_OK);
EXPECT_EQ(freeHugePages2048, 1024);
RemoveFreePageDir();
}
int CreateNumaFile(const std::string& content)
{
std::string certDir = std::filesystem::current_path().string();
NUMA_PATH = certDir + "numa";
std::ofstream numa(NUMA_PATH, std::ios::binary);
if (!numa) {
std::cerr << "Failed to create numa files" << std::endl;
return 1;
}
numa << content;
numa.close();
}
TEST_F(TestNodeControllerCollector, GetLocalNumas_FAIL)
{
std::vector<uint32_t> nodeIds{};
NUMA_PATH = "";
EXPECT_EQ(GetLocalNumas(nodeIds), UBSE_ERROR);
CreateNumaFile("a");
EXPECT_EQ(GetLocalNumas(nodeIds), UBSE_ERROR);
const char* path = NUMA_PATH.c_str();
std::remove(path);
}
TEST_F(TestNodeControllerCollector, GetLocalNumas)
{
std::vector<uint32_t> nodeIds{};
CreateNumaFile("0-1");
EXPECT_EQ(GetLocalNumas(nodeIds), UBSE_OK);
EXPECT_EQ(nodeIds.size(), 2);
EXPECT_EQ(nodeIds[0], 0);
EXPECT_EQ(nodeIds[1], 1);
const char* path = NUMA_PATH.c_str();
std::remove(path);
}
uint32_t MockGetLocalNumas(std::vector<uint32_t>& nodeIds)
{
nodeIds = {1};
return UBSE_OK;
}
UbseResult MockCollectCpuList(uint32_t numa, std::vector<uint16_t>& cpuList)
{
cpuList = {1};
return UBSE_OK;
}
TEST_F(TestNodeControllerCollector, CollectNumaInfo)
{
UbseNodeInfo ubseNodeInfo{};
MOCKER(GetLocalNumas).stubs().will(returnValue(UBSE_ERROR)).then(invoke(MockGetLocalNumas));
EXPECT_EQ(CollectNumaInfo(ubseNodeInfo, "1"), UBSE_ERROR);
MOCKER(CollectCpuList).stubs().will(returnValue(UBSE_ERROR)).then(invoke(MockCollectCpuList));
EXPECT_EQ(CollectNumaInfo(ubseNodeInfo, "1"), UBSE_ERROR);
MOCKER(GetSocketId).stubs().will(returnValue(UBSE_ERROR)).then(returnValue(UBSE_OK));
EXPECT_EQ(CollectNumaInfo(ubseNodeInfo, "1"), UBSE_ERROR);
MOCKER(CollectMemSize).stubs().will(returnValue(UBSE_ERROR)).then(returnValue(UBSE_OK));
EXPECT_EQ(CollectNumaInfo(ubseNodeInfo, "1"), UBSE_ERROR);
MOCKER(CollectNrHugePages).stubs().will(returnValue(UBSE_ERROR)).then(returnValue(UBSE_OK));
EXPECT_EQ(CollectNumaInfo(ubseNodeInfo, "1"), UBSE_ERROR);
MOCKER(CollectFreeHugePages).stubs().will(returnValue(UBSE_ERROR)).then(returnValue(UBSE_OK));
MOCKER(CollectObmmMemPoolInfo).stubs().will(returnValue(UBSE_OK));
EXPECT_EQ(CollectNumaInfo(ubseNodeInfo, "1"), UBSE_ERROR);
EXPECT_EQ(CollectNumaInfo(ubseNodeInfo, "1"), UBSE_OK);
}
TEST_F(TestNodeControllerCollector, AddEdgeInfo)
{
std::pair<const UbseDevPortName, adapter_plugins::mti::UbseMtiCpuTopoPortInfo> port{};
nodeController::UbsePortInfo portInfo{};
adapter_plugins::mti::UbseMtiCpuTopoPortInfo info{};
info.portId = "port";
info.ifName = "ifName";
info.portRole = "master";
info.portStatus = UbseMtiCpuTopoPortStatus::UP;
info.portCna = 1;
info.remoteSlotId = "remoteSlot";
info.remoteChipId = "remoteChip";
info.remoteCardId = "remoteCard";
info.remoteIfName = "remoteIfName";
info.remotePortId = "remotePort";
port.second = info;
EXPECT_NO_THROW(AddEdgeInfo(port, portInfo));
EXPECT_EQ(portInfo.portId, "port");
EXPECT_EQ(portInfo.ifName, "ifName");
EXPECT_EQ(portInfo.portRole, "master");
EXPECT_EQ(portInfo.portStatus, PortStatus::UP);
EXPECT_EQ(portInfo.portCna, 1);
EXPECT_EQ(portInfo.remoteSlotId, "remoteSlot");
EXPECT_EQ(portInfo.remoteChipId, "remoteChip");
EXPECT_EQ(portInfo.remoteCardId, "remoteCard");
EXPECT_EQ(portInfo.remoteIfName, "remoteIfName");
EXPECT_EQ(portInfo.remotePortId, "remotePort");
}
TEST_F(TestNodeControllerCollector, CollectIpListWhenGetIpInfoFail)
{
std::vector<std::string> ipInfos{"127.0.0.1"};
MOCKER_CPP(UbseNetUtil::GetIpInfo).stubs().will(returnValue(UBSE_ERROR));
UbseNodeInfo nodeInfo;
ASSERT_EQ(CollectIpList(nodeInfo), UBSE_ERROR);
}
TEST_F(TestNodeControllerCollector, CollectIpListWhenSuccess)
{
std::vector<std::string> ipInfos{"127.0.0.1"};
MOCKER_CPP(UbseNetUtil::GetIpInfo).stubs().with(outBound(ipInfos)).will(returnValue(UBSE_OK));
UbseNodeInfo nodeInfo;
ASSERT_EQ(CollectIpList(nodeInfo), UBSE_OK);
ASSERT_EQ(nodeInfo.ipList[0].ipv4.addr[0], 127);
}
}