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