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/sub_builder.h"
17 
18 #include <gtest/gtest.h>
19 #include "nn_tensor.h"
20 #include "ops_test.h"
21 
22 using namespace testing;
23 using namespace testing::ext;
24 using namespace OHOS::NeuralNetworkRuntime::Ops;
25 
26 namespace OHOS {
27 namespace NeuralNetworkRuntime {
28 namespace UnitTest {
29 class SubBuilderTest : public OpsTest {
30 protected:
31     void InitTensor(const std::vector<uint32_t>& inputsIndex,
32         const std::vector<uint32_t>& outputsIndex) override;
33     void SaveActivateTypeTensor(OH_NN_DataType dataType, const std::vector<int32_t> &dim,
34         const OH_NN_QuantParam* quantParam, OH_NN_TensorType type);
35 
36 protected:
37     SubBuilder m_builder;
38     int8_t m_expectActivationTypeValue {0};
39 };
40 
SaveActivateTypeTensor(OH_NN_DataType dataType,const std::vector<int32_t> & dim,const OH_NN_QuantParam * quantParam,OH_NN_TensorType type)41 void SubBuilderTest::SaveActivateTypeTensor(OH_NN_DataType dataType, const std::vector<int32_t> &dim,
42     const OH_NN_QuantParam* quantParam, OH_NN_TensorType type)
43 {
44     std::shared_ptr<NNTensor> activationTypeTensor = TransToNNTensor(dataType, dim, quantParam, type);
45     int8_t* activationTypeValue = new (std::nothrow) int8_t[1]{OH_NN_FUSED_RELU6};
46     EXPECT_NE(nullptr, activationTypeValue);
47     activationTypeTensor->SetBuffer(activationTypeValue, sizeof(int8_t));
48     m_allTensors.emplace_back(activationTypeTensor);
49     m_expectActivationTypeValue = mindspore::lite::ACTIVATION_TYPE_RELU6;
50 }
51 
InitTensor(const std::vector<uint32_t> & inputsIndex,const std::vector<uint32_t> & outputsIndex)52 void SubBuilderTest::InitTensor(const std::vector<uint32_t>& inputsIndex, const std::vector<uint32_t>& outputsIndex)
53 {
54     std::vector<uint32_t> paramsIndex = { 3 };
55     std::vector<int32_t> inputDim = {3};
56     std::vector<int32_t> OutputDim = {3};
57 
58     m_paramsIndex = paramsIndex;
59     SaveInputTensor(inputsIndex, OH_NN_FLOAT32, inputDim, nullptr);
60     SaveOutputTensor(outputsIndex, OH_NN_FLOAT32, OutputDim, nullptr);
61 }
62 
63 /**
64  * @tc.name: sub_build_001
65  * @tc.desc: Provide normal input, output, and parameters to verify the normal behavior of the Build function
66  * @tc.type: FUNC
67  */
68 HWTEST_F(SubBuilderTest, sub_build_001, TestSize.Level0)
69 {
70     std::vector<uint32_t> inputsIndex = { 0, 1 };
71     std::vector<uint32_t> outputsIndex = { 2 };
72     std::vector<int32_t> paramDim = {};
73 
74     InitTensor(inputsIndex, outputsIndex);
75     SaveActivateTypeTensor(OH_NN_INT8, paramDim, nullptr, OH_NN_SUB_ACTIVATIONTYPE);
76 
77     OH_NN_ReturnCode ret = m_builder.Build(m_paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors);
78     EXPECT_EQ(OH_NN_SUCCESS, ret);
79 }
80 
81 /**
82  * @tc.name: sub_build_002
83  * @tc.desc: Call Build func twice to verify the abnormal behavior of the Build function
84  * @tc.type: FUNC
85  */
86 HWTEST_F(SubBuilderTest, sub_build_002, TestSize.Level0)
87 {
88     std::vector<uint32_t> inputsIndex = { 0, 1 };
89     std::vector<uint32_t> outputsIndex = { 2 };
90     std::vector<int32_t> paramDim = {};
91 
92     InitTensor(inputsIndex, outputsIndex);
93     SaveActivateTypeTensor(OH_NN_INT8, paramDim, nullptr, OH_NN_SUB_ACTIVATIONTYPE);
94 
95     EXPECT_EQ(OH_NN_SUCCESS, m_builder.Build(m_paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors));
96     OH_NN_ReturnCode ret = m_builder.Build(m_paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors);
97     EXPECT_EQ(OH_NN_OPERATION_FORBIDDEN, ret);
98 }
99 
100 /**
101  * @tc.name: sub_build_003
102  * @tc.desc:Provide one more than normal input to verify the abnormal behavior of the Build function
103  * @tc.type: FUNC
104  */
105 HWTEST_F(SubBuilderTest, sub_build_003, TestSize.Level0)
106 {
107     std::vector<uint32_t> inputsIndex = { 0, 1, 2, 3 };
108     std::vector<uint32_t> outputsIndex = { 4 };
109     std::vector<int32_t> paramDim = {};
110 
111     InitTensor(inputsIndex, outputsIndex);
112     SaveActivateTypeTensor(OH_NN_INT8, paramDim, nullptr, OH_NN_SUB_ACTIVATIONTYPE);
113 
114     OH_NN_ReturnCode ret = m_builder.Build(m_paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors);
115     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
116 }
117 
118 /**
119  * @tc.name: sub_build_004
120  * @tc.desc: Provide one more than normal output to verify the abnormal behavior of the Build function
121  * @tc.type: FUNC
122  */
123 HWTEST_F(SubBuilderTest, sub_build_004, TestSize.Level0)
124 {
125     std::vector<uint32_t> inputsIndex = { 0, 1 };
126     std::vector<uint32_t> outputsIndex = { 2, 3 };
127     std::vector<int32_t> paramDim = {};
128 
129     InitTensor(inputsIndex, outputsIndex);
130     SaveActivateTypeTensor(OH_NN_INT8, paramDim, nullptr, OH_NN_SUB_ACTIVATIONTYPE);
131 
132     OH_NN_ReturnCode ret = m_builder.Build(m_paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors);
133     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
134 }
135 
136 /**
137  * @tc.name: sub_build_005
138  * @tc.desc: Provide empty input, output, and parameters to verify the abnormal behavior of the Build function
139  * @tc.type: FUNC
140  */
141 HWTEST_F(SubBuilderTest, sub_build_005, TestSize.Level0)
142 {
143     std::vector<uint32_t> inputsIndex = { 0, 1, 2 };
144     std::vector<uint32_t> outputsIndex = { 3 };
145     std::vector<uint32_t> paramsIndex = { 4 };
146 
147     OH_NN_ReturnCode ret = m_builder.Build(paramsIndex, inputsIndex, outputsIndex, m_allTensors);
148     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
149 }
150 
151 /**
152  * @tc.name: sub_build_006
153  * @tc.desc: Provide empty output to verify the abnormal behavior of the Build function
154  * @tc.type: FUNC
155  */
156 HWTEST_F(SubBuilderTest, sub_build_006, TestSize.Level0)
157 {
158     std::vector<uint32_t> inputsIndex = { 0, 1, 2 };
159     std::vector<uint32_t> outputsIndex = {};
160     std::vector<int32_t> paramDim = {};
161 
162     InitTensor(inputsIndex, outputsIndex);
163     SaveActivateTypeTensor(OH_NN_BOOL, paramDim, nullptr, OH_NN_SUB_ACTIVATIONTYPE);
164 
165     OH_NN_ReturnCode ret = m_builder.Build(m_paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors);
166     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
167 }
168 
169 /**
170  * @tc.name: sub_build_007
171  * @tc.desc: Provide param type error to verify the abnormal behavior of the Build function
172  * @tc.type: FUNC
173  */
174 HWTEST_F(SubBuilderTest, sub_build_007, TestSize.Level0)
175 {
176     std::vector<uint32_t> inputsIndex = { 0, 1 };
177     std::vector<uint32_t> outputsIndex = { 2 };
178     std::vector<int32_t> paramDim = {};
179 
180     InitTensor(inputsIndex, outputsIndex);
181     SaveActivateTypeTensor(OH_NN_BOOL, paramDim, nullptr, OH_NN_SUB_ACTIVATIONTYPE);
182 
183     OH_NN_ReturnCode ret = m_builder.Build(m_paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors);
184     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
185 }
186 
187 /**
188  * @tc.name: sub_build_008
189  * @tc.desc:Provide param type error to verify the abnormal behavior of the Build function
190  * @tc.type: FUNC
191  */
192 HWTEST_F(SubBuilderTest, sub_build_008, TestSize.Level0)
193 {
194     std::vector<uint32_t> inputsIndex = { 0, 1 };
195     std::vector<uint32_t> outputsIndex = { 2 };
196     std::vector<int32_t> paramDim = {};
197 
198     InitTensor(inputsIndex, outputsIndex);
199     SaveActivateTypeTensor(OH_NN_INT64, paramDim, nullptr, OH_NN_SUB_ACTIVATIONTYPE);
200 
201     OH_NN_ReturnCode ret = m_builder.Build(m_paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors);
202     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
203 }
204 
205 /**
206  * @tc.name: sub_build_009
207  * @tc.desc: Provide activate type parameter buffer is nullptr to verify the abnormal behavior of the Build function
208  * @tc.type: FUNC
209  */
210 HWTEST_F(SubBuilderTest, sub_build_009, TestSize.Level0)
211 {
212     std::vector<uint32_t> inputsIndex = { 0, 1 };
213     std::vector<uint32_t> outputsIndex = { 2 };
214     std::vector<int32_t> paramDim = {};
215 
216     InitTensor(inputsIndex, outputsIndex);
217 
218     std::shared_ptr<NNTensor> activationTypeTensor = TransToNNTensor(OH_NN_INT8, paramDim, nullptr,
219         OH_NN_SUB_ACTIVATIONTYPE);
220     activationTypeTensor->SetBuffer(nullptr, 0);
221     m_allTensors.emplace_back(activationTypeTensor);
222 
223     OH_NN_ReturnCode ret = m_builder.Build(m_paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors);
224     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
225 }
226 
227 /**
228  * @tc.name: sub_build_010
229  * @tc.desc: Provide parameter is not scaler to verify the abnormal behavior of the Build function
230  * @tc.type: FUNC
231  */
232 HWTEST_F(SubBuilderTest, sub_build_010, TestSize.Level0)
233 {
234     std::vector<uint32_t> inputsIndex = { 0, 1 };
235     std::vector<uint32_t> outputsIndex = { 2 };
236     std::vector<int32_t> paramDim = {1, 2};
237 
238     InitTensor(inputsIndex, outputsIndex);
239     SaveActivateTypeTensor(OH_NN_INT8, paramDim, nullptr, OH_NN_SUB_ACTIVATIONTYPE);
240 
241     OH_NN_ReturnCode ret = m_builder.Build(m_paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors);
242     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
243 }
244 
245 /**
246  * @tc.name: sub_build_011
247  * @tc.desc: Provide invalid parameter type to verify the abnormal behavior of the Build function
248  * @tc.type: FUNC
249  */
250 HWTEST_F(SubBuilderTest, sub_build_011, TestSize.Level0)
251 {
252     std::vector<uint32_t> inputsIndex = { 0, 1 };
253     std::vector<uint32_t> outputsIndex = { 2 };
254     std::vector<int32_t> paramDim = {};
255 
256     InitTensor(inputsIndex, outputsIndex);
257     SaveActivateTypeTensor(OH_NN_INT8, paramDim, nullptr, OH_NN_SCALE_AXIS);
258 
259     OH_NN_ReturnCode ret = m_builder.Build(m_paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors);
260     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
261 }
262 
263 /**
264  * @tc.name: sub_build_012
265  * @tc.desc: Provide invalid param value to verify the abnormal behavior of the Build function
266  * @tc.type: FUNC
267  */
268 HWTEST_F(SubBuilderTest, sub_build_012, TestSize.Level0)
269 {
270     std::vector<uint32_t> inputsIndex = { 0, 1 };
271     std::vector<uint32_t> outputsIndex = { 2 };
272     std::vector<int32_t> paramDim = {};
273 
274     InitTensor(inputsIndex, outputsIndex);
275 
276     std::shared_ptr<NNTensor> activationTypeTensor = TransToNNTensor(OH_NN_INT8, paramDim, nullptr,
277         OH_NN_SUB_ACTIVATIONTYPE);
278     int8_t* activationTypeValue = new (std::nothrow) int8_t[1]{-1};
279     EXPECT_NE(nullptr, activationTypeValue);
280     activationTypeTensor->SetBuffer(activationTypeValue, sizeof(int8_t));
281     m_allTensors.emplace_back(activationTypeTensor);
282 
283     OH_NN_ReturnCode ret = m_builder.Build(m_paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors);
284     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
285 }
286 
287 /**
288  * @tc.name: sub_get_primitive_001
289  * @tc.desc: Verify the GetPrimitive function return nullptr
290  * @tc.type: FUNC
291  */
292 HWTEST_F(SubBuilderTest, sub_get_primitive_001, TestSize.Level0)
293 {
294     LiteGraphTensorPtr primitive = m_builder.GetPrimitive();
295     LiteGraphTensorPtr expectPrimitive = { nullptr, DestroyLiteGraphPrimitive };
296     EXPECT_EQ(primitive, expectPrimitive);
297 }
298 
299 /**
300  * @tc.name: sub_get_primitive_002
301  * @tc.desc: Verify the normal params return behavior of the getprimitive function
302  * @tc.type: FUNC
303  */
304 HWTEST_F(SubBuilderTest, sub_get_primitive_002, TestSize.Level0)
305 {
306     std::vector<uint32_t> inputsIndex = { 0, 1 };
307     std::vector<uint32_t> outputsIndex = { 2 };
308     std::vector<int32_t> paramDim = {};
309 
310     InitTensor(inputsIndex, outputsIndex);
311     SaveActivateTypeTensor(OH_NN_INT8, paramDim, nullptr, OH_NN_SUB_ACTIVATIONTYPE);
312 
313     OH_NN_ReturnCode ret = m_builder.Build(m_paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors);
314     EXPECT_EQ(OH_NN_SUCCESS, ret);
315     LiteGraphTensorPtr primitive = m_builder.GetPrimitive();
316     LiteGraphTensorPtr expectPrimitive = { nullptr, DestroyLiteGraphPrimitive };
317     EXPECT_NE(primitive, expectPrimitive);
318 
319     auto returnValue = mindspore::lite::MindIR_SubFusion_GetActivationType(primitive.get());
320     EXPECT_EQ(returnValue, m_expectActivationTypeValue);
321 }
322 } // namespace UnitTest
323 } // namespace NeuralNetworkRuntime
324 } // namespace OHOS
325