Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / system / tests / TestSystemPacketBuffer.cpp
1 /*
2  *
3  *    Copyright (c) 2020-2021 Project CHIP Authors
4  *    Copyright (c) 2016-2017 Nest Labs, Inc.
5  *
6  *    Licensed under the Apache License, Version 2.0 (the "License");
7  *    you may not use this file except in compliance with the License.
8  *    You may obtain a copy of the License at
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *    Unless required by applicable law or agreed to in writing, software
13  *    distributed under the License is distributed on an "AS IS" BASIS,
14  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *    See the License for the specific language governing permissions and
16  *    limitations under the License.
17  */
18
19 /**
20  *    @file
21  *      This file implements a unit test suite for
22  *      <tt>chip::System::PacketBuffer</tt>, a class that provides
23  *      structure for network packet buffer management.
24  */
25
26 #ifndef __STDC_LIMIT_MACROS
27 #define __STDC_LIMIT_MACROS
28 #endif
29
30 #include <errno.h>
31 #include <stdint.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <utility>
35 #include <vector>
36
37 #include <support/CHIPMem.h>
38 #include <support/CodeUtils.h>
39 #include <support/UnitTestRegistration.h>
40 #include <system/SystemPacketBuffer.h>
41
42 #if CHIP_SYSTEM_CONFIG_USE_LWIP
43 #include <lwip/init.h>
44 #include <lwip/tcpip.h>
45 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
46
47 #include <nlunit-test.h>
48
49 #if CHIP_SYSTEM_CONFIG_USE_LWIP
50 #if (LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 1)
51 #define PBUF_TYPE(pbuf) (pbuf)->type_internal
52 #else
53 #define PBUF_TYPE(pbuf) (pbuf)->type
54 #endif // (LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 1)
55 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
56
57 using ::chip::Encoding::PacketBufferWriter;
58 using ::chip::System::PacketBuffer;
59 using ::chip::System::PacketBufferHandle;
60
61 #if !CHIP_SYSTEM_CONFIG_USE_LWIP
62 using ::chip::System::pbuf;
63 #endif
64
65 // Utility functions.
66
67 #define TO_LWIP_PBUF(x) (reinterpret_cast<struct pbuf *>(reinterpret_cast<void *>(x)))
68 #define OF_LWIP_PBUF(x) (reinterpret_cast<PacketBuffer *>(reinterpret_cast<void *>(x)))
69
70 namespace {
71 void ScrambleData(uint8_t * start, uint16_t length)
72 {
73     for (uint16_t i = 0; i < length; ++i)
74         ++start[i];
75 }
76 } // namespace
77
78 /*
79  * An instance of this class created for the test suite.
80  * It is a friend class of `PacketBuffer` and `PacketBufferHandle` because some tests
81  * use or check private methods or properties.
82  */
83 class PacketBufferTest
84 {
85 public:
86     struct TestContext
87     {
88         const uint16_t * const reserved_sizes;
89         size_t reserved_size_count;
90         const uint16_t * const lengths;
91         size_t length_count;
92         PacketBufferTest * test;
93     };
94
95     static int TestSetup(void * inContext);
96     static int TestTeardown(void * inContext);
97     static int TestInitialize(void * inContext);
98     static int TestTerminate(void * inContext);
99
100     static void CheckNew(nlTestSuite * inSuite, void * inContext);
101     static void CheckStart(nlTestSuite * inSuite, void * inContext);
102     static void CheckSetStart(nlTestSuite * inSuite, void * inContext);
103     static void CheckDataLength(nlTestSuite * inSuite, void * inContext);
104     static void CheckSetDataLength(nlTestSuite * inSuite, void * inContext);
105     static void CheckTotalLength(nlTestSuite * inSuite, void * inContext);
106     static void CheckMaxDataLength(nlTestSuite * inSuite, void * inContext);
107     static void CheckAvailableDataLength(nlTestSuite * inSuite, void * inContext);
108     static void CheckReservedSize(nlTestSuite * inSuite, void * inContext);
109     static void CheckHasChainedBuffer(nlTestSuite * inSuite, void * inContext);
110     static void CheckAddToEnd(nlTestSuite * inSuite, void * inContext);
111     static void CheckPopHead(nlTestSuite * inSuite, void * inContext);
112     static void CheckCompactHead(nlTestSuite * inSuite, void * inContext);
113     static void CheckConsumeHead(nlTestSuite * inSuite, void * inContext);
114     static void CheckConsume(nlTestSuite * inSuite, void * inContext);
115     static void CheckEnsureReservedSize(nlTestSuite * inSuite, void * inContext);
116     static void CheckAlignPayload(nlTestSuite * inSuite, void * inContext);
117     static void CheckNext(nlTestSuite * inSuite, void * inContext);
118     static void CheckLast(nlTestSuite * inSuite, void * inContext);
119     static void CheckRead(nlTestSuite * inSuite, void * inContext);
120     static void CheckAddRef(nlTestSuite * inSuite, void * inContext);
121     static void CheckFree(nlTestSuite * inSuite, void * inContext);
122     static void CheckFreeHead(nlTestSuite * inSuite, void * inContext);
123     static void CheckHandleConstruct(nlTestSuite * inSuite, void * inContext);
124     static void CheckHandleMove(nlTestSuite * inSuite, void * inContext);
125     static void CheckHandleRelease(nlTestSuite * inSuite, void * inContext);
126     static void CheckHandleFree(nlTestSuite * inSuite, void * inContext);
127     static void CheckHandleRetain(nlTestSuite * inSuite, void * inContext);
128     static void CheckHandleAdopt(nlTestSuite * inSuite, void * inContext);
129     static void CheckHandleHold(nlTestSuite * inSuite, void * inContext);
130     static void CheckHandleAdvance(nlTestSuite * inSuite, void * inContext);
131     static void CheckHandleRightSize(nlTestSuite * inSuite, void * inContext);
132     static void CheckHandleCloneData(nlTestSuite * inSuite, void * inContext);
133     static void CheckPacketBufferWriter(nlTestSuite * inSuite, void * inContext);
134     static void CheckBuildFreeList(nlTestSuite * inSuite, void * inContext);
135
136     static void PrintHandle(const char * tag, const PacketBuffer * buffer)
137     {
138         printf("%s %p ref=%u len=%-4u next=%p\n", tag, buffer, buffer ? buffer->ref : 0, buffer ? buffer->len : 0,
139                buffer ? buffer->next : 0);
140     }
141     static void PrintHandle(const char * tag, const PacketBufferHandle & handle) { PrintHandle(tag, handle.mBuffer); }
142
143     static constexpr uint16_t kBlockSize = PacketBuffer::kBlockSize;
144
145 private:
146     struct BufferConfiguration
147     {
148         BufferConfiguration(uint16_t aReservedSize = 0) :
149             init_len(0), reserved_size(aReservedSize), start_buffer(nullptr), end_buffer(nullptr), payload_ptr(nullptr),
150             handle(nullptr)
151         {}
152
153         uint16_t init_len;
154         uint16_t reserved_size;
155         uint8_t * start_buffer;
156         uint8_t * end_buffer;
157         uint8_t * payload_ptr;
158         PacketBufferHandle handle;
159     };
160
161     static void PrintHandle(const char * tag, const BufferConfiguration & config) { PrintHandle(tag, config.handle); }
162     static void PrintConfig(const char * tag, const BufferConfiguration & config)
163     {
164         printf("%s pay=%-4zu len=%-4u res=%-4u:", tag, config.payload_ptr - config.start_buffer, config.init_len,
165                config.reserved_size);
166         PrintHandle("", config.handle);
167     }
168
169     PacketBufferTest(TestContext * context);
170     ~PacketBufferTest();
171
172     int InitializeTest(TestContext * context);
173     int TerminateTest(TestContext * context);
174
175     /*
176      * Buffers allocated through PrepareTestBuffer with kRecordHandle set will be recorded in `handles` so that their
177      * reference counts can be verified by ResetHandles(). Initially they have two refs: the recorded one and the returned one.
178      */
179     static constexpr int kRecordHandle     = 0x01;
180     static constexpr int kAllowHandleReuse = 0x02;
181     void PrepareTestBuffer(BufferConfiguration * config, int flags = 0);
182
183     /*
184      * Checks and clears the recorded handles. Returns true if it detects no leaks or double frees.
185      * Called from `TerminateTest()`, but tests may choose to call it more often to verify reference counts.
186      */
187     bool ResetHandles();
188
189     TestContext * mContext;
190     std::vector<BufferConfiguration> configurations;
191     std::vector<PacketBufferHandle> handles;
192 };
193
194 const uint16_t sTestReservedSizes[] = { 0, 10, 128, 1536, PacketBufferTest::kBlockSize };
195 const uint16_t sTestLengths[]       = { 0, 1, 10, 128, PacketBufferTest::kBlockSize, UINT16_MAX };
196
197 PacketBufferTest::TestContext sContext = {
198     sTestReservedSizes,
199     sizeof(sTestReservedSizes) / sizeof(uint16_t),
200     sTestLengths,
201     sizeof(sTestLengths) / sizeof(uint16_t),
202 };
203
204 PacketBufferTest::PacketBufferTest(TestContext * context) : mContext(context)
205 {
206     // Set up the buffer configuration vector for this suite.
207     configurations.resize(0);
208     for (size_t i = 0; i < mContext->reserved_size_count; ++i)
209     {
210         configurations.emplace_back<BufferConfiguration>(mContext->reserved_sizes[i]);
211     }
212 }
213
214 int PacketBufferTest::TestSetup(void * inContext)
215 {
216     chip::Platform::MemoryInit();
217     TestContext * const theContext = reinterpret_cast<TestContext *>(inContext);
218     theContext->test               = new PacketBufferTest(theContext);
219     if (theContext->test == nullptr)
220     {
221         return FAILURE;
222     }
223     return SUCCESS;
224 }
225
226 int PacketBufferTest::TestTeardown(void * inContext)
227 {
228     return SUCCESS;
229 }
230
231 int PacketBufferTest::TestInitialize(void * inContext)
232 {
233     TestContext * const theContext = reinterpret_cast<TestContext *>(inContext);
234     if (theContext->test == nullptr)
235     {
236         return FAILURE;
237     }
238     return theContext->test->InitializeTest(theContext);
239 }
240
241 int PacketBufferTest::InitializeTest(TestContext * context)
242 {
243     if (context != mContext)
244     {
245         return FAILURE;
246     }
247     return SUCCESS;
248 }
249
250 int PacketBufferTest::TestTerminate(void * inContext)
251 {
252     TestContext * const theContext = reinterpret_cast<TestContext *>(inContext);
253     if (theContext->test == nullptr)
254     {
255         return FAILURE;
256     }
257     return theContext->test->TerminateTest(theContext);
258 }
259
260 int PacketBufferTest::TerminateTest(TestContext * context)
261 {
262     const bool context_ok = (context == mContext);
263     // Clear the configurations' bufffer handles.
264     for (size_t i = 0; i < configurations.size(); ++i)
265     {
266         configurations[i].handle = nullptr;
267     }
268     const bool handles_ok = ResetHandles();
269     return (context_ok && handles_ok) ? SUCCESS : FAILURE;
270 }
271
272 /**
273  *  Allocate memory for a test buffer and configure according to test buffer configuration.
274  */
275 void PacketBufferTest::PrepareTestBuffer(BufferConfiguration * config, int flags)
276 {
277     if (config->handle.IsNull())
278     {
279         config->handle = PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0);
280         if (config->handle.IsNull())
281         {
282             printf("NewPacketBuffer: Failed to allocate packet buffer (%zu retained): %s\n", handles.size(), strerror(errno));
283             exit(EXIT_FAILURE);
284         }
285         if (flags & kRecordHandle)
286         {
287             handles.push_back(config->handle.Retain());
288         }
289     }
290     else if ((flags & kAllowHandleReuse) == 0)
291     {
292         printf("Dirty test configuration\n");
293         exit(EXIT_FAILURE);
294     }
295
296     const size_t lInitialSize = PacketBuffer::kStructureSize + config->reserved_size;
297     const size_t lAllocSize   = kBlockSize;
298
299     uint8_t * const raw = reinterpret_cast<uint8_t *>(config->handle.Get());
300     memset(raw + PacketBuffer::kStructureSize, 0, lAllocSize - PacketBuffer::kStructureSize);
301
302     config->start_buffer = raw;
303     config->end_buffer   = raw + lAllocSize;
304
305     if (lInitialSize > lAllocSize)
306     {
307         config->payload_ptr = config->end_buffer;
308     }
309     else
310     {
311         config->payload_ptr = config->start_buffer + lInitialSize;
312     }
313
314     if (config->handle->HasChainedBuffer())
315     {
316         // This should not happen.
317         PacketBuffer::Free(config->handle->ChainedBuffer());
318         config->handle->next = nullptr;
319     }
320     config->handle->payload = config->payload_ptr;
321     config->handle->len     = config->init_len;
322     config->handle->tot_len = config->init_len;
323 }
324
325 bool PacketBufferTest::ResetHandles()
326 {
327     // Check against leaks or double-frees in tests: every handle obtained through
328     // PacketBufferTest::NewPacketBuffer should have a reference count of 1.
329     bool handles_ok = true;
330     for (size_t i = 0; i < handles.size(); ++i)
331     {
332         const PacketBufferHandle & handle = handles[i];
333         if (handle.Get() == nullptr)
334         {
335             printf("TestTerminate: handle %zu null\n", i);
336             handles_ok = false;
337         }
338         else if (handle->ref != 1)
339         {
340             printf("TestTerminate: handle %zu buffer=%p ref=%u\n", i, handle.Get(), handle->ref);
341             handles_ok = false;
342             while (handle->ref > 1)
343             {
344                 PacketBuffer::Free(handle.Get());
345             }
346         }
347     }
348     handles.resize(0);
349     return handles_ok;
350 }
351
352 // Test functions invoked from the suite.
353
354 /**
355  *  Test PacketBufferHandle::New() function.
356  *
357  *  Description: For every buffer-configuration from inContext, create a buffer's instance
358  *               using the New() method. Then, verify that when the size of the reserved space
359  *               passed to New() is greater than PacketBuffer::kMaxSizeWithoutReserve,
360  *               the method returns nullptr. Otherwise, check for correctness of initializing
361  *               the new buffer's internal state.
362  */
363 void PacketBufferTest::CheckNew(nlTestSuite * inSuite, void * inContext)
364 {
365     TestContext * const theContext = static_cast<TestContext *>(inContext);
366     PacketBufferTest * const test  = theContext->test;
367     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
368
369     for (const auto & config : test->configurations)
370     {
371         const PacketBufferHandle buffer = PacketBufferHandle::New(0, config.reserved_size);
372
373         if (config.reserved_size > PacketBuffer::kMaxSizeWithoutReserve)
374         {
375             NL_TEST_ASSERT(inSuite, buffer.IsNull());
376             continue;
377         }
378
379         NL_TEST_ASSERT(inSuite, config.reserved_size <= buffer->AllocSize());
380         NL_TEST_ASSERT(inSuite, !buffer.IsNull());
381
382         if (!buffer.IsNull())
383         {
384             const pbuf * const pb = TO_LWIP_PBUF(buffer.Get());
385
386             NL_TEST_ASSERT(inSuite, pb->len == 0);
387             NL_TEST_ASSERT(inSuite, pb->tot_len == 0);
388             NL_TEST_ASSERT(inSuite, pb->next == nullptr);
389             NL_TEST_ASSERT(inSuite, pb->ref == 1);
390         }
391     }
392
393 #if CHIP_SYSTEM_CONFIG_USE_LWIP || CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE != 0
394     // Use the rest of the buffer space
395     std::vector<PacketBufferHandle> allocate_all_the_things;
396     for (;;)
397     {
398         PacketBufferHandle buffer = PacketBufferHandle::New(0, 0);
399         if (buffer.IsNull())
400         {
401             break;
402         }
403         // Hold on to the buffer, to use up all the buffer space.
404         allocate_all_the_things.push_back(std::move(buffer));
405     }
406 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP || CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE != 0
407 }
408
409 /**
410  *  Test PacketBuffer::Start() function.
411  */
412 void PacketBufferTest::CheckStart(nlTestSuite * inSuite, void * inContext)
413 {
414     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
415     PacketBufferTest * const test         = theContext->test;
416     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
417
418     for (auto & config : test->configurations)
419     {
420         test->PrepareTestBuffer(&config, kRecordHandle);
421         NL_TEST_ASSERT(inSuite, config.handle->Start() == config.payload_ptr);
422     }
423 }
424
425 /**
426  *  Test PacketBuffer::SetStart() function.
427  *
428  *  Description: For every buffer-configuration from inContext, create a
429  *               buffer's instance according to the configuration. Next,
430  *               for any offset value from start_offset[], pass it to the
431  *               buffer's instance through SetStart method. Then, verify that
432  *               the beginning of the buffer has been correctly internally
433  *               adjusted according to the offset value passed into the
434  *               SetStart() method.
435  */
436 void PacketBufferTest::CheckSetStart(nlTestSuite * inSuite, void * inContext)
437 {
438     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
439     PacketBufferTest * const test         = theContext->test;
440     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
441
442     static constexpr ptrdiff_t sSizePacketBuffer = kBlockSize;
443
444     for (auto & config : test->configurations)
445     {
446         // clang-format off
447         static constexpr ptrdiff_t start_offset[] =
448         {
449             -sSizePacketBuffer,
450             -128,
451             -1,
452             0,
453             1,
454             128,
455             sSizePacketBuffer
456         };
457         // clang-format on
458
459         for (ptrdiff_t offset : start_offset)
460         {
461             test->PrepareTestBuffer(&config, kRecordHandle | kAllowHandleReuse);
462             uint8_t * const test_start = config.payload_ptr + offset;
463             uint8_t * verify_start     = test_start;
464
465             config.handle->SetStart(test_start);
466
467             if (verify_start < config.start_buffer + PacketBuffer::kStructureSize)
468             {
469                 // Set start before valid payload beginning.
470                 verify_start = config.start_buffer + PacketBuffer::kStructureSize;
471             }
472
473             if (verify_start > config.end_buffer)
474             {
475                 // Set start after valid payload beginning.
476                 verify_start = config.end_buffer;
477             }
478
479             NL_TEST_ASSERT(inSuite, config.handle->payload == verify_start);
480
481             if ((verify_start - config.payload_ptr) > config.init_len)
482             {
483                 // Set start to the beginning of payload, right after handle's header.
484                 NL_TEST_ASSERT(inSuite, config.handle->len == 0);
485             }
486             else
487             {
488                 // Set start to somewhere between the end of the handle's
489                 // header and the end of payload.
490                 NL_TEST_ASSERT(inSuite, config.handle->len == (config.init_len - (verify_start - config.payload_ptr)));
491             }
492         }
493     }
494 }
495
496 /**
497  *  Test PacketBuffer::DataLength() function.
498  */
499 void PacketBufferTest::CheckDataLength(nlTestSuite * inSuite, void * inContext)
500 {
501     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
502     PacketBufferTest * const test         = theContext->test;
503     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
504
505     for (auto & config : test->configurations)
506     {
507         test->PrepareTestBuffer(&config, kRecordHandle);
508
509         NL_TEST_ASSERT(inSuite, config.handle->DataLength() == config.handle->len);
510     }
511 }
512
513 /**
514  *  Test PacketBuffer::SetDataLength() function.
515  *
516  *  Description: Take two initial configurations of PacketBuffer from
517  *               inContext and create two PacketBuffer instances based on those
518  *               configurations. For any two buffers, call SetDataLength with
519  *               different value from sLength[]. If two buffers are created with
520  *               the same configuration, test SetDataLength on one buffer,
521  *               without specifying the head of the buffer chain. Otherwise,
522  *               test SetDataLength with one buffer being down the chain and the
523  *               other one being passed as the head of the chain. After calling
524  *               the method verify that data lenghts were correctly adjusted.
525  */
526 void PacketBufferTest::CheckSetDataLength(nlTestSuite * inSuite, void * inContext)
527 {
528     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
529     PacketBufferTest * const test         = theContext->test;
530     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
531
532     for (auto & config_1 : test->configurations)
533     {
534         for (auto & config_2 : test->configurations)
535         {
536             for (size_t i = 0; i < theContext->length_count; ++i)
537             {
538                 const uint16_t length = theContext->lengths[i];
539                 test->PrepareTestBuffer(&config_1, kRecordHandle | kAllowHandleReuse);
540                 test->PrepareTestBuffer(&config_2, kRecordHandle | kAllowHandleReuse);
541
542                 if (&config_1 == &config_2)
543                 {
544                     // headOfChain (the second arg) is NULL
545                     config_2.handle->SetDataLength(length, nullptr);
546
547                     if (length > (config_2.end_buffer - config_2.payload_ptr))
548                     {
549                         NL_TEST_ASSERT(inSuite, config_2.handle->len == (config_2.end_buffer - config_2.payload_ptr));
550                         NL_TEST_ASSERT(inSuite, config_2.handle->tot_len == (config_2.end_buffer - config_2.payload_ptr));
551                         NL_TEST_ASSERT(inSuite, config_2.handle->next == nullptr);
552                     }
553                     else
554                     {
555                         NL_TEST_ASSERT(inSuite, config_2.handle->len == length);
556                         NL_TEST_ASSERT(inSuite, config_2.handle->tot_len == length);
557                         NL_TEST_ASSERT(inSuite, config_2.handle->next == nullptr);
558                     }
559                 }
560                 else
561                 {
562                     // headOfChain (the second arg) is config_1.handle
563                     config_2.handle->SetDataLength(length, config_1.handle);
564
565                     if (length > (config_2.end_buffer - config_2.payload_ptr))
566                     {
567                         NL_TEST_ASSERT(inSuite, config_2.handle->len == (config_2.end_buffer - config_2.payload_ptr));
568                         NL_TEST_ASSERT(inSuite, config_2.handle->tot_len == (config_2.end_buffer - config_2.payload_ptr));
569                         NL_TEST_ASSERT(inSuite, config_2.handle->next == nullptr);
570
571                         NL_TEST_ASSERT(inSuite,
572                                        config_1.handle->tot_len ==
573                                            (config_1.init_len + static_cast<int32_t>(config_2.end_buffer - config_2.payload_ptr) -
574                                             static_cast<int32_t>(config_2.init_len)));
575                     }
576                     else
577                     {
578                         NL_TEST_ASSERT(inSuite, config_2.handle->len == length);
579                         NL_TEST_ASSERT(inSuite, config_2.handle->tot_len == length);
580                         NL_TEST_ASSERT(inSuite, config_2.handle->next == nullptr);
581
582                         NL_TEST_ASSERT(
583                             inSuite,
584                             config_1.handle->tot_len ==
585                                 (config_1.init_len + static_cast<int32_t>(length) - static_cast<int32_t>(config_2.init_len)));
586                     }
587                 }
588             }
589         }
590     }
591 }
592
593 /**
594  *  Test PacketBuffer::TotalLength() function.
595  */
596 void PacketBufferTest::CheckTotalLength(nlTestSuite * inSuite, void * inContext)
597 {
598     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
599     PacketBufferTest * const test         = theContext->test;
600     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
601
602     for (auto & config : test->configurations)
603     {
604         test->PrepareTestBuffer(&config, kRecordHandle);
605         NL_TEST_ASSERT(inSuite, config.handle->TotalLength() == config.init_len);
606     }
607 }
608
609 /**
610  *  Test PacketBuffer::MaxDataLength() function.
611  */
612 void PacketBufferTest::CheckMaxDataLength(nlTestSuite * inSuite, void * inContext)
613 {
614     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
615     PacketBufferTest * const test         = theContext->test;
616     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
617
618     for (auto & config : test->configurations)
619     {
620         test->PrepareTestBuffer(&config, kRecordHandle);
621
622         NL_TEST_ASSERT(inSuite, config.handle->MaxDataLength() == (config.end_buffer - config.payload_ptr));
623     }
624 }
625
626 /**
627  *  Test PacketBuffer::AvailableDataLength() function.
628  */
629 void PacketBufferTest::CheckAvailableDataLength(nlTestSuite * inSuite, void * inContext)
630 {
631     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
632     PacketBufferTest * const test         = theContext->test;
633     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
634
635     for (auto & config : test->configurations)
636     {
637         test->PrepareTestBuffer(&config, kRecordHandle);
638
639         NL_TEST_ASSERT(inSuite,
640                        config.handle->AvailableDataLength() == ((config.end_buffer - config.payload_ptr) - config.init_len));
641     }
642 }
643
644 /**
645  *  Test PacketBuffer::ReservedSize() function.
646  */
647 void PacketBufferTest::CheckReservedSize(nlTestSuite * inSuite, void * inContext)
648 {
649     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
650     PacketBufferTest * const test         = theContext->test;
651     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
652
653     for (auto & config : test->configurations)
654     {
655         test->PrepareTestBuffer(&config, kRecordHandle);
656         const size_t kAllocSize = config.handle->AllocSize();
657
658         if (config.reserved_size > kAllocSize)
659         {
660             NL_TEST_ASSERT(inSuite, config.handle->ReservedSize() == kAllocSize);
661         }
662         else
663         {
664             NL_TEST_ASSERT(inSuite, config.handle->ReservedSize() == config.reserved_size);
665         }
666     }
667 }
668
669 /**
670  *  Test PacketBuffer::HasChainedBuffer() function.
671  */
672 void PacketBufferTest::CheckHasChainedBuffer(nlTestSuite * inSuite, void * inContext)
673 {
674     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
675     PacketBufferTest * const test         = theContext->test;
676     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
677
678     for (auto & config_1 : test->configurations)
679     {
680         for (auto & config_2 : test->configurations)
681         {
682             if (&config_1 == &config_2)
683             {
684                 continue;
685             }
686
687             test->PrepareTestBuffer(&config_1);
688             test->PrepareTestBuffer(&config_2);
689
690             NL_TEST_ASSERT(inSuite, config_1.handle->HasChainedBuffer() == false);
691             NL_TEST_ASSERT(inSuite, config_2.handle->HasChainedBuffer() == false);
692
693             config_1.handle->AddToEnd(config_2.handle.Retain());
694             NL_TEST_ASSERT(inSuite, config_1.handle->HasChainedBuffer() == true);
695             NL_TEST_ASSERT(inSuite, config_2.handle->HasChainedBuffer() == false);
696
697             config_1.handle = nullptr;
698             config_2.handle = nullptr;
699         }
700     }
701 }
702
703 /**
704  *  Test PacketBuffer::AddToEnd() function.
705  *
706  *  Description: Take three initial configurations of PacketBuffer from
707  *               inContext, create three PacketBuffers based on those
708  *               configurations and then link those buffers together with
709  *               PacketBuffer:AddToEnd(). Then, assert that after connecting
710  *               buffers together, their internal states are correctly updated.
711  *               This test function tests linking any combination of three
712  *               buffer-configurations passed within inContext.
713  */
714 void PacketBufferTest::CheckAddToEnd(nlTestSuite * inSuite, void * inContext)
715 {
716     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
717     PacketBufferTest * const test         = theContext->test;
718     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
719
720     for (auto & config_1 : test->configurations)
721     {
722         for (auto & config_2 : test->configurations)
723         {
724             for (auto & config_3 : test->configurations)
725             {
726                 if (&config_1 == &config_2 || &config_1 == &config_3 || &config_2 == &config_3)
727                 {
728                     continue;
729                 }
730
731                 test->PrepareTestBuffer(&config_1);
732                 test->PrepareTestBuffer(&config_2);
733                 test->PrepareTestBuffer(&config_3);
734                 NL_TEST_ASSERT(inSuite, config_1.handle->ref == 1);
735                 NL_TEST_ASSERT(inSuite, config_2.handle->ref == 1);
736                 NL_TEST_ASSERT(inSuite, config_3.handle->ref == 1);
737
738                 config_1.handle->AddToEnd(config_2.handle.Retain());
739                 NL_TEST_ASSERT(inSuite, config_1.handle->ref == 1); // config_1.handle
740                 NL_TEST_ASSERT(inSuite, config_2.handle->ref == 2); // config_2.handle and config_1.handle->next
741                 NL_TEST_ASSERT(inSuite, config_3.handle->ref == 1); // config_3.handle
742
743                 NL_TEST_ASSERT(inSuite, config_1.handle->tot_len == (config_1.init_len + config_2.init_len));
744                 NL_TEST_ASSERT(inSuite, config_1.handle->next == config_2.handle.Get());
745                 NL_TEST_ASSERT(inSuite, config_2.handle->next == nullptr);
746                 NL_TEST_ASSERT(inSuite, config_3.handle->next == nullptr);
747
748                 config_1.handle->AddToEnd(config_3.handle.Retain());
749                 NL_TEST_ASSERT(inSuite, config_1.handle->ref == 1); // config_1.handle
750                 NL_TEST_ASSERT(inSuite, config_2.handle->ref == 2); // config_2.handle and config_1.handle->next
751                 NL_TEST_ASSERT(inSuite, config_3.handle->ref == 2); // config_3.handle and config_2.handle->next
752
753                 NL_TEST_ASSERT(inSuite, config_1.handle->tot_len == (config_1.init_len + config_2.init_len + config_3.init_len));
754                 NL_TEST_ASSERT(inSuite, config_1.handle->next == config_2.handle.Get());
755                 NL_TEST_ASSERT(inSuite, config_2.handle->next == config_3.handle.Get());
756                 NL_TEST_ASSERT(inSuite, config_3.handle->next == nullptr);
757
758                 config_1.handle = nullptr;
759                 config_2.handle = nullptr;
760                 config_3.handle = nullptr;
761             }
762         }
763     }
764 }
765
766 /**
767  *  Test PacketBuffer::PopHead() function.
768  *
769  *  Description: Take two initial configurations of PacketBuffer from
770  *               inContext and create two PacketBuffer instances based on those
771  *               configurations. Next, link those buffers together, with the first
772  *               buffer instance pointing to the second one. Then, call PopHead()
773  *               on the first buffer to unlink the second buffer. After the call,
774  *               verify correct internal state of the first buffer.
775  */
776 void PacketBufferTest::CheckPopHead(nlTestSuite * inSuite, void * inContext)
777 {
778     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
779     PacketBufferTest * const test         = theContext->test;
780     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
781
782     // Single buffer test.
783     for (auto & config_1 : test->configurations)
784     {
785         test->PrepareTestBuffer(&config_1, kRecordHandle | kAllowHandleReuse);
786         NL_TEST_ASSERT(inSuite, config_1.handle->ref == 2);
787
788         const PacketBuffer * const buffer_1 = config_1.handle.mBuffer;
789
790         const PacketBufferHandle popped = config_1.handle.PopHead();
791
792         NL_TEST_ASSERT(inSuite, config_1.handle.IsNull());
793         NL_TEST_ASSERT(inSuite, popped.mBuffer == buffer_1);
794         NL_TEST_ASSERT(inSuite, popped->next == nullptr);
795         NL_TEST_ASSERT(inSuite, popped->tot_len == config_1.init_len);
796         NL_TEST_ASSERT(inSuite, popped->ref == 2);
797     }
798     test->ResetHandles();
799
800     // Chained buffers test.
801     for (auto & config_1 : test->configurations)
802     {
803         for (auto & config_2 : test->configurations)
804         {
805             if (&config_1 == &config_2)
806             {
807                 continue;
808             }
809
810             test->PrepareTestBuffer(&config_1, kRecordHandle | kAllowHandleReuse);
811             test->PrepareTestBuffer(&config_2, kRecordHandle | kAllowHandleReuse);
812
813             config_1.handle->AddToEnd(config_2.handle.Retain());
814
815             const PacketBufferHandle popped = config_1.handle.PopHead();
816
817             NL_TEST_ASSERT(inSuite, config_1.handle == config_2.handle);
818             NL_TEST_ASSERT(inSuite, config_1.handle->next == nullptr);
819             NL_TEST_ASSERT(inSuite, config_1.handle->tot_len == config_1.init_len);
820         }
821     }
822 }
823
824 /**
825  *  Test PacketBuffer::CompactHead() function.
826  *
827  *  Description: Take two initial configurations of PacketBuffer from
828  *               inContext and create two PacketBuffer instances based on those
829  *               configurations. Next, set both buffers' data length to any
830  *               combination of values from sLengths[] and link those buffers
831  *               into a chain. Then, call CompactHead() on the first buffer in
832  *               the chain. After calling the method, verify correctly adjusted
833  *               state of the first buffer.
834  */
835 void PacketBufferTest::CheckCompactHead(nlTestSuite * inSuite, void * inContext)
836 {
837     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
838     PacketBufferTest * const test         = theContext->test;
839     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
840
841     // Single buffer test.
842     for (auto & config : test->configurations)
843     {
844         for (size_t i = 0; i < theContext->length_count; ++i)
845         {
846             const uint16_t length = theContext->lengths[i];
847
848             test->PrepareTestBuffer(&config, kRecordHandle | kAllowHandleReuse);
849             config.handle->SetDataLength(length, config.handle);
850             const uint16_t data_length = config.handle->DataLength();
851
852             config.handle->CompactHead();
853
854             NL_TEST_ASSERT(inSuite, config.handle->payload == (config.start_buffer + PacketBuffer::kStructureSize));
855             NL_TEST_ASSERT(inSuite, config.handle->tot_len == data_length);
856         }
857
858         config.handle = nullptr;
859     }
860     NL_TEST_ASSERT(inSuite, test->ResetHandles());
861
862     // Chained buffers test.
863     for (auto & config_1 : test->configurations)
864     {
865         for (auto & config_2 : test->configurations)
866         {
867             if (&config_1 == &config_2)
868             {
869                 continue;
870             }
871
872             // start with various initial length for the first buffer
873             for (size_t i = 0; i < theContext->length_count; ++i)
874             {
875                 const uint16_t length_1 = theContext->lengths[i];
876
877                 // start with various initial length for the second buffer
878                 for (size_t j = 0; j < theContext->length_count; ++j)
879                 {
880                     const uint16_t length_2 = theContext->lengths[j];
881
882                     test->PrepareTestBuffer(&config_1, kRecordHandle | kAllowHandleReuse);
883                     NL_TEST_ASSERT(inSuite, config_1.handle->ref == 2);
884
885                     // CompactHead requires that there be no other references to the chained buffer,
886                     // so we manage it manually.
887                     test->PrepareTestBuffer(&config_2);
888                     NL_TEST_ASSERT(inSuite, config_2.handle->ref == 1);
889                     PacketBuffer * buffer_2 = std::move(config_2.handle).UnsafeRelease();
890                     NL_TEST_ASSERT(inSuite, config_2.handle.IsNull());
891
892                     config_1.handle->SetDataLength(length_1, config_1.handle);
893                     const uint16_t data_length_1 = config_1.handle->DataLength();
894
895                     // This chain will cause buffer_2 to be freed.
896                     config_1.handle->next = buffer_2;
897
898                     // Add various lengths to the second buffer
899                     buffer_2->SetDataLength(length_2, config_1.handle);
900                     const uint16_t data_length_2 = buffer_2->DataLength();
901
902                     config_1.handle->CompactHead();
903
904                     NL_TEST_ASSERT(inSuite, config_1.handle->payload == (config_1.start_buffer + PacketBuffer::kStructureSize));
905
906                     if (config_1.handle->tot_len > config_1.handle->MaxDataLength())
907                     {
908                         NL_TEST_ASSERT(inSuite, config_1.handle->len == config_1.handle->MaxDataLength());
909                         NL_TEST_ASSERT(inSuite, buffer_2->len == config_1.handle->tot_len - config_1.handle->MaxDataLength());
910                         NL_TEST_ASSERT(inSuite, config_1.handle->next == buffer_2);
911                         NL_TEST_ASSERT(inSuite, config_1.handle->ref == 2);
912                         NL_TEST_ASSERT(inSuite, buffer_2->ref == 1);
913                     }
914                     else
915                     {
916                         NL_TEST_ASSERT(inSuite, config_1.handle->len == config_1.handle->tot_len);
917                         if (data_length_1 >= config_1.handle->MaxDataLength() && data_length_2 == 0)
918                         {
919                             /* make sure the second buffer is not freed */
920                             NL_TEST_ASSERT(inSuite, config_1.handle->next == buffer_2);
921                             NL_TEST_ASSERT(inSuite, buffer_2->ref == 1);
922                         }
923                         else
924                         {
925                             /* make sure the second buffer is freed */
926                             NL_TEST_ASSERT(inSuite, config_1.handle->next == nullptr);
927                             buffer_2 = nullptr;
928                         }
929                     }
930
931                     NL_TEST_ASSERT(inSuite, config_1.handle->ref == 2);
932                     config_1.handle = nullptr;
933
934                     // Verify and release handles.
935                     NL_TEST_ASSERT(inSuite, test->ResetHandles());
936                 }
937             }
938         }
939     }
940 }
941
942 /**
943  *  Test PacketBuffer::ConsumeHead() function.
944  *
945  *  Description: For every buffer-configuration from inContext, create a
946  *               buffer's instance according to the configuration. Next,
947  *               for any value from sLengths[], pass it to the buffer's
948  *               instance through ConsumeHead() method. Then, verify that
949  *               the internal state of the buffer has been correctly
950  *               adjusted according to the value passed into the method.
951  */
952 void PacketBufferTest::CheckConsumeHead(nlTestSuite * inSuite, void * inContext)
953 {
954     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
955     PacketBufferTest * const test         = theContext->test;
956     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
957
958     for (auto & config : test->configurations)
959     {
960         for (size_t i = 0; i < theContext->length_count; ++i)
961         {
962             const uint16_t length = theContext->lengths[i];
963             test->PrepareTestBuffer(&config, kRecordHandle | kAllowHandleReuse);
964
965             config.handle->ConsumeHead(length);
966
967             if (length > config.init_len)
968             {
969                 NL_TEST_ASSERT(inSuite, config.handle->payload == (config.payload_ptr + config.init_len));
970                 NL_TEST_ASSERT(inSuite, config.handle->len == 0);
971                 NL_TEST_ASSERT(inSuite, config.handle->tot_len == 0);
972             }
973             else
974             {
975                 NL_TEST_ASSERT(inSuite, config.handle->payload == (config.payload_ptr + length));
976                 NL_TEST_ASSERT(inSuite, config.handle->len == (config.handle->len - length));
977                 NL_TEST_ASSERT(inSuite, config.handle->tot_len == (config.handle->tot_len - length));
978             }
979         }
980     }
981 }
982
983 /**
984  *  Test PacketBuffer::Consume() function.
985  *
986  *  Description: Take two different initial configurations of PacketBuffer from
987  *               inContext and create two PacketBuffer instances based on those
988  *               configurations. Next, set both buffers' data length to any
989  *               combination of values from sLengths[]  and link those buffers
990  *               into a chain. Then, call Consume() on the first buffer in
991  *               the chain with all values from sLengths[]. After calling the
992  *               method, verify correctly adjusted the state of the first
993  *               buffer and appropriate return pointer from the method's call.
994  */
995 void PacketBufferTest::CheckConsume(nlTestSuite * inSuite, void * inContext)
996 {
997     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
998     PacketBufferTest * const test         = theContext->test;
999     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
1000
1001     for (auto & config_1 : test->configurations)
1002     {
1003         for (auto & config_2 : test->configurations)
1004         {
1005             if (&config_1 == &config_2)
1006             {
1007                 continue;
1008             }
1009
1010             // consume various amounts of memory
1011             for (size_t i = 0; i < theContext->length_count; ++i)
1012             {
1013                 const uint16_t consumeLength = theContext->lengths[i];
1014                 // start with various initial length for the first buffer
1015                 for (size_t j = 0; j < theContext->length_count; ++j)
1016                 {
1017                     const uint16_t len_1 = theContext->lengths[j];
1018                     // start with various initial length for the second buffer
1019                     for (size_t k = 0; k < theContext->length_count; ++k)
1020                     {
1021                         const uint16_t len_2 = theContext->lengths[k];
1022
1023                         test->PrepareTestBuffer(&config_1);
1024                         test->PrepareTestBuffer(&config_2);
1025                         NL_TEST_ASSERT(inSuite, config_1.handle->ref == 1);
1026                         NL_TEST_ASSERT(inSuite, config_2.handle->ref == 1);
1027
1028                         config_1.handle->AddToEnd(config_2.handle.Retain());
1029
1030                         // Add various lengths to buffers
1031                         config_1.handle->SetDataLength(len_1, config_1.handle);
1032                         config_2.handle->SetDataLength(len_2, config_1.handle);
1033
1034                         const uint16_t buf_1_len = config_1.handle->len;
1035                         const uint16_t buf_2_len = config_2.handle->len;
1036
1037                         PacketBufferHandle original_handle_1 = config_1.handle.Retain();
1038                         NL_TEST_ASSERT(inSuite, config_1.handle->ref == 2); // config_1.handle and original_handle_1
1039                         NL_TEST_ASSERT(inSuite, config_2.handle->ref == 2); // config_2.handle and config_1.handle->next
1040
1041                         config_1.handle.Consume(consumeLength);
1042
1043                         if (consumeLength == 0)
1044                         {
1045                             NL_TEST_ASSERT(inSuite, config_1.handle == original_handle_1);
1046                             NL_TEST_ASSERT(inSuite, config_1.handle->len == buf_1_len);
1047                             NL_TEST_ASSERT(inSuite, config_2.handle->len == buf_2_len);
1048                             NL_TEST_ASSERT(inSuite, config_1.handle->ref == 2); // config_1.handle and original_handle_1
1049                             NL_TEST_ASSERT(inSuite, config_2.handle->ref == 2); // config_2.handle and config_1.handle->next
1050                         }
1051                         else if (consumeLength < buf_1_len)
1052                         {
1053                             NL_TEST_ASSERT(inSuite, config_1.handle == original_handle_1);
1054                             NL_TEST_ASSERT(inSuite, config_1.handle->len == buf_1_len - consumeLength);
1055                             NL_TEST_ASSERT(inSuite, config_2.handle->len == buf_2_len);
1056                             NL_TEST_ASSERT(inSuite, config_1.handle->ref == 2); // config_1.handle and original_handle_1
1057                             NL_TEST_ASSERT(inSuite, config_2.handle->ref == 2); // config_2.handle and config_1.handle->next
1058                         }
1059                         else if ((consumeLength < buf_1_len + buf_2_len ||
1060                                   (consumeLength == buf_1_len + buf_2_len && buf_2_len == 0)))
1061                         {
1062                             NL_TEST_ASSERT(inSuite, config_1.handle == config_2.handle);
1063                             NL_TEST_ASSERT(inSuite, config_2.handle->len == buf_1_len + buf_2_len - consumeLength);
1064                             NL_TEST_ASSERT(inSuite, original_handle_1->ref == 1); // original_handle_1
1065                             NL_TEST_ASSERT(inSuite, config_2.handle->ref == 2);   // config_1.handle and config_2.handle
1066                         }
1067                         else
1068                         {
1069                             NL_TEST_ASSERT(inSuite, config_1.handle.IsNull());
1070                             NL_TEST_ASSERT(inSuite, original_handle_1->ref == 1); // original_handle_1
1071                             NL_TEST_ASSERT(inSuite, config_2.handle->ref == 1);   // config_2.handle
1072                         }
1073
1074                         original_handle_1 = nullptr;
1075                         config_1.handle   = nullptr;
1076                         config_2.handle   = nullptr;
1077                     }
1078                 }
1079             }
1080         }
1081     }
1082 }
1083
1084 /**
1085  *  Test PacketBuffer::EnsureReservedSize() function.
1086  *
1087  *  Description: For every buffer-configuration from inContext, create a
1088  *               buffer's instance according to the configuration. Next,
1089  *               manually specify how much space is reserved in the buffer.
1090  *               Then, verify that EnsureReservedSize() method correctly
1091  *               retrieves the amount of the reserved space.
1092  */
1093 void PacketBufferTest::CheckEnsureReservedSize(nlTestSuite * inSuite, void * inContext)
1094 {
1095     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
1096     PacketBufferTest * const test         = theContext->test;
1097     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
1098
1099     for (auto & config : test->configurations)
1100     {
1101         for (size_t i = 0; i < theContext->length_count; ++i)
1102         {
1103             const uint16_t length = theContext->lengths[i];
1104
1105             test->PrepareTestBuffer(&config, kRecordHandle | kAllowHandleReuse);
1106             const uint16_t kAllocSize = config.handle->AllocSize();
1107             uint16_t reserved_size    = config.reserved_size;
1108
1109             if (PacketBuffer::kStructureSize + config.reserved_size > kAllocSize)
1110             {
1111                 reserved_size = static_cast<uint16_t>(kAllocSize - PacketBuffer::kStructureSize);
1112             }
1113
1114             if (length <= reserved_size)
1115             {
1116                 NL_TEST_ASSERT(inSuite, config.handle->EnsureReservedSize(length) == true);
1117                 continue;
1118             }
1119
1120             if ((length + config.init_len) > (kAllocSize - PacketBuffer::kStructureSize))
1121             {
1122                 NL_TEST_ASSERT(inSuite, config.handle->EnsureReservedSize(length) == false);
1123                 continue;
1124             }
1125
1126             NL_TEST_ASSERT(inSuite, config.handle->EnsureReservedSize(length) == true);
1127             NL_TEST_ASSERT(inSuite, config.handle->payload == (config.payload_ptr + length - reserved_size));
1128         }
1129     }
1130 }
1131
1132 /**
1133  *  Test PacketBuffer::AlignPayload() function.
1134  *
1135  *  Description: For every buffer-configuration from inContext, create a
1136  *               buffer's instance according to the configuration. Next,
1137  *               manually specify how much space is reserved and the
1138  *               required payload shift. Then, verify that AlignPayload()
1139  *               method correctly aligns the payload start pointer.
1140  */
1141 void PacketBufferTest::CheckAlignPayload(nlTestSuite * inSuite, void * inContext)
1142 {
1143     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
1144     PacketBufferTest * const test         = theContext->test;
1145     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
1146
1147     for (auto & config : test->configurations)
1148     {
1149         for (size_t n = 0; n < theContext->length_count; ++n)
1150         {
1151             test->PrepareTestBuffer(&config, kRecordHandle | kAllowHandleReuse);
1152             const uint16_t kAllocSize = config.handle->AllocSize();
1153
1154             if (theContext->lengths[n] == 0)
1155             {
1156                 NL_TEST_ASSERT(inSuite, config.handle->AlignPayload(theContext->lengths[n]) == false);
1157                 continue;
1158             }
1159
1160             uint16_t reserved_size = config.reserved_size;
1161             if (config.reserved_size > kAllocSize)
1162             {
1163                 reserved_size = kAllocSize;
1164             }
1165
1166             const uint16_t payload_offset =
1167                 static_cast<uint16_t>(reinterpret_cast<uintptr_t>(config.handle->Start()) % theContext->lengths[n]);
1168             uint16_t payload_shift = 0;
1169             if (payload_offset > 0)
1170                 payload_shift = static_cast<uint16_t>(theContext->lengths[n] - payload_offset);
1171
1172             if (payload_shift <= kAllocSize - reserved_size)
1173             {
1174                 NL_TEST_ASSERT(inSuite, config.handle->AlignPayload(theContext->lengths[n]) == true);
1175                 NL_TEST_ASSERT(inSuite, ((unsigned long) config.handle->Start() % theContext->lengths[n]) == 0);
1176             }
1177             else
1178             {
1179                 NL_TEST_ASSERT(inSuite, config.handle->AlignPayload(theContext->lengths[n]) == false);
1180             }
1181         }
1182     }
1183 }
1184
1185 /**
1186  *  Test PacketBuffer::Next() function.
1187  */
1188 void PacketBufferTest::CheckNext(nlTestSuite * inSuite, void * inContext)
1189 {
1190     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
1191     PacketBufferTest * const test         = theContext->test;
1192     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
1193
1194     for (auto & config_1 : test->configurations)
1195     {
1196         for (auto & config_2 : test->configurations)
1197         {
1198             test->PrepareTestBuffer(&config_1, kRecordHandle | kAllowHandleReuse);
1199             test->PrepareTestBuffer(&config_2, kRecordHandle | kAllowHandleReuse);
1200
1201             if (&config_1 != &config_2)
1202             {
1203                 NL_TEST_ASSERT(inSuite, config_1.handle->Next().IsNull());
1204
1205                 config_1.handle->AddToEnd(config_2.handle.Retain());
1206
1207                 NL_TEST_ASSERT(inSuite, config_1.handle->Next() == config_2.handle);
1208                 NL_TEST_ASSERT(inSuite, config_1.handle->ChainedBuffer() == config_2.handle.Get());
1209             }
1210             else
1211             {
1212                 NL_TEST_ASSERT(inSuite, !config_1.handle->HasChainedBuffer());
1213             }
1214
1215             NL_TEST_ASSERT(inSuite, !config_2.handle->HasChainedBuffer());
1216         }
1217     }
1218 }
1219
1220 /**
1221  *  Test PacketBuffer::Last() function.
1222  */
1223 void PacketBufferTest::CheckLast(nlTestSuite * inSuite, void * inContext)
1224 {
1225     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
1226     PacketBufferTest * const test         = theContext->test;
1227     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
1228
1229     for (auto & config_1 : test->configurations)
1230     {
1231         for (auto & config_2 : test->configurations)
1232         {
1233             for (auto & config_3 : test->configurations)
1234             {
1235                 if (&config_1 == &config_2 || &config_1 == &config_3 || &config_2 == &config_3)
1236                 {
1237                     continue;
1238                 }
1239
1240                 test->PrepareTestBuffer(&config_1);
1241                 test->PrepareTestBuffer(&config_2);
1242                 test->PrepareTestBuffer(&config_3);
1243
1244                 NL_TEST_ASSERT(inSuite, config_1.handle->Last() == config_1.handle);
1245                 NL_TEST_ASSERT(inSuite, config_2.handle->Last() == config_2.handle);
1246                 NL_TEST_ASSERT(inSuite, config_3.handle->Last() == config_3.handle);
1247
1248                 config_1.handle->AddToEnd(config_2.handle.Retain());
1249
1250                 NL_TEST_ASSERT(inSuite, config_1.handle->Last() == config_2.handle);
1251                 NL_TEST_ASSERT(inSuite, config_2.handle->Last() == config_2.handle);
1252                 NL_TEST_ASSERT(inSuite, config_3.handle->Last() == config_3.handle);
1253
1254                 config_1.handle->AddToEnd(config_3.handle.Retain());
1255
1256                 NL_TEST_ASSERT(inSuite, config_1.handle->Last() == config_3.handle);
1257                 NL_TEST_ASSERT(inSuite, config_2.handle->Last() == config_3.handle);
1258                 NL_TEST_ASSERT(inSuite, config_3.handle->Last() == config_3.handle);
1259
1260                 config_1.handle = nullptr;
1261                 config_2.handle = nullptr;
1262                 config_3.handle = nullptr;
1263             }
1264         }
1265     }
1266 }
1267
1268 /**
1269  *  Test PacketBuffer::Read() function.
1270  */
1271 void PacketBufferTest::CheckRead(nlTestSuite * inSuite, void * inContext)
1272 {
1273     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
1274     PacketBufferTest * const test         = theContext->test;
1275     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
1276
1277     uint8_t payloads[2 * kBlockSize] = { 1 };
1278     uint8_t result[2 * kBlockSize];
1279     for (size_t i = 1; i < sizeof(payloads); ++i)
1280     {
1281         payloads[i] = static_cast<uint8_t>(random());
1282     }
1283
1284     for (auto & config_1 : test->configurations)
1285     {
1286         for (auto & config_2 : test->configurations)
1287         {
1288             if (&config_1 == &config_2)
1289             {
1290                 continue;
1291             }
1292
1293             test->PrepareTestBuffer(&config_1, kAllowHandleReuse);
1294             test->PrepareTestBuffer(&config_2, kAllowHandleReuse);
1295
1296             const uint16_t length_1     = config_1.handle->MaxDataLength();
1297             const uint16_t length_2     = config_2.handle->MaxDataLength();
1298             const size_t length_sum     = length_1 + length_2;
1299             const uint16_t length_total = static_cast<uint16_t>(length_sum);
1300             NL_TEST_ASSERT(inSuite, length_total == length_sum);
1301
1302             memcpy(config_1.handle->Start(), payloads, length_1);
1303             memcpy(config_2.handle->Start(), payloads + length_1, length_2);
1304             config_1.handle->SetDataLength(length_1);
1305             config_2.handle->SetDataLength(length_2);
1306             config_1.handle->AddToEnd(config_2.handle.Retain());
1307             NL_TEST_ASSERT(inSuite, config_1.handle->TotalLength() == length_total);
1308
1309             if (length_1 >= 1)
1310             {
1311                 // Check a read that does not span packet buffers.
1312                 CHIP_ERROR err = config_1.handle->Read(result, 1);
1313                 NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
1314                 NL_TEST_ASSERT(inSuite, result[0] == payloads[0]);
1315             }
1316
1317             // Check a read that spans packet buffers.
1318             CHIP_ERROR err = config_1.handle->Read(result, length_total);
1319             NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
1320             NL_TEST_ASSERT(inSuite, memcmp(payloads, result, length_total) == 0);
1321
1322             // Check a read that is too long fails.
1323             err = config_1.handle->Read(result, length_total + 1);
1324             NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUFFER_TOO_SMALL);
1325
1326             // Check that running off the end of a corrupt buffer chain is detected.
1327             if (length_total < UINT16_MAX)
1328             {
1329                 // First case: TotalLength() is wrong.
1330                 config_1.handle->tot_len = static_cast<uint16_t>(config_1.handle->tot_len + 1);
1331                 err                      = config_1.handle->Read(result, length_total + 1);
1332                 NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INTERNAL);
1333                 config_1.handle->tot_len = static_cast<uint16_t>(config_1.handle->tot_len - 1);
1334             }
1335             if (length_1 >= 1)
1336             {
1337                 // Second case: an individual buffer's DataLength() is wrong.
1338                 config_1.handle->len = static_cast<uint16_t>(config_1.handle->len - 1);
1339                 err                  = config_1.handle->Read(result, length_total);
1340                 NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INTERNAL);
1341                 config_1.handle->len = static_cast<uint16_t>(config_1.handle->len + 1);
1342             }
1343
1344             config_1.handle = nullptr;
1345             config_2.handle = nullptr;
1346         }
1347     }
1348 }
1349
1350 /**
1351  *  Test PacketBuffer::AddRef() function.
1352  */
1353 void PacketBufferTest::CheckAddRef(nlTestSuite * inSuite, void * inContext)
1354 {
1355     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
1356     PacketBufferTest * const test         = theContext->test;
1357     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
1358
1359     for (auto & config : test->configurations)
1360     {
1361         test->PrepareTestBuffer(&config, kRecordHandle);
1362         const auto refs = config.handle->ref;
1363         config.handle->AddRef();
1364         NL_TEST_ASSERT(inSuite, config.handle->ref == refs + 1);
1365         config.handle->ref = refs; // Don't leak buffers.
1366     }
1367 }
1368
1369 /**
1370  *  Test PacketBuffer::Free() function.
1371  *
1372  *  Description: Take two different initial configurations of PacketBuffer from
1373  *               inContext and create two PacketBuffer instances based on those
1374  *               configurations. Next, chain two buffers together and set each
1375  *               buffer's reference count to one of the values from
1376  *               init_ret_count[]. Then, call Free() on the first buffer in
1377  *               the chain and verify correctly adjusted states of the two
1378  *               buffers.
1379  */
1380 void PacketBufferTest::CheckFree(nlTestSuite * inSuite, void * inContext)
1381 {
1382     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
1383     PacketBufferTest * const test         = theContext->test;
1384     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
1385
1386     const decltype(PacketBuffer::ref) init_ref_count[] = { 1, 2, 3 };
1387     constexpr size_t kRefs                             = sizeof(init_ref_count) / sizeof(init_ref_count[0]);
1388
1389     for (auto & config_1 : test->configurations)
1390     {
1391         for (auto & config_2 : test->configurations)
1392         {
1393             if (&config_1 == &config_2)
1394             {
1395                 continue;
1396             }
1397
1398             // start with various buffer ref counts
1399             for (size_t r = 0; r < kRefs; r++)
1400             {
1401                 config_1.handle = PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0);
1402                 config_2.handle = PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0);
1403                 NL_TEST_ASSERT(inSuite, !config_1.handle.IsNull());
1404                 NL_TEST_ASSERT(inSuite, !config_2.handle.IsNull());
1405
1406                 test->PrepareTestBuffer(&config_1, kAllowHandleReuse);
1407                 test->PrepareTestBuffer(&config_2, kAllowHandleReuse);
1408                 NL_TEST_ASSERT(inSuite, config_1.handle->ref == 1);
1409                 NL_TEST_ASSERT(inSuite, config_2.handle->ref == 1);
1410
1411                 // Chain buffers.
1412                 config_1.handle->next = config_2.handle.Get();
1413
1414                 // Add various buffer ref counts.
1415                 const auto initial_refs_1 = config_1.handle->ref = init_ref_count[r];
1416                 const auto initial_refs_2 = config_2.handle->ref = init_ref_count[(r + 1) % kRefs];
1417
1418                 // Free head.
1419                 PacketBuffer::Free(config_1.handle.mBuffer);
1420                 if (initial_refs_1 == 1)
1421                 {
1422                     config_1.handle.mBuffer = nullptr;
1423                 }
1424
1425                 // Verification.
1426                 if (initial_refs_1 > 1)
1427                 {
1428                     // Verify that head ref count is decremented.
1429                     NL_TEST_ASSERT(inSuite, config_1.handle->ref == initial_refs_1 - 1);
1430                     // Verify that chain is maintained.
1431                     NL_TEST_ASSERT(inSuite, config_1.handle->next == config_2.handle.Get());
1432                     // Verify that chained buffer ref count has not changed.
1433                     NL_TEST_ASSERT(inSuite, config_2.handle->ref == initial_refs_2);
1434                 }
1435                 else
1436                 {
1437                     if (initial_refs_2 > 1)
1438                     {
1439                         // Verify that chained buffer ref count is decremented.
1440                         NL_TEST_ASSERT(inSuite, config_2.handle->ref == initial_refs_2 - 1);
1441                     }
1442                     else
1443                     {
1444                         // Since the test used fake ref counts, config_2.handle now points
1445                         // to a freed buffer; clear the handle's internal pointer.
1446                         config_2.handle.mBuffer = nullptr;
1447                     }
1448                 }
1449
1450                 // Clean up.
1451                 if (!config_1.handle.IsNull())
1452                 {
1453                     config_1.handle->next = nullptr;
1454                     config_1.handle->ref  = 1;
1455                     config_1.handle       = nullptr;
1456                 }
1457                 if (!config_2.handle.IsNull())
1458                 {
1459                     config_2.handle->ref = 1;
1460                     config_2.handle      = nullptr;
1461                 }
1462             }
1463         }
1464     }
1465 }
1466
1467 /**
1468  *  Test PacketBuffer::FreeHead() function.
1469  *
1470  *  Description: Take two different initial configurations of PacketBuffer from
1471  *               inContext and create two PacketBuffer instances based on those
1472  *               configurations. Next, chain two buffers together. Then, call
1473  *               FreeHead() on the first buffer in the chain and verify that
1474  *               the method returned pointer to the second buffer.
1475  */
1476 void PacketBufferTest::CheckFreeHead(nlTestSuite * inSuite, void * inContext)
1477 {
1478     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
1479     PacketBufferTest * const test         = theContext->test;
1480     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
1481
1482     for (auto & config_1 : test->configurations)
1483     {
1484         for (auto & config_2 : test->configurations)
1485         {
1486             if (&config_1 == &config_2)
1487             {
1488                 continue;
1489             }
1490
1491             // Test PacketBuffer::FreeHead
1492
1493             test->PrepareTestBuffer(&config_1, kAllowHandleReuse);
1494             test->PrepareTestBuffer(&config_2, kAllowHandleReuse);
1495             NL_TEST_ASSERT(inSuite, config_1.handle->ref == 1);
1496             NL_TEST_ASSERT(inSuite, config_2.handle->ref == 1);
1497
1498             PacketBufferHandle handle_1 = config_1.handle.Retain();
1499             config_1.handle->AddToEnd(config_2.handle.Retain());
1500             NL_TEST_ASSERT(inSuite, config_1.handle->ref == 2);
1501             NL_TEST_ASSERT(inSuite, config_2.handle->ref == 2); // config_2.handle and config_1.handle->next
1502
1503             PacketBuffer * const returned = PacketBuffer::FreeHead(std::move(config_1.handle).UnsafeRelease());
1504
1505             NL_TEST_ASSERT(inSuite, handle_1->ref == 1);
1506             NL_TEST_ASSERT(inSuite, config_2.handle->ref == 2); // config_2.handle and returned
1507             NL_TEST_ASSERT(inSuite, returned == config_2.handle.Get());
1508
1509             config_1.handle = nullptr;
1510             NL_TEST_ASSERT(inSuite, config_2.handle->ref == 2);
1511             config_2.handle = nullptr;
1512             NL_TEST_ASSERT(inSuite, returned->ref == 1);
1513             PacketBuffer::Free(returned);
1514
1515             // Test PacketBufferHandle::FreeHead
1516
1517             test->PrepareTestBuffer(&config_1, kAllowHandleReuse);
1518             test->PrepareTestBuffer(&config_2, kAllowHandleReuse);
1519             NL_TEST_ASSERT(inSuite, config_1.handle->ref == 1);
1520             NL_TEST_ASSERT(inSuite, config_2.handle->ref == 1);
1521
1522             handle_1 = config_1.handle.Retain();
1523             config_1.handle->AddToEnd(config_2.handle.Retain());
1524             NL_TEST_ASSERT(inSuite, config_1.handle->ref == 2);
1525             NL_TEST_ASSERT(inSuite, config_2.handle->ref == 2); // config_2.handle and config_1.handle->next
1526
1527             PacketBuffer * const buffer_1 = config_1.handle.Get();
1528
1529             config_1.handle.FreeHead();
1530
1531             NL_TEST_ASSERT(inSuite, buffer_1->ref == 1);
1532             NL_TEST_ASSERT(inSuite, config_1.handle == config_2.handle);
1533             NL_TEST_ASSERT(inSuite, config_2.handle->ref == 2); // config_2.handle and config_1.handle
1534
1535             config_1.handle = nullptr;
1536             config_2.handle = nullptr;
1537         }
1538     }
1539 }
1540
1541 void PacketBufferTest::CheckHandleConstruct(nlTestSuite * inSuite, void * inContext)
1542 {
1543     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
1544     PacketBufferTest * const test         = theContext->test;
1545     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
1546
1547     PacketBufferHandle handle_1;
1548     NL_TEST_ASSERT(inSuite, handle_1.IsNull());
1549
1550     PacketBufferHandle handle_2(nullptr);
1551     NL_TEST_ASSERT(inSuite, handle_2.IsNull());
1552
1553     PacketBufferHandle handle_3(PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize));
1554     NL_TEST_ASSERT(inSuite, !handle_3.IsNull());
1555
1556     // Private constructor.
1557     PacketBuffer * const buffer_3 = std::move(handle_3).UnsafeRelease();
1558     PacketBufferHandle handle_4(buffer_3);
1559     NL_TEST_ASSERT(inSuite, handle_4.Get() == buffer_3);
1560 }
1561
1562 void PacketBufferTest::CheckHandleMove(nlTestSuite * inSuite, void * inContext)
1563 {
1564     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
1565     PacketBufferTest * const test         = theContext->test;
1566     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
1567
1568     for (auto & config_1 : test->configurations)
1569     {
1570         for (auto & config_2 : test->configurations)
1571         {
1572             if (&config_1 == &config_2)
1573             {
1574                 continue;
1575             }
1576
1577             test->PrepareTestBuffer(&config_1, kRecordHandle);
1578             test->PrepareTestBuffer(&config_2, kRecordHandle);
1579
1580             const PacketBuffer * const buffer_1 = config_1.handle.Get();
1581             const PacketBuffer * const buffer_2 = config_2.handle.Get();
1582             NL_TEST_ASSERT(inSuite, buffer_1 != buffer_2);
1583             NL_TEST_ASSERT(inSuite, buffer_1->ref == 2); // test.handles and config_1.handle
1584             NL_TEST_ASSERT(inSuite, buffer_2->ref == 2); // test.handles and config_2.handle
1585
1586             config_1.handle = std::move(config_2.handle);
1587             NL_TEST_ASSERT(inSuite, config_1.handle.Get() == buffer_2);
1588             NL_TEST_ASSERT(inSuite, config_2.handle.Get() == nullptr);
1589             NL_TEST_ASSERT(inSuite, buffer_1->ref == 1); // test.handles
1590             NL_TEST_ASSERT(inSuite, buffer_2->ref == 2); // test.handles and config_1.handle
1591
1592             config_1.handle = nullptr;
1593         }
1594         // Verify and release handles.
1595         NL_TEST_ASSERT(inSuite, test->ResetHandles());
1596     }
1597 }
1598
1599 void PacketBufferTest::CheckHandleRelease(nlTestSuite * inSuite, void * inContext)
1600 {
1601     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
1602     PacketBufferTest * const test         = theContext->test;
1603     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
1604
1605     for (auto & config_1 : test->configurations)
1606     {
1607         test->PrepareTestBuffer(&config_1);
1608
1609         PacketBuffer * const buffer_1 = config_1.handle.Get();
1610         PacketBuffer * const taken_1  = std::move(config_1.handle).UnsafeRelease();
1611
1612         NL_TEST_ASSERT(inSuite, buffer_1 == taken_1);
1613         NL_TEST_ASSERT(inSuite, config_1.handle.IsNull());
1614         NL_TEST_ASSERT(inSuite, buffer_1->ref == 1);
1615         PacketBuffer::Free(buffer_1);
1616     }
1617 }
1618
1619 void PacketBufferTest::CheckHandleFree(nlTestSuite * inSuite, void * inContext)
1620 {
1621     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
1622     PacketBufferTest * const test         = theContext->test;
1623     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
1624
1625     for (auto & config_1 : test->configurations)
1626     {
1627         test->PrepareTestBuffer(&config_1, kRecordHandle);
1628
1629         const PacketBuffer * const buffer_1 = config_1.handle.Get();
1630         NL_TEST_ASSERT(inSuite, buffer_1->ref == 2); // test.handles and config_1.handle
1631
1632         config_1.handle = nullptr;
1633         NL_TEST_ASSERT(inSuite, config_1.handle.IsNull());
1634         NL_TEST_ASSERT(inSuite, config_1.handle.Get() == nullptr);
1635         NL_TEST_ASSERT(inSuite, buffer_1->ref == 1); // test.handles only
1636     }
1637 }
1638
1639 void PacketBufferTest::CheckHandleRetain(nlTestSuite * inSuite, void * inContext)
1640 {
1641     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
1642     PacketBufferTest * const test         = theContext->test;
1643     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
1644
1645     for (auto & config_1 : test->configurations)
1646     {
1647         test->PrepareTestBuffer(&config_1, kRecordHandle);
1648
1649         NL_TEST_ASSERT(inSuite, config_1.handle->ref == 2); // test.handles and config_1.handle
1650
1651         PacketBufferHandle handle_1 = config_1.handle.Retain();
1652
1653         NL_TEST_ASSERT(inSuite, config_1.handle == handle_1);
1654         NL_TEST_ASSERT(inSuite, config_1.handle->ref == 3); // test.handles and config_1.handle and handle_1
1655     }
1656 }
1657
1658 void PacketBufferTest::CheckHandleAdopt(nlTestSuite * inSuite, void * inContext)
1659 {
1660     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
1661     PacketBufferTest * const test         = theContext->test;
1662     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
1663
1664     for (auto & config_1 : test->configurations)
1665     {
1666         test->PrepareTestBuffer(&config_1, kRecordHandle);
1667         PacketBuffer * buffer_1 = std::move(config_1.handle).UnsafeRelease();
1668
1669         NL_TEST_ASSERT(inSuite, config_1.handle.IsNull());
1670         NL_TEST_ASSERT(inSuite, buffer_1->ref == 2); // test.handles and buffer_1
1671
1672         config_1.handle = PacketBufferHandle::Adopt(buffer_1);
1673         NL_TEST_ASSERT(inSuite, config_1.handle.Get() == buffer_1);
1674         NL_TEST_ASSERT(inSuite, config_1.handle->ref == 2); // test.handles and config_1.handle
1675
1676         config_1.handle = nullptr;
1677         NL_TEST_ASSERT(inSuite, config_1.handle.IsNull());
1678         NL_TEST_ASSERT(inSuite, buffer_1->ref == 1); // test.handles only
1679     }
1680 }
1681
1682 void PacketBufferTest::CheckHandleHold(nlTestSuite * inSuite, void * inContext)
1683 {
1684     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
1685     PacketBufferTest * const test         = theContext->test;
1686     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
1687
1688     for (auto & config_1 : test->configurations)
1689     {
1690         test->PrepareTestBuffer(&config_1, kRecordHandle);
1691         PacketBuffer * buffer_1 = std::move(config_1.handle).UnsafeRelease();
1692
1693         NL_TEST_ASSERT(inSuite, config_1.handle.IsNull());
1694         NL_TEST_ASSERT(inSuite, buffer_1->ref == 2); // test.handles and buffer_1
1695
1696         config_1.handle = PacketBufferHandle::Hold(buffer_1);
1697         NL_TEST_ASSERT(inSuite, config_1.handle.Get() == buffer_1);
1698         NL_TEST_ASSERT(inSuite, config_1.handle->ref == 3); // test.handles and config_1.handle and buffer_1
1699
1700         config_1.handle = nullptr;
1701         NL_TEST_ASSERT(inSuite, config_1.handle.IsNull());
1702         NL_TEST_ASSERT(inSuite, buffer_1->ref == 2); // test.handles only and buffer_1
1703
1704         PacketBuffer::Free(buffer_1);
1705     }
1706 }
1707
1708 void PacketBufferTest::CheckHandleAdvance(nlTestSuite * inSuite, void * inContext)
1709 {
1710     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
1711     PacketBufferTest * const test         = theContext->test;
1712     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
1713
1714     for (auto & config_1 : test->configurations)
1715     {
1716         for (auto & config_2 : test->configurations)
1717         {
1718             for (auto & config_3 : test->configurations)
1719             {
1720                 if (&config_1 == &config_2 || &config_1 == &config_3 || &config_2 == &config_3)
1721                 {
1722                     continue;
1723                 }
1724
1725                 test->PrepareTestBuffer(&config_1);
1726                 test->PrepareTestBuffer(&config_2);
1727                 test->PrepareTestBuffer(&config_3);
1728
1729                 PacketBufferHandle handle_1 = config_1.handle.Retain();
1730                 PacketBufferHandle handle_2 = config_2.handle.Retain();
1731                 PacketBufferHandle handle_3 = config_3.handle.Retain();
1732
1733                 config_1.handle->AddToEnd(config_2.handle.Retain());
1734                 config_1.handle->AddToEnd(config_3.handle.Retain());
1735
1736                 NL_TEST_ASSERT(inSuite, config_1.handle->ChainedBuffer() == config_2.handle.Get());
1737                 NL_TEST_ASSERT(inSuite, config_2.handle->ChainedBuffer() == config_3.handle.Get());
1738                 NL_TEST_ASSERT(inSuite, config_3.handle->HasChainedBuffer() == false);
1739                 NL_TEST_ASSERT(inSuite, handle_1->ref == 2); // handle_1 and config_1.handle
1740                 NL_TEST_ASSERT(inSuite, handle_2->ref == 3); // handle_2 and config_2.handle and config_1.handle->next
1741                 NL_TEST_ASSERT(inSuite, handle_3->ref == 3); // handle_3 and config_3.handle and config_2.handle->next
1742
1743                 config_1.handle.Advance();
1744
1745                 NL_TEST_ASSERT(inSuite, config_1.handle == handle_2);
1746                 NL_TEST_ASSERT(inSuite, handle_1->ref == 1); // handle_1 only
1747                 NL_TEST_ASSERT(inSuite, handle_2->ref == 4); // handle_2, config_[12].handle, handle_1->next
1748                 NL_TEST_ASSERT(inSuite, handle_3->ref == 3); // handle_3, config_3.handle, config_2.handle->next
1749
1750                 config_1.handle.Advance();
1751
1752                 NL_TEST_ASSERT(inSuite, config_1.handle == handle_3);
1753                 NL_TEST_ASSERT(inSuite, handle_1->ref == 1); // handle_1 only
1754                 NL_TEST_ASSERT(inSuite, handle_2->ref == 3); // handle_2, config_2.handle, handle_1->next
1755                 NL_TEST_ASSERT(inSuite, handle_3->ref == 4); // handle_3, config_[13].handle, handle_2->next
1756
1757                 config_1.handle = nullptr;
1758                 config_2.handle = nullptr;
1759                 config_3.handle = nullptr;
1760             }
1761         }
1762     }
1763 }
1764
1765 void PacketBufferTest::CheckHandleRightSize(nlTestSuite * inSuite, void * inContext)
1766 {
1767     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
1768     PacketBufferTest * const test         = theContext->test;
1769     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
1770
1771     const char kPayload[]     = "Joy!";
1772     PacketBufferHandle handle = PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0);
1773     PacketBuffer * buffer     = handle.mBuffer;
1774
1775     memcpy(handle->Start(), kPayload, sizeof kPayload);
1776     buffer->SetDataLength(sizeof kPayload);
1777     NL_TEST_ASSERT(inSuite, handle->ref == 1);
1778
1779     // RightSize should do nothing if there is another reference to the buffer.
1780     {
1781         PacketBufferHandle anotherHandle = handle.Retain();
1782         handle.RightSize();
1783         NL_TEST_ASSERT(inSuite, handle.mBuffer == buffer);
1784     }
1785
1786 #if CHIP_SYSTEM_PACKETBUFFER_HAS_RIGHT_SIZE
1787
1788     handle.RightSize();
1789     NL_TEST_ASSERT(inSuite, handle.mBuffer != buffer);
1790     NL_TEST_ASSERT(inSuite, handle->DataLength() == sizeof kPayload);
1791     NL_TEST_ASSERT(inSuite, memcmp(handle->Start(), kPayload, sizeof kPayload) == 0);
1792
1793 #else // CHIP_SYSTEM_PACKETBUFFER_HAS_RIGHT_SIZE
1794
1795     // For this configuration, RightSize() does nothing.
1796     handle.RightSize();
1797     NL_TEST_ASSERT(inSuite, handle.mBuffer == buffer);
1798
1799 #endif // CHIP_SYSTEM_PACKETBUFFER_HAS_RIGHT_SIZE
1800 }
1801
1802 void PacketBufferTest::CheckHandleCloneData(nlTestSuite * inSuite, void * inContext)
1803 {
1804     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
1805     PacketBufferTest * const test         = theContext->test;
1806     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
1807
1808     uint8_t lPayload[2 * PacketBuffer::kMaxSizeWithoutReserve];
1809     for (size_t i = 0; i < sizeof(lPayload); ++i)
1810     {
1811         lPayload[i] = static_cast<uint8_t>(random());
1812     }
1813
1814     for (auto & config_1 : test->configurations)
1815     {
1816         for (auto & config_2 : test->configurations)
1817         {
1818             if (&config_1 == &config_2)
1819             {
1820                 continue;
1821             }
1822
1823             test->PrepareTestBuffer(&config_1);
1824             test->PrepareTestBuffer(&config_2);
1825
1826             const uint8_t * payload_1 = lPayload;
1827             memcpy(config_1.handle->Start(), payload_1, config_1.handle->MaxDataLength());
1828             config_1.handle->SetDataLength(config_1.handle->MaxDataLength());
1829
1830             const uint8_t * payload_2 = lPayload + config_1.handle->MaxDataLength();
1831             memcpy(config_2.handle->Start(), payload_2, config_2.handle->MaxDataLength());
1832             config_2.handle->SetDataLength(config_2.handle->MaxDataLength());
1833
1834             // Clone single buffer.
1835             PacketBufferHandle clone_1 = config_1.handle.CloneData();
1836             NL_TEST_ASSERT(inSuite, !clone_1.IsNull());
1837             NL_TEST_ASSERT(inSuite, clone_1->DataLength() == config_1.handle->DataLength());
1838             NL_TEST_ASSERT(inSuite, memcmp(clone_1->Start(), payload_1, clone_1->DataLength()) == 0);
1839             if (clone_1->DataLength())
1840             {
1841                 // Verify that modifying the clone does not affect the original.
1842                 ScrambleData(clone_1->Start(), clone_1->DataLength());
1843                 NL_TEST_ASSERT(inSuite, memcmp(clone_1->Start(), payload_1, clone_1->DataLength()) != 0);
1844                 NL_TEST_ASSERT(inSuite, memcmp(config_1.handle->Start(), payload_1, config_1.handle->DataLength()) == 0);
1845             }
1846
1847             // Clone buffer chain.
1848             config_1.handle->AddToEnd(config_2.handle.Retain());
1849             NL_TEST_ASSERT(inSuite, config_1.handle->HasChainedBuffer());
1850             clone_1                         = config_1.handle.CloneData();
1851             PacketBufferHandle clone_1_next = clone_1->Next();
1852             NL_TEST_ASSERT(inSuite, !clone_1.IsNull());
1853             NL_TEST_ASSERT(inSuite, clone_1->HasChainedBuffer());
1854             NL_TEST_ASSERT(inSuite, clone_1->DataLength() == config_1.handle->DataLength());
1855             NL_TEST_ASSERT(inSuite, clone_1->TotalLength() == config_1.handle->TotalLength());
1856             NL_TEST_ASSERT(inSuite, clone_1_next->DataLength() == config_2.handle->DataLength());
1857             NL_TEST_ASSERT(inSuite, memcmp(clone_1->Start(), payload_1, clone_1->DataLength()) == 0);
1858             NL_TEST_ASSERT(inSuite, memcmp(clone_1_next->Start(), payload_2, clone_1_next->DataLength()) == 0);
1859             if (clone_1->DataLength())
1860             {
1861                 ScrambleData(clone_1->Start(), clone_1->DataLength());
1862                 NL_TEST_ASSERT(inSuite, memcmp(clone_1->Start(), payload_1, clone_1->DataLength()) != 0);
1863                 NL_TEST_ASSERT(inSuite, memcmp(config_1.handle->Start(), payload_1, config_1.handle->DataLength()) == 0);
1864             }
1865             if (clone_1_next->DataLength())
1866             {
1867                 ScrambleData(clone_1_next->Start(), clone_1_next->DataLength());
1868                 NL_TEST_ASSERT(inSuite, memcmp(clone_1_next->Start(), payload_2, clone_1_next->DataLength()) != 0);
1869                 NL_TEST_ASSERT(inSuite, memcmp(config_2.handle->Start(), payload_2, config_2.handle->DataLength()) == 0);
1870             }
1871
1872             config_1.handle = nullptr;
1873             config_2.handle = nullptr;
1874         }
1875     }
1876 }
1877
1878 void PacketBufferTest::CheckPacketBufferWriter(nlTestSuite * inSuite, void * inContext)
1879 {
1880     struct TestContext * const theContext = static_cast<struct TestContext *>(inContext);
1881     PacketBufferTest * const test         = theContext->test;
1882     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
1883
1884     const char kPayload[] = "Hello, world!";
1885
1886     PacketBufferWriter yay(PacketBufferHandle::New(sizeof(kPayload)));
1887     PacketBufferWriter nay(PacketBufferHandle::New(sizeof(kPayload)), sizeof(kPayload) - 2);
1888     NL_TEST_ASSERT(inSuite, !yay.IsNull());
1889     NL_TEST_ASSERT(inSuite, !nay.IsNull());
1890
1891     yay.Put(kPayload);
1892     yay.Put('\0');
1893     nay.Put(kPayload);
1894     nay.Put('\0');
1895     NL_TEST_ASSERT(inSuite, yay.Fit());
1896     NL_TEST_ASSERT(inSuite, !nay.Fit());
1897
1898     PacketBufferHandle yayBuffer = yay.Finalize();
1899     PacketBufferHandle nayBuffer = nay.Finalize();
1900     NL_TEST_ASSERT(inSuite, yay.IsNull());
1901     NL_TEST_ASSERT(inSuite, nay.IsNull());
1902     NL_TEST_ASSERT(inSuite, !yayBuffer.IsNull());
1903     NL_TEST_ASSERT(inSuite, nayBuffer.IsNull());
1904     NL_TEST_ASSERT(inSuite, memcmp(yayBuffer->Start(), kPayload, sizeof kPayload) == 0);
1905 }
1906
1907 /**
1908  *   Test Suite. It lists all the test functions.
1909  */
1910 // clang-format off
1911 const nlTest sTests[] =
1912 {
1913     NL_TEST_DEF("PacketBuffer::New",                    PacketBufferTest::CheckNew),
1914     NL_TEST_DEF("PacketBuffer::Start",                  PacketBufferTest::CheckStart),
1915     NL_TEST_DEF("PacketBuffer::SetStart",               PacketBufferTest::CheckSetStart),
1916     NL_TEST_DEF("PacketBuffer::DataLength",             PacketBufferTest::CheckDataLength),
1917     NL_TEST_DEF("PacketBuffer::SetDataLength",          PacketBufferTest::CheckSetDataLength),
1918     NL_TEST_DEF("PacketBuffer::TotalLength",            PacketBufferTest::CheckTotalLength),
1919     NL_TEST_DEF("PacketBuffer::MaxDataLength",          PacketBufferTest::CheckMaxDataLength),
1920     NL_TEST_DEF("PacketBuffer::AvailableDataLength",    PacketBufferTest::CheckAvailableDataLength),
1921     NL_TEST_DEF("PacketBuffer::HasChainedBuffer",       PacketBufferTest::CheckHasChainedBuffer),
1922     NL_TEST_DEF("PacketBuffer::ReservedSize",           PacketBufferTest::CheckReservedSize),
1923     NL_TEST_DEF("PacketBuffer::AddToEnd",               PacketBufferTest::CheckAddToEnd),
1924     NL_TEST_DEF("PacketBuffer::PopHead",                PacketBufferTest::CheckPopHead),
1925     NL_TEST_DEF("PacketBuffer::CompactHead",            PacketBufferTest::CheckCompactHead),
1926     NL_TEST_DEF("PacketBuffer::ConsumeHead",            PacketBufferTest::CheckConsumeHead),
1927     NL_TEST_DEF("PacketBuffer::Consume",                PacketBufferTest::CheckConsume),
1928     NL_TEST_DEF("PacketBuffer::EnsureReservedSize",     PacketBufferTest::CheckEnsureReservedSize),
1929     NL_TEST_DEF("PacketBuffer::AlignPayload",           PacketBufferTest::CheckAlignPayload),
1930     NL_TEST_DEF("PacketBuffer::Next",                   PacketBufferTest::CheckNext),
1931     NL_TEST_DEF("PacketBuffer::Last",                   PacketBufferTest::CheckLast),
1932     NL_TEST_DEF("PacketBuffer::Read",                   PacketBufferTest::CheckRead),
1933     NL_TEST_DEF("PacketBuffer::AddRef",                 PacketBufferTest::CheckAddRef),
1934     NL_TEST_DEF("PacketBuffer::Free",                   PacketBufferTest::CheckFree),
1935     NL_TEST_DEF("PacketBuffer::FreeHead",               PacketBufferTest::CheckFreeHead),
1936     NL_TEST_DEF("PacketBuffer::HandleConstruct",        PacketBufferTest::CheckHandleConstruct),
1937     NL_TEST_DEF("PacketBuffer::HandleMove",             PacketBufferTest::CheckHandleMove),
1938     NL_TEST_DEF("PacketBuffer::HandleRelease",          PacketBufferTest::CheckHandleRelease),
1939     NL_TEST_DEF("PacketBuffer::HandleFree",             PacketBufferTest::CheckHandleFree),
1940     NL_TEST_DEF("PacketBuffer::HandleRetain",           PacketBufferTest::CheckHandleRetain),
1941     NL_TEST_DEF("PacketBuffer::HandleAdopt",            PacketBufferTest::CheckHandleAdopt),
1942     NL_TEST_DEF("PacketBuffer::HandleHold",             PacketBufferTest::CheckHandleHold),
1943     NL_TEST_DEF("PacketBuffer::HandleAdvance",          PacketBufferTest::CheckHandleAdvance),
1944     NL_TEST_DEF("PacketBuffer::HandleRightSize",        PacketBufferTest::CheckHandleRightSize),
1945     NL_TEST_DEF("PacketBuffer::HandleCloneData",        PacketBufferTest::CheckHandleCloneData),
1946     NL_TEST_DEF("PacketBuffer::PacketBufferWriter",     PacketBufferTest::CheckPacketBufferWriter),
1947
1948     NL_TEST_SENTINEL()
1949 };
1950 // clang-format on
1951
1952 int TestSystemPacketBuffer(void)
1953 {
1954     // clang-format off
1955     nlTestSuite theSuite = {
1956         .name ="chip-system-packetbuffer",
1957         .tests = &sTests[0],
1958         .setup = PacketBufferTest::TestSetup,
1959         .tear_down = PacketBufferTest::TestTeardown,
1960         // .initialize = PacketBufferTest::TestInitialize,
1961         .terminate = PacketBufferTest::TestTerminate
1962     };
1963     // clang-format on
1964
1965     // Run test suit againt one context.
1966     nlTestRunner(&theSuite, &sContext);
1967
1968     return (nlTestRunnerStats(&theSuite));
1969 }
1970
1971 CHIP_REGISTER_TEST_SUITE(TestSystemPacketBuffer)