diff --git a/src/plugins/intel_cpu/src/nodes/reduce.cpp b/src/plugins/intel_cpu/src/nodes/reduce.cpp index 6882327bbf0275..d26dcec39f4b22 100644 --- a/src/plugins/intel_cpu/src/nodes/reduce.cpp +++ b/src/plugins/intel_cpu/src/nodes/reduce.cpp @@ -2020,6 +2020,7 @@ void Reduce::initSupportedPrimitiveDescriptors() { config.outConfs[0].setMemDesc(creatorsMap.at(outFormat)->createSharedDesc(outPrecision, getOutputShapeAtPort(0))); if (useAclExecutor) { +#if defined (OV_CPU_WITH_ACL) std::vector srcMemoryDescs; for (size_t i = 0; i < config.inConfs.size(); i++) { srcMemoryDescs.push_back(config.inConfs[i].getMemDesc()); @@ -2029,11 +2030,27 @@ void Reduce::initSupportedPrimitiveDescriptors() { dstMemoryDescs.push_back(config.outConfs[i].getMemDesc()); } - auto factory = std::make_shared(reduceAttrs, srcMemoryDescs, dstMemoryDescs, + auto attrs = reduceAttrs; + bool apply_ref = customImplPriorities.size() > 0 && customImplPriorities[0] == ref; + bool single_axis_only = one_of(algorithm, Algorithm::ReduceSum, Algorithm::ReduceMax, + Algorithm::ReduceMin, Algorithm::ReduceProd); + // For the case of empty input, transformations ConvertReduceProd(Min, Max, Sum) are disabled to avoid empty output. + // So these 4 reduce modes with empty input reducing more than one axis are not supported by acl executor. Then + // factory->isEmpty() returns true, supportedPrimitiveDescriptors is emtpy. Though we don't actually need these acl + // kernels in execution, here we pass a fake axis {1} to pass assertion of "!supportedPrimitiveDescriptors.empty()" + // in Node::filterSupportedPrimitiveDescriptors(). + if (!apply_ref && !isDynamicNode() && single_axis_only) { + const auto& src_shape = getInputShapeAtPort(REDUCE_DATA).getStaticDims(); + if (shape_size(src_shape) == 0) { + attrs.axes = {1}; + } + } + auto factory = std::make_shared(attrs, srcMemoryDescs, dstMemoryDescs, std::make_shared(context, getImplPriority())); if (!factory->isEmpty()) { supportedPrimitiveDescriptors.push_back({config, impl_type, factory}); } +#endif } else { supportedPrimitiveDescriptors.push_back({config, impl_type}); } @@ -2093,6 +2110,12 @@ bool Reduce::isExecutable() const { } void Reduce::prepareParams() { + auto srcMemPtr = getSrcMemoryAtPort(REDUCE_DATA); + auto dstMemPtr = getDstMemoryAtPort(0); + const auto& src_shape = srcMemPtr->getStaticDims(); + dst_size = dstMemPtr->getSize(); + empty_input = shape_size(src_shape) == 0 || srcMemPtr->getSize() == 0; +#if defined (OV_CPU_WITH_ACL) if (canUseAclExecutor) { std::vector srcMemoryDescs; for (size_t i = 0; i < getParentEdges().size(); i++) { @@ -2102,11 +2125,15 @@ void Reduce::prepareParams() { dstMemoryDescs.push_back(getDstMemoryAtPort(0)->getDescPtr()); auto selectedPD = getSelectedPrimitiveDescriptor(); - aclExecPtr = selectedPD->getExecutorFactoryAs()->makeExecutor(reduceAttrs, srcMemoryDescs, dstMemoryDescs, {}); - selectedPD->setImplementationType(aclExecPtr->getImplType()); - + if (!empty_input) { + aclExecPtr = selectedPD->getExecutorFactoryAs()->makeExecutor(reduceAttrs, srcMemoryDescs, dstMemoryDescs, {}); + selectedPD->setImplementationType(aclExecPtr->getImplType()); + } else { + selectedPD->setImplementationType(acl); + } return; } +#endif src_dims = getParentEdgeAt(REDUCE_DATA)->getMemory().getDesc().getShape().getDims(); std::vector reduce_axes; @@ -2116,9 +2143,7 @@ void Reduce::prepareParams() { reduce_axes = raw_axes; } - auto dstMemPtr = getDstMemoryAtPort(0); const VectorDims &dst_dims = dstMemPtr->getDesc().getShape().getDims(); - dst_size = dstMemPtr->getSize(); calc_process_dst_dims(reduce_axes, dst_dims); if (jit_mode) { set_reduce_dim_flags(); @@ -2274,15 +2299,17 @@ void Reduce::execute(dnnl::stream strm) { const uint8_t *src_data = srcMemPtr->getDataAs(); uint8_t *dst_data = dstMemPtr->getDataAs(); - const auto& src_shape = srcMemPtr->getStaticDims(); - if ((shape_size(src_shape) == 0 || srcMemPtr->getSize() == 0)) { - if (dstMemPtr->getSize() > 0) { - init_dst_data(dst_data, dstMemPtr->getSize()); - const bool skip_post_process = getAlgorithm() == Algorithm::ReduceMean || attr.get()->post_ops_.len() == 0; - if (!skip_post_process) { - reduce_kernel_post_process(dst_data); - } + if (empty_input && dst_size > 0) { +#if defined(OPENVINO_ARCH_X86_64) + output_info_reassign(&dst_data); + init_dst_data(dst_data, dst_size); + output_info_restore(&dst_data); + if (attr.get()->post_ops_.len() != 0) { + reduce_kernel_post_process(dst_data); } +#else + init_dst_data(dst_data, dst_size); +#endif return; } @@ -2291,6 +2318,7 @@ void Reduce::execute(dnnl::stream strm) { dst_data = reinterpret_cast(prc_mem.get_data_handle()); } reduce_type(src_data, dst_data); +#if defined (OV_CPU_WITH_ACL) } else if (aclExecPtr) { std::vector srcMemory; for (size_t i = 0; i < getParentEdges().size(); i++) { @@ -2300,6 +2328,7 @@ void Reduce::execute(dnnl::stream strm) { dstMemory.push_back(getDstMemoryAtPort(0)); aclExecPtr->exec(srcMemory, dstMemory, postOpsDataPtrs.data()); +#endif } else { if (layout == ReduceLayoutType::reduce_ncsp) { auto in_ptr = reinterpret_cast(src_data); @@ -2737,7 +2766,7 @@ inline void Reduce::reduce_kernel_process(const uint8_t *in_p, uint8_t *out_p, s inline void Reduce::reduce_kernel_post_process(uint8_t *out_ptr) { const uint8_t *in_ptr = fuse_low_precision ? static_cast(&intermediate_buf[0]) : nullptr; - const size_t integerDivisor = IB * IC * ID * IH * IW / (OB * OC * OD * OH * OW); + const size_t integerDivisor = empty_input ? 1 : IB * IC * ID * IH * IW / (OB * OC * OD * OH * OW); const float divisor = static_cast(integerDivisor); if (layout == ReduceLayoutType::reduce_ncsp) { parallel_for2d(OB, OC, [&](size_t ob, size_t oc) { diff --git a/src/plugins/intel_cpu/src/nodes/reduce.h b/src/plugins/intel_cpu/src/nodes/reduce.h index 2464686edb1ee4..c790cefb0583b0 100644 --- a/src/plugins/intel_cpu/src/nodes/reduce.h +++ b/src/plugins/intel_cpu/src/nodes/reduce.h @@ -152,6 +152,7 @@ class Reduce : public Node { bool ReduceCDW_opt = false; bool use_aux_kernel = false; bool set_use_aux_kernel = false; + bool empty_input = false; bool ReduceN, ReduceC, ReduceD, ReduceH, ReduceW; size_t IB, IC, ID, IH, IW; size_t OB, OC, OD, OH, OW; @@ -188,9 +189,11 @@ class Reduce : public Node { std::string errorPrefix; +#if defined (OV_CPU_WITH_ACL) ReduceAttrs reduceAttrs; bool canUseAclExecutor = false; std::shared_ptr aclExecPtr = nullptr; +#endif }; } // namespace node diff --git a/src/plugins/intel_cpu/src/transformations/cpu_opset/arm/pass/convert_reduce_multi_axis.cpp b/src/plugins/intel_cpu/src/transformations/cpu_opset/arm/pass/convert_reduce_multi_axis.cpp index 22692e644e6e56..ff5632cb0a5e8f 100644 --- a/src/plugins/intel_cpu/src/transformations/cpu_opset/arm/pass/convert_reduce_multi_axis.cpp +++ b/src/plugins/intel_cpu/src/transformations/cpu_opset/arm/pass/convert_reduce_multi_axis.cpp @@ -23,6 +23,9 @@ ov::matcher_pass_callback ov::intel_cpu::ConvertReduceMultiAxisBase::convert_red if (!reduction_axes) { return false; } + if (!reduce->is_dynamic() && ov::shape_size(input0.get_shape()) == 0) { + return false; + } if (ov::shape_size(input1.get_shape()) <= 1) { return false; } diff --git a/src/plugins/intel_cpu/tests/functional/custom/single_layer_tests/classes/reduce.cpp b/src/plugins/intel_cpu/tests/functional/custom/single_layer_tests/classes/reduce.cpp index 66b1d60932b262..b379655338aaf9 100644 --- a/src/plugins/intel_cpu/tests/functional/custom/single_layer_tests/classes/reduce.cpp +++ b/src/plugins/intel_cpu/tests/functional/custom/single_layer_tests/classes/reduce.cpp @@ -243,6 +243,25 @@ const std::vector& reductionTypes() { return reductionTypes; } +const std::vector& reductionTypesArithmetic() { + static const std::vector reductionTypesArithmetic = { + ov::test::utils::ReductionType::Mean, + ov::test::utils::ReductionType::Sum, + ov::test::utils::ReductionType::Prod, + ov::test::utils::ReductionType::L1, + ov::test::utils::ReductionType::L2, + }; + return reductionTypesArithmetic; +} + +const std::vector& reductionTypesCompare() { + static const std::vector reductionTypesCompare = { + ov::test::utils::ReductionType::Max, + ov::test::utils::ReductionType::Min, + }; + return reductionTypesCompare; +} + const std::vector& inpOutPrc() { static const std::vector inpOutPrc = {ElementType::f32}; return inpOutPrc; diff --git a/src/plugins/intel_cpu/tests/functional/custom/single_layer_tests/classes/reduce.hpp b/src/plugins/intel_cpu/tests/functional/custom/single_layer_tests/classes/reduce.hpp index b3e5fff2ba0b7b..d45cce4b3f913e 100644 --- a/src/plugins/intel_cpu/tests/functional/custom/single_layer_tests/classes/reduce.hpp +++ b/src/plugins/intel_cpu/tests/functional/custom/single_layer_tests/classes/reduce.hpp @@ -52,6 +52,8 @@ const std::vector>& axes(); const std::vector>& axesND(); const std::vector& opTypes(); const std::vector& reductionTypes(); +const std::vector& reductionTypesArithmetic(); +const std::vector& reductionTypesCompare(); const std::vector& inpOutPrc(); const std::vector> additionalConfig(); const std::vector> additionalConfigFP32(); diff --git a/src/plugins/intel_cpu/tests/functional/custom/single_layer_tests/instances/arm/reduce.cpp b/src/plugins/intel_cpu/tests/functional/custom/single_layer_tests/instances/arm/reduce.cpp index 313465eeb20a3e..366fe9a0ad8b4a 100644 --- a/src/plugins/intel_cpu/tests/functional/custom/single_layer_tests/instances/arm/reduce.cpp +++ b/src/plugins/intel_cpu/tests/functional/custom/single_layer_tests/instances/arm/reduce.cpp @@ -18,8 +18,11 @@ namespace { std::vector> inputShapes_5D = { {{{}, {{2, 19, 2, 2, 9}}}}, - {{{}, {{0, 19, 2, 2, 9}}}}, - {{{}, {{1, 0, 0, 2, 9}}}}, +}; + +std::vector> inputShapes_5D_ZeroDim = { + {{{}, {{2, 19, 0, 2, 9}}}}, + {{{}, {{2, 19, 0, 2, 0}}}}, }; const std::vector> axes5D = { @@ -46,6 +49,34 @@ const auto params_MultiAxis_5D = testing::Combine( testing::Values(emptyFusingSpec), testing::ValuesIn(additionalConfig())); +const auto params_MultiAxis_5D_ZeroDim = testing::Combine( + testing::Combine( + testing::ValuesIn(axes5D), + testing::Values(ov::test::utils::OpType::VECTOR), + testing::Values(true), + testing::ValuesIn(reductionTypesArithmetic()), + testing::ValuesIn(inpOutPrc()), + testing::Values(ElementType::undefined), + testing::Values(ElementType::undefined), + testing::ValuesIn(inputShapes_5D_ZeroDim)), + testing::ValuesIn(filterCPUSpecificParams(cpuParams_5D)), + testing::Values(emptyFusingSpec), + testing::ValuesIn(additionalConfig())); + +const auto params_MultiAxis_5D_ZeroDim_Compare = testing::Combine( + testing::Combine( + testing::ValuesIn(axes5D), + testing::Values(ov::test::utils::OpType::VECTOR), + testing::Values(true), + testing::ValuesIn(reductionTypesCompare()), + testing::ValuesIn(inpOutPrc()), + testing::Values(ElementType::undefined), + testing::Values(ElementType::undefined), + testing::ValuesIn(inputShapes_5D_ZeroDim)), + testing::ValuesIn(filterCPUSpecificParams(cpuParams_5D)), + testing::Values(emptyFusingSpec), + testing::ValuesIn(additionalConfigFP32())); + const std::vector> axes5D_ref = { {0} }; @@ -81,6 +112,20 @@ INSTANTIATE_TEST_SUITE_P( ReduceCPULayerTest::getTestCaseName ); +INSTANTIATE_TEST_SUITE_P( + smoke_Reduce_MultiAxis_5D_ZeroDim_CPU, + ReduceCPULayerTest, + params_MultiAxis_5D_ZeroDim, + ReduceCPULayerTest::getTestCaseName +); + +INSTANTIATE_TEST_SUITE_P( + smoke_Reduce_MultiAxis_5D_ZeroDim_Compare_CPU, + ReduceCPULayerTest, + params_MultiAxis_5D_ZeroDim_Compare, + ReduceCPULayerTest::getTestCaseName +); + // Reference implementation testing of ACL unsupported case INSTANTIATE_TEST_SUITE_P( smoke_Reduce_MultiAxis_5D_CPU_ref, diff --git a/src/plugins/intel_cpu/tests/functional/custom/single_layer_tests/instances/common/reduce.cpp b/src/plugins/intel_cpu/tests/functional/custom/single_layer_tests/instances/common/reduce.cpp index daada1ce839f91..f962c20e1566f5 100644 --- a/src/plugins/intel_cpu/tests/functional/custom/single_layer_tests/instances/common/reduce.cpp +++ b/src/plugins/intel_cpu/tests/functional/custom/single_layer_tests/instances/common/reduce.cpp @@ -145,7 +145,6 @@ INSTANTIATE_TEST_SUITE_P( ReduceCPULayerTest::getTestCaseName ); - INSTANTIATE_TEST_SUITE_P( smoke_Reduce_Int32_CPU, ReduceCPULayerTest, diff --git a/src/plugins/intel_cpu/tests/functional/custom/single_layer_tests/instances/x64/reduce.cpp b/src/plugins/intel_cpu/tests/functional/custom/single_layer_tests/instances/x64/reduce.cpp index c5381a871954be..3f4e064c2bf733 100644 --- a/src/plugins/intel_cpu/tests/functional/custom/single_layer_tests/instances/x64/reduce.cpp +++ b/src/plugins/intel_cpu/tests/functional/custom/single_layer_tests/instances/x64/reduce.cpp @@ -105,6 +105,17 @@ const std::vector> axesGather = { {3} }; +const std::vector> axesZeroDim { + {1, 3}, + {0, 1, 3}, + {1, 2, 3}, + {0, 1, 2, 3} +}; + +const std::vector> axesZeroDimFusing = { + {1, 3}, +}; + std::vector cpuParams_5D = { CPUSpecificParams({nCdhw16c}, {nCdhw16c}, {}, {}), CPUSpecificParams({ndhwc}, {ndhwc}, {}, {}), @@ -331,6 +342,34 @@ const auto params_SingleBatch = testing::Combine( testing::Values(emptyFusingSpec), testing::ValuesIn(additionalConfig())); +const auto params_DimZero_Arithmetic = testing::Combine( + testing::Combine( + testing::ValuesIn(axesZeroDim), + testing::Values(ov::test::utils::OpType::VECTOR), + testing::ValuesIn(keepDims()), + testing::ValuesIn(reductionTypesArithmetic()), + testing::ValuesIn(inpOutPrc()), + testing::Values(ElementType::undefined), + testing::Values(ElementType::undefined), + testing::ValuesIn(inputShapes_Dynmic_ZeroDim)), + testing::Values(emptyCPUSpec), + testing::Values(emptyFusingSpec), + testing::ValuesIn(additionalConfig())); + +const auto params_DimZero_Compare = testing::Combine( + testing::Combine( + testing::ValuesIn(axesZeroDim), + testing::Values(ov::test::utils::OpType::VECTOR), + testing::ValuesIn(keepDims()), + testing::ValuesIn(reductionTypesCompare()), + testing::ValuesIn(inpOutPrc()), + testing::Values(ElementType::undefined), + testing::Values(ElementType::undefined), + testing::ValuesIn(inputShapes_Dynmic_ZeroDim)), + testing::Values(emptyCPUSpec), + testing::Values(emptyFusingSpec), + testing::ValuesIn(additionalConfigFP32())); + INSTANTIATE_TEST_SUITE_P( smoke_Reduce_OneAxis_CPU, ReduceCPULayerTest, @@ -408,6 +447,20 @@ INSTANTIATE_TEST_SUITE_P( ReduceCPULayerTest::getTestCaseName ); +INSTANTIATE_TEST_SUITE_P( + smoke_Reduce_DimZero_Arithmetic_CPU, + ReduceCPULayerTest, + params_DimZero_Arithmetic, + ReduceCPULayerTest::getTestCaseName +); + +INSTANTIATE_TEST_SUITE_P( + smoke_Reduce_DimZero_Compare_CPU, + ReduceCPULayerTest, + params_DimZero_Compare, + ReduceCPULayerTest::getTestCaseName +); + /* ================================ 1.2 No fusion - Logical ================================ */ const auto params_OneAxis_Logical = testing::Combine( testing::Combine( @@ -606,6 +659,34 @@ const auto params_LowPrecision_fusing = testing::Combine( testing::ValuesIn(fusingParamsSet_LowPrecision), testing::ValuesIn(additionalConfig())); +const auto params_DimZero_Arithmetic_fusing = testing::Combine( + testing::Combine( + testing::ValuesIn(axesZeroDimFusing), + testing::Values(ov::test::utils::OpType::VECTOR), + testing::Values(true), + testing::ValuesIn(reductionTypesArithmetic()), + testing::ValuesIn(inpOutPrc()), + testing::Values(ElementType::undefined), + testing::Values(ElementType::undefined), + testing::ValuesIn(inputShapes_Dynmic_ZeroDim)), + testing::Values(emptyCPUSpec), + testing::ValuesIn(fusingParamsSet), + testing::ValuesIn(additionalConfig())); + +const auto params_DimZero_Compare_fusing = testing::Combine( + testing::Combine( + testing::ValuesIn(axesZeroDimFusing), + testing::Values(ov::test::utils::OpType::VECTOR), + testing::Values(true), + testing::ValuesIn(reductionTypesCompare()), + testing::ValuesIn(inpOutPrc()), + testing::Values(ElementType::undefined), + testing::Values(ElementType::undefined), + testing::ValuesIn(inputShapes_Dynmic_ZeroDim)), + testing::Values(emptyCPUSpec), + testing::ValuesIn(fusingParamsSet), + testing::ValuesIn(additionalConfigFP32())); + INSTANTIATE_TEST_SUITE_P( smoke_Reduce_OneAxis_fusing_CPU, ReduceCPULayerTest, @@ -641,6 +722,20 @@ INSTANTIATE_TEST_SUITE_P( ReduceCPULayerTest::getTestCaseName ); +INSTANTIATE_TEST_SUITE_P( + smoke_Reduce_DimZero_Arithmetic_fusing_CPU, + ReduceCPULayerTest, + params_DimZero_Arithmetic_fusing, + ReduceCPULayerTest::getTestCaseName +); + +INSTANTIATE_TEST_SUITE_P( + smoke_Reduce_DimZero_Compare_fusing_CPU, + ReduceCPULayerTest, + params_DimZero_Compare_fusing, + ReduceCPULayerTest::getTestCaseName +); + /* ================================ 2.2 Fusion - KeepNoDims ================================ */ const auto params_OneAxis_fusing_KeepNoDims = testing::Combine( testing::Combine( @@ -684,6 +779,34 @@ const auto params_MultiAxis_5D_Hybrid_fusing_KeepNoDims = testing::Combine( testing::ValuesIn(fusingParamsSet_KeepNoDims), testing::ValuesIn(additionalConfigFP32())); +const auto params_DimZero_Arithmetic_fusing_KeepNoDims = testing::Combine( + testing::Combine( + testing::ValuesIn(axesZeroDimFusing), + testing::Values(ov::test::utils::OpType::VECTOR), + testing::Values(false), + testing::ValuesIn(reductionTypesArithmetic()), + testing::ValuesIn(inpOutPrc()), + testing::Values(ElementType::undefined), + testing::Values(ElementType::undefined), + testing::ValuesIn(inputShapes_Dynmic_ZeroDim)), + testing::Values(emptyCPUSpec), + testing::ValuesIn(fusingParamsSet_KeepNoDims), + testing::ValuesIn(additionalConfig())); + +const auto params_DimZero_Compare_fusing_KeepNoDims = testing::Combine( + testing::Combine( + testing::ValuesIn(axesZeroDimFusing), + testing::Values(ov::test::utils::OpType::VECTOR), + testing::Values(false), + testing::ValuesIn(reductionTypesCompare()), + testing::ValuesIn(inpOutPrc()), + testing::Values(ElementType::undefined), + testing::Values(ElementType::undefined), + testing::ValuesIn(inputShapes_Dynmic_ZeroDim)), + testing::Values(emptyCPUSpec), + testing::ValuesIn(fusingParamsSet_KeepNoDims), + testing::ValuesIn(additionalConfigFP32())); + INSTANTIATE_TEST_SUITE_P( smoke_Reduce_OneAxis_fusing_KeepNoDims_CPU, ReduceCPULayerTest, @@ -705,47 +828,17 @@ INSTANTIATE_TEST_SUITE_P( ReduceCPULayerTest::getTestCaseName ); - -/* ================================ 2.3 Empty dims ================================ */ -const auto params_MultiAxis_4D_dynamic_with_zero = testing::Combine( - testing::Combine( - testing::ValuesIn(axesND()), - testing::Values(ov::test::utils::OpType::VECTOR), - testing::ValuesIn(keepDims()), - testing::ValuesIn(reductionTypes()), - testing::ValuesIn(inpOutPrc()), - testing::Values(ElementType::undefined), - testing::Values(ElementType::undefined), - testing::ValuesIn(inputShapes_Dynmic_ZeroDim)), - testing::Values(emptyCPUSpec), - testing::Values(emptyFusingSpec), - testing::ValuesIn(additionalConfig())); - -const auto params_MultiAxis_4D_dynamic_with_zero_fusing = testing::Combine( - testing::Combine( - testing::ValuesIn(axesNDFusing), - testing::Values(ov::test::utils::OpType::VECTOR), - testing::ValuesIn(keepDims()), - testing::ValuesIn(reductionTypes()), - testing::ValuesIn(inpOutPrc()), - testing::Values(ElementType::undefined), - testing::Values(ElementType::undefined), - testing::ValuesIn(inputShapes_Dynmic_ZeroDim)), - testing::Values(emptyCPUSpec), - testing::Values(fusingSwish), - testing::ValuesIn(additionalConfig())); - INSTANTIATE_TEST_SUITE_P( - smoke_Reduce_MultiAxis_4D_dynamic_with_zero_CPU, + smoke_Reduce_DimZero_Arithmetic_fusing_KeepNoDims_CPU, ReduceCPULayerTest, - params_MultiAxis_4D_dynamic_with_zero, + params_DimZero_Arithmetic_fusing_KeepNoDims, ReduceCPULayerTest::getTestCaseName ); INSTANTIATE_TEST_SUITE_P( - smoke_Reduce_MultiAxis_4D_dynamic_with_zero_fusing_CPU, + smoke_Reduce_DimZero_Comapre_fusing_KeepNoDims_CPU, ReduceCPULayerTest, - params_MultiAxis_4D_dynamic_with_zero_fusing, + params_DimZero_Arithmetic_fusing_KeepNoDims, ReduceCPULayerTest::getTestCaseName );