Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / lib / core / tests / TestCHIPTLV.cpp
1 /*
2  *
3  *    Copyright (c) 2020-2021 Project CHIP Authors
4  *    Copyright (c) 2013-2017 Nest Labs, Inc.
5  *    All rights reserved.
6  *
7  *    Licensed under the Apache License, Version 2.0 (the "License");
8  *    you may not use this file except in compliance with the License.
9  *    You may obtain a copy of the License at
10  *
11  *        http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *    Unless required by applicable law or agreed to in writing, software
14  *    distributed under the License is distributed on an "AS IS" BASIS,
15  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *    See the License for the specific language governing permissions and
17  *    limitations under the License.
18  */
19
20 /**
21  *    @file
22  *      This file implements unit tests for the CHIP TLV implementation.
23  *
24  */
25
26 #include <nlbyteorder.h>
27 #include <nlunit-test.h>
28
29 #include <core/CHIPCircularTLVBuffer.h>
30 #include <core/CHIPCore.h>
31 #include <core/CHIPTLV.h>
32 #include <core/CHIPTLVData.hpp>
33 #include <core/CHIPTLVDebug.hpp>
34 #include <core/CHIPTLVUtilities.hpp>
35
36 #include <support/CHIPMem.h>
37 #include <support/CodeUtils.h>
38 #include <support/RandUtils.h>
39 #include <support/ScopedBuffer.h>
40 #include <support/UnitTestRegistration.h>
41
42 #include <system/TLVPacketBufferBackingStore.h>
43
44 #include <string.h>
45
46 using namespace chip;
47 using namespace chip::TLV;
48
49 enum
50 {
51     TestProfile_1 = 0xAABBCCDD,
52     TestProfile_2 = 0x11223344
53 };
54
55 // clang-format off
56 static const char sLargeString [] =
57     "START..."
58     "!123456789ABCDEF@123456789ABCDEF#123456789ABCDEF$123456789ABCDEF%123456789ABCDEF^123456789ABCDEF&123456789ABCDEF*123456789ABCDEF"
59     "01234567(9ABCDEF01234567)9ABCDEF01234567-9ABCDEF01234567=9ABCDEF01234567[9ABCDEF01234567]9ABCDEF01234567;9ABCDEF01234567'9ABCDEF"
60     "...END";
61 // clang-format on
62
63 void TestAndOpenContainer(nlTestSuite * inSuite, TLVReader & reader, TLVType type, uint64_t tag, TLVReader & containerReader)
64 {
65     NL_TEST_ASSERT(inSuite, reader.GetType() == type);
66     NL_TEST_ASSERT(inSuite, reader.GetTag() == tag);
67     NL_TEST_ASSERT(inSuite, reader.GetLength() == 0);
68
69     CHIP_ERROR err = reader.OpenContainer(containerReader);
70     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
71
72     NL_TEST_ASSERT(inSuite, containerReader.GetContainerType() == type);
73 }
74
75 template <class T>
76 void TestAndEnterContainer(nlTestSuite * inSuite, T & t, TLVType type, uint64_t tag, TLVType & outerContainerType)
77 {
78     NL_TEST_ASSERT(inSuite, t.GetType() == type);
79     NL_TEST_ASSERT(inSuite, t.GetTag() == tag);
80     NL_TEST_ASSERT(inSuite, t.GetLength() == 0);
81
82     TLVType expectedContainerType = t.GetContainerType();
83
84     CHIP_ERROR err = t.EnterContainer(outerContainerType);
85     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
86
87     NL_TEST_ASSERT(inSuite, outerContainerType == expectedContainerType);
88     NL_TEST_ASSERT(inSuite, t.GetContainerType() == type);
89 }
90
91 template <class T>
92 void TestNext(nlTestSuite * inSuite, T & t)
93 {
94     CHIP_ERROR err = t.Next();
95     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
96 }
97
98 void TestSkip(nlTestSuite * inSuite, TLVReader & reader)
99 {
100     CHIP_ERROR err = reader.Skip();
101     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
102 }
103
104 void TestMove(nlTestSuite * inSuite, TLVUpdater & updater)
105 {
106     CHIP_ERROR err = updater.Move();
107     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
108 }
109
110 template <class T>
111 void TestEnd(nlTestSuite * inSuite, T & t)
112 {
113     CHIP_ERROR err;
114
115     err = t.Next();
116     NL_TEST_ASSERT(inSuite, err == CHIP_END_OF_TLV);
117 }
118
119 void TestEndAndCloseContainer(nlTestSuite * inSuite, TLVReader & reader, TLVReader & containerReader)
120 {
121     CHIP_ERROR err;
122
123     TestEnd<TLVReader>(inSuite, containerReader);
124
125     err = reader.CloseContainer(containerReader);
126     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
127 }
128
129 template <class T>
130 void TestEndAndExitContainer(nlTestSuite * inSuite, T & t, TLVType outerContainerType)
131 {
132     CHIP_ERROR err;
133
134     TestEnd<T>(inSuite, t);
135
136     err = t.ExitContainer(outerContainerType);
137     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
138
139     NL_TEST_ASSERT(inSuite, t.GetContainerType() == outerContainerType);
140 }
141
142 template <class S, class T>
143 void TestGet(nlTestSuite * inSuite, S & s, TLVType type, uint64_t tag, T expectedVal)
144 {
145     NL_TEST_ASSERT(inSuite, s.GetType() == type);
146     NL_TEST_ASSERT(inSuite, s.GetTag() == tag);
147     NL_TEST_ASSERT(inSuite, s.GetLength() == 0);
148
149     T val;
150     CHIP_ERROR err = s.Get(val);
151     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
152
153     NL_TEST_ASSERT(inSuite, val == expectedVal);
154 }
155
156 void ForEachElement(nlTestSuite * inSuite, TLVReader & reader, void * context,
157                     void (*cb)(nlTestSuite * inSuite, TLVReader & reader, void * context))
158 {
159     CHIP_ERROR err;
160
161     while (true)
162     {
163         err = reader.Next();
164         if (err == CHIP_END_OF_TLV)
165         {
166             return;
167         }
168         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
169
170         if (cb != nullptr)
171         {
172             cb(inSuite, reader, context);
173         }
174
175         if (TLVTypeIsContainer(reader.GetType()))
176         {
177             TLVType outerContainerType;
178
179             err = reader.EnterContainer(outerContainerType);
180             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
181
182             ForEachElement(inSuite, reader, context, cb);
183
184             err = reader.ExitContainer(outerContainerType);
185             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
186         }
187     }
188 }
189
190 /**
191  * context
192  */
193
194 struct TestTLVContext
195 {
196     nlTestSuite * mSuite;
197     int mEvictionCount;
198     uint32_t mEvictedBytes;
199 };
200
201 void TestNull(nlTestSuite * inSuite, TLVReader & reader, uint64_t tag)
202 {
203     NL_TEST_ASSERT(inSuite, reader.GetType() == kTLVType_Null);
204     NL_TEST_ASSERT(inSuite, reader.GetTag() == tag);
205     NL_TEST_ASSERT(inSuite, reader.GetLength() == 0);
206 }
207
208 void TestString(nlTestSuite * inSuite, TLVReader & reader, uint64_t tag, const char * expectedVal)
209 {
210     NL_TEST_ASSERT(inSuite, reader.GetType() == kTLVType_UTF8String);
211     NL_TEST_ASSERT(inSuite, reader.GetTag() == tag);
212
213     size_t expectedLen = strlen(expectedVal);
214     NL_TEST_ASSERT(inSuite, reader.GetLength() == expectedLen);
215
216     chip::Platform::ScopedMemoryBuffer<char> valBuffer;
217     char * val = static_cast<char *>(valBuffer.Alloc(expectedLen + 1).Get());
218
219     CHIP_ERROR err = reader.GetString(val, static_cast<uint32_t>(expectedLen) + 1);
220     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
221
222     NL_TEST_ASSERT(inSuite, memcmp(val, expectedVal, expectedLen + 1) == 0);
223 }
224
225 void TestDupString(nlTestSuite * inSuite, TLVReader & reader, uint64_t tag, const char * expectedVal)
226 {
227     NL_TEST_ASSERT(inSuite, reader.GetType() == kTLVType_UTF8String);
228     NL_TEST_ASSERT(inSuite, reader.GetTag() == tag);
229
230     size_t expectedLen = strlen(expectedVal);
231     NL_TEST_ASSERT(inSuite, reader.GetLength() == expectedLen);
232
233     chip::Platform::ScopedMemoryBuffer<char> valBuffer;
234     char * val = valBuffer.Alloc(expectedLen + 1).Get();
235
236     CHIP_ERROR err = reader.DupString(val);
237     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
238
239     NL_TEST_ASSERT(inSuite, memcmp(val, expectedVal, expectedLen + 1) == 0);
240 }
241
242 void TestDupBytes(nlTestSuite * inSuite, TLVReader & reader, uint64_t tag, const uint8_t * expectedVal, uint32_t expectedLen)
243 {
244     NL_TEST_ASSERT(inSuite, reader.GetType() == kTLVType_UTF8String);
245     NL_TEST_ASSERT(inSuite, reader.GetTag() == tag);
246
247     NL_TEST_ASSERT(inSuite, reader.GetLength() == expectedLen);
248
249     chip::Platform::ScopedMemoryBuffer<uint8_t> valBuffer;
250     uint8_t * val  = valBuffer.Alloc(expectedLen).Get();
251     CHIP_ERROR err = reader.DupBytes(val, expectedLen);
252     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
253
254     NL_TEST_ASSERT(inSuite, memcmp(val, expectedVal, expectedLen) == 0);
255 }
256
257 void TestBufferContents(nlTestSuite * inSuite, const System::PacketBufferHandle & buffer, const uint8_t * expectedVal,
258                         uint32_t expectedLen)
259 {
260     System::PacketBufferHandle buf = buffer.Retain();
261     while (!buf.IsNull())
262     {
263         uint16_t len = buf->DataLength();
264         NL_TEST_ASSERT(inSuite, len <= expectedLen);
265
266         NL_TEST_ASSERT(inSuite, memcmp(buf->Start(), expectedVal, len) == 0);
267
268         expectedVal += len;
269         expectedLen -= len;
270
271         buf.Advance();
272     }
273
274     NL_TEST_ASSERT(inSuite, expectedLen == 0);
275 }
276
277 // clang-format off
278 static const uint8_t Encoding1[] =
279 {
280     0xD5, 0xBB, 0xAA, 0xDD, 0xCC, 0x01, 0x00, 0xC9, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00, 0x88, 0x02,
281     0x00, 0x36, 0x00, 0x00, 0x2A, 0x00, 0xEF, 0x02, 0xF0, 0x67, 0xFD, 0xFF, 0x07, 0x00, 0x90, 0x2F,
282     0x50, 0x09, 0x00, 0x00, 0x00, 0x15, 0x18, 0x17, 0xD4, 0xBB, 0xAA, 0xDD, 0xCC, 0x11, 0x00, 0xB4,
283     0xA0, 0xBB, 0x0D, 0x00, 0x14, 0xB5, 0x00, 0x28, 0x6B, 0xEE, 0x6D, 0x70, 0x11, 0x01, 0x00, 0x0E,
284     0x01, 0x53, 0x54, 0x41, 0x52, 0x54, 0x2E, 0x2E, 0x2E, 0x21, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
285     0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x40, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
286     0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x23, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
287     0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x24, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
288     0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x25, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
289     0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x5E, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
290     0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x26, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
291     0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x2A, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
292     0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
293     0x37, 0x28, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
294     0x37, 0x29, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
295     0x37, 0x2D, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
296     0x37, 0x3D, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
297     0x37, 0x5B, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
298     0x37, 0x5D, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
299     0x37, 0x3B, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
300     0x37, 0x27, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x2E, 0x2E, 0x2E, 0x45, 0x4E, 0x44, 0x18,
301     0x18, 0x18, 0xCC, 0xBB, 0xAA, 0xDD, 0xCC, 0x05, 0x00, 0x0E, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69,
302     0x73, 0x20, 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x8A, 0xFF, 0xFF, 0x33, 0x33, 0x8F, 0x41, 0xAB,
303     0x00, 0x00, 0x01, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0xE6, 0x31, 0x40, 0x18
304 };
305 // clang-format on
306
307 // clang-format off
308 static const uint8_t Encoding1_DataMacro [] =
309 {
310     CHIP_TLV_STRUCTURE(CHIP_TLV_TAG_FULLY_QUALIFIED_6Bytes(TestProfile_1, 1)),
311         CHIP_TLV_BOOL(CHIP_TLV_TAG_FULLY_QUALIFIED_6Bytes(TestProfile_1, 2), true),
312         CHIP_TLV_BOOL(CHIP_TLV_TAG_IMPLICIT_PROFILE_2Bytes(2), false),
313         CHIP_TLV_ARRAY(CHIP_TLV_TAG_CONTEXT_SPECIFIC(0)),
314             CHIP_TLV_INT8(CHIP_TLV_TAG_ANONYMOUS, 42),
315             CHIP_TLV_INT8(CHIP_TLV_TAG_ANONYMOUS, -17),
316             CHIP_TLV_INT32(CHIP_TLV_TAG_ANONYMOUS, -170000),
317             CHIP_TLV_UINT64(CHIP_TLV_TAG_ANONYMOUS, 40000000000ULL),
318             CHIP_TLV_STRUCTURE(CHIP_TLV_TAG_ANONYMOUS),
319             CHIP_TLV_END_OF_CONTAINER,
320             CHIP_TLV_PATH(CHIP_TLV_TAG_ANONYMOUS),
321                 CHIP_TLV_NULL(CHIP_TLV_TAG_FULLY_QUALIFIED_6Bytes(TestProfile_1, 17)),
322                 CHIP_TLV_NULL(CHIP_TLV_TAG_IMPLICIT_PROFILE_4Bytes(900000)),
323                 CHIP_TLV_NULL(CHIP_TLV_TAG_ANONYMOUS),
324                 CHIP_TLV_STRUCTURE(CHIP_TLV_TAG_IMPLICIT_PROFILE_4Bytes(4000000000ULL)),
325                     CHIP_TLV_UTF8_STRING_2ByteLength(CHIP_TLV_TAG_COMMON_PROFILE_4Bytes(70000), sizeof(sLargeString) - 1,
326                     'S', 'T', 'A', 'R', 'T', '.', '.', '.',
327                     '!', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', '@',
328                     '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', '#', '1',
329                     '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', '$', '1', '2',
330                     '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', '%', '1', '2', '3',
331                     '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', '^', '1', '2', '3', '4',
332                     '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', '&', '1', '2', '3', '4', '5',
333                     '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', '*', '1', '2', '3', '4', '5', '6',
334                     '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
335                     '0', '1', '2', '3', '4', '5', '6', '7', '(', '9', 'A', 'B', 'C', 'D', 'E', 'F', '0',
336                     '1', '2', '3', '4', '5', '6', '7', ')', '9', 'A', 'B', 'C', 'D', 'E', 'F', '0', '1',
337                     '2', '3', '4', '5', '6', '7', '-', '9', 'A', 'B', 'C', 'D', 'E', 'F', '0', '1', '2',
338                     '3', '4', '5', '6', '7', '=', '9', 'A', 'B', 'C', 'D', 'E', 'F', '0', '1', '2', '3',
339                     '4', '5', '6', '7', '[', '9', 'A', 'B', 'C', 'D', 'E', 'F', '0', '1', '2', '3', '4',
340                     '5', '6', '7', ']', '9', 'A', 'B', 'C', 'D', 'E', 'F', '0', '1', '2', '3', '4', '5',
341                     '6', '7', ';', '9', 'A', 'B', 'C', 'D', 'E', 'F', '0', '1', '2', '3', '4', '5', '6',
342                     '7', '\'', '9', 'A', 'B', 'C', 'D', 'E', 'F',
343                     '.', '.', '.', 'E', 'N', 'D'),
344                 CHIP_TLV_END_OF_CONTAINER,
345             CHIP_TLV_END_OF_CONTAINER,
346         CHIP_TLV_END_OF_CONTAINER,
347         CHIP_TLV_UTF8_STRING_1ByteLength(CHIP_TLV_TAG_FULLY_QUALIFIED_6Bytes(TestProfile_1, 5), sizeof("This is a test") - 1,
348             'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 't', 'e', 's', 't'),
349         CHIP_TLV_FLOAT32(CHIP_TLV_TAG_IMPLICIT_PROFILE_2Bytes(65535),
350             0x33, 0x33, 0x8f, 0x41), // (float)17.9
351         CHIP_TLV_FLOAT64(CHIP_TLV_TAG_IMPLICIT_PROFILE_4Bytes(65536),
352             0x66, 0x66, 0x66, 0x66, 0x66, 0xE6, 0x31, 0x40), // (double)17.9
353     CHIP_TLV_END_OF_CONTAINER
354 };
355 // clang-format on
356
357 void WriteEncoding1(nlTestSuite * inSuite, TLVWriter & writer)
358 {
359     CHIP_ERROR err;
360     TLVWriter writer2;
361
362     err = writer.OpenContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, writer2);
363     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
364
365     err = writer2.PutBoolean(ProfileTag(TestProfile_1, 2), true);
366     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
367
368     err = writer2.PutBoolean(ProfileTag(TestProfile_2, 2), false);
369     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
370
371     {
372         TLVWriter writer3;
373
374         err = writer2.OpenContainer(ContextTag(0), kTLVType_Array, writer3);
375         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
376
377         // TODO(#1306): expand coverage of inttype encoding tests.
378         err = writer3.Put(AnonymousTag, static_cast<int32_t>(42));
379         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
380
381         err = writer3.Put(AnonymousTag, static_cast<int32_t>(-17));
382         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
383
384         err = writer3.Put(AnonymousTag, static_cast<int32_t>(-170000));
385         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
386
387         err = writer3.Put(AnonymousTag, static_cast<uint64_t>(40000000000ULL));
388         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
389
390         {
391             TLVWriter writer4;
392
393             err = writer3.OpenContainer(AnonymousTag, kTLVType_Structure, writer4);
394             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
395
396             err = writer3.CloseContainer(writer4);
397             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
398         }
399
400         {
401             TLVWriter writer5;
402
403             err = writer3.OpenContainer(AnonymousTag, kTLVType_List, writer5);
404             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
405
406             err = writer5.PutNull(ProfileTag(TestProfile_1, 17));
407             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
408
409             err = writer5.PutNull(ProfileTag(TestProfile_2, 900000));
410             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
411
412             err = writer5.PutNull(AnonymousTag);
413             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
414
415             {
416                 TLVType outerContainerType;
417
418                 err = writer5.StartContainer(ProfileTag(TestProfile_2, 4000000000ULL), kTLVType_Structure, outerContainerType);
419                 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
420
421                 err = writer5.PutString(CommonTag(70000), sLargeString);
422                 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
423
424                 err = writer5.EndContainer(outerContainerType);
425                 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
426             }
427
428             err = writer3.CloseContainer(writer5);
429             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
430         }
431
432         err = writer2.CloseContainer(writer3);
433         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
434     }
435
436     err = writer2.PutString(ProfileTag(TestProfile_1, 5), "This is a test");
437     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
438
439     err = writer2.Put(ProfileTag(TestProfile_2, 65535), static_cast<float>(17.9));
440     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
441
442     err = writer2.Put(ProfileTag(TestProfile_2, 65536), 17.9);
443     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
444
445     err = writer.CloseContainer(writer2);
446     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
447
448     err = writer.Finalize();
449     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
450 }
451
452 void WriteEmptyEncoding(nlTestSuite * inSuite, TLVWriter & writer)
453 {
454     CHIP_ERROR err;
455     TLVWriter writer2;
456
457     err = writer.OpenContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, writer2);
458     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
459
460     {
461         TLVWriter writer3;
462
463         err = writer2.OpenContainer(ProfileTag(TestProfile_1, 256), kTLVType_Array, writer3);
464         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
465
466         err = writer2.CloseContainer(writer3);
467         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
468     }
469
470     err = writer.CloseContainer(writer2);
471     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
472
473     err = writer.Finalize();
474     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
475 }
476
477 void ReadEncoding1(nlTestSuite * inSuite, TLVReader & reader)
478 {
479     TestNext<TLVReader>(inSuite, reader);
480
481     {
482         TLVReader reader2;
483
484         TestAndOpenContainer(inSuite, reader, kTLVType_Structure, ProfileTag(TestProfile_1, 1), reader2);
485
486         TestNext<TLVReader>(inSuite, reader2);
487
488         TestGet<TLVReader, bool>(inSuite, reader2, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), true);
489
490         TestNext<TLVReader>(inSuite, reader2);
491
492         TestGet<TLVReader, bool>(inSuite, reader2, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), false);
493
494         TestNext<TLVReader>(inSuite, reader2);
495
496         {
497             TLVReader reader3;
498
499             TestAndOpenContainer(inSuite, reader2, kTLVType_Array, ContextTag(0), reader3);
500
501             TestNext<TLVReader>(inSuite, reader3);
502
503             TestGet<TLVReader, int8_t>(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag, 42);
504             TestGet<TLVReader, int16_t>(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag, 42);
505             TestGet<TLVReader, int32_t>(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag, 42);
506             TestGet<TLVReader, int64_t>(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag, 42);
507             TestGet<TLVReader, uint8_t>(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag, 42);
508             TestGet<TLVReader, uint16_t>(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag, 42);
509             TestGet<TLVReader, uint32_t>(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag, 42);
510             TestGet<TLVReader, uint64_t>(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag, 42);
511
512             TestNext<TLVReader>(inSuite, reader3);
513
514             TestGet<TLVReader, int8_t>(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag, -17);
515             TestGet<TLVReader, int16_t>(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag, -17);
516             TestGet<TLVReader, int32_t>(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag, -17);
517             TestGet<TLVReader, int64_t>(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag, -17);
518
519             TestNext<TLVReader>(inSuite, reader3);
520
521             TestGet<TLVReader, int32_t>(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag, -170000);
522             TestGet<TLVReader, int64_t>(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag, -170000);
523
524             TestNext<TLVReader>(inSuite, reader3);
525
526             TestGet<TLVReader, int64_t>(inSuite, reader3, kTLVType_UnsignedInteger, AnonymousTag, 40000000000ULL);
527             TestGet<TLVReader, uint64_t>(inSuite, reader3, kTLVType_UnsignedInteger, AnonymousTag, 40000000000ULL);
528
529             TestNext<TLVReader>(inSuite, reader3);
530
531             {
532                 TLVReader reader4;
533
534                 TestAndOpenContainer(inSuite, reader3, kTLVType_Structure, AnonymousTag, reader4);
535
536                 TestEndAndCloseContainer(inSuite, reader3, reader4);
537             }
538
539             TestNext<TLVReader>(inSuite, reader3);
540
541             {
542                 TLVReader reader5;
543
544                 TestAndOpenContainer(inSuite, reader3, kTLVType_List, AnonymousTag, reader5);
545
546                 TestNext<TLVReader>(inSuite, reader5);
547
548                 TestNull(inSuite, reader5, ProfileTag(TestProfile_1, 17));
549
550                 TestNext<TLVReader>(inSuite, reader5);
551
552                 TestNull(inSuite, reader5, ProfileTag(TestProfile_2, 900000));
553
554                 TestNext<TLVReader>(inSuite, reader5);
555
556                 TestNull(inSuite, reader5, AnonymousTag);
557
558                 TestNext<TLVReader>(inSuite, reader5);
559
560                 {
561                     TLVType outerContainerType;
562
563                     TestAndEnterContainer<TLVReader>(inSuite, reader5, kTLVType_Structure, ProfileTag(TestProfile_2, 4000000000ULL),
564                                                      outerContainerType);
565
566                     TestNext<TLVReader>(inSuite, reader5);
567
568                     TestString(inSuite, reader5, CommonTag(70000), sLargeString);
569
570                     TestEndAndExitContainer<TLVReader>(inSuite, reader5, outerContainerType);
571                 }
572
573                 TestEndAndCloseContainer(inSuite, reader3, reader5);
574             }
575
576             TestEndAndCloseContainer(inSuite, reader2, reader3);
577         }
578
579         TestNext<TLVReader>(inSuite, reader2);
580
581         TestString(inSuite, reader2, ProfileTag(TestProfile_1, 5), "This is a test");
582
583         TestNext<TLVReader>(inSuite, reader2);
584
585         TestGet<TLVReader, double>(inSuite, reader2, kTLVType_FloatingPointNumber, ProfileTag(TestProfile_2, 65535),
586                                    static_cast<float>(17.9));
587
588         TestNext<TLVReader>(inSuite, reader2);
589
590         TestGet<TLVReader, double>(inSuite, reader2, kTLVType_FloatingPointNumber, ProfileTag(TestProfile_2, 65536), 17.9);
591
592         TestEndAndCloseContainer(inSuite, reader, reader2);
593     }
594
595     TestEnd<TLVReader>(inSuite, reader);
596 }
597
598 void WriteEncoding2(nlTestSuite * inSuite, TLVWriter & writer)
599 {
600     CHIP_ERROR err;
601
602     { // Container 1
603         TLVWriter writer1;
604
605         err = writer.OpenContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, writer1);
606         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
607
608         err = writer1.PutBoolean(ProfileTag(TestProfile_1, 2), true);
609         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
610
611         err = writer1.PutBoolean(ProfileTag(TestProfile_2, 2), false);
612         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
613
614         err = writer.CloseContainer(writer1);
615         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
616     }
617
618     { // Container 2
619         TLVWriter writer1;
620
621         err = writer.OpenContainer(ProfileTag(TestProfile_2, 1), kTLVType_Structure, writer1);
622         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
623
624         err = writer1.PutBoolean(ProfileTag(TestProfile_2, 2), false);
625         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
626
627         err = writer1.PutBoolean(ProfileTag(TestProfile_1, 2), true);
628         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
629
630         err = writer.CloseContainer(writer1);
631         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
632     }
633
634     err = writer.Finalize();
635     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
636 }
637
638 void WriteEncoding3(nlTestSuite * inSuite, TLVWriter & writer)
639 {
640     CHIP_ERROR err;
641
642     { // Container 1
643         TLVWriter writer1;
644
645         err = writer.OpenContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, writer1);
646         if (err)
647             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
648
649         err = writer1.PutBoolean(ProfileTag(TestProfile_2, 2), false);
650         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
651
652         err = writer.CloseContainer(writer1);
653         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
654     }
655
656     err = writer.Finalize();
657     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
658 }
659
660 void ReadEncoding3(nlTestSuite * inSuite, TLVReader & reader)
661 {
662     TLVReader reader2;
663
664     TestAndOpenContainer(inSuite, reader, kTLVType_Structure, ProfileTag(TestProfile_1, 1), reader2);
665
666     TestNext<TLVReader>(inSuite, reader2);
667
668     TestGet<TLVReader, bool>(inSuite, reader2, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), false);
669
670     TestEndAndCloseContainer(inSuite, reader, reader2);
671 }
672 // clang-format off
673 static const uint8_t Encoding5_DataMacro [] =
674 {
675     CHIP_TLV_STRUCTURE(CHIP_TLV_TAG_FULLY_QUALIFIED_6Bytes(TestProfile_1, 1)),
676         CHIP_TLV_BOOL(CHIP_TLV_TAG_FULLY_QUALIFIED_6Bytes(TestProfile_1, 2), true),
677         CHIP_TLV_BOOL(CHIP_TLV_TAG_IMPLICIT_PROFILE_2Bytes(2), false),
678         CHIP_TLV_BOOL(CHIP_TLV_TAG_FULLY_QUALIFIED_6Bytes(TestProfile_1, 2), false),
679         CHIP_TLV_BOOL(CHIP_TLV_TAG_IMPLICIT_PROFILE_2Bytes(2), true),
680
681         CHIP_TLV_STRUCTURE(CHIP_TLV_TAG_FULLY_QUALIFIED_6Bytes(TestProfile_1, 1)),
682             CHIP_TLV_BOOL(CHIP_TLV_TAG_FULLY_QUALIFIED_6Bytes(TestProfile_1, 2), true),
683             CHIP_TLV_BOOL(CHIP_TLV_TAG_IMPLICIT_PROFILE_2Bytes(2), false),
684         CHIP_TLV_END_OF_CONTAINER,
685
686         CHIP_TLV_STRUCTURE(CHIP_TLV_TAG_IMPLICIT_PROFILE_2Bytes(1)),
687             CHIP_TLV_BOOL(CHIP_TLV_TAG_IMPLICIT_PROFILE_2Bytes(2), false),
688             CHIP_TLV_BOOL(CHIP_TLV_TAG_FULLY_QUALIFIED_6Bytes(TestProfile_1, 2), true),
689         CHIP_TLV_END_OF_CONTAINER,
690     CHIP_TLV_END_OF_CONTAINER,
691
692     CHIP_TLV_STRUCTURE(CHIP_TLV_TAG_IMPLICIT_PROFILE_2Bytes(1)),
693         CHIP_TLV_BOOL(CHIP_TLV_TAG_IMPLICIT_PROFILE_2Bytes(2), false),
694         CHIP_TLV_BOOL(CHIP_TLV_TAG_FULLY_QUALIFIED_6Bytes(TestProfile_1, 2), true),
695     CHIP_TLV_END_OF_CONTAINER,
696 };
697 // clang-format on
698
699 void WriteEncoding5(nlTestSuite * inSuite, TLVWriter & writer)
700 {
701     CHIP_ERROR err;
702
703     { // Container 1
704         TLVWriter writer1;
705
706         err = writer.OpenContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, writer1);
707         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
708
709         err = writer1.PutBoolean(ProfileTag(TestProfile_1, 2), true);
710         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
711
712         err = writer1.PutBoolean(ProfileTag(TestProfile_2, 2), false);
713         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
714
715         err = writer1.PutBoolean(ProfileTag(TestProfile_1, 2), false);
716         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
717
718         err = writer1.PutBoolean(ProfileTag(TestProfile_2, 2), true);
719         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
720
721         { // Inner Container 1
722             TLVWriter writer2;
723
724             err = writer1.OpenContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, writer2);
725             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
726
727             err = writer2.PutBoolean(ProfileTag(TestProfile_1, 2), true);
728             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
729
730             err = writer2.PutBoolean(ProfileTag(TestProfile_2, 2), false);
731             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
732
733             err = writer1.CloseContainer(writer2);
734             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
735         }
736
737         { // Inner Container 2
738             TLVWriter writer2;
739
740             err = writer1.OpenContainer(ProfileTag(TestProfile_2, 1), kTLVType_Structure, writer2);
741             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
742
743             err = writer2.PutBoolean(ProfileTag(TestProfile_2, 2), false);
744             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
745
746             err = writer2.PutBoolean(ProfileTag(TestProfile_1, 2), true);
747             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
748
749             err = writer1.CloseContainer(writer2);
750             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
751         }
752
753         err = writer.CloseContainer(writer1);
754         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
755     }
756
757     { // Container 2
758         TLVWriter writer1;
759
760         err = writer.OpenContainer(ProfileTag(TestProfile_2, 1), kTLVType_Structure, writer1);
761         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
762
763         err = writer1.PutBoolean(ProfileTag(TestProfile_2, 2), false);
764         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
765
766         err = writer1.PutBoolean(ProfileTag(TestProfile_1, 2), true);
767         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
768
769         err = writer.CloseContainer(writer1);
770         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
771     }
772
773     err = writer.Finalize();
774     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
775 }
776
777 /**
778  * AppendEncoding2()
779  *
780  * This function appends two boolean types and two container types to the first
781  * container.
782  *
783  * The boolean types are-
784  * <TestProfile_1, 2, false>
785  * <TestProfile_2, 2, true>
786  *
787  * The two new container types are-
788  * <TestProfile_1, 1, kTLVType_Structure, <TestProfile_1, 2, true> <TestProfile_2, 2, false> >,
789  * <TestProfile_2, 1, kTLVType_Structure, <TestProfile_2, 2, false> <TestProfile_1, 2, true> >
790  */
791 void AppendEncoding2(nlTestSuite * inSuite, uint8_t * buf, uint32_t dataLen, uint32_t maxLen, uint32_t & updatedLen)
792 {
793     CHIP_ERROR err;
794
795     TLVUpdater updater;
796
797     err = updater.Init(buf, dataLen, maxLen);
798     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
799
800     updater.SetImplicitProfileId(TestProfile_2);
801
802     TestNext<TLVUpdater>(inSuite, updater);
803
804     {
805         TLVType outerContainerType;
806
807         TestAndEnterContainer<TLVUpdater>(inSuite, updater, kTLVType_Structure, ProfileTag(TestProfile_1, 1), outerContainerType);
808
809         TestNext<TLVUpdater>(inSuite, updater);
810
811         // Move the element without modification
812         TestMove(inSuite, updater);
813
814         TestNext<TLVUpdater>(inSuite, updater);
815
816         // Read and copy the element with/without modification
817         TestGet<TLVUpdater, bool>(inSuite, updater, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), false);
818         err = updater.PutBoolean(ProfileTag(TestProfile_2, 2), false);
819         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
820
821         // TestEnd and add data at the end of the container
822         TestEnd<TLVUpdater>(inSuite, updater);
823
824         // Put new values in the encoding using the updater
825         // Add <TestProfile_1, 2, false>
826         err = updater.PutBoolean(ProfileTag(TestProfile_1, 2), false);
827         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
828
829         // Add <TestProfile_2, 2, true>
830         err = updater.PutBoolean(ProfileTag(TestProfile_2, 2), true);
831         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
832
833         // Add a new container
834         {
835             TLVType outerContainerType1;
836
837             err = updater.StartContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, outerContainerType1);
838             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
839
840             // Add <TestProfile_1, 2, true>
841             err = updater.PutBoolean(ProfileTag(TestProfile_1, 2), true);
842             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
843
844             // Add <TestProfile_1, 2, true>
845             err = updater.PutBoolean(ProfileTag(TestProfile_2, 2), false);
846             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
847
848             // Close the container
849             err = updater.EndContainer(outerContainerType1);
850             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
851         }
852
853         // Add another new container
854         {
855             TLVType outerContainerType1;
856
857             err = updater.StartContainer(ProfileTag(TestProfile_2, 1), kTLVType_Structure, outerContainerType1);
858             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
859
860             // Add <TestProfile_2, 2, false>
861             err = updater.PutBoolean(ProfileTag(TestProfile_2, 2), false);
862             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
863
864             // Add <TestProfile_1, 2, true>
865             err = updater.PutBoolean(ProfileTag(TestProfile_1, 2), true);
866             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
867
868             // Close the container
869             err = updater.EndContainer(outerContainerType1);
870             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
871         }
872
873         TestEndAndExitContainer<TLVUpdater>(inSuite, updater, outerContainerType);
874     }
875
876     TestNext<TLVUpdater>(inSuite, updater);
877
878     // Move the container unmodified
879     TestMove(inSuite, updater);
880
881     TestEnd<TLVUpdater>(inSuite, updater);
882
883     err = updater.Finalize();
884     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
885
886     updatedLen = updater.GetLengthWritten();
887 }
888
889 /**
890  * FindAppendEncoding2()
891  *
892  * This function appends two boolean types and two container types to the first
893  * container. It is very similar to AppendEncoding2() above except for the fact
894  * that it uses TLVUtilities::Find() to find the element of interest before
895  * appending new data.
896  *
897  * The boolean types are-
898  * <TestProfile_1, 2, false>
899  * <TestProfile_2, 2, true>
900  *
901  * The two new container types are-
902  * <TestProfile_1, 1, kTLVType_Structure, <TestProfile_1, 2, true> <TestProfile_2, 2, false> >,
903  * <TestProfile_2, 1, kTLVType_Structure, <TestProfile_2, 2, false> <TestProfile_1, 2, true> >
904  */
905 void FindAppendEncoding2(nlTestSuite * inSuite, uint8_t * buf, uint32_t dataLen, uint32_t maxLen, uint32_t & updatedLen,
906                          bool findContainer)
907 {
908     CHIP_ERROR err;
909
910     TLVReader reader;
911     TLVUpdater updater;
912
913     // Initialize a reader
914     reader.Init(buf, dataLen);
915     reader.ImplicitProfileId = TestProfile_2;
916
917     if (findContainer)
918     {
919         // Find the container
920         TLVReader tagReader;
921         TLVType outerContainerType;
922         err = chip::TLV::Utilities::Find(reader, ProfileTag(TestProfile_1, 1), tagReader);
923         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
924
925         err = tagReader.EnterContainer(outerContainerType);
926         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
927
928         do
929         {
930             err = tagReader.Next();
931         } while (err != CHIP_END_OF_TLV);
932
933         TestEnd<TLVReader>(inSuite, tagReader);
934
935         // Init a TLVUpdater using the TLVReader
936         err = updater.Init(tagReader, maxLen - dataLen);
937         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
938     }
939     else
940     {
941         // Find
942         TLVReader tagReader;
943         err = chip::TLV::Utilities::Find(reader, ProfileTag(TestProfile_2, 2), tagReader);
944         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
945
946         // Test Find(recurse = true)
947         TLVReader tagReader2;
948         err = chip::TLV::Utilities::Find(reader, ProfileTag(TestProfile_2, 2), tagReader2, true);
949         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
950         //
951         // Test Find(recurse = false)
952         TLVReader tagReader3;
953         err = chip::TLV::Utilities::Find(reader, ProfileTag(TestProfile_2, 2), tagReader3, false);
954         NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_TLV_TAG_NOT_FOUND);
955
956         // Init a TLVUpdater using the TLVReader
957         err = updater.Init(tagReader, maxLen - dataLen);
958         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
959
960         TestNext<TLVUpdater>(inSuite, updater);
961
962         // Move the element without modification
963         TestMove(inSuite, updater);
964     }
965
966     // Put new values in the encoding using the updater
967     // Add <TestProfile_1, 2, false>
968     err = updater.PutBoolean(ProfileTag(TestProfile_1, 2), false);
969     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
970
971     // Add <TestProfile_2, 2, true>
972     err = updater.PutBoolean(ProfileTag(TestProfile_2, 2), true);
973     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
974
975     // Add a new container
976     {
977         TLVType outerContainerType1;
978
979         err = updater.StartContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, outerContainerType1);
980         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
981
982         // Add <TestProfile_1, 2, true>
983         err = updater.PutBoolean(ProfileTag(TestProfile_1, 2), true);
984         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
985
986         // Add <TestProfile_1, 2, true>
987         err = updater.PutBoolean(ProfileTag(TestProfile_2, 2), false);
988         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
989
990         // Close the container
991         err = updater.EndContainer(outerContainerType1);
992         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
993     }
994
995     // Add another new container
996     {
997         TLVType outerContainerType1;
998
999         err = updater.StartContainer(ProfileTag(TestProfile_2, 1), kTLVType_Structure, outerContainerType1);
1000         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
1001
1002         // Add <TestProfile_2, 2, false>
1003         err = updater.PutBoolean(ProfileTag(TestProfile_2, 2), false);
1004         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
1005
1006         // Add <TestProfile_1, 2, true>
1007         err = updater.PutBoolean(ProfileTag(TestProfile_1, 2), true);
1008         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
1009
1010         // Close the container
1011         err = updater.EndContainer(outerContainerType1);
1012         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
1013     }
1014
1015     // Move everything else unmodified
1016     updater.MoveUntilEnd();
1017
1018     TestEnd<TLVUpdater>(inSuite, updater);
1019
1020     err = updater.Finalize();
1021     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
1022
1023     updatedLen = updater.GetLengthWritten();
1024 }
1025
1026 void AppendEncoding3(nlTestSuite * inSuite, uint8_t * buf, uint32_t dataLen, uint32_t maxLen, uint32_t & updatedLen)
1027 {
1028     CHIP_ERROR err;
1029
1030     TLVUpdater updater;
1031
1032     err = updater.Init(buf, dataLen, maxLen);
1033     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
1034
1035     updater.SetImplicitProfileId(TestProfile_2);
1036
1037     TestNext<TLVUpdater>(inSuite, updater);
1038
1039     {
1040         TLVType outerContainerType;
1041
1042         TestAndEnterContainer<TLVUpdater>(inSuite, updater, kTLVType_Structure, ProfileTag(TestProfile_1, 1), outerContainerType);
1043
1044         TestNext<TLVUpdater>(inSuite, updater);
1045
1046         // Move the element without modification
1047         TestMove(inSuite, updater);
1048
1049         // Put new value in the encoding using the updater
1050         // Add <TestProfile_2, 2, true>
1051         err = updater.PutBoolean(ProfileTag(TestProfile_2, 2), true);
1052         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
1053
1054         TestEndAndExitContainer<TLVUpdater>(inSuite, updater, outerContainerType);
1055     }
1056
1057     TestEnd<TLVUpdater>(inSuite, updater);
1058
1059     err = updater.Finalize();
1060     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
1061
1062     updatedLen = updater.GetLengthWritten();
1063 }
1064
1065 void AppendEncoding4(nlTestSuite * inSuite, uint8_t * buf, uint32_t dataLen, uint32_t maxLen, uint32_t & updatedLen)
1066 {
1067     CHIP_ERROR err;
1068
1069     TLVUpdater updater;
1070
1071     err = updater.Init(buf, dataLen, maxLen);
1072     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
1073
1074     updater.SetImplicitProfileId(TestProfile_2);
1075
1076     // Add a new container
1077     {
1078         TLVType outerContainerType;
1079
1080         err = updater.StartContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, outerContainerType);
1081         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
1082
1083         // Add <TestProfile_1, 2, true>
1084         err = updater.PutBoolean(ProfileTag(TestProfile_2, 2), false);
1085         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
1086
1087         // Close the container
1088         err = updater.EndContainer(outerContainerType);
1089         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
1090     }
1091
1092     err = updater.Finalize();
1093     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
1094
1095     updatedLen = updater.GetLengthWritten();
1096 }
1097
1098 void DeleteEncoding5(nlTestSuite * inSuite, uint8_t * buf, uint32_t dataLen, uint32_t maxLen, uint32_t & updatedLen)
1099 {
1100     CHIP_ERROR err;
1101
1102     TLVUpdater updater;
1103
1104     err = updater.Init(buf, dataLen, maxLen);
1105     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
1106
1107     updater.SetImplicitProfileId(TestProfile_2);
1108
1109     TestNext<TLVUpdater>(inSuite, updater);
1110
1111     {
1112         TLVType outerContainerType;
1113
1114         TestAndEnterContainer<TLVUpdater>(inSuite, updater, kTLVType_Structure, ProfileTag(TestProfile_1, 1), outerContainerType);
1115
1116         TestNext<TLVUpdater>(inSuite, updater);
1117
1118         TestMove(inSuite, updater);
1119
1120         TestNext<TLVUpdater>(inSuite, updater);
1121
1122         TestMove(inSuite, updater);
1123
1124         TestNext<TLVUpdater>(inSuite, updater);
1125
1126         // Get the value to inspect and skip writing it
1127         TestGet<TLVUpdater, bool>(inSuite, updater, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), false);
1128
1129         TestNext<TLVUpdater>(inSuite, updater);
1130
1131         // Skip the next boolean type and don't copy by doing nothing
1132
1133         TestNext<TLVUpdater>(inSuite, updater);
1134
1135         // Read ahead into the next container and decide whether to skip or
1136         // not based on elements in the container
1137         {
1138             TLVReader reader;
1139             TLVType containerType;
1140
1141             updater.GetReader(reader);
1142
1143             TestAndEnterContainer<TLVReader>(inSuite, reader, kTLVType_Structure, ProfileTag(TestProfile_1, 1), containerType);
1144
1145             TestNext<TLVReader>(inSuite, reader);
1146
1147             // If the container's first element has the tag <TestProfile_1, 2>
1148             // skip the whole container, and if NOT copy the container
1149             if (reader.GetTag() != ProfileTag(TestProfile_1, 2))
1150                 TestMove(inSuite, updater);
1151         }
1152
1153         TestNext<TLVUpdater>(inSuite, updater);
1154
1155         // Skip the next container and don't copy by doing nothing
1156
1157         TestEndAndExitContainer<TLVUpdater>(inSuite, updater, outerContainerType);
1158     }
1159
1160     // Move everything else unmodified
1161     updater.MoveUntilEnd();
1162
1163     TestEnd<TLVUpdater>(inSuite, updater);
1164
1165     err = updater.Finalize();
1166     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
1167
1168     updatedLen = updater.GetLengthWritten();
1169 }
1170
1171 void ReadAppendedEncoding2(nlTestSuite * inSuite, TLVReader & reader)
1172 {
1173     TestNext<TLVReader>(inSuite, reader);
1174
1175     { // Container 1
1176         TLVReader reader1;
1177
1178         TestAndOpenContainer(inSuite, reader, kTLVType_Structure, ProfileTag(TestProfile_1, 1), reader1);
1179
1180         TestNext<TLVReader>(inSuite, reader1);
1181
1182         TestGet<TLVReader, bool>(inSuite, reader1, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), true);
1183
1184         TestNext<TLVReader>(inSuite, reader1);
1185
1186         TestGet<TLVReader, bool>(inSuite, reader1, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), false);
1187
1188         TestNext<TLVReader>(inSuite, reader1);
1189
1190         TestGet<TLVReader, bool>(inSuite, reader1, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), false);
1191
1192         TestNext<TLVReader>(inSuite, reader1);
1193
1194         TestGet<TLVReader, bool>(inSuite, reader1, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), true);
1195
1196         TestNext<TLVReader>(inSuite, reader1);
1197
1198         {
1199             TLVReader reader2;
1200
1201             TestAndOpenContainer(inSuite, reader1, kTLVType_Structure, ProfileTag(TestProfile_1, 1), reader2);
1202
1203             TestNext<TLVReader>(inSuite, reader2);
1204
1205             TestGet<TLVReader, bool>(inSuite, reader2, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), true);
1206
1207             TestNext<TLVReader>(inSuite, reader2);
1208
1209             TestGet<TLVReader, bool>(inSuite, reader2, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), false);
1210
1211             TestEndAndCloseContainer(inSuite, reader1, reader2);
1212         }
1213
1214         TestNext<TLVReader>(inSuite, reader1);
1215
1216         {
1217             TLVReader reader2;
1218
1219             TestAndOpenContainer(inSuite, reader1, kTLVType_Structure, ProfileTag(TestProfile_2, 1), reader2);
1220
1221             TestNext<TLVReader>(inSuite, reader2);
1222
1223             TestGet<TLVReader, bool>(inSuite, reader2, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), false);
1224
1225             TestNext<TLVReader>(inSuite, reader2);
1226
1227             TestGet<TLVReader, bool>(inSuite, reader2, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), true);
1228
1229             TestEndAndCloseContainer(inSuite, reader1, reader2);
1230         }
1231
1232         TestEndAndCloseContainer(inSuite, reader, reader1);
1233     }
1234
1235     TestNext<TLVReader>(inSuite, reader);
1236
1237     { // Container 2
1238         TLVReader reader1;
1239
1240         TestAndOpenContainer(inSuite, reader, kTLVType_Structure, ProfileTag(TestProfile_2, 1), reader1);
1241
1242         TestNext<TLVReader>(inSuite, reader1);
1243
1244         TestGet<TLVReader, bool>(inSuite, reader1, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), false);
1245
1246         TestNext<TLVReader>(inSuite, reader1);
1247
1248         TestGet<TLVReader, bool>(inSuite, reader1, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), true);
1249
1250         TestEndAndCloseContainer(inSuite, reader, reader1);
1251     }
1252
1253     TestEnd<TLVReader>(inSuite, reader);
1254 }
1255
1256 void ReadAppendedEncoding3(nlTestSuite * inSuite, TLVReader & reader)
1257 {
1258     TestNext<TLVReader>(inSuite, reader);
1259
1260     { // Container 1
1261         TLVReader reader1;
1262
1263         TestAndOpenContainer(inSuite, reader, kTLVType_Structure, ProfileTag(TestProfile_1, 1), reader1);
1264
1265         TestNext<TLVReader>(inSuite, reader1);
1266
1267         TestGet<TLVReader, bool>(inSuite, reader1, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), false);
1268
1269         TestNext<TLVReader>(inSuite, reader1);
1270
1271         TestGet<TLVReader, bool>(inSuite, reader1, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), true);
1272
1273         TestEndAndCloseContainer(inSuite, reader, reader1);
1274     }
1275
1276     TestEnd<TLVReader>(inSuite, reader);
1277 }
1278
1279 void ReadAppendedEncoding4(nlTestSuite * inSuite, TLVReader & reader)
1280 {
1281     TestNext<TLVReader>(inSuite, reader);
1282
1283     { // Container 1
1284         TLVReader reader1;
1285
1286         TestAndOpenContainer(inSuite, reader, kTLVType_Structure, ProfileTag(TestProfile_1, 1), reader1);
1287
1288         TestNext<TLVReader>(inSuite, reader1);
1289
1290         TestGet<TLVReader, bool>(inSuite, reader1, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), false);
1291
1292         TestEndAndCloseContainer(inSuite, reader, reader1);
1293     }
1294
1295     TestEnd<TLVReader>(inSuite, reader);
1296 }
1297
1298 void ReadDeletedEncoding5(nlTestSuite * inSuite, TLVReader & reader)
1299 {
1300     TestNext<TLVReader>(inSuite, reader);
1301
1302     { // Container 1
1303         TLVReader reader1;
1304
1305         TestAndOpenContainer(inSuite, reader, kTLVType_Structure, ProfileTag(TestProfile_1, 1), reader1);
1306
1307         TestNext<TLVReader>(inSuite, reader1);
1308
1309         TestGet<TLVReader, bool>(inSuite, reader1, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), true);
1310
1311         TestNext<TLVReader>(inSuite, reader1);
1312
1313         TestGet<TLVReader, bool>(inSuite, reader1, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), false);
1314
1315         TestEndAndCloseContainer(inSuite, reader, reader1);
1316     }
1317
1318     TestNext<TLVReader>(inSuite, reader);
1319
1320     { // Container 2
1321         TLVReader reader1;
1322
1323         TestAndOpenContainer(inSuite, reader, kTLVType_Structure, ProfileTag(TestProfile_2, 1), reader1);
1324
1325         TestNext<TLVReader>(inSuite, reader1);
1326
1327         TestGet<TLVReader, bool>(inSuite, reader1, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), false);
1328
1329         TestNext<TLVReader>(inSuite, reader1);
1330
1331         TestGet<TLVReader, bool>(inSuite, reader1, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), true);
1332
1333         TestEndAndCloseContainer(inSuite, reader, reader1);
1334     }
1335
1336     TestEnd<TLVReader>(inSuite, reader);
1337 }
1338
1339 /**
1340  *  Test Simple Write and Reader
1341  */
1342 void CheckSimpleWriteRead(nlTestSuite * inSuite, void * inContext)
1343 {
1344     uint8_t buf[2048];
1345     TLVWriter writer;
1346     TLVReader reader;
1347     uint32_t remainingFreedLen;
1348
1349     writer.Init(buf, sizeof(buf));
1350     writer.ImplicitProfileId = TestProfile_2;
1351
1352     remainingFreedLen = writer.GetRemainingFreeLength();
1353     NL_TEST_ASSERT(inSuite, sizeof(buf) == remainingFreedLen);
1354
1355     WriteEncoding1(inSuite, writer);
1356
1357     uint32_t encodedLen = writer.GetLengthWritten();
1358
1359 #ifdef DUMP_ENCODING
1360     for (uint32_t i = 0; i < encodedLen; i++)
1361     {
1362         if (i != 0 && i % 16 == 0)
1363             printf("\n");
1364         printf("0x%02X, ", buf[i]);
1365     }
1366     printf("\n");
1367 #endif
1368
1369     NL_TEST_ASSERT(inSuite, encodedLen == sizeof(Encoding1));
1370     NL_TEST_ASSERT(inSuite, memcmp(buf, Encoding1, encodedLen) == 0);
1371
1372     reader.Init(buf, encodedLen);
1373     reader.ImplicitProfileId = TestProfile_2;
1374
1375     ReadEncoding1(inSuite, reader);
1376 }
1377
1378 /**
1379  *  Log the specified message in the form of @a aFormat.
1380  *
1381  *  @param[in]     aFormat   A pointer to a NULL-terminated C string with
1382  *                           C Standard Library-style format specifiers
1383  *                           containing the log message to be formatted and
1384  *                           logged.
1385  *  @param[in]     ...       An argument list whose elements should correspond
1386  *                           to the format specifiers in @a aFormat.
1387  *
1388  */
1389 void SimpleDumpWriter(const char * aFormat, ...)
1390 {
1391     va_list args;
1392
1393     va_start(args, aFormat);
1394
1395     vprintf(aFormat, args);
1396
1397     va_end(args);
1398 }
1399
1400 /**
1401  *  Test Pretty Printer
1402  */
1403 void CheckPrettyPrinter(nlTestSuite * inSuite, void * inContext)
1404 {
1405     uint8_t buf[2048];
1406     TLVWriter writer;
1407     TLVReader reader;
1408
1409     writer.Init(buf, sizeof(buf));
1410     writer.ImplicitProfileId = TestProfile_2;
1411
1412     WriteEncoding1(inSuite, writer);
1413
1414     uint32_t encodedLen = writer.GetLengthWritten();
1415
1416     NL_TEST_ASSERT(inSuite, encodedLen == sizeof(Encoding1));
1417     NL_TEST_ASSERT(inSuite, memcmp(buf, Encoding1, encodedLen) == 0);
1418
1419     reader.Init(buf, encodedLen);
1420     reader.ImplicitProfileId = TestProfile_2;
1421     chip::TLV::Debug::Dump(reader, SimpleDumpWriter);
1422 }
1423
1424 /**
1425  *  Test Data Macros
1426  */
1427 void CheckDataMacro(nlTestSuite * inSuite, void * inContext)
1428 {
1429     NL_TEST_ASSERT(inSuite, sizeof(Encoding1_DataMacro) == sizeof(Encoding1));
1430     NL_TEST_ASSERT(inSuite, memcmp(Encoding1, Encoding1_DataMacro, sizeof(Encoding1)) == 0);
1431
1432     uint8_t buf[2048];
1433     TLVWriter writer;
1434     writer.Init(buf, sizeof(buf));
1435     writer.ImplicitProfileId = TestProfile_2;
1436     WriteEncoding5(inSuite, writer);
1437     uint32_t encodedLen = writer.GetLengthWritten();
1438
1439     NL_TEST_ASSERT(inSuite, sizeof(Encoding5_DataMacro) == encodedLen);
1440     NL_TEST_ASSERT(inSuite, memcmp(buf, Encoding5_DataMacro, encodedLen) == 0);
1441 }
1442
1443 static CHIP_ERROR NullIterateHandler(const TLVReader & aReader, size_t aDepth, void * aContext)
1444 {
1445     (void) aReader;
1446     (void) aDepth;
1447     (void) aContext;
1448
1449     return CHIP_NO_ERROR;
1450 }
1451
1452 static CHIP_ERROR FindContainerWithElement(const TLVReader & aReader, size_t aDepth, void * aContext)
1453 {
1454     TLVReader reader;
1455     TLVReader result;
1456     uint64_t * tag = static_cast<uint64_t *>(aContext);
1457     CHIP_ERROR err = CHIP_NO_ERROR;
1458     TLVType containerType;
1459
1460     reader.Init(aReader);
1461
1462     if (TLVTypeIsContainer(reader.GetType()))
1463     {
1464         ReturnErrorOnFailure(reader.EnterContainer(containerType));
1465
1466         err = chip::TLV::Utilities::Find(reader, *tag, result, false);
1467
1468         // Map a successful find (CHIP_NO_ERROR) onto a signal that the element has been found.
1469         if (err == CHIP_NO_ERROR)
1470         {
1471             err = CHIP_ERROR_MAX;
1472         }
1473         // Map a failed find attempt to NO_ERROR
1474         else if (err == CHIP_ERROR_TLV_TAG_NOT_FOUND)
1475         {
1476             err = CHIP_NO_ERROR;
1477         }
1478     }
1479     return err;
1480 }
1481
1482 /**
1483  *  Test CHIP TLV Utilities
1484  */
1485 void CheckCHIPTLVUtilities(nlTestSuite * inSuite, void * inContext)
1486 {
1487     uint8_t buf[2048];
1488     TLVWriter writer;
1489     TLVReader reader, reader1;
1490     CHIP_ERROR err = CHIP_NO_ERROR;
1491
1492     writer.Init(buf, sizeof(buf));
1493     writer.ImplicitProfileId = TestProfile_2;
1494
1495     WriteEncoding1(inSuite, writer);
1496
1497     uint32_t encodedLen = writer.GetLengthWritten();
1498
1499     NL_TEST_ASSERT(inSuite, encodedLen == sizeof(Encoding1));
1500     NL_TEST_ASSERT(inSuite, memcmp(buf, Encoding1, encodedLen) == 0);
1501
1502     reader.Init(buf, encodedLen);
1503     reader.ImplicitProfileId = TestProfile_2;
1504
1505     reader1.Init(reader);
1506     err = reader1.Next();
1507     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
1508
1509     // Find a tag
1510     TLVReader tagReader;
1511     err = chip::TLV::Utilities::Find(reader, ProfileTag(TestProfile_2, 65536), tagReader);
1512     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
1513
1514     // Find with reader positioned "on" the element of interest
1515     err = chip::TLV::Utilities::Find(reader1, ProfileTag(TestProfile_1, 1), tagReader);
1516     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
1517
1518     // Find a tag that's not present
1519     err = chip::TLV::Utilities::Find(reader, ProfileTag(TestProfile_2, 1024), tagReader);
1520     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_TLV_TAG_NOT_FOUND);
1521
1522     // Find with a predicate
1523     {
1524         uint8_t buf1[74];
1525
1526         writer.Init(buf1, sizeof(buf1));
1527         writer.ImplicitProfileId = TestProfile_2;
1528
1529         WriteEncoding2(inSuite, writer);
1530
1531         // Initialize a reader
1532         reader1.Init(buf1, writer.GetLengthWritten());
1533         reader1.ImplicitProfileId = TestProfile_2;
1534
1535         // position the reader on the first element
1536         reader1.Next();
1537         uint64_t tag = ProfileTag(TestProfile_1, 1);
1538         err          = chip::TLV::Utilities::Find(reader1, FindContainerWithElement, &tag, tagReader, false);
1539         NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_TLV_TAG_NOT_FOUND);
1540
1541         tag = ProfileTag(TestProfile_2, 2);
1542         err = chip::TLV::Utilities::Find(reader1, FindContainerWithElement, &tag, tagReader, false);
1543         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
1544         NL_TEST_ASSERT(inSuite, tagReader.GetType() == kTLVType_Structure);
1545         NL_TEST_ASSERT(inSuite, tagReader.GetTag() == ProfileTag(TestProfile_1, 1));
1546
1547         // Position the reader on the second element
1548         reader1.Next();
1549         err = chip::TLV::Utilities::Find(reader1, FindContainerWithElement, &tag, tagReader, false);
1550         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
1551         NL_TEST_ASSERT(inSuite, tagReader.GetType() == kTLVType_Structure);
1552         NL_TEST_ASSERT(inSuite, tagReader.GetTag() == ProfileTag(TestProfile_2, 1));
1553     }
1554
1555     // Count
1556     size_t count;
1557     const size_t expectedCount = 18;
1558     reader1.Init(reader);
1559     reader1.Next();
1560
1561     err = chip::TLV::Utilities::Count(reader, count);
1562     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
1563     NL_TEST_ASSERT(inSuite, count == expectedCount);
1564
1565     // Count with reader already positioned "on" the first element in the encoding
1566     err = chip::TLV::Utilities::Count(reader1, count);
1567     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
1568     NL_TEST_ASSERT(inSuite, count == expectedCount);
1569
1570     // Iterate
1571     err = chip::TLV::Utilities::Iterate(reader, NullIterateHandler, nullptr);
1572     NL_TEST_ASSERT(inSuite, err == CHIP_END_OF_TLV);
1573 }
1574
1575 /**
1576  *  Test CHIP TLV Empty Find
1577  */
1578 void CheckCHIPTLVEmptyFind(nlTestSuite * inSuite, void * inContext)
1579 {
1580     uint8_t buf[30];
1581     TLVWriter writer;
1582     TLVReader reader;
1583     CHIP_ERROR err = CHIP_NO_ERROR;
1584
1585     writer.Init(buf, sizeof(buf));
1586     writer.ImplicitProfileId = TestProfile_2;
1587
1588     WriteEmptyEncoding(inSuite, writer);
1589
1590     uint32_t encodedLen = writer.GetLengthWritten();
1591
1592     reader.Init(buf, encodedLen);
1593     reader.ImplicitProfileId = TestProfile_2;
1594
1595     // Find the empty container
1596     TLVReader tagReader;
1597     err = chip::TLV::Utilities::Find(reader, ProfileTag(TestProfile_1, 256), tagReader);
1598     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
1599 }
1600
1601 // clang-format off
1602 uint8_t Encoding2[] =
1603 {
1604     // Container 1
1605     0xD5, 0xBB, 0xAA, 0xDD, 0xCC, 0x01, 0x00,
1606         0xC9, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
1607         0x88, 0x02, 0x00,
1608     0x18,
1609     // Container 2
1610     0x95, 0x01, 0x00,
1611         0x88, 0x02, 0x00,
1612         0xC9, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
1613     0x18
1614 };
1615
1616 uint8_t AppendedEncoding2[] =
1617 {
1618     // Container 1
1619     0xD5, 0xBB, 0xAA, 0xDD, 0xCC, 0x01, 0x00,
1620         0xC9, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
1621         0x88, 0x02, 0x00,
1622         0xC8, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
1623         0x89, 0x02, 0x00,
1624         0xD5, 0xBB, 0xAA, 0xDD, 0xCC, 0x01, 0x00,
1625             0xC9, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
1626             0x88, 0x02, 0x00,
1627         0x18,
1628         0x95, 0x01, 0x00,
1629             0x88, 0x02, 0x00,
1630             0xC9, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
1631         0x18,
1632     0x18,
1633     // Container 2
1634     0x95, 0x01, 0x00,
1635         0x88, 0x02, 0x00,
1636         0xC9, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
1637     0x18
1638 };
1639 // clang-format on
1640
1641 void WriteAppendReadTest0(nlTestSuite * inSuite)
1642 {
1643     uint8_t buf[74];
1644     uint32_t updatedLen;
1645
1646     TLVWriter writer;
1647     TLVReader reader;
1648
1649     writer.Init(buf, sizeof(buf));
1650     writer.ImplicitProfileId = TestProfile_2;
1651
1652     WriteEncoding2(inSuite, writer);
1653
1654     uint32_t encodedLen = writer.GetLengthWritten();
1655
1656 #ifdef DUMP_ENCODING
1657     printf("Initial encoding:\n");
1658     for (uint32_t i = 0; i < encodedLen; i++)
1659     {
1660         if (i != 0 && i % 16 == 0)
1661             printf("\n");
1662         printf("0x%02X, ", buf[i]);
1663     }
1664     printf("\n");
1665 #endif
1666
1667     NL_TEST_ASSERT(inSuite, encodedLen == sizeof(Encoding2));
1668     NL_TEST_ASSERT(inSuite, memcmp(buf, Encoding2, encodedLen) == 0);
1669
1670     // Append new data into encoding
1671     AppendEncoding2(inSuite, buf, encodedLen, sizeof(buf), updatedLen);
1672
1673 #ifdef DUMP_ENCODING
1674     printf("Updated encoding:\n");
1675     for (uint32_t i = 0; i < updatedLen; i++)
1676     {
1677         if (i != 0 && i % 16 == 0)
1678             printf("\n");
1679         printf("0x%02X, ", buf[i]);
1680     }
1681     printf("\n");
1682 #endif
1683
1684     NL_TEST_ASSERT(inSuite, updatedLen == sizeof(AppendedEncoding2));
1685     NL_TEST_ASSERT(inSuite, memcmp(buf, AppendedEncoding2, updatedLen) == 0);
1686
1687     reader.Init(buf, updatedLen);
1688     reader.ImplicitProfileId = TestProfile_2;
1689
1690     ReadAppendedEncoding2(inSuite, reader);
1691 }
1692
1693 void WriteFindAppendReadTest(nlTestSuite * inSuite, bool findContainer)
1694 {
1695     uint8_t buf[74];
1696     uint32_t updatedLen;
1697
1698     TLVWriter writer;
1699     TLVReader reader;
1700
1701     writer.Init(buf, sizeof(buf));
1702     writer.ImplicitProfileId = TestProfile_2;
1703
1704     WriteEncoding2(inSuite, writer);
1705
1706     uint32_t encodedLen = writer.GetLengthWritten();
1707
1708 #ifdef DUMP_ENCODING
1709     printf("Initial encoding:\n");
1710     for (uint32_t i = 0; i < encodedLen; i++)
1711     {
1712         if (i != 0 && i % 16 == 0)
1713             printf("\n");
1714         printf("0x%02X, ", buf[i]);
1715     }
1716     printf("\n");
1717 #endif
1718
1719     NL_TEST_ASSERT(inSuite, encodedLen == sizeof(Encoding2));
1720     NL_TEST_ASSERT(inSuite, memcmp(buf, Encoding2, encodedLen) == 0);
1721
1722     // Append new data into encoding
1723     FindAppendEncoding2(inSuite, buf, encodedLen, sizeof(buf), updatedLen, findContainer);
1724
1725 #ifdef DUMP_ENCODING
1726     printf("Updated encoding:\n");
1727     for (uint32_t i = 0; i < updatedLen; i++)
1728     {
1729         if (i != 0 && i % 16 == 0)
1730             printf("\n");
1731         printf("0x%02X, ", buf[i]);
1732     }
1733     printf("\n");
1734 #endif
1735
1736     NL_TEST_ASSERT(inSuite, updatedLen == sizeof(AppendedEncoding2));
1737     NL_TEST_ASSERT(inSuite, memcmp(buf, AppendedEncoding2, updatedLen) == 0);
1738
1739     reader.Init(buf, updatedLen);
1740     reader.ImplicitProfileId = TestProfile_2;
1741
1742     ReadAppendedEncoding2(inSuite, reader);
1743 }
1744
1745 // clang-format off
1746 uint8_t Encoding3[] =
1747 {
1748     // Container 1
1749     0xD5, 0xBB, 0xAA, 0xDD, 0xCC, 0x01, 0x00,
1750         0x88, 0x02, 0x00,
1751     0x18,
1752 };
1753
1754 uint8_t AppendedEncoding3[] =
1755 {
1756     // Container 1
1757     0xD5, 0xBB, 0xAA, 0xDD, 0xCC, 0x01, 0x00,
1758         0x88, 0x02, 0x00,
1759         0x89, 0x02, 0x00,
1760     0x18
1761 };
1762 // clang-format on
1763
1764 void WriteAppendReadTest1(nlTestSuite * inSuite)
1765 {
1766     uint8_t buf[14];
1767     uint32_t updatedLen;
1768
1769     TLVWriter writer;
1770     TLVReader reader;
1771
1772     writer.Init(buf, sizeof(buf));
1773     writer.ImplicitProfileId = TestProfile_2;
1774
1775     WriteEncoding3(inSuite, writer);
1776
1777     uint32_t encodedLen = writer.GetLengthWritten();
1778
1779 #ifdef DUMP_ENCODING
1780     printf("Initial encoding:\n");
1781     for (uint32_t i = 0; i < encodedLen; i++)
1782     {
1783         if (i != 0 && i % 16 == 0)
1784             printf("\n");
1785         printf("0x%02X, ", buf[i]);
1786     }
1787     printf("\n");
1788 #endif
1789
1790     NL_TEST_ASSERT(inSuite, encodedLen == sizeof(Encoding3));
1791     NL_TEST_ASSERT(inSuite, memcmp(buf, Encoding3, encodedLen) == 0);
1792
1793     // Append new data into encoding
1794     AppendEncoding3(inSuite, buf, encodedLen, sizeof(buf), updatedLen);
1795
1796 #ifdef DUMP_ENCODING
1797     printf("Updated encoding:\n");
1798     for (uint32_t i = 0; i < updatedLen; i++)
1799     {
1800         if (i != 0 && i % 16 == 0)
1801             printf("\n");
1802         printf("0x%02X, ", buf[i]);
1803     }
1804     printf("\n");
1805 #endif
1806
1807     NL_TEST_ASSERT(inSuite, updatedLen == sizeof(AppendedEncoding3));
1808     NL_TEST_ASSERT(inSuite, memcmp(buf, AppendedEncoding3, updatedLen) == 0);
1809
1810     reader.Init(buf, updatedLen);
1811     reader.ImplicitProfileId = TestProfile_2;
1812
1813     ReadAppendedEncoding3(inSuite, reader);
1814 }
1815
1816 // clang-format off
1817 uint8_t AppendedEncoding4[] =
1818 {
1819     // Container 1
1820     0xD5, 0xBB, 0xAA, 0xDD, 0xCC, 0x01, 0x00,
1821         0x88, 0x02, 0x00,
1822     0x18,
1823 };
1824 // clang-format on
1825
1826 void AppendReadTest(nlTestSuite * inSuite)
1827 {
1828     uint8_t buf[11];
1829     uint32_t updatedLen;
1830
1831     memset(buf, 0, sizeof(buf));
1832
1833 #ifdef DUMP_ENCODING
1834     printf("Initial encoding:\n");
1835     for (uint32_t i = 0; i < sizeof(buf); i++)
1836     {
1837         if (i != 0 && i % 16 == 0)
1838             printf("\n");
1839         printf("0x%02X, ", buf[i]);
1840     }
1841     printf("\n");
1842 #endif
1843
1844     // Append new data to encoding
1845     AppendEncoding4(inSuite, buf, 0, sizeof(buf), updatedLen);
1846
1847 #ifdef DUMP_ENCODING
1848     printf("Updated encoding:\n");
1849     for (uint32_t i = 0; i < updatedLen; i++)
1850     {
1851         if (i != 0 && i % 16 == 0)
1852             printf("\n");
1853         printf("0x%02X, ", buf[i]);
1854     }
1855     printf("\n");
1856 #endif
1857
1858     NL_TEST_ASSERT(inSuite, updatedLen == sizeof(AppendedEncoding4));
1859     NL_TEST_ASSERT(inSuite, memcmp(buf, AppendedEncoding4, updatedLen) == 0);
1860
1861     TLVReader reader;
1862     reader.Init(buf, updatedLen);
1863     reader.ImplicitProfileId = TestProfile_2;
1864
1865     ReadAppendedEncoding4(inSuite, reader);
1866 }
1867
1868 // clang-format off
1869 uint8_t Encoding5[] =
1870 {
1871     // Container 1
1872     0xD5, 0xBB, 0xAA, 0xDD, 0xCC, 0x01, 0x00,
1873         0xC9, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
1874         0x88, 0x02, 0x00,
1875         0xC8, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
1876         0x89, 0x02, 0x00,
1877         0xD5, 0xBB, 0xAA, 0xDD, 0xCC, 0x01, 0x00,
1878             0xC9, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
1879             0x88, 0x02, 0x00,
1880         0x18,
1881         0x95, 0x01, 0x00,
1882             0x88, 0x02, 0x00,
1883             0xC9, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
1884         0x18,
1885     0x18,
1886     // Container 2
1887     0x95, 0x01, 0x00,
1888         0x88, 0x02, 0x00,
1889         0xC9, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
1890     0x18
1891 };
1892
1893 uint8_t DeletedEncoding5[] =
1894 {
1895     // Container 1
1896     0xD5, 0xBB, 0xAA, 0xDD, 0xCC, 0x01, 0x00,
1897         0xC9, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
1898         0x88, 0x02, 0x00,
1899     0x18,
1900     // Container 2
1901     0x95, 0x01, 0x00,
1902         0x88, 0x02, 0x00,
1903         0xC9, 0xBB, 0xAA, 0xDD, 0xCC, 0x02, 0x00,
1904     0x18
1905 };
1906 // clang-format on
1907
1908 void WriteDeleteReadTest(nlTestSuite * inSuite)
1909 {
1910     uint8_t buf[74];
1911     uint32_t updatedLen;
1912
1913     TLVWriter writer;
1914     TLVReader reader;
1915
1916     writer.Init(buf, sizeof(buf));
1917     writer.ImplicitProfileId = TestProfile_2;
1918
1919     WriteEncoding5(inSuite, writer);
1920
1921     uint32_t encodedLen = writer.GetLengthWritten();
1922
1923 #ifdef DUMP_ENCODING
1924     for (uint32_t i = 0; i < encodedLen; i++)
1925     {
1926         if (i != 0 && i % 16 == 0)
1927             printf("\n");
1928         printf("0x%02X, ", buf[i]);
1929     }
1930     printf("\n");
1931 #endif
1932
1933     NL_TEST_ASSERT(inSuite, encodedLen == sizeof(Encoding5));
1934     NL_TEST_ASSERT(inSuite, memcmp(buf, Encoding5, encodedLen) == 0);
1935
1936     // Delete some elements from the encoding
1937     DeleteEncoding5(inSuite, buf, encodedLen, sizeof(buf), updatedLen);
1938
1939     NL_TEST_ASSERT(inSuite, updatedLen == sizeof(DeletedEncoding5));
1940     NL_TEST_ASSERT(inSuite, memcmp(buf, DeletedEncoding5, updatedLen) == 0);
1941
1942     reader.Init(buf, updatedLen);
1943     reader.ImplicitProfileId = TestProfile_2;
1944
1945     ReadDeletedEncoding5(inSuite, reader);
1946 }
1947
1948 /**
1949  *  Test Packet Buffer
1950  */
1951 void CheckPacketBuffer(nlTestSuite * inSuite, void * inContext)
1952 {
1953     System::PacketBufferHandle buf = System::PacketBufferHandle::New(sizeof(Encoding1), 0);
1954     System::PacketBufferTLVWriter writer;
1955     System::PacketBufferTLVReader reader;
1956
1957     writer.Init(buf.Retain());
1958     writer.ImplicitProfileId = TestProfile_2;
1959
1960     WriteEncoding1(inSuite, writer);
1961
1962     TestBufferContents(inSuite, buf, Encoding1, sizeof(Encoding1));
1963
1964     reader.Init(buf.Retain());
1965     reader.ImplicitProfileId = TestProfile_2;
1966
1967     ReadEncoding1(inSuite, reader);
1968
1969     reader.Init(buf.Retain(), buf->MaxDataLength());
1970     reader.ImplicitProfileId = TestProfile_2;
1971
1972     ReadEncoding1(inSuite, reader);
1973 }
1974
1975 CHIP_ERROR CountEvictedMembers(CHIPCircularTLVBuffer & inBuffer, void * inAppData, TLVReader & inReader)
1976 {
1977     TestTLVContext * context = static_cast<TestTLVContext *>(inAppData);
1978     CHIP_ERROR err;
1979
1980     // "Process" the first element in the reader
1981     err = inReader.Next();
1982     NL_TEST_ASSERT(context->mSuite, err == CHIP_NO_ERROR);
1983
1984     err = inReader.Skip();
1985     NL_TEST_ASSERT(context->mSuite, err == CHIP_NO_ERROR);
1986
1987     context->mEvictionCount++;
1988     context->mEvictedBytes += inReader.GetLengthRead();
1989
1990     return CHIP_NO_ERROR;
1991 }
1992
1993 void CheckCircularTLVBufferSimple(nlTestSuite * inSuite, void * inContext)
1994 {
1995     // Write 40 bytes as 4 separate events into a 30 byte buffer.  On
1996     // completion of the test, the buffer should contain 2 elements
1997     // and 2 elements should have been evicted in the last call to
1998     // WriteEncoding.
1999
2000     uint8_t backingStore[30];
2001     CircularTLVWriter writer;
2002     CircularTLVReader reader;
2003     TestTLVContext * context = static_cast<TestTLVContext *>(inContext);
2004     CHIPCircularTLVBuffer buffer(backingStore, 30);
2005     writer.Init(buffer);
2006     writer.ImplicitProfileId = TestProfile_2;
2007
2008     context->mEvictionCount = 0;
2009     context->mEvictedBytes  = 0;
2010
2011     buffer.mProcessEvictedElement = CountEvictedMembers;
2012     buffer.mAppData               = inContext;
2013
2014     writer.PutBoolean(ProfileTag(TestProfile_1, 2), true);
2015
2016     WriteEncoding3(inSuite, writer);
2017
2018     WriteEncoding3(inSuite, writer);
2019
2020     WriteEncoding3(inSuite, writer);
2021
2022     NL_TEST_ASSERT(inSuite, context->mEvictionCount == 2);
2023     NL_TEST_ASSERT(inSuite, context->mEvictedBytes == 18);
2024     NL_TEST_ASSERT(inSuite, buffer.DataLength() == 22);
2025     NL_TEST_ASSERT(inSuite, (buffer.DataLength() + context->mEvictedBytes) == writer.GetLengthWritten());
2026
2027     // At this point the buffer should contain 2 instances of Encoding3.
2028     reader.Init(buffer);
2029     reader.ImplicitProfileId = TestProfile_2;
2030
2031     TestNext<TLVReader>(inSuite, reader);
2032
2033     ReadEncoding3(inSuite, reader);
2034
2035     TestNext<TLVReader>(inSuite, reader);
2036
2037     ReadEncoding3(inSuite, reader);
2038
2039     // Check that the reader is out of data
2040     TestEnd<TLVReader>(inSuite, reader);
2041 }
2042
2043 void CheckCircularTLVBufferStartMidway(nlTestSuite * inSuite, void * inContext)
2044 {
2045     // Write 40 bytes as 4 separate events into a 30 byte buffer.  On
2046     // completion of the test, the buffer should contain 2 elements
2047     // and 2 elements should have been evicted in the last call to
2048     // WriteEncoding.
2049
2050     uint8_t backingStore[30];
2051     CircularTLVWriter writer;
2052     CircularTLVReader reader;
2053     TestTLVContext * context = static_cast<TestTLVContext *>(inContext);
2054     CHIPCircularTLVBuffer buffer(backingStore, 30, &(backingStore[15]));
2055     writer.Init(buffer);
2056     writer.ImplicitProfileId = TestProfile_2;
2057
2058     context->mEvictionCount = 0;
2059     context->mEvictedBytes  = 0;
2060
2061     buffer.mProcessEvictedElement = CountEvictedMembers;
2062     buffer.mAppData               = inContext;
2063
2064     writer.PutBoolean(ProfileTag(TestProfile_1, 2), true);
2065
2066     WriteEncoding3(inSuite, writer);
2067
2068     WriteEncoding3(inSuite, writer);
2069
2070     WriteEncoding3(inSuite, writer);
2071
2072     NL_TEST_ASSERT(inSuite, context->mEvictionCount == 2);
2073     NL_TEST_ASSERT(inSuite, context->mEvictedBytes == 18);
2074     NL_TEST_ASSERT(inSuite, buffer.DataLength() == 22);
2075     NL_TEST_ASSERT(inSuite, (buffer.DataLength() + context->mEvictedBytes) == writer.GetLengthWritten());
2076
2077     // At this point the buffer should contain 2 instances of Encoding3.
2078     reader.Init(buffer);
2079     reader.ImplicitProfileId = TestProfile_2;
2080
2081     TestNext<TLVReader>(inSuite, reader);
2082
2083     ReadEncoding3(inSuite, reader);
2084
2085     TestNext<TLVReader>(inSuite, reader);
2086
2087     ReadEncoding3(inSuite, reader);
2088
2089     // Check that the reader is out of data
2090     TestEnd<TLVReader>(inSuite, reader);
2091 }
2092
2093 void CheckCircularTLVBufferEvictStraddlingEvent(nlTestSuite * inSuite, void * inContext)
2094 {
2095     // Write 95 bytes to the buffer as 9 different TLV elements: 1
2096     // 7-byte element and 8 11-byte elements.
2097     // On completion of the test, the buffer should contain 2 elements
2098     // and 7 elements should have been evicted in the last call to
2099     // WriteEncoding.
2100
2101     TestTLVContext * context = static_cast<TestTLVContext *>(inContext);
2102     uint8_t backingStore[30];
2103     CircularTLVWriter writer;
2104     CircularTLVReader reader;
2105     CHIPCircularTLVBuffer buffer(backingStore, 30);
2106     writer.Init(buffer);
2107     writer.ImplicitProfileId = TestProfile_2;
2108
2109     context->mEvictionCount = 0;
2110     context->mEvictedBytes  = 0;
2111
2112     buffer.mProcessEvictedElement = CountEvictedMembers;
2113     buffer.mAppData               = inContext;
2114
2115     writer.PutBoolean(ProfileTag(TestProfile_1, 2), true);
2116
2117     WriteEncoding3(inSuite, writer);
2118
2119     WriteEncoding3(inSuite, writer);
2120
2121     WriteEncoding3(inSuite, writer);
2122
2123     WriteEncoding3(inSuite, writer);
2124
2125     // the write below will evict an element that straddles the buffer boundary.
2126     WriteEncoding3(inSuite, writer);
2127
2128     WriteEncoding3(inSuite, writer);
2129
2130     WriteEncoding3(inSuite, writer);
2131
2132     WriteEncoding3(inSuite, writer);
2133
2134     NL_TEST_ASSERT(inSuite,
2135                    writer.GetLengthWritten() ==
2136                        (8 * 11 + 7)); // 8 writes of Encoding3 (11 bytes each) and 7 bytes for the initial boolean.
2137     NL_TEST_ASSERT(inSuite, buffer.DataLength() == 22);
2138     NL_TEST_ASSERT(inSuite, (buffer.DataLength() + context->mEvictedBytes) == writer.GetLengthWritten());
2139     NL_TEST_ASSERT(inSuite, context->mEvictionCount == 7);
2140
2141     // At this point the buffer should contain 2 instances of Encoding3.
2142     reader.Init(buffer);
2143     reader.ImplicitProfileId = TestProfile_2;
2144
2145     TestNext<TLVReader>(inSuite, reader);
2146
2147     ReadEncoding3(inSuite, reader);
2148
2149     TestNext<TLVReader>(inSuite, reader);
2150
2151     ReadEncoding3(inSuite, reader);
2152
2153     // Check that the reader is out of data
2154     TestEnd<TLVReader>(inSuite, reader);
2155 }
2156
2157 void CheckCircularTLVBufferEdge(nlTestSuite * inSuite, void * inContext)
2158 {
2159     TestTLVContext * context = static_cast<TestTLVContext *>(inContext);
2160     CHIP_ERROR err;
2161     uint8_t backingStore[7];
2162     uint8_t backingStore1[14];
2163     CircularTLVWriter writer;
2164     CircularTLVReader reader;
2165     TLVWriter writer1;
2166
2167     CHIPCircularTLVBuffer buffer(backingStore, sizeof(backingStore));
2168     CHIPCircularTLVBuffer buffer1(backingStore1, sizeof(backingStore1));
2169     writer.Init(buffer);
2170     writer.ImplicitProfileId = TestProfile_2;
2171
2172     context->mEvictionCount = 0;
2173     context->mEvictedBytes  = 0;
2174
2175     buffer.mProcessEvictedElement = CountEvictedMembers;
2176     buffer.mAppData               = inContext;
2177
2178     // Test eviction for an element that fits in the underlying buffer exactly
2179     err = writer.PutBoolean(ProfileTag(TestProfile_1, 2), true);
2180     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2181
2182     err = writer.PutBoolean(ProfileTag(TestProfile_1, 2), false);
2183     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2184
2185     err = writer.Finalize();
2186     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2187     // At this point the buffer should contain only the boolean we just wrote
2188     reader.Init(buffer);
2189     reader.ImplicitProfileId = TestProfile_2;
2190
2191     TestNext<TLVReader>(inSuite, reader);
2192     TestGet<TLVReader, bool>(inSuite, reader, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), false);
2193
2194     // Check that the reader is out of data
2195     TestEnd<TLVReader>(inSuite, reader);
2196
2197     // verify that an element larger than the underlying buffer fails out.
2198     err = writer.OpenContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, writer1);
2199     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2200
2201     err = writer1.PutBoolean(ProfileTag(TestProfile_2, 2), false);
2202     NL_TEST_ASSERT(inSuite, err == CHIP_END_OF_TLV);
2203
2204     // Verify reader correctness
2205
2206     // Write an element that takes half of the buffer, and evict it.
2207     // Do it 2 times, so we test what happens when the head is at the
2208     // middle and at the end of the buffer but the buffer is empty.
2209     int i = 0;
2210     for (i = 0; i < 2; i++)
2211     {
2212         writer.Init(buffer1);
2213         writer.ImplicitProfileId = TestProfile_2;
2214
2215         err = writer.PutBoolean(ProfileTag(TestProfile_1, 2), true);
2216         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2217
2218         err = writer.Finalize();
2219         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2220
2221         reader.Init(buffer1);
2222         reader.ImplicitProfileId = TestProfile_2;
2223
2224         TestNext<TLVReader>(inSuite, reader);
2225         TestGet<TLVReader, bool>(inSuite, reader, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), true);
2226         TestEnd<TLVReader>(inSuite, reader);
2227
2228         buffer1.EvictHead();
2229
2230         reader.Init(buffer1);
2231         reader.ImplicitProfileId = TestProfile_2;
2232         TestEnd<TLVReader>(inSuite, reader);
2233     }
2234
2235     writer.Init(buffer1);
2236     writer.ImplicitProfileId = TestProfile_2;
2237
2238     context->mEvictionCount = 0;
2239     context->mEvictedBytes  = 0;
2240
2241     buffer1.mProcessEvictedElement = CountEvictedMembers;
2242     buffer1.mAppData               = inContext;
2243
2244     // Two elements fit in the buffer exactly
2245     err = writer.PutBoolean(ProfileTag(TestProfile_1, 2), true);
2246     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2247
2248     err = writer.PutBoolean(ProfileTag(TestProfile_1, 2), false);
2249     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2250
2251     err = writer.Finalize();
2252
2253     // Verify that we can read out two elements from the buffer
2254     reader.Init(buffer1);
2255     reader.ImplicitProfileId = TestProfile_2;
2256
2257     TestNext<TLVReader>(inSuite, reader);
2258     TestGet<TLVReader, bool>(inSuite, reader, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), true);
2259
2260     TestNext<TLVReader>(inSuite, reader);
2261     TestGet<TLVReader, bool>(inSuite, reader, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), false);
2262
2263     TestEnd<TLVReader>(inSuite, reader);
2264
2265     // Check that the eviction works as expected
2266
2267     buffer1.EvictHead();
2268
2269     // At this point the buffer should contain only the second boolean
2270     reader.Init(buffer1);
2271     reader.ImplicitProfileId = TestProfile_2;
2272
2273     TestNext<TLVReader>(inSuite, reader);
2274     TestGet<TLVReader, bool>(inSuite, reader, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), false);
2275
2276     // Check that the reader is out of data
2277     TestEnd<TLVReader>(inSuite, reader);
2278
2279     // Write another boolean, verify that the buffer is full and contains two booleans
2280
2281     writer.Init(buffer1);
2282     writer.ImplicitProfileId = TestProfile_2;
2283
2284     err = writer.PutBoolean(ProfileTag(TestProfile_1, 2), true);
2285     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2286
2287     err = writer.Finalize();
2288     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2289
2290     // Verify that we can read out two elements from the buffer
2291     reader.Init(buffer1);
2292     reader.ImplicitProfileId = TestProfile_2;
2293
2294     TestNext<TLVReader>(inSuite, reader);
2295     TestGet<TLVReader, bool>(inSuite, reader, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), false);
2296
2297     TestNext<TLVReader>(inSuite, reader);
2298     TestGet<TLVReader, bool>(inSuite, reader, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), true);
2299
2300     TestEnd<TLVReader>(inSuite, reader);
2301
2302     // Evict the elements from the buffer, verfiy that we have an
2303     // empty reader on our hands
2304
2305     buffer1.EvictHead();
2306     buffer1.EvictHead();
2307
2308     reader.Init(buffer1);
2309     reader.ImplicitProfileId = TestProfile_2;
2310
2311     TestEnd<TLVReader>(inSuite, reader);
2312 }
2313 void CheckCHIPTLVPutStringF(nlTestSuite * inSuite, void * inContext)
2314 {
2315     const size_t bufsize = 24;
2316     char strBuffer[bufsize];
2317     char valStr[bufsize];
2318     uint8_t backingStore[bufsize];
2319     TLVWriter writer;
2320     TLVReader reader;
2321     size_t num     = 1;
2322     CHIP_ERROR err = CHIP_NO_ERROR;
2323
2324     writer.Init(backingStore, bufsize);
2325     snprintf(strBuffer, sizeof(strBuffer), "Sample string %zu", num);
2326
2327     err = writer.PutStringF(ProfileTag(TestProfile_1, 1), "Sample string %zu", num);
2328     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2329
2330     err = writer.Finalize();
2331     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2332
2333     reader.Init(backingStore, writer.GetLengthWritten());
2334     err = reader.Next();
2335     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2336
2337     err = reader.GetString(valStr, 256);
2338     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2339
2340     NL_TEST_ASSERT(inSuite, strncmp(valStr, strBuffer, 256) == 0);
2341 }
2342
2343 void CheckCHIPTLVPutStringFCircular(nlTestSuite * inSuite, void * inContext)
2344 {
2345     const size_t bufsize = 40;
2346     char strBuffer[bufsize];
2347     char valStr[bufsize];
2348     uint8_t backingStore[bufsize];
2349     CircularTLVWriter writer;
2350     CircularTLVReader reader;
2351     CHIPCircularTLVBuffer buffer(backingStore, bufsize);
2352     size_t num     = 1;
2353     CHIP_ERROR err = CHIP_NO_ERROR;
2354
2355     // Initial test: Verify that a straight printf works as expected into continuous buffer.
2356
2357     writer.Init(buffer);
2358     snprintf(strBuffer, sizeof(strBuffer), "Sample string %zu", num);
2359
2360     err = writer.PutBoolean(ProfileTag(TestProfile_1, 2), true);
2361     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2362
2363     err = writer.Finalize();
2364     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2365
2366     err = writer.PutStringF(ProfileTag(TestProfile_1, 1), "Sample string %zu", num);
2367     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2368
2369     err = writer.Finalize();
2370     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2371
2372     reader.Init(buffer);
2373
2374     // Skip over the initial element
2375     err = reader.Next();
2376     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2377
2378     err = reader.Next();
2379     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2380
2381     err = reader.GetString(valStr, bufsize);
2382     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2383
2384     NL_TEST_ASSERT(inSuite, strncmp(valStr, strBuffer, bufsize) == 0);
2385
2386     // Verify that the PutStringF will handle correctly the case with the discontinuous buffer
2387     // This print will both stradle the boundary of the buffer and displace the previous two elements.
2388     num = 2;
2389
2390     snprintf(strBuffer, sizeof(strBuffer), "Sample string %zu", num);
2391
2392     err = writer.PutStringF(ProfileTag(TestProfile_1, 1), "Sample string %zu", num);
2393     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2394
2395     err = writer.Finalize();
2396     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2397
2398     reader.Init(buffer);
2399     err = reader.Next();
2400     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2401
2402     err = reader.GetString(valStr, bufsize);
2403     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2404
2405     NL_TEST_ASSERT(inSuite, strncmp(valStr, strBuffer, bufsize) == 0);
2406 }
2407
2408 void CheckCHIPTLVSkipCircular(nlTestSuite * inSuite, void * inContext)
2409 {
2410     const size_t bufsize = 40; // large enough s.t. 2 elements fit, 3rd causes eviction
2411     uint8_t backingStore[bufsize];
2412     char testString[] = "Sample string"; // 13 characters, without the trailing NULL, add 3 bytes for anon tag
2413     // Any pair of reader and writer would work here, either PacketBuffer based or CircularTLV based.
2414     CircularTLVWriter writer;
2415     CircularTLVReader reader;
2416     CHIPCircularTLVBuffer buffer(backingStore, bufsize);
2417     CHIP_ERROR err = CHIP_NO_ERROR;
2418
2419     writer.Init(buffer);
2420
2421     err = writer.PutString(AnonymousTag, testString);
2422     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2423
2424     err = writer.PutString(AnonymousTag, testString);
2425     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2426
2427     err = writer.PutString(AnonymousTag, testString); // This event straddles the boundary
2428     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2429
2430     err = writer.PutString(AnonymousTag, testString); // This one does not.
2431     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2432
2433     err = writer.Finalize();
2434     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2435
2436     reader.Init(buffer);
2437
2438     err = reader.Next(); // position the reader at the straddling element
2439     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2440
2441     err = reader.Skip(); // // Test that the buf ptr is handled correctly within the ReadData() function.
2442     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2443 }
2444
2445 /**
2446  *  Test Buffer Overflow
2447  */
2448 void CheckBufferOverflow(nlTestSuite * inSuite, void * inContext)
2449 {
2450     System::PacketBufferTLVWriter writer;
2451     System::PacketBufferTLVReader reader;
2452
2453     System::PacketBufferHandle buf = System::PacketBufferHandle::New(sizeof(Encoding1), 0);
2454     uint16_t maxDataLen            = buf->MaxDataLength();
2455     uint16_t reserve = static_cast<uint16_t>((sizeof(Encoding1) < maxDataLen) ? (maxDataLen - sizeof(Encoding1)) + 2 : 0);
2456
2457     // Repeatedly write and read a TLV encoding to a chain of PacketBuffers. Use progressively larger
2458     // and larger amounts of space in the first buffer to force the encoding/decoding to overlap the
2459     // end of the buffer and the beginning of the next.
2460     for (; reserve < maxDataLen; reserve++)
2461     {
2462         buf->SetStart(buf->Start() + reserve);
2463
2464         writer.Init(buf.Retain(), /* useChainedBuffers = */ true);
2465         writer.ImplicitProfileId = TestProfile_2;
2466
2467         WriteEncoding1(inSuite, writer);
2468
2469         TestBufferContents(inSuite, buf, Encoding1, sizeof(Encoding1));
2470
2471         reader.Init(buf.Retain(), /* useChainedBuffers = */ true);
2472         reader.ImplicitProfileId = TestProfile_2;
2473
2474         ReadEncoding1(inSuite, reader);
2475
2476         buf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSizeWithoutReserve, 0);
2477     }
2478 }
2479
2480 /**
2481  * Test case to verify the correctness of TLVReader::GetTag()
2482  *
2483  * TLVReader::GetTag() does not return the correct tag value when the
2484  * the compiler optimization level contains strict aliasing. In the below
2485  * example, the returned tag value would be 0xe, instead of 0xe00000001.
2486  *
2487  * The issue has been spotted on debug builds.
2488  *
2489  */
2490 // clang-format off
2491 static const uint8_t sIdentifyResponseBuf[] =
2492 {
2493     0xD5, 0x00, 0x00, 0x0E, 0x00, 0x01, 0x00, 0x25,
2494     0x00, 0x5A, 0x23, 0x24, 0x01, 0x07, 0x24, 0x02,
2495     0x05, 0x25, 0x03, 0x22, 0x1E, 0x2C, 0x04, 0x10,
2496     0x30, 0x34, 0x41, 0x41, 0x30, 0x31, 0x41, 0x43,
2497     0x32, 0x33, 0x31, 0x34, 0x30, 0x30, 0x4C, 0x50,
2498     0x2C, 0x09, 0x06, 0x31, 0x2E, 0x34, 0x72, 0x63,
2499     0x35, 0x24, 0x0C, 0x01, 0x18,
2500 };
2501 // clang-format on
2502
2503 static const uint32_t kIdentifyResponseLen = 53;
2504
2505 void CheckStrictAliasing(nlTestSuite * inSuite, void * inContext)
2506 {
2507     const uint32_t kProfile_Id = 0x0000000e;
2508     CHIP_ERROR err             = CHIP_NO_ERROR;
2509     TLVReader reader;
2510
2511     reader.Init(sIdentifyResponseBuf, kIdentifyResponseLen);
2512     reader.ImplicitProfileId = kProfile_Id;
2513
2514     err = reader.Next();
2515     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2516
2517     NL_TEST_ASSERT(inSuite, reader.GetTag() == 0xe00000001);
2518 }
2519
2520 /**
2521  *  Test CHIP TLV Writer Copy Container
2522  */
2523 void TestCHIPTLVWriterCopyContainer(nlTestSuite * inSuite)
2524 {
2525     uint8_t buf[2048];
2526
2527     {
2528         TLVWriter writer;
2529         TLVReader reader;
2530
2531         reader.Init(Encoding1, sizeof(Encoding1));
2532         reader.ImplicitProfileId = TestProfile_2;
2533
2534         TestNext<TLVReader>(inSuite, reader);
2535
2536         writer.Init(buf, sizeof(buf));
2537         writer.ImplicitProfileId = TestProfile_2;
2538
2539         CHIP_ERROR err = writer.CopyContainer(reader);
2540         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2541
2542         uint32_t encodedLen = writer.GetLengthWritten();
2543         NL_TEST_ASSERT(inSuite, encodedLen == sizeof(Encoding1));
2544
2545         int memcmpRes = memcmp(buf, Encoding1, encodedLen);
2546         NL_TEST_ASSERT(inSuite, memcmpRes == 0);
2547     }
2548
2549     {
2550         TLVWriter writer;
2551
2552         writer.Init(buf, sizeof(buf));
2553         writer.ImplicitProfileId = TestProfile_2;
2554
2555         CHIP_ERROR err = writer.CopyContainer(ProfileTag(TestProfile_1, 1), Encoding1, sizeof(Encoding1));
2556         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2557
2558         uint32_t encodedLen = writer.GetLengthWritten();
2559         NL_TEST_ASSERT(inSuite, encodedLen == sizeof(Encoding1));
2560
2561         int memcmpRes = memcmp(buf, Encoding1, encodedLen);
2562         NL_TEST_ASSERT(inSuite, memcmpRes == 0);
2563     }
2564 }
2565
2566 /**
2567  *  Test CHIP TLV Writer Copy Element
2568  */
2569 void TestCHIPTLVWriterCopyElement(nlTestSuite * inSuite)
2570 {
2571     CHIP_ERROR err;
2572     uint8_t expectedBuf[2048], testBuf[2048];
2573     uint32_t expectedLen, testLen;
2574     TLVWriter writer;
2575     TLVType outerContainerType;
2576     enum
2577     {
2578         kRepeatCount = 3
2579     };
2580
2581     writer.Init(expectedBuf, sizeof(expectedBuf));
2582     writer.ImplicitProfileId = TestProfile_2;
2583
2584     err = writer.StartContainer(AnonymousTag, kTLVType_Structure, outerContainerType);
2585     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2586
2587     for (int i = 0; i < kRepeatCount; i++)
2588     {
2589         WriteEncoding1(inSuite, writer);
2590     }
2591
2592     err = writer.EndContainer(outerContainerType);
2593     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2594
2595     err = writer.Finalize();
2596     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2597
2598     expectedLen = writer.GetLengthWritten();
2599
2600     writer.Init(testBuf, sizeof(testBuf));
2601     writer.ImplicitProfileId = TestProfile_2;
2602
2603     err = writer.StartContainer(AnonymousTag, kTLVType_Structure, outerContainerType);
2604     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2605
2606     for (int i = 0; i < kRepeatCount; i++)
2607     {
2608         TLVReader reader;
2609
2610         reader.Init(Encoding1, sizeof(Encoding1));
2611         reader.ImplicitProfileId = TestProfile_2;
2612
2613         TestNext<TLVReader>(inSuite, reader);
2614
2615         err = writer.CopyElement(reader);
2616         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2617     }
2618
2619     err = writer.EndContainer(outerContainerType);
2620     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2621
2622     err = writer.Finalize();
2623     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2624
2625     testLen = writer.GetLengthWritten();
2626
2627     NL_TEST_ASSERT(inSuite, testLen == expectedLen);
2628
2629     int memcmpRes = memcmp(testBuf, expectedBuf, testLen);
2630     NL_TEST_ASSERT(inSuite, memcmpRes == 0);
2631 }
2632
2633 void PreserveSizeWrite(nlTestSuite * inSuite, TLVWriter & writer, bool preserveSize)
2634 {
2635     CHIP_ERROR err;
2636     TLVWriter writer2;
2637
2638     // TLVTagControl::FullyQualified_8Bytes
2639     err = writer.Put(ProfileTag(TestProfile_1, 4000000000ULL), static_cast<int64_t>(40000000000ULL), true);
2640     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2641
2642     err = writer.Put(ProfileTag(TestProfile_1, 4000000000ULL), static_cast<int16_t>(12345), true);
2643     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2644
2645     err = writer.Put(ProfileTag(TestProfile_1, 4000000000ULL), static_cast<float>(1.0));
2646     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2647
2648     err = writer.OpenContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, writer2);
2649     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2650
2651     {
2652         TLVWriter writer3;
2653
2654         err = writer2.OpenContainer(ContextTag(0), kTLVType_Array, writer3);
2655         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2656
2657         err = writer3.Put(AnonymousTag, static_cast<uint8_t>(42), preserveSize);
2658         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2659
2660         err = writer3.Put(AnonymousTag, static_cast<uint16_t>(42), preserveSize);
2661         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2662
2663         err = writer3.Put(AnonymousTag, static_cast<uint32_t>(42), preserveSize);
2664         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2665
2666         err = writer3.Put(AnonymousTag, static_cast<uint64_t>(40000000000ULL), preserveSize);
2667         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2668
2669         err = writer3.Put(AnonymousTag, static_cast<int8_t>(-17), preserveSize);
2670         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2671
2672         err = writer3.Put(AnonymousTag, static_cast<int16_t>(-17), preserveSize);
2673         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2674
2675         err = writer3.Put(AnonymousTag, static_cast<int32_t>(-170000), preserveSize);
2676         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2677
2678         err = writer3.Put(AnonymousTag, static_cast<int64_t>(-170000), preserveSize);
2679         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2680
2681         // the below cases are for full coverage of PUTs
2682         err = writer3.Put(AnonymousTag, static_cast<uint64_t>(65535), false);
2683         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2684
2685         err = writer3.Put(AnonymousTag, static_cast<int64_t>(32767), false);
2686         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2687
2688         err = writer3.Put(AnonymousTag, static_cast<int64_t>(40000000000ULL), false);
2689         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2690
2691         err = writer2.CloseContainer(writer3);
2692         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2693     }
2694
2695     err = writer.CloseContainer(writer2);
2696     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2697
2698     err = writer.Finalize();
2699     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2700 }
2701
2702 /**
2703  *  Test CHIP TLV Writer with Preserve Size
2704  */
2705 void TestCHIPTLVWriterPreserveSize(nlTestSuite * inSuite)
2706 {
2707     uint8_t buf[2048];
2708     TLVWriter writer;
2709
2710     writer.Init(buf, sizeof(buf));
2711     writer.ImplicitProfileId = TestProfile_2;
2712
2713     PreserveSizeWrite(inSuite, writer, true);
2714
2715     uint32_t encodedLen = writer.GetLengthWritten();
2716     NL_TEST_ASSERT(inSuite, encodedLen == 105);
2717 }
2718
2719 /**
2720  *  Test error handling of CHIP TLV Writer
2721  */
2722 void TestCHIPTLVWriterErrorHandling(nlTestSuite * inSuite)
2723 {
2724     CHIP_ERROR err;
2725     uint8_t buf[2048];
2726     TLVWriter writer, writer2, writer3;
2727
2728     writer.Init(buf, sizeof(buf));
2729     writer.ImplicitProfileId = TestProfile_2;
2730
2731     // OpenContainer() for non-container
2732     err = writer.OpenContainer(ProfileTag(TestProfile_1, 1), kTLVType_Boolean, writer2);
2733     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_WRONG_TLV_TYPE);
2734
2735     // CloseContainer() for non-container
2736     err = writer.CloseContainer(writer2);
2737     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INCORRECT_STATE);
2738
2739     // OpenContainer() failure
2740     err = writer.OpenContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, writer2);
2741     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2742
2743     err = writer2.OpenContainer(ProfileTag(TestProfile_1, 1), kTLVType_Structure, writer3);
2744     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
2745
2746     // CloseContainer() failure
2747     err = writer.CloseContainer(writer2);
2748     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_TLV_CONTAINER_OPEN);
2749
2750     // StartContainer()
2751     TLVType outerContainerType;
2752     err = writer.StartContainer(ProfileTag(TestProfile_2, 4000000000ULL), kTLVType_Boolean, outerContainerType);
2753     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_WRONG_TLV_TYPE);
2754
2755     // EndContainer()
2756     outerContainerType = kTLVType_Boolean;
2757     err                = writer.EndContainer(outerContainerType);
2758     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INCORRECT_STATE);
2759
2760     // PutPreEncodedContainer()
2761     TLVReader reader;
2762     reader.Init(buf, 2048);
2763     err = writer.PutPreEncodedContainer(ProfileTag(TestProfile_2, 4000000000ULL), kTLVType_Boolean, reader.GetReadPoint(),
2764                                         reader.GetRemainingLength());
2765     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INVALID_ARGUMENT);
2766 }
2767
2768 /**
2769  *  Test CHIP TLV Writer
2770  */
2771 void CheckCHIPTLVWriter(nlTestSuite * inSuite, void * inContext)
2772 {
2773     TestCHIPTLVWriterCopyContainer(inSuite);
2774
2775     TestCHIPTLVWriterCopyElement(inSuite);
2776
2777     TestCHIPTLVWriterPreserveSize(inSuite);
2778
2779     TestCHIPTLVWriterErrorHandling(inSuite);
2780 }
2781
2782 void SkipNonContainer(nlTestSuite * inSuite)
2783 {
2784     TLVReader reader;
2785     const uint8_t * readpoint1 = nullptr;
2786     const uint8_t * readpoint2 = nullptr;
2787
2788     reader.Init(Encoding1, sizeof(Encoding1));
2789     reader.ImplicitProfileId = TestProfile_2;
2790
2791     TestSkip(inSuite, reader);
2792
2793     readpoint1 = reader.GetReadPoint();
2794
2795     // Skip again, to check the operation is idempotent
2796     TestSkip(inSuite, reader);
2797
2798     readpoint2 = reader.GetReadPoint();
2799
2800     NL_TEST_ASSERT(inSuite, readpoint1 == readpoint2);
2801 }
2802
2803 void SkipContainer(nlTestSuite * inSuite)
2804 {
2805     TLVReader reader;
2806     const uint8_t * readpoint1 = nullptr;
2807     const uint8_t * readpoint2 = nullptr;
2808
2809     reader.Init(Encoding1, sizeof(Encoding1));
2810     reader.ImplicitProfileId = TestProfile_2;
2811
2812     TestNext<TLVReader>(inSuite, reader);
2813
2814     TestSkip(inSuite, reader);
2815
2816     readpoint1 = reader.GetReadPoint();
2817
2818     // Skip again, to check the operation is idempotent
2819     TestSkip(inSuite, reader);
2820
2821     readpoint2 = reader.GetReadPoint();
2822
2823     NL_TEST_ASSERT(inSuite, readpoint1 == readpoint2);
2824 }
2825
2826 void NextContainer(nlTestSuite * inSuite)
2827 {
2828     TLVReader reader;
2829
2830     reader.Init(Encoding1, sizeof(Encoding1));
2831     reader.ImplicitProfileId = TestProfile_2;
2832
2833     TestNext<TLVReader>(inSuite, reader);
2834
2835     CHIP_ERROR err = reader.Next();
2836     NL_TEST_ASSERT(inSuite, err == CHIP_END_OF_TLV);
2837 }
2838
2839 /**
2840  *  Test CHIP TLV Reader Skip functions
2841  */
2842 void TestCHIPTLVReaderSkip(nlTestSuite * inSuite)
2843 {
2844     SkipNonContainer(inSuite);
2845
2846     SkipContainer(inSuite);
2847
2848     NextContainer(inSuite);
2849 }
2850
2851 /**
2852  *  Test CHIP TLV Reader Dup functions
2853  */
2854 void TestCHIPTLVReaderDup(nlTestSuite * inSuite)
2855 {
2856     TLVReader reader;
2857
2858     reader.Init(Encoding1, sizeof(Encoding1));
2859     reader.ImplicitProfileId = TestProfile_2;
2860
2861     TestNext<TLVReader>(inSuite, reader);
2862
2863     {
2864         TLVReader reader2;
2865
2866         TestAndOpenContainer(inSuite, reader, kTLVType_Structure, ProfileTag(TestProfile_1, 1), reader2);
2867
2868         TestNext<TLVReader>(inSuite, reader2);
2869
2870         TestGet<TLVReader, bool>(inSuite, reader2, kTLVType_Boolean, ProfileTag(TestProfile_1, 2), true);
2871
2872         TestNext<TLVReader>(inSuite, reader2);
2873
2874         TestGet<TLVReader, bool>(inSuite, reader2, kTLVType_Boolean, ProfileTag(TestProfile_2, 2), false);
2875
2876         TestNext<TLVReader>(inSuite, reader2);
2877
2878         {
2879             TLVReader reader3;
2880
2881             TestAndOpenContainer(inSuite, reader2, kTLVType_Array, ContextTag(0), reader3);
2882
2883             TestNext<TLVReader>(inSuite, reader3);
2884
2885             TestGet<TLVReader, int8_t>(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag, 42);
2886             TestGet<TLVReader, int16_t>(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag, 42);
2887             TestGet<TLVReader, int32_t>(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag, 42);
2888             TestGet<TLVReader, int64_t>(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag, 42);
2889             TestGet<TLVReader, uint32_t>(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag, 42);
2890             TestGet<TLVReader, uint64_t>(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag, 42);
2891
2892             TestNext<TLVReader>(inSuite, reader3);
2893
2894             TestGet<TLVReader, int8_t>(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag, -17);
2895             TestGet<TLVReader, int16_t>(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag, -17);
2896             TestGet<TLVReader, int32_t>(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag, -17);
2897             TestGet<TLVReader, int64_t>(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag, -17);
2898
2899             TestNext<TLVReader>(inSuite, reader3);
2900
2901             TestGet<TLVReader, int32_t>(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag, -170000);
2902             TestGet<TLVReader, int64_t>(inSuite, reader3, kTLVType_SignedInteger, AnonymousTag, -170000);
2903
2904             TestNext<TLVReader>(inSuite, reader3);
2905
2906             TestGet<TLVReader, int64_t>(inSuite, reader3, kTLVType_UnsignedInteger, AnonymousTag, 40000000000ULL);
2907             TestGet<TLVReader, uint64_t>(inSuite, reader3, kTLVType_UnsignedInteger, AnonymousTag, 40000000000ULL);
2908
2909             TestNext<TLVReader>(inSuite, reader3);
2910
2911             {
2912                 TLVReader reader4;
2913
2914                 TestAndOpenContainer(inSuite, reader3, kTLVType_Structure, AnonymousTag, reader4);
2915
2916                 TestEndAndCloseContainer(inSuite, reader3, reader4);
2917             }
2918
2919             TestNext<TLVReader>(inSuite, reader3);
2920
2921             {
2922                 TLVReader reader5;
2923
2924                 TestAndOpenContainer(inSuite, reader3, kTLVType_List, AnonymousTag, reader5);
2925
2926                 TestNext<TLVReader>(inSuite, reader5);
2927
2928                 TestNull(inSuite, reader5, ProfileTag(TestProfile_1, 17));
2929
2930                 TestNext<TLVReader>(inSuite, reader5);
2931
2932                 TestNull(inSuite, reader5, ProfileTag(TestProfile_2, 900000));
2933
2934                 TestNext<TLVReader>(inSuite, reader5);
2935
2936                 TestNull(inSuite, reader5, AnonymousTag);
2937
2938                 TestNext<TLVReader>(inSuite, reader5);
2939
2940                 {
2941                     TLVType outerContainerType;
2942
2943                     TestAndEnterContainer<TLVReader>(inSuite, reader5, kTLVType_Structure, ProfileTag(TestProfile_2, 4000000000ULL),
2944                                                      outerContainerType);
2945
2946                     TestNext<TLVReader>(inSuite, reader5);
2947
2948                     TestDupString(inSuite, reader5, CommonTag(70000), sLargeString);
2949
2950                     TestEndAndExitContainer<TLVReader>(inSuite, reader5, outerContainerType);
2951                 }
2952
2953                 TestEndAndCloseContainer(inSuite, reader3, reader5);
2954             }
2955
2956             TestEndAndCloseContainer(inSuite, reader2, reader3);
2957         }
2958
2959         TestNext<TLVReader>(inSuite, reader2);
2960
2961         TestDupBytes(inSuite, reader2, ProfileTag(TestProfile_1, 5), reinterpret_cast<const uint8_t *>("This is a test"), 14);
2962
2963         TestNext<TLVReader>(inSuite, reader2);
2964
2965         TestGet<TLVReader, double>(inSuite, reader2, kTLVType_FloatingPointNumber, ProfileTag(TestProfile_2, 65535),
2966                                    static_cast<float>(17.9));
2967
2968         TestNext<TLVReader>(inSuite, reader2);
2969
2970         TestGet<TLVReader, double>(inSuite, reader2, kTLVType_FloatingPointNumber, ProfileTag(TestProfile_2, 65536), 17.9);
2971
2972         TestEndAndCloseContainer(inSuite, reader, reader2);
2973     }
2974
2975     TestEnd<TLVReader>(inSuite, reader);
2976 }
2977 /**
2978  *  Test error handling of CHIP TLV Reader
2979  */
2980 void TestCHIPTLVReaderErrorHandling(nlTestSuite * inSuite)
2981 {
2982     CHIP_ERROR err;
2983     uint8_t buf[2048];
2984     TLVReader reader;
2985
2986     reader.Init(buf, sizeof(buf));
2987     reader.ImplicitProfileId = TestProfile_2;
2988
2989     // Get(bool&)
2990     bool val;
2991     err = reader.Get(val);
2992     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_WRONG_TLV_TYPE);
2993
2994     // Get(double&)
2995     double numD;
2996     err = reader.Get(numD);
2997     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_WRONG_TLV_TYPE);
2998
2999     // Get(uint64_t&)
3000     uint64_t num;
3001     err = reader.Get(num);
3002     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_WRONG_TLV_TYPE);
3003
3004     // GetBytes()
3005     uint8_t bBuf[16];
3006     err = reader.GetBytes(bBuf, sizeof(bBuf));
3007     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_WRONG_TLV_TYPE);
3008
3009     // GetString()
3010     char sBuf[16];
3011     err = reader.GetString(sBuf, sizeof(sBuf));
3012     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_WRONG_TLV_TYPE);
3013
3014     // OpenContainer()
3015     TLVReader reader2;
3016     err = reader.OpenContainer(reader2);
3017     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INCORRECT_STATE);
3018
3019     // CloseContainer()
3020     err = reader.CloseContainer(reader2);
3021     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INCORRECT_STATE);
3022
3023     // EnterContainer()
3024     TLVType outerContainerType = kTLVType_Boolean;
3025     err                        = reader.EnterContainer(outerContainerType);
3026     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INCORRECT_STATE);
3027
3028     // DupString()
3029     char * str = static_cast<char *>(chip::Platform::MemoryAlloc(16));
3030     err        = reader.DupString(str);
3031     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_WRONG_TLV_TYPE);
3032     chip::Platform::MemoryFree(str);
3033
3034     // GetDataPtr()
3035     const uint8_t * data = static_cast<uint8_t *>(chip::Platform::MemoryAlloc(16));
3036     err                  = reader.GetDataPtr(data);
3037     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_WRONG_TLV_TYPE);
3038     chip::Platform::MemoryFree(const_cast<uint8_t *>(data));
3039 }
3040 /**
3041  *  Test CHIP TLV Reader in a use case
3042  */
3043 void TestCHIPTLVReaderInPractice(nlTestSuite * inSuite)
3044 {
3045     uint8_t buf[2048];
3046     TLVWriter writer;
3047     TLVReader reader;
3048
3049     writer.Init(buf, sizeof(buf));
3050     writer.ImplicitProfileId = TestProfile_2;
3051
3052     PreserveSizeWrite(inSuite, writer, true);
3053
3054     reader.Init(buf, sizeof(buf));
3055
3056     TestNext<TLVReader>(inSuite, reader);
3057
3058     TestGet<TLVReader, int64_t>(inSuite, reader, kTLVType_SignedInteger, ProfileTag(TestProfile_1, 4000000000ULL),
3059                                 static_cast<int64_t>(40000000000ULL));
3060
3061     TestNext<TLVReader>(inSuite, reader);
3062
3063     TestGet<TLVReader, int64_t>(inSuite, reader, kTLVType_SignedInteger, ProfileTag(TestProfile_1, 4000000000ULL),
3064                                 static_cast<int16_t>(12345));
3065
3066     TestNext<TLVReader>(inSuite, reader);
3067
3068     TestGet<TLVReader, double>(inSuite, reader, kTLVType_FloatingPointNumber, ProfileTag(TestProfile_1, 4000000000ULL),
3069                                static_cast<float>(1.0));
3070 }
3071
3072 void TestCHIPTLVReader_NextOverContainer_ProcessElement(nlTestSuite * inSuite, TLVReader & reader, void * context)
3073 {
3074     CHIP_ERROR err, nextRes1, nextRes2;
3075     TLVType outerContainerType;
3076
3077     // If the current element is a container...
3078     if (TLVTypeIsContainer(reader.GetType()))
3079     {
3080         // Make two copies of the reader
3081         TLVReader readerClone1 = reader;
3082         TLVReader readerClone2 = reader;
3083
3084         // Manually advance one of the readers to the element immediately after the container (if any).
3085         err = readerClone1.EnterContainer(outerContainerType);
3086         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3087         ForEachElement(inSuite, readerClone1, nullptr, nullptr);
3088         err = readerClone1.ExitContainer(outerContainerType);
3089         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3090         nextRes1 = readerClone1.Next();
3091         NL_TEST_ASSERT(inSuite, nextRes1 == CHIP_NO_ERROR || nextRes1 == CHIP_END_OF_TLV);
3092
3093         // For the other reader, skip over the entire container using the Next() method.
3094         nextRes2 = readerClone2.Next();
3095         NL_TEST_ASSERT(inSuite, nextRes2 == CHIP_NO_ERROR || nextRes2 == CHIP_END_OF_TLV);
3096
3097         // Verify the two readers end up in the same state/position.
3098         NL_TEST_ASSERT(inSuite, nextRes1 == nextRes2);
3099         NL_TEST_ASSERT(inSuite, readerClone1.GetType() == readerClone2.GetType());
3100         NL_TEST_ASSERT(inSuite, readerClone1.GetReadPoint() == readerClone2.GetReadPoint());
3101     }
3102 }
3103
3104 /**
3105  * Test using CHIP TLV Reader Next() method to skip over containers.
3106  */
3107 void TestCHIPTLVReader_NextOverContainer(nlTestSuite * inSuite)
3108 {
3109     TLVReader reader;
3110
3111     reader.Init(Encoding1, sizeof(Encoding1));
3112     reader.ImplicitProfileId = TestProfile_2;
3113
3114     ForEachElement(inSuite, reader, nullptr, TestCHIPTLVReader_NextOverContainer_ProcessElement);
3115 }
3116
3117 void TestCHIPTLVReader_SkipOverContainer_ProcessElement(nlTestSuite * inSuite, TLVReader & reader, void * context)
3118 {
3119     CHIP_ERROR err;
3120     TLVType outerContainerType;
3121
3122     // If the current element is a container...
3123     if (TLVTypeIsContainer(reader.GetType()))
3124     {
3125         // Make two copies of the reader
3126         TLVReader readerClone1 = reader;
3127         TLVReader readerClone2 = reader;
3128
3129         // Manually advance one of the readers to immediately after the container.
3130         err = readerClone1.EnterContainer(outerContainerType);
3131         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3132         ForEachElement(inSuite, readerClone1, nullptr, nullptr);
3133         err = readerClone1.ExitContainer(outerContainerType);
3134         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3135
3136         // For the other reader, skip over the entire container using the Skip() method.
3137         err = readerClone2.Skip();
3138         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3139
3140         // Verify the two readers end up in the same state/position.
3141         NL_TEST_ASSERT(inSuite, readerClone1.GetType() == readerClone2.GetType());
3142         NL_TEST_ASSERT(inSuite, readerClone1.GetReadPoint() == readerClone2.GetReadPoint());
3143     }
3144 }
3145
3146 /**
3147  * Test using CHIP TLV Reader Skip() method to skip over containers.
3148  */
3149 void TestCHIPTLVReader_SkipOverContainer(nlTestSuite * inSuite)
3150 {
3151     TLVReader reader;
3152
3153     reader.Init(Encoding1, sizeof(Encoding1));
3154     reader.ImplicitProfileId = TestProfile_2;
3155
3156     ForEachElement(inSuite, reader, nullptr, TestCHIPTLVReader_SkipOverContainer_ProcessElement);
3157 }
3158
3159 /**
3160  *  Test CHIP TLV Reader
3161  */
3162 void CheckCHIPTLVReader(nlTestSuite * inSuite, void * inContext)
3163 {
3164     TestCHIPTLVReaderSkip(inSuite);
3165
3166     TestCHIPTLVReaderDup(inSuite);
3167
3168     TestCHIPTLVReaderErrorHandling(inSuite);
3169
3170     TestCHIPTLVReaderInPractice(inSuite);
3171
3172     TestCHIPTLVReader_NextOverContainer(inSuite);
3173
3174     TestCHIPTLVReader_SkipOverContainer(inSuite);
3175 }
3176
3177 /**
3178  *  Test CHIP TLV Items
3179  */
3180 static void TestItems(nlTestSuite * inSuite, void * inContext)
3181 {
3182     CHIP_ERROR err = CHIP_NO_ERROR;
3183
3184     uint8_t sBuffer[256];
3185
3186     TLVWriter writer;
3187     writer.Init(sBuffer, sizeof(sBuffer));
3188
3189     TLVWriter writer2;
3190     err = writer.OpenContainer(AnonymousTag, kTLVType_Array, writer2);
3191     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3192
3193     {
3194         err = writer2.PutBoolean(AnonymousTag, true);
3195         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3196
3197         err = writer2.Put(AnonymousTag, static_cast<int8_t>(-1));
3198         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3199
3200         err = writer2.Put(AnonymousTag, static_cast<int16_t>(-2));
3201         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3202
3203         err = writer2.Put(AnonymousTag, static_cast<int32_t>(-3));
3204         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3205
3206         err = writer2.Put(AnonymousTag, static_cast<int64_t>(-4));
3207         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3208
3209         err = writer2.Put(AnonymousTag, static_cast<float>(-5.5));
3210         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3211
3212         err = writer2.Put(AnonymousTag, static_cast<double>(-3.14159265358979323846));
3213         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3214     }
3215
3216     err = writer.CloseContainer(writer2);
3217     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3218
3219     err = writer.OpenContainer(AnonymousTag, kTLVType_Array, writer2);
3220     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3221
3222     {
3223         err = writer2.PutBoolean(AnonymousTag, false);
3224         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3225
3226         err = writer2.Put(AnonymousTag, static_cast<int8_t>(1));
3227         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3228
3229         err = writer2.Put(AnonymousTag, static_cast<int16_t>(2));
3230         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3231
3232         err = writer2.Put(AnonymousTag, static_cast<int32_t>(3));
3233         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3234
3235         err = writer2.Put(AnonymousTag, static_cast<int64_t>(4));
3236         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3237
3238         err = writer2.Put(AnonymousTag, static_cast<uint8_t>(5));
3239         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3240
3241         err = writer2.Put(AnonymousTag, static_cast<uint16_t>(6));
3242         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3243
3244         err = writer2.Put(AnonymousTag, static_cast<uint32_t>(7));
3245         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3246
3247         err = writer2.Put(AnonymousTag, static_cast<uint64_t>(8));
3248         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3249
3250         err = writer2.Put(AnonymousTag, static_cast<float>(9.9));
3251         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3252
3253         err = writer2.Put(AnonymousTag, static_cast<double>(3.14159265358979323846));
3254         NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3255     }
3256
3257     err = writer.CloseContainer(writer2);
3258     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3259
3260     err = writer.Finalize();
3261     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3262 }
3263
3264 /**
3265  *  Test CHIP TLV Containers
3266  */
3267 static void TestContainers(nlTestSuite * inSuite, void * inContext)
3268 {
3269     CHIP_ERROR err = CHIP_NO_ERROR;
3270     TLVWriter writer;
3271
3272     uint8_t sBuffer[256];
3273     writer.Init(sBuffer, sizeof(sBuffer));
3274
3275     TLVWriter writer2;
3276     err = writer.OpenContainer(AnonymousTag, kTLVType_Array, writer2);
3277     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3278
3279     TLVType type = writer2.GetContainerType();
3280     NL_TEST_ASSERT(inSuite, type == kTLVType_Array);
3281
3282     err = writer.CloseContainer(writer2);
3283     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3284
3285     err = writer.OpenContainer(AnonymousTag, kTLVType_Structure, writer2);
3286     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3287
3288     type = writer2.GetContainerType();
3289     NL_TEST_ASSERT(inSuite, type == kTLVType_Structure);
3290
3291     err = writer.CloseContainer(writer2);
3292     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3293
3294     err = writer.Finalize();
3295     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3296 }
3297
3298 /**
3299  *  Test CHIP TLV Basics
3300  */
3301 static void CheckCHIPTLVBasics(nlTestSuite * inSuite, void * inContext)
3302 {
3303     TestItems(inSuite, inContext);
3304     TestContainers(inSuite, inContext);
3305 }
3306
3307 /**
3308  *  Test CHIP TLV Updater
3309  */
3310 static void CheckCHIPUpdater(nlTestSuite * inSuite, void * inContext)
3311 {
3312     WriteAppendReadTest0(inSuite);
3313
3314     WriteAppendReadTest1(inSuite);
3315
3316     WriteFindAppendReadTest(inSuite, false); // Find an element
3317
3318     WriteFindAppendReadTest(inSuite, true); // Find a container
3319
3320     AppendReadTest(inSuite);
3321
3322     WriteDeleteReadTest(inSuite);
3323 }
3324
3325 /**
3326  * Test TLV CloseContainer symbol reservations
3327  */
3328
3329 class OptimisticTLVWriter : public TLVWriter
3330 {
3331 public:
3332     void Init(uint8_t * buf, uint32_t maxLen);
3333 };
3334
3335 void OptimisticTLVWriter::Init(uint8_t * buf, uint32_t maxLen)
3336 {
3337     TLVWriter::Init(buf, maxLen);
3338     SetCloseContainerReserved(false);
3339 }
3340
3341 static void CheckCloseContainerReserve(nlTestSuite * inSuite, void * inContext)
3342 {
3343     // We are writing the structure looking like:
3344     //
3345     // [{TestProfile_1:2: true}]
3346     //
3347     // the above should consume 11 bytes in the TLV encoding. The
3348     // chosen buffer is too small for that, this test verifies that we
3349     // fail in the right places in the code.  With the standard
3350     // TLVWriter, we now make provisions to reserve the space for the
3351     // CloseContainer tag in the OpenContainer call.  As a result, we
3352     // expect to error out when we attempt to write out the value for
3353     // the TestProfile_1:2 tag.  In contrast, the
3354     // `OptimisticTLVWriter` implements the earlier TLVWriter behavior
3355     // and fails out in the last CloseContainer call.  The error
3356     // caught there is different because we run up against the mMaxLen
3357     // rather than mRemainingLen check.
3358
3359     uint8_t buf[10];
3360     uint8_t buf1[7];
3361     CHIP_ERROR err = CHIP_NO_ERROR;
3362     TLVWriter writer1;
3363     OptimisticTLVWriter writer2;
3364     TLVWriter innerWriter1, innerWriter2;
3365     TLVType container1, container2;
3366
3367     writer1.Init(buf, sizeof(buf));
3368
3369     err = writer1.OpenContainer(AnonymousTag, kTLVType_Array, innerWriter1);
3370     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3371
3372     err = innerWriter1.OpenContainer(AnonymousTag, kTLVType_Structure, innerWriter2);
3373     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3374
3375     err = innerWriter2.PutBoolean(ProfileTag(TestProfile_1, 2), true);
3376     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);
3377
3378     err = innerWriter1.CloseContainer(innerWriter2);
3379     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3380
3381     err = writer1.CloseContainer(innerWriter1);
3382     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3383
3384     writer2.Init(buf, sizeof(buf));
3385
3386     err = writer2.OpenContainer(AnonymousTag, kTLVType_Array, innerWriter1);
3387     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3388
3389     err = innerWriter1.OpenContainer(AnonymousTag, kTLVType_Structure, innerWriter2);
3390     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3391
3392     err = innerWriter2.PutBoolean(ProfileTag(TestProfile_1, 2), true);
3393     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3394
3395     err = innerWriter1.CloseContainer(innerWriter2);
3396     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3397
3398     err = writer2.CloseContainer(innerWriter1);
3399     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);
3400
3401     // test the same scheme works on the Start/End container
3402
3403     writer1.Init(buf, sizeof(buf));
3404
3405     err = writer1.StartContainer(AnonymousTag, kTLVType_Array, container1);
3406     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3407
3408     err = writer1.StartContainer(AnonymousTag, kTLVType_Structure, container2);
3409     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3410
3411     err = writer1.PutBoolean(ProfileTag(TestProfile_1, 2), true);
3412     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);
3413
3414     err = writer1.EndContainer(container2);
3415     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3416
3417     err = writer1.EndContainer(container1);
3418     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3419
3420     writer2.Init(buf, sizeof(buf));
3421
3422     err = writer2.StartContainer(AnonymousTag, kTLVType_Array, container1);
3423     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3424
3425     err = writer2.StartContainer(AnonymousTag, kTLVType_Structure, container2);
3426     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3427
3428     err = writer2.PutBoolean(ProfileTag(TestProfile_1, 2), true);
3429     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3430
3431     err = writer2.EndContainer(container2);
3432     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3433
3434     err = writer2.EndContainer(container1);
3435     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);
3436
3437     // Test that the reservations work for the empty containers
3438
3439     writer1.Init(buf1, sizeof(buf1));
3440     err = writer1.OpenContainer(ProfileTag(TestProfile_1, 2), kTLVType_Structure, innerWriter1);
3441     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);
3442
3443     err = writer1.CloseContainer(innerWriter1);
3444     NL_TEST_ASSERT(inSuite, err != CHIP_NO_ERROR);
3445
3446     writer2.Init(buf1, sizeof(buf1));
3447     err = writer2.OpenContainer(ProfileTag(TestProfile_1, 2), kTLVType_Structure, innerWriter1);
3448     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3449
3450     err = writer2.CloseContainer(innerWriter1);
3451     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);
3452
3453     writer1.Init(buf1, sizeof(buf1));
3454
3455     err = writer1.StartContainer(ProfileTag(TestProfile_1, 2), kTLVType_Structure, container1);
3456     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);
3457
3458     err = writer1.EndContainer(container1);
3459     NL_TEST_ASSERT(inSuite, err != CHIP_NO_ERROR);
3460
3461     writer2.Init(buf1, sizeof(buf1));
3462
3463     err = writer2.StartContainer(ProfileTag(TestProfile_1, 2), kTLVType_Structure, container1);
3464     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
3465
3466     err = writer2.EndContainer(container1);
3467     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);
3468
3469     // Test that the reservations work if the writer has a maxLen of 0.
3470
3471     writer1.Init(buf1, 0);
3472
3473     err = writer1.OpenContainer(ProfileTag(TestProfile_1, 2), kTLVType_Structure, innerWriter1);
3474     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);
3475
3476     err = writer1.StartContainer(AnonymousTag, kTLVType_Array, container1);
3477     NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);
3478
3479     // Test again all cases from 0 to the length of buf1
3480
3481     for (uint32_t maxLen = 0; maxLen <= sizeof(buf); maxLen++)
3482     {
3483         // Open/CloseContainer
3484
3485         writer1.Init(buf, maxLen);
3486
3487         err = writer1.OpenContainer(AnonymousTag, kTLVType_Array, innerWriter1);
3488
3489         if (err == CHIP_NO_ERROR)
3490             err = innerWriter1.OpenContainer(AnonymousTag, kTLVType_Structure, innerWriter2);
3491
3492         if (err == CHIP_NO_ERROR)
3493             err = innerWriter2.PutBoolean(ProfileTag(TestProfile_1, 2), true);
3494
3495         if (err == CHIP_NO_ERROR)
3496             err = innerWriter1.CloseContainer(innerWriter2);
3497
3498         if (err == CHIP_NO_ERROR)
3499             err = writer1.CloseContainer(innerWriter1);
3500
3501         NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);
3502
3503         // Start/EndContainer
3504
3505         writer1.Init(buf, maxLen);
3506
3507         if (err == CHIP_NO_ERROR)
3508             err = writer1.StartContainer(AnonymousTag, kTLVType_Array, container1);
3509
3510         if (err == CHIP_NO_ERROR)
3511             err = writer1.StartContainer(AnonymousTag, kTLVType_Structure, container2);
3512
3513         if (err == CHIP_NO_ERROR)
3514             err = writer1.PutBoolean(ProfileTag(TestProfile_1, 2), true);
3515
3516         if (err == CHIP_NO_ERROR)
3517             err = writer1.EndContainer(container2);
3518
3519         if (err == CHIP_NO_ERROR)
3520             err = writer1.EndContainer(container1);
3521
3522         NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);
3523     }
3524 }
3525
3526 static CHIP_ERROR ReadFuzzedEncoding1(nlTestSuite * inSuite, TLVReader & reader)
3527 {
3528     CHIP_ERROR err = CHIP_NO_ERROR;
3529
3530 #define FUZZ_CHECK_VAL(TYPE, VAL)                                                                                                  \
3531     do                                                                                                                             \
3532     {                                                                                                                              \
3533         TYPE val;                                                                                                                  \
3534         ReturnErrorOnFailure(reader.Get(val));                                                                                     \
3535         VerifyOrReturnError(val == (VAL), CHIP_ERROR_INVALID_ARGUMENT);                                                            \
3536     } while (0)
3537
3538 #define FUZZ_CHECK_STRING(VAL)                                                                                                     \
3539     do                                                                                                                             \
3540     {                                                                                                                              \
3541         char buf[sizeof(VAL)];                                                                                                     \
3542         VerifyOrReturnError(reader.GetLength() == strlen(VAL), CHIP_ERROR_INVALID_ADDRESS);                                        \
3543         ReturnErrorOnFailure(reader.GetString(buf, sizeof(buf)));                                                                  \
3544         VerifyOrReturnError(strcmp(buf, (VAL)) == 0, CHIP_ERROR_INVALID_ADDRESS);                                                  \
3545     } while (0)
3546
3547     ReturnErrorOnFailure(reader.Next(kTLVType_Structure, ProfileTag(TestProfile_1, 1)));
3548
3549     {
3550         TLVType outerContainer1Type;
3551
3552         ReturnErrorOnFailure(reader.EnterContainer(outerContainer1Type));
3553         ReturnErrorOnFailure(reader.Next(kTLVType_Boolean, ProfileTag(TestProfile_1, 2)));
3554
3555         FUZZ_CHECK_VAL(bool, true);
3556
3557         ReturnErrorOnFailure(reader.Next(kTLVType_Boolean, ProfileTag(TestProfile_2, 2)));
3558
3559         FUZZ_CHECK_VAL(bool, false);
3560
3561         ReturnErrorOnFailure(reader.Next(kTLVType_Array, ContextTag(0)));
3562
3563         {
3564             TLVType outerContainer2Type;
3565
3566             ReturnErrorOnFailure(reader.EnterContainer(outerContainer2Type));
3567             ReturnErrorOnFailure(reader.Next(kTLVType_SignedInteger, AnonymousTag));
3568
3569             FUZZ_CHECK_VAL(int8_t, 42);
3570             FUZZ_CHECK_VAL(int16_t, 42);
3571             FUZZ_CHECK_VAL(int32_t, 42);
3572             FUZZ_CHECK_VAL(int64_t, 42);
3573             FUZZ_CHECK_VAL(uint8_t, 42);
3574             FUZZ_CHECK_VAL(uint16_t, 42);
3575             FUZZ_CHECK_VAL(uint32_t, 42);
3576             FUZZ_CHECK_VAL(uint64_t, 42);
3577
3578             ReturnErrorOnFailure(reader.Next(kTLVType_SignedInteger, AnonymousTag));
3579
3580             FUZZ_CHECK_VAL(int8_t, -17);
3581             FUZZ_CHECK_VAL(int16_t, -17);
3582             FUZZ_CHECK_VAL(int32_t, -17);
3583             FUZZ_CHECK_VAL(int64_t, -17);
3584
3585             ReturnErrorOnFailure(reader.Next(kTLVType_SignedInteger, AnonymousTag));
3586
3587             FUZZ_CHECK_VAL(int32_t, -170000);
3588             FUZZ_CHECK_VAL(int64_t, -170000);
3589
3590             ReturnErrorOnFailure(reader.Next(kTLVType_UnsignedInteger, AnonymousTag));
3591
3592             FUZZ_CHECK_VAL(int64_t, 40000000000ULL);
3593             FUZZ_CHECK_VAL(uint64_t, 40000000000ULL);
3594
3595             ReturnErrorOnFailure(reader.Next(kTLVType_Structure, AnonymousTag));
3596
3597             {
3598                 TLVType outerContainer3Type;
3599
3600                 ReturnErrorOnFailure(reader.EnterContainer(outerContainer3Type));
3601                 ReturnErrorOnFailure(reader.ExitContainer(outerContainer3Type));
3602             }
3603
3604             ReturnErrorOnFailure(reader.Next(kTLVType_List, AnonymousTag));
3605
3606             {
3607                 TLVType outerContainer3Type;
3608
3609                 ReturnErrorOnFailure(reader.EnterContainer(outerContainer3Type));
3610                 ReturnErrorOnFailure(reader.Next(kTLVType_Null, ProfileTag(TestProfile_1, 17)));
3611                 ReturnErrorOnFailure(reader.Next(kTLVType_Null, ProfileTag(TestProfile_2, 900000)));
3612                 ReturnErrorOnFailure(reader.Next(kTLVType_Null, AnonymousTag));
3613                 ReturnErrorOnFailure(reader.Next(kTLVType_Structure, ProfileTag(TestProfile_2, 4000000000ULL)));
3614
3615                 {
3616                     TLVType outerContainer4Type;
3617
3618                     ReturnErrorOnFailure(reader.EnterContainer(outerContainer4Type));
3619                     ReturnErrorOnFailure(reader.Next(kTLVType_UTF8String, CommonTag(70000)));
3620
3621                     FUZZ_CHECK_STRING(sLargeString);
3622
3623                     ReturnErrorOnFailure(reader.ExitContainer(outerContainer4Type));
3624                 }
3625
3626                 ReturnErrorOnFailure(reader.ExitContainer(outerContainer3Type));
3627             }
3628
3629             ReturnErrorOnFailure(reader.ExitContainer(outerContainer2Type));
3630         }
3631
3632         ReturnErrorOnFailure(reader.Next(kTLVType_UTF8String, ProfileTag(TestProfile_1, 5)));
3633
3634         FUZZ_CHECK_STRING("This is a test");
3635
3636         ReturnErrorOnFailure(reader.Next(kTLVType_FloatingPointNumber, ProfileTag(TestProfile_2, 65535)));
3637
3638         FUZZ_CHECK_VAL(double, (float) 17.9);
3639
3640         ReturnErrorOnFailure(reader.Next(kTLVType_FloatingPointNumber, ProfileTag(TestProfile_2, 65536)));
3641
3642         FUZZ_CHECK_VAL(double, (double) 17.9);
3643
3644         ReturnErrorOnFailure(reader.ExitContainer(outerContainer1Type));
3645     }
3646
3647     err = reader.Next();
3648     if (err == CHIP_END_OF_TLV)
3649         err = CHIP_NO_ERROR;
3650
3651     return CHIP_NO_ERROR;
3652 }
3653
3654 static time_t sFuzzTestDurationSecs = 5;
3655 static uint8_t sFixedFuzzMask       = 0;
3656
3657 static void TLVReaderFuzzTest(nlTestSuite * inSuite, void * inContext)
3658 {
3659     time_t now, endTime;
3660     uint8_t fuzzedData[sizeof(Encoding1)];
3661
3662     // clang-format off
3663     static uint8_t sFixedFuzzVals[] =
3664     {
3665         0x00,
3666         0x01,
3667         0xFF,
3668         0x20, // 1-byte signed integer with context tag
3669         0x21, // 2-byte signed integer with context tag
3670         0x22, // 4-byte signed integer with context tag
3671         0x23, // 8-byte signed integer with context tag
3672         0x24, // 1-byte unsigned integer with context tag
3673         0x25, // 1-byte unsigned integer with context tag
3674         0x26, // 1-byte unsigned integer with context tag
3675         0x27, // 1-byte unsigned integer with context tag
3676         0x28, // Boolean false with context tag
3677         0x29, // Boolean true with context tag
3678         0x27, // UTF-8 string with 1-byte length and context tag
3679         0x30, // Byte string with 1-byte length and context tag
3680         0x35, // Structure with context tag
3681         0x36, // Array with context tag
3682         0x18, // End of container
3683     };
3684     // clang-format on
3685
3686     memcpy(fuzzedData, Encoding1, sizeof(fuzzedData));
3687
3688     time(&now);
3689     endTime = now + sFuzzTestDurationSecs + 1;
3690
3691     srand(static_cast<unsigned int>(now));
3692
3693     size_t m = 0;
3694     while (true)
3695     {
3696         for (size_t i = 0; i < sizeof(fuzzedData); i++)
3697         {
3698             uint8_t origVal = fuzzedData[i];
3699
3700             if (m < sizeof(sFixedFuzzVals))
3701             {
3702                 if (origVal == sFixedFuzzVals[m])
3703                     continue;
3704
3705                 fuzzedData[i] = sFixedFuzzVals[m];
3706             }
3707
3708             else
3709             {
3710                 uint8_t fuzzMask = sFixedFuzzMask;
3711                 while (fuzzMask == 0)
3712                     fuzzMask = GetRandU8();
3713
3714                 fuzzedData[i] ^= fuzzMask;
3715             }
3716
3717             TLVReader reader;
3718             reader.Init(fuzzedData, sizeof(fuzzedData));
3719             reader.ImplicitProfileId = TestProfile_2;
3720
3721             CHIP_ERROR readRes = ReadFuzzedEncoding1(inSuite, reader);
3722             NL_TEST_ASSERT(inSuite, readRes != CHIP_NO_ERROR);
3723
3724             if (readRes == CHIP_NO_ERROR)
3725             {
3726                 printf("Unexpected success of fuzz test: offset %u, original value 0x%02X, mutated value 0x%02X\n",
3727                        static_cast<unsigned>(i), static_cast<unsigned>(origVal), static_cast<unsigned>(fuzzedData[i]));
3728                 ExitNow();
3729             }
3730
3731             time(&now);
3732             if (now >= endTime)
3733                 ExitNow();
3734
3735             fuzzedData[i] = origVal;
3736         }
3737
3738         if (m < sizeof(sFixedFuzzVals))
3739             m++;
3740     }
3741
3742 exit:
3743     return;
3744 }
3745
3746 // Test Suite
3747
3748 /**
3749  *  Test Suite that lists all the test functions.
3750  */
3751 // clang-format off
3752 static const nlTest sTests[] =
3753 {
3754     NL_TEST_DEF("Simple Write Read Test",              CheckSimpleWriteRead),
3755     NL_TEST_DEF("Inet Buffer Test",                    CheckPacketBuffer),
3756     NL_TEST_DEF("Buffer Overflow Test",                CheckBufferOverflow),
3757     NL_TEST_DEF("Pretty Print Test",                   CheckPrettyPrinter),
3758     NL_TEST_DEF("Data Macro Test",                     CheckDataMacro),
3759     NL_TEST_DEF("Strict Aliasing Test",                CheckStrictAliasing),
3760     NL_TEST_DEF("CHIP TLV Basics",                     CheckCHIPTLVBasics),
3761     NL_TEST_DEF("CHIP TLV Writer",                     CheckCHIPTLVWriter),
3762     NL_TEST_DEF("CHIP TLV Reader",                     CheckCHIPTLVReader),
3763     NL_TEST_DEF("CHIP TLV Utilities",                  CheckCHIPTLVUtilities),
3764     NL_TEST_DEF("CHIP TLV Updater",                    CheckCHIPUpdater),
3765     NL_TEST_DEF("CHIP TLV Empty Find",                 CheckCHIPTLVEmptyFind),
3766     NL_TEST_DEF("CHIP Circular TLV buffer, simple",    CheckCircularTLVBufferSimple),
3767     NL_TEST_DEF("CHIP Circular TLV buffer, mid-buffer start", CheckCircularTLVBufferStartMidway),
3768     NL_TEST_DEF("CHIP Circular TLV buffer, straddle",  CheckCircularTLVBufferEvictStraddlingEvent),
3769     NL_TEST_DEF("CHIP Circular TLV buffer, edge",      CheckCircularTLVBufferEdge),
3770     NL_TEST_DEF("CHIP TLV Printf",                     CheckCHIPTLVPutStringF),
3771     NL_TEST_DEF("CHIP TLV Printf, Circular TLV buf",   CheckCHIPTLVPutStringFCircular),
3772     NL_TEST_DEF("CHIP TLV Skip non-contiguous",        CheckCHIPTLVSkipCircular),
3773     NL_TEST_DEF("CHIP TLV Check reserve",              CheckCloseContainerReserve),
3774     NL_TEST_DEF("CHIP TLV Reader Fuzz Test",           TLVReaderFuzzTest),
3775
3776     NL_TEST_SENTINEL()
3777 };
3778 // clang-format on
3779
3780 /**
3781  *  Set up the test suite.
3782  */
3783 int TestCHIPTLV_Setup(void * inContext)
3784 {
3785     CHIP_ERROR error = chip::Platform::MemoryInit();
3786     if (error != CHIP_NO_ERROR)
3787         return FAILURE;
3788     return SUCCESS;
3789 }
3790
3791 /**
3792  *  Tear down the test suite.
3793  */
3794 int TestCHIPTLV_Teardown(void * inContext)
3795 {
3796     chip::Platform::MemoryShutdown();
3797     return SUCCESS;
3798 }
3799
3800 int TestCHIPTLV(void)
3801 {
3802     // clang-format off
3803     nlTestSuite theSuite =
3804     {
3805         "chip-tlv",
3806         &sTests[0],
3807         TestCHIPTLV_Setup,
3808         TestCHIPTLV_Teardown
3809     };
3810     // clang-format on
3811     TestTLVContext context;
3812
3813     context.mSuite = &theSuite;
3814
3815     // Run test suit against one context
3816     nlTestRunner(&theSuite, &context);
3817
3818     return (nlTestRunnerStats(&theSuite));
3819 }
3820
3821 CHIP_REGISTER_TEST_SUITE(TestCHIPTLV)