* 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 "hcom_op_utils.h"
#include "mocker/mocker.h"
#include "ge/op_desc.h"
#include "ge/tensor_desc.h"
#include "ge/tensor_utils.h"
#include "sal/sal_interface.h"
using namespace hccl;
class HcomOpUtilsTest : public testing::Test {
protected:
void SetUp() override {
MOCKER_RESET_ALL();
}
void TearDown() override {
}
void SetUpMockSalGetDataTypeSize(HcclDataType dataType, u32 size) {
MOCKER(SalGetDataTypeSize).ExpectCall(
With(dataType),
WithOut(size))
.WillOnce(Return(HCCL_SUCCESS));
}
void SetUpMockTensorUtilsGetSize(int64_t tensorSize) {
MOCKER(ge::TensorUtils::GetSize).ExpectCall(
WithAny(),
WithOut(tensorSize))
.WillOnce(Return(ge::GRAPH_SUCCESS));
}
class MockOpDesc : public ge::OpDesc {
public:
MOCK_METHOD(u64, GetInputsSize, (), (const, override));
MOCK_METHOD(const ge::TensorDesc*, GetInputDescPtr, (u64), (const, override));
};
class MockTensorDesc : public ge::TensorDesc {
public:
MOCK_METHOD(const ge::Shape&, GetShape, (), (const, override));
};
class MockShape : public ge::Shape {
public:
MOCK_METHOD(int64_t, GetShapeSize, (), (const, override));
};
};
TEST_F(HcomOpUtilsTest, Ut_GetAccuracyCountFromOpDesc_When_AllReduceWithValidInput_Expect_Success) {
auto op = std::make_shared<MockOpDesc>();
EXPECT_CALL(*op, GetInputsSize()).WillOnce(Return(1));
auto tensorDesc = std::make_shared<MockTensorDesc>();
auto shape = std::make_shared<MockShape>();
EXPECT_CALL(*shape, GetShapeSize()).WillOnce(Return(256));
EXPECT_CALL(*tensorDesc, GetShape()).WillOnce(Return(*shape));
EXPECT_CALL(*op, GetInputDescPtr(0)).WillOnce(Return(tensorDesc.get()));
SetUpMockSalGetDataTypeSize(HCCL_DATA_TYPE_FP32, 4);
SetUpMockTensorUtilsGetSize(1024);
std::string sCollectiveType = HCCL_KERNEL_OP_TYPE_ALLREDUCE;
HcclDataType dataType = HCCL_DATA_TYPE_FP32;
u64 count = 0;
u32 rankSize = 1;
HcclResult ret = HcomOpUtils::GetAccuracyCountFromOpDesc(op, sCollectiveType, dataType, count, rankSize);
EXPECT_EQ(ret, HCCL_SUCCESS) << "Expected HCCL_SUCCESS, got " << ret;
EXPECT_EQ(count, 256) << "Expected count 256, got " << count;
}
TEST_F(HcomOpUtilsTest, Ut_GetAccuracyCountFromOpDesc_When_BroadcastWithValidInput_Expect_Success) {
auto op = std::make_shared<MockOpDesc>();
EXPECT_CALL(*op, GetInputsSize()).WillOnce(Return(1));
auto tensorDesc = std::make_shared<MockTensorDesc>();
auto shape = std::make_shared<MockShape>();
EXPECT_CALL(*shape, GetShapeSize()).WillOnce(Return(100));
EXPECT_CALL(*tensorDesc, GetShape()).WillOnce(Return(*shape));
EXPECT_CALL(*op, GetInputDescPtr(0)).WillOnce(Return(tensorDesc.get()));
SetUpMockSalGetDataTypeSize(HCCL_DATA_TYPE_FP32, 4);
std::string sCollectiveType = HCCL_KERNEL_OP_TYPE_BROADCAST;
HcclDataType dataType = HCCL_DATA_TYPE_FP32;
u64 count = 0;
u32 rankSize = 4;
HcclResult ret = HcomOpUtils::GetAccuracyCountFromOpDesc(op, sCollectiveType, dataType, count, rankSize);
EXPECT_EQ(ret, HCCL_SUCCESS) << "Expected HCCL_SUCCESS, got " << ret;
EXPECT_EQ(count, 128) << "Expected count 128, got " << count;
}
TEST_F(HcomOpUtilsTest, Ut_GetAccuracyCountFromOpDesc_When_ReceiveOp_Expect_E_PARA) {
auto op = std::make_shared<MockOpDesc>();
EXPECT_CALL(*op, GetInputsSize()).WillOnce(Return(1));
auto tensorDesc = std::make_shared<MockTensorDesc>();
auto shape = std::make_shared<MockShape>();
EXPECT_CALL(*shape, GetShapeSize()).WillOnce(Return(100));
EXPECT_CALL(*tensorDesc, GetShape()).WillOnce(Return(*shape));
EXPECT_CALL(*op, GetInputDescPtr(0)).WillOnce(Return(tensorDesc.get()));
SetUpMockSalGetDataTypeSize(HCCL_DATA_TYPE_FP32, 4);
std::string sCollectiveType = HCCL_KERNEL_OP_TYPE_RECEIVE;
HcclDataType dataType = HCCL_DATA_TYPE_FP32;
u64 count = 0;
u32 rankSize = 4;
HcclResult ret = HcomOpUtils::GetAccuracyCountFromOpDesc(op, sCollectiveType, dataType, count, rankSize);
EXPECT_EQ(ret, HCCL_E_PARA) << "Expected HCCL_E_PARA for RECEIVE op, got " << ret;
}
TEST_F(HcomOpUtilsTest, Ut_GetAccuracyCountFromOpDesc_When_DataTypeSizeZero_Expect_E_PARA) {
auto op = std::make_shared<MockOpDesc>();
EXPECT_CALL(*op, GetInputsSize()).WillOnce(Return(1));
auto tensorDesc = std::make_shared<MockTensorDesc>();
auto shape = std::make_shared<MockShape>();
EXPECT_CALL(*shape, GetShapeSize()).WillOnce(Return(100));
EXPECT_CALL(*tensorDesc, GetShape()).WillOnce(Return(*shape));
EXPECT_CALL(*op, GetInputDescPtr(0)).WillOnce(Return(tensorDesc.get()));
SetUpMockSalGetDataTypeSize(HCCL_DATA_TYPE_FP32, 0);
std::string sCollectiveType = HCCL_KERNEL_OP_TYPE_ALLGATHER;
HcclDataType dataType = HCCL_DATA_TYPE_FP32;
u64 count = 0;
u32 rankSize = 4;
HcclResult ret = HcomOpUtils::GetAccuracyCountFromOpDesc(op, sCollectiveType, dataType, count, rankSize);
EXPECT_EQ(ret, HCCL_E_PARA) << "Expected HCCL_E_PARA for zero dataTypeSize, got " << ret;
}
TEST_F(HcomOpUtilsTest, Ut_GetAccuracyCountFromOpDesc_When_RankSizeZero_Expect_E_PARA) {
auto op = std::make_shared<MockOpDesc>();
EXPECT_CALL(*op, GetInputsSize()).WillOnce(Return(1));
auto tensorDesc = std::make_shared<MockTensorDesc>();
auto shape = std::make_shared<MockShape>();
EXPECT_CALL(*shape, GetShapeSize()).WillOnce(Return(100));
EXPECT_CALL(*tensorDesc, GetShape()).WillOnce(Return(*shape));
EXPECT_CALL(*op, GetInputDescPtr(0)).WillOnce(Return(tensorDesc.get()));
SetUpMockSalGetDataTypeSize(HCCL_DATA_TYPE_FP32, 4);
std::string sCollectiveType = HCCL_KERNEL_OP_TYPE_REDUCESCATTER;
HcclDataType dataType = HCCL_DATA_TYPE_FP32;
u64 count = 0;
u32 rankSize = 0;
HcclResult ret = HcomOpUtils::GetAccuracyCountFromOpDesc(op, sCollectiveType, dataType, count, rankSize);
EXPECT_EQ(ret, HCCL_E_PARA) << "Expected HCCL_E_PARA for zero rankSize, got " << ret;
}
TEST_F(HcomOpUtilsTest, Ut_CalcCommonCount_When_ReduceScatterWithContinuousInput_Expect_Success) {
auto opDesc = std::make_shared<ge::OpDesc>();
ge::GeTensorDesc tensorDesc;
tensorDesc.SetShape(ge::GeShape({1024}));
(void)opDesc->AddInputDesc(tensorDesc);
(void)ge::AttrUtils::SetBool(opDesc, ge::ATTR_NAME_CONTINUOUS_INPUT, true);
std::string sCollectiveType = HCCL_KERNEL_OP_TYPE_REDUCESCATTER;
HcclDataType dataType = HCCL_DATA_TYPE_FP32;
u64 count = 0;
u32 rankSize = 4;
HcclResult ret = HcomOpUtils::GetAccuracyCountFromOpDesc(opDesc, sCollectiveType, dataType, count, rankSize);
EXPECT_EQ(ret, HCCL_SUCCESS) << "Expected HCCL_SUCCESS, got " << ret;
EXPECT_EQ(count, 384) << "Expected count 384, got " << count;
}
TEST_F(HcomOpUtilsTest, Ut_CalcCommonCount_When_ReduceScatterWithNonContinuousInput_Expect_Success) {
auto opDesc = std::make_shared<ge::OpDesc>();
ge::GeTensorDesc tensorDesc;
tensorDesc.SetShape(ge::GeShape({1024}));
(void)opDesc->AddInputDesc(tensorDesc);
(void)ge::AttrUtils::SetBool(opDesc, ge::ATTR_NAME_CONTINUOUS_INPUT, false);
std::string sCollectiveType = HCCL_KERNEL_OP_TYPE_REDUCESCATTER;
HcclDataType dataType = HCCL_DATA_TYPE_FP32;
u64 count = 0;
u32 rankSize = 4;
HcclResult ret = HcomOpUtils::GetAccuracyCountFromOpDesc(opDesc, sCollectiveType, dataType, count, rankSize);
EXPECT_EQ(ret, HCCL_SUCCESS) << "Expected HCCL_SUCCESS, got " << ret;
EXPECT_EQ(count, 256) << "Expected count 256, got " << count;
}
TEST_F(HcomOpUtilsTest, Ut_CalcCommonCount_When_AllGatherWithContinuousInput_Expect_Success) {
auto opDesc = std::make_shared<ge::OpDesc>();
ge::GeTensorDesc tensorDesc;
tensorDesc.SetShape(ge::GeShape({100}));
(void)opDesc->AddInputDesc(tensorDesc);
(void)ge::AttrUtils::SetBool(opDesc, ge::ATTR_NAME_CONTINUOUS_INPUT, true);
std::string sCollectiveType = HCCL_KERNEL_OP_TYPE_ALLGATHER;
HcclDataType dataType = HCCL_DATA_TYPE_FP32;
u64 count = 0;
u32 rankSize = 4;
HcclResult ret = HcomOpUtils::GetAccuracyCountFromOpDesc(opDesc, sCollectiveType, dataType, count, rankSize);
EXPECT_EQ(ret, HCCL_SUCCESS) << "Expected HCCL_SUCCESS, got " << ret;
EXPECT_EQ(count, 128) << "Expected count 128, got " << count;
}
TEST_F(HcomOpUtilsTest, Ut_CalcCommonCount_When_ReduceScatter4MContinuousInput_Expect_Success) {
auto opDesc = std::make_shared<ge::OpDesc>();
ge::GeTensorDesc tensorDesc;
tensorDesc.SetShape(ge::GeShape({1048576}));
(void)opDesc->AddInputDesc(tensorDesc);
(void)ge::AttrUtils::SetBool(opDesc, ge::ATTR_NAME_CONTINUOUS_INPUT, true);
std::string sCollectiveType = HCCL_KERNEL_OP_TYPE_REDUCESCATTER;
HcclDataType dataType = HCCL_DATA_TYPE_FP32;
u64 count = 0;
u32 rankSize = 8;
HcclResult ret = HcomOpUtils::GetAccuracyCountFromOpDesc(opDesc, sCollectiveType, dataType, count, rankSize);
EXPECT_EQ(ret, HCCL_SUCCESS) << "Expected HCCL_SUCCESS, got " << ret;
EXPECT_EQ(count, 131200) << "Expected count 131200, got " << count;
}
TEST_F(HcomOpUtilsTest, Ut_CalcCommonCount_When_ReduceScatter4MNonContinuousInput_Expect_Success) {
auto opDesc = std::make_shared<ge::OpDesc>();
ge::GeTensorDesc tensorDesc;
tensorDesc.SetShape(ge::GeShape({1048576}));
(void)opDesc->AddInputDesc(tensorDesc);
(void)ge::AttrUtils::SetBool(opDesc, ge::ATTR_NAME_CONTINUOUS_INPUT, false);
std::string sCollectiveType = HCCL_KERNEL_OP_TYPE_REDUCESCATTER;
HcclDataType dataType = HCCL_DATA_TYPE_FP32;
u64 count = 0;
u32 rankSize = 8;
HcclResult ret = HcomOpUtils::GetAccuracyCountFromOpDesc(opDesc, sCollectiveType, dataType, count, rankSize);
EXPECT_EQ(ret, HCCL_SUCCESS) << "Expected HCCL_SUCCESS, got " << ret;
EXPECT_EQ(count, 131072) << "Expected count 131072, got " << count;
}
TEST_F(HcomOpUtilsTest, Ut_CalcCommonCount_When_AllGather4MContinuousInput_Expect_Success) {
auto opDesc = std::make_shared<ge::OpDesc>();
ge::GeTensorDesc tensorDesc;
tensorDesc.SetShape(ge::GeShape({1048576}));
(void)opDesc->AddInputDesc(tensorDesc);
(void)ge::AttrUtils::SetBool(opDesc, ge::ATTR_NAME_CONTINUOUS_INPUT, true);
std::string sCollectiveType = HCCL_KERNEL_OP_TYPE_ALLGATHER;
HcclDataType dataType = HCCL_DATA_TYPE_FP32;
u64 count = 0;
u32 rankSize = 8;
HcclResult ret = HcomOpUtils::GetAccuracyCountFromOpDesc(opDesc, sCollectiveType, dataType, count, rankSize);
EXPECT_EQ(ret, HCCL_SUCCESS) << "Expected HCCL_SUCCESS, got " << ret;
EXPECT_EQ(count, 1048576) << "Expected count 1048576, got " << count;
}
TEST_F(HcomOpUtilsTest, Ut_CalcCommonCount_When_AllGather4MNonContinuousInput_Expect_Success) {
auto opDesc = std::make_shared<ge::OpDesc>();
ge::GeTensorDesc tensorDesc;
tensorDesc.SetShape(ge::GeShape({1048576}));
(void)opDesc->AddInputDesc(tensorDesc);
(void)ge::AttrUtils::SetBool(opDesc, ge::ATTR_NAME_CONTINUOUS_INPUT, false);
std::string sCollectiveType = HCCL_KERNEL_OP_TYPE_ALLGATHER;
HcclDataType dataType = HCCL_DATA_TYPE_FP32;
u64 count = 0;
u32 rankSize = 8;
HcclResult ret = HcomOpUtils::GetAccuracyCountFromOpDesc(opDesc, sCollectiveType, dataType, count, rankSize);
EXPECT_EQ(ret, HCCL_SUCCESS) << "Expected HCCL_SUCCESS, got " << ret;
EXPECT_EQ(count, 1048576) << "Expected count 1048576, got " << count;
}
TEST_F(HcomOpUtilsTest, Ut_CalcCommonCount_When_AlltoAll4M_Expect_Success) {
auto opDesc = std::make_shared<ge::OpDesc>();
ge::GeTensorDesc tensorDesc;
tensorDesc.SetShape(ge::GeShape({1048576}));
(void)opDesc->AddInputDesc(tensorDesc);
std::string sCollectiveType = HCCL_KERNEL_OP_TYPE_ALLTOALL;
HcclDataType dataType = HCCL_DATA_TYPE_FP32;
u64 count = 0;
u32 rankSize = 8;
HcclResult ret = HcomOpUtils::GetAccuracyCountFromOpDesc(opDesc, sCollectiveType, dataType, count, rankSize);
EXPECT_EQ(ret, HCCL_SUCCESS) << "Expected HCCL_SUCCESS, got " << ret;
EXPECT_EQ(count, 1048576) << "Expected count 1048576, got " << count;
}
TEST_F(HcomOpUtilsTest, Ut_CalcCommonCount_When_DefaultAlignedOp4M_Expect_Success) {
auto opDesc = std::make_shared<ge::OpDesc>();
ge::GeTensorDesc tensorDesc;
tensorDesc.SetShape(ge::GeShape({1048576}));
(void)opDesc->AddInputDesc(tensorDesc);
std::string sCollectiveType = HCCL_KERNEL_OP_TYPE_ALLREDUCE;
HcclDataType dataType = HCCL_DATA_TYPE_FP32;
u64 count = 0;
u32 rankSize = 8;
HcclResult ret = HcomOpUtils::GetAccuracyCountFromOpDesc(opDesc, sCollectiveType, dataType, count, rankSize);
EXPECT_EQ(ret, HCCL_SUCCESS) << "Expected HCCL_SUCCESS, got " << ret;
EXPECT_EQ(count, 1048576) << "Expected count 1048576, got " << count;
}
TEST_F(HcomOpUtilsTest, Ut_CalcCommonCount_When_AllGatherWithNonContinuousInput_Expect_Success) {
auto opDesc = std::make_shared<ge::OpDesc>();
ge::GeTensorDesc tensorDesc;
tensorDesc.SetShape(ge::GeShape({100}));
(void)opDesc->AddInputDesc(tensorDesc);
(void)ge::AttrUtils::SetBool(opDesc, ge::ATTR_NAME_CONTINUOUS_INPUT, false);
std::string sCollectiveType = HCCL_KERNEL_OP_TYPE_ALLGATHER;
HcclDataType dataType = HCCL_DATA_TYPE_FP32;
u64 count = 0;
u32 rankSize = 4;
HcclResult ret = HcomOpUtils::GetAccuracyCountFromOpDesc(opDesc, sCollectiveType, dataType, count, rankSize);
EXPECT_EQ(ret, HCCL_SUCCESS) << "Expected HCCL_SUCCESS, got " << ret;
EXPECT_EQ(count, 100) << "Expected count 100, got " << count;
}
TEST_F(HcomOpUtilsTest, Ut_CalcCommonCount_When_AlltoAll_Expect_Success) {
auto opDesc = std::make_shared<ge::OpDesc>();
ge::GeTensorDesc tensorDesc;
tensorDesc.SetShape(ge::GeShape({100}));
(void)opDesc->AddInputDesc(tensorDesc);
std::string sCollectiveType = HCCL_KERNEL_OP_TYPE_ALLTOALL;
HcclDataType dataType = HCCL_DATA_TYPE_FP32;
u64 count = 0;
u32 rankSize = 4;
HcclResult ret = HcomOpUtils::GetAccuracyCountFromOpDesc(opDesc, sCollectiveType, dataType, count, rankSize);
EXPECT_EQ(ret, HCCL_SUCCESS) << "Expected HCCL_SUCCESS, got " << ret;
EXPECT_EQ(count, 100) << "Expected count 100, got " << count;
}
TEST_F(HcomOpUtilsTest, Ut_CalcCommonCount_When_DefaultAlignedOp_Expect_Success) {
auto opDesc = std::make_shared<ge::OpDesc>();
ge::GeTensorDesc tensorDesc;
tensorDesc.SetShape(ge::GeShape({100}));
(void)opDesc->AddInputDesc(tensorDesc);
std::string sCollectiveType = HCCL_KERNEL_OP_TYPE_ALLREDUCE;
HcclDataType dataType = HCCL_DATA_TYPE_FP32;
u64 count = 0;
u32 rankSize = 4;
HcclResult ret = HcomOpUtils::GetAccuracyCountFromOpDesc(opDesc, sCollectiveType, dataType, count, rankSize);
EXPECT_EQ(ret, HCCL_SUCCESS) << "Expected HCCL_SUCCESS, got " << ret;
EXPECT_EQ(count, 128) << "Expected count 128, got " << count;
}