1 /*
2  * Copyright (c) 2024 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/clip_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 ClipBuilderTest : public OpsTest {
28 public:
29     void SetUp() override;
30     void TearDown() override;
31 
32 protected:
33     void SaveMax(OH_NN_DataType dataType,
34         const std::vector<int32_t> &dim,  const OH_NN_QuantParam* quantParam, OH_NN_TensorType type);
35     void SaveMin(OH_NN_DataType dataType,
36         const std::vector<int32_t> &dim,  const OH_NN_QuantParam* quantParam, OH_NN_TensorType type);
37 
38 protected:
39     ClipBuilder m_builder;
40     std::vector<uint32_t> m_inputs {0};
41     std::vector<uint32_t> m_outputs {1};
42     std::vector<uint32_t> m_params {2, 3};
43     std::vector<int32_t> m_dim {1, 2, 2, 1};
44     std::vector<int32_t> m_paramDim {};
45 };
46 
SetUp()47 void ClipBuilderTest::SetUp() {}
48 
TearDown()49 void ClipBuilderTest::TearDown() {}
50 
SaveMax(OH_NN_DataType dataType,const std::vector<int32_t> & dim,const OH_NN_QuantParam * quantParam,OH_NN_TensorType type)51 void ClipBuilderTest::SaveMax(OH_NN_DataType dataType,
52     const std::vector<int32_t> &dim, const OH_NN_QuantParam* quantParam, OH_NN_TensorType type)
53 {
54     std::shared_ptr<NNTensor> maxTensor = TransToNNTensor(dataType, dim, quantParam, type);
55     float* maxValue = new (std::nothrow) float [1]{10.0f};
56     EXPECT_NE(nullptr, maxValue);
57     maxTensor->SetBuffer(maxValue, sizeof(float));
58     m_allTensors.emplace_back(maxTensor);
59 }
60 
SaveMin(OH_NN_DataType dataType,const std::vector<int32_t> & dim,const OH_NN_QuantParam * quantParam,OH_NN_TensorType type)61 void ClipBuilderTest::SaveMin(OH_NN_DataType dataType,
62     const std::vector<int32_t> &dim, const OH_NN_QuantParam* quantParam, OH_NN_TensorType type)
63 {
64     std::shared_ptr<NNTensor> minTensor = TransToNNTensor(dataType, dim, quantParam, type);
65     float* minValue = new (std::nothrow) float [1]{1.0f};
66     EXPECT_NE(nullptr, minValue);
67     minTensor->SetBuffer(minValue, sizeof(float));
68     m_allTensors.emplace_back(minTensor);
69 }
70 
71 /**
72  * @tc.name: clip_build_001
73  * @tc.desc: Verify that the build function returns a successful message.
74  * @tc.type: FUNC
75  */
76 HWTEST_F(ClipBuilderTest, clip_build_001, TestSize.Level1)
77 {
78     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
79     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
80     SaveMax(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_CLIP_MAX);
81     SaveMin(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_CLIP_MIN);
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: clip_build_002
89  * @tc.desc: Verify that the build function returns a failed message with true m_isBuild.
90  * @tc.type: FUNC
91  */
92 HWTEST_F(ClipBuilderTest, clip_build_002, TestSize.Level1)
93 {
94     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
95     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
96     SaveMax(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_CLIP_MAX);
97     SaveMin(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_CLIP_MIN);
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: clip_build_003
106  * @tc.desc: Verify that the build function returns a failed message with invalided input.
107  * @tc.type: FUNC
108  */
109 HWTEST_F(ClipBuilderTest, clip_build_003, TestSize.Level1)
110 {
111     m_inputs = {0, 1};
112     m_outputs = {2};
113     m_params = {3, 4};
114 
115     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
116     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
117     SaveMax(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_CLIP_MAX);
118     SaveMin(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_CLIP_MIN);
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: clip_build_004
126  * @tc.desc: Verify that the build function returns a failed message with invalided output.
127  * @tc.type: FUNC
128  */
129 HWTEST_F(ClipBuilderTest, clip_build_004, TestSize.Level1)
130 {
131     m_outputs = {1, 2};
132     m_params = {3, 4};
133 
134     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
135     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
136     SaveMax(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_CLIP_MAX);
137     SaveMin(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_CLIP_MIN);
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: clip_build_005
145  * @tc.desc: Verify that the build function returns a failed message with empty allTensor.
146  * @tc.type: FUNC
147  */
148 HWTEST_F(ClipBuilderTest, clip_build_005, TestSize.Level1)
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: clip_build_006
156  * @tc.desc: Verify that the build function returns a failed message without output tensor.
157  * @tc.type: FUNC
158  */
159 HWTEST_F(ClipBuilderTest, clip_build_006, TestSize.Level1)
160 {
161     SaveInputTensor(m_inputs, OH_NN_INT32, 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: clip_build_007
169  * @tc.desc: Verify that the build function returns a failed message with invalid max's dataType.
170  * @tc.type: FUNC
171  */
172 HWTEST_F(ClipBuilderTest, clip_build_007, TestSize.Level1)
173 {
174     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
175     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
176 
177     std::shared_ptr<NNTensor> maxTensor = TransToNNTensor(OH_NN_INT64, m_paramDim,
178         nullptr, OH_NN_CLIP_MAX);
179     int64_t* maxValue = new (std::nothrow) int64_t [1]{10};
180     EXPECT_NE(nullptr, maxValue);
181     maxTensor->SetBuffer(maxValue, sizeof(int64_t));
182     m_allTensors.emplace_back(maxTensor);
183     SaveMin(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_CLIP_MIN);
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: clip_build_008
191  * @tc.desc: Verify that the build function returns a failed message with invalid min's dataType.
192  * @tc.type: FUNC
193  */
194 HWTEST_F(ClipBuilderTest, clip_build_008, TestSize.Level1)
195 {
196     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
197     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
198 
199     SaveMax(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_CLIP_MAX);
200     std::shared_ptr<NNTensor> minTensor = TransToNNTensor(OH_NN_INT64, m_paramDim,
201         nullptr, OH_NN_CLIP_MIN);
202     int64_t* minValue = new (std::nothrow) int64_t [1]{1};
203     EXPECT_NE(nullptr, minValue);
204     minTensor->SetBuffer(minValue, sizeof(int64_t));
205     m_allTensors.emplace_back(minTensor);
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 }
210 
211 /**
212  * @tc.name: clip_build_009
213  * @tc.desc: Verify that the build function returns a failed message with passing invalid max param.
214  * @tc.type: FUNC
215  */
216 HWTEST_F(ClipBuilderTest, clip_build_009, TestSize.Level1)
217 {
218     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
219     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
220 
221     SaveMax(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_MUL_ACTIVATION_TYPE);
222     SaveMin(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_CLIP_MIN);
223 
224     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
225     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
226 }
227 
228 /**
229  * @tc.name: clip_build_010
230  * @tc.desc: Verify that the build function returns a failed message with passing invalid min param.
231  * @tc.type: FUNC
232  */
233 HWTEST_F(ClipBuilderTest, clip_build_010, TestSize.Level1)
234 {
235     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
236     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
237 
238     SaveMax(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_CLIP_MAX);
239     SaveMin(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_MUL_ACTIVATION_TYPE);
240 
241     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
242     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
243 }
244 
245 /**
246  * @tc.name: clip_build_011
247  * @tc.desc: Verify that the build function returns a failed message without set buffer for max.
248  * @tc.type: FUNC
249  */
250 HWTEST_F(ClipBuilderTest, clip_build_011, TestSize.Level1)
251 {
252     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
253     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
254 
255     std::shared_ptr<NNTensor> maxTensor = TransToNNTensor(OH_NN_FLOAT32, m_paramDim,
256         nullptr, OH_NN_CLIP_MAX);
257     m_allTensors.emplace_back(maxTensor);
258     SaveMin(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_CLIP_MIN);
259 
260     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
261     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
262 }
263 
264 /**
265  * @tc.name: clip_build_012
266  * @tc.desc: Verify that the build function returns a failed message without set buffer for min.
267  * @tc.type: FUNC
268  */
269 HWTEST_F(ClipBuilderTest, clip_build_012, TestSize.Level1)
270 {
271     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
272     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
273 
274     SaveMax(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_CLIP_MAX);
275     std::shared_ptr<NNTensor> minTensor = TransToNNTensor(OH_NN_FLOAT32, m_paramDim,
276         nullptr, OH_NN_CLIP_MIN);
277     m_allTensors.emplace_back(minTensor);
278 
279     OH_NN_ReturnCode ret = m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors);
280     EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
281 }
282 
283 /**
284  * @tc.name: clip_getprimitive_001
285  * @tc.desc: Verify that the getPrimitive function returns a successful message.
286  * @tc.type: FUNC
287  */
288 HWTEST_F(ClipBuilderTest, clip_getprimitive_001, TestSize.Level1)
289 {
290     SaveInputTensor(m_inputs, OH_NN_INT32, m_dim, nullptr);
291     SaveOutputTensor(m_outputs, OH_NN_INT32, m_dim, nullptr);
292     SaveMax(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_CLIP_MAX);
293     SaveMin(OH_NN_FLOAT32, m_paramDim, nullptr, OH_NN_CLIP_MIN);
294 
295     float maxValue = 10.0f;
296     float minValue = 1.0f;
297     EXPECT_EQ(OH_NN_SUCCESS, m_builder.Build(m_params, m_inputsIndex, m_outputsIndex, m_allTensors));
298     LiteGraphPrimitvePtr primitive = m_builder.GetPrimitive();
299     LiteGraphPrimitvePtr expectPrimitive(nullptr, DestroyLiteGraphPrimitive);
300     EXPECT_NE(expectPrimitive, primitive);
301 
302     auto returnMaxValue = mindspore::lite::MindIR_Clip_GetMax(primitive.get());
303     EXPECT_EQ(returnMaxValue, maxValue);
304     auto returnMinValue = mindspore::lite::MindIR_Clip_GetMin(primitive.get());
305     EXPECT_EQ(returnMinValue, minValue);
306 }
307 
308 /**
309  * @tc.name: clip_getprimitive_002
310  * @tc.desc: Verify that the getPrimitive function returns a failed message without build.
311  * @tc.type: FUNC
312  */
313 HWTEST_F(ClipBuilderTest, clip_getprimitive_002, TestSize.Level1)
314 {
315     LiteGraphPrimitvePtr primitive = m_builder.GetPrimitive();
316     LiteGraphPrimitvePtr expectPrimitive(nullptr, DestroyLiteGraphPrimitive);
317     EXPECT_EQ(expectPrimitive, primitive);
318 }
319 }
320 }
321 }