CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
863 lines
33 KiB
C++
863 lines
33 KiB
C++
// Copyright © Advanced Micro Devices, Inc., or its affiliates.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
#include <gtest/gtest.h>
|
|
#include <hipdnn_data_sdk/utilities/PlatformUtils.hpp>
|
|
#include <hipdnn_frontend/Error.hpp>
|
|
#include <hipdnn_frontend/Utilities.hpp>
|
|
#include <hipdnn_frontend/node/detail/Utilities.hpp>
|
|
#include <hipdnn_test_sdk/utilities/ScopedEnvironmentVariableSetter.hpp>
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
using namespace hipdnn_frontend;
|
|
using namespace hipdnn_frontend::graph;
|
|
using namespace hipdnn_frontend::detail;
|
|
using namespace hipdnn_test_sdk::utilities;
|
|
|
|
TEST(TestUtilities, FindCommonShapeValid)
|
|
{
|
|
const std::vector<std::vector<int64_t>> inputShapes = {{1, 2, 3}, {1, 2, 1}, {1, 1, 3}};
|
|
std::vector<int64_t> commonShape;
|
|
|
|
auto error = findCommonShape(inputShapes, commonShape);
|
|
EXPECT_EQ(error.code, ErrorCode::OK);
|
|
EXPECT_EQ(commonShape, (std::vector<int64_t>{1, 2, 3}));
|
|
}
|
|
|
|
TEST(TestUtilities, FindCommonShapeEmptyInput)
|
|
{
|
|
const std::vector<std::vector<int64_t>> inputShapes = {};
|
|
std::vector<int64_t> commonShape;
|
|
|
|
auto error = findCommonShape(inputShapes, commonShape);
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
}
|
|
|
|
TEST(TestUtilities, FindCommonShapeIncompatibleShapes)
|
|
{
|
|
const std::vector<std::vector<int64_t>> inputShapes = {{1, 2, 3}, {1, 2, 4}, {1, 2}};
|
|
std::vector<int64_t> commonShape;
|
|
|
|
auto error = findCommonShape(inputShapes, commonShape);
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
}
|
|
|
|
TEST(TestUtilities, FindCommonShapeSingleInput)
|
|
{
|
|
const std::vector<std::vector<int64_t>> inputShapes = {{1, 2, 3}};
|
|
std::vector<int64_t> commonShape;
|
|
|
|
auto error = findCommonShape(inputShapes, commonShape);
|
|
EXPECT_EQ(error.code, ErrorCode::OK);
|
|
EXPECT_EQ(commonShape, (std::vector<int64_t>{1, 2, 3}));
|
|
}
|
|
|
|
// ============================================================================
|
|
// Batch Normalization Validation Tests
|
|
// ============================================================================
|
|
|
|
// Tests for isBatchNormSpatialMode()
|
|
TEST(TestUtilities, IsBatchNormSpatialModeNullTensor)
|
|
{
|
|
const std::shared_ptr<TensorAttributes> nullScale = nullptr;
|
|
EXPECT_TRUE(isBatchNormSpatialMode(nullScale));
|
|
}
|
|
|
|
TEST(TestUtilities, IsBatchNormSpatialModeUninitializedDims)
|
|
{
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
// Empty dimensions - should default to spatial mode
|
|
EXPECT_TRUE(isBatchNormSpatialMode(scale));
|
|
}
|
|
|
|
TEST(TestUtilities, IsBatchNormSpatialModeDimsSizeLessThanTwo)
|
|
{
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({32}); // Only 1 dimension
|
|
EXPECT_TRUE(isBatchNormSpatialMode(scale));
|
|
}
|
|
|
|
TEST(TestUtilities, IsBatchNormSpatialModeSpatialMode2D)
|
|
{
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 32, 1, 1});
|
|
EXPECT_TRUE(isBatchNormSpatialMode(scale));
|
|
}
|
|
|
|
TEST(TestUtilities, IsBatchNormSpatialModeSpatialMode2DLargeChannels)
|
|
{
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 256, 1, 1});
|
|
EXPECT_TRUE(isBatchNormSpatialMode(scale));
|
|
}
|
|
|
|
TEST(TestUtilities, IsBatchNormSpatialModeSpatialMode3D)
|
|
{
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 32, 1, 1, 1});
|
|
EXPECT_TRUE(isBatchNormSpatialMode(scale));
|
|
}
|
|
|
|
TEST(TestUtilities, IsBatchNormSpatialModeSpatialMode3DLargeChannels)
|
|
{
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 256, 1, 1, 1});
|
|
EXPECT_TRUE(isBatchNormSpatialMode(scale));
|
|
}
|
|
|
|
TEST(TestUtilities, IsBatchNormSpatialModePerActivation2DHGreaterThanOne)
|
|
{
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 32, 14, 14}); // H and W > 1
|
|
EXPECT_FALSE(isBatchNormSpatialMode(scale));
|
|
}
|
|
|
|
TEST(TestUtilities, IsBatchNormSpatialModePerActivation2DWGreaterThanOne)
|
|
{
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 32, 1, 14}); // Only W > 1
|
|
EXPECT_FALSE(isBatchNormSpatialMode(scale));
|
|
}
|
|
|
|
TEST(TestUtilities, IsBatchNormSpatialModePerActivation2DHOnlyGreaterThanOne)
|
|
{
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 32, 14, 1}); // Only H > 1
|
|
EXPECT_FALSE(isBatchNormSpatialMode(scale));
|
|
}
|
|
|
|
TEST(TestUtilities, IsBatchNormSpatialModePerActivation3DDGreaterThanOne)
|
|
{
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 32, 2, 1, 1}); // D > 1
|
|
EXPECT_FALSE(isBatchNormSpatialMode(scale));
|
|
}
|
|
|
|
TEST(TestUtilities, IsBatchNormSpatialModePerActivation3DMultipleSpatialDims)
|
|
{
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 32, 1, 14, 14}); // H and W > 1
|
|
EXPECT_FALSE(isBatchNormSpatialMode(scale));
|
|
}
|
|
|
|
// Tests for validateBatchNormTrainingSpatialDimensions()
|
|
TEST(TestUtilities, ValidateBNTrainingSpatialDimsNullXTensor)
|
|
{
|
|
const std::shared_ptr<TensorAttributes> nullX = nullptr;
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 3, 1, 1});
|
|
|
|
auto error = validateBatchNormTrainingSpatialDimensions(nullX, scale);
|
|
EXPECT_EQ(error.code, ErrorCode::ATTRIBUTE_NOT_SET);
|
|
EXPECT_TRUE(error.get_message().find("Input tensor is not set") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateBNTrainingSpatialDimsNullScaleTensor)
|
|
{
|
|
auto x = std::make_shared<TensorAttributes>();
|
|
x->set_dim({2, 3, 14, 14});
|
|
const std::shared_ptr<TensorAttributes> nullScale = nullptr;
|
|
|
|
auto error = validateBatchNormTrainingSpatialDimensions(x, nullScale);
|
|
EXPECT_EQ(error.code, ErrorCode::ATTRIBUTE_NOT_SET);
|
|
EXPECT_TRUE(error.get_message().find("Scale tensor is not set") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateBNTrainingSpatialDimsXDimsLessThanTwo)
|
|
{
|
|
auto x = std::make_shared<TensorAttributes>();
|
|
x->set_dim({32}); // Only 1 dimension
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 32, 1, 1});
|
|
|
|
auto error = validateBatchNormTrainingSpatialDimensions(x, scale);
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("Input tensor must have at least 2 dimensions")
|
|
!= std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateBNTrainingSpatialDimsValid2DLargeNHW)
|
|
{
|
|
auto x = std::make_shared<TensorAttributes>();
|
|
x->set_dim({2, 3, 2, 2}); // N*H*W = 2*2*2 = 8
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 3, 1, 1});
|
|
|
|
auto error = validateBatchNormTrainingSpatialDimensions(x, scale);
|
|
EXPECT_EQ(error.code, ErrorCode::OK);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateBNTrainingSpatialDimsValid2DEdgeCase)
|
|
{
|
|
auto x = std::make_shared<TensorAttributes>();
|
|
x->set_dim({1, 3, 1, 2}); // N*H*W = 1*1*2 = 2 (just above threshold)
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 3, 1, 1});
|
|
|
|
auto error = validateBatchNormTrainingSpatialDimensions(x, scale);
|
|
EXPECT_EQ(error.code, ErrorCode::OK);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateBNTrainingSpatialDimsValid2DTypicalCase)
|
|
{
|
|
auto x = std::make_shared<TensorAttributes>();
|
|
x->set_dim({8, 32, 7, 7}); // N*H*W = 8*7*7 = 392
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 32, 1, 1});
|
|
|
|
auto error = validateBatchNormTrainingSpatialDimensions(x, scale);
|
|
EXPECT_EQ(error.code, ErrorCode::OK);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateBNTrainingSpatialDimsValid3D)
|
|
{
|
|
auto x = std::make_shared<TensorAttributes>();
|
|
x->set_dim({2, 3, 2, 2, 2}); // N*D*H*W = 2*2*2*2 = 16
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 3, 1, 1, 1});
|
|
|
|
auto error = validateBatchNormTrainingSpatialDimensions(x, scale);
|
|
EXPECT_EQ(error.code, ErrorCode::OK);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateBNTrainingSpatialDimsInvalidSingleElement)
|
|
{
|
|
auto x = std::make_shared<TensorAttributes>();
|
|
x->set_dim({1, 256, 1, 1}); // N*H*W = 1*1*1 = 1 (invalid!)
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 256, 1, 1});
|
|
|
|
auto error = validateBatchNormTrainingSpatialDimensions(x, scale);
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("N * spatial_dimensions must be > 1")
|
|
!= std::string::npos);
|
|
EXPECT_TRUE(error.get_message().find("N=1") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateBNTrainingSpatialDimsInvalidSingleElement3D)
|
|
{
|
|
auto x = std::make_shared<TensorAttributes>();
|
|
x->set_dim({1, 64, 1, 1, 1}); // N*D*H*W = 1*1*1*1 = 1 (invalid!)
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 64, 1, 1, 1});
|
|
|
|
auto error = validateBatchNormTrainingSpatialDimensions(x, scale);
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("N * spatial_dimensions must be > 1")
|
|
!= std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateBNTrainingSpatialDimsPerActivationNotSupported)
|
|
{
|
|
auto x = std::make_shared<TensorAttributes>();
|
|
x->set_dim({2, 3, 14, 14});
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 3, 14, 14}); // Per-activation mode (H, W match input)
|
|
|
|
auto error = validateBatchNormTrainingSpatialDimensions(x, scale);
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("per-activation mode is not currently supported")
|
|
!= std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateBNTrainingSpatialDimsCustomOperationName)
|
|
{
|
|
auto x = std::make_shared<TensorAttributes>();
|
|
x->set_dim({1, 32, 1, 1}); // Invalid: N*H*W = 1
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 32, 1, 1});
|
|
|
|
auto error
|
|
= validateBatchNormTrainingSpatialDimensions(x, scale, "Batch normalization backward");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("Batch normalization backward") != std::string::npos);
|
|
}
|
|
|
|
// Layout-specific tests to ensure validation is layout-agnostic
|
|
TEST(TestUtilities, ValidateBNTrainingSpatialDimsNhwc)
|
|
{
|
|
auto x = std::make_shared<TensorAttributes>();
|
|
x->set_dim({2, 3, 14, 14}); // NCHW: N*H*W = 2*14*14 = 392
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 3, 1, 1}); // Always channel-first
|
|
|
|
auto error = validateBatchNormTrainingSpatialDimensions(x, scale);
|
|
EXPECT_EQ(error.code, ErrorCode::OK);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateBNTrainingSpatialDimsNhwcInvalid)
|
|
{
|
|
auto x = std::make_shared<TensorAttributes>();
|
|
x->set_dim({1, 256, 1, 1}); // NCHW: N*H*W = 1*1*1 = 1 (invalid!)
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 256, 1, 1});
|
|
|
|
auto error = validateBatchNormTrainingSpatialDimensions(x, scale);
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("N * spatial_dimensions must be > 1")
|
|
!= std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateBNTrainingSpatialDimsNDhwc)
|
|
{
|
|
auto x = std::make_shared<TensorAttributes>();
|
|
x->set_dim({2, 3, 2, 2, 2}); // NCDHW: N*D*H*W = 2*2*2*2 = 16
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 3, 1, 1, 1});
|
|
|
|
auto error = validateBatchNormTrainingSpatialDimensions(x, scale);
|
|
EXPECT_EQ(error.code, ErrorCode::OK);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateBNTrainingSpatialDimsNDhwcInvalid)
|
|
{
|
|
auto x = std::make_shared<TensorAttributes>();
|
|
x->set_dim({1, 256, 1, 1, 1}); // NCDHW: N*D*H*W = 1*1*1*1 = 1 (invalid!)
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 256, 1, 1, 1});
|
|
|
|
auto error = validateBatchNormTrainingSpatialDimensions(x, scale);
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("N * spatial_dimensions must be > 1")
|
|
!= std::string::npos);
|
|
}
|
|
|
|
// ============================================================================
|
|
// validateMinimumTensorDimensions Tests
|
|
// ============================================================================
|
|
|
|
TEST(TestUtilities, ValidateMinimumTensorDimensionsNullTensor)
|
|
{
|
|
const std::shared_ptr<TensorAttributes> nullTensor = nullptr;
|
|
auto error = validateMinimumTensorDimensions(nullTensor, 2, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::ATTRIBUTE_NOT_SET);
|
|
EXPECT_TRUE(error.get_message().find("TestTensor is not set") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateMinimumTensorDimensionsEmptyDims)
|
|
{
|
|
auto tensor = std::make_shared<TensorAttributes>();
|
|
// Empty dimensions
|
|
auto error = validateMinimumTensorDimensions(tensor, 2, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("must have at least 2 dimensions") != std::string::npos);
|
|
EXPECT_TRUE(error.get_message().find("but has 0") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateMinimumTensorDimensionsValid2DMeetsRequirement)
|
|
{
|
|
auto tensor = std::make_shared<TensorAttributes>();
|
|
tensor->set_dim({2, 64});
|
|
auto error = validateMinimumTensorDimensions(tensor, 2, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::OK);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateMinimumTensorDimensionsValid4DExceedsRequirement)
|
|
{
|
|
auto tensor = std::make_shared<TensorAttributes>();
|
|
tensor->set_dim({2, 64, 32, 32});
|
|
auto error = validateMinimumTensorDimensions(tensor, 2, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::OK);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateMinimumTensorDimensionsInvalid1DRequires2D)
|
|
{
|
|
auto tensor = std::make_shared<TensorAttributes>();
|
|
tensor->set_dim({64});
|
|
auto error = validateMinimumTensorDimensions(tensor, 2, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("must have at least 2 dimensions") != std::string::npos);
|
|
EXPECT_TRUE(error.get_message().find("but has 1") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateMinimumTensorDimensionsInvalid2DRequires4D)
|
|
{
|
|
auto tensor = std::make_shared<TensorAttributes>();
|
|
tensor->set_dim({2, 64});
|
|
auto error = validateMinimumTensorDimensions(tensor, 4, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("must have at least 4 dimensions") != std::string::npos);
|
|
EXPECT_TRUE(error.get_message().find("but has 2") != std::string::npos);
|
|
}
|
|
|
|
// ============================================================================
|
|
// validateTensorShapesMatch Tests
|
|
// ============================================================================
|
|
|
|
TEST(TestUtilities, ValidateTensorShapesMatchNullTensor1)
|
|
{
|
|
const std::shared_ptr<TensorAttributes> nullTensor = nullptr;
|
|
auto tensor2 = std::make_shared<TensorAttributes>();
|
|
tensor2->set_dim({2, 64});
|
|
|
|
auto error = validateTensorShapesMatch(nullTensor, tensor2, "Tensor1", "Tensor2");
|
|
EXPECT_EQ(error.code, ErrorCode::ATTRIBUTE_NOT_SET);
|
|
EXPECT_TRUE(error.get_message().find("Tensor1 is not set") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateTensorShapesMatchNullTensor2)
|
|
{
|
|
auto tensor1 = std::make_shared<TensorAttributes>();
|
|
tensor1->set_dim({2, 64});
|
|
const std::shared_ptr<TensorAttributes> nullTensor = nullptr;
|
|
|
|
auto error = validateTensorShapesMatch(tensor1, nullTensor, "Tensor1", "Tensor2");
|
|
EXPECT_EQ(error.code, ErrorCode::ATTRIBUTE_NOT_SET);
|
|
EXPECT_TRUE(error.get_message().find("Tensor2 is not set") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateTensorShapesMatchEmptyDims1)
|
|
{
|
|
auto tensor1 = std::make_shared<TensorAttributes>();
|
|
auto tensor2 = std::make_shared<TensorAttributes>();
|
|
tensor2->set_dim({2, 64});
|
|
|
|
auto error = validateTensorShapesMatch(tensor1, tensor2, "Tensor1", "Tensor2");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("must have the same number of dimensions")
|
|
!= std::string::npos);
|
|
EXPECT_TRUE(error.get_message().find("0 vs 2") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateTensorShapesMatchEmptyDims2)
|
|
{
|
|
auto tensor1 = std::make_shared<TensorAttributes>();
|
|
tensor1->set_dim({2, 64});
|
|
auto tensor2 = std::make_shared<TensorAttributes>();
|
|
|
|
auto error = validateTensorShapesMatch(tensor1, tensor2, "Tensor1", "Tensor2");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("must have the same number of dimensions")
|
|
!= std::string::npos);
|
|
EXPECT_TRUE(error.get_message().find("2 vs 0") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateTensorShapesMatchValid)
|
|
{
|
|
auto tensor1 = std::make_shared<TensorAttributes>();
|
|
tensor1->set_dim({2, 64, 32, 32});
|
|
auto tensor2 = std::make_shared<TensorAttributes>();
|
|
tensor2->set_dim({2, 64, 32, 32});
|
|
|
|
auto error = validateTensorShapesMatch(tensor1, tensor2, "Tensor1", "Tensor2");
|
|
EXPECT_EQ(error.code, ErrorCode::OK);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateTensorShapesMatchDifferentDimCount)
|
|
{
|
|
auto tensor1 = std::make_shared<TensorAttributes>();
|
|
tensor1->set_dim({2, 64, 32, 32});
|
|
auto tensor2 = std::make_shared<TensorAttributes>();
|
|
tensor2->set_dim({2, 64});
|
|
|
|
auto error = validateTensorShapesMatch(tensor1, tensor2, "Tensor1", "Tensor2");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("must have the same number of dimensions")
|
|
!= std::string::npos);
|
|
EXPECT_TRUE(error.get_message().find("4 vs 2") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateTensorShapesMatchDifferentDimValues)
|
|
{
|
|
auto tensor1 = std::make_shared<TensorAttributes>();
|
|
tensor1->set_dim({2, 64, 32, 32});
|
|
auto tensor2 = std::make_shared<TensorAttributes>();
|
|
tensor2->set_dim({2, 64, 16, 16});
|
|
|
|
auto error = validateTensorShapesMatch(tensor1, tensor2, "Tensor1", "Tensor2");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("dimension mismatch") != std::string::npos);
|
|
}
|
|
|
|
// ============================================================================
|
|
// validateChannelOnlyTensorShape Tests
|
|
// ============================================================================
|
|
|
|
TEST(TestUtilities, ValidateChannelOnlyTensorShapeNullTensor)
|
|
{
|
|
const std::shared_ptr<TensorAttributes> nullTensor = nullptr;
|
|
auto error = validateChannelOnlyTensorShape(nullTensor, 64, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::ATTRIBUTE_NOT_SET);
|
|
EXPECT_TRUE(error.get_message().find("TestTensor is not set") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateChannelOnlyTensorShapeEmptyDims)
|
|
{
|
|
auto tensor = std::make_shared<TensorAttributes>();
|
|
auto error = validateChannelOnlyTensorShape(tensor, 64, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("must have at least 2 dimensions") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateChannelOnlyTensorShapeValid4D)
|
|
{
|
|
auto tensor = std::make_shared<TensorAttributes>();
|
|
tensor->set_dim({1, 64, 1, 1});
|
|
auto error = validateChannelOnlyTensorShape(tensor, 64, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::OK);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateChannelOnlyTensorShapeValid5D)
|
|
{
|
|
auto tensor = std::make_shared<TensorAttributes>();
|
|
tensor->set_dim({1, 256, 1, 1, 1});
|
|
auto error = validateChannelOnlyTensorShape(tensor, 256, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::OK);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateChannelOnlyTensorShapeInvalidBatchDim)
|
|
{
|
|
auto tensor = std::make_shared<TensorAttributes>();
|
|
tensor->set_dim({2, 64, 1, 1}); // Batch should be 1
|
|
auto error = validateChannelOnlyTensorShape(tensor, 64, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("batch dimension") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateChannelOnlyTensorShapeInvalidChannelDim)
|
|
{
|
|
auto tensor = std::make_shared<TensorAttributes>();
|
|
tensor->set_dim({1, 128, 1, 1}); // Channel should be 64
|
|
auto error = validateChannelOnlyTensorShape(tensor, 64, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("channel dimension") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateChannelOnlyTensorShapeInvalidSpatialDim)
|
|
{
|
|
auto tensor = std::make_shared<TensorAttributes>();
|
|
tensor->set_dim({1, 64, 32, 32}); // Spatial should be 1
|
|
auto error = validateChannelOnlyTensorShape(tensor, 64, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("spatial dimension") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateChannelOnlyTensorShapeInvalidLessThan2D)
|
|
{
|
|
auto tensor = std::make_shared<TensorAttributes>();
|
|
tensor->set_dim({64}); // Only 1D
|
|
auto error = validateChannelOnlyTensorShape(tensor, 64, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("must have at least 2 dimensions") != std::string::npos);
|
|
}
|
|
|
|
// ============================================================================
|
|
// validateScaleNormalizedShape Tests
|
|
// ============================================================================
|
|
|
|
TEST(TestUtilities, ValidateScaleNormalizedShapeFullRank4)
|
|
{
|
|
auto input = std::make_shared<TensorAttributes>();
|
|
input->set_dim({1, 2, 3, 3});
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 2, 3, 3});
|
|
auto error = validateScaleNormalizedShape(scale, input, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::OK);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScaleNormalizedShapeTrailingHW)
|
|
{
|
|
auto input = std::make_shared<TensorAttributes>();
|
|
input->set_dim({1, 2, 3, 3});
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 1, 3, 3});
|
|
auto error = validateScaleNormalizedShape(scale, input, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::OK);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScaleNormalizedShapeTrailingW)
|
|
{
|
|
auto input = std::make_shared<TensorAttributes>();
|
|
input->set_dim({1, 2, 3, 3});
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 1, 1, 3});
|
|
auto error = validateScaleNormalizedShape(scale, input, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::OK);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScaleNormalizedShapeRank3Full)
|
|
{
|
|
auto input = std::make_shared<TensorAttributes>();
|
|
input->set_dim({1, 4, 8});
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 4, 8});
|
|
auto error = validateScaleNormalizedShape(scale, input, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::OK);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScaleNormalizedShapeRank3TrailingW)
|
|
{
|
|
auto input = std::make_shared<TensorAttributes>();
|
|
input->set_dim({1, 4, 8});
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 1, 8});
|
|
auto error = validateScaleNormalizedShape(scale, input, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::OK);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScaleNormalizedShapeRank5TrailingHW)
|
|
{
|
|
auto input = std::make_shared<TensorAttributes>();
|
|
input->set_dim({1, 2, 2, 3, 3});
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 1, 1, 3, 3});
|
|
auto error = validateScaleNormalizedShape(scale, input, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::OK);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScaleNormalizedShapeRejectsPerChannelCanonical)
|
|
{
|
|
auto input = std::make_shared<TensorAttributes>();
|
|
input->set_dim({1, 2, 3, 3});
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 2, 1, 1});
|
|
auto error = validateScaleNormalizedShape(scale, input, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("no trailing dims matching input") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScaleNormalizedShapeRejectsTrailingOneAfterNonOne)
|
|
{
|
|
auto input = std::make_shared<TensorAttributes>();
|
|
input->set_dim({1, 2, 3, 3});
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 2, 3, 1});
|
|
auto error = validateScaleNormalizedShape(scale, input, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("no trailing dims matching input") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScaleNormalizedShapeRejectsOneGapInMiddle)
|
|
{
|
|
auto input = std::make_shared<TensorAttributes>();
|
|
input->set_dim({1, 2, 3, 3});
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 2, 1, 3});
|
|
auto error = validateScaleNormalizedShape(scale, input, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("leading region before normalized shape")
|
|
!= std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScaleNormalizedShapeRejectsNonTrailingMiddleDim)
|
|
{
|
|
auto input = std::make_shared<TensorAttributes>();
|
|
input->set_dim({1, 2, 3, 3});
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 1, 3, 1});
|
|
auto error = validateScaleNormalizedShape(scale, input, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("no trailing dims matching input") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScaleNormalizedShapeRejectsAllOnes)
|
|
{
|
|
auto input = std::make_shared<TensorAttributes>();
|
|
input->set_dim({1, 2, 3, 3});
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 1, 1, 1});
|
|
auto error = validateScaleNormalizedShape(scale, input, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("no trailing dims matching input") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScaleNormalizedShapeAcceptsAllOnesRank4)
|
|
{
|
|
auto input = std::make_shared<TensorAttributes>();
|
|
input->set_dim({1, 1, 1, 1});
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 1, 1, 1});
|
|
auto error = validateScaleNormalizedShape(scale, input, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::OK);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScaleNormalizedShapeAcceptsAllOnesInputRank4WithBatch)
|
|
{
|
|
auto input = std::make_shared<TensorAttributes>();
|
|
input->set_dim({2, 1, 1, 1});
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 1, 1, 1});
|
|
auto error = validateScaleNormalizedShape(scale, input, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::OK);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScaleNormalizedShapeAcceptsAllOnesInputRank3)
|
|
{
|
|
auto input = std::make_shared<TensorAttributes>();
|
|
input->set_dim({3, 1, 1});
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 1, 1});
|
|
auto error = validateScaleNormalizedShape(scale, input, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::OK);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScaleNormalizedShapeRejectsAllOnesScaleWithTrailingNonOneInput)
|
|
{
|
|
auto input = std::make_shared<TensorAttributes>();
|
|
input->set_dim({2, 1, 1, 4});
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 1, 1, 1});
|
|
auto error = validateScaleNormalizedShape(scale, input, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("no trailing dims matching input") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScaleNormalizedShapeRejectsScaleRankGreaterThanInput)
|
|
{
|
|
auto input = std::make_shared<TensorAttributes>();
|
|
input->set_dim({1, 2, 3, 3});
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 1, 2, 3, 3});
|
|
auto error = validateScaleNormalizedShape(scale, input, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("must match input rank") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScaleNormalizedShapeRejectsRank3Rows)
|
|
{
|
|
auto input = std::make_shared<TensorAttributes>();
|
|
input->set_dim({1, 6, 3});
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 6, 1});
|
|
auto error = validateScaleNormalizedShape(scale, input, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("no trailing dims matching input") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScaleNormalizedShapeRejectsRank5Gap)
|
|
{
|
|
auto input = std::make_shared<TensorAttributes>();
|
|
input->set_dim({1, 2, 2, 3, 3});
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 2, 1, 3, 3});
|
|
auto error = validateScaleNormalizedShape(scale, input, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("leading region before normalized shape")
|
|
!= std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScaleNormalizedShapeRejectsBatchNotOne)
|
|
{
|
|
auto input = std::make_shared<TensorAttributes>();
|
|
input->set_dim({2, 2, 3, 3});
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({2, 2, 3, 3});
|
|
auto error = validateScaleNormalizedShape(scale, input, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("batch dimension (index 0) must be 1")
|
|
!= std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScaleNormalizedShapeRejectsMismatchedNonOneDim)
|
|
{
|
|
auto input = std::make_shared<TensorAttributes>();
|
|
input->set_dim({1, 2, 3, 3});
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 5, 3, 3});
|
|
auto error = validateScaleNormalizedShape(scale, input, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("leading region before normalized shape")
|
|
!= std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScaleNormalizedShapeRejectsRankMismatch)
|
|
{
|
|
auto input = std::make_shared<TensorAttributes>();
|
|
input->set_dim({1, 2, 3, 3});
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 2, 3});
|
|
auto error = validateScaleNormalizedShape(scale, input, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("must match input rank") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScaleNormalizedShapeRejectsNullScale)
|
|
{
|
|
auto input = std::make_shared<TensorAttributes>();
|
|
input->set_dim({1, 2, 3, 3});
|
|
const std::shared_ptr<TensorAttributes> nullScale = nullptr;
|
|
auto error = validateScaleNormalizedShape(nullScale, input, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::ATTRIBUTE_NOT_SET);
|
|
EXPECT_TRUE(error.get_message().find("is not set") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScaleNormalizedShapeRejectsNullInput)
|
|
{
|
|
auto scale = std::make_shared<TensorAttributes>();
|
|
scale->set_dim({1, 2, 3, 3});
|
|
const std::shared_ptr<TensorAttributes> nullInput = nullptr;
|
|
auto error = validateScaleNormalizedShape(scale, nullInput, "TestTensor");
|
|
EXPECT_EQ(error.code, ErrorCode::ATTRIBUTE_NOT_SET);
|
|
EXPECT_TRUE(error.get_message().find("is not set") != std::string::npos);
|
|
}
|
|
|
|
// ============================================================================
|
|
// validateScalarParameter Tests
|
|
// ============================================================================
|
|
|
|
TEST(TestUtilities, ValidateScalarParameterNullTensor)
|
|
{
|
|
const std::shared_ptr<TensorAttributes> nullParam = nullptr;
|
|
auto error = validateScalarParameter(nullParam, "TestParameter");
|
|
EXPECT_EQ(error.code, ErrorCode::ATTRIBUTE_NOT_SET);
|
|
EXPECT_TRUE(error.get_message().find("TestParameter parameter is not set")
|
|
!= std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScalarParameterEmptyDims)
|
|
{
|
|
auto param = std::make_shared<TensorAttributes>();
|
|
auto error = validateScalarParameter(param, "TestParameter");
|
|
EXPECT_EQ(error.code, ErrorCode::ATTRIBUTE_NOT_SET);
|
|
EXPECT_TRUE(error.get_message().find("dimensions are not set") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScalarParameterValidSingleElement1D)
|
|
{
|
|
auto param = std::make_shared<TensorAttributes>();
|
|
param->set_dim({1});
|
|
param->set_value(1.0f);
|
|
auto error = validateScalarParameter(param, "TestParameter");
|
|
EXPECT_EQ(error.code, ErrorCode::OK);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScalarParameterValidSingleElement4D)
|
|
{
|
|
auto param = std::make_shared<TensorAttributes>();
|
|
param->set_dim({1, 1, 1, 1});
|
|
param->set_value(1.0f);
|
|
auto error = validateScalarParameter(param, "TestParameter");
|
|
EXPECT_EQ(error.code, ErrorCode::OK);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScalarParameterInvalidNotPassByValue)
|
|
{
|
|
auto param = std::make_shared<TensorAttributes>();
|
|
param->set_dim({1});
|
|
// No value set
|
|
auto error = validateScalarParameter(param, "TestParameter");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("must be a pass-by-value tensor") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScalarParameterInvalidNonScalar)
|
|
{
|
|
auto param = std::make_shared<TensorAttributes>();
|
|
param->set_dim({2, 3});
|
|
auto error = validateScalarParameter(param, "TestParameter");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("must be a scalar") != std::string::npos);
|
|
EXPECT_TRUE(error.get_message().find("but has 6 elements") != std::string::npos);
|
|
}
|
|
|
|
TEST(TestUtilities, ValidateScalarParameterInvalidMultipleElements)
|
|
{
|
|
auto param = std::make_shared<TensorAttributes>();
|
|
param->set_dim({1, 64, 1, 1});
|
|
auto error = validateScalarParameter(param, "TestParameter");
|
|
EXPECT_EQ(error.code, ErrorCode::INVALID_VALUE);
|
|
EXPECT_TRUE(error.get_message().find("must be a scalar") != std::string::npos);
|
|
EXPECT_TRUE(error.get_message().find("but has 64 elements") != std::string::npos);
|
|
}
|