1 /*
2 * Copyright (c) 2021 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 "gtest/gtest.h"
17
18 #include <cstddef>
19 #include <string>
20
21 #include "utils/aie_guard.h"
22 #include "utils/aie_macros.h"
23 #include "utils/encdec/include/data_decoder.h"
24 #include "utils/encdec/include/data_encoder.h"
25 #include "utils/encdec/include/encdec_facade.h"
26 #include "utils/log/aie_log.h"
27
28 using namespace OHOS::AI;
29 using namespace testing::ext;
30 namespace {
31 constexpr size_t ARRAY_LEN = 10;
32 constexpr int g_int = 12;
33 constexpr char g_char = 'd';
34 constexpr float g_float = 0.99f;
35 constexpr long long g_long = 123456789L;
36 const std::string g_string = "random string";
37 const std::string g_emptyString = "";
38
39 typedef struct {
40 char foo;
41 int bar;
42 } StructWithPadding; // definition of struct with padding(blank memory) between members
43
44 typedef struct {
45 int foo;
46 StructWithPadding bar;
47 } NestedStruct;
48
49 typedef struct {
50 size_t objectsNum;
51 StructWithPadding* objects;
52 } StructWithPointer;
53
54 typedef struct {
55 size_t foo;
56 int barArray[ARRAY_LEN];
57 } StructWithArray;
58
59 template<typename Type>
CompareData(const Type & input,const Type & output)60 bool CompareData(const Type &input, const Type &output)
61 {
62 return input == output;
63 }
64
CompareData(const StructWithPadding & input,const StructWithPadding & output)65 bool CompareData(const StructWithPadding &input, const StructWithPadding &output)
66 {
67 return (input.foo == output.foo) && (input.bar == output.bar);
68 }
69
CompareData(const NestedStruct & input,const NestedStruct & output)70 bool CompareData(const NestedStruct &input, const NestedStruct &output)
71 {
72 return (input.foo == output.foo) && CompareData(input.bar, output.bar);
73 }
74
CompareData(const StructWithPointer & input,const StructWithPointer & output)75 bool CompareData(const StructWithPointer &input, const StructWithPointer &output)
76 {
77 if (input.objectsNum != output.objectsNum) {
78 return false;
79 }
80 for (unsigned int i = 0; i < input.objectsNum; ++i) {
81 if (!CompareData(input.objects[i], output.objects[i])) {
82 return false;
83 }
84 }
85 return true;
86 }
87
CompareData(const StructWithArray & input,const StructWithArray & output)88 bool CompareData(const StructWithArray &input, const StructWithArray &output)
89 {
90 if (input.foo != output.foo) {
91 return false;
92 }
93 for (unsigned int i = 0; i < ARRAY_LEN; ++i) {
94 if (!CompareData(input.barArray[i], output.barArray[i])) {
95 return false;
96 }
97 }
98 return true;
99 }
100
GenStructWithPadding(const int myNum,const char myChar)101 StructWithPadding GenStructWithPadding(const int myNum, const char myChar)
102 {
103 StructWithPadding structWithPadding = {
104 .foo = myChar,
105 .bar = myNum
106 };
107 return structWithPadding;
108 }
109
GenNestedStruct()110 NestedStruct GenNestedStruct()
111 {
112 NestedStruct nestedStruct = {
113 .foo = g_int,
114 .bar = GenStructWithPadding(g_int, g_char)
115 };
116 return nestedStruct;
117 }
118
GenStructWithPointer(const size_t objectsNum)119 StructWithPointer GenStructWithPointer(const size_t objectsNum)
120 {
121 StructWithPointer structWithPointer {
122 .objectsNum = objectsNum
123 };
124 if (objectsNum > 0) {
125 AIE_NEW(structWithPointer.objects, StructWithPadding[objectsNum]);
126 for (size_t i = 0; i < objectsNum; ++i) {
127 structWithPointer.objects[i] = GenStructWithPadding(g_int, g_char);
128 }
129 }
130 return structWithPointer;
131 }
132
ReleaseStructWithPointer(StructWithPointer & structWithPointer)133 void ReleaseStructWithPointer(StructWithPointer &structWithPointer)
134 {
135 AIE_DELETE_ARRAY(structWithPointer.objects);
136 }
137
GenStructWithArray(const size_t num)138 StructWithArray GenStructWithArray(const size_t num)
139 {
140 StructWithArray structWithArray {
141 .foo = num
142 };
143 for (size_t i = 0; i < num && i < ARRAY_LEN; ++i) {
144 structWithArray.barArray[i] = g_int;
145 }
146 return structWithArray;
147 }
148
PolluteData(DataInfo & dataInfo)149 void PolluteData(DataInfo &dataInfo)
150 {
151 *(reinterpret_cast<size_t*>(dataInfo.data + dataInfo.length - sizeof(size_t))) = 0U;
152 }
153
BasicTypesCheck(bool normalMode=true)154 void BasicTypesCheck(bool normalMode = true)
155 {
156 DataInfo dataInfo {};
157 int retCode = EncdecFacade::ProcessEncode(dataInfo, g_int, g_char, g_float, g_long, g_string, g_emptyString);
158 MallocPointerGuard<unsigned char> dataInfoGuard(dataInfo.data);
159 ASSERT_EQ(retCode, RETCODE_SUCCESS);
160 if (!normalMode) {
161 PolluteData(dataInfo);
162 }
163 int outInt {};
164 char outChar {};
165 float outFloat {};
166 long long outLong {};
167 std::string outString {};
168 std::string outEmptyString {};
169
170 retCode = EncdecFacade::ProcessDecode(dataInfo, outInt, outChar, outFloat, outLong, outString,
171 outEmptyString);
172 if (normalMode) {
173 ASSERT_EQ(retCode, RETCODE_SUCCESS);
174 ASSERT_TRUE(CompareData(g_int, outInt));
175 ASSERT_TRUE(CompareData(g_char, outChar));
176 ASSERT_TRUE(CompareData(g_float, outFloat));
177 ASSERT_TRUE(CompareData(g_long, outLong));
178 ASSERT_TRUE(CompareData(g_string, outString));
179 ASSERT_TRUE(CompareData(g_emptyString, outEmptyString));
180 } else {
181 ASSERT_NE(retCode, RETCODE_SUCCESS);
182 }
183 }
184
StructCheck(bool normalMode=true)185 void StructCheck(bool normalMode = true)
186 {
187 DataInfo dataInfo {};
188 StructWithPadding structWithPadding = GenStructWithPadding(g_int, g_char);
189 NestedStruct nestedStruct = GenNestedStruct();
190 StructWithArray structWithArray = GenStructWithArray(ARRAY_LEN);
191
192 int retCode = EncdecFacade::ProcessEncode(dataInfo, structWithPadding, nestedStruct, structWithArray);
193 MallocPointerGuard<unsigned char> dataInfoGuard(dataInfo.data);
194 ASSERT_EQ(retCode, RETCODE_SUCCESS);
195 if (!normalMode) {
196 PolluteData(dataInfo);
197 }
198 StructWithPadding outStructWithPadding {};
199 NestedStruct outNestedStruct {};
200 StructWithArray outStructWithArray {};
201
202 retCode = EncdecFacade::ProcessDecode(dataInfo, outStructWithPadding, outNestedStruct, outStructWithArray);
203 if (normalMode) {
204 ASSERT_EQ(retCode, RETCODE_SUCCESS);
205 ASSERT_TRUE(CompareData(structWithPadding, outStructWithPadding));
206 ASSERT_TRUE(CompareData(nestedStruct, outNestedStruct));
207 ASSERT_TRUE(CompareData(structWithArray, outStructWithArray));
208 } else {
209 ASSERT_NE(retCode, RETCODE_SUCCESS);
210 }
211 }
212
StructWithPointerCheck(bool normalMode=true)213 void StructWithPointerCheck(bool normalMode = true)
214 {
215 for (size_t classNum = 0; classNum <= ARRAY_LEN; ++classNum) {
216 HILOGD ("[Test]Normal test StructWithPointer, classNum = %d.************", classNum);
217 StructWithPointer structWithPointer = GenStructWithPointer(classNum);
218 DataInfo dataInfo {};
219 int retCode = EncdecFacade::ProcessEncode(dataInfo, structWithPointer);
220 MallocPointerGuard<unsigned char> dataInfoGuard(dataInfo.data);
221 ASSERT_EQ(retCode, RETCODE_SUCCESS);
222 if (!normalMode) {
223 PolluteData(dataInfo);
224 }
225 StructWithPointer res {};
226 retCode = EncdecFacade::ProcessDecode(dataInfo, res);
227 if (normalMode) {
228 ASSERT_EQ(retCode, RETCODE_SUCCESS);
229 ASSERT_TRUE(CompareData(structWithPointer, res));
230 ReleaseStructWithPointer(res);
231 } else {
232 ASSERT_NE(retCode, RETCODE_SUCCESS);
233 }
234 ReleaseStructWithPointer(structWithPointer);
235 }
236 }
237 }
238
239 namespace OHOS {
240 namespace AI {
241 template<>
EncodeOneParameter(const StructWithPointer & val)242 int DataEncoder::EncodeOneParameter(const StructWithPointer &val)
243 {
244 if (RecursiveEncode(val.objectsNum) != RETCODE_SUCCESS) {
245 HILOGE("[EncdecTest]Serialize memory error.");
246 return RETCODE_FAILURE;
247 }
248 for (size_t i = 0; i < val.objectsNum; ++i) {
249 if (RecursiveEncode(val.objects[i]) != RETCODE_SUCCESS) {
250 HILOGE("[EncdecTest]Serialize memory error.");
251 return RETCODE_FAILURE;
252 }
253 }
254 return RETCODE_SUCCESS;
255 }
256
257 template<>
DecodeOneParameter(StructWithPointer & val)258 int DataDecoder::DecodeOneParameter(StructWithPointer &val)
259 {
260 if (RecursiveDecode(val.objectsNum) != RETCODE_SUCCESS) {
261 HILOGE("[EncdecTest]Unserialize failed.");
262 return RETCODE_FAILURE;
263 }
264 if (val.objectsNum > 0) {
265 AIE_NEW(val.objects, StructWithPadding[val.objectsNum]);
266 for (size_t i = 0; i < val.objectsNum; ++i) {
267 if (RecursiveDecode(val.objects[i]) != RETCODE_SUCCESS) {
268 AIE_DELETE_ARRAY(val.objects);
269 return RETCODE_FAILURE;
270 }
271 }
272 }
273 return RETCODE_SUCCESS;
274 }
275 } // namespace AI
276 } // namespace OHOS
277
278 class EncdecTest : public testing::Test {
279 public:
280 // SetUpTestCase:The preset action of the test suite is executed before the first TestCase
SetUpTestCase()281 static void SetUpTestCase() {};
282
283 // TearDownTestCase:The test suite cleanup action is executed after the last TestCase
TearDownTestCase()284 static void TearDownTestCase() {};
285
286 // SetUp:Execute before each test case
SetUp()287 void SetUp() override {};
288
289 // TearDown:Execute after each test case
TearDown()290 void TearDown() override {};
291 };
292
293 /**
294 * @tc.name: EncdecNormalCheck001
295 * @tc.desc: Test encode decode function for non-pointer type in normal mode.
296 * @tc.type: FUNC
297 * @tc.require: AR000F77MR
298 */
299 HWTEST_F(EncdecTest, EncdecNormalCheck001, TestSize.Level0)
300 {
301 HILOGD ("**********[Test]Normal test start, all the result should return 0************");
302 BasicTypesCheck();
303 HILOGD ("**********[Test]Normal test end************");
304 }
305
306 /**
307 * @tc.name: EncdecNormalCheck002
308 * @tc.desc: Test encode decode function for struct without pointer.
309 * @tc.type: FUNC
310 * @tc.require: AR000F77MR
311 */
312 HWTEST_F(EncdecTest, EncdecNormalCheck002, TestSize.Level0)
313 {
314 HILOGD ("**********[Test]Normal test start, all the result should return 0************");
315 StructCheck();
316 HILOGD ("**********[Test]Normal test end************");
317 }
318
319 /**
320 * @tc.name: EncdecNormalCheck003
321 * @tc.desc: Test encode decode function for types which include pointers in normal mode.
322 * @tc.type: FUNC
323 * @tc.require: AR000F77MR
324 */
325 HWTEST_F(EncdecTest, EncdecNormalCheck003, TestSize.Level0)
326 {
327 HILOGD ("**********[Test]Normal test start, all the result should return 0************");
328 StructWithPointerCheck();
329 HILOGD ("**********[Test]Normal test end************");
330 }
331
332 /**
333 * @tc.name: EncdecAbnormalCheck001
334 * @tc.desc: Test encode decode function for non-pointer type in abnormal mode.
335 * @tc.type: FUNC
336 * @tc.require: AR000F77MR
337 */
338 HWTEST_F(EncdecTest, EncdecAbnormalCheck001, TestSize.Level1)
339 {
340 HILOGD ("**********[Test]abnormal test start************");
341 BasicTypesCheck(false);
342 HILOGD ("**********[Test]abnormal test end************");
343 }
344
345 /**
346 * @tc.name: EncdecAbnormalCheck002
347 * @tc.desc: Test encode decode function for types which include pointers in abnormal mode.
348 * @tc.type: FUNC
349 * @tc.require: AR000F77MR
350 */
351 HWTEST_F(EncdecTest, EncdecAbnormalCheck002, TestSize.Level1)
352 {
353 HILOGD ("**********[Test]abnormal test start************");
354 StructCheck(false);
355 HILOGD ("**********[Test]abnormal test end************");
356 }
357
358 /**
359 * @tc.name: EncdecAbnormalCheck003
360 * @tc.desc: Test encode decode function for types which include pointers in normal mode.
361 * @tc.type: FUNC
362 * @tc.require: AR000F77MR
363 */
364 HWTEST_F(EncdecTest, EncdecAbnormalCheck003, TestSize.Level1)
365 {
366 HILOGD ("**********[Test]Normal test start, all the result should return 0************");
367 StructWithPointerCheck(false);
368 HILOGD ("**********[Test]Normal test end************");
369 }
370