• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 #include <string>
18 #include <vector>
19 #include <cstring>
20 
21 #include "comm_log.h"
22 #include "softbus_adapter_mem.h"
23 #include "softbus_error_code.h"
24 #include "softbus_tlv_utils.h"
25 
26 using namespace std;
27 using namespace testing::ext;
28 
29 namespace OHOS {
30 class TlvFrame {
31 public:
32     int type_;
33     string value_;
34 
TlvFrame(int type,string value)35     TlvFrame(int type, string value) : type_(type), value_(value) {}
36 };
37 
38 class SoftBusTlvUtilsTest : public testing::Test {
39 public:
SetUpTestCase(void)40     static void SetUpTestCase(void) { }
TearDownTestCase(void)41     static void TearDownTestCase(void) { }
42 };
43 
BytesToHexString(const uint8_t * data,uint32_t len)44 static string BytesToHexString(const uint8_t *data, uint32_t len)
45 {
46     std::stringstream hexStream;
47     for (uint32_t i = 0; i < len; i++) {
48         hexStream << "0x" << std::hex << std::setw(2) << std::setfill('0') << static_cast<uint32_t>(data[i]) << ", ";
49     }
50     return hexStream.str();
51 }
52 
TLvFeatureTest(uint8_t tSize,uint8_t lSize,vector<TlvFrame> & testcases)53 static void TLvFeatureTest(uint8_t tSize, uint8_t lSize, vector<TlvFrame> &testcases)
54 {
55     COMM_LOGI(COMM_UTILS, "tSize=%{public}u, lSize=%{public}u", tSize, lSize);
56     int32_t ret;
57     TlvObject *sendObj = CreateTlvObject(tSize, lSize);
58     ASSERT_TRUE(sendObj != nullptr);
59     for (auto testcase: testcases) {
60         COMM_LOGI(COMM_UTILS, "t=%{public}d, l=%{public}d, v=%{public}s",
61             testcase.type_, (int)testcase.value_.length(), testcase.value_.c_str());
62         ret = AddTlvMember(sendObj, testcase.type_,
63             testcase.value_.length(), (const uint8_t *)testcase.value_.c_str());
64         EXPECT_EQ(ret, SOFTBUS_OK);
65     }
66     uint8_t *output = nullptr;
67     uint32_t outputSize = 0;
68     ret = GetTlvBinary(sendObj, &output, &outputSize);
69     EXPECT_EQ(ret, SOFTBUS_OK);
70     DestroyTlvObject(sendObj);
71 
72     COMM_LOGI(COMM_UTILS, "output=%{public}s, outputSize=%{public}u",
73         BytesToHexString(output, outputSize).c_str(), outputSize);
74 
75     uint32_t length = 0;
76     uint8_t *value = nullptr;
77     TlvObject *recvObj = CreateTlvObject(tSize, lSize);
78     ASSERT_TRUE(recvObj != nullptr);
79     ret = SetTlvBinary(recvObj, output, outputSize);
80     EXPECT_EQ(ret, SOFTBUS_OK);
81 
82     for (auto testcase: testcases) {
83         ret = GetTlvMember(recvObj, testcase.type_, &length, &value);
84         EXPECT_EQ(ret, SOFTBUS_OK);
85         ASSERT_EQ(length, testcase.value_.length());
86         EXPECT_EQ(memcmp(value, testcase.value_.c_str(), length), 0);
87     }
88     DestroyTlvObject(recvObj);
89     SoftBusFree(output);
90 }
91 
92 /**
93  * @tc.name: TlvUtilsNormalUsage
94  * @tc.desc: TlvUtilsNormalUsage
95  * @tc.type: FUNC
96  * @tc.require:
97  */
98 HWTEST_F(SoftBusTlvUtilsTest, TlvUtilsNormalUsage, TestSize.Level0)
99 {
100     COMM_LOGI(COMM_UTILS, "===TlvUtilsNormalUsage begin");
101     vector<vector<TlvFrame>> tlvFrameTestcases = {
102         // 1.only one tlv frame, length = 0
103         { TlvFrame(1, "") },
104         // 2.only one tlv frame, length > 0
105         { TlvFrame(1, "test1") },
106         // 3.many tlv frames, length = 0
107         { TlvFrame(1, ""), TlvFrame(2, ""), TlvFrame(3, "") },
108         // 4.many tlv frames, length >= 0
109         { TlvFrame(1, "test1"), TlvFrame(2, ""), TlvFrame(3, "test3") },
110         // 5.many tlv frames, all length > 0
111         { TlvFrame(1, "test1"), TlvFrame(2, "test2"), TlvFrame(3, "test3") },
112     };
113 
114     for (auto frame: tlvFrameTestcases) {
115         TLvFeatureTest(UINT8_T, UINT8_T, frame);
116         TLvFeatureTest(UINT8_T, UINT16_T, frame);
117         TLvFeatureTest(UINT8_T, UINT32_T, frame);
118         TLvFeatureTest(UINT16_T, UINT8_T, frame);
119         TLvFeatureTest(UINT16_T, UINT16_T, frame);
120         TLvFeatureTest(UINT16_T, UINT32_T, frame);
121         TLvFeatureTest(UINT32_T, UINT8_T, frame);
122         TLvFeatureTest(UINT32_T, UINT16_T, frame);
123         TLvFeatureTest(UINT32_T, UINT32_T, frame);
124     }
125     COMM_LOGI(COMM_UTILS, "===TlvUtilsNormalUsage end");
126 }
127 
128 /**
129  * @tc.name: TlvUtilsPackTlvTest
130  * @tc.desc: TlvUtilsPackTlvTest.
131  * @tc.type: FUNC
132  * @tc.require:
133  */
134 HWTEST_F(SoftBusTlvUtilsTest, TlvUtilsPackTlvTest, TestSize.Level0)
135 {
136     COMM_LOGI(COMM_UTILS, "===TlvUtilsPackTlvTest begin");
137     // mock ts=UINT16_T ls=UINT16_T
138     TlvFrame frame1 = TlvFrame(1024, "test1024");
139     TlvFrame frame2 = TlvFrame(2048, "test2048");
140     uint8_t tlvBytes[] = {
141         0x00, 0x04, 0x08, 0x00, 0x74, 0x65, 0x73, 0x74, 0x31, 0x30, 0x32, 0x34, // frame1
142         0x00, 0x08, 0x08, 0x00, 0x74, 0x65, 0x73, 0x74, 0x32, 0x30, 0x34, 0x38  // frame2
143     };
144     // usage1: add one tlv frame
145     TlvObject *obj = CreateTlvObject(UINT16_T, UINT16_T);
146     ASSERT_TRUE(obj != nullptr);
147     int32_t ret = AddTlvMember(obj, frame1.type_, frame1.value_.length(), (const uint8_t *)frame1.value_.c_str());
148     EXPECT_EQ(ret, SOFTBUS_OK);
149     uint8_t *output = nullptr;
150     uint32_t outputSize = 0;
151     ret = GetTlvBinary(obj, &output, &outputSize);
152     EXPECT_EQ(ret, SOFTBUS_OK);
153     COMM_LOGI(COMM_UTILS, "output=%{public}s, outputSize=%{public}u",
154         BytesToHexString(output, outputSize).c_str(), outputSize);
155     ASSERT_EQ(outputSize, 12); // 12: UINT16_T + UINT16_T + strlen("test1024")
156     EXPECT_EQ(memcmp(output, tlvBytes, outputSize), 0);
157     SoftBusFree(output);
158     output = nullptr;
159 
160     // usage2: append one tlv frame after GetTlvBinary
161     ret = AddTlvMember(obj, frame2.type_, frame2.value_.length(), (const uint8_t *)frame2.value_.c_str());
162     EXPECT_EQ(ret, SOFTBUS_OK);
163     ret = GetTlvBinary(obj, &output, &outputSize);
164     EXPECT_EQ(ret, SOFTBUS_OK);
165     DestroyTlvObject(obj);
166 
167     COMM_LOGI(COMM_UTILS, "output=%{public}s, outputSize=%{public}u",
168         BytesToHexString(output, outputSize).c_str(), outputSize);
169     ASSERT_EQ(outputSize, sizeof(tlvBytes));
170     EXPECT_EQ(memcmp(output, tlvBytes, outputSize), 0);
171     SoftBusFree(output);
172     output = nullptr;
173     // usage3: append new tlv frame after SetTlvBinary
174     obj = CreateTlvObject(UINT16_T, UINT16_T);
175     ASSERT_TRUE(obj != nullptr);
176     ret = SetTlvBinary(obj, tlvBytes, 12); // 12: UINT16_T + UINT16_T + strlen("test1024")
177     EXPECT_EQ(ret, SOFTBUS_OK);
178     ret = AddTlvMember(obj, frame2.type_, frame2.value_.length(), (const uint8_t *)frame2.value_.c_str());
179     EXPECT_EQ(ret, SOFTBUS_OK);
180     ret = GetTlvBinary(obj, &output, &outputSize);
181     EXPECT_EQ(ret, SOFTBUS_OK);
182     DestroyTlvObject(obj);
183 
184     COMM_LOGI(COMM_UTILS, "output=%{public}s, outputSize=%{public}u",
185         BytesToHexString(output, outputSize).c_str(), outputSize);
186     ASSERT_EQ(outputSize, sizeof(tlvBytes));
187     EXPECT_EQ(memcmp(output, tlvBytes, outputSize), 0);
188     SoftBusFree(output);
189     output = nullptr;
190     COMM_LOGI(COMM_UTILS, "===TlvUtilsPackTlvTest end");
191 }
192 
193 /**
194  * @tc.name: TlvUtilsUnpackTlvTest
195  * @tc.desc: TlvUtilsUnpackTlvTest
196  * @tc.type: FUNC
197  * @tc.require:
198  */
199 HWTEST_F(SoftBusTlvUtilsTest, TlvUtilsUnpackTlvTest, TestSize.Level0)
200 {
201     COMM_LOGI(COMM_UTILS, "===TlvUtilsUnpackTlvTest begin");
202     // mock ts=UINT16_T ls=UINT16_T
203     TlvFrame frame1 = TlvFrame(1024, "test1024");
204     TlvFrame frame2 = TlvFrame(2048, "test2048");
205     uint8_t tlvBytes[] = {
206         0x00, 0x04, 0x08, 0x00, 0x74, 0x65, 0x73, 0x74, 0x31, 0x30, 0x32, 0x34, // frame1
207         0x00, 0x08, 0x08, 0x00, 0x74, 0x65, 0x73, 0x74, 0x32, 0x30, 0x34, 0x38  // frame2
208     };
209     // usage 1: parse only one tlv frame
210     TlvObject *obj = CreateTlvObject(UINT16_T, UINT16_T);
211     ASSERT_TRUE(obj != nullptr);
212     int32_t ret = SetTlvBinary(obj, tlvBytes, 12); // 12: UINT16_T + UINT16_T + strlen("test1024")
213     EXPECT_EQ(ret, SOFTBUS_OK);
214     uint32_t length = 0;
215     uint8_t *value = nullptr;
216     ret = GetTlvMember(obj, frame1.type_, &length, &value);
217     EXPECT_EQ(ret, SOFTBUS_OK);
218     ASSERT_EQ(length, frame1.value_.length());
219     EXPECT_EQ(memcmp(value, frame1.value_.c_str(), length), 0);
220     DestroyTlvObject(obj);
221     // usage 2: parse two tlv frames
222     obj = CreateTlvObject(UINT16_T, UINT16_T);
223     ASSERT_TRUE(obj != nullptr);
224     ret = SetTlvBinary(obj, tlvBytes, sizeof(tlvBytes));
225     EXPECT_EQ(ret, SOFTBUS_OK);
226     ret = GetTlvMember(obj, frame1.type_, &length, &value);
227     EXPECT_EQ(ret, SOFTBUS_OK);
228     ASSERT_EQ(length, frame1.value_.length());
229     EXPECT_EQ(memcmp(value, frame1.value_.c_str(), length), 0);
230     ret = GetTlvMember(obj, frame2.type_, &length, &value);
231     EXPECT_EQ(ret, SOFTBUS_OK);
232     ASSERT_EQ(length, frame2.value_.length());
233     EXPECT_EQ(memcmp(value, frame2.value_.c_str(), length), 0);
234     DestroyTlvObject(obj);
235     COMM_LOGI(COMM_UTILS, "===TlvUtilsUnpackTlvTest end");
236 }
237 
238 typedef struct {
239     uint32_t type;
240     union {
241         uint8_t u8;
242         uint16_t u16;
243         uint32_t u32;
244         uint64_t u64;
245     };
246 } TlvNumberFrame;
247 
248 /**
249  * @tc.name: TlvUtilsPackNumberTest
250  * @tc.desc: TlvUtilsPackNumberTest
251  * @tc.type: FUNC
252  * @tc.require:
253  */
254 HWTEST_F(SoftBusTlvUtilsTest, TlvUtilsPackNumberTest, TestSize.Level0)
255 {
256     COMM_LOGI(COMM_UTILS, "===TlvUtilsPackNumberTest begin");
257     // mock ts=UINT16_T ls=UINT16_T
258     TlvNumberFrame tlvFrames[] = {
259         { .type = 0x08, .u8 = 0x1F },
260         { .type = 0x16, .u16 = 0x2FF },
261         { .type = 0x32, .u32 = 0x3FFF },
262         { .type = 0x64, .u64 = 0x4FFFF },
263     };
264     uint8_t tlvBytes[] = {
265         0x08, 0x00, 0x01, 0x00, 0x1F, // .type = 0x08, .u8 = 0x1F
266         0x16, 0x00, 0x02, 0x00, 0xFF, 0x02, // .type = 0x16, .u16 = 0x2FF
267         0x32, 0x00, 0x04, 0x00, 0xFF, 0x3F, 0x00, 0x00, // .type = 0x32, .u32 = 0x3FFF
268         0x64, 0x00, 0x08, 0x00, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 // .type = 0x64, .u64 = 0x4FFFF
269     };
270 
271     TlvObject *obj = CreateTlvObject(UINT16_T, UINT16_T);
272     ASSERT_TRUE(obj != nullptr);
273 
274     int32_t ret = AddTlvMemberU8(obj, tlvFrames[0].type, tlvFrames[0].u8);
275     EXPECT_EQ(ret, SOFTBUS_OK);
276     ret = AddTlvMemberU16(obj, tlvFrames[1].type, tlvFrames[1].u16);
277     EXPECT_EQ(ret, SOFTBUS_OK);
278     ret = AddTlvMemberU32(obj, tlvFrames[2].type, tlvFrames[2].u32);
279     EXPECT_EQ(ret, SOFTBUS_OK);
280     ret = AddTlvMemberU64(obj, tlvFrames[3].type, tlvFrames[3].u64);
281     EXPECT_EQ(ret, SOFTBUS_OK);
282 
283     uint8_t *output = nullptr;
284     uint32_t outputSize = 0;
285     ret = GetTlvBinary(obj, &output, &outputSize);
286     EXPECT_EQ(ret, SOFTBUS_OK);
287     DestroyTlvObject(obj);
288 
289     COMM_LOGI(COMM_UTILS, "output=%{public}s, outputSize=%{public}u",
290         BytesToHexString(output, outputSize).c_str(), outputSize);
291     ASSERT_EQ(outputSize, sizeof(tlvBytes));
292     EXPECT_EQ(memcmp(output, tlvBytes, outputSize), 0);
293     SoftBusFree(output);
294     output = nullptr;
295     COMM_LOGI(COMM_UTILS, "===TlvUtilsPackNumberTest end");
296 }
297 
298 /**
299  * @tc.name: TlvUtilsUnpackNumberTest
300  * @tc.desc: TlvUtilsUnpackNumberTest
301  * @tc.type: FUNC
302  * @tc.require:
303  */
304 HWTEST_F(SoftBusTlvUtilsTest, TlvUtilsUnpackNumberTest, TestSize.Level0)
305 {
306     COMM_LOGI(COMM_UTILS, "===TlvUtilsUnpackNumberTest begin");
307     // mock ts=UINT16_T ls=UINT16_T
308     TlvNumberFrame tlvFrames[] = {
309         { .type = 0x08, .u8 = 0x1F },
310         { .type = 0x16, .u16 = 0x2FF },
311         { .type = 0x32, .u32 = 0x3FFF },
312         { .type = 0x64, .u64 = 0x4FFFF },
313     };
314     uint8_t tlvBytes[] = {
315         0x08, 0x00, 0x01, 0x00, 0x1F, // .type = 0x08, .u8 = 0x1F
316         0x16, 0x00, 0x02, 0x00, 0xFF, 0x02, // .type = 0x16, .u16 = 0x2FF
317         0x32, 0x00, 0x04, 0x00, 0xFF, 0x3F, 0x00, 0x00, // .type = 0x32, .u32 = 0x3FFF
318         0x64, 0x00, 0x08, 0x00, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 // .type = 0x64, .u64 = 0x4FFFF
319     };
320 
321     TlvObject *obj = CreateTlvObject(UINT16_T, UINT16_T);
322     ASSERT_TRUE(obj != nullptr);
323     int32_t ret = SetTlvBinary(obj, tlvBytes, sizeof(tlvBytes));
324     EXPECT_EQ(ret, SOFTBUS_OK);
325 
326     uint8_t u8 = 0;
327     ret = GetTlvMemberU8(obj, tlvFrames[0].type, &u8);
328     EXPECT_EQ(ret, SOFTBUS_OK);
329     EXPECT_EQ(u8, tlvFrames[0].u8);
330     uint16_t u16 = 0;
331     ret = GetTlvMemberU16(obj, tlvFrames[1].type, &u16);
332     EXPECT_EQ(ret, SOFTBUS_OK);
333     EXPECT_EQ(u16, tlvFrames[1].u16);
334     uint32_t u32 = 0;
335     ret = GetTlvMemberU32(obj, tlvFrames[2].type, &u32);
336     EXPECT_EQ(ret, SOFTBUS_OK);
337     EXPECT_EQ(u32, tlvFrames[2].u32);
338     uint64_t u64 = 0;
339     ret = GetTlvMemberU64(obj, tlvFrames[3].type, &u64);
340     EXPECT_EQ(ret, SOFTBUS_OK);
341     EXPECT_EQ(u64, tlvFrames[3].u64);
342 
343     DestroyTlvObject(obj);
344     COMM_LOGI(COMM_UTILS, "===TlvUtilsUnpackNumberTest end");
345 }
346 
347 /**
348  * @tc.name: GetTlvMemberWithBuffer
349  * @tc.desc: GetTlvMemberWithBuffer
350  * @tc.type: FUNC
351  * @tc.require:
352  */
353 HWTEST_F(SoftBusTlvUtilsTest, TlvUtilsGetTlvMemberWithBufferTest, TestSize.Level0)
354 {
355     COMM_LOGI(COMM_UTILS, "===TlvUtilsGetTlvMemberWithBufferTest begin");
356     // mock ts=UINT16_T ls=UINT16_T
357     const uint32_t type1 = 1;
358     const uint8_t value1[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
359     const uint32_t type2 = 2;
360     const char value2[] = "test1024";
361     const uint32_t type3 = 3;
362     uint8_t tlvBytes[] = {
363         0x01, 0x00, 0x06, 0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, // type=1, len=6 MAC
364         0x02, 0x00, 0x08, 0x00, 0x74, 0x65, 0x73, 0x74, 0x31, 0x30, 0x32, 0x34, // type=2, len=6, NAME
365         0x03, 0x00, 0x00, 0x00, // type=3, len=0, empty
366     };
367 
368     TlvObject *obj = CreateTlvObject(UINT16_T, UINT16_T);
369     ASSERT_TRUE(obj != nullptr);
370     int32_t ret = SetTlvBinary(obj, tlvBytes, sizeof(tlvBytes));
371     EXPECT_EQ(ret, SOFTBUS_OK);
372 
373     uint8_t mac[6]; // 6: mac size
374     ret = GetTlvMemberWithSpecifiedBuffer(obj, type1, mac, sizeof(mac));
375     EXPECT_EQ(ret, SOFTBUS_OK);
376     EXPECT_EQ(memcmp(value1, mac, sizeof(mac)), 0);
377 
378     uint8_t name[16] = {}; // 16: max name len
379     uint32_t nameSize = sizeof(name);
380     ret = GetTlvMemberWithEstimatedBuffer(obj, type2, name, &nameSize);
381     EXPECT_EQ(ret, SOFTBUS_OK);
382     for (uint32_t i = 0; i < nameSize; i++) {
383         GTEST_LOG_(INFO) << "name=" << name[i];
384     }
385     EXPECT_EQ(memcmp(value2, name, nameSize), 0);
386 
387     uint32_t empty = 0;
388     uint8_t emptyBuf[16]; // 16: not use
389     ret = GetTlvMemberWithEstimatedBuffer(obj, type3, emptyBuf, &empty);
390     EXPECT_EQ(ret, SOFTBUS_OK);
391     EXPECT_EQ(empty, 0);
392 
393     DestroyTlvObject(obj);
394     COMM_LOGI(COMM_UTILS, "===TlvUtilsGetTlvMemberWithBufferTest end");
395 }
396 
397 /**
398  * @tc.name: TlvUtilsExceptionDataTest
399  * @tc.desc: TlvUtilsExceptionDataTest
400  * @tc.type: FUNC
401  * @tc.require:
402  */
403 HWTEST_F(SoftBusTlvUtilsTest, TlvUtilsExceptionDataTest, TestSize.Level0)
404 {
405     COMM_LOGI(COMM_UTILS, "===TlvUtilsExceptionDataTest begin");
406     // mock ts=UINT16_T ls=UINT16_T
407     uint8_t tlvBytes[] = {
408         0x01, 0x00, 0x08, 0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, // type=1, len=8, value=6
409     };
410 
411     TlvObject *obj = CreateTlvObject(UINT16_T, UINT16_T);
412     ASSERT_TRUE(obj != nullptr);
413     int32_t ret = SetTlvBinary(obj, tlvBytes, sizeof(tlvBytes));
414     EXPECT_EQ(ret, SOFTBUS_NO_ENOUGH_DATA);
415 
416     DestroyTlvObject(obj);
417     COMM_LOGI(COMM_UTILS, "===TlvUtilsExceptionDataTest end");
418 }
419 } // namespace OHOS
420