* -------------------------------------------------------------------------
* This file is part of the Vision SDK project.
* Copyright (c) 2025 Huawei Technologies Co.,Ltd.
*
* Vision SDK 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.
* -------------------------------------------------------------------------
* Description: Gtest unit cases.
* Author: MindX SDK
* Create: 2020
* History: NA
*/
#include <gtest/gtest.h>
#include <mockcpp/mockcpp.hpp>
#include "acl/acl.h"
#include "MxBase/MxBase.h"
#include "dvpp/securec.h"
#include "MxBase/CV/MultipleObjectTracking/Huangarian.h"
#include "module/Algorithm/MultipleObjectTracking/Huangarian.cpp"
using namespace MxBase;
namespace {
const int HANDLE_MAX = 8192;
const int THREE = 3;
constexpr int TWO = 2;
class HuangarianTest : public testing::Test {
protected:
void SetUp() {
}
void TearDown()
{
GlobalMockObject::verify();
}
};
std::vector<std::vector<int>> CreateCostMatrix(int rows, int cols)
{
std::vector<std::vector<int>> costMatrix;
costMatrix.resize(rows, std::vector<int>(cols, 0));
for (int j = 0; j < cols; ++j) {
for (int i = 0; i < rows; ++i) {
if (i == j) {
costMatrix[i][j] = 1;
} else {
costMatrix[i][j] = 0;
}
}
}
return costMatrix;
}
TEST_F(HuangarianTest, HungarianSolveLess)
{
HungarianHandle hungarianHandleObj;
int rows = 3;
int cols = 5;
APP_ERROR ret = HungarianHandleInit(hungarianHandleObj, rows, cols);
EXPECT_EQ(ret, APP_ERR_OK);
std::vector<std::vector<int>> costMatrix = CreateCostMatrix(rows, cols);
HungarianSolve(hungarianHandleObj, costMatrix, rows, cols);
int actualResultFirst = 0;
EXPECT_EQ(hungarianHandleObj.resX[0], actualResultFirst);
int actualResultSecond = 1;
EXPECT_EQ(hungarianHandleObj.resX[1], actualResultSecond);
int actualResultThird = 2;
EXPECT_EQ(hungarianHandleObj.resX[TWO], actualResultThird);
}
TEST_F(HuangarianTest, HungarianSolveMore)
{
HungarianHandle hungarianHandleObj;
int rows = 4;
int cols = 3;
APP_ERROR ret = HungarianHandleInit(hungarianHandleObj, rows, cols);
EXPECT_EQ(ret, APP_ERR_OK);
std::vector<std::vector<int>> costMatrix = CreateCostMatrix(rows, cols);
HungarianSolve(hungarianHandleObj, costMatrix, rows, cols);
int actualResultFirst = 0;
EXPECT_EQ(hungarianHandleObj.resX[0], actualResultFirst);
int actualResultSecond = 1;
EXPECT_EQ(hungarianHandleObj.resX[1], actualResultSecond);
int actualResultThird = 2;
EXPECT_EQ(hungarianHandleObj.resX[TWO], actualResultThird);
int actualResultForth = -1;
EXPECT_EQ(hungarianHandleObj.resX[THREE], actualResultForth);
}
TEST_F(HuangarianTest, Test_HungarianHandleInit_Should_Return_Failed_When_Rows_Cols_Valid)
{
HungarianHandle hungarianHandleObj;
APP_ERROR ret = HungarianHandleInit(hungarianHandleObj, 0, 1);
EXPECT_EQ(ret, APP_ERR_COMM_INVALID_PARAM);
ret = HungarianHandleInit(hungarianHandleObj, HANDLE_MAX + 1, 1);
EXPECT_EQ(ret, APP_ERR_COMM_INVALID_PARAM);
ret = HungarianHandleInit(hungarianHandleObj, 1, 0);
EXPECT_EQ(ret, APP_ERR_COMM_INVALID_PARAM);
ret = HungarianHandleInit(hungarianHandleObj, 1, HANDLE_MAX + 1);
EXPECT_EQ(ret, APP_ERR_COMM_INVALID_PARAM);
}
TEST_F(HuangarianTest, Test_HungarianHandleInit_Should_Return_Fail_When_Memsets_Fail_First)
{
MOCKER_CPP(&memset_s).stubs().will(returnValue(1));
HungarianHandle hungarianHandleObj;
int rows = 3;
int cols = 5;
APP_ERROR ret = HungarianHandleInit(hungarianHandleObj, rows, cols);
EXPECT_EQ(ret, APP_ERR_COMM_ALLOC_MEM);
}
TEST_F(HuangarianTest, Test_HungarianHandleInit_Should_Return_Fail_When_Malloc_Fail_Second)
{
int callTimes = 2;
MOCKER_CPP(&memset_s).times(callTimes).will(returnValue(0)).then(returnValue(1));
HungarianHandle hungarianHandleObj;
int rows = 3;
int cols = 5;
APP_ERROR ret = HungarianHandleInit(hungarianHandleObj, rows, cols);
EXPECT_EQ(ret, APP_ERR_COMM_ALLOC_MEM);
}
TEST_F(HuangarianTest, Test_HungarianSolve_Should_Return_Fail_When_Rows_Cols_Cost_Valid)
{
HungarianHandle hungarianHandleObj;
int rows = 4;
int cols = 3;
APP_ERROR ret = HungarianHandleInit(hungarianHandleObj, rows, cols);
EXPECT_EQ(ret, APP_ERR_OK);
std::vector<std::vector<int>> costMatrix;
ret = HungarianSolve(hungarianHandleObj, costMatrix, 0, 1);
EXPECT_EQ(ret, -1);
ret = HungarianSolve(hungarianHandleObj, costMatrix, 1, 0);
EXPECT_EQ(ret, -1);
ret = HungarianSolve(hungarianHandleObj, costMatrix, HANDLE_MAX + 1, 1);
EXPECT_EQ(ret, -1);
ret = HungarianSolve(hungarianHandleObj, costMatrix, 1, HANDLE_MAX + 1);
EXPECT_EQ(ret, -1);
ret = HungarianSolve(hungarianHandleObj, costMatrix, 1, 1);
EXPECT_EQ(ret, -1);
}
TEST_F(HuangarianTest, Test_HungarianSolve_Should_Return_Fail_When_Rows_Valid)
{
HungarianHandle hungarianHandleObj;
int rows = 4;
int cols = 3;
APP_ERROR ret = HungarianHandleInit(hungarianHandleObj, rows, cols);
EXPECT_EQ(ret, APP_ERR_OK);
std::vector<std::vector<int>> costMatrix = CreateCostMatrix(rows, cols);
ret = HungarianSolve(hungarianHandleObj, costMatrix, rows - 1, cols);
EXPECT_EQ(ret, -1);
}
TEST_F(HuangarianTest, Test_HungarianSolve_Should_Return_Fail_When_Cols_Valid)
{
HungarianHandle hungarianHandleObj;
int rows = 4;
int cols = 3;
APP_ERROR ret = HungarianHandleInit(hungarianHandleObj, rows, cols);
EXPECT_EQ(ret, APP_ERR_OK);
std::vector<std::vector<int>> costMatrix = CreateCostMatrix(rows, cols);
ret = HungarianSolve(hungarianHandleObj, costMatrix, rows, cols - 1);
EXPECT_EQ(ret, -1);
}
TEST_F(HuangarianTest, Test_HungarianSolve_Should_Return_Fail_When_CostMatrix_Valid)
{
HungarianHandle hungarianHandleObj;
int rows = 4;
int cols = 3;
APP_ERROR ret = HungarianHandleInit(hungarianHandleObj, rows, cols);
EXPECT_EQ(ret, APP_ERR_OK);
std::vector<std::vector<int>> costMatrix = CreateCostMatrix(rows, cols);
costMatrix[1].push_back(0);
ret = HungarianSolve(hungarianHandleObj, costMatrix, rows, cols);
EXPECT_EQ(ret, -1);
}
TEST_F(HuangarianTest, Test_HungarianSolve_Should_Return_Fail_When_xMatch_Null)
{
HungarianHandle hungarianHandleObj;
int rows = 4;
int cols = 3;
APP_ERROR ret = HungarianHandleInit(hungarianHandleObj, rows, cols);
EXPECT_EQ(ret, APP_ERR_OK);
std::vector<std::vector<int>> costMatrix = CreateCostMatrix(rows, cols);
hungarianHandleObj.xMatch = nullptr;
ret = HungarianSolve(hungarianHandleObj, costMatrix, rows, cols);
EXPECT_EQ(ret, -1);
}
TEST_F(HuangarianTest, Test_HungarianSolve_Should_Return_Fail_When_yMatch_Null)
{
HungarianHandle hungarianHandleObj;
int rows = 4;
int cols = 3;
APP_ERROR ret = HungarianHandleInit(hungarianHandleObj, rows, cols);
EXPECT_EQ(ret, APP_ERR_OK);
std::vector<std::vector<int>> costMatrix = CreateCostMatrix(rows, cols);
hungarianHandleObj.yMatch = nullptr;
ret = HungarianSolve(hungarianHandleObj, costMatrix, rows, cols);
EXPECT_EQ(ret, -1);
}
TEST_F(HuangarianTest, Test_HungarianSolve_Should_Return_Fail_When_xValue_Null)
{
HungarianHandle hungarianHandleObj;
int rows = 4;
int cols = 3;
APP_ERROR ret = HungarianHandleInit(hungarianHandleObj, rows, cols);
EXPECT_EQ(ret, APP_ERR_OK);
std::vector<std::vector<int>> costMatrix = CreateCostMatrix(rows, cols);
hungarianHandleObj.xValue = nullptr;
ret = HungarianSolve(hungarianHandleObj, costMatrix, rows, cols);
EXPECT_EQ(ret, -1);
}
TEST_F(HuangarianTest, Test_HungarianSolve_Should_Return_Fail_When_yValue_Null)
{
HungarianHandle hungarianHandleObj;
int rows = 4;
int cols = 3;
APP_ERROR ret = HungarianHandleInit(hungarianHandleObj, rows, cols);
EXPECT_EQ(ret, APP_ERR_OK);
std::vector<std::vector<int>> costMatrix = CreateCostMatrix(rows, cols);
hungarianHandleObj.yValue = nullptr;
ret = HungarianSolve(hungarianHandleObj, costMatrix, rows, cols);
EXPECT_EQ(ret, -1);
}
TEST_F(HuangarianTest, Test_HungarianSolve_Should_Return_Fail_When_slack_Null)
{
HungarianHandle hungarianHandleObj;
int rows = 4;
int cols = 3;
APP_ERROR ret = HungarianHandleInit(hungarianHandleObj, rows, cols);
EXPECT_EQ(ret, APP_ERR_OK);
std::vector<std::vector<int>> costMatrix = CreateCostMatrix(rows, cols);
hungarianHandleObj.slack = nullptr;
ret = HungarianSolve(hungarianHandleObj, costMatrix, rows, cols);
EXPECT_EQ(ret, -1);
}
TEST_F(HuangarianTest, Test_HungarianSolve_Should_Return_Fail_When_xVisit_Null)
{
HungarianHandle hungarianHandleObj;
int rows = 4;
int cols = 3;
APP_ERROR ret = HungarianHandleInit(hungarianHandleObj, rows, cols);
EXPECT_EQ(ret, APP_ERR_OK);
std::vector<std::vector<int>> costMatrix = CreateCostMatrix(rows, cols);
hungarianHandleObj.xVisit = nullptr;
ret = HungarianSolve(hungarianHandleObj, costMatrix, rows, cols);
EXPECT_EQ(ret, -1);
}
TEST_F(HuangarianTest, Test_HungarianSolve_Should_Return_Fail_When_yVisit_Null)
{
HungarianHandle hungarianHandleObj;
int rows = 4;
int cols = 3;
APP_ERROR ret = HungarianHandleInit(hungarianHandleObj, rows, cols);
EXPECT_EQ(ret, APP_ERR_OK);
std::vector<std::vector<int>> costMatrix = CreateCostMatrix(rows, cols);
hungarianHandleObj.yVisit = nullptr;
ret = HungarianSolve(hungarianHandleObj, costMatrix, rows, cols);
EXPECT_EQ(ret, -1);
}
TEST_F(HuangarianTest, Test_HungarianSolve_Should_Return_Fail_When_adjMat_Null)
{
HungarianHandle hungarianHandleObj;
int rows = 4;
int cols = 3;
APP_ERROR ret = HungarianHandleInit(hungarianHandleObj, rows, cols);
EXPECT_EQ(ret, APP_ERR_OK);
std::vector<std::vector<int>> costMatrix = CreateCostMatrix(rows, cols);
hungarianHandleObj.adjMat = nullptr;
ret = HungarianSolve(hungarianHandleObj, costMatrix, rows, cols);
EXPECT_EQ(ret, -1);
}
HungarianHandle CreateTestHungarianHandleObj()
{
HungarianHandle handle;
auto array = std::make_shared<std::array<int, 3>>(std::array<int, 3>{1, 2, 3});
std::shared_ptr<int> ptr(array, array->data());
handle.yVisit = ptr;
handle.xVisit = ptr;
handle.xValue = ptr;
handle.yValue = ptr;
handle.adjMat = ptr;
handle.yMatch = ptr;
handle.xMatch = ptr;
handle.slack = ptr;
return handle;
}
TEST_F(HuangarianTest, Test_Match_Should_Continue_When_yVisit_Is_VISITED)
{
HungarianHandle handle = CreateTestHungarianHandleObj();
const int id = 1;
handle.cols = THREE;
bool ret = MxBase::Match(handle, id);
EXPECT_EQ(ret, false);
}
TEST_F(HuangarianTest, Test_Match_Should_Return_False_When_Cols_Is_0)
{
HungarianHandle handle = CreateTestHungarianHandleObj();
const int id = 1;
handle.cols = 0;
bool ret = MxBase::Match(handle, id);
EXPECT_EQ(ret, false);
}
TEST_F(HuangarianTest, Test_Match_Should_Return_False_When_delta_Is_Inf)
{
HungarianHandle handle = CreateTestHungarianHandleObj();
const int id = 1;
handle.cols = 0;
handle.rows = 0;
int delta = 0;
bool ret = MxBase::ObjectAssociated(handle, delta, id);
EXPECT_EQ(ret, false);
}
}
int main(int argc, char* argv[])
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}