diff --git a/tests/nnfw_api/lib/CircleGen.cc b/tests/nnfw_api/lib/CircleGen.cc index 38559a678b2..885ad4eb79d 100644 --- a/tests/nnfw_api/lib/CircleGen.cc +++ b/tests/nnfw_api/lib/CircleGen.cc @@ -582,6 +582,15 @@ uint32_t CircleGen::addOperatorSquare(const OperatorParams ¶ms) circle::BuiltinOptions_SquareOptions, options); } +uint32_t CircleGen::addOperatorSqueeze(const OperatorParams ¶ms, + const std::vector &squeeze_dims) +{ + auto squeeze_dims_vec = _fbb.CreateVector(squeeze_dims.data(), squeeze_dims.size()); + auto options = circle::CreateSqueezeOptions(_fbb, squeeze_dims_vec).Union(); + return addOperatorWithOptions(params, circle::BuiltinOperator_SQUEEZE, + circle::BuiltinOptions_SqueezeOptions, options); +} + uint32_t CircleGen::addOperatorBatchToSpaceND(const OperatorParams ¶ms) { auto options = circle::CreateBatchToSpaceNDOptions(_fbb).Union(); diff --git a/tests/nnfw_api/lib/CircleGen.h b/tests/nnfw_api/lib/CircleGen.h index 388e173ae8e..f039370aba4 100644 --- a/tests/nnfw_api/lib/CircleGen.h +++ b/tests/nnfw_api/lib/CircleGen.h @@ -222,6 +222,8 @@ class CircleGen uint32_t addOperatorSplit(const OperatorParams ¶ms, int32_t num_split); uint32_t addOperatorSqrt(const OperatorParams ¶ms); uint32_t addOperatorSquare(const OperatorParams ¶ms); + uint32_t addOperatorSqueeze(const OperatorParams ¶ms, + const std::vector &squeeze_dims); uint32_t addOperatorStridedSlice(const OperatorParams ¶ms, int32_t begin_mask = 0, int32_t end_mask = 0, int32_t ellipsis_mask = 0, int32_t new_axis_mask = 0, int32_t shrink_axis_mask = 0); diff --git a/tests/nnfw_api/src/GenModelTests/ModelTensorMemorySharing.test.cc b/tests/nnfw_api/src/GenModelTests/ModelTensorMemorySharing.test.cc new file mode 100644 index 00000000000..590b0df2e73 --- /dev/null +++ b/tests/nnfw_api/src/GenModelTests/ModelTensorMemorySharing.test.cc @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "CircleGen.h" +#include "GenModelTest.h" + +namespace +{ +// Add node other than Reshape/ExpandDims/Squeeze. +// It is used for cases where Reshape input/output is not input/output on the whole model. +uint32_t addNotOptimizedNode(CircleGen &cgen, const CircleGen::OperatorParams ¶ms) +{ + return cgen.addOperatorCos(params); +} +} // namespace + +TEST_F(GenModelTest, reshape_inference) +{ + CircleGen cgen; + std::vector new_shape_data{2, 2}; + uint32_t new_shape_buf = cgen.addBuffer(new_shape_data); + int input = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32}); + int cos1_out = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32}); + int new_shape = cgen.addTensor({{2}, circle::TensorType::TensorType_INT32, new_shape_buf}); + int reshape_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + int cos2_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + + addNotOptimizedNode(cgen, {{input}, {cos1_out}}); + cgen.addOperatorReshape({{cos1_out, new_shape}, {reshape_out}}, &new_shape_data); + addNotOptimizedNode(cgen, {{reshape_out}, {cos2_out}}); + cgen.setInputsAndOutputs({input}, {cos2_out}); + + _context = std::make_unique(cgen.finish()); + _context->addTestCase( + uniformTCD({{1, 2, 3, 4}}, {{0.85755322, 0.91465333, 0.54869613, 0.79387345}})); + _context->setBackends({"cpu"}); + + SUCCEED(); +} + +TEST_F(GenModelTest, expand_dims_inference) +{ + CircleGen cgen; + std::vector axes_data{0, 1}; + uint32_t axes_buf = cgen.addBuffer(axes_data); + int input = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32}); + int cos1_out = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32}); + int axes = cgen.addTensor({{2}, circle::TensorType::TensorType_INT32, axes_buf}); + int expand_dims_out = cgen.addTensor({{1, 1, 2, 2}, circle::TensorType::TensorType_FLOAT32}); + int cos2_out = cgen.addTensor({{1, 1, 2, 2}, circle::TensorType::TensorType_FLOAT32}); + + addNotOptimizedNode(cgen, {{input}, {cos1_out}}); + cgen.addOperatorExpandDims({{cos1_out, axes}, {expand_dims_out}}); + addNotOptimizedNode(cgen, {{expand_dims_out}, {cos2_out}}); + cgen.setInputsAndOutputs({input}, {cos2_out}); + + _context = std::make_unique(cgen.finish()); + _context->addTestCase( + uniformTCD({{1, 2, 3, 4}}, {{0.85755322, 0.91465333, 0.54869613, 0.79387345}})); + _context->setBackends({"cpu"}); + + SUCCEED(); +} + +TEST_F(GenModelTest, squeeze_inference) +{ + CircleGen cgen; + const std::vector squeeze_dims{0, 2}; + int input = cgen.addTensor({{1, 2, 1, 2}, circle::TensorType::TensorType_FLOAT32}); + int cos1_out = cgen.addTensor({{1, 2, 1, 2}, circle::TensorType::TensorType_FLOAT32}); + int squeeze_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + int cos2_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + + addNotOptimizedNode(cgen, {{input}, {cos1_out}}); + cgen.addOperatorSqueeze({{cos1_out}, {squeeze_out}}, squeeze_dims); + addNotOptimizedNode(cgen, {{squeeze_out}, {cos2_out}}); + cgen.setInputsAndOutputs({input}, {cos2_out}); + + _context = std::make_unique(cgen.finish()); + _context->addTestCase( + uniformTCD({{1, 2, 3, 4}}, {{0.85755322, 0.91465333, 0.54869613, 0.79387345}})); + _context->setBackends({"cpu"}); + + SUCCEED(); +} + +TEST_F(GenModelTest, reshape_const_input_inference) +{ + CircleGen cgen; + std::vector new_shape_data{2, 2}; + uint32_t new_shape_buf = cgen.addBuffer(new_shape_data); + std::vector reshape_in_data{1, 2, 3, 4}; + uint32_t reshape_in_buf = cgen.addBuffer(reshape_in_data); + int reshape_input = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32, reshape_in_buf}); + int new_shape = cgen.addTensor({{2}, circle::TensorType::TensorType_INT32, new_shape_buf}); + int reshape_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + int cos_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + + cgen.addOperatorReshape({{reshape_input, new_shape}, {reshape_out}}, &new_shape_data); + addNotOptimizedNode(cgen, {{reshape_out}, {cos_out}}); + cgen.setInputsAndOutputs({}, {cos_out}); + + _context = std::make_unique(cgen.finish()); + _context->addTestCase( + uniformTCD({}, {{0.54030231, -0.41614684, -0.9899925, -0.65364362}})); + _context->setBackends({"cpu"}); + + SUCCEED(); +} + +TEST_F(GenModelTest, reshape_dynamic_output) +{ + CircleGen cgen; + int cast_in = cgen.addTensor({{4}, circle::TensorType::TensorType_INT32}); + int cast_out = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32}); + int new_shape = cgen.addTensor({{2}, circle::TensorType::TensorType_INT32}); + int reshape_out = cgen.addTensor({{}, circle::TensorType::TensorType_FLOAT32}); + int cast2_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_INT32}); + + cgen.addOperatorCast({{cast_in}, {cast_out}}, circle::TensorType::TensorType_INT32, + circle::TensorType::TensorType_FLOAT32); + cgen.addOperatorReshape({{cast_out, new_shape}, {reshape_out}}); + cgen.addOperatorCast({{reshape_out}, {cast2_out}}, circle::TensorType::TensorType_FLOAT32, + circle::TensorType::TensorType_INT32); + cgen.setInputsAndOutputs({cast_in, new_shape}, {cast2_out}); + + _context = std::make_unique(cgen.finish()); + _context->addTestCase(uniformTCD({{1, 2, 3, 4}, {2, 2}}, {{1, 2, 3, 4}})); + _context->setBackends({"cpu"}); + + SUCCEED(); +} + +TEST_F(GenModelTest, reshape_input_used_in_many_places_inference) +{ + CircleGen cgen; + std::vector new_shape_data{2, 2}; + uint32_t new_shape_buf = cgen.addBuffer(new_shape_data); + int input = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32}); + int cos1_out = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32}); + int new_shape = cgen.addTensor({{2}, circle::TensorType::TensorType_INT32, new_shape_buf}); + int reshape_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + int cos2_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + int cos3_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + + addNotOptimizedNode(cgen, {{input}, {cos1_out}}); + cgen.addOperatorReshape({{cos1_out, new_shape}, {reshape_out}}, &new_shape_data); + addNotOptimizedNode(cgen, {{reshape_out}, {cos2_out}}); + addNotOptimizedNode(cgen, {{cos1_out}, {cos3_out}}); + cgen.setInputsAndOutputs({input}, {cos2_out, cos3_out}); + + _context = std::make_unique(cgen.finish()); + _context->addTestCase( + uniformTCD({{1, 2, 3, 4}}, {{0.85755322, 0.91465333, 0.54869613, 0.79387345}, + {0.85755322, 0.91465333, 0.54869613, 0.79387345}})); + _context->setBackends({"cpu"}); + + SUCCEED(); +} + +TEST_F(GenModelTest, reshape_output_used_in_many_places_inference) +{ + CircleGen cgen; + std::vector new_shape_data{2, 2}; + uint32_t new_shape_buf = cgen.addBuffer(new_shape_data); + int input = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32}); + int cos1_out = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32}); + int new_shape = cgen.addTensor({{2}, circle::TensorType::TensorType_INT32, new_shape_buf}); + int reshape_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + int cos2_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + int cos3_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + + addNotOptimizedNode(cgen, {{input}, {cos1_out}}); + cgen.addOperatorReshape({{cos1_out, new_shape}, {reshape_out}}, &new_shape_data); + addNotOptimizedNode(cgen, {{reshape_out}, {cos2_out}}); + addNotOptimizedNode(cgen, {{reshape_out}, {cos3_out}}); + cgen.setInputsAndOutputs({input}, {cos2_out, cos3_out}); + + _context = std::make_unique(cgen.finish()); + _context->addTestCase( + uniformTCD({{1, 2, 3, 4}}, {{0.85755322, 0.91465333, 0.54869613, 0.79387345}, + {0.85755322, 0.91465333, 0.54869613, 0.79387345}})); + _context->setBackends({"cpu"}); + + SUCCEED(); +} + +TEST_F(GenModelTest, reshape_reshape_chain_inference) +{ + CircleGen cgen; + std::vector new_shape_data{2, 2}; + uint32_t new_shape_buf = cgen.addBuffer(new_shape_data); + int input = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32}); + int cos1_out = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32}); + int new_shape = cgen.addTensor({{2}, circle::TensorType::TensorType_INT32, new_shape_buf}); + int reshape1_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + int reshape2_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + int cos2_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + + addNotOptimizedNode(cgen, {{input}, {cos1_out}}); + cgen.addOperatorReshape({{cos1_out, new_shape}, {reshape1_out}}, &new_shape_data); + cgen.addOperatorReshape({{reshape1_out, new_shape}, {reshape2_out}}, &new_shape_data); + addNotOptimizedNode(cgen, {{reshape2_out}, {cos2_out}}); + cgen.setInputsAndOutputs({input}, {cos2_out}); + + _context = std::make_unique(cgen.finish()); + _context->addTestCase( + uniformTCD({{1, 2, 3, 4}}, {{0.85755322, 0.91465333, 0.54869613, 0.79387345}})); + _context->setBackends({"cpu"}); + + SUCCEED(); +} + +TEST_F(GenModelTest, reshape_reshape_reshape_chain_inference) +{ + CircleGen cgen; + std::vector new_shape_data{2, 2}; + uint32_t new_shape_buf = cgen.addBuffer(new_shape_data); + int input = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32}); + int cos1_out = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32}); + int new_shape = cgen.addTensor({{2}, circle::TensorType::TensorType_INT32, new_shape_buf}); + int reshape1_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + int reshape2_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + int reshape3_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + int cos2_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + + addNotOptimizedNode(cgen, {{input}, {cos1_out}}); + cgen.addOperatorReshape({{cos1_out, new_shape}, {reshape1_out}}, &new_shape_data); + cgen.addOperatorReshape({{reshape1_out, new_shape}, {reshape2_out}}, &new_shape_data); + cgen.addOperatorReshape({{reshape2_out, new_shape}, {reshape3_out}}, &new_shape_data); + addNotOptimizedNode(cgen, {{reshape3_out}, {cos2_out}}); + cgen.setInputsAndOutputs({input}, {cos2_out}); + + _context = std::make_unique(cgen.finish()); + _context->addTestCase( + uniformTCD({{1, 2, 3, 4}}, {{0.85755322, 0.91465333, 0.54869613, 0.79387345}})); + _context->setBackends({"cpu"}); + + SUCCEED(); +} + +TEST_F(GenModelTest, reshape_input_model_input_inference) +{ + CircleGen cgen; + std::vector new_shape_data{2, 2}; + uint32_t new_shape_buf = cgen.addBuffer(new_shape_data); + int input = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32}); + int new_shape = cgen.addTensor({{2}, circle::TensorType::TensorType_INT32, new_shape_buf}); + int output = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + + cgen.addOperatorReshape({{input, new_shape}, {output}}, &new_shape_data); + cgen.setInputsAndOutputs({input}, {output}); + + _context = std::make_unique(cgen.finish()); + _context->addTestCase(uniformTCD({{1, 2, 3, 4}}, {{1, 2, 3, 4}})); + _context->setBackends({"cpu"}); + + SUCCEED(); +} + +TEST_F(GenModelTest, reshape_input_model_output_inference) +{ + CircleGen cgen; + std::vector new_shape_data{2, 2}; + uint32_t new_shape_buf = cgen.addBuffer(new_shape_data); + int input = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32}); + int cos1_out = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32}); + int new_shape = cgen.addTensor({{2}, circle::TensorType::TensorType_INT32, new_shape_buf}); + int reshape_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + int cos2_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + + addNotOptimizedNode(cgen, {{input}, {cos1_out}}); + cgen.addOperatorReshape({{cos1_out, new_shape}, {reshape_out}}, &new_shape_data); + addNotOptimizedNode(cgen, {{reshape_out}, {cos2_out}}); + cgen.setInputsAndOutputs({input}, {cos1_out, cos2_out}); + + _context = std::make_unique(cgen.finish()); + _context->addTestCase( + uniformTCD({{1, 2, 3, 4}}, {{0.54030231, -0.41614684, -0.9899925, -0.65364362}, + {0.85755322, 0.91465333, 0.54869613, 0.79387345}})); + _context->setBackends({"cpu"}); + + SUCCEED(); +} + +TEST_F(GenModelTest, reshape_output_model_output_inference) +{ + CircleGen cgen; + std::vector new_shape_data{2, 2}; + uint32_t new_shape_buf = cgen.addBuffer(new_shape_data); + int input = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32}); + int cos1_out = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32}); + int new_shape = cgen.addTensor({{2}, circle::TensorType::TensorType_INT32, new_shape_buf}); + int reshape_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + + addNotOptimizedNode(cgen, {{input}, {cos1_out}}); + cgen.addOperatorReshape({{cos1_out, new_shape}, {reshape_out}}, &new_shape_data); + cgen.setInputsAndOutputs({input}, {reshape_out}); + + _context = std::make_unique(cgen.finish()); + _context->addTestCase( + uniformTCD({{1, 2, 3, 4}}, {{0.54030231, -0.41614684, -0.9899925, -0.65364362}})); + _context->setBackends({"cpu"}); + + SUCCEED(); +} diff --git a/tests/nnfw_api/src/GenModelTests/one_op_tests/ExpandDims.test.cc b/tests/nnfw_api/src/GenModelTests/one_op_tests/ExpandDims.test.cc index 280cf7344f0..9c88a77f8be 100644 --- a/tests/nnfw_api/src/GenModelTests/one_op_tests/ExpandDims.test.cc +++ b/tests/nnfw_api/src/GenModelTests/one_op_tests/ExpandDims.test.cc @@ -56,7 +56,7 @@ TEST_F(GenModelTest, OneOp_ExpandDims_Int64AxisNeg) SUCCEED(); } -TEST_F(GenModelTest, OneOp_neg_ExpandDims_Axis) +TEST_F(GenModelTest, neg_OneOp_ExpandDims_Axis) { CircleGen cgen; @@ -75,7 +75,26 @@ TEST_F(GenModelTest, OneOp_neg_ExpandDims_Axis) SUCCEED(); } -TEST_F(GenModelTest, OneOp_neg_ExpandDims_AxisNegInput) +TEST_F(GenModelTest, neg_OneOp_ExpandDims_NegAxis) +{ + CircleGen cgen; + + std::vector axis_data{-5}; + uint32_t axis_buf = cgen.addBuffer(axis_data); + int in = cgen.addTensor({{1, 4, 1}, circle::TensorType::TensorType_FLOAT32}); + int axis = cgen.addTensor({{1}, circle::TensorType::TensorType_INT32, axis_buf}); + int out = cgen.addTensor({{1, 1, 4, 1}, circle::TensorType::TensorType_FLOAT32}); + cgen.addOperatorExpandDims({{in, axis}, {out}}); + cgen.setInputsAndOutputs({in}, {out}); + + _context = std::make_unique(cgen.finish()); + _context->setBackends({"cpu"}); + _context->expectFailCompile(); + + SUCCEED(); +} + +TEST_F(GenModelTest, neg_OneOp_ExpandDims_AxisNegInput) { CircleGen cgen; diff --git a/tests/nnfw_api/src/GenModelTests/one_op_tests/Reshape.test.cc b/tests/nnfw_api/src/GenModelTests/one_op_tests/Reshape.test.cc new file mode 100644 index 00000000000..314fe914580 --- /dev/null +++ b/tests/nnfw_api/src/GenModelTests/one_op_tests/Reshape.test.cc @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "GenModelTest.h" + +TEST_F(GenModelTest, neg_OneOp_Reshape_invalid_target_shape) +{ + CircleGen cgen; + const auto f32 = circle::TensorType::TensorType_FLOAT32; + + const std::vector new_shape_data{1, 5}; + const uint32_t new_shape_buf = cgen.addBuffer(new_shape_data); + const int new_shape = cgen.addTensor({{2}, f32, new_shape_buf}); + const int input = cgen.addTensor({{4}, f32}); + const int out = cgen.addTensor({{1, 5}, f32}); + + cgen.addOperatorReshape({{input, new_shape}, {out}}, &new_shape_data); + cgen.setInputsAndOutputs({input}, {out}); + + _context = std::make_unique(cgen.finish()); + _context->addTestCase(uniformTCD({{1, 2, 3, 4}}, {{1, 2, 3, 4}})); + _context->setBackends({"cpu", "gpu_cl"}); + + _context->expectFailCompile(); + + SUCCEED(); +} + +TEST_F(GenModelTest, neg_OneOp_Reshape_invalid_target_dyn_shape) +{ + CircleGen cgen; + const auto f32 = circle::TensorType::TensorType_FLOAT32; + const auto i32 = circle::TensorType::TensorType_INT32; + + const std::vector in_data{1.f, 2.f, 3.f, 4.f}; + const uint32_t input_buf = cgen.addBuffer(in_data); + const int input = cgen.addTensor({{4}, f32, input_buf}); + const int new_shape = cgen.addTensor({{2}, i32}); + const int out = cgen.addTensor({{}, f32}); // unspecified shape + + const CircleGen::Shape empty_new_shape; + cgen.addOperatorReshape({{input, new_shape}, {out}}, &empty_new_shape); + cgen.setInputsAndOutputs({new_shape}, {out}); + + _context = std::make_unique(cgen.finish()); + _context->addTestCase( + TestCaseData{}.addInput(std::vector{1, 5}).addOutput(in_data).expectFailRun()); + _context->output_sizes(0, sizeof(float) * in_data.size()); + _context->setBackends({"cpu", "gpu_cl"}); + + SUCCEED(); +} + +TEST_F(GenModelTest, neg_OneOp_Reshape_invalid_target_dyn_type) +{ + CircleGen cgen; + const auto f32 = circle::TensorType::TensorType_FLOAT32; + + const std::vector in_data{1.f, 2.f, 3.f, 4.f}; + const uint32_t input_buf = cgen.addBuffer(in_data); + const int input = cgen.addTensor({{4}, f32, input_buf}); + const int new_shape = cgen.addTensor({{2}, f32}); + const int out = cgen.addTensor({{}, f32}); // unspecified shape + + const CircleGen::Shape empty_new_shape; + cgen.addOperatorReshape({{input, new_shape}, {out}}, &empty_new_shape); + cgen.setInputsAndOutputs({new_shape}, {out}); + + _context = std::make_unique(cgen.finish()); + _context->addTestCase( + TestCaseData{}.addInput(std::vector{2, 2}).addOutput(in_data).expectFailRun()); + _context->output_sizes(0, sizeof(float) * in_data.size()); + _context->setBackends({"cpu", "gpu_cl"}); + + SUCCEED(); +} + +TEST_F(GenModelTest, neg_OneOp_Reshape_invalid_target_shape_with_neg_dim) +{ + CircleGen cgen; + const auto f32 = circle::TensorType::TensorType_FLOAT32; + + const std::vector new_shape_data{5, -1}; + const uint32_t new_shape_buf = cgen.addBuffer(new_shape_data); + const int new_shape = cgen.addTensor({{2}, f32, new_shape_buf}); + const int input = cgen.addTensor({{4}, f32}); + const int out = cgen.addTensor({{1, 5}, f32}); + + cgen.addOperatorReshape({{input, new_shape}, {out}}, &new_shape_data); + cgen.setInputsAndOutputs({input}, {out}); + + _context = std::make_unique(cgen.finish()); + _context->addTestCase(uniformTCD({{1, 2, 3, 4}}, {{1, 2, 3, 4}})); + _context->setBackends({"cpu", "gpu_cl"}); + + _context->expectFailCompile(); + + SUCCEED(); +} + +TEST_F(GenModelTest, neg_OneOp_Reshape_invalid_target_dyn_shape_with_neg_dim) +{ + CircleGen cgen; + const auto f32 = circle::TensorType::TensorType_FLOAT32; + const auto i32 = circle::TensorType::TensorType_INT32; + + const std::vector in_data{1.f, 2.f, 3.f, 4.f}; + const uint32_t input_buf = cgen.addBuffer(in_data); + const int input = cgen.addTensor({{4}, f32, input_buf}); + const int new_shape = cgen.addTensor({{2}, i32}); + const int out = cgen.addTensor({{}, f32}); // unspecified shape + + const CircleGen::Shape empty_new_shape; + cgen.addOperatorReshape({{input, new_shape}, {out}}, &empty_new_shape); + cgen.setInputsAndOutputs({new_shape}, {out}); + + _context = std::make_unique(cgen.finish()); + _context->addTestCase( + TestCaseData{}.addInput(std::vector{-1, 5}).addOutput(in_data).expectFailRun()); + _context->output_sizes(0, sizeof(float) * in_data.size()); + _context->setBackends({"cpu", "gpu_cl"}); + + SUCCEED(); +} + +TEST_F(GenModelTest, neg_OneOp_Reshape_invalid_target_shape_with_zero_dim) +{ + CircleGen cgen; + const auto f32 = circle::TensorType::TensorType_FLOAT32; + + const std::vector new_shape_data{5, 0}; + const uint32_t new_shape_buf = cgen.addBuffer(new_shape_data); + const int new_shape = cgen.addTensor({{2}, f32, new_shape_buf}); + const int input = cgen.addTensor({{4}, f32}); + const int out = cgen.addTensor({{1, 5}, f32}); + + cgen.addOperatorReshape({{input, new_shape}, {out}}, &new_shape_data); + cgen.setInputsAndOutputs({input}, {out}); + + _context = std::make_unique(cgen.finish()); + _context->addTestCase(uniformTCD({{1, 2, 3, 4}}, {{1, 2, 3, 4}})); + _context->setBackends({"cpu", "gpu_cl"}); + + _context->expectFailCompile(); + + SUCCEED(); +} + +TEST_F(GenModelTest, neg_OneOp_Reshape_invalid_target_dyn_shape_with_zero_dim) +{ + CircleGen cgen; + const auto f32 = circle::TensorType::TensorType_FLOAT32; + const auto i32 = circle::TensorType::TensorType_INT32; + + const std::vector in_data{1.f, 2.f, 3.f, 4.f}; + const uint32_t input_buf = cgen.addBuffer(in_data); + const int input = cgen.addTensor({{4}, f32, input_buf}); + const int new_shape = cgen.addTensor({{2}, i32}); + const int out = cgen.addTensor({{}, f32}); // unspecified shape + + const CircleGen::Shape empty_new_shape; + cgen.addOperatorReshape({{input, new_shape}, {out}}, &empty_new_shape); + cgen.setInputsAndOutputs({new_shape}, {out}); + + _context = std::make_unique(cgen.finish()); + _context->addTestCase( + TestCaseData{}.addInput(std::vector{-1, 5}).addOutput(in_data).expectFailRun()); + _context->output_sizes(0, sizeof(float) * in_data.size()); + _context->setBackends({"cpu", "gpu_cl"}); + + SUCCEED(); +} diff --git a/tests/nnfw_api/src/GenModelTests/one_op_tests/Squeeze.test.cc b/tests/nnfw_api/src/GenModelTests/one_op_tests/Squeeze.test.cc new file mode 100644 index 00000000000..73021e39f96 --- /dev/null +++ b/tests/nnfw_api/src/GenModelTests/one_op_tests/Squeeze.test.cc @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "GenModelTest.h" + +TEST_F(GenModelTest, neg_OneOp_Squeeze_invalid_dims) +{ + CircleGen cgen; + const std::vector squeeze_dims{0, 1}; // 1 dim here is incorrect + int input = cgen.addTensor({{1, 2, 1, 2}, circle::TensorType::TensorType_FLOAT32}); + int squeeze_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + + cgen.addOperatorSqueeze({{input}, {squeeze_out}}, squeeze_dims); + cgen.setInputsAndOutputs({input}, {squeeze_out}); + + _context = std::make_unique(cgen.finish()); + _context->addTestCase(uniformTCD({{1, 2, 3, 4}}, {{1, 2, 3, 4}})); + _context->setBackends({"cpu", "gpu_cl"}); + + _context->expectFailCompile(); + + SUCCEED(); +} + +TEST_F(GenModelTest, neg_OneOp_Squeeze_out_of_rank_dims) +{ + CircleGen cgen; + const std::vector squeeze_dims{0, 4}; // 4 dim here is incorrect + int input = cgen.addTensor({{1, 2, 1, 2}, circle::TensorType::TensorType_FLOAT32}); + int squeeze_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + + cgen.addOperatorSqueeze({{input}, {squeeze_out}}, squeeze_dims); + cgen.setInputsAndOutputs({input}, {squeeze_out}); + + _context = std::make_unique(cgen.finish()); + _context->addTestCase(uniformTCD({{1, 2, 3, 4}}, {{1, 2, 3, 4}})); + _context->setBackends({"cpu", "gpu_cl"}); + + _context->expectFailCompile(); + + SUCCEED(); +} + +TEST_F(GenModelTest, neg_OneOp_Squeeze_neg_invalid_dims) +{ + CircleGen cgen; + const std::vector squeeze_dims{0, -3}; // -3 dim here is incorrect + int input = cgen.addTensor({{1, 2, 1, 2}, circle::TensorType::TensorType_FLOAT32}); + int squeeze_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + + cgen.addOperatorSqueeze({{input}, {squeeze_out}}, squeeze_dims); + cgen.setInputsAndOutputs({input}, {squeeze_out}); + + _context = std::make_unique(cgen.finish()); + _context->addTestCase(uniformTCD({{1, 2, 3, 4}}, {{1, 2, 3, 4}})); + _context->setBackends({"cpu", "gpu_cl"}); + + _context->expectFailCompile(); + + SUCCEED(); +} + +TEST_F(GenModelTest, neg_OneOp_Squeeze_neg_out_of_rank_dims) +{ + CircleGen cgen; + const std::vector squeeze_dims{0, -5}; // -5 dim here is incorrect + int input = cgen.addTensor({{1, 2, 1, 2}, circle::TensorType::TensorType_FLOAT32}); + int squeeze_out = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32}); + + cgen.addOperatorSqueeze({{input}, {squeeze_out}}, squeeze_dims); + cgen.setInputsAndOutputs({input}, {squeeze_out}); + + _context = std::make_unique(cgen.finish()); + _context->addTestCase(uniformTCD({{1, 2, 3, 4}}, {{1, 2, 3, 4}})); + _context->setBackends({"cpu", "gpu_cl"}); + + _context->expectFailCompile(); + + SUCCEED(); +}