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/pow_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 PowBuilderTest : public OpsTest {
28 public:
29     void SetUp() override;
30     void TearDown() override;
31 
32 protected:
33     void SaveShift(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 
38 protected:
39     PowBuilder m_builder;
40     std::vector<uint32_t> m_inputs {0, 1};
41     std::vector<uint32_t> m_outputs {2};
42     std::vector<uint32_t> m_params {3, 4};
43     std::vector<int32_t> m_dim {1, 2, 2, 1};
44     std::vector<int32_t> m_shiftDim {1};
45     std::vector<int32_t> m_scaleDim {1};
46 };
47 
SetUp()48 void PowBuilderTest::SetUp() {}
49 
TearDown()50 void PowBuilderTest::TearDown() {}
51 
SaveShift(OH_NN_DataType dataType,const std::vector<int32_t> & dim,const OH_NN_QuantParam * quantParam,OH_NN_TensorType type)52 void PowBuilderTest::SaveShift(OH_NN_DataType dataType,
53     const std::vector<int32_t> &dim, const OH_NN_QuantParam* quantParam, OH_NN_TensorType type)
54 {
55     std::shared_ptr<NNTensor> shiftTensor = TransToNNTensor(dataType, dim, quantParam, type);
56     float* shiftValue = new (std::nothrow) float[1] {0.0f};
57     EXPECT_NE(nullptr, shiftValue);
58     shiftTensor->SetBuffer(shiftValue, sizeof(float));
59     m_allTensors.emplace_back(shiftTensor);
60 }
61 
SaveScale(OH_NN_DataType dataType,const std::vector<int32_t> & dim,const OH_NN_QuantParam * quantParam,OH_NN_TensorType type)62 void PowBuilderTest::SaveScale(OH_NN_DataType dataType,
63     const std::vector<int32_t> &dim, const OH_NN_QuantParam* quantParam, OH_NN_TensorType type)
64 {
65     std::shared_ptr<NNTensor> scaleTensor = TransToNNTensor(dataType, dim, quantParam, type);
66     float* scaleValue = new (std::nothrow) float[1] {1.0f};
67     EXPECT_NE(nullptr, scaleValue);
68     scaleTensor->SetBuffer(scaleValue, sizeof(float));
69     m_allTensors.emplace_back(scaleTensor);
70 }
71 
72 /**
73  * @tc.name: pow_build_001
74  * @tc.desc: Provide normal input, output, and parameters to verify the normal behavior of the Build function
75  * @tc.type: FUNC
76  */
77 HWTEST_F(PowBuilderTest, pow_build_001, TestSize.Level1)
78 {
79     SaveInputTensor(m_inputs, OH_NN_FLOAT32, m_dim, nullptr);
80     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_dim, nullptr);
81     SaveShift(OH_NN_FLOAT32, m_shiftDim, nullptr, OH_NN_POW_SHIFT);
82     SaveScale(OH_NN_FLOAT32, m_scaleDim, nullptr, OH_NN_POW_SCALE);
83 
84     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
85     EXPECT_EQ(OH_NN_SUCCESS, ret);
86 }
87 
88 /**
89  * @tc.name: pow_build_002
90  * @tc.desc: Call Build func twice to verify the abnormal behavior of the Build function
91  * @tc.type: FUNC
92  */
93 HWTEST_F(PowBuilderTest, pow_build_002, TestSize.Level1)
94 {
95     SaveInputTensor(m_inputs, OH_NN_FLOAT32, m_dim, nullptr);
96     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_dim, nullptr);
97     SaveShift(OH_NN_FLOAT32, m_shiftDim, nullptr, OH_NN_POW_SHIFT);
98     SaveScale(OH_NN_FLOAT32, m_scaleDim, nullptr, OH_NN_POW_SCALE);
99 
100     EXPECT_EQ(OH_NN_SUCCESS, m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors));
101     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
102     EXPECT_EQ(OH_NN_OPERATION_FORBIDDEN, ret);
103 }
104 
105 /**
106  * @tc.name: pow_build_003
107  * @tc.desc: Provide one more than normal input to verify the abnormal behavior of the Build function
108  * @tc.type: FUNC
109  */
110 HWTEST_F(PowBuilderTest, pow_build_003, TestSize.Level1)
111 {
112     m_inputs = {0, 1, 2};
113     m_outputs = {3};
114     m_params = {4, 5};
115 
116     SaveInputTensor(m_inputs, OH_NN_FLOAT32, m_dim, nullptr);
117     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_dim, nullptr);
118     SaveShift(OH_NN_FLOAT32, m_shiftDim, nullptr, OH_NN_POW_SHIFT);
119     SaveScale(OH_NN_FLOAT32, m_scaleDim, nullptr, OH_NN_POW_SCALE);
120 
121     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
122     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
123 }
124 
125 /**
126  * @tc.name: pow_build_004
127  * @tc.desc: Provide one more than normal output to verify the abnormal behavior of the Build function
128  * @tc.type: FUNC
129  */
130 HWTEST_F(PowBuilderTest, pow_build_004, TestSize.Level1)
131 {
132     m_outputs = {2, 3};
133     m_params = {4, 5};
134 
135     SaveInputTensor(m_inputs, OH_NN_FLOAT32, m_dim, nullptr);
136     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_dim, nullptr);
137     SaveShift(OH_NN_FLOAT32, m_shiftDim, nullptr, OH_NN_POW_SHIFT);
138     SaveScale(OH_NN_FLOAT32, m_scaleDim, nullptr, OH_NN_POW_SCALE);
139 
140     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
141     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
142 }
143 
144 /**
145  * @tc.name: pow_build_005
146  * @tc.desc: Verify that the build function return a failed message with null allTensor
147  * @tc.type: FUNC
148  */
149 HWTEST_F(PowBuilderTest, pow_build_005, TestSize.Level1)
150 {
151     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputs, m_outputs, m_allTensors);
152     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
153 }
154 
155 /**
156  * @tc.name: pow_build_006
157  * @tc.desc: Verify that the build function return a failed message without output tensor
158  * @tc.type: FUNC
159  */
160 HWTEST_F(PowBuilderTest, pow_build_006, TestSize.Level1)
161 {
162     SaveInputTensor(m_inputs, OH_NN_FLOAT32, m_dim, nullptr);
163 
164     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputs, m_allTensors);
165     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
166 }
167 
168 /**
169  * @tc.name: pow_build_007
170  * @tc.desc: Verify that the build function returns a failed message with invalid shift's dataType.
171  * @tc.type: FUNC
172  */
173 HWTEST_F(PowBuilderTest, pow_build_007, TestSize.Level1)
174 {
175     SaveInputTensor(m_inputs, OH_NN_FLOAT32, m_dim, nullptr);
176     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_dim, nullptr);
177 
178     std::shared_ptr<NNTensor> shiftTensor = TransToNNTensor(OH_NN_INT64, m_shiftDim,
179         nullptr, OH_NN_POW_SHIFT);
180     int64_t* shiftValue = new (std::nothrow) int64_t[1] {0};
181     shiftTensor->SetBuffer(shiftValue, sizeof(shiftValue));
182     m_allTensors.emplace_back(shiftTensor);
183     SaveScale(OH_NN_FLOAT32, m_scaleDim, nullptr, OH_NN_POW_SCALE);
184 
185     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
186     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
187 }
188 
189 /**
190  * @tc.name: pow_build_008
191  * @tc.desc: Verify that the build function returns a failed message with invalid scale's dataType.
192  * @tc.type: FUNC
193  */
194 HWTEST_F(PowBuilderTest, pow_build_008, TestSize.Level1)
195 {
196     SaveInputTensor(m_inputs, OH_NN_FLOAT32, m_dim, nullptr);
197     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_dim, nullptr);
198 
199     SaveShift(OH_NN_FLOAT32, m_shiftDim, nullptr, OH_NN_POW_SHIFT);
200     std::shared_ptr<NNTensor> scaleTensor = TransToNNTensor(OH_NN_INT64, m_scaleDim,
201         nullptr, OH_NN_POW_SCALE);
202     int64_t* scaleValue = new (std::nothrow) int64_t[1] {1};
203     scaleTensor->SetBuffer(scaleValue, sizeof(scaleValue));
204     m_allTensors.emplace_back(scaleTensor);
205 
206     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
207     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
208 }
209 
210 /**
211  * @tc.name: pow_build_009
212  * @tc.desc: Verify that the build function returns a failed message with passing invalid shift param.
213  * @tc.type: FUNC
214  */
215 HWTEST_F(PowBuilderTest, pow_build_009, TestSize.Level1)
216 {
217     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
218     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
219     SaveShift(OH_NN_FLOAT32, m_shiftDim, nullptr, OH_NN_MUL_ACTIVATION_TYPE);
220     SaveScale(OH_NN_FLOAT32, m_scaleDim, nullptr, OH_NN_POW_SCALE);;
221 
222     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
223     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
224 }
225 
226 /**
227  * @tc.name: pow_build_010
228  * @tc.desc: Verify that the build function returns a failed message with passing invalid scale param.
229  * @tc.type: FUNC
230  */
231 HWTEST_F(PowBuilderTest, pow_build_010, TestSize.Level1)
232 {
233     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
234     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
235     SaveShift(OH_NN_FLOAT32, m_shiftDim, nullptr, OH_NN_POW_SHIFT);
236     SaveScale(OH_NN_FLOAT32, m_scaleDim, nullptr, OH_NN_MUL_ACTIVATION_TYPE);
237 
238     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
239     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
240 }
241 
242 /**
243  * @tc.name: pow_build_011
244  * @tc.desc: Verify that the build function returns a failed message without set buffer for shift.
245  * @tc.type: FUNC
246  */
247 HWTEST_F(PowBuilderTest, pow_build_011, TestSize.Level1)
248 {
249     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
250     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
251 
252     std::shared_ptr<NNTensor> shiftTensor = TransToNNTensor(OH_NN_FLOAT32, m_shiftDim,
253         nullptr, OH_NN_POW_SHIFT);
254     m_allTensors.emplace_back(shiftTensor);
255     SaveScale(OH_NN_FLOAT32, m_scaleDim, nullptr, OH_NN_POW_SCALE);;
256 
257     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
258     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
259 }
260 
261 /**
262  * @tc.name: pow_build_012
263  * @tc.desc: Verify that the build function returns a failed message without set buffer for scale.
264  * @tc.type: FUNC
265  */
266 HWTEST_F(PowBuilderTest, pow_build_012, TestSize.Level1)
267 {
268     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
269     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
270 
271     SaveShift(OH_NN_FLOAT32, m_shiftDim, nullptr, OH_NN_POW_SHIFT);
272     std::shared_ptr<NNTensor> scaleTensor = TransToNNTensor(OH_NN_FLOAT32, m_scaleDim,
273         nullptr, OH_NN_POW_SCALE);
274     m_allTensors.emplace_back(scaleTensor);
275 
276     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
277     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
278 }
279 
280 /**
281  * @tc.name: pow_get_primitive_001
282  * @tc.desc: Verify the GetPrimitive function return nullptr
283  * @tc.type: FUNC
284  */
285 HWTEST_F(PowBuilderTest, pow_get_primitive_001, TestSize.Level1)
286 {
287     LiteGraphTensorPtr primitive = m_builder.GetPrimitive();
288     LiteGraphTensorPtr expectPrimitive = {nullptr, DestroyLiteGraphPrimitive};
289     EXPECT_EQ(primitive, expectPrimitive);
290 }
291 
292 /**
293  * @tc.name: pow_get_primitive_002
294  * @tc.desc: Verify the normal params return behavior of the getprimitive function
295  * @tc.type: FUNC
296  */
297 HWTEST_F(PowBuilderTest, pow_get_primitive_002, TestSize.Level1)
298 {
299     SaveInputTensor(m_inputs, OH_NN_FLOAT32, m_dim, nullptr);
300     SaveOutputTensor(m_outputs, OH_NN_FLOAT32, m_dim, nullptr);
301 
302     SaveShift(OH_NN_FLOAT32, m_shiftDim, nullptr, OH_NN_POW_SHIFT);
303     SaveScale(OH_NN_FLOAT32, m_scaleDim, nullptr, OH_NN_POW_SCALE);
304 
305     float shiftValue = 0.0f;
306     float scaleValue = 1.0f;
307     EXPECT_EQ(OH_NN_SUCCESS, m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors));
308     LiteGraphTensorPtr powPrimitive = m_builder.GetPrimitive();
309     LiteGraphTensorPtr expectPrimitive = {nullptr, DestroyLiteGraphPrimitive};
310     EXPECT_NE(powPrimitive, expectPrimitive);
311 
312     auto returnShiftValue = mindspore::lite::MindIR_PowFusion_GetShift(powPrimitive.get());
313     EXPECT_EQ(shiftValue, returnShiftValue);
314     auto returnScaleValue = mindspore::lite::MindIR_PowFusion_GetScale(powPrimitive.get());
315     EXPECT_EQ(scaleValue, returnScaleValue);
316 }
317 } // namespace UnitTest
318 } // namespace NeuralNetworkRuntime
319 } // namespace OHOS