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/exp_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 ExpBuilderTest : public OpsTest {
28 public:
29     void SetUp() override;
30     void TearDown() override;
31 
32 protected:
33     void SaveBase(OH_NN_DataType dataType,
34         const std::vector<int32_t> &dim,  const OH_NN_QuantParam* quantParam, OH_NN_TensorType type);
35     void SaveScale(OH_NN_DataType dataType,
36         const std::vector<int32_t> &dim,  const OH_NN_QuantParam* quantParam, OH_NN_TensorType type);
37     void SaveShift(OH_NN_DataType dataType,
38         const std::vector<int32_t> &dim,  const OH_NN_QuantParam* quantParam, OH_NN_TensorType type);
39 
40 protected:
41     ExpBuilder m_builder;
42     std::vector<uint32_t> m_inputs {0};
43     std::vector<uint32_t> m_outputs {1};
44     std::vector<uint32_t> m_params {2, 3, 4};
45     std::vector<int32_t> m_dim {1, 2, 2, 1};
46     std::vector<int32_t> m_paramDim {};
47 };
48 
SetUp()49 void ExpBuilderTest::SetUp() {}
50 
TearDown()51 void ExpBuilderTest::TearDown() {}
52 
SaveBase(OH_NN_DataType dataType,const std::vector<int32_t> & dim,const OH_NN_QuantParam * quantParam,OH_NN_TensorType type)53 void ExpBuilderTest::SaveBase(OH_NN_DataType dataType,
54     const std::vector<int32_t> &dim, const OH_NN_QuantParam* quantParam, OH_NN_TensorType type)
55 {
56     std::shared_ptr<NNTensor> baseTensor = TransToNNTensor(dataType, dim, quantParam, type);
57     float* baseValue = new (std::nothrow) float [1]{-1.0f};
58     EXPECT_NE(nullptr, baseValue);
59     baseTensor->SetBuffer(baseValue, sizeof(float));
60     m_allTensors.emplace_back(baseTensor);
61 }
62 
SaveScale(OH_NN_DataType dataType,const std::vector<int32_t> & dim,const OH_NN_QuantParam * quantParam,OH_NN_TensorType type)63 void ExpBuilderTest::SaveScale(OH_NN_DataType dataType,
64     const std::vector<int32_t> &dim, const OH_NN_QuantParam* quantParam, OH_NN_TensorType type)
65 {
66     std::shared_ptr<NNTensor> scaleTensor = TransToNNTensor(dataType, dim, quantParam, type);
67     float* scaleValue = new (std::nothrow) float [1]{1.0f};
68     EXPECT_NE(nullptr, scaleValue);
69     scaleTensor->SetBuffer(scaleValue, sizeof(float));
70     m_allTensors.emplace_back(scaleTensor);
71 }
72 
SaveShift(OH_NN_DataType dataType,const std::vector<int32_t> & dim,const OH_NN_QuantParam * quantParam,OH_NN_TensorType type)73 void ExpBuilderTest::SaveShift(OH_NN_DataType dataType,
74     const std::vector<int32_t> &dim, const OH_NN_QuantParam* quantParam, OH_NN_TensorType type)
75 {
76     std::shared_ptr<NNTensor> shiftTensor = TransToNNTensor(dataType, dim, quantParam, type);
77     float* shiftValue = new (std::nothrow) float [1]{0.0f};
78     EXPECT_NE(nullptr, shiftValue);
79     shiftTensor->SetBuffer(shiftValue, sizeof(float));
80     m_allTensors.emplace_back(shiftTensor);
81 }
82 
83 /**
84  * @tc.name: exp_build_001
85  * @tc.desc: Verify that the build function returns a successful message.
86  * @tc.type: FUNC
87  */
88 HWTEST_F(ExpBuilderTest, exp_build_001, TestSize.Level1)
89 {
90     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
91     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
92     SaveBase(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_BASE);
93     SaveScale(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_SCALE);
94     SaveShift(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_SHIFT);
95 
96     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
97     EXPECT_EQ(OH_NN_SUCCESS, ret);
98 }
99 
100 /**
101  * @tc.name: exp_build_002
102  * @tc.desc: Verify that the build function returns a failed message with true m_isBuild.
103  * @tc.type: FUNC
104  */
105 HWTEST_F(ExpBuilderTest, exp_build_002, TestSize.Level1)
106 {
107     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
108     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
109     SaveBase(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_BASE);
110     SaveScale(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_SCALE);
111     SaveShift(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_SHIFT);
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: exp_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(ExpBuilderTest, exp_build_003, TestSize.Level1)
124 {
125     m_inputs = {0, 1};
126     m_outputs = {2};
127     m_params = {3, 4, 5};
128 
129     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
130     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
131     SaveBase(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_BASE);
132     SaveScale(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_SCALE);
133     SaveShift(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_SHIFT);
134 
135     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
136     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
137 }
138 
139 /**
140  * @tc.name: exp_build_004
141  * @tc.desc: Verify that the build function returns a failed message with invalided output.
142  * @tc.type: FUNC
143  */
144 HWTEST_F(ExpBuilderTest, exp_build_004, TestSize.Level1)
145 {
146     m_outputs = {1, 2};
147     m_params = {3, 4, 5};
148 
149     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
150     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
151     SaveBase(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_BASE);
152     SaveScale(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_SCALE);
153     SaveShift(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_SHIFT);
154 
155     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
156     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
157 }
158 
159 /**
160  * @tc.name: exp_build_005
161  * @tc.desc: Verify that the build function returns a failed message with empty allTensor.
162  * @tc.type: FUNC
163  */
164 HWTEST_F(ExpBuilderTest, exp_build_005, TestSize.Level1)
165 {
166     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputs, m_outputs, m_allTensors);
167     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
168 }
169 
170 /**
171  * @tc.name: exp_build_006
172  * @tc.desc: Verify that the build function returns a failed message without output tensor.
173  * @tc.type: FUNC
174  */
175 HWTEST_F(ExpBuilderTest, exp_build_006, TestSize.Level1)
176 {
177     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
178 
179     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputs, m_allTensors);
180     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
181 }
182 
183 /**
184  * @tc.name: exp_build_007
185  * @tc.desc: Verify that the build function returns a failed message with invalid base's dataType.
186  * @tc.type: FUNC
187  */
188 HWTEST_F(ExpBuilderTest, exp_build_007, TestSize.Level1)
189 {
190     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
191     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
192 
193     std::shared_ptr<NNTensor> baseTensor = TransToNNTensor(OH_NN_INT64, m_paramDim,
194         nullptr, OH_NN_EXP_BASE);
195     int64_t* baseValue = new (std::nothrow) int64_t [1]{-1};
196     EXPECT_NE(nullptr, baseValue);
197     baseTensor->SetBuffer(baseValue, sizeof(int64_t));
198     m_allTensors.emplace_back(baseTensor);
199     SaveScale(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_SCALE);
200     SaveShift(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_SHIFT);
201 
202     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
203     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
204 }
205 
206 /**
207  * @tc.name: exp_build_008
208  * @tc.desc: Verify that the build function returns a failed message with invalid scale's dataType.
209  * @tc.type: FUNC
210  */
211 HWTEST_F(ExpBuilderTest, exp_build_008, TestSize.Level1)
212 {
213     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
214     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
215 
216     SaveBase(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_BASE);
217     std::shared_ptr<NNTensor> scaleTensor = TransToNNTensor(OH_NN_INT64, m_paramDim,
218         nullptr, OH_NN_EXP_SCALE);
219     int64_t* scaleValue = new (std::nothrow) int64_t [1]{1};
220     EXPECT_NE(nullptr, scaleValue);
221     scaleTensor->SetBuffer(scaleValue, sizeof(int64_t));
222     m_allTensors.emplace_back(scaleTensor);
223     SaveShift(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_SHIFT);
224 
225     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
226     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
227 }
228 
229 /**
230  * @tc.name: exp_build_009
231  * @tc.desc: Verify that the build function returns a failed message with invalid base's dataType.
232  * @tc.type: FUNC
233  */
234 HWTEST_F(ExpBuilderTest, exp_build_009, TestSize.Level1)
235 {
236     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
237     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
238 
239     SaveBase(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_BASE);
240     SaveScale(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_SCALE);
241     std::shared_ptr<NNTensor> shiftTensor = TransToNNTensor(OH_NN_INT64, m_paramDim,
242         nullptr, OH_NN_EXP_SHIFT);
243     int64_t* shiftValue = new (std::nothrow) int64_t [1]{0};
244     EXPECT_NE(nullptr, shiftValue);
245     shiftTensor->SetBuffer(shiftValue, sizeof(int64_t));
246     m_allTensors.emplace_back(shiftTensor);
247 
248     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
249     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
250 }
251 
252 /**
253  * @tc.name: exp_build_010
254  * @tc.desc: Verify that the build function returns a failed message with passing invalid base param.
255  * @tc.type: FUNC
256  */
257 HWTEST_F(ExpBuilderTest, exp_build_010, TestSize.Level1)
258 {
259     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
260     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
261 
262     SaveBase(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_MUL_ACTIVATION_TYPE);
263     SaveScale(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_SCALE);
264     SaveShift(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_SHIFT);
265 
266     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
267     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
268 }
269 
270 /**
271  * @tc.name: exp_build_011
272  * @tc.desc: Verify that the build function returns a failed message with passing invalid scale param.
273  * @tc.type: FUNC
274  */
275 HWTEST_F(ExpBuilderTest, exp_build_011, TestSize.Level1)
276 {
277     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
278     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
279 
280     SaveBase(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_BASE);
281     SaveScale(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_MUL_ACTIVATION_TYPE);
282     SaveShift(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_SHIFT);
283 
284     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
285     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
286 }
287 
288 /**
289  * @tc.name: exp_build_012
290  * @tc.desc: Verify that the build function returns a failed message with passing invalid shift param.
291  * @tc.type: FUNC
292  */
293 HWTEST_F(ExpBuilderTest, exp_build_012, TestSize.Level1)
294 {
295     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
296     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
297 
298     SaveBase(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_BASE);
299     SaveScale(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_SCALE);
300     SaveShift(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_MUL_ACTIVATION_TYPE);
301 
302     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
303     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
304 }
305 
306 /**
307  * @tc.name: exp_build_013
308  * @tc.desc: Verify that the build function returns a failed message without set buffer for base.
309  * @tc.type: FUNC
310  */
311 HWTEST_F(ExpBuilderTest, exp_build_013, TestSize.Level1)
312 {
313     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
314     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
315 
316     std::shared_ptr<NNTensor> baseTensor = TransToNNTensor(OH_NN_FLOAT32, m_paramDim,
317         nullptr, OH_NN_EXP_BASE);
318     m_allTensors.emplace_back(baseTensor);
319     SaveScale(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_SCALE);
320     SaveShift(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_SHIFT);
321 
322     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
323     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
324 }
325 
326 /**
327  * @tc.name: exp_build_014
328  * @tc.desc: Verify that the build function returns a failed message without set buffer for scale.
329  * @tc.type: FUNC
330  */
331 HWTEST_F(ExpBuilderTest, exp_build_014, TestSize.Level1)
332 {
333     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
334     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
335 
336     SaveBase(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_BASE);
337     std::shared_ptr<NNTensor> scaleTensor = TransToNNTensor(OH_NN_FLOAT32, m_paramDim,
338         nullptr, OH_NN_EXP_SCALE);
339     m_allTensors.emplace_back(scaleTensor);
340     SaveShift(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_SHIFT);
341 
342 
343     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
344     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
345 }
346 
347 /**
348  * @tc.name: exp_build_015
349  * @tc.desc: Verify that the build function returns a failed message without set buffer for shift.
350  * @tc.type: FUNC
351  */
352 HWTEST_F(ExpBuilderTest, exp_build_015, TestSize.Level1)
353 {
354     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
355     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
356 
357     SaveBase(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_BASE);
358     SaveScale(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_SCALE);
359     std::shared_ptr<NNTensor> shiftTensor = TransToNNTensor(OH_NN_FLOAT32, m_paramDim,
360         nullptr, OH_NN_EXP_SHIFT);
361     m_allTensors.emplace_back(shiftTensor);
362 
363     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
364     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
365 }
366 
367 /**
368  * @tc.name: exp_getprimitive_001
369  * @tc.desc: Verify that the getPrimitive function returns a successful message
370  * @tc.type: FUNC
371  */
372 HWTEST_F(ExpBuilderTest, exp_getprimitive_001, TestSize.Level1)
373 {
374     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
375     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
376     SaveBase(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_BASE);
377     SaveScale(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_SCALE);
378     SaveShift(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_EXP_SHIFT);
379 
380     float baseValue = -1.0f;
381     float scaleValue = 1.0f;
382     float shiftValue = 0.0f;
383     EXPECT_EQ(OH_NN_SUCCESS, m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors));
384     LiteGraphPrimitvePtr primitive = m_builder.GetPrimitive();
385     LiteGraphPrimitvePtr expectPrimitive(nullptr, DestroyLiteGraphPrimitive);
386     EXPECT_NE(expectPrimitive, primitive);
387 
388     auto returnBaseValue = mindspore::lite::MindIR_ExpFusion_GetBase(primitive.get());
389     EXPECT_EQ(returnBaseValue, baseValue);
390     auto returnScaleValue = mindspore::lite::MindIR_ExpFusion_GetScale(primitive.get());
391     EXPECT_EQ(returnScaleValue, scaleValue);
392     auto returnShiftValue = mindspore::lite::MindIR_ExpFusion_GetShift(primitive.get());
393     EXPECT_EQ(returnShiftValue, shiftValue);
394 }
395 
396 /**
397  * @tc.name: exp_getprimitive_002
398  * @tc.desc: Verify that the getPrimitive function returns a failed message without build.
399  * @tc.type: FUNC
400  */
401 HWTEST_F(ExpBuilderTest, exp_getprimitive_002, TestSize.Level1)
402 {
403     LiteGraphPrimitvePtr primitive = m_builder.GetPrimitive();
404     LiteGraphPrimitvePtr expectPrimitive(nullptr, DestroyLiteGraphPrimitive);
405     EXPECT_EQ(expectPrimitive, primitive);
406 }
407 }
408 }
409 }