blob: 8b56dc2863074609fca0fb6e1790585903a75a68 [file] [log] [blame]
/*
*
* Copyright (c) 2017 Nest Labs, Inc.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file
* This file implements a unit test suite for the Weave
* RetainedPacketBuffer object.
*
*/
#include <SystemLayer/SystemConfig.h>
#include <SystemLayer/SystemStats.h>
#include <Weave/Profiles/common/WeaveMessage.h>
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
#include <lwip/tcpip.h>
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
#include <nltest.h>
using namespace nl::Weave;
static void PacketBufferAlloc(System::PacketBuffer *&aBuffer)
{
aBuffer = System::PacketBuffer::New();
}
static void PacketBufferFree(System::PacketBuffer *&aBuffer)
{
if (aBuffer != NULL)
{
System::PacketBuffer::Free(aBuffer);
aBuffer = NULL;
}
}
/**
* Test default construction and, implictly, destruction
*
*/
static void CheckDefaultConstruction(nlTestSuite *inSuite, void *inContext)
{
Profiles::RetainedPacketBuffer theExtent;
}
/**
* Test the GetBuffer accessor method
*
*/
static void CheckGetBufferAccessor(nlTestSuite *inSuite, void *inContext)
{
Profiles::RetainedPacketBuffer theRetainedBuffer;
System::PacketBuffer *theBuffer;
theBuffer = theRetainedBuffer.GetBuffer();
NL_TEST_ASSERT(inSuite, theBuffer == NULL);
}
/**
* Test the IsRetaining accessor method.
*
*/
static void CheckIsRetainingAccessor(nlTestSuite *inSuite, void *inContext)
{
Profiles::RetainedPacketBuffer theRetainedBuffer;
System::PacketBuffer *theBuffer;
bool retaining;
theBuffer = theRetainedBuffer.GetBuffer();
NL_TEST_ASSERT(inSuite, theBuffer == NULL);
retaining = theRetainedBuffer.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
}
/**
* Test the copy constructor absent retaining a buffer.
*
*/
static void CheckCopyConstructionWithoutRetainedBuffer(nlTestSuite *inSuite, void *inContext)
{
Profiles::RetainedPacketBuffer theRetainedBuffer_1;
Profiles::RetainedPacketBuffer theRetainedBuffer_2(theRetainedBuffer_1);
System::PacketBuffer *theBuffer;
bool retaining;
theBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, theBuffer == NULL);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
theBuffer = theRetainedBuffer_2.GetBuffer();
NL_TEST_ASSERT(inSuite, theBuffer == NULL);
retaining = theRetainedBuffer_2.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
}
/**
* Test the assignment operator absent retaining a buffer.
*
*/
void CheckAssignmentWithoutRetainedBuffer(nlTestSuite *inSuite, void *inContext)
{
Profiles::RetainedPacketBuffer theRetainedBuffer_1;
Profiles::RetainedPacketBuffer theRetainedBuffer_2;
System::PacketBuffer *theBuffer;
bool retaining;
theBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, theBuffer == NULL);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
theBuffer = theRetainedBuffer_2.GetBuffer();
NL_TEST_ASSERT(inSuite, theBuffer == NULL);
retaining = theRetainedBuffer_2.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
theRetainedBuffer_2 = theRetainedBuffer_1;
theBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, theBuffer == NULL);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
theBuffer = theRetainedBuffer_2.GetBuffer();
NL_TEST_ASSERT(inSuite, theBuffer == NULL);
retaining = theRetainedBuffer_2.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
}
/**
* Test the Release method absent a retained buffer
*
*/
void CheckReleaseWithoutRetainedBuffer(nlTestSuite *inSuite, void *inContext)
{
Profiles::RetainedPacketBuffer theRetainedBuffer;
System::PacketBuffer *theBuffer;
bool retaining;
theBuffer = theRetainedBuffer.GetBuffer();
NL_TEST_ASSERT(inSuite, theBuffer == NULL);
retaining = theRetainedBuffer.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
theRetainedBuffer.Release();
theBuffer = theRetainedBuffer.GetBuffer();
NL_TEST_ASSERT(inSuite, theBuffer == NULL);
retaining = theRetainedBuffer.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
}
/**
* Test the Retain method with a NULL pointer
*
*/
void CheckRetainWithNullPointer(nlTestSuite *inSuite, void *inContext)
{
Profiles::RetainedPacketBuffer theRetainedBuffer;
System::PacketBuffer *theBuffer;
bool retaining;
theBuffer = theRetainedBuffer.GetBuffer();
NL_TEST_ASSERT(inSuite, theBuffer == NULL);
retaining = theRetainedBuffer.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
theRetainedBuffer.Retain(NULL);
theBuffer = theRetainedBuffer.GetBuffer();
NL_TEST_ASSERT(inSuite, theBuffer == NULL);
retaining = theRetainedBuffer.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
theRetainedBuffer.Release();
theBuffer = theRetainedBuffer.GetBuffer();
NL_TEST_ASSERT(inSuite, theBuffer == NULL);
retaining = theRetainedBuffer.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
}
/**
* Test the Retain method with an allocated buffer and an implicit
* release via object destruction
*
*/
static void CheckRetainAllocatedBufferWithImplicitRelease(nlTestSuite *inSuite, void *inContext)
{
System::PacketBuffer *allocatedBuffer;
System::PacketBuffer *accessedBuffer;
bool retaining;
// Add a scope nesting level to get implicit allocated buffer
// dereference via object destruction when it goes out of scope.
{
Profiles::RetainedPacketBuffer theRetainedBuffer;
accessedBuffer = theRetainedBuffer.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer == NULL);
retaining = theRetainedBuffer.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
// Allocate a new system packet buffer with reference count of one (1).
PacketBufferAlloc(allocatedBuffer);
NL_TEST_ASSERT(inSuite, allocatedBuffer != NULL);
theRetainedBuffer.Retain(allocatedBuffer);
accessedBuffer = theRetainedBuffer.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
// At this point, the retained packet buffer object holds
// another reference, leaving the reference count at two (2).
}
// At this point, object destruction should have implicitly
// dereferenced the buffer, leaving the buffer reference count at
// one (1).
PacketBufferFree(allocatedBuffer);
// Assert that the buffer has been released to the pool, as expected.
NL_TEST_ASSERT(inSuite, System::Stats::GetResourcesInUse()[System::Stats::kSystemLayer_NumPacketBufs] == 0);
}
/**
* Test the Retain method with an allocated buffer and an explicit
* release via the Release method
*
*/
static void CheckRetainAllocatedBufferWithExplicitRelease(nlTestSuite *inSuite, void *inContext)
{
Profiles::RetainedPacketBuffer theRetainedBuffer;
System::PacketBuffer *allocatedBuffer;
System::PacketBuffer *accessedBuffer;
bool retaining;
accessedBuffer = theRetainedBuffer.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer == NULL);
retaining = theRetainedBuffer.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
// Allocate a new system packet buffer with reference count of one (1).
PacketBufferAlloc(allocatedBuffer);
NL_TEST_ASSERT(inSuite, allocatedBuffer != NULL);
theRetainedBuffer.Retain(allocatedBuffer);
accessedBuffer = theRetainedBuffer.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
// At this point, the retained packet buffer object holds
// another reference, leaving the reference count at two (2).
// Explicitly release the associated buffer.
theRetainedBuffer.Release();
accessedBuffer = theRetainedBuffer.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer == NULL);
retaining = theRetainedBuffer.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
// At this point, the explicit release should have dereferenced
// the buffer, leaving the buffer reference count at one (1).
PacketBufferFree(allocatedBuffer);
// Assert that the buffer has been released to the pool, as expected.
NL_TEST_ASSERT(inSuite, System::Stats::GetResourcesInUse()[System::Stats::kSystemLayer_NumPacketBufs] == 0);
}
/**
* Test copy construction with non-NULL buffer and implicitly release the target
* first via destruction and then implicitly the source second via
* destruction
*
*/
static void CheckCopyConstructionWithAllocatedBufferImplicitTargetImplicitSourceRelease(nlTestSuite *inSuite, void *inContext)
{
System::PacketBuffer *allocatedBuffer;
System::PacketBuffer *accessedBuffer;
bool retaining;
// Add a scope nesting level to get implicit allocated buffer
// dereference via object destruction when it goes out of scope.
{
Profiles::RetainedPacketBuffer theRetainedBuffer_1;
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer == NULL);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
// Allocate a new system packet buffer with reference count of one (1).
PacketBufferAlloc(allocatedBuffer);
NL_TEST_ASSERT(inSuite, allocatedBuffer != NULL);
theRetainedBuffer_1.Retain(allocatedBuffer);
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
// At this point, the first retained packet buffer object holds
// another reference, leaving the reference count at two (2).
// Add a scope nesting level to get implicit allocated buffer
// dereference via object destruction when it goes out of scope.
{
Profiles::RetainedPacketBuffer theRetainedBuffer_2(theRetainedBuffer_1);
accessedBuffer = theRetainedBuffer_2.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_2.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
// At this point, the second retained packet buffer object holds
// another reference, leaving the reference count at three (3).
}
// theRetainedBuffer_2 is now destroyed. theRetainedBuffer_1
// should still be retained.
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
// At this point, object destruction should have implicitly
// dereferenced the buffer, leaving the buffer reference count at
// two (2).
}
// At this point, object destruction should have implicitly
// dereferenced the buffer, leaving the buffer reference count at
// one (1).
PacketBufferFree(allocatedBuffer);
// Assert that the buffer has been released to the pool, as expected.
NL_TEST_ASSERT(inSuite, System::Stats::GetResourcesInUse()[System::Stats::kSystemLayer_NumPacketBufs] == 0);
}
/**
* Test copy construction with non-NULL buffer and implicitly release the target
* first via destruction and then explicitly the source second.
*
*/
static void CheckCopyConstructionWithAllocatedBufferImplicitTargetExplicitSourceRelease(nlTestSuite *inSuite, void *inContext)
{
Profiles::RetainedPacketBuffer theRetainedBuffer_1;
System::PacketBuffer *allocatedBuffer;
System::PacketBuffer *accessedBuffer;
bool retaining;
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer == NULL);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
// Allocate a new system packet buffer with reference count of one (1).
PacketBufferAlloc(allocatedBuffer);
NL_TEST_ASSERT(inSuite, allocatedBuffer != NULL);
theRetainedBuffer_1.Retain(allocatedBuffer);
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
// At this point, the first retained packet buffer object holds
// another reference, leaving the reference count at two (2).
// Add a scope nesting level to get implicit allocated buffer
// dereference via object destruction when it goes out of scope.
{
Profiles::RetainedPacketBuffer theRetainedBuffer_2(theRetainedBuffer_1);
accessedBuffer = theRetainedBuffer_2.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_2.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
// At this point, the second retained packet buffer object holds
// another reference, leaving the reference count at three (3).
}
// theRetainedBuffer_2 is now destroyed. theRetainedBuffer_1
// should still be retained.
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
// At this point, object destruction should have implicitly
// dereferenced the buffer, leaving the buffer reference count at
// two (2).
// Explicitly release the associated buffer.
theRetainedBuffer_1.Release();
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer == NULL);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
// At this point, the explicit release should have dereferenced
// the buffer, leaving the buffer reference count at one (1).
PacketBufferFree(allocatedBuffer);
// Assert that the buffer has been released to the pool, as expected.
NL_TEST_ASSERT(inSuite, System::Stats::GetResourcesInUse()[System::Stats::kSystemLayer_NumPacketBufs] == 0);
}
/**
* Test copy construction with non-NULL buffer and explicitly release the target
* first and then implicitly the source second via destruction
*
*/
static void CheckCopyConstructionWithAllocatedBufferExplicitTargetImplicitSourceRelease(nlTestSuite *inSuite, void *inContext)
{
System::PacketBuffer *allocatedBuffer;
System::PacketBuffer *accessedBuffer;
bool retaining;
// Add a scope nesting level to get implicit allocated buffer
// dereference via object destruction when it goes out of scope.
{
Profiles::RetainedPacketBuffer theRetainedBuffer_1;
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer == NULL);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
// Allocate a new system packet buffer with reference count of one (1).
PacketBufferAlloc(allocatedBuffer);
NL_TEST_ASSERT(inSuite, allocatedBuffer != NULL);
theRetainedBuffer_1.Retain(allocatedBuffer);
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
// At this point, the first retained packet buffer object holds
// another reference, leaving the reference count at two (2).
// Add a scope nesting level to get implicit allocated buffer
// dereference via object destruction when it goes out of scope.
{
Profiles::RetainedPacketBuffer theRetainedBuffer_2(theRetainedBuffer_1);
accessedBuffer = theRetainedBuffer_2.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_2.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
// At this point, the second retained packet buffer object holds
// another reference, leaving the reference count at three (3).
// Explicitly release the associated buffer.
theRetainedBuffer_2.Release();
accessedBuffer = theRetainedBuffer_2.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer == NULL);
retaining = theRetainedBuffer_2.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
}
// theRetainedBuffer_2 is now both released and
// destroyed. theRetainedBuffer_1 should still be retained.
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
// At this point, the explicit release should have dereferenced
// the buffer, leaving the buffer reference count at two (2).
}
// At this point, object destruction should have implicitly
// dereferenced the buffer, leaving the buffer reference count at
// one (1).
PacketBufferFree(allocatedBuffer);
// Assert that the buffer has been released to the pool, as expected.
NL_TEST_ASSERT(inSuite, System::Stats::GetResourcesInUse()[System::Stats::kSystemLayer_NumPacketBufs] == 0);
}
/**
* Test copy construction with non-NULL buffer and explicitly release the target
* first and then explicitly the source second
*
*/
static void CheckCopyConstructionWithAllocatedBufferExplicitTargetExplicitSourceRelease(nlTestSuite *inSuite, void *inContext)
{
Profiles::RetainedPacketBuffer theRetainedBuffer_1;
System::PacketBuffer *allocatedBuffer;
System::PacketBuffer *accessedBuffer;
bool retaining;
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer == NULL);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
// Allocate a new system packet buffer with reference count of one (1).
PacketBufferAlloc(allocatedBuffer);
NL_TEST_ASSERT(inSuite, allocatedBuffer != NULL);
theRetainedBuffer_1.Retain(allocatedBuffer);
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
// At this point, the first retained packet buffer object holds
// another reference, leaving the reference count at two (2).
{
Profiles::RetainedPacketBuffer theRetainedBuffer_2(theRetainedBuffer_1);
accessedBuffer = theRetainedBuffer_2.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_2.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
// At this point, the second retained packet buffer object holds
// another reference, leaving the reference count at three (3).
// Explicitly release the associated buffer.
theRetainedBuffer_2.Release();
accessedBuffer = theRetainedBuffer_2.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer == NULL);
retaining = theRetainedBuffer_2.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
// At this point, the explicit release should have dereferenced
// the buffer, leaving the buffer reference count at two (2).
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
}
// theRetainedBuffer_2 is now both released and
// destroyed. theRetainedBuffer_1 should still be retained.
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
// Explicitly release the associated buffer.
theRetainedBuffer_1.Release();
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer == NULL);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
// At this point, the explicit release should have dereferenced
// the buffer, leaving the buffer reference count at one (1).
PacketBufferFree(allocatedBuffer);
// Assert that the buffer has been released to the pool, as expected.
NL_TEST_ASSERT(inSuite, System::Stats::GetResourcesInUse()[System::Stats::kSystemLayer_NumPacketBufs] == 0);
}
/**
* Test assignment with non-NULL buffer and implicitly release the target
* first via destruction and then implicitly the source second via
* destruction
*
*/
static void CheckAssignmentWithAllocatedBufferImplicitTargetImplicitSourceRelease(nlTestSuite *inSuite, void *inContext)
{
System::PacketBuffer *allocatedBuffer;
System::PacketBuffer *accessedBuffer;
bool retaining;
// Add a scope nesting level to get implicit allocated buffer
// dereference via object destruction when it goes out of scope.
{
Profiles::RetainedPacketBuffer theRetainedBuffer_1;
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer == NULL);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
// Allocate a new system packet buffer with reference count of one (1).
PacketBufferAlloc(allocatedBuffer);
NL_TEST_ASSERT(inSuite, allocatedBuffer != NULL);
theRetainedBuffer_1.Retain(allocatedBuffer);
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
// At this point, the first retained packet buffer object holds
// another reference, leaving the reference count at two (2).
// Add a scope nesting level to get implicit allocated buffer
// dereference via object destruction when it goes out of scope.
{
Profiles::RetainedPacketBuffer theRetainedBuffer_2;
theRetainedBuffer_2 = theRetainedBuffer_1;
accessedBuffer = theRetainedBuffer_2.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_2.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
// At this point, the second retained packet buffer object holds
// another reference, leaving the reference count at three (3).
}
// theRetainedBuffer_2 is now destroyed. theRetainedBuffer_1
// should still be retained.
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
// At this point, object destruction should have implicitly
// dereferenced the buffer, leaving the buffer reference count at
// two (2).
}
// At this point, object destruction should have implicitly
// dereferenced the buffer, leaving the buffer reference count at
// one (1).
PacketBufferFree(allocatedBuffer);
// Assert that the buffer has been released to the pool, as expected.
NL_TEST_ASSERT(inSuite, System::Stats::GetResourcesInUse()[System::Stats::kSystemLayer_NumPacketBufs] == 0);
}
/**
* Test assignment with non-NULL buffer and implicitly release the target
* first via destruction and then explicitly the source second.
*
*/
static void CheckAssignmentWithAllocatedBufferImplicitTargetExplicitSourceRelease(nlTestSuite *inSuite, void *inContext)
{
Profiles::RetainedPacketBuffer theRetainedBuffer_1;
System::PacketBuffer *allocatedBuffer;
System::PacketBuffer *accessedBuffer;
bool retaining;
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer == NULL);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
// Allocate a new system packet buffer with reference count of one (1).
PacketBufferAlloc(allocatedBuffer);
NL_TEST_ASSERT(inSuite, allocatedBuffer != NULL);
theRetainedBuffer_1.Retain(allocatedBuffer);
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
// At this point, the first retained packet buffer object holds
// another reference, leaving the reference count at two (2).
// Add a scope nesting level to get implicit allocated buffer
// dereference via object destruction when it goes out of scope.
{
Profiles::RetainedPacketBuffer theRetainedBuffer_2;
theRetainedBuffer_2 = theRetainedBuffer_1;
accessedBuffer = theRetainedBuffer_2.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_2.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
// At this point, the second retained packet buffer object holds
// another reference, leaving the reference count at three (3).
}
// theRetainedBuffer_2 is now destroyed. theRetainedBuffer_1
// should still be retained.
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
// At this point, object destruction should have implicitly
// dereferenced the buffer, leaving the buffer reference count at
// two (2).
// Explicitly release the associated buffer.
theRetainedBuffer_1.Release();
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer == NULL);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
// At this point, the explicit release should have dereferenced
// the buffer, leaving the buffer reference count at one (1).
PacketBufferFree(allocatedBuffer);
// Assert that the buffer has been released to the pool, as expected.
NL_TEST_ASSERT(inSuite, System::Stats::GetResourcesInUse()[System::Stats::kSystemLayer_NumPacketBufs] == 0);
}
/**
* Test assignment with non-NULL buffer and explicitly release the target
* first and then implicitly the source second via destruction
*
*/
static void CheckAssignmentWithAllocatedBufferExplicitTargetImplicitSourceRelease(nlTestSuite *inSuite, void *inContext)
{
System::PacketBuffer *allocatedBuffer;
System::PacketBuffer *accessedBuffer;
bool retaining;
// Add a scope nesting level to get implicit allocated buffer
// dereference via object destruction when it goes out of scope.
{
Profiles::RetainedPacketBuffer theRetainedBuffer_1;
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer == NULL);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
// Allocate a new system packet buffer with reference count of one (1).
PacketBufferAlloc(allocatedBuffer);
NL_TEST_ASSERT(inSuite, allocatedBuffer != NULL);
theRetainedBuffer_1.Retain(allocatedBuffer);
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
// At this point, the first retained packet buffer object holds
// another reference, leaving the reference count at two (2).
// Add a scope nesting level to get implicit allocated buffer
// dereference via object destruction when it goes out of scope.
{
Profiles::RetainedPacketBuffer theRetainedBuffer_2;
theRetainedBuffer_2 = theRetainedBuffer_1;
accessedBuffer = theRetainedBuffer_2.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_2.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
// At this point, the second retained packet buffer object holds
// another reference, leaving the reference count at three (3).
// Explicitly release the associated buffer.
theRetainedBuffer_2.Release();
accessedBuffer = theRetainedBuffer_2.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer == NULL);
retaining = theRetainedBuffer_2.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
}
// theRetainedBuffer_2 is now both released and
// destroyed. theRetainedBuffer_1 should still be retained.
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
// At this point, the explicit release should have dereferenced
// the buffer, leaving the buffer reference count at two (2).
}
// At this point, object destruction should have implicitly
// dereferenced the buffer, leaving the buffer reference count at
// one (1).
PacketBufferFree(allocatedBuffer);
// Assert that the buffer has been released to the pool, as expected.
NL_TEST_ASSERT(inSuite, System::Stats::GetResourcesInUse()[System::Stats::kSystemLayer_NumPacketBufs] == 0);
}
/**
* Test assignment with non-NULL buffer and explicitly release the target
* first and then explicitly the source second
*
*/
static void CheckAssignmentWithAllocatedBufferExplicitTargetExplicitSourceRelease(nlTestSuite *inSuite, void *inContext)
{
Profiles::RetainedPacketBuffer theRetainedBuffer_1;
System::PacketBuffer *allocatedBuffer;
System::PacketBuffer *accessedBuffer;
bool retaining;
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer == NULL);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
// Allocate a new system packet buffer with reference count of one (1).
PacketBufferAlloc(allocatedBuffer);
NL_TEST_ASSERT(inSuite, allocatedBuffer != NULL);
theRetainedBuffer_1.Retain(allocatedBuffer);
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
// At this point, the first retained packet buffer object holds
// another reference, leaving the reference count at two (2).
{
Profiles::RetainedPacketBuffer theRetainedBuffer_2;
theRetainedBuffer_2 = theRetainedBuffer_1;
accessedBuffer = theRetainedBuffer_2.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_2.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
// At this point, the second retained packet buffer object holds
// another reference, leaving the reference count at three (3).
// Explicitly release the associated buffer.
theRetainedBuffer_2.Release();
accessedBuffer = theRetainedBuffer_2.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer == NULL);
retaining = theRetainedBuffer_2.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
// At this point, the explicit release should have dereferenced
// the buffer, leaving the buffer reference count at two (2).
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
}
// theRetainedBuffer_2 is now both released and
// destroyed. theRetainedBuffer_1 should still be retained.
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer != NULL);
NL_TEST_ASSERT(inSuite, accessedBuffer == allocatedBuffer);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, retaining);
// Explicitly release the associated buffer.
theRetainedBuffer_1.Release();
accessedBuffer = theRetainedBuffer_1.GetBuffer();
NL_TEST_ASSERT(inSuite, accessedBuffer == NULL);
retaining = theRetainedBuffer_1.IsRetaining();
NL_TEST_ASSERT(inSuite, !retaining);
// At this point, the explicit release should have dereferenced
// the buffer, leaving the buffer reference count at one (1).
PacketBufferFree(allocatedBuffer);
// Assert that the buffer has been released to the pool, as expected.
NL_TEST_ASSERT(inSuite, System::Stats::GetResourcesInUse()[System::Stats::kSystemLayer_NumPacketBufs] == 0);
}
static const nlTest sTests[] = {
NL_TEST_DEF("default construction and destruction", CheckDefaultConstruction),
NL_TEST_DEF("get buffer accessor", CheckGetBufferAccessor),
NL_TEST_DEF("is retaining accessor", CheckIsRetainingAccessor),
NL_TEST_DEF("copy construction with no retained buffer", CheckCopyConstructionWithoutRetainedBuffer),
NL_TEST_DEF("assignment with no retained buffer", CheckAssignmentWithoutRetainedBuffer),
NL_TEST_DEF("release with no retained buffer", CheckReleaseWithoutRetainedBuffer),
NL_TEST_DEF("retain with a null pointer", CheckRetainWithNullPointer),
NL_TEST_DEF("retain with an allocated buffer and implicit release", CheckRetainAllocatedBufferWithImplicitRelease),
NL_TEST_DEF("retain with an allocated buffer and explicit release", CheckRetainAllocatedBufferWithExplicitRelease),
NL_TEST_DEF("copy construction with allocated buffer and implicit target then implicit source release", CheckCopyConstructionWithAllocatedBufferImplicitTargetImplicitSourceRelease),
NL_TEST_DEF("copy construction with allocated buffer and implicit target then explicit source release", CheckCopyConstructionWithAllocatedBufferImplicitTargetExplicitSourceRelease),
NL_TEST_DEF("copy construction with allocated buffer and explicit target then implicit source release", CheckCopyConstructionWithAllocatedBufferExplicitTargetImplicitSourceRelease),
NL_TEST_DEF("copy construction with allocated buffer and explicit target then explicit source release", CheckCopyConstructionWithAllocatedBufferExplicitTargetExplicitSourceRelease),
NL_TEST_DEF("assignment with allocated buffer and implicit target then implicit source release", CheckAssignmentWithAllocatedBufferImplicitTargetImplicitSourceRelease),
NL_TEST_DEF("assignment with allocated buffer and implicit target then explicit source release", CheckAssignmentWithAllocatedBufferImplicitTargetExplicitSourceRelease),
NL_TEST_DEF("assignment with allocated buffer and explicit target then implicit source release", CheckAssignmentWithAllocatedBufferExplicitTargetImplicitSourceRelease),
NL_TEST_DEF("assignment with allocated buffer and explicit target then explicit source release", CheckAssignmentWithAllocatedBufferExplicitTargetExplicitSourceRelease),
NL_TEST_SENTINEL()
};
int main(void)
{
nlTestSuite theSuite = {
"weave-retained-packet-buffer",
&sTests[0]
};
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
tcpip_init(NULL, NULL);
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
nl_test_set_output_style(OUTPUT_CSV);
nlTestRunner(&theSuite, NULL);
return nlTestRunnerStats(&theSuite);
}