From 8061fc459836d0fb37240cfa475f91565625483d Mon Sep 17 00:00:00 2001 From: Denes Tarjan Date: Mon, 25 Mar 2024 11:46:00 +0100 Subject: [PATCH] [test] Add various padding tests to cover all branches in types.h --- test/api/test_merge.cpp | 74 ++++++++++++++++++++++++++---- test/api/test_rgb_and_gray.cpp | 21 ++++++--- test/api/test_saturating_add.cpp | 12 +++++ test/api/test_saturating_sub.cpp | 12 +++++ test/api/test_scale.cpp | 37 ++++++++++----- test/api/test_split.cpp | 59 ++++++++++++++++++++---- test/api/test_threshold_binary.cpp | 8 ++++ test/framework/operation.h | 53 +++++++++++++++------ 8 files changed, 225 insertions(+), 51 deletions(-) diff --git a/test/api/test_merge.cpp b/test/api/test_merge.cpp index 8334cc108..1fcbdbf8a 100644 --- a/test/api/test_merge.cpp +++ b/test/api/test_merge.cpp @@ -16,8 +16,13 @@ class MergeTest final { using ArrayType = test::Array2D; // Sets the number of padding bytes at the end of rows. - MergeTest& with_padding(size_t padding) { - padding_ = padding; + MergeTest& with_paddings(std::initializer_list inputs_padding, + size_t output_padding) { + output_padding_ = output_padding; + size_t i = 0; + for (size_t p : inputs_padding) { + inputs_padding_[i++] = p; + } return *this; } @@ -32,13 +37,13 @@ class MergeTest final { // Create input and output arrays std::array inputs; for (size_t i = 0; i < Channels; ++i) { - inputs[i] = ArrayType{input_width, height, padding_}; + inputs[i] = ArrayType{input_width, height, inputs_padding_[i]}; inputs[i].fill(ElementType{0}); } - ArrayType expected_output{output_width, height, padding_}; + ArrayType expected_output{output_width, height, output_padding_}; expected_output.fill(ElementType{0}); - ArrayType actual_output{output_width, height, padding_}; + ArrayType actual_output{output_width, height, output_padding_}; // Prefill actual_outputs with a different value than expected actual_output.fill(ElementType{1}); @@ -89,7 +94,8 @@ class MergeTest final { private: // Number of padding bytes at the end of rows. - size_t padding_{0}; + std::array inputs_padding_; + size_t output_padding_; }; template @@ -122,17 +128,67 @@ TYPED_TEST_SUITE(Merge, ElementTypes); TYPED_TEST(Merge, TwoChannels) { MergeTest().test(); - MergeTest().with_padding(test::Options::vector_length()).test(); + MergeTest().with_paddings({0, 0}, 1).test(); + MergeTest().with_paddings({0, 1}, 0).test(); + MergeTest().with_paddings({0, 1}, 1).test(); + MergeTest().with_paddings({1, 0}, 0).test(); + MergeTest().with_paddings({1, 0}, 1).test(); + MergeTest().with_paddings({1, 1}, 0).test(); + MergeTest().with_paddings({1, 1}, 1).test(); } TYPED_TEST(Merge, ThreeChannels) { MergeTest().test(); - MergeTest().with_padding(test::Options::vector_length()).test(); + MergeTest().with_paddings({0, 0, 0}, 1).test(); + MergeTest().with_paddings({0, 0, 1}, 0).test(); + MergeTest().with_paddings({0, 0, 1}, 1).test(); + MergeTest().with_paddings({0, 1, 0}, 0).test(); + MergeTest().with_paddings({0, 1, 0}, 1).test(); + MergeTest().with_paddings({0, 1, 1}, 0).test(); + MergeTest().with_paddings({0, 1, 1}, 1).test(); + MergeTest().with_paddings({1, 0, 0}, 0).test(); + MergeTest().with_paddings({1, 0, 0}, 1).test(); + MergeTest().with_paddings({1, 0, 1}, 0).test(); + MergeTest().with_paddings({1, 0, 1}, 1).test(); + MergeTest().with_paddings({1, 1, 0}, 0).test(); + MergeTest().with_paddings({1, 1, 0}, 1).test(); + MergeTest().with_paddings({1, 1, 1}, 0).test(); + MergeTest().with_paddings({1, 1, 1}, 1).test(); } TYPED_TEST(Merge, FourChannels) { MergeTest().test(); - MergeTest().with_padding(test::Options::vector_length()).test(); + MergeTest().with_paddings({0, 0, 0, 0}, 1).test(); + MergeTest().with_paddings({0, 0, 0, 1}, 0).test(); + MergeTest().with_paddings({0, 0, 0, 1}, 1).test(); + MergeTest().with_paddings({0, 0, 1, 0}, 0).test(); + MergeTest().with_paddings({0, 0, 1, 0}, 1).test(); + MergeTest().with_paddings({0, 0, 1, 1}, 0).test(); + MergeTest().with_paddings({0, 0, 1, 1}, 1).test(); + MergeTest().with_paddings({0, 1, 0, 0}, 0).test(); + MergeTest().with_paddings({0, 1, 0, 0}, 1).test(); + MergeTest().with_paddings({0, 1, 0, 1}, 0).test(); + MergeTest().with_paddings({0, 1, 0, 1}, 1).test(); + MergeTest().with_paddings({0, 1, 1, 0}, 0).test(); + MergeTest().with_paddings({0, 1, 1, 0}, 1).test(); + MergeTest().with_paddings({0, 1, 1, 1}, 0).test(); + MergeTest().with_paddings({0, 1, 1, 1}, 1).test(); + MergeTest().with_paddings({1, 0, 0, 0}, 0).test(); + MergeTest().with_paddings({1, 0, 0, 0}, 1).test(); + MergeTest().with_paddings({1, 0, 0, 1}, 0).test(); + MergeTest().with_paddings({1, 0, 0, 1}, 1).test(); + MergeTest().with_paddings({1, 0, 1, 0}, 0).test(); + MergeTest().with_paddings({1, 0, 1, 0}, 1).test(); + MergeTest().with_paddings({1, 0, 1, 1}, 0).test(); + MergeTest().with_paddings({1, 0, 1, 1}, 1).test(); + MergeTest().with_paddings({1, 1, 0, 0}, 0).test(); + MergeTest().with_paddings({1, 1, 0, 0}, 1).test(); + MergeTest().with_paddings({1, 1, 0, 1}, 0).test(); + MergeTest().with_paddings({1, 1, 0, 1}, 1).test(); + MergeTest().with_paddings({1, 1, 1, 0}, 0).test(); + MergeTest().with_paddings({1, 1, 1, 0}, 1).test(); + MergeTest().with_paddings({1, 1, 1, 1}, 0).test(); + MergeTest().with_paddings({1, 1, 1, 1}, 1).test(); } TYPED_TEST(Merge, OneChannelOutOfRange) { diff --git a/test/api/test_rgb_and_gray.cpp b/test/api/test_rgb_and_gray.cpp index add41d4a2..d832a5d37 100644 --- a/test/api/test_rgb_and_gray.cpp +++ b/test/api/test_rgb_and_gray.cpp @@ -14,14 +14,20 @@ class GrayTest final { explicit GrayTest(bool hasAlpha) : hasAlpha_(hasAlpha), outChannels_{hasAlpha ? 4U : 3U} {} + // Sets the number of padding bytes at the end of rows. + GrayTest &with_padding(size_t padding) { + padding_ = padding; + return *this; + } + template void execute_test(F impl) { // Set width to be more than vector length, but not quite a multiple of // vector length to force both vector and scalar paths size_t logical_width = 3 * test::Options::vector_lanes() - 1; - test::Array2D source{logical_width, 3}; - test::Array2D actual{logical_width * outChannels_, 3}; - test::Array2D expected{logical_width * outChannels_, 3}; + test::Array2D source{logical_width, 3, padding_}; + test::Array2D actual{logical_width * outChannels_, 3, padding_}; + test::Array2D expected{logical_width * outChannels_, 3, padding_}; source.set(0, 0, {1}); source.set(1, 0, {0xFF}); @@ -66,6 +72,7 @@ class GrayTest final { } } + size_t padding_{0}; bool hasAlpha_; size_t outChannels_; }; @@ -154,13 +161,13 @@ class ColourTest final { }; TEST(GRAY2, RGB) { - GrayTest gray_test(false); - gray_test.execute_test(intrinsiccv_gray_to_rgb_u8); + GrayTest{false}.execute_test(intrinsiccv_gray_to_rgb_u8); + GrayTest{false}.with_padding(1).execute_test(intrinsiccv_gray_to_rgb_u8); } TEST(GRAY2, RGBA) { - GrayTest gray_test(true); - gray_test.execute_test(intrinsiccv_gray_to_rgba_u8); + GrayTest{true}.execute_test(intrinsiccv_gray_to_rgba_u8); + GrayTest{true}.with_padding(1).execute_test(intrinsiccv_gray_to_rgba_u8); } TEST(RGB2, RGB) { diff --git a/test/api/test_saturating_add.cpp b/test/api/test_saturating_add.cpp index 359724475..95053f0c2 100644 --- a/test/api/test_saturating_add.cpp +++ b/test/api/test_saturating_add.cpp @@ -96,6 +96,18 @@ TYPED_TEST(SaturatingAdd, API) { sizeof(TypeParam), dst, sizeof(TypeParam), 1, 1); } +// Tests various padding combinations. +TYPED_TEST(SaturatingAdd, Padding) { + SaturatingAddTest{}.with_paddings({0, 0}, {0}).test(); + SaturatingAddTest{}.with_paddings({0, 0}, {1}).test(); + SaturatingAddTest{}.with_paddings({0, 1}, {0}).test(); + SaturatingAddTest{}.with_paddings({0, 1}, {1}).test(); + SaturatingAddTest{}.with_paddings({1, 0}, {0}).test(); + SaturatingAddTest{}.with_paddings({1, 0}, {1}).test(); + SaturatingAddTest{}.with_paddings({1, 1}, {0}).test(); + SaturatingAddTest{}.with_paddings({1, 1}, {1}).test(); +} + TYPED_TEST(SaturatingAdd, Misalignment) { if (sizeof(TypeParam) == 1) { // misalignment impossible diff --git a/test/api/test_saturating_sub.cpp b/test/api/test_saturating_sub.cpp index df3a1c339..b7b9957cc 100644 --- a/test/api/test_saturating_sub.cpp +++ b/test/api/test_saturating_sub.cpp @@ -98,6 +98,18 @@ TYPED_TEST(SaturatingSub, API) { sizeof(TypeParam), dst, sizeof(TypeParam), 1, 1); } +// Tests various padding combinations. +TYPED_TEST(SaturatingSub, Padding) { + SaturatingSubTest{}.with_paddings({0, 0}, {0}).test(); + SaturatingSubTest{}.with_paddings({0, 0}, {1}).test(); + SaturatingSubTest{}.with_paddings({0, 1}, {0}).test(); + SaturatingSubTest{}.with_paddings({0, 1}, {1}).test(); + SaturatingSubTest{}.with_paddings({1, 0}, {0}).test(); + SaturatingSubTest{}.with_paddings({1, 0}, {1}).test(); + SaturatingSubTest{}.with_paddings({1, 1}, {0}).test(); + SaturatingSubTest{}.with_paddings({1, 1}, {1}).test(); +} + TYPED_TEST(SaturatingSub, Misalignment) { if (sizeof(TypeParam) == 1) { // misalignment impossible diff --git a/test/api/test_scale.cpp b/test/api/test_scale.cpp index a197d3240..da6afd23f 100644 --- a/test/api/test_scale.cpp +++ b/test/api/test_scale.cpp @@ -48,17 +48,13 @@ class ScaleTestBase : public UnaryOperationTest { template class ScaleTestLinearBase { - protected: - static constexpr ElementType min() { - return std::numeric_limits::min(); - } - static constexpr ElementType max() { - return std::numeric_limits::max(); + public: + // Sets the number of padding bytes at the end of rows. + ScaleTestLinearBase& with_padding(size_t padding) { + padding_ = padding; + return *this; } - virtual float scale() = 0; - virtual float shift() = 0; - public: // minimum_size set by caller to trigger the 'big' scale path. void test_scalar(size_t minimum_size = 1) { size_t width = test::Options::vector_length() - 1; @@ -70,6 +66,16 @@ class ScaleTestLinearBase { test_linear(width, minimum_size); } + protected: + static constexpr ElementType min() { + return std::numeric_limits::min(); + } + static constexpr ElementType max() { + return std::numeric_limits::max(); + } + virtual float scale() = 0; + virtual float shift() = 0; + private: class GenerateLinearSeries : public test::Generator { public: @@ -82,14 +88,17 @@ class ScaleTestLinearBase { ElementType counter_; }; // end of class GenerateLinearSeries + // Number of padding bytes at the end of rows. + size_t padding_{0}; + void test_linear(size_t width, size_t minimum_size) { size_t image_size = std::max(minimum_size, static_cast(max() - min())); size_t height = image_size / width + 1; - test::Array2D source(width, height, 1, 1); - test::Array2D expected(width, height, 1, 1); + test::Array2D source(width, height, padding_, 1); + test::Array2D expected(width, height, padding_, 1); test::Array2D actual = - test::Array2D(width, height, 1, 1); + test::Array2D(width, height, padding_, 1); GenerateLinearSeries generator(min()); @@ -326,16 +335,20 @@ TYPED_TEST_SUITE(ScaleTest, ElementTypes); TYPED_TEST(ScaleTest, TestScalar1) { ScaleTestLinear1{}.test_scalar(); + ScaleTestLinear1{}.with_padding(1).test_scalar(); } TYPED_TEST(ScaleTest, TestVector1) { ScaleTestLinear1{}.test_vector(); + ScaleTestLinear1{}.with_padding(1).test_vector(); } TYPED_TEST(ScaleTest, TestScalar1Tbx) { ScaleTestLinear1{}.test_scalar(2500); + ScaleTestLinear1{}.with_padding(1).test_scalar(2500); } TYPED_TEST(ScaleTest, TestVector1Tbx) { ScaleTestLinear1{}.test_vector(2500); + ScaleTestLinear1{}.with_padding(1).test_vector(2500); } TYPED_TEST(ScaleTest, TestScalar2) { diff --git a/test/api/test_split.cpp b/test/api/test_split.cpp index 51c2221b2..e28b9e4ef 100644 --- a/test/api/test_split.cpp +++ b/test/api/test_split.cpp @@ -16,8 +16,13 @@ class SplitTest final { using ArrayType = test::Array2D; // Sets the number of padding bytes at the end of rows. - SplitTest& with_padding(size_t padding) { - padding_ = padding; + SplitTest& with_paddings(size_t input_padding, + std::initializer_list outputs_padding) { + input_padding_ = input_padding; + size_t i = 0; + for (size_t p : outputs_padding) { + outputs_padding_[i++] = p; + } return *this; } @@ -30,15 +35,16 @@ class SplitTest final { size_t height = 2; // Create input and output arrays - ArrayType input{input_width, height, padding_}; + ArrayType input{input_width, height, input_padding_}; input.fill(ElementType{0}); std::array expected_outputs; std::array actual_outputs; for (size_t i = 0; i < Channels; ++i) { - expected_outputs[i] = ArrayType{output_width, height, padding_}; + expected_outputs[i] = + ArrayType{output_width, height, outputs_padding_[i]}; expected_outputs[i].fill(ElementType{0}); - actual_outputs[i] = ArrayType{output_width, height, padding_}; + actual_outputs[i] = ArrayType{output_width, height, outputs_padding_[i]}; // Prefill actual_outputs with a different value than expected actual_outputs[i].fill(ElementType{1}); } @@ -87,7 +93,8 @@ class SplitTest final { private: // Number of padding bytes at the end of rows. - size_t padding_{0}; + size_t input_padding_; + std::array outputs_padding_; }; template @@ -121,17 +128,51 @@ TYPED_TEST_SUITE(Split, ElementTypes); TYPED_TEST(Split, TwoChannels) { SplitTest().test(); - SplitTest().with_padding(test::Options::vector_length()).test(); + SplitTest().with_paddings(0, {0, 1}).test(); + SplitTest().with_paddings(0, {1, 0}).test(); + SplitTest().with_paddings(0, {1, 1}).test(); + SplitTest().with_paddings(1, {0, 0}).test(); + SplitTest().with_paddings(1, {0, 1}).test(); + SplitTest().with_paddings(1, {1, 0}).test(); + SplitTest().with_paddings(1, {1, 1}).test(); } TYPED_TEST(Split, ThreeChannels) { SplitTest().test(); - SplitTest().with_padding(test::Options::vector_length()).test(); + SplitTest().with_paddings(0, {0, 0, 1}).test(); + SplitTest().with_paddings(0, {0, 1, 0}).test(); + SplitTest().with_paddings(0, {0, 1, 1}).test(); + SplitTest().with_paddings(0, {1, 0, 0}).test(); + SplitTest().with_paddings(0, {1, 0, 1}).test(); + SplitTest().with_paddings(0, {1, 1, 0}).test(); + SplitTest().with_paddings(0, {1, 1, 1}).test(); + SplitTest().with_paddings(1, {0, 0, 0}).test(); + SplitTest().with_paddings(1, {0, 0, 1}).test(); + SplitTest().with_paddings(1, {0, 1, 0}).test(); + SplitTest().with_paddings(1, {0, 1, 1}).test(); + SplitTest().with_paddings(1, {1, 0, 0}).test(); + SplitTest().with_paddings(1, {1, 0, 1}).test(); + SplitTest().with_paddings(1, {1, 1, 0}).test(); + SplitTest().with_paddings(1, {1, 1, 1}).test(); } TYPED_TEST(Split, FourChannels) { SplitTest().test(); - SplitTest().with_padding(test::Options::vector_length()).test(); + SplitTest().with_paddings(0, {0, 0, 0, 1}).test(); + SplitTest().with_paddings(0, {0, 0, 1, 0}).test(); + SplitTest().with_paddings(0, {0, 0, 1, 1}).test(); + SplitTest().with_paddings(0, {0, 1, 0, 0}).test(); + SplitTest().with_paddings(0, {0, 1, 0, 1}).test(); + SplitTest().with_paddings(0, {0, 1, 1, 0}).test(); + SplitTest().with_paddings(0, {0, 1, 1, 1}).test(); + SplitTest().with_paddings(1, {1, 0, 0, 0}).test(); + SplitTest().with_paddings(1, {1, 0, 0, 1}).test(); + SplitTest().with_paddings(1, {1, 0, 1, 0}).test(); + SplitTest().with_paddings(1, {1, 0, 1, 1}).test(); + SplitTest().with_paddings(1, {1, 1, 0, 0}).test(); + SplitTest().with_paddings(1, {1, 1, 0, 1}).test(); + SplitTest().with_paddings(1, {1, 1, 1, 0}).test(); + SplitTest().with_paddings(1, {1, 1, 1, 1}).test(); } TYPED_TEST(Split, OneChannelOutOfRange) { diff --git a/test/api/test_threshold_binary.cpp b/test/api/test_threshold_binary.cpp index a645849ef..e790dda05 100644 --- a/test/api/test_threshold_binary.cpp +++ b/test/api/test_threshold_binary.cpp @@ -114,6 +114,14 @@ TYPED_TEST_SUITE(ThresholdBinary, ElementTypes); TYPED_TEST(ThresholdBinary, Test) { ThresholdBinaryTest{}.test(); } +// Tests various padding combinations. +TYPED_TEST(ThresholdBinary, Padding) { + ThresholdBinaryTest{}.with_paddings({0}, {0}).test(); + ThresholdBinaryTest{}.with_paddings({0}, {1}).test(); + ThresholdBinaryTest{}.with_paddings({1}, {0}).test(); + ThresholdBinaryTest{}.with_paddings({1}, {1}).test(); +} + TYPED_TEST(ThresholdBinary, TestMin) { ThresholdBinaryTestMin{}.test(); } diff --git a/test/framework/operation.h b/test/framework/operation.h index c338a79fe..e3235adf3 100644 --- a/test/framework/operation.h +++ b/test/framework/operation.h @@ -24,12 +24,39 @@ class OperationTest { ElementType values[InputsSize + OutputsSize]; }; // end of struct Elements + OperationTest() { + inputs_padding_.fill(0); + outputs_padding_.fill(0); + } + virtual ~OperationTest() = default; - // Sets the number of padding bytes at the end of rows. + // Sets the number of padding bytes at the end of rows, same for all arrays OperationTest& with_padding( size_t padding) { - padding_ = padding; + for (auto& in_padding : inputs_padding_) { + in_padding = padding; + } + + for (auto& out_padding : outputs_padding_) { + out_padding = padding; + } + + return *this; + } + + // Sets the number of padding bytes at the end of rows. + OperationTest& with_paddings( + std::initializer_list inputs_padding, + std::initializer_list outputs_padding) { + size_t i = 0; + for (size_t p : inputs_padding) { + inputs_padding_[i++] = p; + } + size_t j = 0; + for (size_t q : outputs_padding) { + outputs_padding_[j++] = q; + } return *this; } @@ -41,10 +68,10 @@ class OperationTest { } void test() { - for (auto& input : inputs_) { - input = ArrayType{width(), height(), padding()}; - input.fill(0); - ASSERT_TRUE(input.valid()); + for (size_t i = 0; i < inputs_.size(); ++i) { + inputs_[i] = ArrayType{width(), height(), inputs_padding_[i]}; + inputs_[i].fill(0); + ASSERT_TRUE(inputs_[i].valid()); } for (auto& expected : expected_) { @@ -53,10 +80,10 @@ class OperationTest { ASSERT_TRUE(expected.valid()); } - for (auto& actual : actual_) { - actual = ArrayType{width(), height(), padding()}; - actual.fill(42); // fill with any value different than `expected` - ASSERT_TRUE(actual.valid()); + for (size_t i = 0; i < actual_.size(); ++i) { + actual_[i] = ArrayType{width(), height(), outputs_padding_[i]}; + actual_[i].fill(42); // fill with any value different than `expected` + ASSERT_TRUE(actual_[i].valid()); } setup(); @@ -110,9 +137,6 @@ class OperationTest { // Tested number of elements in a row. virtual size_t width() const { return width_; } - // Returns the number of padding bytes at the end of rows. - size_t padding() const { return padding_; } - // Returns the minimum value for ElementType. static constexpr ElementType min() { return std::numeric_limits::min(); @@ -130,7 +154,8 @@ class OperationTest { // Actual result of the operation. std::array actual_; // Number of padding bytes at the end of rows. - size_t padding_{0}; + std::array inputs_padding_; + std::array outputs_padding_; // Tested number of elements in a row. // Sufficient number of elements to exercise both vector and scalar paths. size_t width_{3 * test::Options::vector_lanes() - 1}; -- GitLab