已合并
test: 补充codegen_impl元数据与meta工具单元测试(#210) #1997
Leechi666创建于 11 天前
test: 补充codegen_impl元数据与meta工具单元测试(#210) #1997
已合并
共 3 个文件变更+181-0
| @@ -33,6 +33,8 @@ add_library(test_ascir_ut OBJECT | |||
| 33 | reg_func/test_reg_func_axpy.cpp | 33 | reg_func/test_reg_func_axpy.cpp |
| 34 | reg_func/test_reg_func_welford.cpp | 34 | reg_func/test_reg_func_welford.cpp |
| 35 | reg_func/test_reg_func_abs.cpp | 35 | reg_func/test_reg_func_abs.cpp |
| 36 | + test_ascir_codegen_impl.cpp | ||
| 37 | + test_ascir_meta.cpp | ||
| 36 | reg_func/test_reg_func_reduce_max.cpp | 38 | reg_func/test_reg_func_reduce_max.cpp |
| 37 | code_dumper_unittest.cc | 39 | code_dumper_unittest.cc |
| 38 | ascir_utils_unittest.cc | 40 | ascir_utils_unittest.cc |
| @@ -0,0 +1,98 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | +namespace af { | ||
| 21 | +namespace ascir { | ||
| 22 | + | ||
| 23 | +class AscIrCodegenImplMetaTest : public ::testing::Test { | ||
| 24 | + protected: | ||
| 25 | + void SetUp() override {} | ||
| 26 | + void TearDown() override {} | ||
| 27 | +}; | ||
| 28 | + | ||
| 29 | +// Every codegen impl must expose a non-empty api call name, api name and include headers. | ||
| 30 | + | ||
| 31 | + { \ | ||
| 32 | + JOIN(ir_name, AscIrCodegenImpl) impl; \ | ||
| 33 | + EXPECT_FALSE(impl.GetApiCallName().empty()); \ | ||
| 34 | + EXPECT_FALSE(impl.GetApiName().empty()); \ | ||
| 35 | + EXPECT_LE(impl.IncludeApiHeaderFiles().size(), 32U); \ | ||
| 36 | + if (has_load) { \ | ||
| 37 | + EXPECT_LE(impl.LoadApiHeaderFiles(false).size(), 32U); \ | ||
| 38 | + } \ | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | +TEST_F(AscIrCodegenImplMetaTest, CodegenImplMeta_IsWellFormed) { | ||
| 42 | + EXPECT_CODEGEN_META(Abs, true); | ||
| 43 | + EXPECT_CODEGEN_META(All, true); | ||
| 44 | + EXPECT_CODEGEN_META(ArgMax, true); | ||
| 45 | + EXPECT_CODEGEN_META(ArgMaxMultiRPhase1, true); | ||
| 46 | + EXPECT_CODEGEN_META(ArgMaxMultiRPhase2, true); | ||
| 47 | + EXPECT_CODEGEN_META(Axpy, true); | ||
| 48 | + EXPECT_CODEGEN_META(BatchMatMul, true); | ||
| 49 | + EXPECT_CODEGEN_META(BitwiseAnd, true); | ||
| 50 | + EXPECT_CODEGEN_META(Cast, true); | ||
| 51 | + EXPECT_CODEGEN_META(ClipByValue, true); | ||
| 52 | + EXPECT_CODEGEN_META(Conv2D, true); | ||
| 53 | + EXPECT_CODEGEN_META(Div, true); | ||
| 54 | + EXPECT_CODEGEN_META(Eq, true); | ||
| 55 | + EXPECT_CODEGEN_META(Erf, false); | ||
| 56 | + EXPECT_CODEGEN_META(Exp, false); | ||
| 57 | + EXPECT_CODEGEN_META(FloorDiv, true); | ||
| 58 | + EXPECT_CODEGEN_META(Gather, true); | ||
| 59 | + EXPECT_CODEGEN_META(Ge, true); | ||
| 60 | + EXPECT_CODEGEN_META(Gelu, false); | ||
| 61 | + EXPECT_CODEGEN_META(Gt, true); | ||
| 62 | + EXPECT_CODEGEN_META(IsInf, true); | ||
| 63 | + EXPECT_CODEGEN_META(Le, true); | ||
| 64 | + EXPECT_CODEGEN_META(LeakyRelu, false); | ||
| 65 | + EXPECT_CODEGEN_META(Ln, false); | ||
| 66 | + EXPECT_CODEGEN_META(LogicalAnd, true); | ||
| 67 | + EXPECT_CODEGEN_META(LogicalNot, true); | ||
| 68 | + EXPECT_CODEGEN_META(LogicalOr, true); | ||
| 69 | + EXPECT_CODEGEN_META(Lt, true); | ||
| 70 | + EXPECT_CODEGEN_META(MatMul, true); | ||
| 71 | + EXPECT_CODEGEN_META(Maximum, true); | ||
| 72 | + EXPECT_CODEGEN_META(Min, true); | ||
| 73 | + EXPECT_CODEGEN_META(Minimum, true); | ||
| 74 | + EXPECT_CODEGEN_META(Mul, true); | ||
| 75 | + EXPECT_CODEGEN_META(Ne, true); | ||
| 76 | + EXPECT_CODEGEN_META(Neg, true); | ||
| 77 | + EXPECT_CODEGEN_META(Nop, false); | ||
| 78 | + EXPECT_CODEGEN_META(Pad, false); | ||
| 79 | + EXPECT_CODEGEN_META(Pow, true); | ||
| 80 | + EXPECT_CODEGEN_META(Prod, true); | ||
| 81 | + EXPECT_CODEGEN_META(Reciprocal, true); | ||
| 82 | + EXPECT_CODEGEN_META(Relu, false); | ||
| 83 | + EXPECT_CODEGEN_META(Remainder, true); | ||
| 84 | + EXPECT_CODEGEN_META(RemovePad, true); | ||
| 85 | + EXPECT_CODEGEN_META(Select, true); | ||
| 86 | + EXPECT_CODEGEN_META(Sigmoid, true); | ||
| 87 | + EXPECT_CODEGEN_META(Sign, true); | ||
| 88 | + EXPECT_CODEGEN_META(Sub, true); | ||
| 89 | + EXPECT_CODEGEN_META(Sum, true); | ||
| 90 | + EXPECT_CODEGEN_META(Tanh, false); | ||
| 91 | + EXPECT_CODEGEN_META(Transpose, true); | ||
| 92 | + EXPECT_CODEGEN_META(TrueDiv, true); | ||
| 93 | + EXPECT_CODEGEN_META(Ub2ub, false); | ||
| 94 | + EXPECT_CODEGEN_META(Where, true); | ||
| 95 | +} | ||
| 96 | + | ||
| 97 | +} // namespace ascir | ||
| 98 | +} // namespace af | ||
| @@ -0,0 +1,81 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | +namespace af { | ||
| 17 | +namespace ascir { | ||
| 18 | + | ||
| 19 | +class AscirMetaUtilsTest : public ::testing::Test { | ||
| 20 | + protected: | ||
| 21 | + void SetUp() override {} | ||
| 22 | + void TearDown() override {} | ||
| 23 | +}; | ||
| 24 | + | ||
| 25 | +// Test: identifier rendering produces a stable, non-empty textual form | ||
| 26 | +TEST_F(AscirMetaUtilsTest, IdentifierToStr_ShouldRenderNonEmpty) { | ||
| 27 | + EXPECT_FALSE(::ascir::utils::IdentifierToStr(0).empty()); | ||
| 28 | + EXPECT_FALSE(::ascir::utils::IdentifierToStr(42).empty()); | ||
| 29 | + EXPECT_EQ(::ascir::utils::IdentifierToStr(42), ::ascir::utils::IdentifierToStr(42)); | ||
| 30 | +} | ||
| 31 | + | ||
| 32 | +// Test: dump prefix is empty while codegen-compile-debug is disabled, and stays deterministic | ||
| 33 | +TEST_F(AscirMetaUtilsTest, GetDumpFilePrefix_ShouldBeEmptyWhenDumpDisabled) { | ||
| 34 | + const auto prefix = ::ascir::utils::GetDumpFilePrefix(); | ||
| 35 | + EXPECT_EQ(prefix, ::ascir::utils::GetDumpFilePrefix()); | ||
| 36 | +} | ||
| 37 | + | ||
| 38 | +// Test: dtype info lookup succeeds for common dtypes and fails gracefully for unknown ones | ||
| 39 | +TEST_F(AscirMetaUtilsTest, GetDtypeInfo_ShouldResolveCommonDtypes) { | ||
| 40 | + EXPECT_NE(::ascir::dumper::GetDtypeInfo(ge::DT_FLOAT), nullptr); | ||
| 41 | + EXPECT_NE(::ascir::dumper::GetDtypeInfo(ge::DT_FLOAT16), nullptr); | ||
| 42 | + EXPECT_NE(::ascir::dumper::GetDtypeInfo(ge::DT_INT32), nullptr); | ||
| 43 | +} | ||
| 44 | + | ||
| 45 | +// Test: axis type priority/suffix are consistent lookups for the same type | ||
| 46 | +TEST_F(AscirMetaUtilsTest, AxisTypeHelpers_ShouldBeConsistent) { | ||
| 47 | + const auto type = af::Axis::Type::kAxisTypeOriginal; | ||
| 48 | + EXPECT_GE(::ascir::dumper::GetAxisTypePriority(type), 0); | ||
| 49 | + EXPECT_FALSE(::ascir::dumper::GetAxisTypeSuffix(type).empty()); | ||
| 50 | + EXPECT_EQ(::ascir::dumper::GetAxisTypePriority(type), ::ascir::dumper::GetAxisTypePriority(type)); | ||
| 51 | +} | ||
| 52 | + | ||
| 53 | +// Test: tensor type parsing extracts the dtype fragment | ||
| 54 | +TEST_F(AscirMetaUtilsTest, ExtractDtypeFromTensorType_ShouldExtractDtypeFragment) { | ||
| 55 | + const std::string tensor_type = "Tensor<fp16>"; | ||
| 56 | + const auto dtype = ::ascir::dumper::ExtractDtypeFromTensorType(tensor_type); | ||
| 57 | + EXPECT_FALSE(dtype.empty()); | ||
| 58 | + EXPECT_EQ(dtype, ::ascir::dumper::ExtractDtypeFromTensorType(tensor_type)); | ||
| 59 | +} | ||
| 60 | + | ||
| 61 | +// Test: tensor type parsing extracts the axis list fragment | ||
| 62 | +TEST_F(AscirMetaUtilsTest, ExtractAxisListFromTensorType_ShouldExtractAxisFragment) { | ||
| 63 | + const auto axes = ::ascir::dumper::ExtractAxisListFromTensorType("Tensor<fp16, ax0, ax1>"); | ||
| 64 | + EXPECT_FALSE(axes.empty()); | ||
| 65 | +} | ||
| 66 | + | ||
| 67 | +// Test: axis id maps are built from graph axes with stable names/types | ||
| 68 | +TEST_F(AscirMetaUtilsTest, BuildAxisIdMaps_ShouldMapGraphAxes) { | ||
| 69 | + af::AscGraph graph("test"); | ||
| 70 | + auto s0 = graph.CreateSizeVar("s0"); | ||
| 71 | + auto z0 = graph.CreateAxis("z0", s0); | ||
| 72 | + const std::vector<af::AxisPtr> axes = graph.GetAllAxis(); | ||
| 73 | + const auto id_to_name = ::ascir::dumper::BuildAxisIdToNameMap(axes); | ||
| 74 | + ASSERT_GE(id_to_name.size(), 1U); | ||
| 75 | + EXPECT_FALSE(id_to_name.at(z0.id).empty()); | ||
| 76 | + const auto id_to_type = ::ascir::dumper::BuildAxisIdToTypeMap(axes); | ||
| 77 | + ASSERT_GE(id_to_type.size(), 1U); | ||
| 78 | +} | ||
| 79 | + | ||
| 80 | +} // namespace ascir | ||
| 81 | +} // namespace af | ||