1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ops/crop_builder.h"
17 
18 #include "ops_test.h"
19 
20 using namespace testing;
21 using namespace testing::ext;
22 using namespace OHOS::NeuralNetworkRuntime::Ops;
23 
24 namespace OHOS {
25 namespace NeuralNetworkRuntime {
26 namespace UnitTest {
27 class CropBuilderTest : public OpsTest {
28 public:
29     void SetUp() override;
30     void TearDown() override;
31 
32 protected:
33     void SaveAxis(OH_NN_DataType dataType,
34         const std::vector<int32_t> &dim,  const OH_NN_QuantParam* quantParam, OH_NN_TensorType type);
35     void SaveOffset(OH_NN_DataType dataType,
36         const std::vector<int32_t> &dim,  const OH_NN_QuantParam* quantParam, OH_NN_TensorType type);
37     void SetInputAndShape();
38 
39 protected:
40     CropBuilder m_builder;
41     std::vector<uint32_t> m_inputs {0, 1};
42     std::vector<uint32_t> m_outputs {2};
43     std::vector<uint32_t> m_params {3, 4};
44     std::vector<int32_t> m_inputDim {2, 3, 4, 5};
45     std::vector<int32_t> m_shapeDim {1};
46     std::vector<int32_t> m_outputDim {2, 3, 4, 5};
47     std::vector<int32_t> m_axisDim {};
48     std::vector<int32_t> m_offsetDim {1};
49 };
50 
SetUp()51 void CropBuilderTest::SetUp() {}
52 
TearDown()53 void CropBuilderTest::TearDown() {}
54 
SetInputAndShape()55 void CropBuilderTest::SetInputAndShape()
56 {
57     m_inputsIndex = m_inputs;
58     std::shared_ptr<NNTensor> inputTensor;
59     inputTensor = TransToNNTensor(OH_NN_FLOAT32, m_inputDim, nullptr, OH_NN_TENSOR);
60     m_allTensors.emplace_back(inputTensor);
61 
62     std::shared_ptr<NNTensor> shapeTensor;
63     shapeTensor = TransToNNTensor(OH_NN_FLOAT32, m_shapeDim, nullptr, OH_NN_TENSOR);
64     m_allTensors.emplace_back(shapeTensor);
65 }
66 
SaveAxis(OH_NN_DataType dataType,const std::vector<int32_t> & dim,const OH_NN_QuantParam * quantParam,OH_NN_TensorType type)67 void CropBuilderTest::SaveAxis(OH_NN_DataType dataType,
68     const std::vector<int32_t> &dim, const OH_NN_QuantParam* quantParam, OH_NN_TensorType type)
69 {
70     std::shared_ptr<NNTensor> axisTensor = TransToNNTensor(dataType, dim, quantParam, type);
71     int64_t* axisValue = new (std::nothrow) int64_t[1] {0};
72     axisTensor->SetBuffer(axisValue, sizeof(int64_t));
73     m_allTensors.emplace_back(axisTensor);
74 }
75 
SaveOffset(OH_NN_DataType dataType,const std::vector<int32_t> & dim,const OH_NN_QuantParam * quantParam,OH_NN_TensorType type)76 void CropBuilderTest::SaveOffset(OH_NN_DataType dataType,
77     const std::vector<int32_t> &dim, const OH_NN_QuantParam* quantParam, OH_NN_TensorType type)
78 {
79     std::shared_ptr<NNTensor> offsetTensor = TransToNNTensor(dataType, dim, quantParam, type);
80     int64_t* offsetValue = new (std::nothrow) int64_t[1] {1};
81     offsetTensor->SetBuffer(offsetValue, sizeof(int64_t));
82     m_allTensors.emplace_back(offsetTensor);
83 }
84 
85 /**
86  * @tc.name: crop_build_001
87  * @tc.desc: Verify that the build function returns a successful message.
88  * @tc.type: FUNC
89  */
90 HWTEST_F(CropBuilderTest, crop_build_001, TestSize.Level1)
91 {
92     SetInputAndShape();
93     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_outputDim, nullptr);
94     SaveAxis(OH_NN_INT64, m_axisDim, nullptr, OH_NN_CROP_AXIS);
95     SaveOffset(OH_NN_INT64, m_offsetDim, nullptr, OH_NN_CROP_OFFSET);
96 
97     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
98     EXPECT_EQ(OH_NN_SUCCESS, ret);
99 }
100 
101 /**
102  * @tc.name: crop_build_002
103  * @tc.desc: Verify that the build function returns a failed message with true m_isBuild.
104  * @tc.type: FUNC
105  */
106 HWTEST_F(CropBuilderTest, crop_build_002, TestSize.Level1)
107 {
108     SetInputAndShape();
109     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_outputDim, nullptr);
110     SaveAxis(OH_NN_INT64, m_axisDim, nullptr, OH_NN_CROP_AXIS);
111     SaveOffset(OH_NN_INT64, m_offsetDim, nullptr, OH_NN_CROP_OFFSET);
112 
113     EXPECT_EQ(OH_NN_SUCCESS, m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors));
114     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
115     EXPECT_EQ(OH_NN_OPERATION_FORBIDDEN, ret);
116 }
117 
118 /**
119  * @tc.name: crop_build_003
120  * @tc.desc: Verify that the build function returns a failed message with invalided input.
121  * @tc.type: FUNC
122  */
123 HWTEST_F(CropBuilderTest, crop_build_003, TestSize.Level1)
124 {
125     m_inputs = {0, 1, 2};
126     m_outputs = {3};
127     m_params = {4, 5};
128 
129     SetInputAndShape();
130     std::shared_ptr<NNTensor> inputTensor = TransToNNTensor(OH_NN_FLOAT32, m_inputDim, nullptr, OH_NN_TENSOR);
131     m_allTensors.emplace_back(inputTensor);
132 
133     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_outputDim, nullptr);
134     SaveAxis(OH_NN_INT64, m_axisDim, nullptr, OH_NN_CROP_AXIS);
135     SaveOffset(OH_NN_INT64, m_offsetDim, nullptr, OH_NN_CROP_OFFSET);
136 
137     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputs, m_outputs, m_allTensors);
138     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
139 }
140 
141 /**
142  * @tc.name: crop_build_004
143  * @tc.desc: Verify that the build function returns a failed message with invalided output.
144  * @tc.type: FUNC
145  */
146 HWTEST_F(CropBuilderTest, crop_build_004, TestSize.Level1)
147 {
148     m_outputs = {2, 3};
149     m_params = {4, 5};
150 
151     SetInputAndShape();
152     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_outputDim, nullptr);
153     SaveAxis(OH_NN_INT64, m_axisDim, nullptr, OH_NN_CROP_AXIS);
154     SaveOffset(OH_NN_INT64, m_offsetDim, nullptr, OH_NN_CROP_OFFSET);
155 
156     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
157     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
158 }
159 
160 /**
161  * @tc.name: crop_build_005
162  * @tc.desc: Verify that the build function returns a failed message with empty allTensor.
163  * @tc.type: FUNC
164  */
165 HWTEST_F(CropBuilderTest, crop_build_005, TestSize.Level1)
166 {
167     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputs, m_outputs, m_allTensors);
168     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
169 }
170 
171 /**
172  * @tc.name: crop_build_006
173  * @tc.desc: Verify that the build function returns a failed message without output tensor.
174  * @tc.type: FUNC
175  */
176 HWTEST_F(CropBuilderTest, crop_build_006, TestSize.Level1)
177 {
178     SetInputAndShape();
179 
180     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputs, m_allTensors);
181     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
182 }
183 
184 /**
185  * @tc.name: crop_build_007
186  * @tc.desc: Verify that the build function returns a failed message with invalid axis's dataType.
187  * @tc.type: FUNC
188  */
189 HWTEST_F(CropBuilderTest, crop_build_007, TestSize.Level1)
190 {
191     SetInputAndShape();
192     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_outputDim, nullptr);
193 
194     std::shared_ptr<NNTensor> axisTensor = TransToNNTensor(OH_NN_FLOAT32, m_axisDim,
195         nullptr, OH_NN_CROP_AXIS);
__anonfbf230a50102null196     float* axisValue = new (std::nothrow) float [1]{0.0f};
197     axisTensor->SetBuffer(axisValue, sizeof(float));
198     m_allTensors.emplace_back(axisTensor);
199     SaveOffset(OH_NN_INT64, m_offsetDim, nullptr, OH_NN_CROP_OFFSET);
200 
201     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
202     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
203 }
204 
205 /**
206  * @tc.name: crop_build_008
207  * @tc.desc: Verify that the build function returns a failed message with invalid offset's dataType.
208  * @tc.type: FUNC
209  */
210 HWTEST_F(CropBuilderTest, crop_build_008, TestSize.Level1)
211 {
212     SetInputAndShape();
213     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_outputDim, nullptr);
214 
215     SaveAxis(OH_NN_INT64, m_axisDim, nullptr, OH_NN_CROP_AXIS);
216     std::shared_ptr<NNTensor> offsetTensor = TransToNNTensor(OH_NN_FLOAT32, m_offsetDim,
217         nullptr, OH_NN_CROP_OFFSET);
__anonfbf230a50202null218     float* offsetValue = new (std::nothrow) float[1] {1.0f};
219     int32_t offsetSize = 1;
220     EXPECT_NE(nullptr, offsetValue);
221     offsetTensor->SetBuffer(offsetValue, sizeof(float) * offsetSize);
222     m_allTensors.emplace_back(offsetTensor);
223 
224     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
225     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
226 }
227 
228 /**
229  * @tc.name: crop_build_009
230  * @tc.desc: Verify that the build function returns a failed message with passing invalid dataType param.
231  * @tc.type: FUNC
232  */
233 HWTEST_F(CropBuilderTest, crop_build_009, TestSize.Level1)
234 {
235     SetInputAndShape();
236     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_outputDim, nullptr);
237     SaveAxis(OH_NN_INT64, m_axisDim, nullptr, OH_NN_MUL_ACTIVATION_TYPE);
238     SaveOffset(OH_NN_INT64, m_offsetDim, nullptr, OH_NN_CROP_OFFSET);
239 
240     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
241     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
242 }
243 
244 /**
245  * @tc.name: crop_build_010
246  * @tc.desc: Verify that the build function returns a failed message with passing invalid value param.
247  * @tc.type: FUNC
248  */
249 HWTEST_F(CropBuilderTest, crop_build_010, TestSize.Level1)
250 {
251     SetInputAndShape();
252     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_outputDim, nullptr);
253     SaveAxis(OH_NN_INT64, m_axisDim, nullptr, OH_NN_CROP_AXIS);
254     SaveOffset(OH_NN_INT64, m_offsetDim, nullptr, OH_NN_MUL_ACTIVATION_TYPE);
255 
256     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
257     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
258 }
259 
260 /**
261  * @tc.name: crop_build_011
262  * @tc.desc: Verify that the build function returns a failed message without set buffer for dataType.
263  * @tc.type: FUNC
264  */
265 HWTEST_F(CropBuilderTest, crop_build_011, TestSize.Level1)
266 {
267     SetInputAndShape();
268     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_outputDim, nullptr);
269 
270     std::shared_ptr<NNTensor> dataTypeTensor = TransToNNTensor(OH_NN_INT64, m_axisDim,
271         nullptr, OH_NN_CROP_AXIS);
272     m_allTensors.emplace_back(dataTypeTensor);
273     SaveOffset(OH_NN_INT64, m_offsetDim, nullptr, OH_NN_CROP_OFFSET);
274 
275     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
276     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
277 }
278 
279 /**
280  * @tc.name: crop_build_012
281  * @tc.desc: Verify that the build function returns a failed message without set buffer for value.
282  * @tc.type: FUNC
283  */
284 HWTEST_F(CropBuilderTest, crop_build_012, TestSize.Level1)
285 {
286     SetInputAndShape();
287     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_outputDim, nullptr);
288 
289     SaveAxis(OH_NN_INT64, m_axisDim, nullptr, OH_NN_CROP_AXIS);
290     std::shared_ptr<NNTensor> valueTensor = TransToNNTensor(OH_NN_INT64, m_offsetDim,
291         nullptr, OH_NN_CROP_OFFSET);
292     m_allTensors.emplace_back(valueTensor);
293 
294     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
295     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
296 }
297 
298 /**
299  * @tc.name: crop_getprimitive_001
300  * @tc.desc: Verify that the getPrimitive function returns a successful message
301  * @tc.type: FUNC
302  */
303 HWTEST_F(CropBuilderTest, crop_getprimitive_001, TestSize.Level1)
304 {
305     SetInputAndShape();
306     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_outputDim, nullptr);
307     SaveAxis(OH_NN_INT64, m_axisDim, nullptr, OH_NN_CROP_AXIS);
308     SaveOffset(OH_NN_INT64, m_offsetDim, nullptr, OH_NN_CROP_OFFSET);
309 
310     int64_t axisValue = 0;
311     std::vector<int64_t> offsetsValue = {1};
312     EXPECT_EQ(OH_NN_SUCCESS, m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors));
313     LiteGraphPrimitvePtr primitive = m_builder.GetPrimitive();
314     LiteGraphPrimitvePtr expectPrimitive(nullptr, DestroyLiteGraphPrimitive);
315     EXPECT_NE(expectPrimitive, primitive);
316 
317     auto returnAxisValue = mindspore::lite::MindIR_Crop_GetAxis(primitive.get());
318     EXPECT_EQ(returnAxisValue, axisValue);
319     auto returnOffsets = mindspore::lite::MindIR_Crop_GetOffsets(primitive.get());
320     auto returnOffsetsSize = returnOffsets.size();
321     for (size_t i = 0; i < returnOffsetsSize; ++i) {
322         EXPECT_EQ(returnOffsets[i], offsetsValue[i]);
323     }
324 }
325 
326 /**
327  * @tc.name: crop_getprimitive_002
328  * @tc.desc: Verify that the getPrimitive function returns a failed message without build.
329  * @tc.type: FUNC
330  */
331 HWTEST_F(CropBuilderTest, crop_getprimitive_002, TestSize.Level1)
332 {
333     LiteGraphPrimitvePtr primitive = m_builder.GetPrimitive();
334     LiteGraphPrimitvePtr expectPrimitive(nullptr, DestroyLiteGraphPrimitive);
335     EXPECT_EQ(expectPrimitive, primitive);
336 }
337 }
338 }
339 }