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/unsqueeze_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 UnsqueezeBuilderTest : public OpsTest {
30 protected:
31     void InitTensor(const std::vector<uint32_t>& inputsIndex,
32         const std::vector<uint32_t>& outputsIndex) override;
33     void SaveAxisTensor(OH_NN_DataType dataType, const std::vector<int32_t> &dim,
34         const OH_NN_QuantParam* quantParam, OH_NN_TensorType type);
35 
36 protected:
37     UnsqueezeBuilder m_builder;
38     std::vector<int64_t> m_expectAxisValue;
39 };
40 
SaveAxisTensor(OH_NN_DataType dataType,const std::vector<int32_t> & dim,const OH_NN_QuantParam * quantParam,OH_NN_TensorType type)41 void UnsqueezeBuilderTest::SaveAxisTensor(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> axisTensor = TransToNNTensor(dataType, dim, quantParam, type);
45     int64_t* axisValue = new (std::nothrow) int64_t[1]{1};
46     axisTensor->SetBuffer(axisValue, sizeof(int64_t));
47     m_allTensors.emplace_back(axisTensor);
48     m_expectAxisValue.emplace_back(*axisValue);
49 }
50 
InitTensor(const std::vector<uint32_t> & inputsIndex,const std::vector<uint32_t> & outputsIndex)51 void UnsqueezeBuilderTest::InitTensor(const std::vector<uint32_t>& inputsIndex,
52     const std::vector<uint32_t>& outputsIndex)
53 {
54     std::vector<uint32_t> paramsIndex = { 2 };
55     std::vector<int32_t> inputDim = {1, 5, 1};
56     std::vector<int32_t> OutputDim = {1, 1, 5, 1};
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: unsqueeze_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(UnsqueezeBuilderTest, unsqueeze_build_001, TestSize.Level0)
69 {
70     std::vector<uint32_t> inputsIndex = { 0 };
71     std::vector<uint32_t> outputsIndex = { 1 };
72     std::vector<int32_t> paramDim = {};
73 
74     InitTensor(inputsIndex, outputsIndex);
75     SaveAxisTensor(OH_NN_INT64, paramDim, nullptr, OH_NN_UNSQUEEZE_AXIS);
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: unsqueeze_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(UnsqueezeBuilderTest, unsqueeze_build_002, TestSize.Level0)
87 {
88     std::vector<uint32_t> inputsIndex = { 0 };
89     std::vector<uint32_t> outputsIndex = { 1 };
90     std::vector<int32_t> paramDim = {};
91 
92     InitTensor(inputsIndex, outputsIndex);
93     SaveAxisTensor(OH_NN_INT64, paramDim, nullptr, OH_NN_UNSQUEEZE_AXIS);
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: unsqueeze_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(UnsqueezeBuilderTest, unsqueeze_build_003, TestSize.Level0)
106 {
107     std::vector<uint32_t> inputsIndex = { 0, 1, 2 };
108     std::vector<uint32_t> outputsIndex = { 3 };
109     std::vector<int32_t> paramDim = {};
110 
111     InitTensor(inputsIndex, outputsIndex);
112     SaveAxisTensor(OH_NN_INT64, paramDim, nullptr, OH_NN_UNSQUEEZE_AXIS);
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: unsqueeze_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(UnsqueezeBuilderTest, unsqueeze_build_004, TestSize.Level0)
124 {
125     std::vector<uint32_t> inputsIndex = { 0 };
126     std::vector<uint32_t> outputsIndex = { 1, 2 };
127     std::vector<int32_t> paramDim = {};
128 
129     InitTensor(inputsIndex, outputsIndex);
130     SaveAxisTensor(OH_NN_INT64, paramDim, nullptr, OH_NN_UNSQUEEZE_AXIS);
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: unsqueeze_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(UnsqueezeBuilderTest, unsqueeze_build_005, TestSize.Level0)
142 {
143     std::vector<uint32_t> inputsIndex = { 0 };
144     std::vector<uint32_t> outputsIndex = { 1 };
145     std::vector<uint32_t> paramsIndex = { 2 };
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: unsqueeze_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(UnsqueezeBuilderTest, unsqueeze_build_006, TestSize.Level0)
157 {
158     std::vector<uint32_t> inputsIndex = { 0 };
159     std::vector<uint32_t> outputsIndex = {};
160     std::vector<int32_t> paramDim = {};
161 
162     InitTensor(inputsIndex, outputsIndex);
163     SaveAxisTensor(OH_NN_INT64, paramDim, nullptr, OH_NN_UNSQUEEZE_AXIS);
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: unsqueeze_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(UnsqueezeBuilderTest, unsqueeze_build_007, TestSize.Level0)
175 {
176     std::vector<uint32_t> inputsIndex = { 0 };
177     std::vector<uint32_t> outputsIndex = { 1 };
178     std::vector<int32_t> paramDim = {};
179 
180     InitTensor(inputsIndex, outputsIndex);
181     SaveAxisTensor(OH_NN_INT8, paramDim, nullptr, OH_NN_UNSQUEEZE_AXIS);
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: unsqueeze_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(UnsqueezeBuilderTest, unsqueeze_build_008, TestSize.Level0)
193 {
194     std::vector<uint32_t> inputsIndex = { 0 };
195     std::vector<uint32_t> outputsIndex = { 1 };
196     std::vector<int32_t> paramDim = {};
197 
198     InitTensor(inputsIndex, outputsIndex);
199     SaveAxisTensor(OH_NN_INT32, paramDim, nullptr, OH_NN_UNSQUEEZE_AXIS);
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: unsqueeze_build_009
207  * @tc.desc: Provide axis parameter buffer is nullptr to verify the abnormal behavior of the Build function
208  * @tc.type: FUNC
209  */
210 HWTEST_F(UnsqueezeBuilderTest, unsqueeze_build_009, TestSize.Level0)
211 {
212     std::vector<uint32_t> inputsIndex = { 0 };
213     std::vector<uint32_t> outputsIndex = { 1 };
214     std::vector<int32_t> paramDim = {};
215 
216     InitTensor(inputsIndex, outputsIndex);
217 
218     std::shared_ptr<NNTensor> axisTensor = TransToNNTensor(OH_NN_INT64, paramDim, nullptr, OH_NN_UNSQUEEZE_AXIS);
219     axisTensor->SetBuffer(nullptr, 0);
220     m_allTensors.emplace_back(axisTensor);
221 
222     OH_NN_ReturnCode ret = m_builder.Build(m_paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors);
223     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
224 }
225 
226 /**
227  * @tc.name: unsqueeze_build_010
228  * @tc.desc: Provide axis parameter is not scaler to verify the abnormal behavior of the Build function
229  * @tc.type: FUNC
230  */
231 HWTEST_F(UnsqueezeBuilderTest, unsqueeze_build_010, TestSize.Level0)
232 {
233     std::vector<uint32_t> inputsIndex = { 0 };
234     std::vector<uint32_t> outputsIndex = { 1 };
235     std::vector<int32_t> paramDim = {1, 2};
236 
237     InitTensor(inputsIndex, outputsIndex);
238     SaveAxisTensor(OH_NN_INT64, paramDim, nullptr, OH_NN_UNSQUEEZE_AXIS);
239 
240     OH_NN_ReturnCode ret = m_builder.Build(m_paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors);
241     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
242 }
243 
244 /**
245  * @tc.name: unsqueeze_build_011
246  * @tc.desc: Provide invalid parameter type to verify the abnormal behavior of the Build function
247  * @tc.type: FUNC
248  */
249 HWTEST_F(UnsqueezeBuilderTest, unsqueeze_build_011, TestSize.Level0)
250 {
251     std::vector<uint32_t> inputsIndex = { 0 };
252     std::vector<uint32_t> outputsIndex = { 1 };
253     std::vector<int32_t> paramDim = {};
254 
255     InitTensor(inputsIndex, outputsIndex);
256     SaveAxisTensor(OH_NN_INT64, paramDim, nullptr, OH_NN_SCALE_AXIS);
257 
258     OH_NN_ReturnCode ret = m_builder.Build(m_paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors);
259     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
260 }
261 
262 /**
263  * @tc.name: unsqueeze_get_primitive_001
264  * @tc.desc: Verify the GetPrimitive function return nullptr
265  * @tc.type: FUNC
266  */
267 HWTEST_F(UnsqueezeBuilderTest, unsqueeze_get_primitive_001, TestSize.Level0)
268 {
269     LiteGraphTensorPtr primitive = m_builder.GetPrimitive();
270     LiteGraphTensorPtr expectPrimitive = { nullptr, DestroyLiteGraphPrimitive };
271     EXPECT_EQ(primitive, expectPrimitive);
272 }
273 
274 /**
275  * @tc.name: unsqueeze_get_primitive_002
276  * @tc.desc: Verify the normal params return behavior of the getprimitive function
277  * @tc.type: FUNC
278  */
279 HWTEST_F(UnsqueezeBuilderTest, unsqueeze_get_primitive_002, TestSize.Level0)
280 {
281     std::vector<uint32_t> inputsIndex = { 0 };
282     std::vector<uint32_t> outputsIndex = { 1 };
283     std::vector<int32_t> paramDim = {};
284 
285     InitTensor(inputsIndex, outputsIndex);
286     SaveAxisTensor(OH_NN_INT64, paramDim, nullptr, OH_NN_UNSQUEEZE_AXIS);
287 
288     EXPECT_EQ(OH_NN_SUCCESS, m_builder.Build(m_paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors));
289     LiteGraphTensorPtr primitive = m_builder.GetPrimitive();
290     LiteGraphTensorPtr expectPrimitive = { nullptr, DestroyLiteGraphPrimitive };
291     EXPECT_NE(primitive, expectPrimitive);
292 
293     auto axisReturn = mindspore::lite::MindIR_Unsqueeze_GetAxis(primitive.get());
294     auto axisReturnSize = axisReturn.size();
295     for (size_t i = 0; i < axisReturnSize; ++i) {
296         EXPECT_EQ(axisReturn[i], m_expectAxisValue[i]);
297     }
298 }
299 } // namespace UnitTest
300 } // namespace NeuralNetworkRuntime
301 } // namespace OHOS
302