1 /*
2  * Copyright (c) 2022 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/scale_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 ScaleBuilderTest : public OpsTest {
28 public:
29     void SetUp() override;
30     void TearDown() override;
31 
32 protected:
33     void SaveAxisTensor(OH_NN_DataType dataType, const std::vector<int32_t> &dim,
34         const OH_NN_QuantParam* quantParam, OH_NN_TensorType type);
35     void SaveActivationTensor(OH_NN_DataType dataType, const std::vector<int32_t> &dim,
36         const OH_NN_QuantParam* quantParam, OH_NN_TensorType type);
37 
38 protected:
39     ScaleBuilder m_builder;
40     std::vector<uint32_t> m_inputs {0, 1, 2};
41     std::vector<uint32_t> m_outputs {3};
42     std::vector<uint32_t> m_params {4, 5};
43     std::vector<int32_t> m_dim {1, 4, 1, 1};
44     std::vector<int32_t> m_paramDim {};
45 };
46 
SetUp()47 void ScaleBuilderTest::SetUp() {}
48 
TearDown()49 void ScaleBuilderTest::TearDown() {}
50 
SaveAxisTensor(OH_NN_DataType dataType,const std::vector<int32_t> & dim,const OH_NN_QuantParam * quantParam,OH_NN_TensorType type)51 void ScaleBuilderTest::SaveAxisTensor(OH_NN_DataType dataType, const std::vector<int32_t> &dim,
52     const OH_NN_QuantParam* quantParam, OH_NN_TensorType type)
53 {
54     std::shared_ptr<NNTensor> axisTensor = TransToNNTensor(dataType, dim, quantParam, type);
55     int64_t *axisValue = new (std::nothrow) int64_t(1);
56     EXPECT_NE(nullptr, axisValue);
57     axisTensor->SetBuffer(axisValue, sizeof(int64_t));
58     m_allTensors.emplace_back(axisTensor);
59 }
60 
SaveActivationTensor(OH_NN_DataType dataType,const std::vector<int32_t> & dim,const OH_NN_QuantParam * quantParam,OH_NN_TensorType type)61 void ScaleBuilderTest::SaveActivationTensor(OH_NN_DataType dataType, const std::vector<int32_t> &dim,
62     const OH_NN_QuantParam* quantParam, OH_NN_TensorType type)
63 {
64     std::shared_ptr<NNTensor> activationTensor = TransToNNTensor(dataType, dim, quantParam, type);
65     int8_t *activationValue = new (std::nothrow) int8_t(0);
66     EXPECT_NE(nullptr, activationValue);
67     activationTensor->SetBuffer(activationValue, sizeof(int64_t));
68     m_allTensors.emplace_back(activationTensor);
69 }
70 
71 /**
72  * @tc.name: scale_build_001
73  * @tc.desc: Provide normal input, output, and parameters to verify the normal behavior of the Build function
74  * @tc.type: FUNC
75  */
76 HWTEST_F(ScaleBuilderTest, scale_build_001, TestSize.Level0)
77 {
78     SaveInputTensor(m_inputs, OH_NN_FLOAT32, m_dim, nullptr);
79     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_dim, nullptr);
80     SaveAxisTensor(OH_NN_INT64, m_paramDim, nullptr, OH_NN_SCALE_AXIS);
81     SaveActivationTensor(OH_NN_INT8, m_paramDim, nullptr, OH_NN_SCALE_ACTIVATIONTYPE);
82 
83     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
84     EXPECT_EQ(OH_NN_SUCCESS, ret);
85 }
86 
87 /**
88  * @tc.name: scale_build_002
89  * @tc.desc: Call Build func twice to verify the abnormal behavior of the Build function
90  * @tc.type: FUNC
91  */
92 HWTEST_F(ScaleBuilderTest, scale_build_002, TestSize.Level0)
93 {
94     SaveInputTensor(m_inputs, OH_NN_FLOAT32, m_dim, nullptr);
95     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_dim, nullptr);
96     SaveAxisTensor(OH_NN_INT64, m_paramDim, nullptr, OH_NN_SCALE_AXIS);
97     SaveActivationTensor(OH_NN_INT8, m_paramDim, nullptr, OH_NN_SCALE_ACTIVATIONTYPE);
98 
99     EXPECT_EQ(OH_NN_SUCCESS, m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors));
100     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
101     EXPECT_EQ(OH_NN_OPERATION_FORBIDDEN, ret);
102 }
103 
104 /**
105  * @tc.name: scale_build_003
106  * @tc.desc: Provide one more than normal input to verify the abnormal behavior of the Build function
107  * @tc.type: FUNC
108  */
109 HWTEST_F(ScaleBuilderTest, scale_build_003, TestSize.Level0)
110 {
111     m_inputs = {0, 1, 2, 3};
112     m_outputs = {4};
113     m_params = {5, 6};
114 
115     SaveInputTensor(m_inputs, OH_NN_FLOAT32, m_dim, nullptr);
116     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_dim, nullptr);
117     SaveAxisTensor(OH_NN_INT64, m_paramDim, nullptr, OH_NN_SCALE_AXIS);
118     SaveActivationTensor(OH_NN_INT8, m_paramDim, nullptr, OH_NN_SCALE_ACTIVATIONTYPE);
119 
120     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
121     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
122 }
123 
124 /**
125  * @tc.name: scale_build_004
126  * @tc.desc: Provide one more than normal output to verify the abnormal behavior of the Build function
127  * @tc.type: FUNC
128  */
129 HWTEST_F(ScaleBuilderTest, scale_build_004, TestSize.Level0)
130 {
131     m_outputs = {3, 4};
132     m_params = {5, 6};
133 
134     SaveInputTensor(m_inputs, OH_NN_FLOAT32, m_dim, nullptr);
135     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_dim, nullptr);
136     SaveAxisTensor(OH_NN_INT64, m_paramDim, nullptr, OH_NN_SCALE_AXIS);
137     SaveActivationTensor(OH_NN_INT8, m_paramDim, nullptr, OH_NN_SCALE_ACTIVATIONTYPE);
138 
139     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
140     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
141 }
142 
143 /**
144  * @tc.name: scale_build_005
145  * @tc.desc: Verify that the build function return a failed message with null allTensor
146  * @tc.type: FUNC
147  */
148 HWTEST_F(ScaleBuilderTest, scale_build_005, TestSize.Level0)
149 {
150     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputs, m_outputs, m_allTensors);
151     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
152 }
153 
154 /**
155  * @tc.name: scale_build_006
156  * @tc.desc: Verify that the build function return a failed message without output tensor
157  * @tc.type: FUNC
158  */
159 HWTEST_F(ScaleBuilderTest, scale_build_006, TestSize.Level0)
160 {
161     SaveInputTensor(m_inputs, OH_NN_FLOAT32, m_dim, nullptr);
162 
163     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputs, m_allTensors);
164     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
165 }
166 
167 /**
168  * @tc.name: scale_build_007
169  * @tc.desc: Verify that the build function return a failed message with invalided axis's dataType
170  * @tc.type: FUNC
171  */
172 HWTEST_F(ScaleBuilderTest, scale_build_007, TestSize.Level0)
173 {
174     SaveInputTensor(m_inputs, OH_NN_FLOAT32, m_dim, nullptr);
175     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_dim, nullptr);
176 
177     SaveActivationTensor(OH_NN_INT8, m_paramDim, nullptr, OH_NN_SCALE_ACTIVATIONTYPE);
178 
179     std::shared_ptr<NNTensor> axisTensor = TransToNNTensor(OH_NN_INT32, m_paramDim, nullptr, OH_NN_SCALE_AXIS);
180     int32_t axisValue = 1;
181     axisTensor->SetBuffer(&axisValue, sizeof(axisValue));
182     m_allTensors.emplace_back(axisTensor);
183 
184     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
185     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
186     axisTensor->SetBuffer(nullptr, 0);
187 }
188 
189 /**
190  * @tc.name: scale_build_008
191  * @tc.desc: Verify that the build function return a failed message with invalided activation's dataType
192  * @tc.type: FUNC
193  */
194 HWTEST_F(ScaleBuilderTest, scale_build_008, TestSize.Level0)
195 {
196     SaveInputTensor(m_inputs, OH_NN_FLOAT32, m_dim, nullptr);
197     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_dim, nullptr);
198 
199     SaveAxisTensor(OH_NN_INT64, m_paramDim, nullptr, OH_NN_SCALE_AXIS);
200 
201     std::shared_ptr<NNTensor> activationTensor = TransToNNTensor(OH_NN_INT64, m_paramDim,
202         nullptr, OH_NN_SCALE_ACTIVATIONTYPE);
203     int64_t activationValue = 0;
204     activationTensor->SetBuffer(&activationValue, sizeof(activationValue));
205     m_allTensors.emplace_back(activationTensor);
206 
207     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
208     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
209     activationTensor->SetBuffer(nullptr, 0);
210 }
211 
212 /**
213  * @tc.name: scale_build_009
214  * @tc.desc: Verify that the build function return a failed message with invalided axis's dimension
215  * @tc.type: FUNC
216  */
217 HWTEST_F(ScaleBuilderTest, scale_build_009, TestSize.Level0)
218 {
219     SaveInputTensor(m_inputs, OH_NN_FLOAT32, m_dim, nullptr);
220     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_dim, nullptr);
221 
222     std::vector<int32_t> axistDim = {2};
223     std::shared_ptr<NNTensor> axisTensor = TransToNNTensor(OH_NN_INT64, axistDim, nullptr, OH_NN_SCALE_AXIS);
224     int64_t axisValue[2] = {1, 1};
225     axisTensor->SetBuffer(axisValue, 2 * sizeof(int64_t));
226     m_allTensors.emplace_back(axisTensor);
227 
228     SaveActivationTensor(OH_NN_INT8, m_paramDim, nullptr, OH_NN_SCALE_ACTIVATIONTYPE);
229 
230     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
231     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
232     axisTensor->SetBuffer(nullptr, 0);
233 }
234 
235 /**
236  * @tc.name: scale_build_010
237  * @tc.desc: Verify that the build function return a failed message with invalided activation's dimension
238  * @tc.type: FUNC
239  */
240 HWTEST_F(ScaleBuilderTest, scale_build_010, TestSize.Level0)
241 {
242     SaveInputTensor(m_inputs, OH_NN_FLOAT32, m_dim, nullptr);
243     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_dim, nullptr);
244 
245     SaveAxisTensor(OH_NN_INT64, m_paramDim, nullptr, OH_NN_SCALE_AXIS);
246 
247     std::vector<int32_t> activationDim = {2};
248     std::shared_ptr<NNTensor> activationTensor = TransToNNTensor(OH_NN_INT8,
249         activationDim, nullptr, OH_NN_SCALE_ACTIVATIONTYPE);
250     int64_t activationValue[2] = {1, 1};
251     activationTensor->SetBuffer(activationValue, 2 * sizeof(int64_t));
252     m_allTensors.emplace_back(activationTensor);
253 
254     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
255     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
256     activationTensor->SetBuffer(nullptr, 0);
257 }
258 
259 /**
260  * @tc.name: scale_build_011
261  * @tc.desc: Verify that the build function return a failed message with invalided activation's buffer
262  * @tc.type: FUNC
263  */
264 HWTEST_F(ScaleBuilderTest, scale_build_011, TestSize.Level0)
265 {
266     SaveInputTensor(m_inputs, OH_NN_FLOAT32, m_dim, nullptr);
267     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_dim, nullptr);
268 
269     SaveAxisTensor(OH_NN_INT64, m_paramDim, nullptr, OH_NN_SCALE_AXIS);
270 
271     std::shared_ptr<NNTensor> activationTensor = TransToNNTensor(OH_NN_INT8,
272         m_paramDim, nullptr, OH_NN_SCALE_ACTIVATIONTYPE);
273     int8_t activationValue = -1;
274     activationTensor->SetBuffer(&activationValue, sizeof(activationValue));
275     m_allTensors.emplace_back(activationTensor);
276 
277     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
278     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
279     activationTensor->SetBuffer(nullptr, 0);
280 }
281 
282 /**
283  * @tc.name: scale_build_012
284  * @tc.desc: Verify that the build function return a failed message with invalided parameter
285  * @tc.type: FUNC
286  */
287 HWTEST_F(ScaleBuilderTest, scale_build_012, TestSize.Level0)
288 {
289     SaveInputTensor(m_inputs, OH_NN_FLOAT32, m_dim, nullptr);
290     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_dim, nullptr);
291     SaveAxisTensor(OH_NN_INT64, m_paramDim, nullptr, OH_NN_SCALE_AXIS);
292     SaveActivationTensor(OH_NN_INT8, m_paramDim, nullptr, OH_NN_QUANT_DTYPE_CAST_SRC_T);
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: scale_build_013
300  * @tc.desc: Verify that the build function return a failed message with empty axis's buffer
301  * @tc.type: FUNC
302  */
303 HWTEST_F(ScaleBuilderTest, scale_build_013, TestSize.Level0)
304 {
305     SaveInputTensor(m_inputs, OH_NN_FLOAT32, m_dim, nullptr);
306     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_dim, nullptr);
307 
308     SaveActivationTensor(OH_NN_INT8, m_paramDim, nullptr, OH_NN_SCALE_ACTIVATIONTYPE);
309 
310     std::shared_ptr<NNTensor> axisTensor = TransToNNTensor(OH_NN_INT64, m_paramDim, nullptr, OH_NN_SCALE_AXIS);
311     m_allTensors.emplace_back(axisTensor);
312 
313     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
314     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
315     axisTensor->SetBuffer(nullptr, 0);
316 }
317 
318 /**
319  * @tc.name: scale_build_014
320  * @tc.desc: Verify that the build function return a failed message with empty activation's buffer
321  * @tc.type: FUNC
322  */
323 HWTEST_F(ScaleBuilderTest, scale_build_014, TestSize.Level0)
324 {
325     SaveInputTensor(m_inputs, OH_NN_FLOAT32, m_dim, nullptr);
326     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_dim, nullptr);
327 
328     SaveAxisTensor(OH_NN_INT64, m_paramDim, nullptr, OH_NN_SCALE_AXIS);
329 
330     std::shared_ptr<NNTensor> activationTensor = TransToNNTensor(OH_NN_INT8, m_paramDim,
331         nullptr, OH_NN_SCALE_ACTIVATIONTYPE);
332     m_allTensors.emplace_back(activationTensor);
333 
334     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
335     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
336     activationTensor->SetBuffer(nullptr, 0);
337 }
338 
339 /**
340  * @tc.name: scale_get_primitive_001
341  * @tc.desc: Verify the GetPrimitive function return nullptr
342  * @tc.type: FUNC
343  */
344 HWTEST_F(ScaleBuilderTest, scale_get_primitive_001, TestSize.Level0)
345 {
346     LiteGraphTensorPtr primitive = m_builder.GetPrimitive();
347     LiteGraphTensorPtr expectPrimitive = {nullptr, DestroyLiteGraphPrimitive};
348     EXPECT_EQ(primitive, expectPrimitive);
349 }
350 
351 /**
352  * @tc.name: scale_get_primitive_002
353  * @tc.desc: Verify the normal params return behavior of the getprimitive function
354  * @tc.type: FUNC
355  */
356 HWTEST_F(ScaleBuilderTest, scale_get_primitive_002, TestSize.Level0)
357 {
358     SaveInputTensor(m_inputs, OH_NN_FLOAT32, m_dim, nullptr);
359     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_dim, nullptr);
360     SaveAxisTensor(OH_NN_INT64, m_paramDim, nullptr, OH_NN_SCALE_AXIS);
361     SaveActivationTensor(OH_NN_INT8, m_paramDim, nullptr, OH_NN_SCALE_ACTIVATIONTYPE);
362 
363     EXPECT_EQ(OH_NN_SUCCESS, m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors));
364     LiteGraphTensorPtr primitive = m_builder.GetPrimitive();
365     LiteGraphTensorPtr expectPrimitive = {nullptr, DestroyLiteGraphPrimitive};
366     EXPECT_NE(primitive, expectPrimitive);
367 
368     int64_t axisValue = 1;
369     int8_t activationValue = 0;
370     auto axisReturn = mindspore::lite::MindIR_ScaleFusion_GetAxis(primitive.get());
371     EXPECT_EQ(axisReturn, axisValue);
372     auto activationReturn = mindspore::lite::MindIR_ScaleFusion_GetActivationType(primitive.get());
373     EXPECT_EQ(activationReturn, activationValue);
374 }
375 } // namespace UnitTest
376 } // namespace NeuralNetworkRuntime
377 } // namespace OHOS