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/top_k_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 TopKBuilderTest : public OpsTest {
30 protected:
31 void InitTensor(const std::vector<uint32_t>& inputsIndex,
32 const std::vector<uint32_t>& outputsIndex) override;
33 void SaveSortedTensor(OH_NN_DataType dataType, const std::vector<int32_t> &dim,
34 const OH_NN_QuantParam* quantParam, OH_NN_TensorType type);
35 void SaveAxisTensor(OH_NN_DataType dataType, const std::vector<int32_t> &dim,
36 const OH_NN_QuantParam* quantParam, OH_NN_TensorType type);
37
38 protected:
39 TopKBuilder m_builder;
40 bool m_topkValue {false};
41 };
42
InitTensor(const std::vector<uint32_t> & inputsIndex,const std::vector<uint32_t> & outputsIndex)43 void TopKBuilderTest::InitTensor(const std::vector<uint32_t>& inputsIndex, const std::vector<uint32_t>& outputsIndex)
44 {
45 std::vector<int32_t> inputDim = {9};
46 std::vector<int32_t> OutputDim = {3};
47
48 SaveInputTensor(inputsIndex, OH_NN_FLOAT32, inputDim, nullptr);
49 SaveOutputTensor(outputsIndex, OH_NN_FLOAT32, OutputDim, nullptr);
50 }
51
SaveAxisTensor(OH_NN_DataType dataType,const std::vector<int32_t> & dim,const OH_NN_QuantParam * quantParam,OH_NN_TensorType type)52 void TopKBuilderTest::SaveAxisTensor(OH_NN_DataType dataType, const std::vector<int32_t> &dim,
53 const OH_NN_QuantParam* quantParam, OH_NN_TensorType type)
54 {
55 std::shared_ptr<NNTensor> axisTensor = TransToNNTensor(dataType, dim, quantParam, type);
56 int64_t* axisValue = new (std::nothrow) int64_t[1] {0};
57 EXPECT_NE(nullptr, axisValue);
58 axisTensor->SetBuffer(axisValue, sizeof(int64_t));
59 m_allTensors.emplace_back(axisTensor);
60 }
61
SaveSortedTensor(OH_NN_DataType dataType,const std::vector<int32_t> & dim,const OH_NN_QuantParam * quantParam,OH_NN_TensorType type)62 void TopKBuilderTest::SaveSortedTensor(OH_NN_DataType dataType, const std::vector<int32_t> &dim,
63 const OH_NN_QuantParam* quantParam, OH_NN_TensorType type)
64 {
65 std::shared_ptr<NNTensor> topkTensor = TransToNNTensor(dataType, dim, quantParam, type);
66 bool* topkValue = new (std::nothrow) bool[1] {true};
67 EXPECT_NE(nullptr, topkValue);
68 topkTensor->SetBuffer(topkValue, sizeof(bool));
69 m_allTensors.emplace_back(topkTensor);
70 m_topkValue = *topkValue;
71 }
72
73 /**
74 * @tc.name: topk_build_001
75 * @tc.desc: Provide normal input, output, and parameters to verify the normal behavior of the Build function
76 * @tc.type: FUNC
77 */
78 HWTEST_F(TopKBuilderTest, topk_build_001, TestSize.Level0)
79 {
80 std::vector<uint32_t> inputsIndex = { 0, 1 };
81 std::vector<uint32_t> outputsIndex = { 2, 3 };
82 std::vector<uint32_t> paramsIndex = { 4, 5 };
83 std::vector<int32_t> paramDim = {};
84
85 InitTensor(inputsIndex, outputsIndex);
86 SaveSortedTensor(OH_NN_BOOL, paramDim, nullptr, OH_NN_TOP_K_SORTED);
87 SaveAxisTensor(OH_NN_INT64, paramDim, nullptr, OH_NN_TOP_K_AXIS);
88
89 OH_NN_ReturnCode ret = m_builder.Build(paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors);
90 EXPECT_EQ(OH_NN_SUCCESS, ret);
91 }
92
93 /**
94 * @tc.name: topk_build_002
95 * @tc.desc: Call Build func twice to verify the abnormal behavior of the Build function
96 * @tc.type: FUNC
97 */
98 HWTEST_F(TopKBuilderTest, topk_build_002, TestSize.Level0)
99 {
100 std::vector<uint32_t> inputsIndex = { 0, 1 };
101 std::vector<uint32_t> outputsIndex = { 2, 3 };
102 std::vector<uint32_t> paramsIndex = { 4, 5 };
103 std::vector<int32_t> paramDim = {};
104
105 InitTensor(inputsIndex, outputsIndex);
106 SaveSortedTensor(OH_NN_BOOL, paramDim, nullptr, OH_NN_TOP_K_SORTED);
107 SaveAxisTensor(OH_NN_INT64, paramDim, nullptr, OH_NN_TOP_K_AXIS);
108
109 EXPECT_EQ(OH_NN_SUCCESS, m_builder.Build(paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors));
110 OH_NN_ReturnCode ret = m_builder.Build(paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors);
111 EXPECT_EQ(OH_NN_OPERATION_FORBIDDEN, ret);
112 }
113
114 /**
115 * @tc.name: topk_build_003
116 * @tc.desc: Provide one more than normal input to verify the abnormal behavior of the Build function
117 * @tc.type: FUNC
118 */
119 HWTEST_F(TopKBuilderTest, topk_build_003, TestSize.Level0)
120 {
121 std::vector<uint32_t> inputsIndex = { 0, 1, 2, 3 };
122 std::vector<uint32_t> outputsIndex = { 4, 5 };
123 std::vector<uint32_t> paramsIndex = { 6, 7 };
124 std::vector<int32_t> paramDim = {};
125
126 InitTensor(inputsIndex, outputsIndex);
127 SaveSortedTensor(OH_NN_BOOL, paramDim, nullptr, OH_NN_TOP_K_SORTED);
128 SaveAxisTensor(OH_NN_INT64, paramDim, nullptr, OH_NN_TOP_K_AXIS);
129
130 OH_NN_ReturnCode ret = m_builder.Build(paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors);
131 EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
132 }
133
134 /**
135 * @tc.name: topk_builder_004
136 * @tc.desc: Provide one more than normal output to verify the abnormal behavior of the Build function
137 * @tc.type: FUNC
138 */
139 HWTEST_F(TopKBuilderTest, topk_builder_004, TestSize.Level0)
140 {
141 std::vector<uint32_t> inputsIndex = { 0, 1 };
142 std::vector<uint32_t> outputsIndex = { 2, 3, 4 };
143 std::vector<uint32_t> paramsIndex = { 5, 6 };
144 std::vector<int32_t> paramDim = {};
145
146 InitTensor(inputsIndex, outputsIndex);
147 SaveSortedTensor(OH_NN_BOOL, paramDim, nullptr, OH_NN_TOP_K_SORTED);
148 SaveAxisTensor(OH_NN_INT64, paramDim, nullptr, OH_NN_TOP_K_AXIS);
149
150 OH_NN_ReturnCode ret = m_builder.Build(paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors);
151 EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
152 }
153
154 /**
155 * @tc.name: topk_build_005
156 * @tc.desc: Provide empty input, output, and parameters to verify the abnormal behavior of the Build function
157 * @tc.type: FUNC
158 */
159 HWTEST_F(TopKBuilderTest, topk_build_005, TestSize.Level0)
160 {
161 std::vector<uint32_t> inputsIndex = { 0, 1, 2 };
162 std::vector<uint32_t> outputsIndex = { 3, 4 };
163 std::vector<uint32_t> paramsIndex = { 5, 6, 7 };
164
165 OH_NN_ReturnCode ret = m_builder.Build(paramsIndex, inputsIndex, outputsIndex, m_allTensors);
166 EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
167 }
168
169 /**
170 * @tc.name: topk_build_006
171 * @tc.desc: Provide param type error to verify the abnormal behavior of the Build function
172 * @tc.type: FUNC
173 */
174 HWTEST_F(TopKBuilderTest, topk_build_006, TestSize.Level0)
175 {
176 std::vector<uint32_t> inputsIndex = { 0, 1 };
177 std::vector<uint32_t> outputsIndex = { 2, 3 };
178 std::vector<uint32_t> paramsIndex = { 4, 5 };
179 std::vector<int32_t> paramDim = {};
180
181 InitTensor(inputsIndex, outputsIndex);
182 SaveSortedTensor(OH_NN_INT8, paramDim, nullptr, OH_NN_TOP_K_SORTED);
183 SaveAxisTensor(OH_NN_INT64, paramDim, nullptr, OH_NN_TOP_K_AXIS);
184
185 OH_NN_ReturnCode ret = m_builder.Build(paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors);
186 EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
187 }
188
189 /**
190 * @tc.name: topk_build_007
191 * @tc.desc: Provide param type error to verify the abnormal behavior of the Build function
192 * @tc.type: FUNC
193 */
194 HWTEST_F(TopKBuilderTest, topk_build_007, TestSize.Level0)
195 {
196 std::vector<uint32_t> inputsIndex = { 0, 1 };
197 std::vector<uint32_t> outputsIndex = { 2, 3 };
198 std::vector<uint32_t> paramsIndex = { 4, 5 };
199 std::vector<int32_t> paramDim = {};
200
201 InitTensor(inputsIndex, outputsIndex);
202 SaveSortedTensor(OH_NN_BOOL, paramDim, nullptr, OH_NN_TOP_K_SORTED);
203 SaveAxisTensor(OH_NN_INT32, paramDim, nullptr, OH_NN_TOP_K_AXIS);
204
205 OH_NN_ReturnCode ret = m_builder.Build(paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors);
206 EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
207 }
208
209 /**
210 * @tc.name: topk_build_008
211 * @tc.desc: Provide sorted parameter buffer is nullptr to verify the abnormal behavior of the Build function
212 * @tc.type: FUNC
213 */
214 HWTEST_F(TopKBuilderTest, topk_build_008, TestSize.Level0)
215 {
216 std::vector<uint32_t> inputsIndex = { 0, 1 };
217 std::vector<uint32_t> outputsIndex = { 2, 3 };
218 std::vector<uint32_t> paramsIndex = { 4, 5 };
219 std::vector<int32_t> paramDim = {};
220
221 InitTensor(inputsIndex, outputsIndex);
222
223 std::shared_ptr<NNTensor> topkTensor = TransToNNTensor(OH_NN_BOOL, paramDim, nullptr, OH_NN_TOP_K_SORTED);
224 topkTensor->SetBuffer(nullptr, 0);
225 m_allTensors.emplace_back(topkTensor);
226 SaveAxisTensor(OH_NN_INT64, paramDim, nullptr, OH_NN_TOP_K_AXIS);
227
228 OH_NN_ReturnCode ret = m_builder.Build(paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors);
229 EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
230 }
231
232 /**
233 * @tc.name: topk_build_009
234 * @tc.desc: Provide axis parameter buffer is nullptr to verify the abnormal behavior of the Build function
235 * @tc.type: FUNC
236 */
237 HWTEST_F(TopKBuilderTest, topk_build_009, TestSize.Level0)
238 {
239 std::vector<uint32_t> inputsIndex = { 0, 1 };
240 std::vector<uint32_t> outputsIndex = { 2, 3 };
241 std::vector<uint32_t> paramsIndex = { 4, 5 };
242 std::vector<int32_t> paramDim = {};
243
244 InitTensor(inputsIndex, outputsIndex);
245
246 SaveSortedTensor(OH_NN_BOOL, paramDim, nullptr, OH_NN_TOP_K_SORTED);
247 std::shared_ptr<NNTensor> axisTensor = TransToNNTensor(OH_NN_INT64, paramDim, nullptr, OH_NN_TOP_K_AXIS);
248 axisTensor->SetBuffer(nullptr, 0);
249 m_allTensors.emplace_back(axisTensor);
250
251 OH_NN_ReturnCode ret = m_builder.Build(paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors);
252 EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
253 }
254
255 /**
256 * @tc.name: topk_build_010
257 * @tc.desc: Provide invalid parameter type to verify the abnormal behavior of the Build function
258 * @tc.type: FUNC
259 */
260 HWTEST_F(TopKBuilderTest, topk_build_010, TestSize.Level0)
261 {
262 std::vector<uint32_t> inputsIndex = { 0, 1 };
263 std::vector<uint32_t> outputsIndex = { 2, 3 };
264 std::vector<uint32_t> paramsIndex = { 4, 5 };
265 std::vector<int32_t> paramDim = {};
266
267 InitTensor(inputsIndex, outputsIndex);
268 SaveSortedTensor(OH_NN_BOOL, paramDim, nullptr, OH_NN_SCALE_AXIS);
269 SaveAxisTensor(OH_NN_INT64, paramDim, nullptr, OH_NN_TOP_K_AXIS);
270
271 OH_NN_ReturnCode ret = m_builder.Build(paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors);
272 EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
273 }
274
275 /**
276 * @tc.name: topk_build_011
277 * @tc.desc: Provide invalid parameter type to verify the abnormal behavior of the Build function
278 * @tc.type: FUNC
279 */
280 HWTEST_F(TopKBuilderTest, topk_build_011, TestSize.Level0)
281 {
282 std::vector<uint32_t> inputsIndex = { 0, 1 };
283 std::vector<uint32_t> outputsIndex = { 2, 3 };
284 std::vector<uint32_t> paramsIndex = { 4, 5 };
285 std::vector<int32_t> paramDim = {};
286
287 InitTensor(inputsIndex, outputsIndex);
288 SaveSortedTensor(OH_NN_BOOL, paramDim, nullptr, OH_NN_TOP_K_SORTED);
289 SaveAxisTensor(OH_NN_INT64, paramDim, nullptr, OH_NN_SCALE_AXIS);
290
291 OH_NN_ReturnCode ret = m_builder.Build(paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors);
292 EXPECT_EQ(OH_NN_INVALID_PARAMETER, ret);
293 }
294
295 /**
296 * @tc.name: topk_get_primitive_001
297 * @tc.desc: Verify the GetPrimitive function return nullptr
298 * @tc.type: FUNC
299 */
300 HWTEST_F(TopKBuilderTest, topk_get_primitive_001, TestSize.Level0)
301 {
302 LiteGraphTensorPtr primitive = m_builder.GetPrimitive();
303 LiteGraphTensorPtr expectPrimitive = { nullptr, DestroyLiteGraphPrimitive };
304 EXPECT_EQ(primitive, expectPrimitive);
305 }
306
307 /**
308 * @tc.name: topk_get_primitive_002
309 * @tc.desc: Verify the normal params return behavior of the getprimitive function
310 * @tc.type: FUNC
311 */
312 HWTEST_F(TopKBuilderTest, topk_get_primitive_002, TestSize.Level0)
313 {
314 std::vector<uint32_t> inputsIndex = { 0, 1 };
315 std::vector<uint32_t> outputsIndex = { 2, 3 };
316 std::vector<uint32_t> paramsIndex = { 4, 5 };
317 std::vector<int32_t> paramDim = {};
318
319 InitTensor(inputsIndex, outputsIndex);
320 SaveSortedTensor(OH_NN_BOOL, paramDim, nullptr, OH_NN_TOP_K_SORTED);
321 SaveAxisTensor(OH_NN_INT64, paramDim, nullptr, OH_NN_TOP_K_AXIS);
322
323 int64_t axisValue = 0;
324 EXPECT_EQ(OH_NN_SUCCESS, m_builder.Build(paramsIndex, m_inputsIndex, m_outputsIndex, m_allTensors));
325 LiteGraphTensorPtr primitive = m_builder.GetPrimitive();
326 LiteGraphTensorPtr expectPrimitive = { nullptr, DestroyLiteGraphPrimitive };
327 EXPECT_NE(primitive, expectPrimitive);
328
329 auto sortedReturn = mindspore::lite::MindIR_TopKFusion_GetSorted(primitive.get());
330 EXPECT_EQ(sortedReturn, m_topkValue);
331 auto axisReturn = mindspore::lite::MindIR_TopKFusion_GetAxis(primitive.get());
332 EXPECT_EQ(axisReturn, axisValue);
333 }
334 } // namespace UnitTest
335 } // namespace NeuralNetworkRuntime
336 } // namespace OHOS
337